Back to home page

OSCL-LXR

 
 

    


0001 /*
0002 * Copyright 2016 Advanced Micro Devices, Inc.
0003  * Copyright 2019 Raptor Engineering, LLC
0004  *
0005  * Permission is hereby granted, free of charge, to any person obtaining a
0006  * copy of this software and associated documentation files (the "Software"),
0007  * to deal in the Software without restriction, including without limitation
0008  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0009  * and/or sell copies of the Software, and to permit persons to whom the
0010  * Software is furnished to do so, subject to the following conditions:
0011  *
0012  * The above copyright notice and this permission notice shall be included in
0013  * all copies or substantial portions of the Software.
0014  *
0015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0018  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0019  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0020  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0021  * OTHER DEALINGS IN THE SOFTWARE.
0022  *
0023  * Authors: AMD
0024  *
0025  */
0026 
0027 #include <linux/slab.h>
0028 
0029 #include "dm_services.h"
0030 #include "dc.h"
0031 
0032 #include "dcn20_init.h"
0033 
0034 #include "resource.h"
0035 #include "include/irq_service_interface.h"
0036 #include "dcn20/dcn20_resource.h"
0037 
0038 #include "dml/dcn20/dcn20_fpu.h"
0039 
0040 #include "dcn10/dcn10_hubp.h"
0041 #include "dcn10/dcn10_ipp.h"
0042 #include "dcn20_hubbub.h"
0043 #include "dcn20_mpc.h"
0044 #include "dcn20_hubp.h"
0045 #include "irq/dcn20/irq_service_dcn20.h"
0046 #include "dcn20_dpp.h"
0047 #include "dcn20_optc.h"
0048 #include "dcn20_hwseq.h"
0049 #include "dce110/dce110_hw_sequencer.h"
0050 #include "dcn10/dcn10_resource.h"
0051 #include "dcn20_opp.h"
0052 
0053 #include "dcn20_dsc.h"
0054 
0055 #include "dcn20_link_encoder.h"
0056 #include "dcn20_stream_encoder.h"
0057 #include "dce/dce_clock_source.h"
0058 #include "dce/dce_audio.h"
0059 #include "dce/dce_hwseq.h"
0060 #include "virtual/virtual_stream_encoder.h"
0061 #include "dce110/dce110_resource.h"
0062 #include "dml/display_mode_vba.h"
0063 #include "dcn20_dccg.h"
0064 #include "dcn20_vmid.h"
0065 #include "dc_link_ddc.h"
0066 #include "dce/dce_panel_cntl.h"
0067 
0068 #include "navi10_ip_offset.h"
0069 
0070 #include "dcn/dcn_2_0_0_offset.h"
0071 #include "dcn/dcn_2_0_0_sh_mask.h"
0072 #include "dpcs/dpcs_2_0_0_offset.h"
0073 #include "dpcs/dpcs_2_0_0_sh_mask.h"
0074 
0075 #include "nbio/nbio_2_3_offset.h"
0076 
0077 #include "dcn20/dcn20_dwb.h"
0078 #include "dcn20/dcn20_mmhubbub.h"
0079 
0080 #include "mmhub/mmhub_2_0_0_offset.h"
0081 #include "mmhub/mmhub_2_0_0_sh_mask.h"
0082 
0083 #include "reg_helper.h"
0084 #include "dce/dce_abm.h"
0085 #include "dce/dce_dmcu.h"
0086 #include "dce/dce_aux.h"
0087 #include "dce/dce_i2c.h"
0088 #include "vm_helper.h"
0089 #include "link_enc_cfg.h"
0090 
0091 #include "amdgpu_socbb.h"
0092 
0093 #define DC_LOGGER_INIT(logger)
0094 
0095 #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
0096     #define mmDP0_DP_DPHY_INTERNAL_CTRL     0x210f
0097     #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
0098     #define mmDP1_DP_DPHY_INTERNAL_CTRL     0x220f
0099     #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
0100     #define mmDP2_DP_DPHY_INTERNAL_CTRL     0x230f
0101     #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
0102     #define mmDP3_DP_DPHY_INTERNAL_CTRL     0x240f
0103     #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
0104     #define mmDP4_DP_DPHY_INTERNAL_CTRL     0x250f
0105     #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
0106     #define mmDP5_DP_DPHY_INTERNAL_CTRL     0x260f
0107     #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
0108     #define mmDP6_DP_DPHY_INTERNAL_CTRL     0x270f
0109     #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
0110 #endif
0111 
0112 
0113 enum dcn20_clk_src_array_id {
0114     DCN20_CLK_SRC_PLL0,
0115     DCN20_CLK_SRC_PLL1,
0116     DCN20_CLK_SRC_PLL2,
0117     DCN20_CLK_SRC_PLL3,
0118     DCN20_CLK_SRC_PLL4,
0119     DCN20_CLK_SRC_PLL5,
0120     DCN20_CLK_SRC_TOTAL
0121 };
0122 
0123 /* begin *********************
0124  * macros to expend register list macro defined in HW object header file */
0125 
0126 /* DCN */
0127 /* TODO awful hack. fixup dcn20_dwb.h */
0128 #undef BASE_INNER
0129 #define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
0130 
0131 #define BASE(seg) BASE_INNER(seg)
0132 
0133 #define SR(reg_name)\
0134         .reg_name = BASE(mm ## reg_name ## _BASE_IDX) +  \
0135                     mm ## reg_name
0136 
0137 #define SRI(reg_name, block, id)\
0138     .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
0139                     mm ## block ## id ## _ ## reg_name
0140 
0141 #define SRIR(var_name, reg_name, block, id)\
0142     .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
0143                     mm ## block ## id ## _ ## reg_name
0144 
0145 #define SRII(reg_name, block, id)\
0146     .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
0147                     mm ## block ## id ## _ ## reg_name
0148 
0149 #define DCCG_SRII(reg_name, block, id)\
0150     .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
0151                     mm ## block ## id ## _ ## reg_name
0152 
0153 #define VUPDATE_SRII(reg_name, block, id)\
0154     .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \
0155                     mm ## reg_name ## _ ## block ## id
0156 
0157 /* NBIO */
0158 #define NBIO_BASE_INNER(seg) \
0159     NBIO_BASE__INST0_SEG ## seg
0160 
0161 #define NBIO_BASE(seg) \
0162     NBIO_BASE_INNER(seg)
0163 
0164 #define NBIO_SR(reg_name)\
0165         .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \
0166                     mm ## reg_name
0167 
0168 /* MMHUB */
0169 #define MMHUB_BASE_INNER(seg) \
0170     MMHUB_BASE__INST0_SEG ## seg
0171 
0172 #define MMHUB_BASE(seg) \
0173     MMHUB_BASE_INNER(seg)
0174 
0175 #define MMHUB_SR(reg_name)\
0176         .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \
0177                     mmMM ## reg_name
0178 
0179 static const struct bios_registers bios_regs = {
0180         NBIO_SR(BIOS_SCRATCH_3),
0181         NBIO_SR(BIOS_SCRATCH_6)
0182 };
0183 
0184 #define clk_src_regs(index, pllid)\
0185 [index] = {\
0186     CS_COMMON_REG_LIST_DCN2_0(index, pllid),\
0187 }
0188 
0189 static const struct dce110_clk_src_regs clk_src_regs[] = {
0190     clk_src_regs(0, A),
0191     clk_src_regs(1, B),
0192     clk_src_regs(2, C),
0193     clk_src_regs(3, D),
0194     clk_src_regs(4, E),
0195     clk_src_regs(5, F)
0196 };
0197 
0198 static const struct dce110_clk_src_shift cs_shift = {
0199         CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
0200 };
0201 
0202 static const struct dce110_clk_src_mask cs_mask = {
0203         CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
0204 };
0205 
0206 static const struct dce_dmcu_registers dmcu_regs = {
0207         DMCU_DCN10_REG_LIST()
0208 };
0209 
0210 static const struct dce_dmcu_shift dmcu_shift = {
0211         DMCU_MASK_SH_LIST_DCN10(__SHIFT)
0212 };
0213 
0214 static const struct dce_dmcu_mask dmcu_mask = {
0215         DMCU_MASK_SH_LIST_DCN10(_MASK)
0216 };
0217 
0218 static const struct dce_abm_registers abm_regs = {
0219         ABM_DCN20_REG_LIST()
0220 };
0221 
0222 static const struct dce_abm_shift abm_shift = {
0223         ABM_MASK_SH_LIST_DCN20(__SHIFT)
0224 };
0225 
0226 static const struct dce_abm_mask abm_mask = {
0227         ABM_MASK_SH_LIST_DCN20(_MASK)
0228 };
0229 
0230 #define audio_regs(id)\
0231 [id] = {\
0232         AUD_COMMON_REG_LIST(id)\
0233 }
0234 
0235 static const struct dce_audio_registers audio_regs[] = {
0236     audio_regs(0),
0237     audio_regs(1),
0238     audio_regs(2),
0239     audio_regs(3),
0240     audio_regs(4),
0241     audio_regs(5),
0242     audio_regs(6),
0243 };
0244 
0245 #define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\
0246         SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
0247         SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
0248         AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)
0249 
0250 static const struct dce_audio_shift audio_shift = {
0251         DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)
0252 };
0253 
0254 static const struct dce_audio_mask audio_mask = {
0255         DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)
0256 };
0257 
0258 #define stream_enc_regs(id)\
0259 [id] = {\
0260     SE_DCN2_REG_LIST(id)\
0261 }
0262 
0263 static const struct dcn10_stream_enc_registers stream_enc_regs[] = {
0264     stream_enc_regs(0),
0265     stream_enc_regs(1),
0266     stream_enc_regs(2),
0267     stream_enc_regs(3),
0268     stream_enc_regs(4),
0269     stream_enc_regs(5),
0270 };
0271 
0272 static const struct dcn10_stream_encoder_shift se_shift = {
0273         SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT)
0274 };
0275 
0276 static const struct dcn10_stream_encoder_mask se_mask = {
0277         SE_COMMON_MASK_SH_LIST_DCN20(_MASK)
0278 };
0279 
0280 
0281 #define aux_regs(id)\
0282 [id] = {\
0283     DCN2_AUX_REG_LIST(id)\
0284 }
0285 
0286 static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = {
0287         aux_regs(0),
0288         aux_regs(1),
0289         aux_regs(2),
0290         aux_regs(3),
0291         aux_regs(4),
0292         aux_regs(5)
0293 };
0294 
0295 #define hpd_regs(id)\
0296 [id] = {\
0297     HPD_REG_LIST(id)\
0298 }
0299 
0300 static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = {
0301         hpd_regs(0),
0302         hpd_regs(1),
0303         hpd_regs(2),
0304         hpd_regs(3),
0305         hpd_regs(4),
0306         hpd_regs(5)
0307 };
0308 
0309 #define link_regs(id, phyid)\
0310 [id] = {\
0311     LE_DCN10_REG_LIST(id), \
0312     UNIPHY_DCN2_REG_LIST(phyid), \
0313     DPCS_DCN2_REG_LIST(id), \
0314     SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \
0315 }
0316 
0317 static const struct dcn10_link_enc_registers link_enc_regs[] = {
0318     link_regs(0, A),
0319     link_regs(1, B),
0320     link_regs(2, C),
0321     link_regs(3, D),
0322     link_regs(4, E),
0323     link_regs(5, F)
0324 };
0325 
0326 static const struct dcn10_link_enc_shift le_shift = {
0327     LINK_ENCODER_MASK_SH_LIST_DCN20(__SHIFT),\
0328     DPCS_DCN2_MASK_SH_LIST(__SHIFT)
0329 };
0330 
0331 static const struct dcn10_link_enc_mask le_mask = {
0332     LINK_ENCODER_MASK_SH_LIST_DCN20(_MASK),\
0333     DPCS_DCN2_MASK_SH_LIST(_MASK)
0334 };
0335 
0336 static const struct dce_panel_cntl_registers panel_cntl_regs[] = {
0337     { DCN_PANEL_CNTL_REG_LIST() }
0338 };
0339 
0340 static const struct dce_panel_cntl_shift panel_cntl_shift = {
0341     DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT)
0342 };
0343 
0344 static const struct dce_panel_cntl_mask panel_cntl_mask = {
0345     DCE_PANEL_CNTL_MASK_SH_LIST(_MASK)
0346 };
0347 
0348 #define ipp_regs(id)\
0349 [id] = {\
0350     IPP_REG_LIST_DCN20(id),\
0351 }
0352 
0353 static const struct dcn10_ipp_registers ipp_regs[] = {
0354     ipp_regs(0),
0355     ipp_regs(1),
0356     ipp_regs(2),
0357     ipp_regs(3),
0358     ipp_regs(4),
0359     ipp_regs(5),
0360 };
0361 
0362 static const struct dcn10_ipp_shift ipp_shift = {
0363         IPP_MASK_SH_LIST_DCN20(__SHIFT)
0364 };
0365 
0366 static const struct dcn10_ipp_mask ipp_mask = {
0367         IPP_MASK_SH_LIST_DCN20(_MASK),
0368 };
0369 
0370 #define opp_regs(id)\
0371 [id] = {\
0372     OPP_REG_LIST_DCN20(id),\
0373 }
0374 
0375 static const struct dcn20_opp_registers opp_regs[] = {
0376     opp_regs(0),
0377     opp_regs(1),
0378     opp_regs(2),
0379     opp_regs(3),
0380     opp_regs(4),
0381     opp_regs(5),
0382 };
0383 
0384 static const struct dcn20_opp_shift opp_shift = {
0385         OPP_MASK_SH_LIST_DCN20(__SHIFT)
0386 };
0387 
0388 static const struct dcn20_opp_mask opp_mask = {
0389         OPP_MASK_SH_LIST_DCN20(_MASK)
0390 };
0391 
0392 #define aux_engine_regs(id)\
0393 [id] = {\
0394     AUX_COMMON_REG_LIST0(id), \
0395     .AUXN_IMPCAL = 0, \
0396     .AUXP_IMPCAL = 0, \
0397     .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \
0398 }
0399 
0400 static const struct dce110_aux_registers aux_engine_regs[] = {
0401         aux_engine_regs(0),
0402         aux_engine_regs(1),
0403         aux_engine_regs(2),
0404         aux_engine_regs(3),
0405         aux_engine_regs(4),
0406         aux_engine_regs(5)
0407 };
0408 
0409 #define tf_regs(id)\
0410 [id] = {\
0411     TF_REG_LIST_DCN20(id),\
0412     TF_REG_LIST_DCN20_COMMON_APPEND(id),\
0413 }
0414 
0415 static const struct dcn2_dpp_registers tf_regs[] = {
0416     tf_regs(0),
0417     tf_regs(1),
0418     tf_regs(2),
0419     tf_regs(3),
0420     tf_regs(4),
0421     tf_regs(5),
0422 };
0423 
0424 static const struct dcn2_dpp_shift tf_shift = {
0425         TF_REG_LIST_SH_MASK_DCN20(__SHIFT),
0426         TF_DEBUG_REG_LIST_SH_DCN20
0427 };
0428 
0429 static const struct dcn2_dpp_mask tf_mask = {
0430         TF_REG_LIST_SH_MASK_DCN20(_MASK),
0431         TF_DEBUG_REG_LIST_MASK_DCN20
0432 };
0433 
0434 #define dwbc_regs_dcn2(id)\
0435 [id] = {\
0436     DWBC_COMMON_REG_LIST_DCN2_0(id),\
0437         }
0438 
0439 static const struct dcn20_dwbc_registers dwbc20_regs[] = {
0440     dwbc_regs_dcn2(0),
0441 };
0442 
0443 static const struct dcn20_dwbc_shift dwbc20_shift = {
0444     DWBC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
0445 };
0446 
0447 static const struct dcn20_dwbc_mask dwbc20_mask = {
0448     DWBC_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
0449 };
0450 
0451 #define mcif_wb_regs_dcn2(id)\
0452 [id] = {\
0453     MCIF_WB_COMMON_REG_LIST_DCN2_0(id),\
0454         }
0455 
0456 static const struct dcn20_mmhubbub_registers mcif_wb20_regs[] = {
0457     mcif_wb_regs_dcn2(0),
0458 };
0459 
0460 static const struct dcn20_mmhubbub_shift mcif_wb20_shift = {
0461     MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
0462 };
0463 
0464 static const struct dcn20_mmhubbub_mask mcif_wb20_mask = {
0465     MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
0466 };
0467 
0468 static const struct dcn20_mpc_registers mpc_regs = {
0469         MPC_REG_LIST_DCN2_0(0),
0470         MPC_REG_LIST_DCN2_0(1),
0471         MPC_REG_LIST_DCN2_0(2),
0472         MPC_REG_LIST_DCN2_0(3),
0473         MPC_REG_LIST_DCN2_0(4),
0474         MPC_REG_LIST_DCN2_0(5),
0475         MPC_OUT_MUX_REG_LIST_DCN2_0(0),
0476         MPC_OUT_MUX_REG_LIST_DCN2_0(1),
0477         MPC_OUT_MUX_REG_LIST_DCN2_0(2),
0478         MPC_OUT_MUX_REG_LIST_DCN2_0(3),
0479         MPC_OUT_MUX_REG_LIST_DCN2_0(4),
0480         MPC_OUT_MUX_REG_LIST_DCN2_0(5),
0481         MPC_DBG_REG_LIST_DCN2_0()
0482 };
0483 
0484 static const struct dcn20_mpc_shift mpc_shift = {
0485     MPC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT),
0486     MPC_DEBUG_REG_LIST_SH_DCN20
0487 };
0488 
0489 static const struct dcn20_mpc_mask mpc_mask = {
0490     MPC_COMMON_MASK_SH_LIST_DCN2_0(_MASK),
0491     MPC_DEBUG_REG_LIST_MASK_DCN20
0492 };
0493 
0494 #define tg_regs(id)\
0495 [id] = {TG_COMMON_REG_LIST_DCN2_0(id)}
0496 
0497 
0498 static const struct dcn_optc_registers tg_regs[] = {
0499     tg_regs(0),
0500     tg_regs(1),
0501     tg_regs(2),
0502     tg_regs(3),
0503     tg_regs(4),
0504     tg_regs(5)
0505 };
0506 
0507 static const struct dcn_optc_shift tg_shift = {
0508     TG_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
0509 };
0510 
0511 static const struct dcn_optc_mask tg_mask = {
0512     TG_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
0513 };
0514 
0515 #define hubp_regs(id)\
0516 [id] = {\
0517     HUBP_REG_LIST_DCN20(id)\
0518 }
0519 
0520 static const struct dcn_hubp2_registers hubp_regs[] = {
0521         hubp_regs(0),
0522         hubp_regs(1),
0523         hubp_regs(2),
0524         hubp_regs(3),
0525         hubp_regs(4),
0526         hubp_regs(5)
0527 };
0528 
0529 static const struct dcn_hubp2_shift hubp_shift = {
0530         HUBP_MASK_SH_LIST_DCN20(__SHIFT)
0531 };
0532 
0533 static const struct dcn_hubp2_mask hubp_mask = {
0534         HUBP_MASK_SH_LIST_DCN20(_MASK)
0535 };
0536 
0537 static const struct dcn_hubbub_registers hubbub_reg = {
0538         HUBBUB_REG_LIST_DCN20(0)
0539 };
0540 
0541 static const struct dcn_hubbub_shift hubbub_shift = {
0542         HUBBUB_MASK_SH_LIST_DCN20(__SHIFT)
0543 };
0544 
0545 static const struct dcn_hubbub_mask hubbub_mask = {
0546         HUBBUB_MASK_SH_LIST_DCN20(_MASK)
0547 };
0548 
0549 #define vmid_regs(id)\
0550 [id] = {\
0551         DCN20_VMID_REG_LIST(id)\
0552 }
0553 
0554 static const struct dcn_vmid_registers vmid_regs[] = {
0555     vmid_regs(0),
0556     vmid_regs(1),
0557     vmid_regs(2),
0558     vmid_regs(3),
0559     vmid_regs(4),
0560     vmid_regs(5),
0561     vmid_regs(6),
0562     vmid_regs(7),
0563     vmid_regs(8),
0564     vmid_regs(9),
0565     vmid_regs(10),
0566     vmid_regs(11),
0567     vmid_regs(12),
0568     vmid_regs(13),
0569     vmid_regs(14),
0570     vmid_regs(15)
0571 };
0572 
0573 static const struct dcn20_vmid_shift vmid_shifts = {
0574         DCN20_VMID_MASK_SH_LIST(__SHIFT)
0575 };
0576 
0577 static const struct dcn20_vmid_mask vmid_masks = {
0578         DCN20_VMID_MASK_SH_LIST(_MASK)
0579 };
0580 
0581 static const struct dce110_aux_registers_shift aux_shift = {
0582         DCN_AUX_MASK_SH_LIST(__SHIFT)
0583 };
0584 
0585 static const struct dce110_aux_registers_mask aux_mask = {
0586         DCN_AUX_MASK_SH_LIST(_MASK)
0587 };
0588 
0589 static int map_transmitter_id_to_phy_instance(
0590     enum transmitter transmitter)
0591 {
0592     switch (transmitter) {
0593     case TRANSMITTER_UNIPHY_A:
0594         return 0;
0595     break;
0596     case TRANSMITTER_UNIPHY_B:
0597         return 1;
0598     break;
0599     case TRANSMITTER_UNIPHY_C:
0600         return 2;
0601     break;
0602     case TRANSMITTER_UNIPHY_D:
0603         return 3;
0604     break;
0605     case TRANSMITTER_UNIPHY_E:
0606         return 4;
0607     break;
0608     case TRANSMITTER_UNIPHY_F:
0609         return 5;
0610     break;
0611     default:
0612         ASSERT(0);
0613         return 0;
0614     }
0615 }
0616 
0617 #define dsc_regsDCN20(id)\
0618 [id] = {\
0619     DSC_REG_LIST_DCN20(id)\
0620 }
0621 
0622 static const struct dcn20_dsc_registers dsc_regs[] = {
0623     dsc_regsDCN20(0),
0624     dsc_regsDCN20(1),
0625     dsc_regsDCN20(2),
0626     dsc_regsDCN20(3),
0627     dsc_regsDCN20(4),
0628     dsc_regsDCN20(5)
0629 };
0630 
0631 static const struct dcn20_dsc_shift dsc_shift = {
0632     DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)
0633 };
0634 
0635 static const struct dcn20_dsc_mask dsc_mask = {
0636     DSC_REG_LIST_SH_MASK_DCN20(_MASK)
0637 };
0638 
0639 static const struct dccg_registers dccg_regs = {
0640         DCCG_REG_LIST_DCN2()
0641 };
0642 
0643 static const struct dccg_shift dccg_shift = {
0644         DCCG_MASK_SH_LIST_DCN2(__SHIFT)
0645 };
0646 
0647 static const struct dccg_mask dccg_mask = {
0648         DCCG_MASK_SH_LIST_DCN2(_MASK)
0649 };
0650 
0651 static const struct resource_caps res_cap_nv10 = {
0652         .num_timing_generator = 6,
0653         .num_opp = 6,
0654         .num_video_plane = 6,
0655         .num_audio = 7,
0656         .num_stream_encoder = 6,
0657         .num_pll = 6,
0658         .num_dwb = 1,
0659         .num_ddc = 6,
0660         .num_vmid = 16,
0661         .num_dsc = 6,
0662 };
0663 
0664 static const struct dc_plane_cap plane_cap = {
0665     .type = DC_PLANE_TYPE_DCN_UNIVERSAL,
0666     .blends_with_above = true,
0667     .blends_with_below = true,
0668     .per_pixel_alpha = true,
0669 
0670     .pixel_format_support = {
0671             .argb8888 = true,
0672             .nv12 = true,
0673             .fp16 = true,
0674             .p010 = true
0675     },
0676 
0677     .max_upscale_factor = {
0678             .argb8888 = 16000,
0679             .nv12 = 16000,
0680             .fp16 = 1
0681     },
0682 
0683     .max_downscale_factor = {
0684             .argb8888 = 250,
0685             .nv12 = 250,
0686             .fp16 = 1
0687     },
0688     16,
0689     16
0690 };
0691 static const struct resource_caps res_cap_nv14 = {
0692         .num_timing_generator = 5,
0693         .num_opp = 5,
0694         .num_video_plane = 5,
0695         .num_audio = 6,
0696         .num_stream_encoder = 5,
0697         .num_pll = 5,
0698         .num_dwb = 1,
0699         .num_ddc = 5,
0700         .num_vmid = 16,
0701         .num_dsc = 5,
0702 };
0703 
0704 static const struct dc_debug_options debug_defaults_drv = {
0705         .disable_dmcu = false,
0706         .force_abm_enable = false,
0707         .timing_trace = false,
0708         .clock_trace = true,
0709         .disable_pplib_clock_request = true,
0710         .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP,
0711         .force_single_disp_pipe_split = false,
0712         .disable_dcc = DCC_ENABLE,
0713         .vsr_support = true,
0714         .performance_trace = false,
0715         .max_downscale_src_width = 5120,/*upto 5K*/
0716         .disable_pplib_wm_range = false,
0717         .scl_reset_length10 = true,
0718         .sanity_checks = false,
0719         .underflow_assert_delay_us = 0xFFFFFFFF,
0720 };
0721 
0722 static const struct dc_debug_options debug_defaults_diags = {
0723         .disable_dmcu = false,
0724         .force_abm_enable = false,
0725         .timing_trace = true,
0726         .clock_trace = true,
0727         .disable_dpp_power_gate = true,
0728         .disable_hubp_power_gate = true,
0729         .disable_clock_gate = true,
0730         .disable_pplib_clock_request = true,
0731         .disable_pplib_wm_range = true,
0732         .disable_stutter = true,
0733         .scl_reset_length10 = true,
0734         .underflow_assert_delay_us = 0xFFFFFFFF,
0735         .enable_tri_buf = true,
0736 };
0737 
0738 void dcn20_dpp_destroy(struct dpp **dpp)
0739 {
0740     kfree(TO_DCN20_DPP(*dpp));
0741     *dpp = NULL;
0742 }
0743 
0744 struct dpp *dcn20_dpp_create(
0745     struct dc_context *ctx,
0746     uint32_t inst)
0747 {
0748     struct dcn20_dpp *dpp =
0749         kzalloc(sizeof(struct dcn20_dpp), GFP_ATOMIC);
0750 
0751     if (!dpp)
0752         return NULL;
0753 
0754     if (dpp2_construct(dpp, ctx, inst,
0755             &tf_regs[inst], &tf_shift, &tf_mask))
0756         return &dpp->base;
0757 
0758     BREAK_TO_DEBUGGER();
0759     kfree(dpp);
0760     return NULL;
0761 }
0762 
0763 struct input_pixel_processor *dcn20_ipp_create(
0764     struct dc_context *ctx, uint32_t inst)
0765 {
0766     struct dcn10_ipp *ipp =
0767         kzalloc(sizeof(struct dcn10_ipp), GFP_ATOMIC);
0768 
0769     if (!ipp) {
0770         BREAK_TO_DEBUGGER();
0771         return NULL;
0772     }
0773 
0774     dcn20_ipp_construct(ipp, ctx, inst,
0775             &ipp_regs[inst], &ipp_shift, &ipp_mask);
0776     return &ipp->base;
0777 }
0778 
0779 
0780 struct output_pixel_processor *dcn20_opp_create(
0781     struct dc_context *ctx, uint32_t inst)
0782 {
0783     struct dcn20_opp *opp =
0784         kzalloc(sizeof(struct dcn20_opp), GFP_ATOMIC);
0785 
0786     if (!opp) {
0787         BREAK_TO_DEBUGGER();
0788         return NULL;
0789     }
0790 
0791     dcn20_opp_construct(opp, ctx, inst,
0792             &opp_regs[inst], &opp_shift, &opp_mask);
0793     return &opp->base;
0794 }
0795 
0796 struct dce_aux *dcn20_aux_engine_create(
0797     struct dc_context *ctx,
0798     uint32_t inst)
0799 {
0800     struct aux_engine_dce110 *aux_engine =
0801         kzalloc(sizeof(struct aux_engine_dce110), GFP_ATOMIC);
0802 
0803     if (!aux_engine)
0804         return NULL;
0805 
0806     dce110_aux_engine_construct(aux_engine, ctx, inst,
0807                     SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
0808                     &aux_engine_regs[inst],
0809                     &aux_mask,
0810                     &aux_shift,
0811                     ctx->dc->caps.extended_aux_timeout_support);
0812 
0813     return &aux_engine->base;
0814 }
0815 #define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) }
0816 
0817 static const struct dce_i2c_registers i2c_hw_regs[] = {
0818         i2c_inst_regs(1),
0819         i2c_inst_regs(2),
0820         i2c_inst_regs(3),
0821         i2c_inst_regs(4),
0822         i2c_inst_regs(5),
0823         i2c_inst_regs(6),
0824 };
0825 
0826 static const struct dce_i2c_shift i2c_shifts = {
0827         I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT)
0828 };
0829 
0830 static const struct dce_i2c_mask i2c_masks = {
0831         I2C_COMMON_MASK_SH_LIST_DCN2(_MASK)
0832 };
0833 
0834 struct dce_i2c_hw *dcn20_i2c_hw_create(
0835     struct dc_context *ctx,
0836     uint32_t inst)
0837 {
0838     struct dce_i2c_hw *dce_i2c_hw =
0839         kzalloc(sizeof(struct dce_i2c_hw), GFP_ATOMIC);
0840 
0841     if (!dce_i2c_hw)
0842         return NULL;
0843 
0844     dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,
0845                     &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);
0846 
0847     return dce_i2c_hw;
0848 }
0849 struct mpc *dcn20_mpc_create(struct dc_context *ctx)
0850 {
0851     struct dcn20_mpc *mpc20 = kzalloc(sizeof(struct dcn20_mpc),
0852                       GFP_ATOMIC);
0853 
0854     if (!mpc20)
0855         return NULL;
0856 
0857     dcn20_mpc_construct(mpc20, ctx,
0858             &mpc_regs,
0859             &mpc_shift,
0860             &mpc_mask,
0861             6);
0862 
0863     return &mpc20->base;
0864 }
0865 
0866 struct hubbub *dcn20_hubbub_create(struct dc_context *ctx)
0867 {
0868     int i;
0869     struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub),
0870                       GFP_ATOMIC);
0871 
0872     if (!hubbub)
0873         return NULL;
0874 
0875     hubbub2_construct(hubbub, ctx,
0876             &hubbub_reg,
0877             &hubbub_shift,
0878             &hubbub_mask);
0879 
0880     for (i = 0; i < res_cap_nv10.num_vmid; i++) {
0881         struct dcn20_vmid *vmid = &hubbub->vmid[i];
0882 
0883         vmid->ctx = ctx;
0884 
0885         vmid->regs = &vmid_regs[i];
0886         vmid->shifts = &vmid_shifts;
0887         vmid->masks = &vmid_masks;
0888     }
0889 
0890     return &hubbub->base;
0891 }
0892 
0893 struct timing_generator *dcn20_timing_generator_create(
0894         struct dc_context *ctx,
0895         uint32_t instance)
0896 {
0897     struct optc *tgn10 =
0898         kzalloc(sizeof(struct optc), GFP_ATOMIC);
0899 
0900     if (!tgn10)
0901         return NULL;
0902 
0903     tgn10->base.inst = instance;
0904     tgn10->base.ctx = ctx;
0905 
0906     tgn10->tg_regs = &tg_regs[instance];
0907     tgn10->tg_shift = &tg_shift;
0908     tgn10->tg_mask = &tg_mask;
0909 
0910     dcn20_timing_generator_init(tgn10);
0911 
0912     return &tgn10->base;
0913 }
0914 
0915 static const struct encoder_feature_support link_enc_feature = {
0916         .max_hdmi_deep_color = COLOR_DEPTH_121212,
0917         .max_hdmi_pixel_clock = 600000,
0918         .hdmi_ycbcr420_supported = true,
0919         .dp_ycbcr420_supported = true,
0920         .fec_supported = true,
0921         .flags.bits.IS_HBR2_CAPABLE = true,
0922         .flags.bits.IS_HBR3_CAPABLE = true,
0923         .flags.bits.IS_TPS3_CAPABLE = true,
0924         .flags.bits.IS_TPS4_CAPABLE = true
0925 };
0926 
0927 struct link_encoder *dcn20_link_encoder_create(
0928     struct dc_context *ctx,
0929     const struct encoder_init_data *enc_init_data)
0930 {
0931     struct dcn20_link_encoder *enc20 =
0932         kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
0933     int link_regs_id;
0934 
0935     if (!enc20)
0936         return NULL;
0937 
0938     link_regs_id =
0939         map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
0940 
0941     dcn20_link_encoder_construct(enc20,
0942                       enc_init_data,
0943                       &link_enc_feature,
0944                       &link_enc_regs[link_regs_id],
0945                       &link_enc_aux_regs[enc_init_data->channel - 1],
0946                       &link_enc_hpd_regs[enc_init_data->hpd_source],
0947                       &le_shift,
0948                       &le_mask);
0949 
0950     return &enc20->enc10.base;
0951 }
0952 
0953 static struct panel_cntl *dcn20_panel_cntl_create(const struct panel_cntl_init_data *init_data)
0954 {
0955     struct dce_panel_cntl *panel_cntl =
0956         kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL);
0957 
0958     if (!panel_cntl)
0959         return NULL;
0960 
0961     dce_panel_cntl_construct(panel_cntl,
0962             init_data,
0963             &panel_cntl_regs[init_data->inst],
0964             &panel_cntl_shift,
0965             &panel_cntl_mask);
0966 
0967     return &panel_cntl->base;
0968 }
0969 
0970 static struct clock_source *dcn20_clock_source_create(
0971     struct dc_context *ctx,
0972     struct dc_bios *bios,
0973     enum clock_source_id id,
0974     const struct dce110_clk_src_regs *regs,
0975     bool dp_clk_src)
0976 {
0977     struct dce110_clk_src *clk_src =
0978         kzalloc(sizeof(struct dce110_clk_src), GFP_ATOMIC);
0979 
0980     if (!clk_src)
0981         return NULL;
0982 
0983     if (dcn20_clk_src_construct(clk_src, ctx, bios, id,
0984             regs, &cs_shift, &cs_mask)) {
0985         clk_src->base.dp_clk_src = dp_clk_src;
0986         return &clk_src->base;
0987     }
0988 
0989     kfree(clk_src);
0990     BREAK_TO_DEBUGGER();
0991     return NULL;
0992 }
0993 
0994 static void read_dce_straps(
0995     struct dc_context *ctx,
0996     struct resource_straps *straps)
0997 {
0998     generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX),
0999         FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);
1000 }
1001 
1002 static struct audio *dcn20_create_audio(
1003         struct dc_context *ctx, unsigned int inst)
1004 {
1005     return dce_audio_create(ctx, inst,
1006             &audio_regs[inst], &audio_shift, &audio_mask);
1007 }
1008 
1009 struct stream_encoder *dcn20_stream_encoder_create(
1010     enum engine_id eng_id,
1011     struct dc_context *ctx)
1012 {
1013     struct dcn10_stream_encoder *enc1 =
1014         kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
1015 
1016     if (!enc1)
1017         return NULL;
1018 
1019     if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) {
1020         if (eng_id >= ENGINE_ID_DIGD)
1021             eng_id++;
1022     }
1023 
1024     dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id,
1025                     &stream_enc_regs[eng_id],
1026                     &se_shift, &se_mask);
1027 
1028     return &enc1->base;
1029 }
1030 
1031 static const struct dce_hwseq_registers hwseq_reg = {
1032         HWSEQ_DCN2_REG_LIST()
1033 };
1034 
1035 static const struct dce_hwseq_shift hwseq_shift = {
1036         HWSEQ_DCN2_MASK_SH_LIST(__SHIFT)
1037 };
1038 
1039 static const struct dce_hwseq_mask hwseq_mask = {
1040         HWSEQ_DCN2_MASK_SH_LIST(_MASK)
1041 };
1042 
1043 struct dce_hwseq *dcn20_hwseq_create(
1044     struct dc_context *ctx)
1045 {
1046     struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
1047 
1048     if (hws) {
1049         hws->ctx = ctx;
1050         hws->regs = &hwseq_reg;
1051         hws->shifts = &hwseq_shift;
1052         hws->masks = &hwseq_mask;
1053     }
1054     return hws;
1055 }
1056 
1057 static const struct resource_create_funcs res_create_funcs = {
1058     .read_dce_straps = read_dce_straps,
1059     .create_audio = dcn20_create_audio,
1060     .create_stream_encoder = dcn20_stream_encoder_create,
1061     .create_hwseq = dcn20_hwseq_create,
1062 };
1063 
1064 static const struct resource_create_funcs res_create_maximus_funcs = {
1065     .read_dce_straps = NULL,
1066     .create_audio = NULL,
1067     .create_stream_encoder = NULL,
1068     .create_hwseq = dcn20_hwseq_create,
1069 };
1070 
1071 static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu);
1072 
1073 void dcn20_clock_source_destroy(struct clock_source **clk_src)
1074 {
1075     kfree(TO_DCE110_CLK_SRC(*clk_src));
1076     *clk_src = NULL;
1077 }
1078 
1079 
1080 struct display_stream_compressor *dcn20_dsc_create(
1081     struct dc_context *ctx, uint32_t inst)
1082 {
1083     struct dcn20_dsc *dsc =
1084         kzalloc(sizeof(struct dcn20_dsc), GFP_ATOMIC);
1085 
1086     if (!dsc) {
1087         BREAK_TO_DEBUGGER();
1088         return NULL;
1089     }
1090 
1091     dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
1092     return &dsc->base;
1093 }
1094 
1095 void dcn20_dsc_destroy(struct display_stream_compressor **dsc)
1096 {
1097     kfree(container_of(*dsc, struct dcn20_dsc, base));
1098     *dsc = NULL;
1099 }
1100 
1101 
1102 static void dcn20_resource_destruct(struct dcn20_resource_pool *pool)
1103 {
1104     unsigned int i;
1105 
1106     for (i = 0; i < pool->base.stream_enc_count; i++) {
1107         if (pool->base.stream_enc[i] != NULL) {
1108             kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));
1109             pool->base.stream_enc[i] = NULL;
1110         }
1111     }
1112 
1113     for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
1114         if (pool->base.dscs[i] != NULL)
1115             dcn20_dsc_destroy(&pool->base.dscs[i]);
1116     }
1117 
1118     if (pool->base.mpc != NULL) {
1119         kfree(TO_DCN20_MPC(pool->base.mpc));
1120         pool->base.mpc = NULL;
1121     }
1122     if (pool->base.hubbub != NULL) {
1123         kfree(pool->base.hubbub);
1124         pool->base.hubbub = NULL;
1125     }
1126     for (i = 0; i < pool->base.pipe_count; i++) {
1127         if (pool->base.dpps[i] != NULL)
1128             dcn20_dpp_destroy(&pool->base.dpps[i]);
1129 
1130         if (pool->base.ipps[i] != NULL)
1131             pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);
1132 
1133         if (pool->base.hubps[i] != NULL) {
1134             kfree(TO_DCN20_HUBP(pool->base.hubps[i]));
1135             pool->base.hubps[i] = NULL;
1136         }
1137 
1138         if (pool->base.irqs != NULL) {
1139             dal_irq_service_destroy(&pool->base.irqs);
1140         }
1141     }
1142 
1143     for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
1144         if (pool->base.engines[i] != NULL)
1145             dce110_engine_destroy(&pool->base.engines[i]);
1146         if (pool->base.hw_i2cs[i] != NULL) {
1147             kfree(pool->base.hw_i2cs[i]);
1148             pool->base.hw_i2cs[i] = NULL;
1149         }
1150         if (pool->base.sw_i2cs[i] != NULL) {
1151             kfree(pool->base.sw_i2cs[i]);
1152             pool->base.sw_i2cs[i] = NULL;
1153         }
1154     }
1155 
1156     for (i = 0; i < pool->base.res_cap->num_opp; i++) {
1157         if (pool->base.opps[i] != NULL)
1158             pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
1159     }
1160 
1161     for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
1162         if (pool->base.timing_generators[i] != NULL)    {
1163             kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
1164             pool->base.timing_generators[i] = NULL;
1165         }
1166     }
1167 
1168     for (i = 0; i < pool->base.res_cap->num_dwb; i++) {
1169         if (pool->base.dwbc[i] != NULL) {
1170             kfree(TO_DCN20_DWBC(pool->base.dwbc[i]));
1171             pool->base.dwbc[i] = NULL;
1172         }
1173         if (pool->base.mcif_wb[i] != NULL) {
1174             kfree(TO_DCN20_MMHUBBUB(pool->base.mcif_wb[i]));
1175             pool->base.mcif_wb[i] = NULL;
1176         }
1177     }
1178 
1179     for (i = 0; i < pool->base.audio_count; i++) {
1180         if (pool->base.audios[i])
1181             dce_aud_destroy(&pool->base.audios[i]);
1182     }
1183 
1184     for (i = 0; i < pool->base.clk_src_count; i++) {
1185         if (pool->base.clock_sources[i] != NULL) {
1186             dcn20_clock_source_destroy(&pool->base.clock_sources[i]);
1187             pool->base.clock_sources[i] = NULL;
1188         }
1189     }
1190 
1191     if (pool->base.dp_clock_source != NULL) {
1192         dcn20_clock_source_destroy(&pool->base.dp_clock_source);
1193         pool->base.dp_clock_source = NULL;
1194     }
1195 
1196 
1197     if (pool->base.abm != NULL)
1198         dce_abm_destroy(&pool->base.abm);
1199 
1200     if (pool->base.dmcu != NULL)
1201         dce_dmcu_destroy(&pool->base.dmcu);
1202 
1203     if (pool->base.dccg != NULL)
1204         dcn_dccg_destroy(&pool->base.dccg);
1205 
1206     if (pool->base.pp_smu != NULL)
1207         dcn20_pp_smu_destroy(&pool->base.pp_smu);
1208 
1209     if (pool->base.oem_device != NULL)
1210         dal_ddc_service_destroy(&pool->base.oem_device);
1211 }
1212 
1213 struct hubp *dcn20_hubp_create(
1214     struct dc_context *ctx,
1215     uint32_t inst)
1216 {
1217     struct dcn20_hubp *hubp2 =
1218         kzalloc(sizeof(struct dcn20_hubp), GFP_ATOMIC);
1219 
1220     if (!hubp2)
1221         return NULL;
1222 
1223     if (hubp2_construct(hubp2, ctx, inst,
1224             &hubp_regs[inst], &hubp_shift, &hubp_mask))
1225         return &hubp2->base;
1226 
1227     BREAK_TO_DEBUGGER();
1228     kfree(hubp2);
1229     return NULL;
1230 }
1231 
1232 static void get_pixel_clock_parameters(
1233     struct pipe_ctx *pipe_ctx,
1234     struct pixel_clk_params *pixel_clk_params)
1235 {
1236     const struct dc_stream_state *stream = pipe_ctx->stream;
1237     struct pipe_ctx *odm_pipe;
1238     int opp_cnt = 1;
1239     struct dc_link *link = stream->link;
1240     struct link_encoder *link_enc = NULL;
1241     struct dc *dc = pipe_ctx->stream->ctx->dc;
1242     struct dce_hwseq *hws = dc->hwseq;
1243 
1244     for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
1245         opp_cnt++;
1246 
1247     pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
1248 
1249     link_enc = link_enc_cfg_get_link_enc(link);
1250     if (link_enc)
1251         pixel_clk_params->encoder_object_id = link_enc->id;
1252 
1253     pixel_clk_params->signal_type = pipe_ctx->stream->signal;
1254     pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1;
1255     /* TODO: un-hardcode*/
1256     /* TODO - DP2.0 HW: calculate requested_sym_clk for UHBR rates */
1257     pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
1258         LINK_RATE_REF_FREQ_IN_KHZ;
1259     pixel_clk_params->flags.ENABLE_SS = 0;
1260     pixel_clk_params->color_depth =
1261         stream->timing.display_color_depth;
1262     pixel_clk_params->flags.DISPLAY_BLANKED = 1;
1263     pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding;
1264 
1265     if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
1266         pixel_clk_params->color_depth = COLOR_DEPTH_888;
1267 
1268     if (opp_cnt == 4)
1269         pixel_clk_params->requested_pix_clk_100hz /= 4;
1270     else if (optc2_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2)
1271         pixel_clk_params->requested_pix_clk_100hz /= 2;
1272     else if (hws->funcs.is_dp_dig_pixel_rate_div_policy) {
1273         if (hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx))
1274             pixel_clk_params->requested_pix_clk_100hz /= 2;
1275     }
1276 
1277     if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
1278         pixel_clk_params->requested_pix_clk_100hz *= 2;
1279 
1280 }
1281 
1282 static void build_clamping_params(struct dc_stream_state *stream)
1283 {
1284     stream->clamping.clamping_level = CLAMPING_FULL_RANGE;
1285     stream->clamping.c_depth = stream->timing.display_color_depth;
1286     stream->clamping.pixel_encoding = stream->timing.pixel_encoding;
1287 }
1288 
1289 static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
1290 {
1291 
1292     get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params);
1293 
1294     pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
1295         pipe_ctx->clock_source,
1296         &pipe_ctx->stream_res.pix_clk_params,
1297         &pipe_ctx->pll_settings);
1298 
1299     pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding;
1300 
1301     resource_build_bit_depth_reduction_params(pipe_ctx->stream,
1302                     &pipe_ctx->stream->bit_depth_params);
1303     build_clamping_params(pipe_ctx->stream);
1304 
1305     return DC_OK;
1306 }
1307 
1308 enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream)
1309 {
1310     enum dc_status status = DC_OK;
1311     struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream);
1312 
1313     if (!pipe_ctx)
1314         return DC_ERROR_UNEXPECTED;
1315 
1316 
1317     status = build_pipe_hw_param(pipe_ctx);
1318 
1319     return status;
1320 }
1321 
1322 
1323 void dcn20_acquire_dsc(const struct dc *dc,
1324             struct resource_context *res_ctx,
1325             struct display_stream_compressor **dsc,
1326             int pipe_idx)
1327 {
1328     int i;
1329     const struct resource_pool *pool = dc->res_pool;
1330     struct display_stream_compressor *dsc_old = dc->current_state->res_ctx.pipe_ctx[pipe_idx].stream_res.dsc;
1331 
1332     ASSERT(*dsc == NULL); /* If this ASSERT fails, dsc was not released properly */
1333     *dsc = NULL;
1334 
1335     /* Always do 1-to-1 mapping when number of DSCs is same as number of pipes */
1336     if (pool->res_cap->num_dsc == pool->res_cap->num_opp) {
1337         *dsc = pool->dscs[pipe_idx];
1338         res_ctx->is_dsc_acquired[pipe_idx] = true;
1339         return;
1340     }
1341 
1342     /* Return old DSC to avoid the need for re-programming */
1343     if (dsc_old && !res_ctx->is_dsc_acquired[dsc_old->inst]) {
1344         *dsc = dsc_old;
1345         res_ctx->is_dsc_acquired[dsc_old->inst] = true;
1346         return ;
1347     }
1348 
1349     /* Find first free DSC */
1350     for (i = 0; i < pool->res_cap->num_dsc; i++)
1351         if (!res_ctx->is_dsc_acquired[i]) {
1352             *dsc = pool->dscs[i];
1353             res_ctx->is_dsc_acquired[i] = true;
1354             break;
1355         }
1356 }
1357 
1358 void dcn20_release_dsc(struct resource_context *res_ctx,
1359             const struct resource_pool *pool,
1360             struct display_stream_compressor **dsc)
1361 {
1362     int i;
1363 
1364     for (i = 0; i < pool->res_cap->num_dsc; i++)
1365         if (pool->dscs[i] == *dsc) {
1366             res_ctx->is_dsc_acquired[i] = false;
1367             *dsc = NULL;
1368             break;
1369         }
1370 }
1371 
1372 
1373 
1374 enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc,
1375         struct dc_state *dc_ctx,
1376         struct dc_stream_state *dc_stream)
1377 {
1378     enum dc_status result = DC_OK;
1379     int i;
1380 
1381     /* Get a DSC if required and available */
1382     for (i = 0; i < dc->res_pool->pipe_count; i++) {
1383         struct pipe_ctx *pipe_ctx = &dc_ctx->res_ctx.pipe_ctx[i];
1384 
1385         if (pipe_ctx->stream != dc_stream)
1386             continue;
1387 
1388         if (pipe_ctx->stream_res.dsc)
1389             continue;
1390 
1391         dcn20_acquire_dsc(dc, &dc_ctx->res_ctx, &pipe_ctx->stream_res.dsc, i);
1392 
1393         /* The number of DSCs can be less than the number of pipes */
1394         if (!pipe_ctx->stream_res.dsc) {
1395             result = DC_NO_DSC_RESOURCE;
1396         }
1397 
1398         break;
1399     }
1400 
1401     return result;
1402 }
1403 
1404 
1405 static enum dc_status remove_dsc_from_stream_resource(struct dc *dc,
1406         struct dc_state *new_ctx,
1407         struct dc_stream_state *dc_stream)
1408 {
1409     struct pipe_ctx *pipe_ctx = NULL;
1410     int i;
1411 
1412     for (i = 0; i < MAX_PIPES; i++) {
1413         if (new_ctx->res_ctx.pipe_ctx[i].stream == dc_stream && !new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
1414             pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
1415 
1416             if (pipe_ctx->stream_res.dsc)
1417                 dcn20_release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc);
1418         }
1419     }
1420 
1421     if (!pipe_ctx)
1422         return DC_ERROR_UNEXPECTED;
1423     else
1424         return DC_OK;
1425 }
1426 
1427 
1428 enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream)
1429 {
1430     enum dc_status result = DC_ERROR_UNEXPECTED;
1431 
1432     result = resource_map_pool_resources(dc, new_ctx, dc_stream);
1433 
1434     if (result == DC_OK)
1435         result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream);
1436 
1437     /* Get a DSC if required and available */
1438     if (result == DC_OK && dc_stream->timing.flags.DSC)
1439         result = dcn20_add_dsc_to_stream_resource(dc, new_ctx, dc_stream);
1440 
1441     if (result == DC_OK)
1442         result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream);
1443 
1444     return result;
1445 }
1446 
1447 
1448 enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream)
1449 {
1450     enum dc_status result = DC_OK;
1451 
1452     result = remove_dsc_from_stream_resource(dc, new_ctx, dc_stream);
1453 
1454     return result;
1455 }
1456 
1457 bool dcn20_split_stream_for_odm(
1458         const struct dc *dc,
1459         struct resource_context *res_ctx,
1460         struct pipe_ctx *prev_odm_pipe,
1461         struct pipe_ctx *next_odm_pipe)
1462 {
1463     int pipe_idx = next_odm_pipe->pipe_idx;
1464     const struct resource_pool *pool = dc->res_pool;
1465 
1466     *next_odm_pipe = *prev_odm_pipe;
1467 
1468     next_odm_pipe->pipe_idx = pipe_idx;
1469     next_odm_pipe->plane_res.mi = pool->mis[next_odm_pipe->pipe_idx];
1470     next_odm_pipe->plane_res.hubp = pool->hubps[next_odm_pipe->pipe_idx];
1471     next_odm_pipe->plane_res.ipp = pool->ipps[next_odm_pipe->pipe_idx];
1472     next_odm_pipe->plane_res.xfm = pool->transforms[next_odm_pipe->pipe_idx];
1473     next_odm_pipe->plane_res.dpp = pool->dpps[next_odm_pipe->pipe_idx];
1474     next_odm_pipe->plane_res.mpcc_inst = pool->dpps[next_odm_pipe->pipe_idx]->inst;
1475     next_odm_pipe->stream_res.dsc = NULL;
1476     if (prev_odm_pipe->next_odm_pipe && prev_odm_pipe->next_odm_pipe != next_odm_pipe) {
1477         next_odm_pipe->next_odm_pipe = prev_odm_pipe->next_odm_pipe;
1478         next_odm_pipe->next_odm_pipe->prev_odm_pipe = next_odm_pipe;
1479     }
1480     if (prev_odm_pipe->top_pipe && prev_odm_pipe->top_pipe->next_odm_pipe) {
1481         prev_odm_pipe->top_pipe->next_odm_pipe->bottom_pipe = next_odm_pipe;
1482         next_odm_pipe->top_pipe = prev_odm_pipe->top_pipe->next_odm_pipe;
1483     }
1484     if (prev_odm_pipe->bottom_pipe && prev_odm_pipe->bottom_pipe->next_odm_pipe) {
1485         prev_odm_pipe->bottom_pipe->next_odm_pipe->top_pipe = next_odm_pipe;
1486         next_odm_pipe->bottom_pipe = prev_odm_pipe->bottom_pipe->next_odm_pipe;
1487     }
1488     prev_odm_pipe->next_odm_pipe = next_odm_pipe;
1489     next_odm_pipe->prev_odm_pipe = prev_odm_pipe;
1490 
1491     if (prev_odm_pipe->plane_state) {
1492         struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data;
1493         int new_width;
1494 
1495         /* HACTIVE halved for odm combine */
1496         sd->h_active /= 2;
1497         /* Calculate new vp and recout for left pipe */
1498         /* Need at least 16 pixels width per side */
1499         if (sd->recout.x + 16 >= sd->h_active)
1500             return false;
1501         new_width = sd->h_active - sd->recout.x;
1502         sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
1503                 sd->ratios.horz, sd->recout.width - new_width));
1504         sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
1505                 sd->ratios.horz_c, sd->recout.width - new_width));
1506         sd->recout.width = new_width;
1507 
1508         /* Calculate new vp and recout for right pipe */
1509         sd = &next_odm_pipe->plane_res.scl_data;
1510         /* HACTIVE halved for odm combine */
1511         sd->h_active /= 2;
1512         /* Need at least 16 pixels width per side */
1513         if (new_width <= 16)
1514             return false;
1515         new_width = sd->recout.width + sd->recout.x - sd->h_active;
1516         sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
1517                 sd->ratios.horz, sd->recout.width - new_width));
1518         sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
1519                 sd->ratios.horz_c, sd->recout.width - new_width));
1520         sd->recout.width = new_width;
1521         sd->viewport.x += dc_fixpt_floor(dc_fixpt_mul_int(
1522                 sd->ratios.horz, sd->h_active - sd->recout.x));
1523         sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int(
1524                 sd->ratios.horz_c, sd->h_active - sd->recout.x));
1525         sd->recout.x = 0;
1526     }
1527     if (!next_odm_pipe->top_pipe)
1528         next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
1529     else
1530         next_odm_pipe->stream_res.opp = next_odm_pipe->top_pipe->stream_res.opp;
1531     if (next_odm_pipe->stream->timing.flags.DSC == 1 && !next_odm_pipe->top_pipe) {
1532         dcn20_acquire_dsc(dc, res_ctx, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx);
1533         ASSERT(next_odm_pipe->stream_res.dsc);
1534         if (next_odm_pipe->stream_res.dsc == NULL)
1535             return false;
1536     }
1537 
1538     return true;
1539 }
1540 
1541 void dcn20_split_stream_for_mpc(
1542         struct resource_context *res_ctx,
1543         const struct resource_pool *pool,
1544         struct pipe_ctx *primary_pipe,
1545         struct pipe_ctx *secondary_pipe)
1546 {
1547     int pipe_idx = secondary_pipe->pipe_idx;
1548     struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe;
1549 
1550     *secondary_pipe = *primary_pipe;
1551     secondary_pipe->bottom_pipe = sec_bot_pipe;
1552 
1553     secondary_pipe->pipe_idx = pipe_idx;
1554     secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx];
1555     secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx];
1556     secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx];
1557     secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx];
1558     secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx];
1559     secondary_pipe->plane_res.mpcc_inst = pool->dpps[secondary_pipe->pipe_idx]->inst;
1560     secondary_pipe->stream_res.dsc = NULL;
1561     if (primary_pipe->bottom_pipe && primary_pipe->bottom_pipe != secondary_pipe) {
1562         ASSERT(!secondary_pipe->bottom_pipe);
1563         secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe;
1564         secondary_pipe->bottom_pipe->top_pipe = secondary_pipe;
1565     }
1566     primary_pipe->bottom_pipe = secondary_pipe;
1567     secondary_pipe->top_pipe = primary_pipe;
1568 
1569     ASSERT(primary_pipe->plane_state);
1570 }
1571 
1572 unsigned int dcn20_calc_max_scaled_time(
1573         unsigned int time_per_pixel,
1574         enum mmhubbub_wbif_mode mode,
1575         unsigned int urgent_watermark)
1576 {
1577     unsigned int time_per_byte = 0;
1578     unsigned int total_y_free_entry = 0x200; /* two memory piece for luma */
1579     unsigned int total_c_free_entry = 0x140; /* two memory piece for chroma */
1580     unsigned int small_free_entry, max_free_entry;
1581     unsigned int buf_lh_capability;
1582     unsigned int max_scaled_time;
1583 
1584     if (mode == PACKED_444) /* packed mode */
1585         time_per_byte = time_per_pixel/4;
1586     else if (mode == PLANAR_420_8BPC)
1587         time_per_byte  = time_per_pixel;
1588     else if (mode == PLANAR_420_10BPC) /* p010 */
1589         time_per_byte  = time_per_pixel * 819/1024;
1590 
1591     if (time_per_byte == 0)
1592         time_per_byte = 1;
1593 
1594     small_free_entry  = (total_y_free_entry > total_c_free_entry) ? total_c_free_entry : total_y_free_entry;
1595     max_free_entry    = (mode == PACKED_444) ? total_y_free_entry + total_c_free_entry : small_free_entry;
1596     buf_lh_capability = max_free_entry*time_per_byte*32/16; /* there is 4bit fraction */
1597     max_scaled_time   = buf_lh_capability - urgent_watermark;
1598     return max_scaled_time;
1599 }
1600 
1601 void dcn20_set_mcif_arb_params(
1602         struct dc *dc,
1603         struct dc_state *context,
1604         display_e2e_pipe_params_st *pipes,
1605         int pipe_cnt)
1606 {
1607     enum mmhubbub_wbif_mode wbif_mode;
1608     struct mcif_arb_params *wb_arb_params;
1609     int i, j, dwb_pipe;
1610 
1611     /* Writeback MCIF_WB arbitration parameters */
1612     dwb_pipe = 0;
1613     for (i = 0; i < dc->res_pool->pipe_count; i++) {
1614 
1615         if (!context->res_ctx.pipe_ctx[i].stream)
1616             continue;
1617 
1618         for (j = 0; j < MAX_DWB_PIPES; j++) {
1619             if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].wb_enabled == false)
1620                 continue;
1621 
1622             //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params;
1623             wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe];
1624 
1625             if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.out_format == dwb_scaler_mode_yuv420) {
1626                 if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
1627                     wbif_mode = PLANAR_420_8BPC;
1628                 else
1629                     wbif_mode = PLANAR_420_10BPC;
1630             } else
1631                 wbif_mode = PACKED_444;
1632 
1633             DC_FP_START();
1634             dcn20_fpu_set_wb_arb_params(wb_arb_params, context, pipes, pipe_cnt, i);
1635             DC_FP_END();
1636 
1637             wb_arb_params->slice_lines = 32;
1638             wb_arb_params->arbitration_slice = 2;
1639             wb_arb_params->max_scaled_time = dcn20_calc_max_scaled_time(wb_arb_params->time_per_pixel,
1640                 wbif_mode,
1641                 wb_arb_params->cli_watermark[0]); /* assume 4 watermark sets have the same value */
1642 
1643             dwb_pipe++;
1644 
1645             if (dwb_pipe >= MAX_DWB_PIPES)
1646                 return;
1647         }
1648         if (dwb_pipe >= MAX_DWB_PIPES)
1649             return;
1650     }
1651 }
1652 
1653 bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx)
1654 {
1655     int i;
1656 
1657     /* Validate DSC config, dsc count validation is already done */
1658     for (i = 0; i < dc->res_pool->pipe_count; i++) {
1659         struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
1660         struct dc_stream_state *stream = pipe_ctx->stream;
1661         struct dsc_config dsc_cfg;
1662         struct pipe_ctx *odm_pipe;
1663         int opp_cnt = 1;
1664 
1665         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
1666             opp_cnt++;
1667 
1668         /* Only need to validate top pipe */
1669         if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe || !stream || !stream->timing.flags.DSC)
1670             continue;
1671 
1672         dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left
1673                 + stream->timing.h_border_right) / opp_cnt;
1674         dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top
1675                 + stream->timing.v_border_bottom;
1676         dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
1677         dsc_cfg.color_depth = stream->timing.display_color_depth;
1678         dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
1679         dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
1680         dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
1681 
1682         if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
1683             return false;
1684     }
1685     return true;
1686 }
1687 
1688 struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
1689         struct resource_context *res_ctx,
1690         const struct resource_pool *pool,
1691         const struct pipe_ctx *primary_pipe)
1692 {
1693     struct pipe_ctx *secondary_pipe = NULL;
1694 
1695     if (dc && primary_pipe) {
1696         int j;
1697         int preferred_pipe_idx = 0;
1698 
1699         /* first check the prev dc state:
1700          * if this primary pipe has a bottom pipe in prev. state
1701          * and if the bottom pipe is still available (which it should be),
1702          * pick that pipe as secondary
1703          * Same logic applies for ODM pipes
1704          */
1705         if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
1706             preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
1707             if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
1708                 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
1709                 secondary_pipe->pipe_idx = preferred_pipe_idx;
1710             }
1711         }
1712         if (secondary_pipe == NULL &&
1713                 dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
1714             preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
1715             if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
1716                 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
1717                 secondary_pipe->pipe_idx = preferred_pipe_idx;
1718             }
1719         }
1720 
1721         /*
1722          * if this primary pipe does not have a bottom pipe in prev. state
1723          * start backward and find a pipe that did not used to be a bottom pipe in
1724          * prev. dc state. This way we make sure we keep the same assignment as
1725          * last state and will not have to reprogram every pipe
1726          */
1727         if (secondary_pipe == NULL) {
1728             for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
1729                 if (dc->current_state->res_ctx.pipe_ctx[j].top_pipe == NULL
1730                         && dc->current_state->res_ctx.pipe_ctx[j].prev_odm_pipe == NULL) {
1731                     preferred_pipe_idx = j;
1732 
1733                     if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
1734                         secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
1735                         secondary_pipe->pipe_idx = preferred_pipe_idx;
1736                         break;
1737                     }
1738                 }
1739             }
1740         }
1741         /*
1742          * We should never hit this assert unless assignments are shuffled around
1743          * if this happens we will prob. hit a vsync tdr
1744          */
1745         ASSERT(secondary_pipe);
1746         /*
1747          * search backwards for the second pipe to keep pipe
1748          * assignment more consistent
1749          */
1750         if (secondary_pipe == NULL) {
1751             for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
1752                 preferred_pipe_idx = j;
1753 
1754                 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
1755                     secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
1756                     secondary_pipe->pipe_idx = preferred_pipe_idx;
1757                     break;
1758                 }
1759             }
1760         }
1761     }
1762 
1763     return secondary_pipe;
1764 }
1765 
1766 void dcn20_merge_pipes_for_validate(
1767         struct dc *dc,
1768         struct dc_state *context)
1769 {
1770     int i;
1771 
1772     /* merge previously split odm pipes since mode support needs to make the decision */
1773     for (i = 0; i < dc->res_pool->pipe_count; i++) {
1774         struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1775         struct pipe_ctx *odm_pipe = pipe->next_odm_pipe;
1776 
1777         if (pipe->prev_odm_pipe)
1778             continue;
1779 
1780         pipe->next_odm_pipe = NULL;
1781         while (odm_pipe) {
1782             struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
1783 
1784             odm_pipe->plane_state = NULL;
1785             odm_pipe->stream = NULL;
1786             odm_pipe->top_pipe = NULL;
1787             odm_pipe->bottom_pipe = NULL;
1788             odm_pipe->prev_odm_pipe = NULL;
1789             odm_pipe->next_odm_pipe = NULL;
1790             if (odm_pipe->stream_res.dsc)
1791                 dcn20_release_dsc(&context->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc);
1792             /* Clear plane_res and stream_res */
1793             memset(&odm_pipe->plane_res, 0, sizeof(odm_pipe->plane_res));
1794             memset(&odm_pipe->stream_res, 0, sizeof(odm_pipe->stream_res));
1795             odm_pipe = next_odm_pipe;
1796         }
1797         if (pipe->plane_state)
1798             resource_build_scaling_params(pipe);
1799     }
1800 
1801     /* merge previously mpc split pipes since mode support needs to make the decision */
1802     for (i = 0; i < dc->res_pool->pipe_count; i++) {
1803         struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1804         struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe;
1805 
1806         if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state)
1807             continue;
1808 
1809         pipe->bottom_pipe = hsplit_pipe->bottom_pipe;
1810         if (hsplit_pipe->bottom_pipe)
1811             hsplit_pipe->bottom_pipe->top_pipe = pipe;
1812         hsplit_pipe->plane_state = NULL;
1813         hsplit_pipe->stream = NULL;
1814         hsplit_pipe->top_pipe = NULL;
1815         hsplit_pipe->bottom_pipe = NULL;
1816 
1817         /* Clear plane_res and stream_res */
1818         memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res));
1819         memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res));
1820         if (pipe->plane_state)
1821             resource_build_scaling_params(pipe);
1822     }
1823 }
1824 
1825 int dcn20_validate_apply_pipe_split_flags(
1826         struct dc *dc,
1827         struct dc_state *context,
1828         int vlevel,
1829         int *split,
1830         bool *merge)
1831 {
1832     int i, pipe_idx, vlevel_split;
1833     int plane_count = 0;
1834     bool force_split = false;
1835     bool avoid_split = dc->debug.pipe_split_policy == MPC_SPLIT_AVOID;
1836     struct vba_vars_st *v = &context->bw_ctx.dml.vba;
1837     int max_mpc_comb = v->maxMpcComb;
1838 
1839     if (context->stream_count > 1) {
1840         if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP)
1841             avoid_split = true;
1842     } else if (dc->debug.force_single_disp_pipe_split)
1843             force_split = true;
1844 
1845     for (i = 0; i < dc->res_pool->pipe_count; i++) {
1846         struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1847 
1848         /**
1849          * Workaround for avoiding pipe-split in cases where we'd split
1850          * planes that are too small, resulting in splits that aren't
1851          * valid for the scaler.
1852          */
1853         if (pipe->plane_state &&
1854             (pipe->plane_state->dst_rect.width <= 16 ||
1855              pipe->plane_state->dst_rect.height <= 16 ||
1856              pipe->plane_state->src_rect.width <= 16 ||
1857              pipe->plane_state->src_rect.height <= 16))
1858             avoid_split = true;
1859 
1860         /* TODO: fix dc bugs and remove this split threshold thing */
1861         if (pipe->stream && !pipe->prev_odm_pipe &&
1862                 (!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state))
1863             ++plane_count;
1864     }
1865     if (plane_count > dc->res_pool->pipe_count / 2)
1866         avoid_split = true;
1867 
1868     /* W/A: Mode timing with borders may not work well with pipe split, avoid for this corner case */
1869     for (i = 0; i < dc->res_pool->pipe_count; i++) {
1870         struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1871         struct dc_crtc_timing timing;
1872 
1873         if (!pipe->stream)
1874             continue;
1875         else {
1876             timing = pipe->stream->timing;
1877             if (timing.h_border_left + timing.h_border_right
1878                     + timing.v_border_top + timing.v_border_bottom > 0) {
1879                 avoid_split = true;
1880                 break;
1881             }
1882         }
1883     }
1884 
1885     /* Avoid split loop looks for lowest voltage level that allows most unsplit pipes possible */
1886     if (avoid_split) {
1887         for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
1888             if (!context->res_ctx.pipe_ctx[i].stream)
1889                 continue;
1890 
1891             for (vlevel_split = vlevel; vlevel <= context->bw_ctx.dml.soc.num_states; vlevel++)
1892                 if (v->NoOfDPP[vlevel][0][pipe_idx] == 1 &&
1893                         v->ModeSupport[vlevel][0])
1894                     break;
1895             /* Impossible to not split this pipe */
1896             if (vlevel > context->bw_ctx.dml.soc.num_states)
1897                 vlevel = vlevel_split;
1898             else
1899                 max_mpc_comb = 0;
1900             pipe_idx++;
1901         }
1902         v->maxMpcComb = max_mpc_comb;
1903     }
1904 
1905     /* Split loop sets which pipe should be split based on dml outputs and dc flags */
1906     for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
1907         struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1908         int pipe_plane = v->pipe_plane[pipe_idx];
1909         bool split4mpc = context->stream_count == 1 && plane_count == 1
1910                 && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4;
1911 
1912         if (!context->res_ctx.pipe_ctx[i].stream)
1913             continue;
1914 
1915         if (split4mpc || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 4)
1916             split[i] = 4;
1917         else if (force_split || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 2)
1918                 split[i] = 2;
1919 
1920         if ((pipe->stream->view_format ==
1921                 VIEW_3D_FORMAT_SIDE_BY_SIDE ||
1922                 pipe->stream->view_format ==
1923                 VIEW_3D_FORMAT_TOP_AND_BOTTOM) &&
1924                 (pipe->stream->timing.timing_3d_format ==
1925                 TIMING_3D_FORMAT_TOP_AND_BOTTOM ||
1926                  pipe->stream->timing.timing_3d_format ==
1927                 TIMING_3D_FORMAT_SIDE_BY_SIDE))
1928             split[i] = 2;
1929         if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) {
1930             split[i] = 2;
1931             v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_2to1;
1932         }
1933         if (dc->debug.force_odm_combine_4to1 & (1 << pipe->stream_res.tg->inst)) {
1934             split[i] = 4;
1935             v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_4to1;
1936         }
1937         /*420 format workaround*/
1938         if (pipe->stream->timing.h_addressable > 7680 &&
1939                 pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
1940             split[i] = 4;
1941         }
1942         v->ODMCombineEnabled[pipe_plane] =
1943             v->ODMCombineEnablePerState[vlevel][pipe_plane];
1944 
1945         if (v->ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) {
1946             if (get_num_mpc_splits(pipe) == 1) {
1947                 /*If need split for mpc but 2 way split already*/
1948                 if (split[i] == 4)
1949                     split[i] = 2; /* 2 -> 4 MPC */
1950                 else if (split[i] == 2)
1951                     split[i] = 0; /* 2 -> 2 MPC */
1952                 else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state)
1953                     merge[i] = true; /* 2 -> 1 MPC */
1954             } else if (get_num_mpc_splits(pipe) == 3) {
1955                 /*If need split for mpc but 4 way split already*/
1956                 if (split[i] == 2 && ((pipe->top_pipe && !pipe->top_pipe->top_pipe)
1957                         || !pipe->bottom_pipe)) {
1958                     merge[i] = true; /* 4 -> 2 MPC */
1959                 } else if (split[i] == 0 && pipe->top_pipe &&
1960                         pipe->top_pipe->plane_state == pipe->plane_state)
1961                     merge[i] = true; /* 4 -> 1 MPC */
1962                 split[i] = 0;
1963             } else if (get_num_odm_splits(pipe)) {
1964                 /* ODM -> MPC transition */
1965                 if (pipe->prev_odm_pipe) {
1966                     split[i] = 0;
1967                     merge[i] = true;
1968                 }
1969             }
1970         } else {
1971             if (get_num_odm_splits(pipe) == 1) {
1972                 /*If need split for odm but 2 way split already*/
1973                 if (split[i] == 4)
1974                     split[i] = 2; /* 2 -> 4 ODM */
1975                 else if (split[i] == 2)
1976                     split[i] = 0; /* 2 -> 2 ODM */
1977                 else if (pipe->prev_odm_pipe) {
1978                     ASSERT(0); /* NOT expected yet */
1979                     merge[i] = true; /* exit ODM */
1980                 }
1981             } else if (get_num_odm_splits(pipe) == 3) {
1982                 /*If need split for odm but 4 way split already*/
1983                 if (split[i] == 2 && ((pipe->prev_odm_pipe && !pipe->prev_odm_pipe->prev_odm_pipe)
1984                         || !pipe->next_odm_pipe)) {
1985                     merge[i] = true; /* 4 -> 2 ODM */
1986                 } else if (split[i] == 0 && pipe->prev_odm_pipe) {
1987                     ASSERT(0); /* NOT expected yet */
1988                     merge[i] = true; /* exit ODM */
1989                 }
1990                 split[i] = 0;
1991             } else if (get_num_mpc_splits(pipe)) {
1992                 /* MPC -> ODM transition */
1993                 ASSERT(0); /* NOT expected yet */
1994                 if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
1995                     split[i] = 0;
1996                     merge[i] = true;
1997                 }
1998             }
1999         }
2000 
2001         /* Adjust dppclk when split is forced, do not bother with dispclk */
2002         if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] == 1) {
2003             DC_FP_START();
2004             dcn20_fpu_adjust_dppclk(v, vlevel, max_mpc_comb, pipe_idx, false);
2005             DC_FP_END();
2006         }
2007         pipe_idx++;
2008     }
2009 
2010     return vlevel;
2011 }
2012 
2013 bool dcn20_fast_validate_bw(
2014         struct dc *dc,
2015         struct dc_state *context,
2016         display_e2e_pipe_params_st *pipes,
2017         int *pipe_cnt_out,
2018         int *pipe_split_from,
2019         int *vlevel_out,
2020         bool fast_validate)
2021 {
2022     bool out = false;
2023     int split[MAX_PIPES] = { 0 };
2024     int pipe_cnt, i, pipe_idx, vlevel;
2025 
2026     ASSERT(pipes);
2027     if (!pipes)
2028         return false;
2029 
2030     dcn20_merge_pipes_for_validate(dc, context);
2031 
2032     DC_FP_START();
2033     pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
2034     DC_FP_END();
2035 
2036     *pipe_cnt_out = pipe_cnt;
2037 
2038     if (!pipe_cnt) {
2039         out = true;
2040         goto validate_out;
2041     }
2042 
2043     vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
2044 
2045     if (vlevel > context->bw_ctx.dml.soc.num_states)
2046         goto validate_fail;
2047 
2048     vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL);
2049 
2050     /*initialize pipe_just_split_from to invalid idx*/
2051     for (i = 0; i < MAX_PIPES; i++)
2052         pipe_split_from[i] = -1;
2053 
2054     for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {
2055         struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
2056         struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe;
2057 
2058         if (!pipe->stream || pipe_split_from[i] >= 0)
2059             continue;
2060 
2061         pipe_idx++;
2062 
2063         if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
2064             hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
2065             ASSERT(hsplit_pipe);
2066             if (!dcn20_split_stream_for_odm(
2067                     dc, &context->res_ctx,
2068                     pipe, hsplit_pipe))
2069                 goto validate_fail;
2070             pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
2071             dcn20_build_mapped_resource(dc, context, pipe->stream);
2072         }
2073 
2074         if (!pipe->plane_state)
2075             continue;
2076         /* Skip 2nd half of already split pipe */
2077         if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state)
2078             continue;
2079 
2080         /* We do not support mpo + odm at the moment */
2081         if (hsplit_pipe && hsplit_pipe->plane_state != pipe->plane_state
2082                 && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx])
2083             goto validate_fail;
2084 
2085         if (split[i] == 2) {
2086             if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) {
2087                 /* pipe not split previously needs split */
2088                 hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
2089                 ASSERT(hsplit_pipe);
2090                 if (!hsplit_pipe) {
2091                     DC_FP_START();
2092                     dcn20_fpu_adjust_dppclk(&context->bw_ctx.dml.vba, vlevel, context->bw_ctx.dml.vba.maxMpcComb, pipe_idx, true);
2093                     DC_FP_END();
2094                     continue;
2095                 }
2096                 if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
2097                     if (!dcn20_split_stream_for_odm(
2098                             dc, &context->res_ctx,
2099                             pipe, hsplit_pipe))
2100                         goto validate_fail;
2101                     dcn20_build_mapped_resource(dc, context, pipe->stream);
2102                 } else {
2103                     dcn20_split_stream_for_mpc(
2104                             &context->res_ctx, dc->res_pool,
2105                             pipe, hsplit_pipe);
2106                     resource_build_scaling_params(pipe);
2107                     resource_build_scaling_params(hsplit_pipe);
2108                 }
2109                 pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
2110             }
2111         } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) {
2112             /* merge should already have been done */
2113             ASSERT(0);
2114         }
2115     }
2116     /* Actual dsc count per stream dsc validation*/
2117     if (!dcn20_validate_dsc(dc, context)) {
2118         context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] =
2119                 DML_FAIL_DSC_VALIDATION_FAILURE;
2120         goto validate_fail;
2121     }
2122 
2123     *vlevel_out = vlevel;
2124 
2125     out = true;
2126     goto validate_out;
2127 
2128 validate_fail:
2129     out = false;
2130 
2131 validate_out:
2132     return out;
2133 }
2134 
2135 bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
2136         bool fast_validate)
2137 {
2138     bool voltage_supported;
2139     DC_FP_START();
2140     voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate);
2141     DC_FP_END();
2142     return voltage_supported;
2143 }
2144 
2145 struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer(
2146         struct dc_state *state,
2147         const struct resource_pool *pool,
2148         struct dc_stream_state *stream)
2149 {
2150     struct resource_context *res_ctx = &state->res_ctx;
2151     struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
2152     struct pipe_ctx *idle_pipe = find_idle_secondary_pipe(res_ctx, pool, head_pipe);
2153 
2154     if (!head_pipe)
2155         ASSERT(0);
2156 
2157     if (!idle_pipe)
2158         return NULL;
2159 
2160     idle_pipe->stream = head_pipe->stream;
2161     idle_pipe->stream_res.tg = head_pipe->stream_res.tg;
2162     idle_pipe->stream_res.opp = head_pipe->stream_res.opp;
2163 
2164     idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];
2165     idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx];
2166     idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx];
2167     idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst;
2168 
2169     return idle_pipe;
2170 }
2171 
2172 bool dcn20_get_dcc_compression_cap(const struct dc *dc,
2173         const struct dc_dcc_surface_param *input,
2174         struct dc_surface_dcc_cap *output)
2175 {
2176     return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
2177             dc->res_pool->hubbub,
2178             input,
2179             output);
2180 }
2181 
2182 static void dcn20_destroy_resource_pool(struct resource_pool **pool)
2183 {
2184     struct dcn20_resource_pool *dcn20_pool = TO_DCN20_RES_POOL(*pool);
2185 
2186     dcn20_resource_destruct(dcn20_pool);
2187     kfree(dcn20_pool);
2188     *pool = NULL;
2189 }
2190 
2191 
2192 static struct dc_cap_funcs cap_funcs = {
2193     .get_dcc_compression_cap = dcn20_get_dcc_compression_cap
2194 };
2195 
2196 
2197 enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state)
2198 {
2199     enum surface_pixel_format surf_pix_format = plane_state->format;
2200     unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format);
2201 
2202     enum swizzle_mode_values swizzle = DC_SW_LINEAR;
2203 
2204     if (bpp == 64)
2205         swizzle = DC_SW_64KB_D;
2206     else
2207         swizzle = DC_SW_64KB_S;
2208 
2209     plane_state->tiling_info.gfx9.swizzle = swizzle;
2210     return DC_OK;
2211 }
2212 
2213 static const struct resource_funcs dcn20_res_pool_funcs = {
2214     .destroy = dcn20_destroy_resource_pool,
2215     .link_enc_create = dcn20_link_encoder_create,
2216     .panel_cntl_create = dcn20_panel_cntl_create,
2217     .validate_bandwidth = dcn20_validate_bandwidth,
2218     .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
2219     .add_stream_to_ctx = dcn20_add_stream_to_ctx,
2220     .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
2221     .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
2222     .populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context,
2223     .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
2224     .set_mcif_arb_params = dcn20_set_mcif_arb_params,
2225     .populate_dml_pipes = dcn20_populate_dml_pipes_from_context,
2226     .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link
2227 };
2228 
2229 bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
2230 {
2231     int i;
2232     uint32_t pipe_count = pool->res_cap->num_dwb;
2233 
2234     for (i = 0; i < pipe_count; i++) {
2235         struct dcn20_dwbc *dwbc20 = kzalloc(sizeof(struct dcn20_dwbc),
2236                             GFP_KERNEL);
2237 
2238         if (!dwbc20) {
2239             dm_error("DC: failed to create dwbc20!\n");
2240             return false;
2241         }
2242         dcn20_dwbc_construct(dwbc20, ctx,
2243                 &dwbc20_regs[i],
2244                 &dwbc20_shift,
2245                 &dwbc20_mask,
2246                 i);
2247         pool->dwbc[i] = &dwbc20->base;
2248     }
2249     return true;
2250 }
2251 
2252 bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
2253 {
2254     int i;
2255     uint32_t pipe_count = pool->res_cap->num_dwb;
2256 
2257     ASSERT(pipe_count > 0);
2258 
2259     for (i = 0; i < pipe_count; i++) {
2260         struct dcn20_mmhubbub *mcif_wb20 = kzalloc(sizeof(struct dcn20_mmhubbub),
2261                             GFP_KERNEL);
2262 
2263         if (!mcif_wb20) {
2264             dm_error("DC: failed to create mcif_wb20!\n");
2265             return false;
2266         }
2267 
2268         dcn20_mmhubbub_construct(mcif_wb20, ctx,
2269                 &mcif_wb20_regs[i],
2270                 &mcif_wb20_shift,
2271                 &mcif_wb20_mask,
2272                 i);
2273 
2274         pool->mcif_wb[i] = &mcif_wb20->base;
2275     }
2276     return true;
2277 }
2278 
2279 static struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx)
2280 {
2281     struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_ATOMIC);
2282 
2283     if (!pp_smu)
2284         return pp_smu;
2285 
2286     dm_pp_get_funcs(ctx, pp_smu);
2287 
2288     if (pp_smu->ctx.ver != PP_SMU_VER_NV)
2289         pp_smu = memset(pp_smu, 0, sizeof(struct pp_smu_funcs));
2290 
2291     return pp_smu;
2292 }
2293 
2294 static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu)
2295 {
2296     if (pp_smu && *pp_smu) {
2297         kfree(*pp_smu);
2298         *pp_smu = NULL;
2299     }
2300 }
2301 
2302 static struct _vcs_dpi_soc_bounding_box_st *get_asic_rev_soc_bb(
2303     uint32_t hw_internal_rev)
2304 {
2305     if (ASICREV_IS_NAVI14_M(hw_internal_rev))
2306         return &dcn2_0_nv14_soc;
2307 
2308     if (ASICREV_IS_NAVI12_P(hw_internal_rev))
2309         return &dcn2_0_nv12_soc;
2310 
2311     return &dcn2_0_soc;
2312 }
2313 
2314 static struct _vcs_dpi_ip_params_st *get_asic_rev_ip_params(
2315     uint32_t hw_internal_rev)
2316 {
2317     /* NV14 */
2318     if (ASICREV_IS_NAVI14_M(hw_internal_rev))
2319         return &dcn2_0_nv14_ip;
2320 
2321     /* NV12 and NV10 */
2322     return &dcn2_0_ip;
2323 }
2324 
2325 static enum dml_project get_dml_project_version(uint32_t hw_internal_rev)
2326 {
2327     return DML_PROJECT_NAVI10v2;
2328 }
2329 
2330 static bool init_soc_bounding_box(struct dc *dc,
2331                   struct dcn20_resource_pool *pool)
2332 {
2333     struct _vcs_dpi_soc_bounding_box_st *loaded_bb =
2334             get_asic_rev_soc_bb(dc->ctx->asic_id.hw_internal_rev);
2335     struct _vcs_dpi_ip_params_st *loaded_ip =
2336             get_asic_rev_ip_params(dc->ctx->asic_id.hw_internal_rev);
2337 
2338     DC_LOGGER_INIT(dc->ctx->logger);
2339 
2340     if (pool->base.pp_smu) {
2341         struct pp_smu_nv_clock_table max_clocks = {0};
2342         unsigned int uclk_states[8] = {0};
2343         unsigned int num_states = 0;
2344         enum pp_smu_status status;
2345         bool clock_limits_available = false;
2346         bool uclk_states_available = false;
2347 
2348         if (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) {
2349             status = (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states)
2350                 (&pool->base.pp_smu->nv_funcs.pp_smu, uclk_states, &num_states);
2351 
2352             uclk_states_available = (status == PP_SMU_RESULT_OK);
2353         }
2354 
2355         if (pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) {
2356             status = (*pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks)
2357                     (&pool->base.pp_smu->nv_funcs.pp_smu, &max_clocks);
2358             /* SMU cannot set DCF clock to anything equal to or higher than SOC clock
2359              */
2360             if (max_clocks.dcfClockInKhz >= max_clocks.socClockInKhz)
2361                 max_clocks.dcfClockInKhz = max_clocks.socClockInKhz - 1000;
2362             clock_limits_available = (status == PP_SMU_RESULT_OK);
2363         }
2364 
2365         if (clock_limits_available && uclk_states_available && num_states) {
2366             DC_FP_START();
2367             dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states);
2368             DC_FP_END();
2369         } else if (clock_limits_available) {
2370             DC_FP_START();
2371             dcn20_cap_soc_clocks(loaded_bb, max_clocks);
2372             DC_FP_END();
2373         }
2374     }
2375 
2376     loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
2377     loaded_ip->max_num_dpp = pool->base.pipe_count;
2378     DC_FP_START();
2379     dcn20_patch_bounding_box(dc, loaded_bb);
2380     DC_FP_END();
2381     return true;
2382 }
2383 
2384 static bool dcn20_resource_construct(
2385     uint8_t num_virtual_links,
2386     struct dc *dc,
2387     struct dcn20_resource_pool *pool)
2388 {
2389     int i;
2390     struct dc_context *ctx = dc->ctx;
2391     struct irq_service_init_data init_data;
2392     struct ddc_service_init_data ddc_init_data = {0};
2393     struct _vcs_dpi_soc_bounding_box_st *loaded_bb =
2394             get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev);
2395     struct _vcs_dpi_ip_params_st *loaded_ip =
2396             get_asic_rev_ip_params(ctx->asic_id.hw_internal_rev);
2397     enum dml_project dml_project_version =
2398             get_dml_project_version(ctx->asic_id.hw_internal_rev);
2399 
2400     ctx->dc_bios->regs = &bios_regs;
2401     pool->base.funcs = &dcn20_res_pool_funcs;
2402 
2403     if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) {
2404         pool->base.res_cap = &res_cap_nv14;
2405         pool->base.pipe_count = 5;
2406         pool->base.mpcc_count = 5;
2407     } else {
2408         pool->base.res_cap = &res_cap_nv10;
2409         pool->base.pipe_count = 6;
2410         pool->base.mpcc_count = 6;
2411     }
2412     /*************************************************
2413      *  Resource + asic cap harcoding                *
2414      *************************************************/
2415     pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
2416 
2417     dc->caps.max_downscale_ratio = 200;
2418     dc->caps.i2c_speed_in_khz = 100;
2419     dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/
2420     dc->caps.max_cursor_size = 256;
2421     dc->caps.min_horizontal_blanking_period = 80;
2422     dc->caps.dmdata_alloc_size = 2048;
2423 
2424     dc->caps.max_slave_planes = 1;
2425     dc->caps.max_slave_yuv_planes = 1;
2426     dc->caps.max_slave_rgb_planes = 1;
2427     dc->caps.post_blend_color_processing = true;
2428     dc->caps.force_dp_tps4_for_cp2520 = true;
2429     dc->caps.extended_aux_timeout_support = true;
2430 
2431     /* Color pipeline capabilities */
2432     dc->caps.color.dpp.dcn_arch = 1;
2433     dc->caps.color.dpp.input_lut_shared = 0;
2434     dc->caps.color.dpp.icsc = 1;
2435     dc->caps.color.dpp.dgam_ram = 1;
2436     dc->caps.color.dpp.dgam_rom_caps.srgb = 1;
2437     dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;
2438     dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0;
2439     dc->caps.color.dpp.dgam_rom_caps.pq = 0;
2440     dc->caps.color.dpp.dgam_rom_caps.hlg = 0;
2441     dc->caps.color.dpp.post_csc = 0;
2442     dc->caps.color.dpp.gamma_corr = 0;
2443     dc->caps.color.dpp.dgam_rom_for_yuv = 1;
2444 
2445     dc->caps.color.dpp.hw_3d_lut = 1;
2446     dc->caps.color.dpp.ogam_ram = 1;
2447     // no OGAM ROM on DCN2, only MPC ROM
2448     dc->caps.color.dpp.ogam_rom_caps.srgb = 0;
2449     dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;
2450     dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;
2451     dc->caps.color.dpp.ogam_rom_caps.pq = 0;
2452     dc->caps.color.dpp.ogam_rom_caps.hlg = 0;
2453     dc->caps.color.dpp.ocsc = 0;
2454 
2455     dc->caps.color.mpc.gamut_remap = 0;
2456     dc->caps.color.mpc.num_3dluts = 0;
2457     dc->caps.color.mpc.shared_3d_lut = 0;
2458     dc->caps.color.mpc.ogam_ram = 1;
2459     dc->caps.color.mpc.ogam_rom_caps.srgb = 0;
2460     dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;
2461     dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;
2462     dc->caps.color.mpc.ogam_rom_caps.pq = 0;
2463     dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
2464     dc->caps.color.mpc.ocsc = 1;
2465 
2466     dc->caps.dp_hdmi21_pcon_support = true;
2467 
2468     if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) {
2469         dc->debug = debug_defaults_drv;
2470     } else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
2471         pool->base.pipe_count = 4;
2472         pool->base.mpcc_count = pool->base.pipe_count;
2473         dc->debug = debug_defaults_diags;
2474     } else {
2475         dc->debug = debug_defaults_diags;
2476     }
2477     //dcn2.0x
2478     dc->work_arounds.dedcn20_305_wa = true;
2479 
2480     // Init the vm_helper
2481     if (dc->vm_helper)
2482         vm_helper_init(dc->vm_helper, 16);
2483 
2484     /*************************************************
2485      *  Create resources                             *
2486      *************************************************/
2487 
2488     pool->base.clock_sources[DCN20_CLK_SRC_PLL0] =
2489             dcn20_clock_source_create(ctx, ctx->dc_bios,
2490                 CLOCK_SOURCE_COMBO_PHY_PLL0,
2491                 &clk_src_regs[0], false);
2492     pool->base.clock_sources[DCN20_CLK_SRC_PLL1] =
2493             dcn20_clock_source_create(ctx, ctx->dc_bios,
2494                 CLOCK_SOURCE_COMBO_PHY_PLL1,
2495                 &clk_src_regs[1], false);
2496     pool->base.clock_sources[DCN20_CLK_SRC_PLL2] =
2497             dcn20_clock_source_create(ctx, ctx->dc_bios,
2498                 CLOCK_SOURCE_COMBO_PHY_PLL2,
2499                 &clk_src_regs[2], false);
2500     pool->base.clock_sources[DCN20_CLK_SRC_PLL3] =
2501             dcn20_clock_source_create(ctx, ctx->dc_bios,
2502                 CLOCK_SOURCE_COMBO_PHY_PLL3,
2503                 &clk_src_regs[3], false);
2504     pool->base.clock_sources[DCN20_CLK_SRC_PLL4] =
2505             dcn20_clock_source_create(ctx, ctx->dc_bios,
2506                 CLOCK_SOURCE_COMBO_PHY_PLL4,
2507                 &clk_src_regs[4], false);
2508     pool->base.clock_sources[DCN20_CLK_SRC_PLL5] =
2509             dcn20_clock_source_create(ctx, ctx->dc_bios,
2510                 CLOCK_SOURCE_COMBO_PHY_PLL5,
2511                 &clk_src_regs[5], false);
2512     pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL;
2513     /* todo: not reuse phy_pll registers */
2514     pool->base.dp_clock_source =
2515             dcn20_clock_source_create(ctx, ctx->dc_bios,
2516                 CLOCK_SOURCE_ID_DP_DTO,
2517                 &clk_src_regs[0], true);
2518 
2519     for (i = 0; i < pool->base.clk_src_count; i++) {
2520         if (pool->base.clock_sources[i] == NULL) {
2521             dm_error("DC: failed to create clock sources!\n");
2522             BREAK_TO_DEBUGGER();
2523             goto create_fail;
2524         }
2525     }
2526 
2527     pool->base.dccg = dccg2_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);
2528     if (pool->base.dccg == NULL) {
2529         dm_error("DC: failed to create dccg!\n");
2530         BREAK_TO_DEBUGGER();
2531         goto create_fail;
2532     }
2533 
2534     pool->base.dmcu = dcn20_dmcu_create(ctx,
2535             &dmcu_regs,
2536             &dmcu_shift,
2537             &dmcu_mask);
2538     if (pool->base.dmcu == NULL) {
2539         dm_error("DC: failed to create dmcu!\n");
2540         BREAK_TO_DEBUGGER();
2541         goto create_fail;
2542     }
2543 
2544     pool->base.abm = dce_abm_create(ctx,
2545             &abm_regs,
2546             &abm_shift,
2547             &abm_mask);
2548     if (pool->base.abm == NULL) {
2549         dm_error("DC: failed to create abm!\n");
2550         BREAK_TO_DEBUGGER();
2551         goto create_fail;
2552     }
2553 
2554     pool->base.pp_smu = dcn20_pp_smu_create(ctx);
2555 
2556 
2557     if (!init_soc_bounding_box(dc, pool)) {
2558         dm_error("DC: failed to initialize soc bounding box!\n");
2559         BREAK_TO_DEBUGGER();
2560         goto create_fail;
2561     }
2562 
2563     dml_init_instance(&dc->dml, loaded_bb, loaded_ip, dml_project_version);
2564 
2565     if (!dc->debug.disable_pplib_wm_range) {
2566         struct pp_smu_wm_range_sets ranges = {0};
2567         int i = 0;
2568 
2569         ranges.num_reader_wm_sets = 0;
2570 
2571         if (loaded_bb->num_states == 1) {
2572             ranges.reader_wm_sets[0].wm_inst = i;
2573             ranges.reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
2574             ranges.reader_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
2575             ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
2576             ranges.reader_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
2577 
2578             ranges.num_reader_wm_sets = 1;
2579         } else if (loaded_bb->num_states > 1) {
2580             for (i = 0; i < 4 && i < loaded_bb->num_states; i++) {
2581                 ranges.reader_wm_sets[i].wm_inst = i;
2582                 ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
2583                 ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
2584                 DC_FP_START();
2585                 dcn20_fpu_set_wm_ranges(i, &ranges, loaded_bb);
2586                 DC_FP_END();
2587 
2588                 ranges.num_reader_wm_sets = i + 1;
2589             }
2590 
2591             ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
2592             ranges.reader_wm_sets[ranges.num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
2593         }
2594 
2595         ranges.num_writer_wm_sets = 1;
2596 
2597         ranges.writer_wm_sets[0].wm_inst = 0;
2598         ranges.writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
2599         ranges.writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
2600         ranges.writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
2601         ranges.writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
2602 
2603         /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
2604         if (pool->base.pp_smu->nv_funcs.set_wm_ranges)
2605             pool->base.pp_smu->nv_funcs.set_wm_ranges(&pool->base.pp_smu->nv_funcs.pp_smu, &ranges);
2606     }
2607 
2608     init_data.ctx = dc->ctx;
2609     pool->base.irqs = dal_irq_service_dcn20_create(&init_data);
2610     if (!pool->base.irqs)
2611         goto create_fail;
2612 
2613     /* mem input -> ipp -> dpp -> opp -> TG */
2614     for (i = 0; i < pool->base.pipe_count; i++) {
2615         pool->base.hubps[i] = dcn20_hubp_create(ctx, i);
2616         if (pool->base.hubps[i] == NULL) {
2617             BREAK_TO_DEBUGGER();
2618             dm_error(
2619                 "DC: failed to create memory input!\n");
2620             goto create_fail;
2621         }
2622 
2623         pool->base.ipps[i] = dcn20_ipp_create(ctx, i);
2624         if (pool->base.ipps[i] == NULL) {
2625             BREAK_TO_DEBUGGER();
2626             dm_error(
2627                 "DC: failed to create input pixel processor!\n");
2628             goto create_fail;
2629         }
2630 
2631         pool->base.dpps[i] = dcn20_dpp_create(ctx, i);
2632         if (pool->base.dpps[i] == NULL) {
2633             BREAK_TO_DEBUGGER();
2634             dm_error(
2635                 "DC: failed to create dpps!\n");
2636             goto create_fail;
2637         }
2638     }
2639     for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
2640         pool->base.engines[i] = dcn20_aux_engine_create(ctx, i);
2641         if (pool->base.engines[i] == NULL) {
2642             BREAK_TO_DEBUGGER();
2643             dm_error(
2644                 "DC:failed to create aux engine!!\n");
2645             goto create_fail;
2646         }
2647         pool->base.hw_i2cs[i] = dcn20_i2c_hw_create(ctx, i);
2648         if (pool->base.hw_i2cs[i] == NULL) {
2649             BREAK_TO_DEBUGGER();
2650             dm_error(
2651                 "DC:failed to create hw i2c!!\n");
2652             goto create_fail;
2653         }
2654         pool->base.sw_i2cs[i] = NULL;
2655     }
2656 
2657     for (i = 0; i < pool->base.res_cap->num_opp; i++) {
2658         pool->base.opps[i] = dcn20_opp_create(ctx, i);
2659         if (pool->base.opps[i] == NULL) {
2660             BREAK_TO_DEBUGGER();
2661             dm_error(
2662                 "DC: failed to create output pixel processor!\n");
2663             goto create_fail;
2664         }
2665     }
2666 
2667     for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
2668         pool->base.timing_generators[i] = dcn20_timing_generator_create(
2669                 ctx, i);
2670         if (pool->base.timing_generators[i] == NULL) {
2671             BREAK_TO_DEBUGGER();
2672             dm_error("DC: failed to create tg!\n");
2673             goto create_fail;
2674         }
2675     }
2676 
2677     pool->base.timing_generator_count = i;
2678 
2679     pool->base.mpc = dcn20_mpc_create(ctx);
2680     if (pool->base.mpc == NULL) {
2681         BREAK_TO_DEBUGGER();
2682         dm_error("DC: failed to create mpc!\n");
2683         goto create_fail;
2684     }
2685 
2686     pool->base.hubbub = dcn20_hubbub_create(ctx);
2687     if (pool->base.hubbub == NULL) {
2688         BREAK_TO_DEBUGGER();
2689         dm_error("DC: failed to create hubbub!\n");
2690         goto create_fail;
2691     }
2692 
2693     for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
2694         pool->base.dscs[i] = dcn20_dsc_create(ctx, i);
2695         if (pool->base.dscs[i] == NULL) {
2696             BREAK_TO_DEBUGGER();
2697             dm_error("DC: failed to create display stream compressor %d!\n", i);
2698             goto create_fail;
2699         }
2700     }
2701 
2702     if (!dcn20_dwbc_create(ctx, &pool->base)) {
2703         BREAK_TO_DEBUGGER();
2704         dm_error("DC: failed to create dwbc!\n");
2705         goto create_fail;
2706     }
2707     if (!dcn20_mmhubbub_create(ctx, &pool->base)) {
2708         BREAK_TO_DEBUGGER();
2709         dm_error("DC: failed to create mcif_wb!\n");
2710         goto create_fail;
2711     }
2712 
2713     if (!resource_construct(num_virtual_links, dc, &pool->base,
2714             (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
2715             &res_create_funcs : &res_create_maximus_funcs)))
2716             goto create_fail;
2717 
2718     dcn20_hw_sequencer_construct(dc);
2719 
2720     // IF NV12, set PG function pointer to NULL. It's not that
2721     // PG isn't supported for NV12, it's that we don't want to
2722     // program the registers because that will cause more power
2723     // to be consumed. We could have created dcn20_init_hw to get
2724     // the same effect by checking ASIC rev, but there was a
2725     // request at some point to not check ASIC rev on hw sequencer.
2726     if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) {
2727         dc->hwseq->funcs.enable_power_gating_plane = NULL;
2728         dc->debug.disable_dpp_power_gate = true;
2729         dc->debug.disable_hubp_power_gate = true;
2730     }
2731 
2732 
2733     dc->caps.max_planes =  pool->base.pipe_count;
2734 
2735     for (i = 0; i < dc->caps.max_planes; ++i)
2736         dc->caps.planes[i] = plane_cap;
2737 
2738     dc->cap_funcs = cap_funcs;
2739 
2740     if (dc->ctx->dc_bios->fw_info.oem_i2c_present) {
2741         ddc_init_data.ctx = dc->ctx;
2742         ddc_init_data.link = NULL;
2743         ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;
2744         ddc_init_data.id.enum_id = 0;
2745         ddc_init_data.id.type = OBJECT_TYPE_GENERIC;
2746         pool->base.oem_device = dal_ddc_service_create(&ddc_init_data);
2747     } else {
2748         pool->base.oem_device = NULL;
2749     }
2750 
2751     return true;
2752 
2753 create_fail:
2754 
2755     dcn20_resource_destruct(pool);
2756 
2757     return false;
2758 }
2759 
2760 struct resource_pool *dcn20_create_resource_pool(
2761         const struct dc_init_data *init_data,
2762         struct dc *dc)
2763 {
2764     struct dcn20_resource_pool *pool =
2765         kzalloc(sizeof(struct dcn20_resource_pool), GFP_ATOMIC);
2766 
2767     if (!pool)
2768         return NULL;
2769 
2770     if (dcn20_resource_construct(init_data->num_virtual_links, dc, pool))
2771         return &pool->base;
2772 
2773     BREAK_TO_DEBUGGER();
2774     kfree(pool);
2775     return NULL;
2776 }