xref: /openbsd-src/sys/dev/pci/drm/amd/display/dc/dcn32/dcn32_resource.c (revision 4b0e85add7a765c13fc1270f31ec7d2a745b6489)
11bb76ff1Sjsg // SPDX-License-Identifier: MIT
21bb76ff1Sjsg /*
31bb76ff1Sjsg  * Copyright 2022 Advanced Micro Devices, Inc.
41bb76ff1Sjsg  *
51bb76ff1Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
61bb76ff1Sjsg  * copy of this software and associated documentation files (the "Software"),
71bb76ff1Sjsg  * to deal in the Software without restriction, including without limitation
81bb76ff1Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
91bb76ff1Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
101bb76ff1Sjsg  * Software is furnished to do so, subject to the following conditions:
111bb76ff1Sjsg  *
121bb76ff1Sjsg  * The above copyright notice and this permission notice shall be included in
131bb76ff1Sjsg  * all copies or substantial portions of the Software.
141bb76ff1Sjsg  *
151bb76ff1Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161bb76ff1Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171bb76ff1Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
181bb76ff1Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
191bb76ff1Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
201bb76ff1Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
211bb76ff1Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
221bb76ff1Sjsg  *
231bb76ff1Sjsg  * Authors: AMD
241bb76ff1Sjsg  *
251bb76ff1Sjsg  */
261bb76ff1Sjsg 
271bb76ff1Sjsg #include "dm_services.h"
281bb76ff1Sjsg #include "dc.h"
291bb76ff1Sjsg 
301bb76ff1Sjsg #include "dcn32_init.h"
311bb76ff1Sjsg 
321bb76ff1Sjsg #include "resource.h"
331bb76ff1Sjsg #include "include/irq_service_interface.h"
341bb76ff1Sjsg #include "dcn32_resource.h"
351bb76ff1Sjsg 
361bb76ff1Sjsg #include "dcn20/dcn20_resource.h"
371bb76ff1Sjsg #include "dcn30/dcn30_resource.h"
381bb76ff1Sjsg 
391bb76ff1Sjsg #include "dcn10/dcn10_ipp.h"
401bb76ff1Sjsg #include "dcn30/dcn30_hubbub.h"
411bb76ff1Sjsg #include "dcn31/dcn31_hubbub.h"
421bb76ff1Sjsg #include "dcn32/dcn32_hubbub.h"
431bb76ff1Sjsg #include "dcn32/dcn32_mpc.h"
441bb76ff1Sjsg #include "dcn32_hubp.h"
451bb76ff1Sjsg #include "irq/dcn32/irq_service_dcn32.h"
461bb76ff1Sjsg #include "dcn32/dcn32_dpp.h"
471bb76ff1Sjsg #include "dcn32/dcn32_optc.h"
481bb76ff1Sjsg #include "dcn20/dcn20_hwseq.h"
491bb76ff1Sjsg #include "dcn30/dcn30_hwseq.h"
501bb76ff1Sjsg #include "dce110/dce110_hw_sequencer.h"
511bb76ff1Sjsg #include "dcn30/dcn30_opp.h"
521bb76ff1Sjsg #include "dcn20/dcn20_dsc.h"
531bb76ff1Sjsg #include "dcn30/dcn30_vpg.h"
541bb76ff1Sjsg #include "dcn30/dcn30_afmt.h"
551bb76ff1Sjsg #include "dcn30/dcn30_dio_stream_encoder.h"
561bb76ff1Sjsg #include "dcn32/dcn32_dio_stream_encoder.h"
571bb76ff1Sjsg #include "dcn31/dcn31_hpo_dp_stream_encoder.h"
581bb76ff1Sjsg #include "dcn31/dcn31_hpo_dp_link_encoder.h"
591bb76ff1Sjsg #include "dcn32/dcn32_hpo_dp_link_encoder.h"
601bb76ff1Sjsg #include "dcn31/dcn31_apg.h"
611bb76ff1Sjsg #include "dcn31/dcn31_dio_link_encoder.h"
621bb76ff1Sjsg #include "dcn32/dcn32_dio_link_encoder.h"
631bb76ff1Sjsg #include "dce/dce_clock_source.h"
641bb76ff1Sjsg #include "dce/dce_audio.h"
651bb76ff1Sjsg #include "dce/dce_hwseq.h"
661bb76ff1Sjsg #include "clk_mgr.h"
671bb76ff1Sjsg #include "virtual/virtual_stream_encoder.h"
681bb76ff1Sjsg #include "dml/display_mode_vba.h"
691bb76ff1Sjsg #include "dcn32/dcn32_dccg.h"
701bb76ff1Sjsg #include "dcn10/dcn10_resource.h"
71f005ef32Sjsg #include "link.h"
721bb76ff1Sjsg #include "dcn31/dcn31_panel_cntl.h"
731bb76ff1Sjsg 
741bb76ff1Sjsg #include "dcn30/dcn30_dwb.h"
751bb76ff1Sjsg #include "dcn32/dcn32_mmhubbub.h"
761bb76ff1Sjsg 
771bb76ff1Sjsg #include "dcn/dcn_3_2_0_offset.h"
781bb76ff1Sjsg #include "dcn/dcn_3_2_0_sh_mask.h"
791bb76ff1Sjsg #include "nbio/nbio_4_3_0_offset.h"
801bb76ff1Sjsg 
811bb76ff1Sjsg #include "reg_helper.h"
821bb76ff1Sjsg #include "dce/dmub_abm.h"
831bb76ff1Sjsg #include "dce/dmub_psr.h"
841bb76ff1Sjsg #include "dce/dce_aux.h"
851bb76ff1Sjsg #include "dce/dce_i2c.h"
861bb76ff1Sjsg 
871bb76ff1Sjsg #include "dml/dcn30/display_mode_vba_30.h"
881bb76ff1Sjsg #include "vm_helper.h"
891bb76ff1Sjsg #include "dcn20/dcn20_vmid.h"
901bb76ff1Sjsg #include "dml/dcn32/dcn32_fpu.h"
911bb76ff1Sjsg 
921bb76ff1Sjsg #define DC_LOGGER_INIT(logger)
931bb76ff1Sjsg 
941bb76ff1Sjsg enum dcn32_clk_src_array_id {
951bb76ff1Sjsg 	DCN32_CLK_SRC_PLL0,
961bb76ff1Sjsg 	DCN32_CLK_SRC_PLL1,
971bb76ff1Sjsg 	DCN32_CLK_SRC_PLL2,
981bb76ff1Sjsg 	DCN32_CLK_SRC_PLL3,
991bb76ff1Sjsg 	DCN32_CLK_SRC_PLL4,
1001bb76ff1Sjsg 	DCN32_CLK_SRC_TOTAL
1011bb76ff1Sjsg };
1021bb76ff1Sjsg 
1031bb76ff1Sjsg /* begin *********************
1041bb76ff1Sjsg  * macros to expend register list macro defined in HW object header file
1051bb76ff1Sjsg  */
1061bb76ff1Sjsg 
1071bb76ff1Sjsg /* DCN */
1081bb76ff1Sjsg #define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]
1091bb76ff1Sjsg 
1101bb76ff1Sjsg #define BASE(seg) BASE_INNER(seg)
1111bb76ff1Sjsg 
1121bb76ff1Sjsg #define SR(reg_name)\
1131bb76ff1Sjsg 		REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) +  \
1141bb76ff1Sjsg 					reg ## reg_name
1151bb76ff1Sjsg #define SR_ARR(reg_name, id) \
1161bb76ff1Sjsg 	REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name
1171bb76ff1Sjsg 
1181bb76ff1Sjsg #define SR_ARR_INIT(reg_name, id, value) \
1191bb76ff1Sjsg 	REG_STRUCT[id].reg_name = value
1201bb76ff1Sjsg 
1211bb76ff1Sjsg #define SRI(reg_name, block, id)\
1221bb76ff1Sjsg 	REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1231bb76ff1Sjsg 		reg ## block ## id ## _ ## reg_name
1241bb76ff1Sjsg 
1251bb76ff1Sjsg #define SRI_ARR(reg_name, block, id)\
1261bb76ff1Sjsg 	REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1271bb76ff1Sjsg 		reg ## block ## id ## _ ## reg_name
1281bb76ff1Sjsg 
1291bb76ff1Sjsg #define SR_ARR_I2C(reg_name, id) \
1301bb76ff1Sjsg 	REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name
1311bb76ff1Sjsg 
1321bb76ff1Sjsg #define SRI_ARR_I2C(reg_name, block, id)\
1331bb76ff1Sjsg 	REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1341bb76ff1Sjsg 		reg ## block ## id ## _ ## reg_name
1351bb76ff1Sjsg 
1361bb76ff1Sjsg #define SRI_ARR_ALPHABET(reg_name, block, index, id)\
1371bb76ff1Sjsg 	REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1381bb76ff1Sjsg 		reg ## block ## id ## _ ## reg_name
1391bb76ff1Sjsg 
1401bb76ff1Sjsg #define SRI2(reg_name, block, id)\
1411bb76ff1Sjsg 	.reg_name = BASE(reg ## reg_name ## _BASE_IDX) +	\
1421bb76ff1Sjsg 		reg ## reg_name
1431bb76ff1Sjsg #define SRI2_ARR(reg_name, block, id)\
1441bb76ff1Sjsg 	REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) +	\
1451bb76ff1Sjsg 		reg ## reg_name
1461bb76ff1Sjsg 
1471bb76ff1Sjsg #define SRIR(var_name, reg_name, block, id)\
1481bb76ff1Sjsg 	.var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1491bb76ff1Sjsg 		reg ## block ## id ## _ ## reg_name
1501bb76ff1Sjsg 
1511bb76ff1Sjsg #define SRII(reg_name, block, id)\
1521bb76ff1Sjsg 	REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1531bb76ff1Sjsg 					reg ## block ## id ## _ ## reg_name
1541bb76ff1Sjsg 
1551bb76ff1Sjsg #define SRII_ARR_2(reg_name, block, id, inst)\
1561bb76ff1Sjsg 	REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1571bb76ff1Sjsg 		reg ## block ## id ## _ ## reg_name
1581bb76ff1Sjsg 
1591bb76ff1Sjsg #define SRII_MPC_RMU(reg_name, block, id)\
1601bb76ff1Sjsg 	.RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1611bb76ff1Sjsg 		reg ## block ## id ## _ ## reg_name
1621bb76ff1Sjsg 
1631bb76ff1Sjsg #define SRII_DWB(reg_name, temp_name, block, id)\
1641bb76ff1Sjsg 	REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
1651bb76ff1Sjsg 		reg ## block ## id ## _ ## temp_name
1661bb76ff1Sjsg 
167f005ef32Sjsg #define SF_DWB2(reg_name, block, id, field_name, post_fix)	\
168f005ef32Sjsg 	.field_name = reg_name ## __ ## field_name ## post_fix
169f005ef32Sjsg 
1701bb76ff1Sjsg #define DCCG_SRII(reg_name, block, id)\
1711bb76ff1Sjsg 	REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
1721bb76ff1Sjsg 		reg ## block ## id ## _ ## reg_name
1731bb76ff1Sjsg 
1741bb76ff1Sjsg #define VUPDATE_SRII(reg_name, block, id)\
1751bb76ff1Sjsg 	REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \
1761bb76ff1Sjsg 		reg ## reg_name ## _ ## block ## id
1771bb76ff1Sjsg 
1781bb76ff1Sjsg /* NBIO */
1791bb76ff1Sjsg #define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg]
1801bb76ff1Sjsg 
1811bb76ff1Sjsg #define NBIO_BASE(seg) \
1821bb76ff1Sjsg 	NBIO_BASE_INNER(seg)
1831bb76ff1Sjsg 
1841bb76ff1Sjsg #define NBIO_SR(reg_name)\
1851bb76ff1Sjsg 	REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \
1861bb76ff1Sjsg 			regBIF_BX0_ ## reg_name
1871bb76ff1Sjsg #define NBIO_SR_ARR(reg_name, id)\
1881bb76ff1Sjsg 	REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \
1891bb76ff1Sjsg 		regBIF_BX0_ ## reg_name
1901bb76ff1Sjsg 
1911bb76ff1Sjsg #undef CTX
1921bb76ff1Sjsg #define CTX ctx
1931bb76ff1Sjsg #define REG(reg_name) \
1941bb76ff1Sjsg 	(ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)
1951bb76ff1Sjsg 
1961bb76ff1Sjsg static struct bios_registers bios_regs;
1971bb76ff1Sjsg 
1981bb76ff1Sjsg #define bios_regs_init() \
1991bb76ff1Sjsg 		( \
2001bb76ff1Sjsg 		NBIO_SR(BIOS_SCRATCH_3),\
2011bb76ff1Sjsg 		NBIO_SR(BIOS_SCRATCH_6)\
2021bb76ff1Sjsg 		)
2031bb76ff1Sjsg 
2041bb76ff1Sjsg #define clk_src_regs_init(index, pllid)\
2051bb76ff1Sjsg 	CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid)
2061bb76ff1Sjsg 
2071bb76ff1Sjsg static struct dce110_clk_src_regs clk_src_regs[5];
2081bb76ff1Sjsg 
2091bb76ff1Sjsg static const struct dce110_clk_src_shift cs_shift = {
2101bb76ff1Sjsg 		CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT)
2111bb76ff1Sjsg };
2121bb76ff1Sjsg 
2131bb76ff1Sjsg static const struct dce110_clk_src_mask cs_mask = {
2141bb76ff1Sjsg 		CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK)
2151bb76ff1Sjsg };
2161bb76ff1Sjsg 
2171bb76ff1Sjsg #define abm_regs_init(id)\
2181bb76ff1Sjsg 		ABM_DCN32_REG_LIST_RI(id)
2191bb76ff1Sjsg 
2201bb76ff1Sjsg static struct dce_abm_registers abm_regs[4];
2211bb76ff1Sjsg 
2221bb76ff1Sjsg static const struct dce_abm_shift abm_shift = {
2231bb76ff1Sjsg 		ABM_MASK_SH_LIST_DCN32(__SHIFT)
2241bb76ff1Sjsg };
2251bb76ff1Sjsg 
2261bb76ff1Sjsg static const struct dce_abm_mask abm_mask = {
2271bb76ff1Sjsg 		ABM_MASK_SH_LIST_DCN32(_MASK)
2281bb76ff1Sjsg };
2291bb76ff1Sjsg 
2301bb76ff1Sjsg #define audio_regs_init(id)\
2311bb76ff1Sjsg 		AUD_COMMON_REG_LIST_RI(id)
2321bb76ff1Sjsg 
2331bb76ff1Sjsg static struct dce_audio_registers audio_regs[5];
2341bb76ff1Sjsg 
2351bb76ff1Sjsg #define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\
2361bb76ff1Sjsg 		SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
2371bb76ff1Sjsg 		SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
2381bb76ff1Sjsg 		AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)
2391bb76ff1Sjsg 
2401bb76ff1Sjsg static const struct dce_audio_shift audio_shift = {
2411bb76ff1Sjsg 		DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)
2421bb76ff1Sjsg };
2431bb76ff1Sjsg 
2441bb76ff1Sjsg static const struct dce_audio_mask audio_mask = {
2451bb76ff1Sjsg 		DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)
2461bb76ff1Sjsg };
2471bb76ff1Sjsg 
2481bb76ff1Sjsg #define vpg_regs_init(id)\
2491bb76ff1Sjsg 	VPG_DCN3_REG_LIST_RI(id)
2501bb76ff1Sjsg 
2511bb76ff1Sjsg static struct dcn30_vpg_registers vpg_regs[10];
2521bb76ff1Sjsg 
2531bb76ff1Sjsg static const struct dcn30_vpg_shift vpg_shift = {
2541bb76ff1Sjsg 	DCN3_VPG_MASK_SH_LIST(__SHIFT)
2551bb76ff1Sjsg };
2561bb76ff1Sjsg 
2571bb76ff1Sjsg static const struct dcn30_vpg_mask vpg_mask = {
2581bb76ff1Sjsg 	DCN3_VPG_MASK_SH_LIST(_MASK)
2591bb76ff1Sjsg };
2601bb76ff1Sjsg 
2611bb76ff1Sjsg #define afmt_regs_init(id)\
2621bb76ff1Sjsg 	AFMT_DCN3_REG_LIST_RI(id)
2631bb76ff1Sjsg 
2641bb76ff1Sjsg static struct dcn30_afmt_registers afmt_regs[6];
2651bb76ff1Sjsg 
2661bb76ff1Sjsg static const struct dcn30_afmt_shift afmt_shift = {
2671bb76ff1Sjsg 	DCN3_AFMT_MASK_SH_LIST(__SHIFT)
2681bb76ff1Sjsg };
2691bb76ff1Sjsg 
2701bb76ff1Sjsg static const struct dcn30_afmt_mask afmt_mask = {
2711bb76ff1Sjsg 	DCN3_AFMT_MASK_SH_LIST(_MASK)
2721bb76ff1Sjsg };
2731bb76ff1Sjsg 
2741bb76ff1Sjsg #define apg_regs_init(id)\
2751bb76ff1Sjsg 	APG_DCN31_REG_LIST_RI(id)
2761bb76ff1Sjsg 
2771bb76ff1Sjsg static struct dcn31_apg_registers apg_regs[4];
2781bb76ff1Sjsg 
2791bb76ff1Sjsg static const struct dcn31_apg_shift apg_shift = {
2801bb76ff1Sjsg 	DCN31_APG_MASK_SH_LIST(__SHIFT)
2811bb76ff1Sjsg };
2821bb76ff1Sjsg 
2831bb76ff1Sjsg static const struct dcn31_apg_mask apg_mask = {
2841bb76ff1Sjsg 		DCN31_APG_MASK_SH_LIST(_MASK)
2851bb76ff1Sjsg };
2861bb76ff1Sjsg 
2871bb76ff1Sjsg #define stream_enc_regs_init(id)\
2881bb76ff1Sjsg 	SE_DCN32_REG_LIST_RI(id)
2891bb76ff1Sjsg 
2901bb76ff1Sjsg static struct dcn10_stream_enc_registers stream_enc_regs[5];
2911bb76ff1Sjsg 
2921bb76ff1Sjsg static const struct dcn10_stream_encoder_shift se_shift = {
2931bb76ff1Sjsg 		SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT)
2941bb76ff1Sjsg };
2951bb76ff1Sjsg 
2961bb76ff1Sjsg static const struct dcn10_stream_encoder_mask se_mask = {
2971bb76ff1Sjsg 		SE_COMMON_MASK_SH_LIST_DCN32(_MASK)
2981bb76ff1Sjsg };
2991bb76ff1Sjsg 
3001bb76ff1Sjsg 
3011bb76ff1Sjsg #define aux_regs_init(id)\
3021bb76ff1Sjsg 	DCN2_AUX_REG_LIST_RI(id)
3031bb76ff1Sjsg 
3041bb76ff1Sjsg static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5];
3051bb76ff1Sjsg 
3061bb76ff1Sjsg #define hpd_regs_init(id)\
3071bb76ff1Sjsg 	HPD_REG_LIST_RI(id)
3081bb76ff1Sjsg 
3091bb76ff1Sjsg static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];
3101bb76ff1Sjsg 
3111bb76ff1Sjsg #define link_regs_init(id, phyid)\
3121bb76ff1Sjsg 	( \
3131bb76ff1Sjsg 	LE_DCN31_REG_LIST_RI(id), \
3141bb76ff1Sjsg 	UNIPHY_DCN2_REG_LIST_RI(id, phyid)\
3151bb76ff1Sjsg 	)
3161bb76ff1Sjsg 	/*DPCS_DCN31_REG_LIST(id),*/ \
3171bb76ff1Sjsg 
3181bb76ff1Sjsg static struct dcn10_link_enc_registers link_enc_regs[5];
3191bb76ff1Sjsg 
3201bb76ff1Sjsg static const struct dcn10_link_enc_shift le_shift = {
3211bb76ff1Sjsg 	LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \
3221bb76ff1Sjsg 	//DPCS_DCN31_MASK_SH_LIST(__SHIFT)
3231bb76ff1Sjsg };
3241bb76ff1Sjsg 
3251bb76ff1Sjsg static const struct dcn10_link_enc_mask le_mask = {
3261bb76ff1Sjsg 	LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \
3271bb76ff1Sjsg 	//DPCS_DCN31_MASK_SH_LIST(_MASK)
3281bb76ff1Sjsg };
3291bb76ff1Sjsg 
3301bb76ff1Sjsg #define hpo_dp_stream_encoder_reg_init(id)\
3311bb76ff1Sjsg 	DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id)
3321bb76ff1Sjsg 
3331bb76ff1Sjsg static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4];
3341bb76ff1Sjsg 
3351bb76ff1Sjsg static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = {
3361bb76ff1Sjsg 	DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT)
3371bb76ff1Sjsg };
3381bb76ff1Sjsg 
3391bb76ff1Sjsg static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = {
3401bb76ff1Sjsg 	DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)
3411bb76ff1Sjsg };
3421bb76ff1Sjsg 
3431bb76ff1Sjsg 
3441bb76ff1Sjsg #define hpo_dp_link_encoder_reg_init(id)\
3451bb76ff1Sjsg 	DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id)
3461bb76ff1Sjsg 	/*DCN3_1_RDPCSTX_REG_LIST(0),*/
3471bb76ff1Sjsg 	/*DCN3_1_RDPCSTX_REG_LIST(1),*/
3481bb76ff1Sjsg 	/*DCN3_1_RDPCSTX_REG_LIST(2),*/
3491bb76ff1Sjsg 	/*DCN3_1_RDPCSTX_REG_LIST(3),*/
3501bb76ff1Sjsg 
3511bb76ff1Sjsg static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2];
3521bb76ff1Sjsg 
3531bb76ff1Sjsg static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = {
3541bb76ff1Sjsg 	DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT)
3551bb76ff1Sjsg };
3561bb76ff1Sjsg 
3571bb76ff1Sjsg static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = {
3581bb76ff1Sjsg 	DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK)
3591bb76ff1Sjsg };
3601bb76ff1Sjsg 
3611bb76ff1Sjsg #define dpp_regs_init(id)\
3621bb76ff1Sjsg 	DPP_REG_LIST_DCN30_COMMON_RI(id)
3631bb76ff1Sjsg 
3641bb76ff1Sjsg static struct dcn3_dpp_registers dpp_regs[4];
3651bb76ff1Sjsg 
3661bb76ff1Sjsg static const struct dcn3_dpp_shift tf_shift = {
3671bb76ff1Sjsg 		DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT)
3681bb76ff1Sjsg };
3691bb76ff1Sjsg 
3701bb76ff1Sjsg static const struct dcn3_dpp_mask tf_mask = {
3711bb76ff1Sjsg 		DPP_REG_LIST_SH_MASK_DCN30_COMMON(_MASK)
3721bb76ff1Sjsg };
3731bb76ff1Sjsg 
3741bb76ff1Sjsg 
3751bb76ff1Sjsg #define opp_regs_init(id)\
3761bb76ff1Sjsg 	OPP_REG_LIST_DCN30_RI(id)
3771bb76ff1Sjsg 
3781bb76ff1Sjsg static struct dcn20_opp_registers opp_regs[4];
3791bb76ff1Sjsg 
3801bb76ff1Sjsg static const struct dcn20_opp_shift opp_shift = {
3811bb76ff1Sjsg 	OPP_MASK_SH_LIST_DCN20(__SHIFT)
3821bb76ff1Sjsg };
3831bb76ff1Sjsg 
3841bb76ff1Sjsg static const struct dcn20_opp_mask opp_mask = {
3851bb76ff1Sjsg 	OPP_MASK_SH_LIST_DCN20(_MASK)
3861bb76ff1Sjsg };
3871bb76ff1Sjsg 
3881bb76ff1Sjsg #define aux_engine_regs_init(id)\
3891bb76ff1Sjsg 	( \
3901bb76ff1Sjsg 	AUX_COMMON_REG_LIST0_RI(id), \
3911bb76ff1Sjsg 	SR_ARR_INIT(AUXN_IMPCAL, id, 0), \
3921bb76ff1Sjsg 	SR_ARR_INIT(AUXP_IMPCAL, id, 0), \
3931bb76ff1Sjsg 	SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \
3941bb76ff1Sjsg 	SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\
3951bb76ff1Sjsg 	)
3961bb76ff1Sjsg 
3971bb76ff1Sjsg static struct dce110_aux_registers aux_engine_regs[5];
3981bb76ff1Sjsg 
3991bb76ff1Sjsg static const struct dce110_aux_registers_shift aux_shift = {
4001bb76ff1Sjsg 	DCN_AUX_MASK_SH_LIST(__SHIFT)
4011bb76ff1Sjsg };
4021bb76ff1Sjsg 
4031bb76ff1Sjsg static const struct dce110_aux_registers_mask aux_mask = {
4041bb76ff1Sjsg 	DCN_AUX_MASK_SH_LIST(_MASK)
4051bb76ff1Sjsg };
4061bb76ff1Sjsg 
4071bb76ff1Sjsg #define dwbc_regs_dcn3_init(id)\
4081bb76ff1Sjsg 	DWBC_COMMON_REG_LIST_DCN30_RI(id)
4091bb76ff1Sjsg 
4101bb76ff1Sjsg static struct dcn30_dwbc_registers dwbc30_regs[1];
4111bb76ff1Sjsg 
4121bb76ff1Sjsg static const struct dcn30_dwbc_shift dwbc30_shift = {
4131bb76ff1Sjsg 	DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)
4141bb76ff1Sjsg };
4151bb76ff1Sjsg 
4161bb76ff1Sjsg static const struct dcn30_dwbc_mask dwbc30_mask = {
4171bb76ff1Sjsg 	DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK)
4181bb76ff1Sjsg };
4191bb76ff1Sjsg 
4201bb76ff1Sjsg #define mcif_wb_regs_dcn3_init(id)\
4211bb76ff1Sjsg 	MCIF_WB_COMMON_REG_LIST_DCN32_RI(id)
4221bb76ff1Sjsg 
4231bb76ff1Sjsg static struct dcn30_mmhubbub_registers mcif_wb30_regs[1];
4241bb76ff1Sjsg 
4251bb76ff1Sjsg static const struct dcn30_mmhubbub_shift mcif_wb30_shift = {
4261bb76ff1Sjsg 	MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT)
4271bb76ff1Sjsg };
4281bb76ff1Sjsg 
4291bb76ff1Sjsg static const struct dcn30_mmhubbub_mask mcif_wb30_mask = {
4301bb76ff1Sjsg 	MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK)
4311bb76ff1Sjsg };
4321bb76ff1Sjsg 
4331bb76ff1Sjsg #define dsc_regsDCN20_init(id)\
4341bb76ff1Sjsg 	DSC_REG_LIST_DCN20_RI(id)
4351bb76ff1Sjsg 
4361bb76ff1Sjsg static struct dcn20_dsc_registers dsc_regs[4];
4371bb76ff1Sjsg 
4381bb76ff1Sjsg static const struct dcn20_dsc_shift dsc_shift = {
4391bb76ff1Sjsg 	DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)
4401bb76ff1Sjsg };
4411bb76ff1Sjsg 
4421bb76ff1Sjsg static const struct dcn20_dsc_mask dsc_mask = {
4431bb76ff1Sjsg 	DSC_REG_LIST_SH_MASK_DCN20(_MASK)
4441bb76ff1Sjsg };
4451bb76ff1Sjsg 
4461bb76ff1Sjsg static struct dcn30_mpc_registers mpc_regs;
4471bb76ff1Sjsg 
4481bb76ff1Sjsg #define dcn_mpc_regs_init() \
4491bb76ff1Sjsg 	MPC_REG_LIST_DCN3_2_RI(0),\
4501bb76ff1Sjsg 	MPC_REG_LIST_DCN3_2_RI(1),\
4511bb76ff1Sjsg 	MPC_REG_LIST_DCN3_2_RI(2),\
4521bb76ff1Sjsg 	MPC_REG_LIST_DCN3_2_RI(3),\
4531bb76ff1Sjsg 	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\
4541bb76ff1Sjsg 	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\
4551bb76ff1Sjsg 	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\
4561bb76ff1Sjsg 	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\
4571bb76ff1Sjsg 	MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0)
4581bb76ff1Sjsg 
4591bb76ff1Sjsg static const struct dcn30_mpc_shift mpc_shift = {
4601bb76ff1Sjsg 	MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT)
4611bb76ff1Sjsg };
4621bb76ff1Sjsg 
4631bb76ff1Sjsg static const struct dcn30_mpc_mask mpc_mask = {
4641bb76ff1Sjsg 	MPC_COMMON_MASK_SH_LIST_DCN32(_MASK)
4651bb76ff1Sjsg };
4661bb76ff1Sjsg 
4671bb76ff1Sjsg #define optc_regs_init(id)\
4681bb76ff1Sjsg 	OPTC_COMMON_REG_LIST_DCN3_2_RI(id)
4691bb76ff1Sjsg 
4701bb76ff1Sjsg static struct dcn_optc_registers optc_regs[4];
4711bb76ff1Sjsg 
4721bb76ff1Sjsg static const struct dcn_optc_shift optc_shift = {
4731bb76ff1Sjsg 	OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT)
4741bb76ff1Sjsg };
4751bb76ff1Sjsg 
4761bb76ff1Sjsg static const struct dcn_optc_mask optc_mask = {
4771bb76ff1Sjsg 	OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK)
4781bb76ff1Sjsg };
4791bb76ff1Sjsg 
4801bb76ff1Sjsg #define hubp_regs_init(id)\
4811bb76ff1Sjsg 	HUBP_REG_LIST_DCN32_RI(id)
4821bb76ff1Sjsg 
4831bb76ff1Sjsg static struct dcn_hubp2_registers hubp_regs[4];
4841bb76ff1Sjsg 
4851bb76ff1Sjsg 
4861bb76ff1Sjsg static const struct dcn_hubp2_shift hubp_shift = {
4871bb76ff1Sjsg 		HUBP_MASK_SH_LIST_DCN32(__SHIFT)
4881bb76ff1Sjsg };
4891bb76ff1Sjsg 
4901bb76ff1Sjsg static const struct dcn_hubp2_mask hubp_mask = {
4911bb76ff1Sjsg 		HUBP_MASK_SH_LIST_DCN32(_MASK)
4921bb76ff1Sjsg };
4931bb76ff1Sjsg 
4941bb76ff1Sjsg static struct dcn_hubbub_registers hubbub_reg;
4951bb76ff1Sjsg #define hubbub_reg_init()\
4961bb76ff1Sjsg 		HUBBUB_REG_LIST_DCN32_RI(0)
4971bb76ff1Sjsg 
4981bb76ff1Sjsg static const struct dcn_hubbub_shift hubbub_shift = {
4991bb76ff1Sjsg 		HUBBUB_MASK_SH_LIST_DCN32(__SHIFT)
5001bb76ff1Sjsg };
5011bb76ff1Sjsg 
5021bb76ff1Sjsg static const struct dcn_hubbub_mask hubbub_mask = {
5031bb76ff1Sjsg 		HUBBUB_MASK_SH_LIST_DCN32(_MASK)
5041bb76ff1Sjsg };
5051bb76ff1Sjsg 
5061bb76ff1Sjsg static struct dccg_registers dccg_regs;
5071bb76ff1Sjsg 
5081bb76ff1Sjsg #define dccg_regs_init()\
5091bb76ff1Sjsg 	DCCG_REG_LIST_DCN32_RI()
5101bb76ff1Sjsg 
5111bb76ff1Sjsg static const struct dccg_shift dccg_shift = {
5121bb76ff1Sjsg 		DCCG_MASK_SH_LIST_DCN32(__SHIFT)
5131bb76ff1Sjsg };
5141bb76ff1Sjsg 
5151bb76ff1Sjsg static const struct dccg_mask dccg_mask = {
5161bb76ff1Sjsg 		DCCG_MASK_SH_LIST_DCN32(_MASK)
5171bb76ff1Sjsg };
5181bb76ff1Sjsg 
5191bb76ff1Sjsg 
5201bb76ff1Sjsg #define SRII2(reg_name_pre, reg_name_post, id)\
5211bb76ff1Sjsg 	.reg_name_pre ## _ ##  reg_name_post[id] = BASE(reg ## reg_name_pre \
5221bb76ff1Sjsg 			## id ## _ ## reg_name_post ## _BASE_IDX) + \
5231bb76ff1Sjsg 			reg ## reg_name_pre ## id ## _ ## reg_name_post
5241bb76ff1Sjsg 
5251bb76ff1Sjsg 
5261bb76ff1Sjsg #define HWSEQ_DCN32_REG_LIST()\
5271bb76ff1Sjsg 	SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
5281bb76ff1Sjsg 	SR(DIO_MEM_PWR_CTRL), \
5291bb76ff1Sjsg 	SR(ODM_MEM_PWR_CTRL3), \
5301bb76ff1Sjsg 	SR(MMHUBBUB_MEM_PWR_CNTL), \
5311bb76ff1Sjsg 	SR(DCCG_GATE_DISABLE_CNTL), \
5321bb76ff1Sjsg 	SR(DCCG_GATE_DISABLE_CNTL2), \
5331bb76ff1Sjsg 	SR(DCFCLK_CNTL),\
5341bb76ff1Sjsg 	SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \
5351bb76ff1Sjsg 	SRII(PIXEL_RATE_CNTL, OTG, 0), \
5361bb76ff1Sjsg 	SRII(PIXEL_RATE_CNTL, OTG, 1),\
5371bb76ff1Sjsg 	SRII(PIXEL_RATE_CNTL, OTG, 2),\
5381bb76ff1Sjsg 	SRII(PIXEL_RATE_CNTL, OTG, 3),\
5391bb76ff1Sjsg 	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\
5401bb76ff1Sjsg 	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\
5411bb76ff1Sjsg 	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\
5421bb76ff1Sjsg 	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\
5431bb76ff1Sjsg 	SR(MICROSECOND_TIME_BASE_DIV), \
5441bb76ff1Sjsg 	SR(MILLISECOND_TIME_BASE_DIV), \
5451bb76ff1Sjsg 	SR(DISPCLK_FREQ_CHANGE_CNTL), \
5461bb76ff1Sjsg 	SR(RBBMIF_TIMEOUT_DIS), \
5471bb76ff1Sjsg 	SR(RBBMIF_TIMEOUT_DIS_2), \
5481bb76ff1Sjsg 	SR(DCHUBBUB_CRC_CTRL), \
5491bb76ff1Sjsg 	SR(DPP_TOP0_DPP_CRC_CTRL), \
5501bb76ff1Sjsg 	SR(DPP_TOP0_DPP_CRC_VAL_B_A), \
5511bb76ff1Sjsg 	SR(DPP_TOP0_DPP_CRC_VAL_R_G), \
5521bb76ff1Sjsg 	SR(MPC_CRC_CTRL), \
5531bb76ff1Sjsg 	SR(MPC_CRC_RESULT_GB), \
5541bb76ff1Sjsg 	SR(MPC_CRC_RESULT_C), \
5551bb76ff1Sjsg 	SR(MPC_CRC_RESULT_AR), \
5561bb76ff1Sjsg 	SR(DOMAIN0_PG_CONFIG), \
5571bb76ff1Sjsg 	SR(DOMAIN1_PG_CONFIG), \
5581bb76ff1Sjsg 	SR(DOMAIN2_PG_CONFIG), \
5591bb76ff1Sjsg 	SR(DOMAIN3_PG_CONFIG), \
5601bb76ff1Sjsg 	SR(DOMAIN16_PG_CONFIG), \
5611bb76ff1Sjsg 	SR(DOMAIN17_PG_CONFIG), \
5621bb76ff1Sjsg 	SR(DOMAIN18_PG_CONFIG), \
5631bb76ff1Sjsg 	SR(DOMAIN19_PG_CONFIG), \
5641bb76ff1Sjsg 	SR(DOMAIN0_PG_STATUS), \
5651bb76ff1Sjsg 	SR(DOMAIN1_PG_STATUS), \
5661bb76ff1Sjsg 	SR(DOMAIN2_PG_STATUS), \
5671bb76ff1Sjsg 	SR(DOMAIN3_PG_STATUS), \
5681bb76ff1Sjsg 	SR(DOMAIN16_PG_STATUS), \
5691bb76ff1Sjsg 	SR(DOMAIN17_PG_STATUS), \
5701bb76ff1Sjsg 	SR(DOMAIN18_PG_STATUS), \
5711bb76ff1Sjsg 	SR(DOMAIN19_PG_STATUS), \
5721bb76ff1Sjsg 	SR(D1VGA_CONTROL), \
5731bb76ff1Sjsg 	SR(D2VGA_CONTROL), \
5741bb76ff1Sjsg 	SR(D3VGA_CONTROL), \
5751bb76ff1Sjsg 	SR(D4VGA_CONTROL), \
5761bb76ff1Sjsg 	SR(D5VGA_CONTROL), \
5771bb76ff1Sjsg 	SR(D6VGA_CONTROL), \
5781bb76ff1Sjsg 	SR(DC_IP_REQUEST_CNTL), \
5791bb76ff1Sjsg 	SR(AZALIA_AUDIO_DTO), \
5801bb76ff1Sjsg 	SR(AZALIA_CONTROLLER_CLOCK_GATING)
5811bb76ff1Sjsg 
5821bb76ff1Sjsg static struct dce_hwseq_registers hwseq_reg;
5831bb76ff1Sjsg 
5841bb76ff1Sjsg #define hwseq_reg_init()\
5851bb76ff1Sjsg 	HWSEQ_DCN32_REG_LIST()
5861bb76ff1Sjsg 
5871bb76ff1Sjsg #define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\
5881bb76ff1Sjsg 	HWSEQ_DCN_MASK_SH_LIST(mask_sh), \
5891bb76ff1Sjsg 	HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
5901bb76ff1Sjsg 	HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
5911bb76ff1Sjsg 	HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
5921bb76ff1Sjsg 	HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
5931bb76ff1Sjsg 	HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
5941bb76ff1Sjsg 	HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
5951bb76ff1Sjsg 	HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
5961bb76ff1Sjsg 	HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
5971bb76ff1Sjsg 	HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
5981bb76ff1Sjsg 	HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
5991bb76ff1Sjsg 	HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
6001bb76ff1Sjsg 	HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
6011bb76ff1Sjsg 	HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
6021bb76ff1Sjsg 	HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
6031bb76ff1Sjsg 	HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
6041bb76ff1Sjsg 	HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
6051bb76ff1Sjsg 	HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
6061bb76ff1Sjsg 	HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
6071bb76ff1Sjsg 	HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
6081bb76ff1Sjsg 	HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
6091bb76ff1Sjsg 	HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
6101bb76ff1Sjsg 	HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
6111bb76ff1Sjsg 	HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
6121bb76ff1Sjsg 	HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
6131bb76ff1Sjsg 	HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
6141bb76ff1Sjsg 	HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
6151bb76ff1Sjsg 	HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \
6161bb76ff1Sjsg 	HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \
6171bb76ff1Sjsg 	HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \
6181bb76ff1Sjsg 	HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \
6191bb76ff1Sjsg 	HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh)
6201bb76ff1Sjsg 
6211bb76ff1Sjsg static const struct dce_hwseq_shift hwseq_shift = {
6221bb76ff1Sjsg 		HWSEQ_DCN32_MASK_SH_LIST(__SHIFT)
6231bb76ff1Sjsg };
6241bb76ff1Sjsg 
6251bb76ff1Sjsg static const struct dce_hwseq_mask hwseq_mask = {
6261bb76ff1Sjsg 		HWSEQ_DCN32_MASK_SH_LIST(_MASK)
6271bb76ff1Sjsg };
6281bb76ff1Sjsg #define vmid_regs_init(id)\
6291bb76ff1Sjsg 		DCN20_VMID_REG_LIST_RI(id)
6301bb76ff1Sjsg 
6311bb76ff1Sjsg static struct dcn_vmid_registers vmid_regs[16];
6321bb76ff1Sjsg 
6331bb76ff1Sjsg static const struct dcn20_vmid_shift vmid_shifts = {
6341bb76ff1Sjsg 		DCN20_VMID_MASK_SH_LIST(__SHIFT)
6351bb76ff1Sjsg };
6361bb76ff1Sjsg 
6371bb76ff1Sjsg static const struct dcn20_vmid_mask vmid_masks = {
6381bb76ff1Sjsg 		DCN20_VMID_MASK_SH_LIST(_MASK)
6391bb76ff1Sjsg };
6401bb76ff1Sjsg 
6411bb76ff1Sjsg static const struct resource_caps res_cap_dcn32 = {
6421bb76ff1Sjsg 	.num_timing_generator = 4,
6431bb76ff1Sjsg 	.num_opp = 4,
6441bb76ff1Sjsg 	.num_video_plane = 4,
6451bb76ff1Sjsg 	.num_audio = 5,
6461bb76ff1Sjsg 	.num_stream_encoder = 5,
6471bb76ff1Sjsg 	.num_hpo_dp_stream_encoder = 4,
6481bb76ff1Sjsg 	.num_hpo_dp_link_encoder = 2,
6491bb76ff1Sjsg 	.num_pll = 5,
6501bb76ff1Sjsg 	.num_dwb = 1,
6511bb76ff1Sjsg 	.num_ddc = 5,
6521bb76ff1Sjsg 	.num_vmid = 16,
6531bb76ff1Sjsg 	.num_mpc_3dlut = 4,
6541bb76ff1Sjsg 	.num_dsc = 4,
6551bb76ff1Sjsg };
6561bb76ff1Sjsg 
6571bb76ff1Sjsg static const struct dc_plane_cap plane_cap = {
6581bb76ff1Sjsg 	.type = DC_PLANE_TYPE_DCN_UNIVERSAL,
6591bb76ff1Sjsg 	.per_pixel_alpha = true,
6601bb76ff1Sjsg 
6611bb76ff1Sjsg 	.pixel_format_support = {
6621bb76ff1Sjsg 			.argb8888 = true,
6631bb76ff1Sjsg 			.nv12 = true,
6641bb76ff1Sjsg 			.fp16 = true,
6651bb76ff1Sjsg 			.p010 = true,
6661bb76ff1Sjsg 			.ayuv = false,
6671bb76ff1Sjsg 	},
6681bb76ff1Sjsg 
6691bb76ff1Sjsg 	.max_upscale_factor = {
6701bb76ff1Sjsg 			.argb8888 = 16000,
6711bb76ff1Sjsg 			.nv12 = 16000,
6721bb76ff1Sjsg 			.fp16 = 16000
6731bb76ff1Sjsg 	},
6741bb76ff1Sjsg 
6751bb76ff1Sjsg 	// 6:1 downscaling ratio: 1000/6 = 166.666
6761bb76ff1Sjsg 	.max_downscale_factor = {
6771bb76ff1Sjsg 			.argb8888 = 167,
6781bb76ff1Sjsg 			.nv12 = 167,
6791bb76ff1Sjsg 			.fp16 = 167
6801bb76ff1Sjsg 	},
6811bb76ff1Sjsg 	64,
6821bb76ff1Sjsg 	64
6831bb76ff1Sjsg };
6841bb76ff1Sjsg 
6851bb76ff1Sjsg static const struct dc_debug_options debug_defaults_drv = {
6861bb76ff1Sjsg 	.disable_dmcu = true,
6871bb76ff1Sjsg 	.force_abm_enable = false,
6881bb76ff1Sjsg 	.timing_trace = false,
6891bb76ff1Sjsg 	.clock_trace = true,
6901bb76ff1Sjsg 	.disable_pplib_clock_request = false,
6911bb76ff1Sjsg 	.pipe_split_policy = MPC_SPLIT_AVOID, // Due to CRB, no need to MPC split anymore
6921bb76ff1Sjsg 	.force_single_disp_pipe_split = false,
6931bb76ff1Sjsg 	.disable_dcc = DCC_ENABLE,
6941bb76ff1Sjsg 	.vsr_support = true,
6951bb76ff1Sjsg 	.performance_trace = false,
6961bb76ff1Sjsg 	.max_downscale_src_width = 7680,/*upto 8K*/
6971bb76ff1Sjsg 	.disable_pplib_wm_range = false,
6981bb76ff1Sjsg 	.scl_reset_length10 = true,
6991bb76ff1Sjsg 	.sanity_checks = false,
7001bb76ff1Sjsg 	.underflow_assert_delay_us = 0xFFFFFFFF,
7011bb76ff1Sjsg 	.dwb_fi_phase = -1, // -1 = disable,
7021bb76ff1Sjsg 	.dmub_command_table = true,
7031bb76ff1Sjsg 	.enable_mem_low_power = {
7041bb76ff1Sjsg 		.bits = {
7051bb76ff1Sjsg 			.vga = false,
7061bb76ff1Sjsg 			.i2c = false,
7071bb76ff1Sjsg 			.dmcu = false, // This is previously known to cause hang on S3 cycles if enabled
7081bb76ff1Sjsg 			.dscl = false,
7091bb76ff1Sjsg 			.cm = false,
7101bb76ff1Sjsg 			.mpc = false,
7111bb76ff1Sjsg 			.optc = true,
7121bb76ff1Sjsg 		}
7131bb76ff1Sjsg 	},
7141bb76ff1Sjsg 	.use_max_lb = true,
7151bb76ff1Sjsg 	.force_disable_subvp = false,
7161bb76ff1Sjsg 	.exit_idle_opt_for_cursor_updates = true,
7171bb76ff1Sjsg 	.enable_single_display_2to1_odm_policy = true,
7181bb76ff1Sjsg 
7191bb76ff1Sjsg 	/* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/
7201bb76ff1Sjsg 	.enable_double_buffered_dsc_pg_support = true,
7211bb76ff1Sjsg 	.enable_dp_dig_pixel_rate_div_policy = 1,
722f005ef32Sjsg 	.allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback"
7231bb76ff1Sjsg 	.alloc_extra_way_for_cursor = true,
7241bb76ff1Sjsg 	.min_prefetch_in_strobe_ns = 60000, // 60us
725f005ef32Sjsg 	.disable_unbounded_requesting = false,
726f005ef32Sjsg 	.override_dispclk_programming = true,
727f005ef32Sjsg 	.disable_fpo_optimizations = false,
728f005ef32Sjsg 	.fpo_vactive_margin_us = 2000, // 2000us
729f005ef32Sjsg 	.disable_fpo_vactive = false,
730f005ef32Sjsg 	.disable_boot_optimizations = false,
731f005ef32Sjsg 	.disable_subvp_high_refresh = false,
732f005ef32Sjsg 	.disable_dp_plus_plus_wa = true,
733f005ef32Sjsg 	.fpo_vactive_min_active_margin_us = 200,
734f005ef32Sjsg 	.fpo_vactive_max_blank_us = 1000,
735f005ef32Sjsg 	.enable_legacy_fast_update = false,
7361bb76ff1Sjsg };
7371bb76ff1Sjsg 
7381bb76ff1Sjsg static struct dce_aux *dcn32_aux_engine_create(
7391bb76ff1Sjsg 	struct dc_context *ctx,
7401bb76ff1Sjsg 	uint32_t inst)
7411bb76ff1Sjsg {
7421bb76ff1Sjsg 	struct aux_engine_dce110 *aux_engine =
7431bb76ff1Sjsg 		kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);
7441bb76ff1Sjsg 
7451bb76ff1Sjsg 	if (!aux_engine)
7461bb76ff1Sjsg 		return NULL;
7471bb76ff1Sjsg 
7481bb76ff1Sjsg #undef REG_STRUCT
7491bb76ff1Sjsg #define REG_STRUCT aux_engine_regs
7501bb76ff1Sjsg 	aux_engine_regs_init(0),
7511bb76ff1Sjsg 	aux_engine_regs_init(1),
7521bb76ff1Sjsg 	aux_engine_regs_init(2),
7531bb76ff1Sjsg 	aux_engine_regs_init(3),
7541bb76ff1Sjsg 	aux_engine_regs_init(4);
7551bb76ff1Sjsg 
7561bb76ff1Sjsg 	dce110_aux_engine_construct(aux_engine, ctx, inst,
7571bb76ff1Sjsg 				    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
7581bb76ff1Sjsg 				    &aux_engine_regs[inst],
7591bb76ff1Sjsg 					&aux_mask,
7601bb76ff1Sjsg 					&aux_shift,
7611bb76ff1Sjsg 					ctx->dc->caps.extended_aux_timeout_support);
7621bb76ff1Sjsg 
7631bb76ff1Sjsg 	return &aux_engine->base;
7641bb76ff1Sjsg }
7651bb76ff1Sjsg #define i2c_inst_regs_init(id)\
7661bb76ff1Sjsg 	I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id)
7671bb76ff1Sjsg 
7681bb76ff1Sjsg static struct dce_i2c_registers i2c_hw_regs[5];
7691bb76ff1Sjsg 
7701bb76ff1Sjsg static const struct dce_i2c_shift i2c_shifts = {
7711bb76ff1Sjsg 		I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT)
7721bb76ff1Sjsg };
7731bb76ff1Sjsg 
7741bb76ff1Sjsg static const struct dce_i2c_mask i2c_masks = {
7751bb76ff1Sjsg 		I2C_COMMON_MASK_SH_LIST_DCN30(_MASK)
7761bb76ff1Sjsg };
7771bb76ff1Sjsg 
7781bb76ff1Sjsg static struct dce_i2c_hw *dcn32_i2c_hw_create(
7791bb76ff1Sjsg 	struct dc_context *ctx,
7801bb76ff1Sjsg 	uint32_t inst)
7811bb76ff1Sjsg {
7821bb76ff1Sjsg 	struct dce_i2c_hw *dce_i2c_hw =
7831bb76ff1Sjsg 		kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);
7841bb76ff1Sjsg 
7851bb76ff1Sjsg 	if (!dce_i2c_hw)
7861bb76ff1Sjsg 		return NULL;
7871bb76ff1Sjsg 
7881bb76ff1Sjsg #undef REG_STRUCT
7891bb76ff1Sjsg #define REG_STRUCT i2c_hw_regs
7901bb76ff1Sjsg 	i2c_inst_regs_init(1),
7911bb76ff1Sjsg 	i2c_inst_regs_init(2),
7921bb76ff1Sjsg 	i2c_inst_regs_init(3),
7931bb76ff1Sjsg 	i2c_inst_regs_init(4),
7941bb76ff1Sjsg 	i2c_inst_regs_init(5);
7951bb76ff1Sjsg 
7961bb76ff1Sjsg 	dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,
7971bb76ff1Sjsg 				    &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);
7981bb76ff1Sjsg 
7991bb76ff1Sjsg 	return dce_i2c_hw;
8001bb76ff1Sjsg }
8011bb76ff1Sjsg 
8021bb76ff1Sjsg static struct clock_source *dcn32_clock_source_create(
8031bb76ff1Sjsg 		struct dc_context *ctx,
8041bb76ff1Sjsg 		struct dc_bios *bios,
8051bb76ff1Sjsg 		enum clock_source_id id,
8061bb76ff1Sjsg 		const struct dce110_clk_src_regs *regs,
8071bb76ff1Sjsg 		bool dp_clk_src)
8081bb76ff1Sjsg {
8091bb76ff1Sjsg 	struct dce110_clk_src *clk_src =
8101bb76ff1Sjsg 		kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL);
8111bb76ff1Sjsg 
8121bb76ff1Sjsg 	if (!clk_src)
8131bb76ff1Sjsg 		return NULL;
8141bb76ff1Sjsg 
8151bb76ff1Sjsg 	if (dcn31_clk_src_construct(clk_src, ctx, bios, id,
8161bb76ff1Sjsg 			regs, &cs_shift, &cs_mask)) {
8171bb76ff1Sjsg 		clk_src->base.dp_clk_src = dp_clk_src;
8181bb76ff1Sjsg 		return &clk_src->base;
8191bb76ff1Sjsg 	}
8201bb76ff1Sjsg 
821f005ef32Sjsg 	kfree(clk_src);
8221bb76ff1Sjsg 	BREAK_TO_DEBUGGER();
8231bb76ff1Sjsg 	return NULL;
8241bb76ff1Sjsg }
8251bb76ff1Sjsg 
8261bb76ff1Sjsg static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx)
8271bb76ff1Sjsg {
8281bb76ff1Sjsg 	int i;
8291bb76ff1Sjsg 
8301bb76ff1Sjsg 	struct dcn20_hubbub *hubbub2 = kzalloc(sizeof(struct dcn20_hubbub),
8311bb76ff1Sjsg 					  GFP_KERNEL);
8321bb76ff1Sjsg 
8331bb76ff1Sjsg 	if (!hubbub2)
8341bb76ff1Sjsg 		return NULL;
8351bb76ff1Sjsg 
8361bb76ff1Sjsg #undef REG_STRUCT
8371bb76ff1Sjsg #define REG_STRUCT hubbub_reg
8381bb76ff1Sjsg 	hubbub_reg_init();
8391bb76ff1Sjsg 
8401bb76ff1Sjsg #undef REG_STRUCT
8411bb76ff1Sjsg #define REG_STRUCT vmid_regs
8421bb76ff1Sjsg 	vmid_regs_init(0),
8431bb76ff1Sjsg 	vmid_regs_init(1),
8441bb76ff1Sjsg 	vmid_regs_init(2),
8451bb76ff1Sjsg 	vmid_regs_init(3),
8461bb76ff1Sjsg 	vmid_regs_init(4),
8471bb76ff1Sjsg 	vmid_regs_init(5),
8481bb76ff1Sjsg 	vmid_regs_init(6),
8491bb76ff1Sjsg 	vmid_regs_init(7),
8501bb76ff1Sjsg 	vmid_regs_init(8),
8511bb76ff1Sjsg 	vmid_regs_init(9),
8521bb76ff1Sjsg 	vmid_regs_init(10),
8531bb76ff1Sjsg 	vmid_regs_init(11),
8541bb76ff1Sjsg 	vmid_regs_init(12),
8551bb76ff1Sjsg 	vmid_regs_init(13),
8561bb76ff1Sjsg 	vmid_regs_init(14),
8571bb76ff1Sjsg 	vmid_regs_init(15);
8581bb76ff1Sjsg 
8591bb76ff1Sjsg 	hubbub32_construct(hubbub2, ctx,
8601bb76ff1Sjsg 			&hubbub_reg,
8611bb76ff1Sjsg 			&hubbub_shift,
8621bb76ff1Sjsg 			&hubbub_mask,
8631bb76ff1Sjsg 			ctx->dc->dml.ip.det_buffer_size_kbytes,
8641bb76ff1Sjsg 			ctx->dc->dml.ip.pixel_chunk_size_kbytes,
8651bb76ff1Sjsg 			ctx->dc->dml.ip.config_return_buffer_size_in_kbytes);
8661bb76ff1Sjsg 
8671bb76ff1Sjsg 
8681bb76ff1Sjsg 	for (i = 0; i < res_cap_dcn32.num_vmid; i++) {
8691bb76ff1Sjsg 		struct dcn20_vmid *vmid = &hubbub2->vmid[i];
8701bb76ff1Sjsg 
8711bb76ff1Sjsg 		vmid->ctx = ctx;
8721bb76ff1Sjsg 
8731bb76ff1Sjsg 		vmid->regs = &vmid_regs[i];
8741bb76ff1Sjsg 		vmid->shifts = &vmid_shifts;
8751bb76ff1Sjsg 		vmid->masks = &vmid_masks;
8761bb76ff1Sjsg 	}
8771bb76ff1Sjsg 
8781bb76ff1Sjsg 	return &hubbub2->base;
8791bb76ff1Sjsg }
8801bb76ff1Sjsg 
8811bb76ff1Sjsg static struct hubp *dcn32_hubp_create(
8821bb76ff1Sjsg 	struct dc_context *ctx,
8831bb76ff1Sjsg 	uint32_t inst)
8841bb76ff1Sjsg {
8851bb76ff1Sjsg 	struct dcn20_hubp *hubp2 =
8861bb76ff1Sjsg 		kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL);
8871bb76ff1Sjsg 
8881bb76ff1Sjsg 	if (!hubp2)
8891bb76ff1Sjsg 		return NULL;
8901bb76ff1Sjsg 
8911bb76ff1Sjsg #undef REG_STRUCT
8921bb76ff1Sjsg #define REG_STRUCT hubp_regs
8931bb76ff1Sjsg 	hubp_regs_init(0),
8941bb76ff1Sjsg 	hubp_regs_init(1),
8951bb76ff1Sjsg 	hubp_regs_init(2),
8961bb76ff1Sjsg 	hubp_regs_init(3);
8971bb76ff1Sjsg 
8981bb76ff1Sjsg 	if (hubp32_construct(hubp2, ctx, inst,
8991bb76ff1Sjsg 			&hubp_regs[inst], &hubp_shift, &hubp_mask))
9001bb76ff1Sjsg 		return &hubp2->base;
9011bb76ff1Sjsg 
9021bb76ff1Sjsg 	BREAK_TO_DEBUGGER();
9031bb76ff1Sjsg 	kfree(hubp2);
9041bb76ff1Sjsg 	return NULL;
9051bb76ff1Sjsg }
9061bb76ff1Sjsg 
9071bb76ff1Sjsg static void dcn32_dpp_destroy(struct dpp **dpp)
9081bb76ff1Sjsg {
9091bb76ff1Sjsg 	kfree(TO_DCN30_DPP(*dpp));
9101bb76ff1Sjsg 	*dpp = NULL;
9111bb76ff1Sjsg }
9121bb76ff1Sjsg 
9131bb76ff1Sjsg static struct dpp *dcn32_dpp_create(
9141bb76ff1Sjsg 	struct dc_context *ctx,
9151bb76ff1Sjsg 	uint32_t inst)
9161bb76ff1Sjsg {
9171bb76ff1Sjsg 	struct dcn3_dpp *dpp3 =
9181bb76ff1Sjsg 		kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL);
9191bb76ff1Sjsg 
9201bb76ff1Sjsg 	if (!dpp3)
9211bb76ff1Sjsg 		return NULL;
9221bb76ff1Sjsg 
9231bb76ff1Sjsg #undef REG_STRUCT
9241bb76ff1Sjsg #define REG_STRUCT dpp_regs
9251bb76ff1Sjsg 	dpp_regs_init(0),
9261bb76ff1Sjsg 	dpp_regs_init(1),
9271bb76ff1Sjsg 	dpp_regs_init(2),
9281bb76ff1Sjsg 	dpp_regs_init(3);
9291bb76ff1Sjsg 
9301bb76ff1Sjsg 	if (dpp32_construct(dpp3, ctx, inst,
9311bb76ff1Sjsg 			&dpp_regs[inst], &tf_shift, &tf_mask))
9321bb76ff1Sjsg 		return &dpp3->base;
9331bb76ff1Sjsg 
9341bb76ff1Sjsg 	BREAK_TO_DEBUGGER();
9351bb76ff1Sjsg 	kfree(dpp3);
9361bb76ff1Sjsg 	return NULL;
9371bb76ff1Sjsg }
9381bb76ff1Sjsg 
9391bb76ff1Sjsg static struct mpc *dcn32_mpc_create(
9401bb76ff1Sjsg 		struct dc_context *ctx,
9411bb76ff1Sjsg 		int num_mpcc,
9421bb76ff1Sjsg 		int num_rmu)
9431bb76ff1Sjsg {
9441bb76ff1Sjsg 	struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc),
9451bb76ff1Sjsg 					  GFP_KERNEL);
9461bb76ff1Sjsg 
9471bb76ff1Sjsg 	if (!mpc30)
9481bb76ff1Sjsg 		return NULL;
9491bb76ff1Sjsg 
9501bb76ff1Sjsg #undef REG_STRUCT
9511bb76ff1Sjsg #define REG_STRUCT mpc_regs
9521bb76ff1Sjsg 	dcn_mpc_regs_init();
9531bb76ff1Sjsg 
9541bb76ff1Sjsg 	dcn32_mpc_construct(mpc30, ctx,
9551bb76ff1Sjsg 			&mpc_regs,
9561bb76ff1Sjsg 			&mpc_shift,
9571bb76ff1Sjsg 			&mpc_mask,
9581bb76ff1Sjsg 			num_mpcc,
9591bb76ff1Sjsg 			num_rmu);
9601bb76ff1Sjsg 
9611bb76ff1Sjsg 	return &mpc30->base;
9621bb76ff1Sjsg }
9631bb76ff1Sjsg 
9641bb76ff1Sjsg static struct output_pixel_processor *dcn32_opp_create(
9651bb76ff1Sjsg 	struct dc_context *ctx, uint32_t inst)
9661bb76ff1Sjsg {
9671bb76ff1Sjsg 	struct dcn20_opp *opp2 =
9681bb76ff1Sjsg 		kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL);
9691bb76ff1Sjsg 
9701bb76ff1Sjsg 	if (!opp2) {
9711bb76ff1Sjsg 		BREAK_TO_DEBUGGER();
9721bb76ff1Sjsg 		return NULL;
9731bb76ff1Sjsg 	}
9741bb76ff1Sjsg 
9751bb76ff1Sjsg #undef REG_STRUCT
9761bb76ff1Sjsg #define REG_STRUCT opp_regs
9771bb76ff1Sjsg 	opp_regs_init(0),
9781bb76ff1Sjsg 	opp_regs_init(1),
9791bb76ff1Sjsg 	opp_regs_init(2),
9801bb76ff1Sjsg 	opp_regs_init(3);
9811bb76ff1Sjsg 
9821bb76ff1Sjsg 	dcn20_opp_construct(opp2, ctx, inst,
9831bb76ff1Sjsg 			&opp_regs[inst], &opp_shift, &opp_mask);
9841bb76ff1Sjsg 	return &opp2->base;
9851bb76ff1Sjsg }
9861bb76ff1Sjsg 
9871bb76ff1Sjsg 
9881bb76ff1Sjsg static struct timing_generator *dcn32_timing_generator_create(
9891bb76ff1Sjsg 		struct dc_context *ctx,
9901bb76ff1Sjsg 		uint32_t instance)
9911bb76ff1Sjsg {
9921bb76ff1Sjsg 	struct optc *tgn10 =
9931bb76ff1Sjsg 		kzalloc(sizeof(struct optc), GFP_KERNEL);
9941bb76ff1Sjsg 
9951bb76ff1Sjsg 	if (!tgn10)
9961bb76ff1Sjsg 		return NULL;
9971bb76ff1Sjsg 
9981bb76ff1Sjsg #undef REG_STRUCT
9991bb76ff1Sjsg #define REG_STRUCT optc_regs
10001bb76ff1Sjsg 	optc_regs_init(0),
10011bb76ff1Sjsg 	optc_regs_init(1),
10021bb76ff1Sjsg 	optc_regs_init(2),
10031bb76ff1Sjsg 	optc_regs_init(3);
10041bb76ff1Sjsg 
10051bb76ff1Sjsg 	tgn10->base.inst = instance;
10061bb76ff1Sjsg 	tgn10->base.ctx = ctx;
10071bb76ff1Sjsg 
10081bb76ff1Sjsg 	tgn10->tg_regs = &optc_regs[instance];
10091bb76ff1Sjsg 	tgn10->tg_shift = &optc_shift;
10101bb76ff1Sjsg 	tgn10->tg_mask = &optc_mask;
10111bb76ff1Sjsg 
10121bb76ff1Sjsg 	dcn32_timing_generator_init(tgn10);
10131bb76ff1Sjsg 
10141bb76ff1Sjsg 	return &tgn10->base;
10151bb76ff1Sjsg }
10161bb76ff1Sjsg 
10171bb76ff1Sjsg static const struct encoder_feature_support link_enc_feature = {
10181bb76ff1Sjsg 		.max_hdmi_deep_color = COLOR_DEPTH_121212,
10191bb76ff1Sjsg 		.max_hdmi_pixel_clock = 600000,
10201bb76ff1Sjsg 		.hdmi_ycbcr420_supported = true,
10211bb76ff1Sjsg 		.dp_ycbcr420_supported = true,
10221bb76ff1Sjsg 		.fec_supported = true,
10231bb76ff1Sjsg 		.flags.bits.IS_HBR2_CAPABLE = true,
10241bb76ff1Sjsg 		.flags.bits.IS_HBR3_CAPABLE = true,
10251bb76ff1Sjsg 		.flags.bits.IS_TPS3_CAPABLE = true,
10261bb76ff1Sjsg 		.flags.bits.IS_TPS4_CAPABLE = true
10271bb76ff1Sjsg };
10281bb76ff1Sjsg 
10291bb76ff1Sjsg static struct link_encoder *dcn32_link_encoder_create(
10301bb76ff1Sjsg 	struct dc_context *ctx,
10311bb76ff1Sjsg 	const struct encoder_init_data *enc_init_data)
10321bb76ff1Sjsg {
10331bb76ff1Sjsg 	struct dcn20_link_encoder *enc20 =
10341bb76ff1Sjsg 		kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
10351bb76ff1Sjsg 
10361bb76ff1Sjsg 	if (!enc20)
10371bb76ff1Sjsg 		return NULL;
10381bb76ff1Sjsg 
10391bb76ff1Sjsg #undef REG_STRUCT
10401bb76ff1Sjsg #define REG_STRUCT link_enc_aux_regs
10411bb76ff1Sjsg 	aux_regs_init(0),
10421bb76ff1Sjsg 	aux_regs_init(1),
10431bb76ff1Sjsg 	aux_regs_init(2),
10441bb76ff1Sjsg 	aux_regs_init(3),
10451bb76ff1Sjsg 	aux_regs_init(4);
10461bb76ff1Sjsg 
10471bb76ff1Sjsg #undef REG_STRUCT
10481bb76ff1Sjsg #define REG_STRUCT link_enc_hpd_regs
10491bb76ff1Sjsg 	hpd_regs_init(0),
10501bb76ff1Sjsg 	hpd_regs_init(1),
10511bb76ff1Sjsg 	hpd_regs_init(2),
10521bb76ff1Sjsg 	hpd_regs_init(3),
10531bb76ff1Sjsg 	hpd_regs_init(4);
10541bb76ff1Sjsg 
10551bb76ff1Sjsg #undef REG_STRUCT
10561bb76ff1Sjsg #define REG_STRUCT link_enc_regs
10571bb76ff1Sjsg 	link_regs_init(0, A),
10581bb76ff1Sjsg 	link_regs_init(1, B),
10591bb76ff1Sjsg 	link_regs_init(2, C),
10601bb76ff1Sjsg 	link_regs_init(3, D),
10611bb76ff1Sjsg 	link_regs_init(4, E);
10621bb76ff1Sjsg 
10631bb76ff1Sjsg 	dcn32_link_encoder_construct(enc20,
10641bb76ff1Sjsg 			enc_init_data,
10651bb76ff1Sjsg 			&link_enc_feature,
10661bb76ff1Sjsg 			&link_enc_regs[enc_init_data->transmitter],
10671bb76ff1Sjsg 			&link_enc_aux_regs[enc_init_data->channel - 1],
10681bb76ff1Sjsg 			&link_enc_hpd_regs[enc_init_data->hpd_source],
10691bb76ff1Sjsg 			&le_shift,
10701bb76ff1Sjsg 			&le_mask);
10711bb76ff1Sjsg 
10721bb76ff1Sjsg 	return &enc20->enc10.base;
10731bb76ff1Sjsg }
10741bb76ff1Sjsg 
10751bb76ff1Sjsg struct panel_cntl *dcn32_panel_cntl_create(const struct panel_cntl_init_data *init_data)
10761bb76ff1Sjsg {
10771bb76ff1Sjsg 	struct dcn31_panel_cntl *panel_cntl =
10781bb76ff1Sjsg 		kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL);
10791bb76ff1Sjsg 
10801bb76ff1Sjsg 	if (!panel_cntl)
10811bb76ff1Sjsg 		return NULL;
10821bb76ff1Sjsg 
10831bb76ff1Sjsg 	dcn31_panel_cntl_construct(panel_cntl, init_data);
10841bb76ff1Sjsg 
10851bb76ff1Sjsg 	return &panel_cntl->base;
10861bb76ff1Sjsg }
10871bb76ff1Sjsg 
10881bb76ff1Sjsg static void read_dce_straps(
10891bb76ff1Sjsg 	struct dc_context *ctx,
10901bb76ff1Sjsg 	struct resource_straps *straps)
10911bb76ff1Sjsg {
10921bb76ff1Sjsg 	generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS,
10931bb76ff1Sjsg 		FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);
10941bb76ff1Sjsg 
10951bb76ff1Sjsg }
10961bb76ff1Sjsg 
10971bb76ff1Sjsg static struct audio *dcn32_create_audio(
10981bb76ff1Sjsg 		struct dc_context *ctx, unsigned int inst)
10991bb76ff1Sjsg {
11001bb76ff1Sjsg 
11011bb76ff1Sjsg #undef REG_STRUCT
11021bb76ff1Sjsg #define REG_STRUCT audio_regs
11031bb76ff1Sjsg 	audio_regs_init(0),
11041bb76ff1Sjsg 	audio_regs_init(1),
11051bb76ff1Sjsg 	audio_regs_init(2),
11061bb76ff1Sjsg 	audio_regs_init(3),
11071bb76ff1Sjsg 	audio_regs_init(4);
11081bb76ff1Sjsg 
11091bb76ff1Sjsg 	return dce_audio_create(ctx, inst,
11101bb76ff1Sjsg 			&audio_regs[inst], &audio_shift, &audio_mask);
11111bb76ff1Sjsg }
11121bb76ff1Sjsg 
11131bb76ff1Sjsg static struct vpg *dcn32_vpg_create(
11141bb76ff1Sjsg 	struct dc_context *ctx,
11151bb76ff1Sjsg 	uint32_t inst)
11161bb76ff1Sjsg {
11171bb76ff1Sjsg 	struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL);
11181bb76ff1Sjsg 
11191bb76ff1Sjsg 	if (!vpg3)
11201bb76ff1Sjsg 		return NULL;
11211bb76ff1Sjsg 
11221bb76ff1Sjsg #undef REG_STRUCT
11231bb76ff1Sjsg #define REG_STRUCT vpg_regs
11241bb76ff1Sjsg 	vpg_regs_init(0),
11251bb76ff1Sjsg 	vpg_regs_init(1),
11261bb76ff1Sjsg 	vpg_regs_init(2),
11271bb76ff1Sjsg 	vpg_regs_init(3),
11281bb76ff1Sjsg 	vpg_regs_init(4),
11291bb76ff1Sjsg 	vpg_regs_init(5),
11301bb76ff1Sjsg 	vpg_regs_init(6),
11311bb76ff1Sjsg 	vpg_regs_init(7),
11321bb76ff1Sjsg 	vpg_regs_init(8),
11331bb76ff1Sjsg 	vpg_regs_init(9);
11341bb76ff1Sjsg 
11351bb76ff1Sjsg 	vpg3_construct(vpg3, ctx, inst,
11361bb76ff1Sjsg 			&vpg_regs[inst],
11371bb76ff1Sjsg 			&vpg_shift,
11381bb76ff1Sjsg 			&vpg_mask);
11391bb76ff1Sjsg 
11401bb76ff1Sjsg 	return &vpg3->base;
11411bb76ff1Sjsg }
11421bb76ff1Sjsg 
11431bb76ff1Sjsg static struct afmt *dcn32_afmt_create(
11441bb76ff1Sjsg 	struct dc_context *ctx,
11451bb76ff1Sjsg 	uint32_t inst)
11461bb76ff1Sjsg {
11471bb76ff1Sjsg 	struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL);
11481bb76ff1Sjsg 
11491bb76ff1Sjsg 	if (!afmt3)
11501bb76ff1Sjsg 		return NULL;
11511bb76ff1Sjsg 
11521bb76ff1Sjsg #undef REG_STRUCT
11531bb76ff1Sjsg #define REG_STRUCT afmt_regs
11541bb76ff1Sjsg 	afmt_regs_init(0),
11551bb76ff1Sjsg 	afmt_regs_init(1),
11561bb76ff1Sjsg 	afmt_regs_init(2),
11571bb76ff1Sjsg 	afmt_regs_init(3),
11581bb76ff1Sjsg 	afmt_regs_init(4),
11591bb76ff1Sjsg 	afmt_regs_init(5);
11601bb76ff1Sjsg 
11611bb76ff1Sjsg 	afmt3_construct(afmt3, ctx, inst,
11621bb76ff1Sjsg 			&afmt_regs[inst],
11631bb76ff1Sjsg 			&afmt_shift,
11641bb76ff1Sjsg 			&afmt_mask);
11651bb76ff1Sjsg 
11661bb76ff1Sjsg 	return &afmt3->base;
11671bb76ff1Sjsg }
11681bb76ff1Sjsg 
11691bb76ff1Sjsg static struct apg *dcn31_apg_create(
11701bb76ff1Sjsg 	struct dc_context *ctx,
11711bb76ff1Sjsg 	uint32_t inst)
11721bb76ff1Sjsg {
11731bb76ff1Sjsg 	struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL);
11741bb76ff1Sjsg 
11751bb76ff1Sjsg 	if (!apg31)
11761bb76ff1Sjsg 		return NULL;
11771bb76ff1Sjsg 
11781bb76ff1Sjsg #undef REG_STRUCT
11791bb76ff1Sjsg #define REG_STRUCT apg_regs
11801bb76ff1Sjsg 	apg_regs_init(0),
11811bb76ff1Sjsg 	apg_regs_init(1),
11821bb76ff1Sjsg 	apg_regs_init(2),
11831bb76ff1Sjsg 	apg_regs_init(3);
11841bb76ff1Sjsg 
11851bb76ff1Sjsg 	apg31_construct(apg31, ctx, inst,
11861bb76ff1Sjsg 			&apg_regs[inst],
11871bb76ff1Sjsg 			&apg_shift,
11881bb76ff1Sjsg 			&apg_mask);
11891bb76ff1Sjsg 
11901bb76ff1Sjsg 	return &apg31->base;
11911bb76ff1Sjsg }
11921bb76ff1Sjsg 
11931bb76ff1Sjsg static struct stream_encoder *dcn32_stream_encoder_create(
11941bb76ff1Sjsg 	enum engine_id eng_id,
11951bb76ff1Sjsg 	struct dc_context *ctx)
11961bb76ff1Sjsg {
11971bb76ff1Sjsg 	struct dcn10_stream_encoder *enc1;
11981bb76ff1Sjsg 	struct vpg *vpg;
11991bb76ff1Sjsg 	struct afmt *afmt;
12001bb76ff1Sjsg 	int vpg_inst;
12011bb76ff1Sjsg 	int afmt_inst;
12021bb76ff1Sjsg 
12031bb76ff1Sjsg 	/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
12041bb76ff1Sjsg 	if (eng_id <= ENGINE_ID_DIGF) {
12051bb76ff1Sjsg 		vpg_inst = eng_id;
12061bb76ff1Sjsg 		afmt_inst = eng_id;
12071bb76ff1Sjsg 	} else
12081bb76ff1Sjsg 		return NULL;
12091bb76ff1Sjsg 
12101bb76ff1Sjsg 	enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
12111bb76ff1Sjsg 	vpg = dcn32_vpg_create(ctx, vpg_inst);
12121bb76ff1Sjsg 	afmt = dcn32_afmt_create(ctx, afmt_inst);
12131bb76ff1Sjsg 
12141bb76ff1Sjsg 	if (!enc1 || !vpg || !afmt) {
12151bb76ff1Sjsg 		kfree(enc1);
12161bb76ff1Sjsg 		kfree(vpg);
12171bb76ff1Sjsg 		kfree(afmt);
12181bb76ff1Sjsg 		return NULL;
12191bb76ff1Sjsg 	}
12201bb76ff1Sjsg 
12211bb76ff1Sjsg #undef REG_STRUCT
12221bb76ff1Sjsg #define REG_STRUCT stream_enc_regs
12231bb76ff1Sjsg 	stream_enc_regs_init(0),
12241bb76ff1Sjsg 	stream_enc_regs_init(1),
12251bb76ff1Sjsg 	stream_enc_regs_init(2),
12261bb76ff1Sjsg 	stream_enc_regs_init(3),
12271bb76ff1Sjsg 	stream_enc_regs_init(4);
12281bb76ff1Sjsg 
12291bb76ff1Sjsg 	dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,
12301bb76ff1Sjsg 					eng_id, vpg, afmt,
12311bb76ff1Sjsg 					&stream_enc_regs[eng_id],
12321bb76ff1Sjsg 					&se_shift, &se_mask);
12331bb76ff1Sjsg 
12341bb76ff1Sjsg 	return &enc1->base;
12351bb76ff1Sjsg }
12361bb76ff1Sjsg 
12371bb76ff1Sjsg static struct hpo_dp_stream_encoder *dcn32_hpo_dp_stream_encoder_create(
12381bb76ff1Sjsg 	enum engine_id eng_id,
12391bb76ff1Sjsg 	struct dc_context *ctx)
12401bb76ff1Sjsg {
12411bb76ff1Sjsg 	struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31;
12421bb76ff1Sjsg 	struct vpg *vpg;
12431bb76ff1Sjsg 	struct apg *apg;
12441bb76ff1Sjsg 	uint32_t hpo_dp_inst;
12451bb76ff1Sjsg 	uint32_t vpg_inst;
12461bb76ff1Sjsg 	uint32_t apg_inst;
12471bb76ff1Sjsg 
12481bb76ff1Sjsg 	ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3));
12491bb76ff1Sjsg 	hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0;
12501bb76ff1Sjsg 
12511bb76ff1Sjsg 	/* Mapping of VPG register blocks to HPO DP block instance:
12521bb76ff1Sjsg 	 * VPG[6] -> HPO_DP[0]
12531bb76ff1Sjsg 	 * VPG[7] -> HPO_DP[1]
12541bb76ff1Sjsg 	 * VPG[8] -> HPO_DP[2]
12551bb76ff1Sjsg 	 * VPG[9] -> HPO_DP[3]
12561bb76ff1Sjsg 	 */
12571bb76ff1Sjsg 	vpg_inst = hpo_dp_inst + 6;
12581bb76ff1Sjsg 
12591bb76ff1Sjsg 	/* Mapping of APG register blocks to HPO DP block instance:
12601bb76ff1Sjsg 	 * APG[0] -> HPO_DP[0]
12611bb76ff1Sjsg 	 * APG[1] -> HPO_DP[1]
12621bb76ff1Sjsg 	 * APG[2] -> HPO_DP[2]
12631bb76ff1Sjsg 	 * APG[3] -> HPO_DP[3]
12641bb76ff1Sjsg 	 */
12651bb76ff1Sjsg 	apg_inst = hpo_dp_inst;
12661bb76ff1Sjsg 
12671bb76ff1Sjsg 	/* allocate HPO stream encoder and create VPG sub-block */
12681bb76ff1Sjsg 	hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL);
12691bb76ff1Sjsg 	vpg = dcn32_vpg_create(ctx, vpg_inst);
12701bb76ff1Sjsg 	apg = dcn31_apg_create(ctx, apg_inst);
12711bb76ff1Sjsg 
12721bb76ff1Sjsg 	if (!hpo_dp_enc31 || !vpg || !apg) {
12731bb76ff1Sjsg 		kfree(hpo_dp_enc31);
12741bb76ff1Sjsg 		kfree(vpg);
12751bb76ff1Sjsg 		kfree(apg);
12761bb76ff1Sjsg 		return NULL;
12771bb76ff1Sjsg 	}
12781bb76ff1Sjsg 
12791bb76ff1Sjsg #undef REG_STRUCT
12801bb76ff1Sjsg #define REG_STRUCT hpo_dp_stream_enc_regs
12811bb76ff1Sjsg 	hpo_dp_stream_encoder_reg_init(0),
12821bb76ff1Sjsg 	hpo_dp_stream_encoder_reg_init(1),
12831bb76ff1Sjsg 	hpo_dp_stream_encoder_reg_init(2),
12841bb76ff1Sjsg 	hpo_dp_stream_encoder_reg_init(3);
12851bb76ff1Sjsg 
12861bb76ff1Sjsg 	dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios,
12871bb76ff1Sjsg 					hpo_dp_inst, eng_id, vpg, apg,
12881bb76ff1Sjsg 					&hpo_dp_stream_enc_regs[hpo_dp_inst],
12891bb76ff1Sjsg 					&hpo_dp_se_shift, &hpo_dp_se_mask);
12901bb76ff1Sjsg 
12911bb76ff1Sjsg 	return &hpo_dp_enc31->base;
12921bb76ff1Sjsg }
12931bb76ff1Sjsg 
12941bb76ff1Sjsg static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create(
12951bb76ff1Sjsg 	uint8_t inst,
12961bb76ff1Sjsg 	struct dc_context *ctx)
12971bb76ff1Sjsg {
12981bb76ff1Sjsg 	struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31;
12991bb76ff1Sjsg 
13001bb76ff1Sjsg 	/* allocate HPO link encoder */
13011bb76ff1Sjsg 	hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
1302*4b0e85adSjsg 	if (!hpo_dp_enc31)
1303*4b0e85adSjsg 		return NULL; /* out of memory */
13041bb76ff1Sjsg 
13051bb76ff1Sjsg #undef REG_STRUCT
13061bb76ff1Sjsg #define REG_STRUCT hpo_dp_link_enc_regs
13071bb76ff1Sjsg 	hpo_dp_link_encoder_reg_init(0),
13081bb76ff1Sjsg 	hpo_dp_link_encoder_reg_init(1);
13091bb76ff1Sjsg 
13101bb76ff1Sjsg 	hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst,
13111bb76ff1Sjsg 					&hpo_dp_link_enc_regs[inst],
13121bb76ff1Sjsg 					&hpo_dp_le_shift, &hpo_dp_le_mask);
13131bb76ff1Sjsg 
13141bb76ff1Sjsg 	return &hpo_dp_enc31->base;
13151bb76ff1Sjsg }
13161bb76ff1Sjsg 
13171bb76ff1Sjsg static struct dce_hwseq *dcn32_hwseq_create(
13181bb76ff1Sjsg 	struct dc_context *ctx)
13191bb76ff1Sjsg {
13201bb76ff1Sjsg 	struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
13211bb76ff1Sjsg 
13221bb76ff1Sjsg #undef REG_STRUCT
13231bb76ff1Sjsg #define REG_STRUCT hwseq_reg
13241bb76ff1Sjsg 	hwseq_reg_init();
13251bb76ff1Sjsg 
13261bb76ff1Sjsg 	if (hws) {
13271bb76ff1Sjsg 		hws->ctx = ctx;
13281bb76ff1Sjsg 		hws->regs = &hwseq_reg;
13291bb76ff1Sjsg 		hws->shifts = &hwseq_shift;
13301bb76ff1Sjsg 		hws->masks = &hwseq_mask;
13311bb76ff1Sjsg 	}
13321bb76ff1Sjsg 	return hws;
13331bb76ff1Sjsg }
13341bb76ff1Sjsg static const struct resource_create_funcs res_create_funcs = {
13351bb76ff1Sjsg 	.read_dce_straps = read_dce_straps,
13361bb76ff1Sjsg 	.create_audio = dcn32_create_audio,
13371bb76ff1Sjsg 	.create_stream_encoder = dcn32_stream_encoder_create,
13381bb76ff1Sjsg 	.create_hpo_dp_stream_encoder = dcn32_hpo_dp_stream_encoder_create,
13391bb76ff1Sjsg 	.create_hpo_dp_link_encoder = dcn32_hpo_dp_link_encoder_create,
13401bb76ff1Sjsg 	.create_hwseq = dcn32_hwseq_create,
13411bb76ff1Sjsg };
13421bb76ff1Sjsg 
13431bb76ff1Sjsg static void dcn32_resource_destruct(struct dcn32_resource_pool *pool)
13441bb76ff1Sjsg {
13451bb76ff1Sjsg 	unsigned int i;
13461bb76ff1Sjsg 
13471bb76ff1Sjsg 	for (i = 0; i < pool->base.stream_enc_count; i++) {
13481bb76ff1Sjsg 		if (pool->base.stream_enc[i] != NULL) {
13491bb76ff1Sjsg 			if (pool->base.stream_enc[i]->vpg != NULL) {
13501bb76ff1Sjsg 				kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg));
13511bb76ff1Sjsg 				pool->base.stream_enc[i]->vpg = NULL;
13521bb76ff1Sjsg 			}
13531bb76ff1Sjsg 			if (pool->base.stream_enc[i]->afmt != NULL) {
13541bb76ff1Sjsg 				kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt));
13551bb76ff1Sjsg 				pool->base.stream_enc[i]->afmt = NULL;
13561bb76ff1Sjsg 			}
13571bb76ff1Sjsg 			kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));
13581bb76ff1Sjsg 			pool->base.stream_enc[i] = NULL;
13591bb76ff1Sjsg 		}
13601bb76ff1Sjsg 	}
13611bb76ff1Sjsg 
13621bb76ff1Sjsg 	for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) {
13631bb76ff1Sjsg 		if (pool->base.hpo_dp_stream_enc[i] != NULL) {
13641bb76ff1Sjsg 			if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) {
13651bb76ff1Sjsg 				kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg));
13661bb76ff1Sjsg 				pool->base.hpo_dp_stream_enc[i]->vpg = NULL;
13671bb76ff1Sjsg 			}
13681bb76ff1Sjsg 			if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) {
13691bb76ff1Sjsg 				kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg));
13701bb76ff1Sjsg 				pool->base.hpo_dp_stream_enc[i]->apg = NULL;
13711bb76ff1Sjsg 			}
13721bb76ff1Sjsg 			kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i]));
13731bb76ff1Sjsg 			pool->base.hpo_dp_stream_enc[i] = NULL;
13741bb76ff1Sjsg 		}
13751bb76ff1Sjsg 	}
13761bb76ff1Sjsg 
13771bb76ff1Sjsg 	for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) {
13781bb76ff1Sjsg 		if (pool->base.hpo_dp_link_enc[i] != NULL) {
13791bb76ff1Sjsg 			kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i]));
13801bb76ff1Sjsg 			pool->base.hpo_dp_link_enc[i] = NULL;
13811bb76ff1Sjsg 		}
13821bb76ff1Sjsg 	}
13831bb76ff1Sjsg 
13841bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
13851bb76ff1Sjsg 		if (pool->base.dscs[i] != NULL)
13861bb76ff1Sjsg 			dcn20_dsc_destroy(&pool->base.dscs[i]);
13871bb76ff1Sjsg 	}
13881bb76ff1Sjsg 
13891bb76ff1Sjsg 	if (pool->base.mpc != NULL) {
13901bb76ff1Sjsg 		kfree(TO_DCN20_MPC(pool->base.mpc));
13911bb76ff1Sjsg 		pool->base.mpc = NULL;
13921bb76ff1Sjsg 	}
13931bb76ff1Sjsg 	if (pool->base.hubbub != NULL) {
13941bb76ff1Sjsg 		kfree(TO_DCN20_HUBBUB(pool->base.hubbub));
13951bb76ff1Sjsg 		pool->base.hubbub = NULL;
13961bb76ff1Sjsg 	}
13971bb76ff1Sjsg 	for (i = 0; i < pool->base.pipe_count; i++) {
13981bb76ff1Sjsg 		if (pool->base.dpps[i] != NULL)
13991bb76ff1Sjsg 			dcn32_dpp_destroy(&pool->base.dpps[i]);
14001bb76ff1Sjsg 
14011bb76ff1Sjsg 		if (pool->base.ipps[i] != NULL)
14021bb76ff1Sjsg 			pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);
14031bb76ff1Sjsg 
14041bb76ff1Sjsg 		if (pool->base.hubps[i] != NULL) {
14051bb76ff1Sjsg 			kfree(TO_DCN20_HUBP(pool->base.hubps[i]));
14061bb76ff1Sjsg 			pool->base.hubps[i] = NULL;
14071bb76ff1Sjsg 		}
14081bb76ff1Sjsg 
14091bb76ff1Sjsg 		if (pool->base.irqs != NULL) {
14101bb76ff1Sjsg 			dal_irq_service_destroy(&pool->base.irqs);
14111bb76ff1Sjsg 		}
14121bb76ff1Sjsg 	}
14131bb76ff1Sjsg 
14141bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
14151bb76ff1Sjsg 		if (pool->base.engines[i] != NULL)
14161bb76ff1Sjsg 			dce110_engine_destroy(&pool->base.engines[i]);
14171bb76ff1Sjsg 		if (pool->base.hw_i2cs[i] != NULL) {
14181bb76ff1Sjsg 			kfree(pool->base.hw_i2cs[i]);
14191bb76ff1Sjsg 			pool->base.hw_i2cs[i] = NULL;
14201bb76ff1Sjsg 		}
14211bb76ff1Sjsg 		if (pool->base.sw_i2cs[i] != NULL) {
14221bb76ff1Sjsg 			kfree(pool->base.sw_i2cs[i]);
14231bb76ff1Sjsg 			pool->base.sw_i2cs[i] = NULL;
14241bb76ff1Sjsg 		}
14251bb76ff1Sjsg 	}
14261bb76ff1Sjsg 
14271bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_opp; i++) {
14281bb76ff1Sjsg 		if (pool->base.opps[i] != NULL)
14291bb76ff1Sjsg 			pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
14301bb76ff1Sjsg 	}
14311bb76ff1Sjsg 
14321bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
14331bb76ff1Sjsg 		if (pool->base.timing_generators[i] != NULL)	{
14341bb76ff1Sjsg 			kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
14351bb76ff1Sjsg 			pool->base.timing_generators[i] = NULL;
14361bb76ff1Sjsg 		}
14371bb76ff1Sjsg 	}
14381bb76ff1Sjsg 
14391bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_dwb; i++) {
14401bb76ff1Sjsg 		if (pool->base.dwbc[i] != NULL) {
14411bb76ff1Sjsg 			kfree(TO_DCN30_DWBC(pool->base.dwbc[i]));
14421bb76ff1Sjsg 			pool->base.dwbc[i] = NULL;
14431bb76ff1Sjsg 		}
14441bb76ff1Sjsg 		if (pool->base.mcif_wb[i] != NULL) {
14451bb76ff1Sjsg 			kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i]));
14461bb76ff1Sjsg 			pool->base.mcif_wb[i] = NULL;
14471bb76ff1Sjsg 		}
14481bb76ff1Sjsg 	}
14491bb76ff1Sjsg 
14501bb76ff1Sjsg 	for (i = 0; i < pool->base.audio_count; i++) {
14511bb76ff1Sjsg 		if (pool->base.audios[i])
14521bb76ff1Sjsg 			dce_aud_destroy(&pool->base.audios[i]);
14531bb76ff1Sjsg 	}
14541bb76ff1Sjsg 
14551bb76ff1Sjsg 	for (i = 0; i < pool->base.clk_src_count; i++) {
14561bb76ff1Sjsg 		if (pool->base.clock_sources[i] != NULL) {
14571bb76ff1Sjsg 			dcn20_clock_source_destroy(&pool->base.clock_sources[i]);
14581bb76ff1Sjsg 			pool->base.clock_sources[i] = NULL;
14591bb76ff1Sjsg 		}
14601bb76ff1Sjsg 	}
14611bb76ff1Sjsg 
14621bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) {
14631bb76ff1Sjsg 		if (pool->base.mpc_lut[i] != NULL) {
14641bb76ff1Sjsg 			dc_3dlut_func_release(pool->base.mpc_lut[i]);
14651bb76ff1Sjsg 			pool->base.mpc_lut[i] = NULL;
14661bb76ff1Sjsg 		}
14671bb76ff1Sjsg 		if (pool->base.mpc_shaper[i] != NULL) {
14681bb76ff1Sjsg 			dc_transfer_func_release(pool->base.mpc_shaper[i]);
14691bb76ff1Sjsg 			pool->base.mpc_shaper[i] = NULL;
14701bb76ff1Sjsg 		}
14711bb76ff1Sjsg 	}
14721bb76ff1Sjsg 
14731bb76ff1Sjsg 	if (pool->base.dp_clock_source != NULL) {
14741bb76ff1Sjsg 		dcn20_clock_source_destroy(&pool->base.dp_clock_source);
14751bb76ff1Sjsg 		pool->base.dp_clock_source = NULL;
14761bb76ff1Sjsg 	}
14771bb76ff1Sjsg 
14781bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
14791bb76ff1Sjsg 		if (pool->base.multiple_abms[i] != NULL)
14801bb76ff1Sjsg 			dce_abm_destroy(&pool->base.multiple_abms[i]);
14811bb76ff1Sjsg 	}
14821bb76ff1Sjsg 
14831bb76ff1Sjsg 	if (pool->base.psr != NULL)
14841bb76ff1Sjsg 		dmub_psr_destroy(&pool->base.psr);
14851bb76ff1Sjsg 
14861bb76ff1Sjsg 	if (pool->base.dccg != NULL)
14871bb76ff1Sjsg 		dcn_dccg_destroy(&pool->base.dccg);
14881bb76ff1Sjsg 
1489f005ef32Sjsg 	if (pool->base.oem_device != NULL) {
1490f005ef32Sjsg 		struct dc *dc = pool->base.oem_device->ctx->dc;
1491f005ef32Sjsg 
1492f005ef32Sjsg 		dc->link_srv->destroy_ddc_service(&pool->base.oem_device);
1493f005ef32Sjsg 	}
14941bb76ff1Sjsg }
14951bb76ff1Sjsg 
14961bb76ff1Sjsg 
14971bb76ff1Sjsg static bool dcn32_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
14981bb76ff1Sjsg {
14991bb76ff1Sjsg 	int i;
15001bb76ff1Sjsg 	uint32_t dwb_count = pool->res_cap->num_dwb;
15011bb76ff1Sjsg 
15021bb76ff1Sjsg 	for (i = 0; i < dwb_count; i++) {
15031bb76ff1Sjsg 		struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc),
15041bb76ff1Sjsg 						    GFP_KERNEL);
15051bb76ff1Sjsg 
15061bb76ff1Sjsg 		if (!dwbc30) {
15071bb76ff1Sjsg 			dm_error("DC: failed to create dwbc30!\n");
15081bb76ff1Sjsg 			return false;
15091bb76ff1Sjsg 		}
15101bb76ff1Sjsg 
15111bb76ff1Sjsg #undef REG_STRUCT
15121bb76ff1Sjsg #define REG_STRUCT dwbc30_regs
15131bb76ff1Sjsg 		dwbc_regs_dcn3_init(0);
15141bb76ff1Sjsg 
15151bb76ff1Sjsg 		dcn30_dwbc_construct(dwbc30, ctx,
15161bb76ff1Sjsg 				&dwbc30_regs[i],
15171bb76ff1Sjsg 				&dwbc30_shift,
15181bb76ff1Sjsg 				&dwbc30_mask,
15191bb76ff1Sjsg 				i);
15201bb76ff1Sjsg 
15211bb76ff1Sjsg 		pool->dwbc[i] = &dwbc30->base;
15221bb76ff1Sjsg 	}
15231bb76ff1Sjsg 	return true;
15241bb76ff1Sjsg }
15251bb76ff1Sjsg 
15261bb76ff1Sjsg static bool dcn32_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
15271bb76ff1Sjsg {
15281bb76ff1Sjsg 	int i;
15291bb76ff1Sjsg 	uint32_t dwb_count = pool->res_cap->num_dwb;
15301bb76ff1Sjsg 
15311bb76ff1Sjsg 	for (i = 0; i < dwb_count; i++) {
15321bb76ff1Sjsg 		struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub),
15331bb76ff1Sjsg 						    GFP_KERNEL);
15341bb76ff1Sjsg 
15351bb76ff1Sjsg 		if (!mcif_wb30) {
15361bb76ff1Sjsg 			dm_error("DC: failed to create mcif_wb30!\n");
15371bb76ff1Sjsg 			return false;
15381bb76ff1Sjsg 		}
15391bb76ff1Sjsg 
15401bb76ff1Sjsg #undef REG_STRUCT
15411bb76ff1Sjsg #define REG_STRUCT mcif_wb30_regs
15421bb76ff1Sjsg 		mcif_wb_regs_dcn3_init(0);
15431bb76ff1Sjsg 
15441bb76ff1Sjsg 		dcn32_mmhubbub_construct(mcif_wb30, ctx,
15451bb76ff1Sjsg 				&mcif_wb30_regs[i],
15461bb76ff1Sjsg 				&mcif_wb30_shift,
15471bb76ff1Sjsg 				&mcif_wb30_mask,
15481bb76ff1Sjsg 				i);
15491bb76ff1Sjsg 
15501bb76ff1Sjsg 		pool->mcif_wb[i] = &mcif_wb30->base;
15511bb76ff1Sjsg 	}
15521bb76ff1Sjsg 	return true;
15531bb76ff1Sjsg }
15541bb76ff1Sjsg 
15551bb76ff1Sjsg static struct display_stream_compressor *dcn32_dsc_create(
15561bb76ff1Sjsg 	struct dc_context *ctx, uint32_t inst)
15571bb76ff1Sjsg {
15581bb76ff1Sjsg 	struct dcn20_dsc *dsc =
15591bb76ff1Sjsg 		kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL);
15601bb76ff1Sjsg 
15611bb76ff1Sjsg 	if (!dsc) {
15621bb76ff1Sjsg 		BREAK_TO_DEBUGGER();
15631bb76ff1Sjsg 		return NULL;
15641bb76ff1Sjsg 	}
15651bb76ff1Sjsg 
15661bb76ff1Sjsg #undef REG_STRUCT
15671bb76ff1Sjsg #define REG_STRUCT dsc_regs
15681bb76ff1Sjsg 	dsc_regsDCN20_init(0),
15691bb76ff1Sjsg 	dsc_regsDCN20_init(1),
15701bb76ff1Sjsg 	dsc_regsDCN20_init(2),
15711bb76ff1Sjsg 	dsc_regsDCN20_init(3);
15721bb76ff1Sjsg 
15731bb76ff1Sjsg 	dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
15741bb76ff1Sjsg 
15751bb76ff1Sjsg 	dsc->max_image_width = 6016;
15761bb76ff1Sjsg 
15771bb76ff1Sjsg 	return &dsc->base;
15781bb76ff1Sjsg }
15791bb76ff1Sjsg 
15801bb76ff1Sjsg static void dcn32_destroy_resource_pool(struct resource_pool **pool)
15811bb76ff1Sjsg {
15821bb76ff1Sjsg 	struct dcn32_resource_pool *dcn32_pool = TO_DCN32_RES_POOL(*pool);
15831bb76ff1Sjsg 
15841bb76ff1Sjsg 	dcn32_resource_destruct(dcn32_pool);
15851bb76ff1Sjsg 	kfree(dcn32_pool);
15861bb76ff1Sjsg 	*pool = NULL;
15871bb76ff1Sjsg }
15881bb76ff1Sjsg 
15891bb76ff1Sjsg bool dcn32_acquire_post_bldn_3dlut(
15901bb76ff1Sjsg 		struct resource_context *res_ctx,
15911bb76ff1Sjsg 		const struct resource_pool *pool,
15921bb76ff1Sjsg 		int mpcc_id,
15931bb76ff1Sjsg 		struct dc_3dlut **lut,
15941bb76ff1Sjsg 		struct dc_transfer_func **shaper)
15951bb76ff1Sjsg {
15961bb76ff1Sjsg 	bool ret = false;
15971bb76ff1Sjsg 
15981bb76ff1Sjsg 	ASSERT(*lut == NULL && *shaper == NULL);
15991bb76ff1Sjsg 	*lut = NULL;
16001bb76ff1Sjsg 	*shaper = NULL;
16011bb76ff1Sjsg 
16021bb76ff1Sjsg 	if (!res_ctx->is_mpc_3dlut_acquired[mpcc_id]) {
16031bb76ff1Sjsg 		*lut = pool->mpc_lut[mpcc_id];
16041bb76ff1Sjsg 		*shaper = pool->mpc_shaper[mpcc_id];
16051bb76ff1Sjsg 		res_ctx->is_mpc_3dlut_acquired[mpcc_id] = true;
16061bb76ff1Sjsg 		ret = true;
16071bb76ff1Sjsg 	}
16081bb76ff1Sjsg 	return ret;
16091bb76ff1Sjsg }
16101bb76ff1Sjsg 
16111bb76ff1Sjsg bool dcn32_release_post_bldn_3dlut(
16121bb76ff1Sjsg 		struct resource_context *res_ctx,
16131bb76ff1Sjsg 		const struct resource_pool *pool,
16141bb76ff1Sjsg 		struct dc_3dlut **lut,
16151bb76ff1Sjsg 		struct dc_transfer_func **shaper)
16161bb76ff1Sjsg {
16171bb76ff1Sjsg 	int i;
16181bb76ff1Sjsg 	bool ret = false;
16191bb76ff1Sjsg 
16201bb76ff1Sjsg 	for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) {
16211bb76ff1Sjsg 		if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) {
16221bb76ff1Sjsg 			res_ctx->is_mpc_3dlut_acquired[i] = false;
16231bb76ff1Sjsg 			pool->mpc_lut[i]->state.raw = 0;
16241bb76ff1Sjsg 			*lut = NULL;
16251bb76ff1Sjsg 			*shaper = NULL;
16261bb76ff1Sjsg 			ret = true;
16271bb76ff1Sjsg 			break;
16281bb76ff1Sjsg 		}
16291bb76ff1Sjsg 	}
16301bb76ff1Sjsg 	return ret;
16311bb76ff1Sjsg }
16321bb76ff1Sjsg 
16331bb76ff1Sjsg static void dcn32_enable_phantom_plane(struct dc *dc,
16341bb76ff1Sjsg 		struct dc_state *context,
16351bb76ff1Sjsg 		struct dc_stream_state *phantom_stream,
16361bb76ff1Sjsg 		unsigned int dc_pipe_idx)
16371bb76ff1Sjsg {
16381bb76ff1Sjsg 	struct dc_plane_state *phantom_plane = NULL;
16391bb76ff1Sjsg 	struct dc_plane_state *prev_phantom_plane = NULL;
16401bb76ff1Sjsg 	struct pipe_ctx *curr_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];
16411bb76ff1Sjsg 
16421bb76ff1Sjsg 	while (curr_pipe) {
16431bb76ff1Sjsg 		if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state)
16441bb76ff1Sjsg 			phantom_plane = prev_phantom_plane;
16451bb76ff1Sjsg 		else
16461bb76ff1Sjsg 			phantom_plane = dc_create_plane_state(dc);
16471bb76ff1Sjsg 
16481bb76ff1Sjsg 		memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address));
16491bb76ff1Sjsg 		memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality,
16501bb76ff1Sjsg 				sizeof(phantom_plane->scaling_quality));
16511bb76ff1Sjsg 		memcpy(&phantom_plane->src_rect, &curr_pipe->plane_state->src_rect, sizeof(phantom_plane->src_rect));
16521bb76ff1Sjsg 		memcpy(&phantom_plane->dst_rect, &curr_pipe->plane_state->dst_rect, sizeof(phantom_plane->dst_rect));
16531bb76ff1Sjsg 		memcpy(&phantom_plane->clip_rect, &curr_pipe->plane_state->clip_rect, sizeof(phantom_plane->clip_rect));
16541bb76ff1Sjsg 		memcpy(&phantom_plane->plane_size, &curr_pipe->plane_state->plane_size,
16551bb76ff1Sjsg 				sizeof(phantom_plane->plane_size));
16561bb76ff1Sjsg 		memcpy(&phantom_plane->tiling_info, &curr_pipe->plane_state->tiling_info,
16571bb76ff1Sjsg 				sizeof(phantom_plane->tiling_info));
16581bb76ff1Sjsg 		memcpy(&phantom_plane->dcc, &curr_pipe->plane_state->dcc, sizeof(phantom_plane->dcc));
16591bb76ff1Sjsg 		phantom_plane->format = curr_pipe->plane_state->format;
16601bb76ff1Sjsg 		phantom_plane->rotation = curr_pipe->plane_state->rotation;
16611bb76ff1Sjsg 		phantom_plane->visible = curr_pipe->plane_state->visible;
16621bb76ff1Sjsg 
16631bb76ff1Sjsg 		/* Shadow pipe has small viewport. */
16641bb76ff1Sjsg 		phantom_plane->clip_rect.y = 0;
1665f005ef32Sjsg 		phantom_plane->clip_rect.height = phantom_stream->src.height;
16661bb76ff1Sjsg 
16671bb76ff1Sjsg 		phantom_plane->is_phantom = true;
16681bb76ff1Sjsg 
16691bb76ff1Sjsg 		dc_add_plane_to_context(dc, phantom_stream, phantom_plane, context);
16701bb76ff1Sjsg 
16711bb76ff1Sjsg 		curr_pipe = curr_pipe->bottom_pipe;
16721bb76ff1Sjsg 		prev_phantom_plane = phantom_plane;
16731bb76ff1Sjsg 	}
16741bb76ff1Sjsg }
16751bb76ff1Sjsg 
16761bb76ff1Sjsg static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc,
16771bb76ff1Sjsg 		struct dc_state *context,
16781bb76ff1Sjsg 		display_e2e_pipe_params_st *pipes,
16791bb76ff1Sjsg 		unsigned int pipe_cnt,
16801bb76ff1Sjsg 		unsigned int dc_pipe_idx)
16811bb76ff1Sjsg {
16821bb76ff1Sjsg 	struct dc_stream_state *phantom_stream = NULL;
16831bb76ff1Sjsg 	struct pipe_ctx *ref_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];
16841bb76ff1Sjsg 
16851bb76ff1Sjsg 	phantom_stream = dc_create_stream_for_sink(ref_pipe->stream->sink);
16861bb76ff1Sjsg 	phantom_stream->signal = SIGNAL_TYPE_VIRTUAL;
16871bb76ff1Sjsg 	phantom_stream->dpms_off = true;
16881bb76ff1Sjsg 	phantom_stream->mall_stream_config.type = SUBVP_PHANTOM;
16891bb76ff1Sjsg 	phantom_stream->mall_stream_config.paired_stream = ref_pipe->stream;
16901bb76ff1Sjsg 	ref_pipe->stream->mall_stream_config.type = SUBVP_MAIN;
16911bb76ff1Sjsg 	ref_pipe->stream->mall_stream_config.paired_stream = phantom_stream;
16921bb76ff1Sjsg 
16931bb76ff1Sjsg 	/* stream has limited viewport and small timing */
16941bb76ff1Sjsg 	memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing));
16951bb76ff1Sjsg 	memcpy(&phantom_stream->src, &ref_pipe->stream->src, sizeof(phantom_stream->src));
16961bb76ff1Sjsg 	memcpy(&phantom_stream->dst, &ref_pipe->stream->dst, sizeof(phantom_stream->dst));
16971bb76ff1Sjsg 	DC_FP_START();
16981bb76ff1Sjsg 	dcn32_set_phantom_stream_timing(dc, context, ref_pipe, phantom_stream, pipes, pipe_cnt, dc_pipe_idx);
16991bb76ff1Sjsg 	DC_FP_END();
17001bb76ff1Sjsg 
17011bb76ff1Sjsg 	dc_add_stream_to_ctx(dc, context, phantom_stream);
17021bb76ff1Sjsg 	return phantom_stream;
17031bb76ff1Sjsg }
17041bb76ff1Sjsg 
170561d5f3a6Sjsg void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context)
170661d5f3a6Sjsg {
170761d5f3a6Sjsg 	int i;
170861d5f3a6Sjsg 	struct dc_plane_state *phantom_plane = NULL;
170961d5f3a6Sjsg 	struct dc_stream_state *phantom_stream = NULL;
171061d5f3a6Sjsg 
171161d5f3a6Sjsg 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
171261d5f3a6Sjsg 		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
171361d5f3a6Sjsg 
1714f005ef32Sjsg 		if (resource_is_pipe_type(pipe, OTG_MASTER) &&
1715f005ef32Sjsg 				resource_is_pipe_type(pipe, DPP_PIPE) &&
171661d5f3a6Sjsg 				pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
171761d5f3a6Sjsg 			phantom_plane = pipe->plane_state;
171861d5f3a6Sjsg 			phantom_stream = pipe->stream;
171961d5f3a6Sjsg 
172061d5f3a6Sjsg 			dc_plane_state_retain(phantom_plane);
172161d5f3a6Sjsg 			dc_stream_retain(phantom_stream);
172261d5f3a6Sjsg 		}
172361d5f3a6Sjsg 	}
172461d5f3a6Sjsg }
172561d5f3a6Sjsg 
17261bb76ff1Sjsg // return true if removed piped from ctx, false otherwise
1727f005ef32Sjsg bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context, bool fast_update)
17281bb76ff1Sjsg {
17291bb76ff1Sjsg 	int i;
17301bb76ff1Sjsg 	bool removed_pipe = false;
17311bb76ff1Sjsg 	struct dc_plane_state *phantom_plane = NULL;
17321bb76ff1Sjsg 	struct dc_stream_state *phantom_stream = NULL;
17331bb76ff1Sjsg 
17341bb76ff1Sjsg 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
17351bb76ff1Sjsg 		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
17361bb76ff1Sjsg 		// build scaling params for phantom pipes
17371bb76ff1Sjsg 		if (pipe->plane_state && pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
17381bb76ff1Sjsg 			phantom_plane = pipe->plane_state;
17391bb76ff1Sjsg 			phantom_stream = pipe->stream;
17401bb76ff1Sjsg 
17411bb76ff1Sjsg 			dc_rem_all_planes_for_stream(dc, pipe->stream, context);
17421bb76ff1Sjsg 			dc_remove_stream_from_ctx(dc, context, pipe->stream);
17431bb76ff1Sjsg 
17441bb76ff1Sjsg 			/* Ref count is incremented on allocation and also when added to the context.
17451bb76ff1Sjsg 			 * Therefore we must call release for the the phantom plane and stream once
17461bb76ff1Sjsg 			 * they are removed from the ctx to finally decrement the refcount to 0 to free.
17471bb76ff1Sjsg 			 */
17481bb76ff1Sjsg 			dc_plane_state_release(phantom_plane);
17491bb76ff1Sjsg 			dc_stream_release(phantom_stream);
17501bb76ff1Sjsg 
17511bb76ff1Sjsg 			removed_pipe = true;
17521bb76ff1Sjsg 		}
17531bb76ff1Sjsg 
1754f005ef32Sjsg 		/* For non-full updates, a shallow copy of the current state
1755f005ef32Sjsg 		 * is created. In this case we don't want to erase the current
1756f005ef32Sjsg 		 * state (there can be 2 HIRQL threads, one in flip, and one in
1757f005ef32Sjsg 		 * checkMPO) that can cause a race condition.
1758f005ef32Sjsg 		 *
1759f005ef32Sjsg 		 * This is just a workaround, needs a proper fix.
1760f005ef32Sjsg 		 */
1761f005ef32Sjsg 		if (!fast_update) {
17621bb76ff1Sjsg 			// Clear all phantom stream info
17631bb76ff1Sjsg 			if (pipe->stream) {
17641bb76ff1Sjsg 				pipe->stream->mall_stream_config.type = SUBVP_NONE;
17651bb76ff1Sjsg 				pipe->stream->mall_stream_config.paired_stream = NULL;
17661bb76ff1Sjsg 			}
17671bb76ff1Sjsg 
17681bb76ff1Sjsg 			if (pipe->plane_state) {
17691bb76ff1Sjsg 				pipe->plane_state->is_phantom = false;
17701bb76ff1Sjsg 			}
17711bb76ff1Sjsg 		}
1772f005ef32Sjsg 	}
17731bb76ff1Sjsg 	return removed_pipe;
17741bb76ff1Sjsg }
17751bb76ff1Sjsg 
17761bb76ff1Sjsg /* TODO: Input to this function should indicate which pipe indexes (or streams)
17771bb76ff1Sjsg  * require a phantom pipe / stream
17781bb76ff1Sjsg  */
17791bb76ff1Sjsg void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context,
17801bb76ff1Sjsg 		display_e2e_pipe_params_st *pipes,
17811bb76ff1Sjsg 		unsigned int pipe_cnt,
17821bb76ff1Sjsg 		unsigned int index)
17831bb76ff1Sjsg {
17841bb76ff1Sjsg 	struct dc_stream_state *phantom_stream = NULL;
17851bb76ff1Sjsg 	unsigned int i;
17861bb76ff1Sjsg 
17871bb76ff1Sjsg 	// The index of the DC pipe passed into this function is guarenteed to
17881bb76ff1Sjsg 	// be a valid candidate for SubVP (i.e. has a plane, stream, doesn't
17891bb76ff1Sjsg 	// already have phantom pipe assigned, etc.) by previous checks.
17901bb76ff1Sjsg 	phantom_stream = dcn32_enable_phantom_stream(dc, context, pipes, pipe_cnt, index);
17918ca68bcaSjsg 	if (!phantom_stream)
17928ca68bcaSjsg 		return;
17938ca68bcaSjsg 
17941bb76ff1Sjsg 	dcn32_enable_phantom_plane(dc, context, phantom_stream, index);
17951bb76ff1Sjsg 
17961bb76ff1Sjsg 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
17971bb76ff1Sjsg 		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
17981bb76ff1Sjsg 
17991bb76ff1Sjsg 		// Build scaling params for phantom pipes which were newly added.
18001bb76ff1Sjsg 		// We determine which phantom pipes were added by comparing with
18011bb76ff1Sjsg 		// the phantom stream.
18021bb76ff1Sjsg 		if (pipe->plane_state && pipe->stream && pipe->stream == phantom_stream &&
18031bb76ff1Sjsg 				pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
18041bb76ff1Sjsg 			pipe->stream->use_dynamic_meta = false;
18051bb76ff1Sjsg 			pipe->plane_state->flip_immediate = false;
18061bb76ff1Sjsg 			if (!resource_build_scaling_params(pipe)) {
18071bb76ff1Sjsg 				// Log / remove phantom pipes since failed to build scaling params
18081bb76ff1Sjsg 			}
18091bb76ff1Sjsg 		}
18101bb76ff1Sjsg 	}
18111bb76ff1Sjsg }
18121bb76ff1Sjsg 
18131bb76ff1Sjsg bool dcn32_validate_bandwidth(struct dc *dc,
18141bb76ff1Sjsg 		struct dc_state *context,
18151bb76ff1Sjsg 		bool fast_validate)
18161bb76ff1Sjsg {
18171bb76ff1Sjsg 	bool out = false;
18181bb76ff1Sjsg 
18191bb76ff1Sjsg 	BW_VAL_TRACE_SETUP();
18201bb76ff1Sjsg 
18211bb76ff1Sjsg 	int vlevel = 0;
18221bb76ff1Sjsg 	int pipe_cnt = 0;
18231bb76ff1Sjsg 	display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
18241bb76ff1Sjsg 	struct mall_temp_config mall_temp_config;
18251bb76ff1Sjsg 
18261bb76ff1Sjsg 	/* To handle Freesync properly, setting FreeSync DML parameters
18271bb76ff1Sjsg 	 * to its default state for the first stage of validation
18281bb76ff1Sjsg 	 */
18291bb76ff1Sjsg 	context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
18301bb76ff1Sjsg 	context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true;
18311bb76ff1Sjsg 
18321bb76ff1Sjsg 	DC_LOGGER_INIT(dc->ctx->logger);
18331bb76ff1Sjsg 
18341bb76ff1Sjsg 	/* For fast validation, there are situations where a shallow copy of
18351bb76ff1Sjsg 	 * of the dc->current_state is created for the validation. In this case
18361bb76ff1Sjsg 	 * we want to save and restore the mall config because we always
18371bb76ff1Sjsg 	 * teardown subvp at the beginning of validation (and don't attempt
18381bb76ff1Sjsg 	 * to add it back if it's fast validation). If we don't restore the
18391bb76ff1Sjsg 	 * subvp config in cases of fast validation + shallow copy of the
18401bb76ff1Sjsg 	 * dc->current_state, the dc->current_state will have a partially
18411bb76ff1Sjsg 	 * removed subvp state when we did not intend to remove it.
18421bb76ff1Sjsg 	 */
18431bb76ff1Sjsg 	if (fast_validate) {
18441bb76ff1Sjsg 		memset(&mall_temp_config, 0, sizeof(mall_temp_config));
18451bb76ff1Sjsg 		dcn32_save_mall_state(dc, context, &mall_temp_config);
18461bb76ff1Sjsg 	}
18471bb76ff1Sjsg 
18481bb76ff1Sjsg 	BW_VAL_TRACE_COUNT();
18491bb76ff1Sjsg 
1850*4b0e85adSjsg 	if (!pipes)
1851*4b0e85adSjsg 		goto validate_fail;
1852*4b0e85adSjsg 
18531bb76ff1Sjsg 	DC_FP_START();
18541bb76ff1Sjsg 	out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);
18551bb76ff1Sjsg 	DC_FP_END();
18561bb76ff1Sjsg 
18571bb76ff1Sjsg 	if (fast_validate)
18581bb76ff1Sjsg 		dcn32_restore_mall_state(dc, context, &mall_temp_config);
18591bb76ff1Sjsg 
18601bb76ff1Sjsg 	if (pipe_cnt == 0)
18611bb76ff1Sjsg 		goto validate_out;
18621bb76ff1Sjsg 
18631bb76ff1Sjsg 	if (!out)
18641bb76ff1Sjsg 		goto validate_fail;
18651bb76ff1Sjsg 
18661bb76ff1Sjsg 	BW_VAL_TRACE_END_VOLTAGE_LEVEL();
18671bb76ff1Sjsg 
18681bb76ff1Sjsg 	if (fast_validate) {
18691bb76ff1Sjsg 		BW_VAL_TRACE_SKIP(fast);
18701bb76ff1Sjsg 		goto validate_out;
18711bb76ff1Sjsg 	}
18721bb76ff1Sjsg 
18731bb76ff1Sjsg 	dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
18741bb76ff1Sjsg 
1875f005ef32Sjsg 	dcn32_override_min_req_memclk(dc, context);
1876f005ef32Sjsg 
18771bb76ff1Sjsg 	BW_VAL_TRACE_END_WATERMARKS();
18781bb76ff1Sjsg 
18791bb76ff1Sjsg 	goto validate_out;
18801bb76ff1Sjsg 
18811bb76ff1Sjsg validate_fail:
18821bb76ff1Sjsg 	DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",
18831bb76ff1Sjsg 		dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]));
18841bb76ff1Sjsg 
18851bb76ff1Sjsg 	BW_VAL_TRACE_SKIP(fail);
18861bb76ff1Sjsg 	out = false;
18871bb76ff1Sjsg 
18881bb76ff1Sjsg validate_out:
18891bb76ff1Sjsg 	kfree(pipes);
18901bb76ff1Sjsg 
18911bb76ff1Sjsg 	BW_VAL_TRACE_FINISH();
18921bb76ff1Sjsg 
18931bb76ff1Sjsg 	return out;
18941bb76ff1Sjsg }
18951bb76ff1Sjsg 
18961bb76ff1Sjsg int dcn32_populate_dml_pipes_from_context(
18971bb76ff1Sjsg 	struct dc *dc, struct dc_state *context,
18981bb76ff1Sjsg 	display_e2e_pipe_params_st *pipes,
18991bb76ff1Sjsg 	bool fast_validate)
19001bb76ff1Sjsg {
19011bb76ff1Sjsg 	int i, pipe_cnt;
19021bb76ff1Sjsg 	struct resource_context *res_ctx = &context->res_ctx;
1903f005ef32Sjsg 	struct pipe_ctx *pipe = NULL;
19041bb76ff1Sjsg 	bool subvp_in_use = false;
19051bb76ff1Sjsg 	struct dc_crtc_timing *timing;
19068cc4793fSjsg 	bool vsr_odm_support = false;
19071bb76ff1Sjsg 
19081bb76ff1Sjsg 	dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
19091bb76ff1Sjsg 
19101bb76ff1Sjsg 	/* Determine whether we will apply ODM 2to1 policy:
19111bb76ff1Sjsg 	 * Applies to single display and where the number of planes is less than 3.
19121bb76ff1Sjsg 	 * For 3 plane case ( 2 MPO planes ), we will not set the policy for the MPO pipes.
19131bb76ff1Sjsg 	 *
19141bb76ff1Sjsg 	 * Apply pipe split policy first so we can predict the pipe split correctly
19151bb76ff1Sjsg 	 * (dcn32_predict_pipe_split).
19161bb76ff1Sjsg 	 */
19171bb76ff1Sjsg 	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
19181bb76ff1Sjsg 		if (!res_ctx->pipe_ctx[i].stream)
19191bb76ff1Sjsg 			continue;
19201bb76ff1Sjsg 		pipe = &res_ctx->pipe_ctx[i];
19211bb76ff1Sjsg 		timing = &pipe->stream->timing;
19221bb76ff1Sjsg 
19231bb76ff1Sjsg 		pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
19248cc4793fSjsg 		vsr_odm_support = (res_ctx->pipe_ctx[i].stream->src.width >= 5120 &&
19258cc4793fSjsg 				res_ctx->pipe_ctx[i].stream->src.width > res_ctx->pipe_ctx[i].stream->dst.width);
19261bb76ff1Sjsg 		if (context->stream_count == 1 &&
19271bb76ff1Sjsg 				context->stream_status[0].plane_count == 1 &&
19281bb76ff1Sjsg 				!dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&
19291bb76ff1Sjsg 				is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) &&
19301bb76ff1Sjsg 				pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ &&
19318cc4793fSjsg 				dc->debug.enable_single_display_2to1_odm_policy &&
19328cc4793fSjsg 				!vsr_odm_support) { //excluding 2to1 ODM combine on >= 5k vsr
19331bb76ff1Sjsg 			pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
19341bb76ff1Sjsg 		}
19351bb76ff1Sjsg 		pipe_cnt++;
19361bb76ff1Sjsg 	}
19371bb76ff1Sjsg 
19381bb76ff1Sjsg 	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
19391bb76ff1Sjsg 
19401bb76ff1Sjsg 		if (!res_ctx->pipe_ctx[i].stream)
19411bb76ff1Sjsg 			continue;
19421bb76ff1Sjsg 		pipe = &res_ctx->pipe_ctx[i];
19431bb76ff1Sjsg 		timing = &pipe->stream->timing;
19441bb76ff1Sjsg 
19451bb76ff1Sjsg 		pipes[pipe_cnt].pipe.src.gpuvm = true;
19463b9bf99bSjsg 		DC_FP_START();
19473b9bf99bSjsg 		dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt);
19483b9bf99bSjsg 		DC_FP_END();
19491bb76ff1Sjsg 		pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
19501bb76ff1Sjsg 		pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet
19511bb76ff1Sjsg 		pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
19521bb76ff1Sjsg 		pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19;
19531bb76ff1Sjsg 
1954f005ef32Sjsg 		/* Only populate DML input with subvp info for full updates.
1955f005ef32Sjsg 		 * This is just a workaround -- needs a proper fix.
1956f005ef32Sjsg 		 */
1957f005ef32Sjsg 		if (!fast_validate) {
19581bb76ff1Sjsg 			switch (pipe->stream->mall_stream_config.type) {
19591bb76ff1Sjsg 			case SUBVP_MAIN:
19601bb76ff1Sjsg 				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport;
19611bb76ff1Sjsg 				subvp_in_use = true;
19621bb76ff1Sjsg 				break;
19631bb76ff1Sjsg 			case SUBVP_PHANTOM:
19641bb76ff1Sjsg 				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_phantom_pipe;
19651bb76ff1Sjsg 				pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;
19661bb76ff1Sjsg 				// Disallow unbounded req for SubVP according to DCHUB programming guide
19671bb76ff1Sjsg 				pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
19681bb76ff1Sjsg 				break;
19691bb76ff1Sjsg 			case SUBVP_NONE:
19701bb76ff1Sjsg 				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_disable;
19711bb76ff1Sjsg 				pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;
19721bb76ff1Sjsg 				break;
19731bb76ff1Sjsg 			default:
19741bb76ff1Sjsg 				break;
19751bb76ff1Sjsg 			}
1976f005ef32Sjsg 		}
19771bb76ff1Sjsg 
19781bb76ff1Sjsg 		pipes[pipe_cnt].dout.dsc_input_bpc = 0;
19791bb76ff1Sjsg 		if (pipes[pipe_cnt].dout.dsc_enable) {
19801bb76ff1Sjsg 			switch (timing->display_color_depth) {
19811bb76ff1Sjsg 			case COLOR_DEPTH_888:
19821bb76ff1Sjsg 				pipes[pipe_cnt].dout.dsc_input_bpc = 8;
19831bb76ff1Sjsg 				break;
19841bb76ff1Sjsg 			case COLOR_DEPTH_101010:
19851bb76ff1Sjsg 				pipes[pipe_cnt].dout.dsc_input_bpc = 10;
19861bb76ff1Sjsg 				break;
19871bb76ff1Sjsg 			case COLOR_DEPTH_121212:
19881bb76ff1Sjsg 				pipes[pipe_cnt].dout.dsc_input_bpc = 12;
19891bb76ff1Sjsg 				break;
19901bb76ff1Sjsg 			default:
19911bb76ff1Sjsg 				ASSERT(0);
19921bb76ff1Sjsg 				break;
19931bb76ff1Sjsg 			}
19941bb76ff1Sjsg 		}
19951bb76ff1Sjsg 
19961bb76ff1Sjsg 		DC_FP_START();
1997f005ef32Sjsg 		dcn32_predict_pipe_split(context, &pipes[pipe_cnt]);
19981bb76ff1Sjsg 		DC_FP_END();
19991bb76ff1Sjsg 
20001bb76ff1Sjsg 		pipe_cnt++;
20011bb76ff1Sjsg 	}
20021bb76ff1Sjsg 
20031bb76ff1Sjsg 	/* For DET allocation, we don't want to use DML policy (not optimal for utilizing all
20041bb76ff1Sjsg 	 * the DET available for each pipe). Use the DET override input to maintain our driver
20051bb76ff1Sjsg 	 * policy.
20061bb76ff1Sjsg 	 */
20071bb76ff1Sjsg 	dcn32_set_det_allocations(dc, context, pipes);
20081bb76ff1Sjsg 
20091bb76ff1Sjsg 	// In general cases we want to keep the dram clock change requirement
20101bb76ff1Sjsg 	// (prefer configs that support MCLK switch). Only override to false
20111bb76ff1Sjsg 	// for SubVP
2012b4278f97Sjsg 	if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || subvp_in_use)
20131bb76ff1Sjsg 		context->bw_ctx.dml.soc.dram_clock_change_requirement_final = false;
20141bb76ff1Sjsg 	else
20151bb76ff1Sjsg 		context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true;
20161bb76ff1Sjsg 
20171bb76ff1Sjsg 	return pipe_cnt;
20181bb76ff1Sjsg }
20191bb76ff1Sjsg 
20201bb76ff1Sjsg static struct dc_cap_funcs cap_funcs = {
20211bb76ff1Sjsg 	.get_dcc_compression_cap = dcn20_get_dcc_compression_cap
20221bb76ff1Sjsg };
20231bb76ff1Sjsg 
20241bb76ff1Sjsg void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context,
20251bb76ff1Sjsg 				display_e2e_pipe_params_st *pipes,
20261bb76ff1Sjsg 				int pipe_cnt,
20271bb76ff1Sjsg 				int vlevel)
20281bb76ff1Sjsg {
20291bb76ff1Sjsg     DC_FP_START();
20301bb76ff1Sjsg     dcn32_calculate_wm_and_dlg_fpu(dc, context, pipes, pipe_cnt, vlevel);
20311bb76ff1Sjsg     DC_FP_END();
20321bb76ff1Sjsg }
20331bb76ff1Sjsg 
20341bb76ff1Sjsg static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
20351bb76ff1Sjsg {
20361bb76ff1Sjsg 	DC_FP_START();
20371bb76ff1Sjsg 	dcn32_update_bw_bounding_box_fpu(dc, bw_params);
20381bb76ff1Sjsg 	DC_FP_END();
20391bb76ff1Sjsg }
20401bb76ff1Sjsg 
20411bb76ff1Sjsg static struct resource_funcs dcn32_res_pool_funcs = {
20421bb76ff1Sjsg 	.destroy = dcn32_destroy_resource_pool,
20431bb76ff1Sjsg 	.link_enc_create = dcn32_link_encoder_create,
20441bb76ff1Sjsg 	.link_enc_create_minimal = NULL,
20451bb76ff1Sjsg 	.panel_cntl_create = dcn32_panel_cntl_create,
20461bb76ff1Sjsg 	.validate_bandwidth = dcn32_validate_bandwidth,
20471bb76ff1Sjsg 	.calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg,
20481bb76ff1Sjsg 	.populate_dml_pipes = dcn32_populate_dml_pipes_from_context,
2049f005ef32Sjsg 	.acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe,
20501bb76ff1Sjsg 	.add_stream_to_ctx = dcn30_add_stream_to_ctx,
20511bb76ff1Sjsg 	.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
20521bb76ff1Sjsg 	.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
20531bb76ff1Sjsg 	.populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,
20541bb76ff1Sjsg 	.set_mcif_arb_params = dcn30_set_mcif_arb_params,
20551bb76ff1Sjsg 	.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
20561bb76ff1Sjsg 	.acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut,
20571bb76ff1Sjsg 	.release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut,
20581bb76ff1Sjsg 	.update_bw_bounding_box = dcn32_update_bw_bounding_box,
20591bb76ff1Sjsg 	.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
20601bb76ff1Sjsg 	.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
20611bb76ff1Sjsg 	.add_phantom_pipes = dcn32_add_phantom_pipes,
20621bb76ff1Sjsg 	.remove_phantom_pipes = dcn32_remove_phantom_pipes,
206361d5f3a6Sjsg 	.retain_phantom_pipes = dcn32_retain_phantom_pipes,
2064f005ef32Sjsg 	.save_mall_state = dcn32_save_mall_state,
2065f005ef32Sjsg 	.restore_mall_state = dcn32_restore_mall_state,
20661bb76ff1Sjsg };
20671bb76ff1Sjsg 
2068a62fadd3Sjsg static uint32_t read_pipe_fuses(struct dc_context *ctx)
2069a62fadd3Sjsg {
2070a62fadd3Sjsg 	uint32_t value = REG_READ(CC_DC_PIPE_DIS);
2071a62fadd3Sjsg 	/* DCN32 support max 4 pipes */
2072a62fadd3Sjsg 	value = value & 0xf;
2073a62fadd3Sjsg 	return value;
2074a62fadd3Sjsg }
2075a62fadd3Sjsg 
20761bb76ff1Sjsg 
20771bb76ff1Sjsg static bool dcn32_resource_construct(
20781bb76ff1Sjsg 	uint8_t num_virtual_links,
20791bb76ff1Sjsg 	struct dc *dc,
20801bb76ff1Sjsg 	struct dcn32_resource_pool *pool)
20811bb76ff1Sjsg {
20821bb76ff1Sjsg 	int i, j;
20831bb76ff1Sjsg 	struct dc_context *ctx = dc->ctx;
20841bb76ff1Sjsg 	struct irq_service_init_data init_data;
20851bb76ff1Sjsg 	struct ddc_service_init_data ddc_init_data = {0};
20861bb76ff1Sjsg 	uint32_t pipe_fuses = 0;
20871bb76ff1Sjsg 	uint32_t num_pipes  = 4;
20881bb76ff1Sjsg 
20891bb76ff1Sjsg #undef REG_STRUCT
20901bb76ff1Sjsg #define REG_STRUCT bios_regs
20911bb76ff1Sjsg 	bios_regs_init();
20921bb76ff1Sjsg 
20931bb76ff1Sjsg #undef REG_STRUCT
20941bb76ff1Sjsg #define REG_STRUCT clk_src_regs
20951bb76ff1Sjsg 	clk_src_regs_init(0, A),
20961bb76ff1Sjsg 	clk_src_regs_init(1, B),
20971bb76ff1Sjsg 	clk_src_regs_init(2, C),
20981bb76ff1Sjsg 	clk_src_regs_init(3, D),
20991bb76ff1Sjsg 	clk_src_regs_init(4, E);
2100f005ef32Sjsg 
21011bb76ff1Sjsg #undef REG_STRUCT
21021bb76ff1Sjsg #define REG_STRUCT abm_regs
21031bb76ff1Sjsg 	abm_regs_init(0),
21041bb76ff1Sjsg 	abm_regs_init(1),
21051bb76ff1Sjsg 	abm_regs_init(2),
21061bb76ff1Sjsg 	abm_regs_init(3);
21071bb76ff1Sjsg 
21081bb76ff1Sjsg #undef REG_STRUCT
21091bb76ff1Sjsg #define REG_STRUCT dccg_regs
21101bb76ff1Sjsg 	dccg_regs_init();
21111bb76ff1Sjsg 
21121bb76ff1Sjsg 	DC_FP_START();
21131bb76ff1Sjsg 
21141bb76ff1Sjsg 	ctx->dc_bios->regs = &bios_regs;
21151bb76ff1Sjsg 
21161bb76ff1Sjsg 	pool->base.res_cap = &res_cap_dcn32;
21171bb76ff1Sjsg 	/* max number of pipes for ASIC before checking for pipe fuses */
21181bb76ff1Sjsg 	num_pipes  = pool->base.res_cap->num_timing_generator;
2119a62fadd3Sjsg 	pipe_fuses = read_pipe_fuses(ctx);
21201bb76ff1Sjsg 
21211bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++)
21221bb76ff1Sjsg 		if (pipe_fuses & 1 << i)
21231bb76ff1Sjsg 			num_pipes--;
21241bb76ff1Sjsg 
21251bb76ff1Sjsg 	if (pipe_fuses & 1)
21261bb76ff1Sjsg 		ASSERT(0); //Unexpected - Pipe 0 should always be fully functional!
21271bb76ff1Sjsg 
21281bb76ff1Sjsg 	if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK)
21291bb76ff1Sjsg 		ASSERT(0); //Entire DCN is harvested!
21301bb76ff1Sjsg 
21311bb76ff1Sjsg 	/* within dml lib, initial value is hard coded, if ASIC pipe is fused, the
21321bb76ff1Sjsg 	 * value will be changed, update max_num_dpp and max_num_otg for dml.
21331bb76ff1Sjsg 	 */
21341bb76ff1Sjsg 	dcn3_2_ip.max_num_dpp = num_pipes;
21351bb76ff1Sjsg 	dcn3_2_ip.max_num_otg = num_pipes;
21361bb76ff1Sjsg 
21371bb76ff1Sjsg 	pool->base.funcs = &dcn32_res_pool_funcs;
21381bb76ff1Sjsg 
21391bb76ff1Sjsg 	/*************************************************
21401bb76ff1Sjsg 	 *  Resource + asic cap harcoding                *
21411bb76ff1Sjsg 	 *************************************************/
21421bb76ff1Sjsg 	pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
21431bb76ff1Sjsg 	pool->base.timing_generator_count = num_pipes;
21441bb76ff1Sjsg 	pool->base.pipe_count = num_pipes;
21451bb76ff1Sjsg 	pool->base.mpcc_count = num_pipes;
21461bb76ff1Sjsg 	dc->caps.max_downscale_ratio = 600;
21471bb76ff1Sjsg 	dc->caps.i2c_speed_in_khz = 100;
21481bb76ff1Sjsg 	dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/
21491bb76ff1Sjsg 	/* TODO: Bring max_cursor_size back to 256 after subvp cursor corruption is fixed*/
21501bb76ff1Sjsg 	dc->caps.max_cursor_size = 64;
21511bb76ff1Sjsg 	dc->caps.min_horizontal_blanking_period = 80;
21521bb76ff1Sjsg 	dc->caps.dmdata_alloc_size = 2048;
2153cadf119fSjsg 	dc->caps.mall_size_per_mem_channel = 4;
21541bb76ff1Sjsg 	dc->caps.mall_size_total = 0;
21551bb76ff1Sjsg 	dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;
21561bb76ff1Sjsg 
21571bb76ff1Sjsg 	dc->caps.cache_line_size = 64;
21581bb76ff1Sjsg 	dc->caps.cache_num_ways = 16;
2159cadf119fSjsg 
2160cadf119fSjsg 	/* Calculate the available MALL space */
2161cadf119fSjsg 	dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall(
2162cadf119fSjsg 		dc, dc->ctx->dc_bios->vram_info.num_chans) *
2163cadf119fSjsg 		dc->caps.mall_size_per_mem_channel * 1024 * 1024;
2164cadf119fSjsg 	dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;
2165cadf119fSjsg 
21661bb76ff1Sjsg 	dc->caps.subvp_fw_processing_delay_us = 15;
2167f005ef32Sjsg 	dc->caps.subvp_drr_max_vblank_margin_us = 40;
21681bb76ff1Sjsg 	dc->caps.subvp_prefetch_end_to_mall_start_us = 15;
21691bb76ff1Sjsg 	dc->caps.subvp_swath_height_margin_lines = 16;
21701bb76ff1Sjsg 	dc->caps.subvp_pstate_allow_width_us = 20;
21711bb76ff1Sjsg 	dc->caps.subvp_vertical_int_margin_us = 30;
2172f005ef32Sjsg 	dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin
21731bb76ff1Sjsg 
21741bb76ff1Sjsg 	dc->caps.max_slave_planes = 2;
21751bb76ff1Sjsg 	dc->caps.max_slave_yuv_planes = 2;
21761bb76ff1Sjsg 	dc->caps.max_slave_rgb_planes = 2;
21771bb76ff1Sjsg 	dc->caps.post_blend_color_processing = true;
21781bb76ff1Sjsg 	dc->caps.force_dp_tps4_for_cp2520 = true;
2179f005ef32Sjsg 	if (dc->config.forceHBR2CP2520)
2180f005ef32Sjsg 		dc->caps.force_dp_tps4_for_cp2520 = false;
21811bb76ff1Sjsg 	dc->caps.dp_hpo = true;
21821bb76ff1Sjsg 	dc->caps.dp_hdmi21_pcon_support = true;
21831bb76ff1Sjsg 	dc->caps.edp_dsc_support = true;
21841bb76ff1Sjsg 	dc->caps.extended_aux_timeout_support = true;
21851bb76ff1Sjsg 	dc->caps.dmcub_support = true;
2186d0a17858Sjsg 	dc->caps.seamless_odm = true;
2187f005ef32Sjsg 	dc->caps.max_v_total = (1 << 15) - 1;
21881bb76ff1Sjsg 
21891bb76ff1Sjsg 	/* Color pipeline capabilities */
21901bb76ff1Sjsg 	dc->caps.color.dpp.dcn_arch = 1;
21911bb76ff1Sjsg 	dc->caps.color.dpp.input_lut_shared = 0;
21921bb76ff1Sjsg 	dc->caps.color.dpp.icsc = 1;
21931bb76ff1Sjsg 	dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr
21941bb76ff1Sjsg 	dc->caps.color.dpp.dgam_rom_caps.srgb = 1;
21951bb76ff1Sjsg 	dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;
21961bb76ff1Sjsg 	dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1;
21971bb76ff1Sjsg 	dc->caps.color.dpp.dgam_rom_caps.pq = 1;
21981bb76ff1Sjsg 	dc->caps.color.dpp.dgam_rom_caps.hlg = 1;
21991bb76ff1Sjsg 	dc->caps.color.dpp.post_csc = 1;
22001bb76ff1Sjsg 	dc->caps.color.dpp.gamma_corr = 1;
22011bb76ff1Sjsg 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
22021bb76ff1Sjsg 
22031bb76ff1Sjsg 	dc->caps.color.dpp.hw_3d_lut = 1;
22041bb76ff1Sjsg 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
22051bb76ff1Sjsg 	// no OGAM ROM on DCN2 and later ASICs
22061bb76ff1Sjsg 	dc->caps.color.dpp.ogam_rom_caps.srgb = 0;
22071bb76ff1Sjsg 	dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;
22081bb76ff1Sjsg 	dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;
22091bb76ff1Sjsg 	dc->caps.color.dpp.ogam_rom_caps.pq = 0;
22101bb76ff1Sjsg 	dc->caps.color.dpp.ogam_rom_caps.hlg = 0;
22111bb76ff1Sjsg 	dc->caps.color.dpp.ocsc = 0;
22121bb76ff1Sjsg 
22131bb76ff1Sjsg 	dc->caps.color.mpc.gamut_remap = 1;
22141bb76ff1Sjsg 	dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //4, configurable to be before or after BLND in MPCC
22151bb76ff1Sjsg 	dc->caps.color.mpc.ogam_ram = 1;
22161bb76ff1Sjsg 	dc->caps.color.mpc.ogam_rom_caps.srgb = 0;
22171bb76ff1Sjsg 	dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;
22181bb76ff1Sjsg 	dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;
22191bb76ff1Sjsg 	dc->caps.color.mpc.ogam_rom_caps.pq = 0;
22201bb76ff1Sjsg 	dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
22211bb76ff1Sjsg 	dc->caps.color.mpc.ocsc = 1;
22221bb76ff1Sjsg 
22231bb76ff1Sjsg 	/* Use pipe context based otg sync logic */
22241bb76ff1Sjsg 	dc->config.use_pipe_ctx_sync_logic = true;
22251bb76ff1Sjsg 
2226f005ef32Sjsg 	dc->config.dc_mode_clk_limit_support = true;
22271bb76ff1Sjsg 	/* read VBIOS LTTPR caps */
22281bb76ff1Sjsg 	{
22291bb76ff1Sjsg 		if (ctx->dc_bios->funcs->get_lttpr_caps) {
22301bb76ff1Sjsg 			enum bp_result bp_query_result;
22311bb76ff1Sjsg 			uint8_t is_vbios_lttpr_enable = 0;
22321bb76ff1Sjsg 
22331bb76ff1Sjsg 			bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
22341bb76ff1Sjsg 			dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
22351bb76ff1Sjsg 		}
22361bb76ff1Sjsg 
22371bb76ff1Sjsg 		/* interop bit is implicit */
22381bb76ff1Sjsg 		{
22391bb76ff1Sjsg 			dc->caps.vbios_lttpr_aware = true;
22401bb76ff1Sjsg 		}
22411bb76ff1Sjsg 	}
22421bb76ff1Sjsg 
22431bb76ff1Sjsg 	if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
22441bb76ff1Sjsg 		dc->debug = debug_defaults_drv;
2245f005ef32Sjsg 
22461bb76ff1Sjsg 	// Init the vm_helper
22471bb76ff1Sjsg 	if (dc->vm_helper)
22481bb76ff1Sjsg 		vm_helper_init(dc->vm_helper, 16);
22491bb76ff1Sjsg 
22501bb76ff1Sjsg 	/*************************************************
22511bb76ff1Sjsg 	 *  Create resources                             *
22521bb76ff1Sjsg 	 *************************************************/
22531bb76ff1Sjsg 
22541bb76ff1Sjsg 	/* Clock Sources for Pixel Clock*/
22551bb76ff1Sjsg 	pool->base.clock_sources[DCN32_CLK_SRC_PLL0] =
22561bb76ff1Sjsg 			dcn32_clock_source_create(ctx, ctx->dc_bios,
22571bb76ff1Sjsg 				CLOCK_SOURCE_COMBO_PHY_PLL0,
22581bb76ff1Sjsg 				&clk_src_regs[0], false);
22591bb76ff1Sjsg 	pool->base.clock_sources[DCN32_CLK_SRC_PLL1] =
22601bb76ff1Sjsg 			dcn32_clock_source_create(ctx, ctx->dc_bios,
22611bb76ff1Sjsg 				CLOCK_SOURCE_COMBO_PHY_PLL1,
22621bb76ff1Sjsg 				&clk_src_regs[1], false);
22631bb76ff1Sjsg 	pool->base.clock_sources[DCN32_CLK_SRC_PLL2] =
22641bb76ff1Sjsg 			dcn32_clock_source_create(ctx, ctx->dc_bios,
22651bb76ff1Sjsg 				CLOCK_SOURCE_COMBO_PHY_PLL2,
22661bb76ff1Sjsg 				&clk_src_regs[2], false);
22671bb76ff1Sjsg 	pool->base.clock_sources[DCN32_CLK_SRC_PLL3] =
22681bb76ff1Sjsg 			dcn32_clock_source_create(ctx, ctx->dc_bios,
22691bb76ff1Sjsg 				CLOCK_SOURCE_COMBO_PHY_PLL3,
22701bb76ff1Sjsg 				&clk_src_regs[3], false);
22711bb76ff1Sjsg 	pool->base.clock_sources[DCN32_CLK_SRC_PLL4] =
22721bb76ff1Sjsg 			dcn32_clock_source_create(ctx, ctx->dc_bios,
22731bb76ff1Sjsg 				CLOCK_SOURCE_COMBO_PHY_PLL4,
22741bb76ff1Sjsg 				&clk_src_regs[4], false);
22751bb76ff1Sjsg 
22761bb76ff1Sjsg 	pool->base.clk_src_count = DCN32_CLK_SRC_TOTAL;
22771bb76ff1Sjsg 
22781bb76ff1Sjsg 	/* todo: not reuse phy_pll registers */
22791bb76ff1Sjsg 	pool->base.dp_clock_source =
22801bb76ff1Sjsg 			dcn32_clock_source_create(ctx, ctx->dc_bios,
22811bb76ff1Sjsg 				CLOCK_SOURCE_ID_DP_DTO,
22821bb76ff1Sjsg 				&clk_src_regs[0], true);
22831bb76ff1Sjsg 
22841bb76ff1Sjsg 	for (i = 0; i < pool->base.clk_src_count; i++) {
22851bb76ff1Sjsg 		if (pool->base.clock_sources[i] == NULL) {
22861bb76ff1Sjsg 			dm_error("DC: failed to create clock sources!\n");
22871bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
22881bb76ff1Sjsg 			goto create_fail;
22891bb76ff1Sjsg 		}
22901bb76ff1Sjsg 	}
22911bb76ff1Sjsg 
22921bb76ff1Sjsg 	/* DCCG */
22931bb76ff1Sjsg 	pool->base.dccg = dccg32_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);
22941bb76ff1Sjsg 	if (pool->base.dccg == NULL) {
22951bb76ff1Sjsg 		dm_error("DC: failed to create dccg!\n");
22961bb76ff1Sjsg 		BREAK_TO_DEBUGGER();
22971bb76ff1Sjsg 		goto create_fail;
22981bb76ff1Sjsg 	}
22991bb76ff1Sjsg 
23001bb76ff1Sjsg 	/* DML */
23011bb76ff1Sjsg 	dml_init_instance(&dc->dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32);
23021bb76ff1Sjsg 
23031bb76ff1Sjsg 	/* IRQ Service */
23041bb76ff1Sjsg 	init_data.ctx = dc->ctx;
23051bb76ff1Sjsg 	pool->base.irqs = dal_irq_service_dcn32_create(&init_data);
23061bb76ff1Sjsg 	if (!pool->base.irqs)
23071bb76ff1Sjsg 		goto create_fail;
23081bb76ff1Sjsg 
23091bb76ff1Sjsg 	/* HUBBUB */
23101bb76ff1Sjsg 	pool->base.hubbub = dcn32_hubbub_create(ctx);
23111bb76ff1Sjsg 	if (pool->base.hubbub == NULL) {
23121bb76ff1Sjsg 		BREAK_TO_DEBUGGER();
23131bb76ff1Sjsg 		dm_error("DC: failed to create hubbub!\n");
23141bb76ff1Sjsg 		goto create_fail;
23151bb76ff1Sjsg 	}
23161bb76ff1Sjsg 
23171bb76ff1Sjsg 	/* HUBPs, DPPs, OPPs, TGs, ABMs */
23181bb76ff1Sjsg 	for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {
23191bb76ff1Sjsg 
23201bb76ff1Sjsg 		/* if pipe is disabled, skip instance of HW pipe,
23211bb76ff1Sjsg 		 * i.e, skip ASIC register instance
23221bb76ff1Sjsg 		 */
23231bb76ff1Sjsg 		if (pipe_fuses & 1 << i)
23241bb76ff1Sjsg 			continue;
23251bb76ff1Sjsg 
23261bb76ff1Sjsg 		/* HUBPs */
23271bb76ff1Sjsg 		pool->base.hubps[j] = dcn32_hubp_create(ctx, i);
23281bb76ff1Sjsg 		if (pool->base.hubps[j] == NULL) {
23291bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
23301bb76ff1Sjsg 			dm_error(
23311bb76ff1Sjsg 				"DC: failed to create hubps!\n");
23321bb76ff1Sjsg 			goto create_fail;
23331bb76ff1Sjsg 		}
23341bb76ff1Sjsg 
23351bb76ff1Sjsg 		/* DPPs */
23361bb76ff1Sjsg 		pool->base.dpps[j] = dcn32_dpp_create(ctx, i);
23371bb76ff1Sjsg 		if (pool->base.dpps[j] == NULL) {
23381bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
23391bb76ff1Sjsg 			dm_error(
23401bb76ff1Sjsg 				"DC: failed to create dpps!\n");
23411bb76ff1Sjsg 			goto create_fail;
23421bb76ff1Sjsg 		}
23431bb76ff1Sjsg 
23441bb76ff1Sjsg 		/* OPPs */
23451bb76ff1Sjsg 		pool->base.opps[j] = dcn32_opp_create(ctx, i);
23461bb76ff1Sjsg 		if (pool->base.opps[j] == NULL) {
23471bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
23481bb76ff1Sjsg 			dm_error(
23491bb76ff1Sjsg 				"DC: failed to create output pixel processor!\n");
23501bb76ff1Sjsg 			goto create_fail;
23511bb76ff1Sjsg 		}
23521bb76ff1Sjsg 
23531bb76ff1Sjsg 		/* TGs */
23541bb76ff1Sjsg 		pool->base.timing_generators[j] = dcn32_timing_generator_create(
23551bb76ff1Sjsg 				ctx, i);
23561bb76ff1Sjsg 		if (pool->base.timing_generators[j] == NULL) {
23571bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
23581bb76ff1Sjsg 			dm_error("DC: failed to create tg!\n");
23591bb76ff1Sjsg 			goto create_fail;
23601bb76ff1Sjsg 		}
23611bb76ff1Sjsg 
23621bb76ff1Sjsg 		/* ABMs */
23631bb76ff1Sjsg 		pool->base.multiple_abms[j] = dmub_abm_create(ctx,
23641bb76ff1Sjsg 				&abm_regs[i],
23651bb76ff1Sjsg 				&abm_shift,
23661bb76ff1Sjsg 				&abm_mask);
23671bb76ff1Sjsg 		if (pool->base.multiple_abms[j] == NULL) {
23681bb76ff1Sjsg 			dm_error("DC: failed to create abm for pipe %d!\n", i);
23691bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
23701bb76ff1Sjsg 			goto create_fail;
23711bb76ff1Sjsg 		}
23721bb76ff1Sjsg 
23731bb76ff1Sjsg 		/* index for resource pool arrays for next valid pipe */
23741bb76ff1Sjsg 		j++;
23751bb76ff1Sjsg 	}
23761bb76ff1Sjsg 
23771bb76ff1Sjsg 	/* PSR */
23781bb76ff1Sjsg 	pool->base.psr = dmub_psr_create(ctx);
23791bb76ff1Sjsg 	if (pool->base.psr == NULL) {
23801bb76ff1Sjsg 		dm_error("DC: failed to create psr obj!\n");
23811bb76ff1Sjsg 		BREAK_TO_DEBUGGER();
23821bb76ff1Sjsg 		goto create_fail;
23831bb76ff1Sjsg 	}
23841bb76ff1Sjsg 
23851bb76ff1Sjsg 	/* MPCCs */
23861bb76ff1Sjsg 	pool->base.mpc = dcn32_mpc_create(ctx, pool->base.res_cap->num_timing_generator, pool->base.res_cap->num_mpc_3dlut);
23871bb76ff1Sjsg 	if (pool->base.mpc == NULL) {
23881bb76ff1Sjsg 		BREAK_TO_DEBUGGER();
23891bb76ff1Sjsg 		dm_error("DC: failed to create mpc!\n");
23901bb76ff1Sjsg 		goto create_fail;
23911bb76ff1Sjsg 	}
23921bb76ff1Sjsg 
23931bb76ff1Sjsg 	/* DSCs */
23941bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
23951bb76ff1Sjsg 		pool->base.dscs[i] = dcn32_dsc_create(ctx, i);
23961bb76ff1Sjsg 		if (pool->base.dscs[i] == NULL) {
23971bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
23981bb76ff1Sjsg 			dm_error("DC: failed to create display stream compressor %d!\n", i);
23991bb76ff1Sjsg 			goto create_fail;
24001bb76ff1Sjsg 		}
24011bb76ff1Sjsg 	}
24021bb76ff1Sjsg 
24031bb76ff1Sjsg 	/* DWB */
24041bb76ff1Sjsg 	if (!dcn32_dwbc_create(ctx, &pool->base)) {
24051bb76ff1Sjsg 		BREAK_TO_DEBUGGER();
24061bb76ff1Sjsg 		dm_error("DC: failed to create dwbc!\n");
24071bb76ff1Sjsg 		goto create_fail;
24081bb76ff1Sjsg 	}
24091bb76ff1Sjsg 
24101bb76ff1Sjsg 	/* MMHUBBUB */
24111bb76ff1Sjsg 	if (!dcn32_mmhubbub_create(ctx, &pool->base)) {
24121bb76ff1Sjsg 		BREAK_TO_DEBUGGER();
24131bb76ff1Sjsg 		dm_error("DC: failed to create mcif_wb!\n");
24141bb76ff1Sjsg 		goto create_fail;
24151bb76ff1Sjsg 	}
24161bb76ff1Sjsg 
24171bb76ff1Sjsg 	/* AUX and I2C */
24181bb76ff1Sjsg 	for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
24191bb76ff1Sjsg 		pool->base.engines[i] = dcn32_aux_engine_create(ctx, i);
24201bb76ff1Sjsg 		if (pool->base.engines[i] == NULL) {
24211bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
24221bb76ff1Sjsg 			dm_error(
24231bb76ff1Sjsg 				"DC:failed to create aux engine!!\n");
24241bb76ff1Sjsg 			goto create_fail;
24251bb76ff1Sjsg 		}
24261bb76ff1Sjsg 		pool->base.hw_i2cs[i] = dcn32_i2c_hw_create(ctx, i);
24271bb76ff1Sjsg 		if (pool->base.hw_i2cs[i] == NULL) {
24281bb76ff1Sjsg 			BREAK_TO_DEBUGGER();
24291bb76ff1Sjsg 			dm_error(
24301bb76ff1Sjsg 				"DC:failed to create hw i2c!!\n");
24311bb76ff1Sjsg 			goto create_fail;
24321bb76ff1Sjsg 		}
24331bb76ff1Sjsg 		pool->base.sw_i2cs[i] = NULL;
24341bb76ff1Sjsg 	}
24351bb76ff1Sjsg 
24361bb76ff1Sjsg 	/* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */
24371bb76ff1Sjsg 	if (!resource_construct(num_virtual_links, dc, &pool->base,
2438f005ef32Sjsg 			&res_create_funcs))
24391bb76ff1Sjsg 		goto create_fail;
24401bb76ff1Sjsg 
24411bb76ff1Sjsg 	/* HW Sequencer init functions and Plane caps */
24421bb76ff1Sjsg 	dcn32_hw_sequencer_init_functions(dc);
24431bb76ff1Sjsg 
24441bb76ff1Sjsg 	dc->caps.max_planes =  pool->base.pipe_count;
24451bb76ff1Sjsg 
24461bb76ff1Sjsg 	for (i = 0; i < dc->caps.max_planes; ++i)
24471bb76ff1Sjsg 		dc->caps.planes[i] = plane_cap;
24481bb76ff1Sjsg 
24491bb76ff1Sjsg 	dc->cap_funcs = cap_funcs;
24501bb76ff1Sjsg 
24511bb76ff1Sjsg 	if (dc->ctx->dc_bios->fw_info.oem_i2c_present) {
24521bb76ff1Sjsg 		ddc_init_data.ctx = dc->ctx;
24531bb76ff1Sjsg 		ddc_init_data.link = NULL;
24541bb76ff1Sjsg 		ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;
24551bb76ff1Sjsg 		ddc_init_data.id.enum_id = 0;
24561bb76ff1Sjsg 		ddc_init_data.id.type = OBJECT_TYPE_GENERIC;
2457f005ef32Sjsg 		pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data);
24581bb76ff1Sjsg 	} else {
24591bb76ff1Sjsg 		pool->base.oem_device = NULL;
24601bb76ff1Sjsg 	}
24611bb76ff1Sjsg 
2462f005ef32Sjsg 	if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0))
2463f005ef32Sjsg 		dc->config.sdpif_request_limit_words_per_umc = 16;
2464f005ef32Sjsg 
24651bb76ff1Sjsg 	DC_FP_END();
24661bb76ff1Sjsg 
24671bb76ff1Sjsg 	return true;
24681bb76ff1Sjsg 
24691bb76ff1Sjsg create_fail:
24701bb76ff1Sjsg 
24711bb76ff1Sjsg 	DC_FP_END();
24721bb76ff1Sjsg 
24731bb76ff1Sjsg 	dcn32_resource_destruct(pool);
24741bb76ff1Sjsg 
24751bb76ff1Sjsg 	return false;
24761bb76ff1Sjsg }
24771bb76ff1Sjsg 
24781bb76ff1Sjsg struct resource_pool *dcn32_create_resource_pool(
24791bb76ff1Sjsg 		const struct dc_init_data *init_data,
24801bb76ff1Sjsg 		struct dc *dc)
24811bb76ff1Sjsg {
24821bb76ff1Sjsg 	struct dcn32_resource_pool *pool =
24831bb76ff1Sjsg 		kzalloc(sizeof(struct dcn32_resource_pool), GFP_KERNEL);
24841bb76ff1Sjsg 
24851bb76ff1Sjsg 	if (!pool)
24861bb76ff1Sjsg 		return NULL;
24871bb76ff1Sjsg 
24881bb76ff1Sjsg 	if (dcn32_resource_construct(init_data->num_virtual_links, dc, pool))
24891bb76ff1Sjsg 		return &pool->base;
24901bb76ff1Sjsg 
24911bb76ff1Sjsg 	BREAK_TO_DEBUGGER();
24921bb76ff1Sjsg 	kfree(pool);
24931bb76ff1Sjsg 	return NULL;
24941bb76ff1Sjsg }
24951bb76ff1Sjsg 
2496f005ef32Sjsg /*
2497f005ef32Sjsg  * Find the most optimal free pipe from res_ctx, which could be used as a
2498f005ef32Sjsg  * secondary dpp pipe for input opp head pipe.
2499f005ef32Sjsg  *
2500f005ef32Sjsg  * a free pipe - a pipe in input res_ctx not yet used for any streams or
2501f005ef32Sjsg  * planes.
2502f005ef32Sjsg  * secondary dpp pipe - a pipe gets inserted to a head OPP pipe's MPC blending
2503f005ef32Sjsg  * tree. This is typical used for rendering MPO planes or additional offset
2504f005ef32Sjsg  * areas in MPCC combine.
2505f005ef32Sjsg  *
2506f005ef32Sjsg  * Hardware Transition Minimization Algorithm for Finding a Secondary DPP Pipe
2507f005ef32Sjsg  * -------------------------------------------------------------------------
2508f005ef32Sjsg  *
2509f005ef32Sjsg  * PROBLEM:
2510f005ef32Sjsg  *
2511f005ef32Sjsg  * 1. There is a hardware limitation that a secondary DPP pipe cannot be
2512f005ef32Sjsg  * transferred from one MPC blending tree to the other in a single frame.
2513f005ef32Sjsg  * Otherwise it could cause glitches on the screen.
2514f005ef32Sjsg  *
2515f005ef32Sjsg  * For instance, we cannot transition from state 1 to state 2 in one frame. This
2516f005ef32Sjsg  * is because PIPE1 is transferred from PIPE0's MPC blending tree over to
2517f005ef32Sjsg  * PIPE2's MPC blending tree, which is not supported by hardware.
2518f005ef32Sjsg  * To support this transition we need to first remove PIPE1 from PIPE0's MPC
2519f005ef32Sjsg  * blending tree in one frame and then insert PIPE1 to PIPE2's MPC blending tree
2520f005ef32Sjsg  * in the next frame. This is not optimal as it will delay the flip for two
2521f005ef32Sjsg  * frames.
2522f005ef32Sjsg  *
2523f005ef32Sjsg  *	State 1:
2524f005ef32Sjsg  *	PIPE0 -- secondary DPP pipe --> (PIPE1)
2525f005ef32Sjsg  *	PIPE2 -- secondary DPP pipe --> NONE
2526f005ef32Sjsg  *
2527f005ef32Sjsg  *	State 2:
2528f005ef32Sjsg  *	PIPE0 -- secondary DPP pipe --> NONE
2529f005ef32Sjsg  *	PIPE2 -- secondary DPP pipe --> (PIPE1)
2530f005ef32Sjsg  *
2531f005ef32Sjsg  * 2. We want to in general minimize the unnecessary changes in pipe topology.
2532f005ef32Sjsg  * If a pipe is already added in current blending tree and there are no changes
2533f005ef32Sjsg  * to plane topology, we don't want to swap it with another free pipe
2534f005ef32Sjsg  * unnecessarily in every update. Powering up and down a pipe would require a
2535f005ef32Sjsg  * full update which delays the flip for 1 frame. If we use the original pipe
2536f005ef32Sjsg  * we don't have to toggle its power. So we can flip faster.
2537f005ef32Sjsg  */
2538f005ef32Sjsg static int find_optimal_free_pipe_as_secondary_dpp_pipe(
2539f005ef32Sjsg 		const struct resource_context *cur_res_ctx,
2540f005ef32Sjsg 		struct resource_context *new_res_ctx,
2541f005ef32Sjsg 		const struct resource_pool *pool,
2542f005ef32Sjsg 		const struct pipe_ctx *new_opp_head)
2543f005ef32Sjsg {
2544f005ef32Sjsg 	const struct pipe_ctx *cur_opp_head;
2545f005ef32Sjsg 	int free_pipe_idx;
2546f005ef32Sjsg 
2547f005ef32Sjsg 	cur_opp_head = &cur_res_ctx->pipe_ctx[new_opp_head->pipe_idx];
2548f005ef32Sjsg 	free_pipe_idx = resource_find_free_pipe_used_in_cur_mpc_blending_tree(
2549f005ef32Sjsg 			cur_res_ctx, new_res_ctx, cur_opp_head);
2550f005ef32Sjsg 
2551f005ef32Sjsg 	/* Up until here if we have not found a free secondary pipe, we will
2552f005ef32Sjsg 	 * need to wait for at least one frame to complete the transition
2553f005ef32Sjsg 	 * sequence.
2554f005ef32Sjsg 	 */
2555f005ef32Sjsg 	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)
2556f005ef32Sjsg 		free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx(
2557f005ef32Sjsg 				cur_res_ctx, new_res_ctx, pool);
2558f005ef32Sjsg 
2559f005ef32Sjsg 	/* Up until here if we have not found a free secondary pipe, we will
2560f005ef32Sjsg 	 * need to wait for at least two frames to complete the transition
2561f005ef32Sjsg 	 * sequence. It really doesn't matter which pipe we decide take from
2562f005ef32Sjsg 	 * current enabled pipes. It won't save our frame time when we swap only
2563f005ef32Sjsg 	 * one pipe or more pipes.
2564f005ef32Sjsg 	 */
2565f005ef32Sjsg 	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)
2566f005ef32Sjsg 		free_pipe_idx = resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine(
2567f005ef32Sjsg 				cur_res_ctx, new_res_ctx, pool);
2568f005ef32Sjsg 
2569f005ef32Sjsg 	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)
2570f005ef32Sjsg 		free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool);
2571f005ef32Sjsg 
2572f005ef32Sjsg 	return free_pipe_idx;
2573f005ef32Sjsg }
2574f005ef32Sjsg 
25751bb76ff1Sjsg static struct pipe_ctx *find_idle_secondary_pipe_check_mpo(
25761bb76ff1Sjsg 		struct resource_context *res_ctx,
25771bb76ff1Sjsg 		const struct resource_pool *pool,
25781bb76ff1Sjsg 		const struct pipe_ctx *primary_pipe)
25791bb76ff1Sjsg {
25801bb76ff1Sjsg 	int i;
25811bb76ff1Sjsg 	struct pipe_ctx *secondary_pipe = NULL;
25821bb76ff1Sjsg 	struct pipe_ctx *next_odm_mpo_pipe = NULL;
25831bb76ff1Sjsg 	int primary_index, preferred_pipe_idx;
25841bb76ff1Sjsg 	struct pipe_ctx *old_primary_pipe = NULL;
25851bb76ff1Sjsg 
25861bb76ff1Sjsg 	/*
25871bb76ff1Sjsg 	 * Modified from find_idle_secondary_pipe
25881bb76ff1Sjsg 	 * With windowed MPO and ODM, we want to avoid the case where we want a
25891bb76ff1Sjsg 	 *  free pipe for the left side but the free pipe is being used on the
25901bb76ff1Sjsg 	 *  right side.
25911bb76ff1Sjsg 	 * Add check on current_state if the primary_pipe is the left side,
25921bb76ff1Sjsg 	 *  to check the right side ( primary_pipe->next_odm_pipe ) to see if
25931bb76ff1Sjsg 	 *  it is using a pipe for MPO ( primary_pipe->next_odm_pipe->bottom_pipe )
25941bb76ff1Sjsg 	 * - If so, then don't use this pipe
25951bb76ff1Sjsg 	 * EXCEPTION - 3 plane ( 2 MPO plane ) case
25961bb76ff1Sjsg 	 * - in this case, the primary pipe has already gotten a free pipe for the
25971bb76ff1Sjsg 	 *  MPO window in the left
25981bb76ff1Sjsg 	 * - when it tries to get a free pipe for the MPO window on the right,
25991bb76ff1Sjsg 	 *  it will see that it is already assigned to the right side
26001bb76ff1Sjsg 	 *  ( primary_pipe->next_odm_pipe ).  But in this case, we want this
26011bb76ff1Sjsg 	 *  free pipe, since it will be for the right side.  So add an
26021bb76ff1Sjsg 	 *  additional condition, that skipping the free pipe on the right only
26031bb76ff1Sjsg 	 *  applies if the primary pipe has no bottom pipe currently assigned
26041bb76ff1Sjsg 	 */
26051bb76ff1Sjsg 	if (primary_pipe) {
26061bb76ff1Sjsg 		primary_index = primary_pipe->pipe_idx;
26071bb76ff1Sjsg 		old_primary_pipe = &primary_pipe->stream->ctx->dc->current_state->res_ctx.pipe_ctx[primary_index];
26081bb76ff1Sjsg 		if ((old_primary_pipe->next_odm_pipe) && (old_primary_pipe->next_odm_pipe->bottom_pipe)
26091bb76ff1Sjsg 			&& (!primary_pipe->bottom_pipe))
26101bb76ff1Sjsg 			next_odm_mpo_pipe = old_primary_pipe->next_odm_pipe->bottom_pipe;
26111bb76ff1Sjsg 
26121bb76ff1Sjsg 		preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
26131bb76ff1Sjsg 		if ((res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) &&
26141bb76ff1Sjsg 			!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == preferred_pipe_idx)) {
26151bb76ff1Sjsg 			secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
26161bb76ff1Sjsg 			secondary_pipe->pipe_idx = preferred_pipe_idx;
26171bb76ff1Sjsg 		}
26181bb76ff1Sjsg 	}
26191bb76ff1Sjsg 
26201bb76ff1Sjsg 	/*
26211bb76ff1Sjsg 	 * search backwards for the second pipe to keep pipe
26221bb76ff1Sjsg 	 * assignment more consistent
26231bb76ff1Sjsg 	 */
26241bb76ff1Sjsg 	if (!secondary_pipe)
26251bb76ff1Sjsg 		for (i = pool->pipe_count - 1; i >= 0; i--) {
26261bb76ff1Sjsg 			if ((res_ctx->pipe_ctx[i].stream == NULL) &&
26271bb76ff1Sjsg 				!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == i)) {
26281bb76ff1Sjsg 				secondary_pipe = &res_ctx->pipe_ctx[i];
26291bb76ff1Sjsg 				secondary_pipe->pipe_idx = i;
26301bb76ff1Sjsg 				break;
26311bb76ff1Sjsg 			}
26321bb76ff1Sjsg 		}
26331bb76ff1Sjsg 
26341bb76ff1Sjsg 	return secondary_pipe;
26351bb76ff1Sjsg }
26361bb76ff1Sjsg 
2637f005ef32Sjsg static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
26381bb76ff1Sjsg 		struct dc_state *state,
26391bb76ff1Sjsg 		const struct resource_pool *pool,
26401bb76ff1Sjsg 		struct dc_stream_state *stream,
2641f005ef32Sjsg 		const struct pipe_ctx *head_pipe)
26421bb76ff1Sjsg {
26431bb76ff1Sjsg 	struct resource_context *res_ctx = &state->res_ctx;
26441bb76ff1Sjsg 	struct pipe_ctx *idle_pipe, *pipe;
26451bb76ff1Sjsg 	struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx;
26461bb76ff1Sjsg 	int head_index;
26471bb76ff1Sjsg 
26481bb76ff1Sjsg 	if (!head_pipe)
26491bb76ff1Sjsg 		ASSERT(0);
26501bb76ff1Sjsg 
26511bb76ff1Sjsg 	/*
26521bb76ff1Sjsg 	 * Modified from dcn20_acquire_idle_pipe_for_layer
26531bb76ff1Sjsg 	 * Check if head_pipe in old_context already has bottom_pipe allocated.
26541bb76ff1Sjsg 	 * - If so, check if that pipe is available in the current context.
26551bb76ff1Sjsg 	 * --  If so, reuse pipe from old_context
26561bb76ff1Sjsg 	 */
26571bb76ff1Sjsg 	head_index = head_pipe->pipe_idx;
26581bb76ff1Sjsg 	pipe = &old_ctx->pipe_ctx[head_index];
26591bb76ff1Sjsg 	if (pipe->bottom_pipe && res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx].stream == NULL) {
26601bb76ff1Sjsg 		idle_pipe = &res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx];
26611bb76ff1Sjsg 		idle_pipe->pipe_idx = pipe->bottom_pipe->pipe_idx;
26621bb76ff1Sjsg 	} else {
26631bb76ff1Sjsg 		idle_pipe = find_idle_secondary_pipe_check_mpo(res_ctx, pool, head_pipe);
26641bb76ff1Sjsg 		if (!idle_pipe)
26651bb76ff1Sjsg 			return NULL;
26661bb76ff1Sjsg 	}
26671bb76ff1Sjsg 
26681bb76ff1Sjsg 	idle_pipe->stream = head_pipe->stream;
26691bb76ff1Sjsg 	idle_pipe->stream_res.tg = head_pipe->stream_res.tg;
26701bb76ff1Sjsg 	idle_pipe->stream_res.opp = head_pipe->stream_res.opp;
26711bb76ff1Sjsg 
26721bb76ff1Sjsg 	idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];
26731bb76ff1Sjsg 	idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx];
26741bb76ff1Sjsg 	idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx];
26751bb76ff1Sjsg 	idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst;
26761bb76ff1Sjsg 
26771bb76ff1Sjsg 	return idle_pipe;
26781bb76ff1Sjsg }
2679cadf119fSjsg 
2680f005ef32Sjsg struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe(
2681f005ef32Sjsg 		const struct dc_state *cur_ctx,
2682f005ef32Sjsg 		struct dc_state *new_ctx,
2683f005ef32Sjsg 		const struct resource_pool *pool,
2684f005ef32Sjsg 		const struct pipe_ctx *opp_head_pipe)
2685f005ef32Sjsg {
2686f005ef32Sjsg 
2687f005ef32Sjsg 	int free_pipe_idx;
2688f005ef32Sjsg 	struct pipe_ctx *free_pipe;
2689f005ef32Sjsg 
2690f005ef32Sjsg 	if (!opp_head_pipe->stream->ctx->dc->config.enable_windowed_mpo_odm)
2691f005ef32Sjsg 		return dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
2692f005ef32Sjsg 				new_ctx, pool, opp_head_pipe->stream, opp_head_pipe);
2693f005ef32Sjsg 
2694f005ef32Sjsg 	free_pipe_idx = find_optimal_free_pipe_as_secondary_dpp_pipe(
2695f005ef32Sjsg 					&cur_ctx->res_ctx, &new_ctx->res_ctx,
2696f005ef32Sjsg 					pool, opp_head_pipe);
2697f005ef32Sjsg 	if (free_pipe_idx >= 0) {
2698f005ef32Sjsg 		free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx];
2699f005ef32Sjsg 		free_pipe->pipe_idx = free_pipe_idx;
2700f005ef32Sjsg 		free_pipe->stream = opp_head_pipe->stream;
2701f005ef32Sjsg 		free_pipe->stream_res.tg = opp_head_pipe->stream_res.tg;
2702f005ef32Sjsg 		free_pipe->stream_res.opp = opp_head_pipe->stream_res.opp;
2703f005ef32Sjsg 
2704f005ef32Sjsg 		free_pipe->plane_res.hubp = pool->hubps[free_pipe->pipe_idx];
2705f005ef32Sjsg 		free_pipe->plane_res.ipp = pool->ipps[free_pipe->pipe_idx];
2706f005ef32Sjsg 		free_pipe->plane_res.dpp = pool->dpps[free_pipe->pipe_idx];
2707f005ef32Sjsg 		free_pipe->plane_res.mpcc_inst =
2708f005ef32Sjsg 				pool->dpps[free_pipe->pipe_idx]->inst;
2709f005ef32Sjsg 	} else {
2710f005ef32Sjsg 		ASSERT(opp_head_pipe);
2711f005ef32Sjsg 		free_pipe = NULL;
2712f005ef32Sjsg 	}
2713f005ef32Sjsg 
2714f005ef32Sjsg 	return free_pipe;
2715f005ef32Sjsg }
2716f005ef32Sjsg 
2717cadf119fSjsg unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans)
2718cadf119fSjsg {
2719cadf119fSjsg 	/*
2720cadf119fSjsg 	 * DCN32 and DCN321 SKUs may have different sizes for MALL
2721cadf119fSjsg 	 *  but we may not be able to access all the MALL space.
2722cadf119fSjsg 	 *  If the num_chans is power of 2, then we can access all
2723cadf119fSjsg 	 *  of the available MALL space.  Otherwise, we can only
2724cadf119fSjsg 	 *  access:
2725cadf119fSjsg 	 *
2726cadf119fSjsg 	 *  max_cab_size_in_bytes = total_cache_size_in_bytes *
2727cadf119fSjsg 	 *    ((2^floor(log2(num_chans)))/num_chans)
2728cadf119fSjsg 	 *
2729cadf119fSjsg 	 * Calculating the MALL sizes for all available SKUs, we
2730cadf119fSjsg 	 *  have come up with the follow simplified check.
2731cadf119fSjsg 	 * - we have max_chans which provides the max MALL size.
2732cadf119fSjsg 	 *  Each chans supports 4MB of MALL so:
2733cadf119fSjsg 	 *
2734cadf119fSjsg 	 *  total_cache_size_in_bytes = max_chans * 4 MB
2735cadf119fSjsg 	 *
2736cadf119fSjsg 	 * - we have avail_chans which shows the number of channels
2737cadf119fSjsg 	 *  we can use if we can't access the entire MALL space.
2738cadf119fSjsg 	 *  It is generally half of max_chans
2739cadf119fSjsg 	 * - so we use the following checks:
2740cadf119fSjsg 	 *
2741cadf119fSjsg 	 *   if (num_chans == max_chans), return max_chans
2742cadf119fSjsg 	 *   if (num_chans < max_chans), return avail_chans
2743cadf119fSjsg 	 *
2744cadf119fSjsg 	 * - exception is GC_11_0_0 where we can't access max_chans,
2745cadf119fSjsg 	 *  so we define max_avail_chans as the maximum available
2746cadf119fSjsg 	 *  MALL space
2747cadf119fSjsg 	 *
2748cadf119fSjsg 	 */
2749cadf119fSjsg 	int gc_11_0_0_max_chans = 48;
2750cadf119fSjsg 	int gc_11_0_0_max_avail_chans = 32;
2751cadf119fSjsg 	int gc_11_0_0_avail_chans = 16;
2752cadf119fSjsg 	int gc_11_0_3_max_chans = 16;
2753cadf119fSjsg 	int gc_11_0_3_avail_chans = 8;
2754cadf119fSjsg 	int gc_11_0_2_max_chans = 8;
2755cadf119fSjsg 	int gc_11_0_2_avail_chans = 4;
2756cadf119fSjsg 
2757cadf119fSjsg 	if (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev)) {
2758cadf119fSjsg 		return (num_chans == gc_11_0_0_max_chans) ?
2759cadf119fSjsg 			gc_11_0_0_max_avail_chans : gc_11_0_0_avail_chans;
2760cadf119fSjsg 	} else if (ASICREV_IS_GC_11_0_2(dc->ctx->asic_id.hw_internal_rev)) {
2761cadf119fSjsg 		return (num_chans == gc_11_0_2_max_chans) ?
2762cadf119fSjsg 			gc_11_0_2_max_chans : gc_11_0_2_avail_chans;
2763cadf119fSjsg 	} else { // if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev)) {
2764cadf119fSjsg 		return (num_chans == gc_11_0_3_max_chans) ?
2765cadf119fSjsg 			gc_11_0_3_max_chans : gc_11_0_3_avail_chans;
2766cadf119fSjsg 	}
2767cadf119fSjsg }
2768