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