LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dcn20 - dcn20_resource.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1025 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 51 0.0 %

          Line data    Source code
       1             : /*
       2             : * Copyright 2016 Advanced Micro Devices, Inc.
       3             :  * Copyright 2019 Raptor Engineering, LLC
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining a
       6             :  * copy of this software and associated documentation files (the "Software"),
       7             :  * to deal in the Software without restriction, including without limitation
       8             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       9             :  * and/or sell copies of the Software, and to permit persons to whom the
      10             :  * Software is furnished to do so, subject to the following conditions:
      11             :  *
      12             :  * The above copyright notice and this permission notice shall be included in
      13             :  * all copies or substantial portions of the Software.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      19             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      20             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      21             :  * OTHER DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Authors: AMD
      24             :  *
      25             :  */
      26             : 
      27             : #include <linux/slab.h>
      28             : 
      29             : #include "dm_services.h"
      30             : #include "dc.h"
      31             : 
      32             : #include "dcn20_init.h"
      33             : 
      34             : #include "resource.h"
      35             : #include "include/irq_service_interface.h"
      36             : #include "dcn20/dcn20_resource.h"
      37             : 
      38             : #include "dml/dcn20/dcn20_fpu.h"
      39             : 
      40             : #include "dcn10/dcn10_hubp.h"
      41             : #include "dcn10/dcn10_ipp.h"
      42             : #include "dcn20_hubbub.h"
      43             : #include "dcn20_mpc.h"
      44             : #include "dcn20_hubp.h"
      45             : #include "irq/dcn20/irq_service_dcn20.h"
      46             : #include "dcn20_dpp.h"
      47             : #include "dcn20_optc.h"
      48             : #include "dcn20_hwseq.h"
      49             : #include "dce110/dce110_hw_sequencer.h"
      50             : #include "dcn10/dcn10_resource.h"
      51             : #include "dcn20_opp.h"
      52             : 
      53             : #include "dcn20_dsc.h"
      54             : 
      55             : #include "dcn20_link_encoder.h"
      56             : #include "dcn20_stream_encoder.h"
      57             : #include "dce/dce_clock_source.h"
      58             : #include "dce/dce_audio.h"
      59             : #include "dce/dce_hwseq.h"
      60             : #include "virtual/virtual_stream_encoder.h"
      61             : #include "dce110/dce110_resource.h"
      62             : #include "dml/display_mode_vba.h"
      63             : #include "dcn20_dccg.h"
      64             : #include "dcn20_vmid.h"
      65             : #include "dc_link_ddc.h"
      66             : #include "dce/dce_panel_cntl.h"
      67             : 
      68             : #include "navi10_ip_offset.h"
      69             : 
      70             : #include "dcn/dcn_2_0_0_offset.h"
      71             : #include "dcn/dcn_2_0_0_sh_mask.h"
      72             : #include "dpcs/dpcs_2_0_0_offset.h"
      73             : #include "dpcs/dpcs_2_0_0_sh_mask.h"
      74             : 
      75             : #include "nbio/nbio_2_3_offset.h"
      76             : 
      77             : #include "dcn20/dcn20_dwb.h"
      78             : #include "dcn20/dcn20_mmhubbub.h"
      79             : 
      80             : #include "mmhub/mmhub_2_0_0_offset.h"
      81             : #include "mmhub/mmhub_2_0_0_sh_mask.h"
      82             : 
      83             : #include "reg_helper.h"
      84             : #include "dce/dce_abm.h"
      85             : #include "dce/dce_dmcu.h"
      86             : #include "dce/dce_aux.h"
      87             : #include "dce/dce_i2c.h"
      88             : #include "vm_helper.h"
      89             : #include "link_enc_cfg.h"
      90             : 
      91             : #include "amdgpu_socbb.h"
      92             : 
      93             : #define DC_LOGGER_INIT(logger)
      94             : 
      95             : #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
      96             :         #define mmDP0_DP_DPHY_INTERNAL_CTRL             0x210f
      97             :         #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
      98             :         #define mmDP1_DP_DPHY_INTERNAL_CTRL             0x220f
      99             :         #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
     100             :         #define mmDP2_DP_DPHY_INTERNAL_CTRL             0x230f
     101             :         #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
     102             :         #define mmDP3_DP_DPHY_INTERNAL_CTRL             0x240f
     103             :         #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
     104             :         #define mmDP4_DP_DPHY_INTERNAL_CTRL             0x250f
     105             :         #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
     106             :         #define mmDP5_DP_DPHY_INTERNAL_CTRL             0x260f
     107             :         #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
     108             :         #define mmDP6_DP_DPHY_INTERNAL_CTRL             0x270f
     109             :         #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX    2
     110             : #endif
     111             : 
     112             : 
     113             : enum dcn20_clk_src_array_id {
     114             :         DCN20_CLK_SRC_PLL0,
     115             :         DCN20_CLK_SRC_PLL1,
     116             :         DCN20_CLK_SRC_PLL2,
     117             :         DCN20_CLK_SRC_PLL3,
     118             :         DCN20_CLK_SRC_PLL4,
     119             :         DCN20_CLK_SRC_PLL5,
     120             :         DCN20_CLK_SRC_TOTAL
     121             : };
     122             : 
     123             : /* begin *********************
     124             :  * macros to expend register list macro defined in HW object header file */
     125             : 
     126             : /* DCN */
     127             : /* TODO awful hack. fixup dcn20_dwb.h */
     128             : #undef BASE_INNER
     129             : #define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
     130             : 
     131             : #define BASE(seg) BASE_INNER(seg)
     132             : 
     133             : #define SR(reg_name)\
     134             :                 .reg_name = BASE(mm ## reg_name ## _BASE_IDX) +  \
     135             :                                         mm ## reg_name
     136             : 
     137             : #define SRI(reg_name, block, id)\
     138             :         .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
     139             :                                         mm ## block ## id ## _ ## reg_name
     140             : 
     141             : #define SRIR(var_name, reg_name, block, id)\
     142             :         .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
     143             :                                         mm ## block ## id ## _ ## reg_name
     144             : 
     145             : #define SRII(reg_name, block, id)\
     146             :         .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
     147             :                                         mm ## block ## id ## _ ## reg_name
     148             : 
     149             : #define DCCG_SRII(reg_name, block, id)\
     150             :         .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
     151             :                                         mm ## block ## id ## _ ## reg_name
     152             : 
     153             : #define VUPDATE_SRII(reg_name, block, id)\
     154             :         .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \
     155             :                                         mm ## reg_name ## _ ## block ## id
     156             : 
     157             : /* NBIO */
     158             : #define NBIO_BASE_INNER(seg) \
     159             :         NBIO_BASE__INST0_SEG ## seg
     160             : 
     161             : #define NBIO_BASE(seg) \
     162             :         NBIO_BASE_INNER(seg)
     163             : 
     164             : #define NBIO_SR(reg_name)\
     165             :                 .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \
     166             :                                         mm ## reg_name
     167             : 
     168             : /* MMHUB */
     169             : #define MMHUB_BASE_INNER(seg) \
     170             :         MMHUB_BASE__INST0_SEG ## seg
     171             : 
     172             : #define MMHUB_BASE(seg) \
     173             :         MMHUB_BASE_INNER(seg)
     174             : 
     175             : #define MMHUB_SR(reg_name)\
     176             :                 .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \
     177             :                                         mmMM ## reg_name
     178             : 
     179             : static const struct bios_registers bios_regs = {
     180             :                 NBIO_SR(BIOS_SCRATCH_3),
     181             :                 NBIO_SR(BIOS_SCRATCH_6)
     182             : };
     183             : 
     184             : #define clk_src_regs(index, pllid)\
     185             : [index] = {\
     186             :         CS_COMMON_REG_LIST_DCN2_0(index, pllid),\
     187             : }
     188             : 
     189             : static const struct dce110_clk_src_regs clk_src_regs[] = {
     190             :         clk_src_regs(0, A),
     191             :         clk_src_regs(1, B),
     192             :         clk_src_regs(2, C),
     193             :         clk_src_regs(3, D),
     194             :         clk_src_regs(4, E),
     195             :         clk_src_regs(5, F)
     196             : };
     197             : 
     198             : static const struct dce110_clk_src_shift cs_shift = {
     199             :                 CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
     200             : };
     201             : 
     202             : static const struct dce110_clk_src_mask cs_mask = {
     203             :                 CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
     204             : };
     205             : 
     206             : static const struct dce_dmcu_registers dmcu_regs = {
     207             :                 DMCU_DCN10_REG_LIST()
     208             : };
     209             : 
     210             : static const struct dce_dmcu_shift dmcu_shift = {
     211             :                 DMCU_MASK_SH_LIST_DCN10(__SHIFT)
     212             : };
     213             : 
     214             : static const struct dce_dmcu_mask dmcu_mask = {
     215             :                 DMCU_MASK_SH_LIST_DCN10(_MASK)
     216             : };
     217             : 
     218             : static const struct dce_abm_registers abm_regs = {
     219             :                 ABM_DCN20_REG_LIST()
     220             : };
     221             : 
     222             : static const struct dce_abm_shift abm_shift = {
     223             :                 ABM_MASK_SH_LIST_DCN20(__SHIFT)
     224             : };
     225             : 
     226             : static const struct dce_abm_mask abm_mask = {
     227             :                 ABM_MASK_SH_LIST_DCN20(_MASK)
     228             : };
     229             : 
     230             : #define audio_regs(id)\
     231             : [id] = {\
     232             :                 AUD_COMMON_REG_LIST(id)\
     233             : }
     234             : 
     235             : static const struct dce_audio_registers audio_regs[] = {
     236             :         audio_regs(0),
     237             :         audio_regs(1),
     238             :         audio_regs(2),
     239             :         audio_regs(3),
     240             :         audio_regs(4),
     241             :         audio_regs(5),
     242             :         audio_regs(6),
     243             : };
     244             : 
     245             : #define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\
     246             :                 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
     247             :                 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
     248             :                 AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)
     249             : 
     250             : static const struct dce_audio_shift audio_shift = {
     251             :                 DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)
     252             : };
     253             : 
     254             : static const struct dce_audio_mask audio_mask = {
     255             :                 DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)
     256             : };
     257             : 
     258             : #define stream_enc_regs(id)\
     259             : [id] = {\
     260             :         SE_DCN2_REG_LIST(id)\
     261             : }
     262             : 
     263             : static const struct dcn10_stream_enc_registers stream_enc_regs[] = {
     264             :         stream_enc_regs(0),
     265             :         stream_enc_regs(1),
     266             :         stream_enc_regs(2),
     267             :         stream_enc_regs(3),
     268             :         stream_enc_regs(4),
     269             :         stream_enc_regs(5),
     270             : };
     271             : 
     272             : static const struct dcn10_stream_encoder_shift se_shift = {
     273             :                 SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT)
     274             : };
     275             : 
     276             : static const struct dcn10_stream_encoder_mask se_mask = {
     277             :                 SE_COMMON_MASK_SH_LIST_DCN20(_MASK)
     278             : };
     279             : 
     280             : 
     281             : #define aux_regs(id)\
     282             : [id] = {\
     283             :         DCN2_AUX_REG_LIST(id)\
     284             : }
     285             : 
     286             : static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = {
     287             :                 aux_regs(0),
     288             :                 aux_regs(1),
     289             :                 aux_regs(2),
     290             :                 aux_regs(3),
     291             :                 aux_regs(4),
     292             :                 aux_regs(5)
     293             : };
     294             : 
     295             : #define hpd_regs(id)\
     296             : [id] = {\
     297             :         HPD_REG_LIST(id)\
     298             : }
     299             : 
     300             : static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = {
     301             :                 hpd_regs(0),
     302             :                 hpd_regs(1),
     303             :                 hpd_regs(2),
     304             :                 hpd_regs(3),
     305             :                 hpd_regs(4),
     306             :                 hpd_regs(5)
     307             : };
     308             : 
     309             : #define link_regs(id, phyid)\
     310             : [id] = {\
     311             :         LE_DCN10_REG_LIST(id), \
     312             :         UNIPHY_DCN2_REG_LIST(phyid), \
     313             :         DPCS_DCN2_REG_LIST(id), \
     314             :         SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \
     315             : }
     316             : 
     317             : static const struct dcn10_link_enc_registers link_enc_regs[] = {
     318             :         link_regs(0, A),
     319             :         link_regs(1, B),
     320             :         link_regs(2, C),
     321             :         link_regs(3, D),
     322             :         link_regs(4, E),
     323             :         link_regs(5, F)
     324             : };
     325             : 
     326             : static const struct dcn10_link_enc_shift le_shift = {
     327             :         LINK_ENCODER_MASK_SH_LIST_DCN20(__SHIFT),\
     328             :         DPCS_DCN2_MASK_SH_LIST(__SHIFT)
     329             : };
     330             : 
     331             : static const struct dcn10_link_enc_mask le_mask = {
     332             :         LINK_ENCODER_MASK_SH_LIST_DCN20(_MASK),\
     333             :         DPCS_DCN2_MASK_SH_LIST(_MASK)
     334             : };
     335             : 
     336             : static const struct dce_panel_cntl_registers panel_cntl_regs[] = {
     337             :         { DCN_PANEL_CNTL_REG_LIST() }
     338             : };
     339             : 
     340             : static const struct dce_panel_cntl_shift panel_cntl_shift = {
     341             :         DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT)
     342             : };
     343             : 
     344             : static const struct dce_panel_cntl_mask panel_cntl_mask = {
     345             :         DCE_PANEL_CNTL_MASK_SH_LIST(_MASK)
     346             : };
     347             : 
     348             : #define ipp_regs(id)\
     349             : [id] = {\
     350             :         IPP_REG_LIST_DCN20(id),\
     351             : }
     352             : 
     353             : static const struct dcn10_ipp_registers ipp_regs[] = {
     354             :         ipp_regs(0),
     355             :         ipp_regs(1),
     356             :         ipp_regs(2),
     357             :         ipp_regs(3),
     358             :         ipp_regs(4),
     359             :         ipp_regs(5),
     360             : };
     361             : 
     362             : static const struct dcn10_ipp_shift ipp_shift = {
     363             :                 IPP_MASK_SH_LIST_DCN20(__SHIFT)
     364             : };
     365             : 
     366             : static const struct dcn10_ipp_mask ipp_mask = {
     367             :                 IPP_MASK_SH_LIST_DCN20(_MASK),
     368             : };
     369             : 
     370             : #define opp_regs(id)\
     371             : [id] = {\
     372             :         OPP_REG_LIST_DCN20(id),\
     373             : }
     374             : 
     375             : static const struct dcn20_opp_registers opp_regs[] = {
     376             :         opp_regs(0),
     377             :         opp_regs(1),
     378             :         opp_regs(2),
     379             :         opp_regs(3),
     380             :         opp_regs(4),
     381             :         opp_regs(5),
     382             : };
     383             : 
     384             : static const struct dcn20_opp_shift opp_shift = {
     385             :                 OPP_MASK_SH_LIST_DCN20(__SHIFT)
     386             : };
     387             : 
     388             : static const struct dcn20_opp_mask opp_mask = {
     389             :                 OPP_MASK_SH_LIST_DCN20(_MASK)
     390             : };
     391             : 
     392             : #define aux_engine_regs(id)\
     393             : [id] = {\
     394             :         AUX_COMMON_REG_LIST0(id), \
     395             :         .AUXN_IMPCAL = 0, \
     396             :         .AUXP_IMPCAL = 0, \
     397             :         .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \
     398             : }
     399             : 
     400             : static const struct dce110_aux_registers aux_engine_regs[] = {
     401             :                 aux_engine_regs(0),
     402             :                 aux_engine_regs(1),
     403             :                 aux_engine_regs(2),
     404             :                 aux_engine_regs(3),
     405             :                 aux_engine_regs(4),
     406             :                 aux_engine_regs(5)
     407             : };
     408             : 
     409             : #define tf_regs(id)\
     410             : [id] = {\
     411             :         TF_REG_LIST_DCN20(id),\
     412             :         TF_REG_LIST_DCN20_COMMON_APPEND(id),\
     413             : }
     414             : 
     415             : static const struct dcn2_dpp_registers tf_regs[] = {
     416             :         tf_regs(0),
     417             :         tf_regs(1),
     418             :         tf_regs(2),
     419             :         tf_regs(3),
     420             :         tf_regs(4),
     421             :         tf_regs(5),
     422             : };
     423             : 
     424             : static const struct dcn2_dpp_shift tf_shift = {
     425             :                 TF_REG_LIST_SH_MASK_DCN20(__SHIFT),
     426             :                 TF_DEBUG_REG_LIST_SH_DCN20
     427             : };
     428             : 
     429             : static const struct dcn2_dpp_mask tf_mask = {
     430             :                 TF_REG_LIST_SH_MASK_DCN20(_MASK),
     431             :                 TF_DEBUG_REG_LIST_MASK_DCN20
     432             : };
     433             : 
     434             : #define dwbc_regs_dcn2(id)\
     435             : [id] = {\
     436             :         DWBC_COMMON_REG_LIST_DCN2_0(id),\
     437             :                 }
     438             : 
     439             : static const struct dcn20_dwbc_registers dwbc20_regs[] = {
     440             :         dwbc_regs_dcn2(0),
     441             : };
     442             : 
     443             : static const struct dcn20_dwbc_shift dwbc20_shift = {
     444             :         DWBC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
     445             : };
     446             : 
     447             : static const struct dcn20_dwbc_mask dwbc20_mask = {
     448             :         DWBC_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
     449             : };
     450             : 
     451             : #define mcif_wb_regs_dcn2(id)\
     452             : [id] = {\
     453             :         MCIF_WB_COMMON_REG_LIST_DCN2_0(id),\
     454             :                 }
     455             : 
     456             : static const struct dcn20_mmhubbub_registers mcif_wb20_regs[] = {
     457             :         mcif_wb_regs_dcn2(0),
     458             : };
     459             : 
     460             : static const struct dcn20_mmhubbub_shift mcif_wb20_shift = {
     461             :         MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
     462             : };
     463             : 
     464             : static const struct dcn20_mmhubbub_mask mcif_wb20_mask = {
     465             :         MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
     466             : };
     467             : 
     468             : static const struct dcn20_mpc_registers mpc_regs = {
     469             :                 MPC_REG_LIST_DCN2_0(0),
     470             :                 MPC_REG_LIST_DCN2_0(1),
     471             :                 MPC_REG_LIST_DCN2_0(2),
     472             :                 MPC_REG_LIST_DCN2_0(3),
     473             :                 MPC_REG_LIST_DCN2_0(4),
     474             :                 MPC_REG_LIST_DCN2_0(5),
     475             :                 MPC_OUT_MUX_REG_LIST_DCN2_0(0),
     476             :                 MPC_OUT_MUX_REG_LIST_DCN2_0(1),
     477             :                 MPC_OUT_MUX_REG_LIST_DCN2_0(2),
     478             :                 MPC_OUT_MUX_REG_LIST_DCN2_0(3),
     479             :                 MPC_OUT_MUX_REG_LIST_DCN2_0(4),
     480             :                 MPC_OUT_MUX_REG_LIST_DCN2_0(5),
     481             :                 MPC_DBG_REG_LIST_DCN2_0()
     482             : };
     483             : 
     484             : static const struct dcn20_mpc_shift mpc_shift = {
     485             :         MPC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT),
     486             :         MPC_DEBUG_REG_LIST_SH_DCN20
     487             : };
     488             : 
     489             : static const struct dcn20_mpc_mask mpc_mask = {
     490             :         MPC_COMMON_MASK_SH_LIST_DCN2_0(_MASK),
     491             :         MPC_DEBUG_REG_LIST_MASK_DCN20
     492             : };
     493             : 
     494             : #define tg_regs(id)\
     495             : [id] = {TG_COMMON_REG_LIST_DCN2_0(id)}
     496             : 
     497             : 
     498             : static const struct dcn_optc_registers tg_regs[] = {
     499             :         tg_regs(0),
     500             :         tg_regs(1),
     501             :         tg_regs(2),
     502             :         tg_regs(3),
     503             :         tg_regs(4),
     504             :         tg_regs(5)
     505             : };
     506             : 
     507             : static const struct dcn_optc_shift tg_shift = {
     508             :         TG_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT)
     509             : };
     510             : 
     511             : static const struct dcn_optc_mask tg_mask = {
     512             :         TG_COMMON_MASK_SH_LIST_DCN2_0(_MASK)
     513             : };
     514             : 
     515             : #define hubp_regs(id)\
     516             : [id] = {\
     517             :         HUBP_REG_LIST_DCN20(id)\
     518             : }
     519             : 
     520             : static const struct dcn_hubp2_registers hubp_regs[] = {
     521             :                 hubp_regs(0),
     522             :                 hubp_regs(1),
     523             :                 hubp_regs(2),
     524             :                 hubp_regs(3),
     525             :                 hubp_regs(4),
     526             :                 hubp_regs(5)
     527             : };
     528             : 
     529             : static const struct dcn_hubp2_shift hubp_shift = {
     530             :                 HUBP_MASK_SH_LIST_DCN20(__SHIFT)
     531             : };
     532             : 
     533             : static const struct dcn_hubp2_mask hubp_mask = {
     534             :                 HUBP_MASK_SH_LIST_DCN20(_MASK)
     535             : };
     536             : 
     537             : static const struct dcn_hubbub_registers hubbub_reg = {
     538             :                 HUBBUB_REG_LIST_DCN20(0)
     539             : };
     540             : 
     541             : static const struct dcn_hubbub_shift hubbub_shift = {
     542             :                 HUBBUB_MASK_SH_LIST_DCN20(__SHIFT)
     543             : };
     544             : 
     545             : static const struct dcn_hubbub_mask hubbub_mask = {
     546             :                 HUBBUB_MASK_SH_LIST_DCN20(_MASK)
     547             : };
     548             : 
     549             : #define vmid_regs(id)\
     550             : [id] = {\
     551             :                 DCN20_VMID_REG_LIST(id)\
     552             : }
     553             : 
     554             : static const struct dcn_vmid_registers vmid_regs[] = {
     555             :         vmid_regs(0),
     556             :         vmid_regs(1),
     557             :         vmid_regs(2),
     558             :         vmid_regs(3),
     559             :         vmid_regs(4),
     560             :         vmid_regs(5),
     561             :         vmid_regs(6),
     562             :         vmid_regs(7),
     563             :         vmid_regs(8),
     564             :         vmid_regs(9),
     565             :         vmid_regs(10),
     566             :         vmid_regs(11),
     567             :         vmid_regs(12),
     568             :         vmid_regs(13),
     569             :         vmid_regs(14),
     570             :         vmid_regs(15)
     571             : };
     572             : 
     573             : static const struct dcn20_vmid_shift vmid_shifts = {
     574             :                 DCN20_VMID_MASK_SH_LIST(__SHIFT)
     575             : };
     576             : 
     577             : static const struct dcn20_vmid_mask vmid_masks = {
     578             :                 DCN20_VMID_MASK_SH_LIST(_MASK)
     579             : };
     580             : 
     581             : static const struct dce110_aux_registers_shift aux_shift = {
     582             :                 DCN_AUX_MASK_SH_LIST(__SHIFT)
     583             : };
     584             : 
     585             : static const struct dce110_aux_registers_mask aux_mask = {
     586             :                 DCN_AUX_MASK_SH_LIST(_MASK)
     587             : };
     588             : 
     589           0 : static int map_transmitter_id_to_phy_instance(
     590             :         enum transmitter transmitter)
     591             : {
     592           0 :         switch (transmitter) {
     593             :         case TRANSMITTER_UNIPHY_A:
     594             :                 return 0;
     595             :         break;
     596             :         case TRANSMITTER_UNIPHY_B:
     597           0 :                 return 1;
     598             :         break;
     599             :         case TRANSMITTER_UNIPHY_C:
     600           0 :                 return 2;
     601             :         break;
     602             :         case TRANSMITTER_UNIPHY_D:
     603           0 :                 return 3;
     604             :         break;
     605             :         case TRANSMITTER_UNIPHY_E:
     606           0 :                 return 4;
     607             :         break;
     608             :         case TRANSMITTER_UNIPHY_F:
     609           0 :                 return 5;
     610             :         break;
     611             :         default:
     612           0 :                 ASSERT(0);
     613             :                 return 0;
     614             :         }
     615             : }
     616             : 
     617             : #define dsc_regsDCN20(id)\
     618             : [id] = {\
     619             :         DSC_REG_LIST_DCN20(id)\
     620             : }
     621             : 
     622             : static const struct dcn20_dsc_registers dsc_regs[] = {
     623             :         dsc_regsDCN20(0),
     624             :         dsc_regsDCN20(1),
     625             :         dsc_regsDCN20(2),
     626             :         dsc_regsDCN20(3),
     627             :         dsc_regsDCN20(4),
     628             :         dsc_regsDCN20(5)
     629             : };
     630             : 
     631             : static const struct dcn20_dsc_shift dsc_shift = {
     632             :         DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)
     633             : };
     634             : 
     635             : static const struct dcn20_dsc_mask dsc_mask = {
     636             :         DSC_REG_LIST_SH_MASK_DCN20(_MASK)
     637             : };
     638             : 
     639             : static const struct dccg_registers dccg_regs = {
     640             :                 DCCG_REG_LIST_DCN2()
     641             : };
     642             : 
     643             : static const struct dccg_shift dccg_shift = {
     644             :                 DCCG_MASK_SH_LIST_DCN2(__SHIFT)
     645             : };
     646             : 
     647             : static const struct dccg_mask dccg_mask = {
     648             :                 DCCG_MASK_SH_LIST_DCN2(_MASK)
     649             : };
     650             : 
     651             : static const struct resource_caps res_cap_nv10 = {
     652             :                 .num_timing_generator = 6,
     653             :                 .num_opp = 6,
     654             :                 .num_video_plane = 6,
     655             :                 .num_audio = 7,
     656             :                 .num_stream_encoder = 6,
     657             :                 .num_pll = 6,
     658             :                 .num_dwb = 1,
     659             :                 .num_ddc = 6,
     660             :                 .num_vmid = 16,
     661             :                 .num_dsc = 6,
     662             : };
     663             : 
     664             : static const struct dc_plane_cap plane_cap = {
     665             :         .type = DC_PLANE_TYPE_DCN_UNIVERSAL,
     666             :         .blends_with_above = true,
     667             :         .blends_with_below = true,
     668             :         .per_pixel_alpha = true,
     669             : 
     670             :         .pixel_format_support = {
     671             :                         .argb8888 = true,
     672             :                         .nv12 = true,
     673             :                         .fp16 = true,
     674             :                         .p010 = true
     675             :         },
     676             : 
     677             :         .max_upscale_factor = {
     678             :                         .argb8888 = 16000,
     679             :                         .nv12 = 16000,
     680             :                         .fp16 = 1
     681             :         },
     682             : 
     683             :         .max_downscale_factor = {
     684             :                         .argb8888 = 250,
     685             :                         .nv12 = 250,
     686             :                         .fp16 = 1
     687             :         },
     688             :         16,
     689             :         16
     690             : };
     691             : static const struct resource_caps res_cap_nv14 = {
     692             :                 .num_timing_generator = 5,
     693             :                 .num_opp = 5,
     694             :                 .num_video_plane = 5,
     695             :                 .num_audio = 6,
     696             :                 .num_stream_encoder = 5,
     697             :                 .num_pll = 5,
     698             :                 .num_dwb = 1,
     699             :                 .num_ddc = 5,
     700             :                 .num_vmid = 16,
     701             :                 .num_dsc = 5,
     702             : };
     703             : 
     704             : static const struct dc_debug_options debug_defaults_drv = {
     705             :                 .disable_dmcu = false,
     706             :                 .force_abm_enable = false,
     707             :                 .timing_trace = false,
     708             :                 .clock_trace = true,
     709             :                 .disable_pplib_clock_request = true,
     710             :                 .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP,
     711             :                 .force_single_disp_pipe_split = false,
     712             :                 .disable_dcc = DCC_ENABLE,
     713             :                 .vsr_support = true,
     714             :                 .performance_trace = false,
     715             :                 .max_downscale_src_width = 5120,/*upto 5K*/
     716             :                 .disable_pplib_wm_range = false,
     717             :                 .scl_reset_length10 = true,
     718             :                 .sanity_checks = false,
     719             :                 .underflow_assert_delay_us = 0xFFFFFFFF,
     720             : };
     721             : 
     722             : static const struct dc_debug_options debug_defaults_diags = {
     723             :                 .disable_dmcu = false,
     724             :                 .force_abm_enable = false,
     725             :                 .timing_trace = true,
     726             :                 .clock_trace = true,
     727             :                 .disable_dpp_power_gate = true,
     728             :                 .disable_hubp_power_gate = true,
     729             :                 .disable_clock_gate = true,
     730             :                 .disable_pplib_clock_request = true,
     731             :                 .disable_pplib_wm_range = true,
     732             :                 .disable_stutter = true,
     733             :                 .scl_reset_length10 = true,
     734             :                 .underflow_assert_delay_us = 0xFFFFFFFF,
     735             :                 .enable_tri_buf = true,
     736             : };
     737             : 
     738           0 : void dcn20_dpp_destroy(struct dpp **dpp)
     739             : {
     740           0 :         kfree(TO_DCN20_DPP(*dpp));
     741           0 :         *dpp = NULL;
     742           0 : }
     743             : 
     744           0 : struct dpp *dcn20_dpp_create(
     745             :         struct dc_context *ctx,
     746             :         uint32_t inst)
     747             : {
     748           0 :         struct dcn20_dpp *dpp =
     749             :                 kzalloc(sizeof(struct dcn20_dpp), GFP_ATOMIC);
     750             : 
     751           0 :         if (!dpp)
     752             :                 return NULL;
     753             : 
     754           0 :         if (dpp2_construct(dpp, ctx, inst,
     755             :                         &tf_regs[inst], &tf_shift, &tf_mask))
     756           0 :                 return &dpp->base;
     757             : 
     758           0 :         BREAK_TO_DEBUGGER();
     759           0 :         kfree(dpp);
     760           0 :         return NULL;
     761             : }
     762             : 
     763           0 : struct input_pixel_processor *dcn20_ipp_create(
     764             :         struct dc_context *ctx, uint32_t inst)
     765             : {
     766           0 :         struct dcn10_ipp *ipp =
     767             :                 kzalloc(sizeof(struct dcn10_ipp), GFP_ATOMIC);
     768             : 
     769           0 :         if (!ipp) {
     770           0 :                 BREAK_TO_DEBUGGER();
     771           0 :                 return NULL;
     772             :         }
     773             : 
     774           0 :         dcn20_ipp_construct(ipp, ctx, inst,
     775             :                         &ipp_regs[inst], &ipp_shift, &ipp_mask);
     776           0 :         return &ipp->base;
     777             : }
     778             : 
     779             : 
     780           0 : struct output_pixel_processor *dcn20_opp_create(
     781             :         struct dc_context *ctx, uint32_t inst)
     782             : {
     783           0 :         struct dcn20_opp *opp =
     784             :                 kzalloc(sizeof(struct dcn20_opp), GFP_ATOMIC);
     785             : 
     786           0 :         if (!opp) {
     787           0 :                 BREAK_TO_DEBUGGER();
     788           0 :                 return NULL;
     789             :         }
     790             : 
     791           0 :         dcn20_opp_construct(opp, ctx, inst,
     792             :                         &opp_regs[inst], &opp_shift, &opp_mask);
     793           0 :         return &opp->base;
     794             : }
     795             : 
     796           0 : struct dce_aux *dcn20_aux_engine_create(
     797             :         struct dc_context *ctx,
     798             :         uint32_t inst)
     799             : {
     800           0 :         struct aux_engine_dce110 *aux_engine =
     801             :                 kzalloc(sizeof(struct aux_engine_dce110), GFP_ATOMIC);
     802             : 
     803           0 :         if (!aux_engine)
     804             :                 return NULL;
     805             : 
     806           0 :         dce110_aux_engine_construct(aux_engine, ctx, inst,
     807             :                                     SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
     808             :                                     &aux_engine_regs[inst],
     809             :                                         &aux_mask,
     810             :                                         &aux_shift,
     811           0 :                                         ctx->dc->caps.extended_aux_timeout_support);
     812             : 
     813           0 :         return &aux_engine->base;
     814             : }
     815             : #define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) }
     816             : 
     817             : static const struct dce_i2c_registers i2c_hw_regs[] = {
     818             :                 i2c_inst_regs(1),
     819             :                 i2c_inst_regs(2),
     820             :                 i2c_inst_regs(3),
     821             :                 i2c_inst_regs(4),
     822             :                 i2c_inst_regs(5),
     823             :                 i2c_inst_regs(6),
     824             : };
     825             : 
     826             : static const struct dce_i2c_shift i2c_shifts = {
     827             :                 I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT)
     828             : };
     829             : 
     830             : static const struct dce_i2c_mask i2c_masks = {
     831             :                 I2C_COMMON_MASK_SH_LIST_DCN2(_MASK)
     832             : };
     833             : 
     834           0 : struct dce_i2c_hw *dcn20_i2c_hw_create(
     835             :         struct dc_context *ctx,
     836             :         uint32_t inst)
     837             : {
     838           0 :         struct dce_i2c_hw *dce_i2c_hw =
     839             :                 kzalloc(sizeof(struct dce_i2c_hw), GFP_ATOMIC);
     840             : 
     841           0 :         if (!dce_i2c_hw)
     842             :                 return NULL;
     843             : 
     844           0 :         dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,
     845             :                                     &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);
     846             : 
     847           0 :         return dce_i2c_hw;
     848             : }
     849           0 : struct mpc *dcn20_mpc_create(struct dc_context *ctx)
     850             : {
     851           0 :         struct dcn20_mpc *mpc20 = kzalloc(sizeof(struct dcn20_mpc),
     852             :                                           GFP_ATOMIC);
     853             : 
     854           0 :         if (!mpc20)
     855             :                 return NULL;
     856             : 
     857           0 :         dcn20_mpc_construct(mpc20, ctx,
     858             :                         &mpc_regs,
     859             :                         &mpc_shift,
     860             :                         &mpc_mask,
     861             :                         6);
     862             : 
     863           0 :         return &mpc20->base;
     864             : }
     865             : 
     866           0 : struct hubbub *dcn20_hubbub_create(struct dc_context *ctx)
     867             : {
     868             :         int i;
     869           0 :         struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub),
     870             :                                           GFP_ATOMIC);
     871             : 
     872           0 :         if (!hubbub)
     873             :                 return NULL;
     874             : 
     875           0 :         hubbub2_construct(hubbub, ctx,
     876             :                         &hubbub_reg,
     877             :                         &hubbub_shift,
     878             :                         &hubbub_mask);
     879             : 
     880           0 :         for (i = 0; i < res_cap_nv10.num_vmid; i++) {
     881           0 :                 struct dcn20_vmid *vmid = &hubbub->vmid[i];
     882             : 
     883           0 :                 vmid->ctx = ctx;
     884             : 
     885           0 :                 vmid->regs = &vmid_regs[i];
     886           0 :                 vmid->shifts = &vmid_shifts;
     887           0 :                 vmid->masks = &vmid_masks;
     888             :         }
     889             : 
     890           0 :         return &hubbub->base;
     891             : }
     892             : 
     893           0 : struct timing_generator *dcn20_timing_generator_create(
     894             :                 struct dc_context *ctx,
     895             :                 uint32_t instance)
     896             : {
     897           0 :         struct optc *tgn10 =
     898             :                 kzalloc(sizeof(struct optc), GFP_ATOMIC);
     899             : 
     900           0 :         if (!tgn10)
     901             :                 return NULL;
     902             : 
     903           0 :         tgn10->base.inst = instance;
     904           0 :         tgn10->base.ctx = ctx;
     905             : 
     906           0 :         tgn10->tg_regs = &tg_regs[instance];
     907           0 :         tgn10->tg_shift = &tg_shift;
     908           0 :         tgn10->tg_mask = &tg_mask;
     909             : 
     910           0 :         dcn20_timing_generator_init(tgn10);
     911             : 
     912           0 :         return &tgn10->base;
     913             : }
     914             : 
     915             : static const struct encoder_feature_support link_enc_feature = {
     916             :                 .max_hdmi_deep_color = COLOR_DEPTH_121212,
     917             :                 .max_hdmi_pixel_clock = 600000,
     918             :                 .hdmi_ycbcr420_supported = true,
     919             :                 .dp_ycbcr420_supported = true,
     920             :                 .fec_supported = true,
     921             :                 .flags.bits.IS_HBR2_CAPABLE = true,
     922             :                 .flags.bits.IS_HBR3_CAPABLE = true,
     923             :                 .flags.bits.IS_TPS3_CAPABLE = true,
     924             :                 .flags.bits.IS_TPS4_CAPABLE = true
     925             : };
     926             : 
     927           0 : struct link_encoder *dcn20_link_encoder_create(
     928             :         struct dc_context *ctx,
     929             :         const struct encoder_init_data *enc_init_data)
     930             : {
     931           0 :         struct dcn20_link_encoder *enc20 =
     932             :                 kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
     933             :         int link_regs_id;
     934             : 
     935           0 :         if (!enc20)
     936             :                 return NULL;
     937             : 
     938           0 :         link_regs_id =
     939           0 :                 map_transmitter_id_to_phy_instance(enc_init_data->transmitter);
     940             : 
     941           0 :         dcn20_link_encoder_construct(enc20,
     942             :                                       enc_init_data,
     943             :                                       &link_enc_feature,
     944             :                                       &link_enc_regs[link_regs_id],
     945           0 :                                       &link_enc_aux_regs[enc_init_data->channel - 1],
     946           0 :                                       &link_enc_hpd_regs[enc_init_data->hpd_source],
     947             :                                       &le_shift,
     948             :                                       &le_mask);
     949             : 
     950           0 :         return &enc20->enc10.base;
     951             : }
     952             : 
     953           0 : static struct panel_cntl *dcn20_panel_cntl_create(const struct panel_cntl_init_data *init_data)
     954             : {
     955           0 :         struct dce_panel_cntl *panel_cntl =
     956             :                 kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL);
     957             : 
     958           0 :         if (!panel_cntl)
     959             :                 return NULL;
     960             : 
     961           0 :         dce_panel_cntl_construct(panel_cntl,
     962             :                         init_data,
     963           0 :                         &panel_cntl_regs[init_data->inst],
     964             :                         &panel_cntl_shift,
     965             :                         &panel_cntl_mask);
     966             : 
     967           0 :         return &panel_cntl->base;
     968             : }
     969             : 
     970           0 : static struct clock_source *dcn20_clock_source_create(
     971             :         struct dc_context *ctx,
     972             :         struct dc_bios *bios,
     973             :         enum clock_source_id id,
     974             :         const struct dce110_clk_src_regs *regs,
     975             :         bool dp_clk_src)
     976             : {
     977           0 :         struct dce110_clk_src *clk_src =
     978             :                 kzalloc(sizeof(struct dce110_clk_src), GFP_ATOMIC);
     979             : 
     980           0 :         if (!clk_src)
     981             :                 return NULL;
     982             : 
     983           0 :         if (dcn20_clk_src_construct(clk_src, ctx, bios, id,
     984             :                         regs, &cs_shift, &cs_mask)) {
     985           0 :                 clk_src->base.dp_clk_src = dp_clk_src;
     986           0 :                 return &clk_src->base;
     987             :         }
     988             : 
     989           0 :         kfree(clk_src);
     990           0 :         BREAK_TO_DEBUGGER();
     991           0 :         return NULL;
     992             : }
     993             : 
     994           0 : static void read_dce_straps(
     995             :         struct dc_context *ctx,
     996             :         struct resource_straps *straps)
     997             : {
     998           0 :         generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX),
     999             :                 FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);
    1000           0 : }
    1001             : 
    1002           0 : static struct audio *dcn20_create_audio(
    1003             :                 struct dc_context *ctx, unsigned int inst)
    1004             : {
    1005           0 :         return dce_audio_create(ctx, inst,
    1006             :                         &audio_regs[inst], &audio_shift, &audio_mask);
    1007             : }
    1008             : 
    1009           0 : struct stream_encoder *dcn20_stream_encoder_create(
    1010             :         enum engine_id eng_id,
    1011             :         struct dc_context *ctx)
    1012             : {
    1013           0 :         struct dcn10_stream_encoder *enc1 =
    1014             :                 kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
    1015             : 
    1016           0 :         if (!enc1)
    1017             :                 return NULL;
    1018             : 
    1019           0 :         if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) {
    1020           0 :                 if (eng_id >= ENGINE_ID_DIGD)
    1021           0 :                         eng_id++;
    1022             :         }
    1023             : 
    1024           0 :         dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id,
    1025             :                                         &stream_enc_regs[eng_id],
    1026             :                                         &se_shift, &se_mask);
    1027             : 
    1028           0 :         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           0 : struct dce_hwseq *dcn20_hwseq_create(
    1044             :         struct dc_context *ctx)
    1045             : {
    1046           0 :         struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
    1047             : 
    1048           0 :         if (hws) {
    1049           0 :                 hws->ctx = ctx;
    1050           0 :                 hws->regs = &hwseq_reg;
    1051           0 :                 hws->shifts = &hwseq_shift;
    1052           0 :                 hws->masks = &hwseq_mask;
    1053             :         }
    1054           0 :         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           0 : void dcn20_clock_source_destroy(struct clock_source **clk_src)
    1074             : {
    1075           0 :         kfree(TO_DCE110_CLK_SRC(*clk_src));
    1076           0 :         *clk_src = NULL;
    1077           0 : }
    1078             : 
    1079             : 
    1080           0 : struct display_stream_compressor *dcn20_dsc_create(
    1081             :         struct dc_context *ctx, uint32_t inst)
    1082             : {
    1083           0 :         struct dcn20_dsc *dsc =
    1084             :                 kzalloc(sizeof(struct dcn20_dsc), GFP_ATOMIC);
    1085             : 
    1086           0 :         if (!dsc) {
    1087           0 :                 BREAK_TO_DEBUGGER();
    1088           0 :                 return NULL;
    1089             :         }
    1090             : 
    1091           0 :         dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
    1092           0 :         return &dsc->base;
    1093             : }
    1094             : 
    1095           0 : void dcn20_dsc_destroy(struct display_stream_compressor **dsc)
    1096             : {
    1097           0 :         kfree(container_of(*dsc, struct dcn20_dsc, base));
    1098           0 :         *dsc = NULL;
    1099           0 : }
    1100             : 
    1101             : 
    1102           0 : static void dcn20_resource_destruct(struct dcn20_resource_pool *pool)
    1103             : {
    1104             :         unsigned int i;
    1105             : 
    1106           0 :         for (i = 0; i < pool->base.stream_enc_count; i++) {
    1107           0 :                 if (pool->base.stream_enc[i] != NULL) {
    1108           0 :                         kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));
    1109           0 :                         pool->base.stream_enc[i] = NULL;
    1110             :                 }
    1111             :         }
    1112             : 
    1113           0 :         for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
    1114           0 :                 if (pool->base.dscs[i] != NULL)
    1115           0 :                         dcn20_dsc_destroy(&pool->base.dscs[i]);
    1116             :         }
    1117             : 
    1118           0 :         if (pool->base.mpc != NULL) {
    1119           0 :                 kfree(TO_DCN20_MPC(pool->base.mpc));
    1120           0 :                 pool->base.mpc = NULL;
    1121             :         }
    1122           0 :         if (pool->base.hubbub != NULL) {
    1123           0 :                 kfree(pool->base.hubbub);
    1124           0 :                 pool->base.hubbub = NULL;
    1125             :         }
    1126           0 :         for (i = 0; i < pool->base.pipe_count; i++) {
    1127           0 :                 if (pool->base.dpps[i] != NULL)
    1128           0 :                         dcn20_dpp_destroy(&pool->base.dpps[i]);
    1129             : 
    1130           0 :                 if (pool->base.ipps[i] != NULL)
    1131           0 :                         pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);
    1132             : 
    1133           0 :                 if (pool->base.hubps[i] != NULL) {
    1134           0 :                         kfree(TO_DCN20_HUBP(pool->base.hubps[i]));
    1135           0 :                         pool->base.hubps[i] = NULL;
    1136             :                 }
    1137             : 
    1138           0 :                 if (pool->base.irqs != NULL) {
    1139           0 :                         dal_irq_service_destroy(&pool->base.irqs);
    1140             :                 }
    1141             :         }
    1142             : 
    1143           0 :         for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
    1144           0 :                 if (pool->base.engines[i] != NULL)
    1145           0 :                         dce110_engine_destroy(&pool->base.engines[i]);
    1146           0 :                 if (pool->base.hw_i2cs[i] != NULL) {
    1147           0 :                         kfree(pool->base.hw_i2cs[i]);
    1148           0 :                         pool->base.hw_i2cs[i] = NULL;
    1149             :                 }
    1150           0 :                 if (pool->base.sw_i2cs[i] != NULL) {
    1151           0 :                         kfree(pool->base.sw_i2cs[i]);
    1152           0 :                         pool->base.sw_i2cs[i] = NULL;
    1153             :                 }
    1154             :         }
    1155             : 
    1156           0 :         for (i = 0; i < pool->base.res_cap->num_opp; i++) {
    1157           0 :                 if (pool->base.opps[i] != NULL)
    1158           0 :                         pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
    1159             :         }
    1160             : 
    1161           0 :         for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
    1162           0 :                 if (pool->base.timing_generators[i] != NULL) {
    1163           0 :                         kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
    1164           0 :                         pool->base.timing_generators[i] = NULL;
    1165             :                 }
    1166             :         }
    1167             : 
    1168           0 :         for (i = 0; i < pool->base.res_cap->num_dwb; i++) {
    1169           0 :                 if (pool->base.dwbc[i] != NULL) {
    1170           0 :                         kfree(TO_DCN20_DWBC(pool->base.dwbc[i]));
    1171           0 :                         pool->base.dwbc[i] = NULL;
    1172             :                 }
    1173           0 :                 if (pool->base.mcif_wb[i] != NULL) {
    1174           0 :                         kfree(TO_DCN20_MMHUBBUB(pool->base.mcif_wb[i]));
    1175           0 :                         pool->base.mcif_wb[i] = NULL;
    1176             :                 }
    1177             :         }
    1178             : 
    1179           0 :         for (i = 0; i < pool->base.audio_count; i++) {
    1180           0 :                 if (pool->base.audios[i])
    1181           0 :                         dce_aud_destroy(&pool->base.audios[i]);
    1182             :         }
    1183             : 
    1184           0 :         for (i = 0; i < pool->base.clk_src_count; i++) {
    1185           0 :                 if (pool->base.clock_sources[i] != NULL) {
    1186           0 :                         dcn20_clock_source_destroy(&pool->base.clock_sources[i]);
    1187             :                         pool->base.clock_sources[i] = NULL;
    1188             :                 }
    1189             :         }
    1190             : 
    1191           0 :         if (pool->base.dp_clock_source != NULL) {
    1192           0 :                 dcn20_clock_source_destroy(&pool->base.dp_clock_source);
    1193             :                 pool->base.dp_clock_source = NULL;
    1194             :         }
    1195             : 
    1196             : 
    1197           0 :         if (pool->base.abm != NULL)
    1198           0 :                 dce_abm_destroy(&pool->base.abm);
    1199             : 
    1200           0 :         if (pool->base.dmcu != NULL)
    1201           0 :                 dce_dmcu_destroy(&pool->base.dmcu);
    1202             : 
    1203           0 :         if (pool->base.dccg != NULL)
    1204           0 :                 dcn_dccg_destroy(&pool->base.dccg);
    1205             : 
    1206           0 :         if (pool->base.pp_smu != NULL)
    1207           0 :                 dcn20_pp_smu_destroy(&pool->base.pp_smu);
    1208             : 
    1209           0 :         if (pool->base.oem_device != NULL)
    1210           0 :                 dal_ddc_service_destroy(&pool->base.oem_device);
    1211           0 : }
    1212             : 
    1213           0 : struct hubp *dcn20_hubp_create(
    1214             :         struct dc_context *ctx,
    1215             :         uint32_t inst)
    1216             : {
    1217           0 :         struct dcn20_hubp *hubp2 =
    1218             :                 kzalloc(sizeof(struct dcn20_hubp), GFP_ATOMIC);
    1219             : 
    1220           0 :         if (!hubp2)
    1221             :                 return NULL;
    1222             : 
    1223           0 :         if (hubp2_construct(hubp2, ctx, inst,
    1224             :                         &hubp_regs[inst], &hubp_shift, &hubp_mask))
    1225           0 :                 return &hubp2->base;
    1226             : 
    1227           0 :         BREAK_TO_DEBUGGER();
    1228           0 :         kfree(hubp2);
    1229           0 :         return NULL;
    1230             : }
    1231             : 
    1232           0 : static void get_pixel_clock_parameters(
    1233             :         struct pipe_ctx *pipe_ctx,
    1234             :         struct pixel_clk_params *pixel_clk_params)
    1235             : {
    1236           0 :         const struct dc_stream_state *stream = pipe_ctx->stream;
    1237             :         struct pipe_ctx *odm_pipe;
    1238           0 :         int opp_cnt = 1;
    1239           0 :         struct dc_link *link = stream->link;
    1240           0 :         struct link_encoder *link_enc = NULL;
    1241           0 :         struct dc *dc = pipe_ctx->stream->ctx->dc;
    1242           0 :         struct dce_hwseq *hws = dc->hwseq;
    1243             : 
    1244           0 :         for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
    1245           0 :                 opp_cnt++;
    1246             : 
    1247           0 :         pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
    1248             : 
    1249           0 :         link_enc = link_enc_cfg_get_link_enc(link);
    1250           0 :         if (link_enc)
    1251           0 :                 pixel_clk_params->encoder_object_id = link_enc->id;
    1252             : 
    1253           0 :         pixel_clk_params->signal_type = pipe_ctx->stream->signal;
    1254           0 :         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           0 :         pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
    1258             :                 LINK_RATE_REF_FREQ_IN_KHZ;
    1259           0 :         pixel_clk_params->flags.ENABLE_SS = 0;
    1260           0 :         pixel_clk_params->color_depth =
    1261           0 :                 stream->timing.display_color_depth;
    1262           0 :         pixel_clk_params->flags.DISPLAY_BLANKED = 1;
    1263           0 :         pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding;
    1264             : 
    1265           0 :         if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
    1266           0 :                 pixel_clk_params->color_depth = COLOR_DEPTH_888;
    1267             : 
    1268           0 :         if (opp_cnt == 4)
    1269           0 :                 pixel_clk_params->requested_pix_clk_100hz /= 4;
    1270           0 :         else if (optc2_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2)
    1271           0 :                 pixel_clk_params->requested_pix_clk_100hz /= 2;
    1272           0 :         else if (hws->funcs.is_dp_dig_pixel_rate_div_policy) {
    1273           0 :                 if (hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx))
    1274           0 :                         pixel_clk_params->requested_pix_clk_100hz /= 2;
    1275             :         }
    1276             : 
    1277           0 :         if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
    1278           0 :                 pixel_clk_params->requested_pix_clk_100hz *= 2;
    1279             : 
    1280           0 : }
    1281             : 
    1282             : static void build_clamping_params(struct dc_stream_state *stream)
    1283             : {
    1284           0 :         stream->clamping.clamping_level = CLAMPING_FULL_RANGE;
    1285           0 :         stream->clamping.c_depth = stream->timing.display_color_depth;
    1286           0 :         stream->clamping.pixel_encoding = stream->timing.pixel_encoding;
    1287             : }
    1288             : 
    1289           0 : static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
    1290             : {
    1291             : 
    1292           0 :         get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params);
    1293             : 
    1294           0 :         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           0 :         pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding;
    1300             : 
    1301           0 :         resource_build_bit_depth_reduction_params(pipe_ctx->stream,
    1302           0 :                                         &pipe_ctx->stream->bit_depth_params);
    1303           0 :         build_clamping_params(pipe_ctx->stream);
    1304             : 
    1305           0 :         return DC_OK;
    1306             : }
    1307             : 
    1308           0 : enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream)
    1309             : {
    1310           0 :         enum dc_status status = DC_OK;
    1311           0 :         struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream);
    1312             : 
    1313           0 :         if (!pipe_ctx)
    1314             :                 return DC_ERROR_UNEXPECTED;
    1315             : 
    1316             : 
    1317           0 :         status = build_pipe_hw_param(pipe_ctx);
    1318             : 
    1319           0 :         return status;
    1320             : }
    1321             : 
    1322             : 
    1323           0 : 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           0 :         const struct resource_pool *pool = dc->res_pool;
    1330           0 :         struct display_stream_compressor *dsc_old = dc->current_state->res_ctx.pipe_ctx[pipe_idx].stream_res.dsc;
    1331             : 
    1332           0 :         ASSERT(*dsc == NULL); /* If this ASSERT fails, dsc was not released properly */
    1333           0 :         *dsc = NULL;
    1334             : 
    1335             :         /* Always do 1-to-1 mapping when number of DSCs is same as number of pipes */
    1336           0 :         if (pool->res_cap->num_dsc == pool->res_cap->num_opp) {
    1337           0 :                 *dsc = pool->dscs[pipe_idx];
    1338           0 :                 res_ctx->is_dsc_acquired[pipe_idx] = true;
    1339           0 :                 return;
    1340             :         }
    1341             : 
    1342             :         /* Return old DSC to avoid the need for re-programming */
    1343           0 :         if (dsc_old && !res_ctx->is_dsc_acquired[dsc_old->inst]) {
    1344           0 :                 *dsc = dsc_old;
    1345           0 :                 res_ctx->is_dsc_acquired[dsc_old->inst] = true;
    1346           0 :                 return ;
    1347             :         }
    1348             : 
    1349             :         /* Find first free DSC */
    1350           0 :         for (i = 0; i < pool->res_cap->num_dsc; i++)
    1351           0 :                 if (!res_ctx->is_dsc_acquired[i]) {
    1352           0 :                         *dsc = pool->dscs[i];
    1353           0 :                         res_ctx->is_dsc_acquired[i] = true;
    1354           0 :                         break;
    1355             :                 }
    1356             : }
    1357             : 
    1358           0 : 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           0 :         for (i = 0; i < pool->res_cap->num_dsc; i++)
    1365           0 :                 if (pool->dscs[i] == *dsc) {
    1366           0 :                         res_ctx->is_dsc_acquired[i] = false;
    1367           0 :                         *dsc = NULL;
    1368           0 :                         break;
    1369             :                 }
    1370           0 : }
    1371             : 
    1372             : 
    1373             : 
    1374           0 : 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           0 :         enum dc_status result = DC_OK;
    1379             :         int i;
    1380             : 
    1381             :         /* Get a DSC if required and available */
    1382           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    1383           0 :                 struct pipe_ctx *pipe_ctx = &dc_ctx->res_ctx.pipe_ctx[i];
    1384             : 
    1385           0 :                 if (pipe_ctx->stream != dc_stream)
    1386           0 :                         continue;
    1387             : 
    1388           0 :                 if (pipe_ctx->stream_res.dsc)
    1389           0 :                         continue;
    1390             : 
    1391           0 :                 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           0 :                 if (!pipe_ctx->stream_res.dsc) {
    1395           0 :                         result = DC_NO_DSC_RESOURCE;
    1396             :                 }
    1397             : 
    1398             :                 break;
    1399             :         }
    1400             : 
    1401           0 :         return result;
    1402             : }
    1403             : 
    1404             : 
    1405           0 : 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           0 :         struct pipe_ctx *pipe_ctx = NULL;
    1410             :         int i;
    1411             : 
    1412           0 :         for (i = 0; i < MAX_PIPES; i++) {
    1413           0 :                 if (new_ctx->res_ctx.pipe_ctx[i].stream == dc_stream && !new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
    1414           0 :                         pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
    1415             : 
    1416           0 :                         if (pipe_ctx->stream_res.dsc)
    1417           0 :                                 dcn20_release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc);
    1418             :                 }
    1419             :         }
    1420             : 
    1421           0 :         if (!pipe_ctx)
    1422             :                 return DC_ERROR_UNEXPECTED;
    1423             :         else
    1424             :                 return DC_OK;
    1425             : }
    1426             : 
    1427             : 
    1428           0 : enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream)
    1429             : {
    1430           0 :         enum dc_status result = DC_ERROR_UNEXPECTED;
    1431             : 
    1432           0 :         result = resource_map_pool_resources(dc, new_ctx, dc_stream);
    1433             : 
    1434           0 :         if (result == DC_OK)
    1435           0 :                 result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream);
    1436             : 
    1437             :         /* Get a DSC if required and available */
    1438           0 :         if (result == DC_OK && dc_stream->timing.flags.DSC)
    1439           0 :                 result = dcn20_add_dsc_to_stream_resource(dc, new_ctx, dc_stream);
    1440             : 
    1441           0 :         if (result == DC_OK)
    1442             :                 result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream);
    1443             : 
    1444           0 :         return result;
    1445             : }
    1446             : 
    1447             : 
    1448           0 : enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream)
    1449             : {
    1450           0 :         enum dc_status result = DC_OK;
    1451             : 
    1452           0 :         result = remove_dsc_from_stream_resource(dc, new_ctx, dc_stream);
    1453             : 
    1454           0 :         return result;
    1455             : }
    1456             : 
    1457           0 : 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           0 :         int pipe_idx = next_odm_pipe->pipe_idx;
    1464           0 :         const struct resource_pool *pool = dc->res_pool;
    1465             : 
    1466           0 :         *next_odm_pipe = *prev_odm_pipe;
    1467             : 
    1468           0 :         next_odm_pipe->pipe_idx = pipe_idx;
    1469           0 :         next_odm_pipe->plane_res.mi = pool->mis[next_odm_pipe->pipe_idx];
    1470           0 :         next_odm_pipe->plane_res.hubp = pool->hubps[next_odm_pipe->pipe_idx];
    1471           0 :         next_odm_pipe->plane_res.ipp = pool->ipps[next_odm_pipe->pipe_idx];
    1472           0 :         next_odm_pipe->plane_res.xfm = pool->transforms[next_odm_pipe->pipe_idx];
    1473           0 :         next_odm_pipe->plane_res.dpp = pool->dpps[next_odm_pipe->pipe_idx];
    1474           0 :         next_odm_pipe->plane_res.mpcc_inst = pool->dpps[next_odm_pipe->pipe_idx]->inst;
    1475           0 :         next_odm_pipe->stream_res.dsc = NULL;
    1476           0 :         if (prev_odm_pipe->next_odm_pipe && prev_odm_pipe->next_odm_pipe != next_odm_pipe) {
    1477           0 :                 next_odm_pipe->next_odm_pipe = prev_odm_pipe->next_odm_pipe;
    1478           0 :                 next_odm_pipe->next_odm_pipe->prev_odm_pipe = next_odm_pipe;
    1479             :         }
    1480           0 :         if (prev_odm_pipe->top_pipe && prev_odm_pipe->top_pipe->next_odm_pipe) {
    1481           0 :                 prev_odm_pipe->top_pipe->next_odm_pipe->bottom_pipe = next_odm_pipe;
    1482           0 :                 next_odm_pipe->top_pipe = prev_odm_pipe->top_pipe->next_odm_pipe;
    1483             :         }
    1484           0 :         if (prev_odm_pipe->bottom_pipe && prev_odm_pipe->bottom_pipe->next_odm_pipe) {
    1485           0 :                 prev_odm_pipe->bottom_pipe->next_odm_pipe->top_pipe = next_odm_pipe;
    1486           0 :                 next_odm_pipe->bottom_pipe = prev_odm_pipe->bottom_pipe->next_odm_pipe;
    1487             :         }
    1488           0 :         prev_odm_pipe->next_odm_pipe = next_odm_pipe;
    1489           0 :         next_odm_pipe->prev_odm_pipe = prev_odm_pipe;
    1490             : 
    1491           0 :         if (prev_odm_pipe->plane_state) {
    1492           0 :                 struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data;
    1493             :                 int new_width;
    1494             : 
    1495             :                 /* HACTIVE halved for odm combine */
    1496           0 :                 sd->h_active /= 2;
    1497             :                 /* Calculate new vp and recout for left pipe */
    1498             :                 /* Need at least 16 pixels width per side */
    1499           0 :                 if (sd->recout.x + 16 >= sd->h_active)
    1500             :                         return false;
    1501           0 :                 new_width = sd->h_active - sd->recout.x;
    1502           0 :                 sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
    1503           0 :                                 sd->ratios.horz, sd->recout.width - new_width));
    1504           0 :                 sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
    1505           0 :                                 sd->ratios.horz_c, sd->recout.width - new_width));
    1506           0 :                 sd->recout.width = new_width;
    1507             : 
    1508             :                 /* Calculate new vp and recout for right pipe */
    1509           0 :                 sd = &next_odm_pipe->plane_res.scl_data;
    1510             :                 /* HACTIVE halved for odm combine */
    1511           0 :                 sd->h_active /= 2;
    1512             :                 /* Need at least 16 pixels width per side */
    1513           0 :                 if (new_width <= 16)
    1514             :                         return false;
    1515           0 :                 new_width = sd->recout.width + sd->recout.x - sd->h_active;
    1516           0 :                 sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
    1517             :                                 sd->ratios.horz, sd->recout.width - new_width));
    1518           0 :                 sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
    1519           0 :                                 sd->ratios.horz_c, sd->recout.width - new_width));
    1520           0 :                 sd->recout.width = new_width;
    1521           0 :                 sd->viewport.x += dc_fixpt_floor(dc_fixpt_mul_int(
    1522           0 :                                 sd->ratios.horz, sd->h_active - sd->recout.x));
    1523           0 :                 sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int(
    1524           0 :                                 sd->ratios.horz_c, sd->h_active - sd->recout.x));
    1525           0 :                 sd->recout.x = 0;
    1526             :         }
    1527           0 :         if (!next_odm_pipe->top_pipe)
    1528           0 :                 next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
    1529             :         else
    1530           0 :                 next_odm_pipe->stream_res.opp = next_odm_pipe->top_pipe->stream_res.opp;
    1531           0 :         if (next_odm_pipe->stream->timing.flags.DSC == 1 && !next_odm_pipe->top_pipe) {
    1532           0 :                 dcn20_acquire_dsc(dc, res_ctx, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx);
    1533           0 :                 ASSERT(next_odm_pipe->stream_res.dsc);
    1534           0 :                 if (next_odm_pipe->stream_res.dsc == NULL)
    1535             :                         return false;
    1536             :         }
    1537             : 
    1538             :         return true;
    1539             : }
    1540             : 
    1541           0 : 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           0 :         int pipe_idx = secondary_pipe->pipe_idx;
    1548           0 :         struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe;
    1549             : 
    1550           0 :         *secondary_pipe = *primary_pipe;
    1551           0 :         secondary_pipe->bottom_pipe = sec_bot_pipe;
    1552             : 
    1553           0 :         secondary_pipe->pipe_idx = pipe_idx;
    1554           0 :         secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx];
    1555           0 :         secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx];
    1556           0 :         secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx];
    1557           0 :         secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx];
    1558           0 :         secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx];
    1559           0 :         secondary_pipe->plane_res.mpcc_inst = pool->dpps[secondary_pipe->pipe_idx]->inst;
    1560           0 :         secondary_pipe->stream_res.dsc = NULL;
    1561           0 :         if (primary_pipe->bottom_pipe && primary_pipe->bottom_pipe != secondary_pipe) {
    1562           0 :                 ASSERT(!secondary_pipe->bottom_pipe);
    1563           0 :                 secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe;
    1564           0 :                 secondary_pipe->bottom_pipe->top_pipe = secondary_pipe;
    1565             :         }
    1566           0 :         primary_pipe->bottom_pipe = secondary_pipe;
    1567           0 :         secondary_pipe->top_pipe = primary_pipe;
    1568             : 
    1569           0 :         ASSERT(primary_pipe->plane_state);
    1570           0 : }
    1571             : 
    1572           0 : 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           0 :         unsigned int time_per_byte = 0;
    1578           0 :         unsigned int total_y_free_entry = 0x200; /* two memory piece for luma */
    1579           0 :         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           0 :         if (mode == PACKED_444) /* packed mode */
    1585           0 :                 time_per_byte = time_per_pixel/4;
    1586           0 :         else if (mode == PLANAR_420_8BPC)
    1587             :                 time_per_byte  = time_per_pixel;
    1588           0 :         else if (mode == PLANAR_420_10BPC) /* p010 */
    1589           0 :                 time_per_byte  = time_per_pixel * 819/1024;
    1590             : 
    1591           0 :         if (time_per_byte == 0)
    1592           0 :                 time_per_byte = 1;
    1593             : 
    1594           0 :         small_free_entry  = (total_y_free_entry > total_c_free_entry) ? total_c_free_entry : total_y_free_entry;
    1595           0 :         max_free_entry    = (mode == PACKED_444) ? total_y_free_entry + total_c_free_entry : small_free_entry;
    1596           0 :         buf_lh_capability = max_free_entry*time_per_byte*32/16; /* there is 4bit fraction */
    1597           0 :         max_scaled_time   = buf_lh_capability - urgent_watermark;
    1598           0 :         return max_scaled_time;
    1599             : }
    1600             : 
    1601           0 : 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           0 :         dwb_pipe = 0;
    1613           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    1614             : 
    1615           0 :                 if (!context->res_ctx.pipe_ctx[i].stream)
    1616           0 :                         continue;
    1617             : 
    1618           0 :                 for (j = 0; j < MAX_DWB_PIPES; j++) {
    1619           0 :                         if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].wb_enabled == false)
    1620           0 :                                 continue;
    1621             : 
    1622             :                         //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params;
    1623           0 :                         wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe];
    1624             : 
    1625           0 :                         if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.out_format == dwb_scaler_mode_yuv420) {
    1626           0 :                                 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           0 :                                         wbif_mode = PLANAR_420_10BPC;
    1630             :                         } else
    1631             :                                 wbif_mode = PACKED_444;
    1632             : 
    1633           0 :                         DC_FP_START();
    1634           0 :                         dcn20_fpu_set_wb_arb_params(wb_arb_params, context, pipes, pipe_cnt, i);
    1635           0 :                         DC_FP_END();
    1636             : 
    1637           0 :                         wb_arb_params->slice_lines = 32;
    1638           0 :                         wb_arb_params->arbitration_slice = 2;
    1639           0 :                         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           0 :                         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           0 : 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           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    1659           0 :                 struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
    1660           0 :                 struct dc_stream_state *stream = pipe_ctx->stream;
    1661             :                 struct dsc_config dsc_cfg;
    1662             :                 struct pipe_ctx *odm_pipe;
    1663           0 :                 int opp_cnt = 1;
    1664             : 
    1665           0 :                 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
    1666           0 :                         opp_cnt++;
    1667             : 
    1668             :                 /* Only need to validate top pipe */
    1669           0 :                 if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe || !stream || !stream->timing.flags.DSC)
    1670           0 :                         continue;
    1671             : 
    1672           0 :                 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left
    1673           0 :                                 + stream->timing.h_border_right) / opp_cnt;
    1674           0 :                 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top
    1675           0 :                                 + stream->timing.v_border_bottom;
    1676           0 :                 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
    1677           0 :                 dsc_cfg.color_depth = stream->timing.display_color_depth;
    1678           0 :                 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
    1679           0 :                 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
    1680           0 :                 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
    1681             : 
    1682           0 :                 if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
    1683           0 :                         return false;
    1684             :         }
    1685             :         return true;
    1686             : }
    1687             : 
    1688           0 : 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           0 :         struct pipe_ctx *secondary_pipe = NULL;
    1694             : 
    1695           0 :         if (dc && primary_pipe) {
    1696             :                 int j;
    1697           0 :                 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           0 :                 if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
    1706           0 :                         preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
    1707           0 :                         if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
    1708           0 :                                 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
    1709           0 :                                 secondary_pipe->pipe_idx = preferred_pipe_idx;
    1710             :                         }
    1711             :                 }
    1712           0 :                 if (secondary_pipe == NULL &&
    1713           0 :                                 dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
    1714           0 :                         preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
    1715           0 :                         if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
    1716           0 :                                 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
    1717           0 :                                 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           0 :                 if (secondary_pipe == NULL) {
    1728           0 :                         for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
    1729           0 :                                 if (dc->current_state->res_ctx.pipe_ctx[j].top_pipe == NULL
    1730           0 :                                                 && dc->current_state->res_ctx.pipe_ctx[j].prev_odm_pipe == NULL) {
    1731           0 :                                         preferred_pipe_idx = j;
    1732             : 
    1733           0 :                                         if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
    1734           0 :                                                 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
    1735           0 :                                                 secondary_pipe->pipe_idx = preferred_pipe_idx;
    1736           0 :                                                 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           0 :                 ASSERT(secondary_pipe);
    1746             :                 /*
    1747             :                  * search backwards for the second pipe to keep pipe
    1748             :                  * assignment more consistent
    1749             :                  */
    1750           0 :                 if (secondary_pipe == NULL) {
    1751           0 :                         for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) {
    1752           0 :                                 preferred_pipe_idx = j;
    1753             : 
    1754           0 :                                 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
    1755           0 :                                         secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
    1756           0 :                                         secondary_pipe->pipe_idx = preferred_pipe_idx;
    1757           0 :                                         break;
    1758             :                                 }
    1759             :                         }
    1760             :                 }
    1761             :         }
    1762             : 
    1763           0 :         return secondary_pipe;
    1764             : }
    1765             : 
    1766           0 : 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           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    1774           0 :                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
    1775           0 :                 struct pipe_ctx *odm_pipe = pipe->next_odm_pipe;
    1776             : 
    1777           0 :                 if (pipe->prev_odm_pipe)
    1778           0 :                         continue;
    1779             : 
    1780           0 :                 pipe->next_odm_pipe = NULL;
    1781           0 :                 while (odm_pipe) {
    1782           0 :                         struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
    1783             : 
    1784           0 :                         odm_pipe->plane_state = NULL;
    1785           0 :                         odm_pipe->stream = NULL;
    1786           0 :                         odm_pipe->top_pipe = NULL;
    1787           0 :                         odm_pipe->bottom_pipe = NULL;
    1788           0 :                         odm_pipe->prev_odm_pipe = NULL;
    1789           0 :                         odm_pipe->next_odm_pipe = NULL;
    1790           0 :                         if (odm_pipe->stream_res.dsc)
    1791           0 :                                 dcn20_release_dsc(&context->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc);
    1792             :                         /* Clear plane_res and stream_res */
    1793           0 :                         memset(&odm_pipe->plane_res, 0, sizeof(odm_pipe->plane_res));
    1794           0 :                         memset(&odm_pipe->stream_res, 0, sizeof(odm_pipe->stream_res));
    1795           0 :                         odm_pipe = next_odm_pipe;
    1796             :                 }
    1797           0 :                 if (pipe->plane_state)
    1798           0 :                         resource_build_scaling_params(pipe);
    1799             :         }
    1800             : 
    1801             :         /* merge previously mpc split pipes since mode support needs to make the decision */
    1802           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    1803           0 :                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
    1804           0 :                 struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe;
    1805             : 
    1806           0 :                 if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state)
    1807           0 :                         continue;
    1808             : 
    1809           0 :                 pipe->bottom_pipe = hsplit_pipe->bottom_pipe;
    1810           0 :                 if (hsplit_pipe->bottom_pipe)
    1811           0 :                         hsplit_pipe->bottom_pipe->top_pipe = pipe;
    1812           0 :                 hsplit_pipe->plane_state = NULL;
    1813           0 :                 hsplit_pipe->stream = NULL;
    1814           0 :                 hsplit_pipe->top_pipe = NULL;
    1815           0 :                 hsplit_pipe->bottom_pipe = NULL;
    1816             : 
    1817             :                 /* Clear plane_res and stream_res */
    1818           0 :                 memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res));
    1819           0 :                 memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res));
    1820           0 :                 if (pipe->plane_state)
    1821           0 :                         resource_build_scaling_params(pipe);
    1822             :         }
    1823           0 : }
    1824             : 
    1825           0 : 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           0 :         int plane_count = 0;
    1834           0 :         bool force_split = false;
    1835           0 :         bool avoid_split = dc->debug.pipe_split_policy == MPC_SPLIT_AVOID;
    1836           0 :         struct vba_vars_st *v = &context->bw_ctx.dml.vba;
    1837           0 :         int max_mpc_comb = v->maxMpcComb;
    1838             : 
    1839           0 :         if (context->stream_count > 1) {
    1840           0 :                 if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP)
    1841           0 :                         avoid_split = true;
    1842           0 :         } else if (dc->debug.force_single_disp_pipe_split)
    1843           0 :                         force_split = true;
    1844             : 
    1845           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    1846           0 :                 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           0 :                 if (pipe->plane_state &&
    1854           0 :                     (pipe->plane_state->dst_rect.width <= 16 ||
    1855           0 :                      pipe->plane_state->dst_rect.height <= 16 ||
    1856           0 :                      pipe->plane_state->src_rect.width <= 16 ||
    1857           0 :                      pipe->plane_state->src_rect.height <= 16))
    1858           0 :                         avoid_split = true;
    1859             : 
    1860             :                 /* TODO: fix dc bugs and remove this split threshold thing */
    1861           0 :                 if (pipe->stream && !pipe->prev_odm_pipe &&
    1862           0 :                                 (!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state))
    1863           0 :                         ++plane_count;
    1864             :         }
    1865           0 :         if (plane_count > dc->res_pool->pipe_count / 2)
    1866           0 :                 avoid_split = true;
    1867             : 
    1868             :         /* W/A: Mode timing with borders may not work well with pipe split, avoid for this corner case */
    1869           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    1870           0 :                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
    1871             :                 struct dc_crtc_timing timing;
    1872             : 
    1873           0 :                 if (!pipe->stream)
    1874           0 :                         continue;
    1875             :                 else {
    1876           0 :                         timing = pipe->stream->timing;
    1877           0 :                         if (timing.h_border_left + timing.h_border_right
    1878           0 :                                         + 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           0 :         if (avoid_split) {
    1887           0 :                 for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
    1888           0 :                         if (!context->res_ctx.pipe_ctx[i].stream)
    1889           0 :                                 continue;
    1890             : 
    1891           0 :                         for (vlevel_split = vlevel; vlevel <= context->bw_ctx.dml.soc.num_states; vlevel++)
    1892           0 :                                 if (v->NoOfDPP[vlevel][0][pipe_idx] == 1 &&
    1893           0 :                                                 v->ModeSupport[vlevel][0])
    1894             :                                         break;
    1895             :                         /* Impossible to not split this pipe */
    1896           0 :                         if (vlevel > context->bw_ctx.dml.soc.num_states)
    1897             :                                 vlevel = vlevel_split;
    1898             :                         else
    1899           0 :                                 max_mpc_comb = 0;
    1900           0 :                         pipe_idx++;
    1901             :                 }
    1902           0 :                 v->maxMpcComb = max_mpc_comb;
    1903             :         }
    1904             : 
    1905             :         /* Split loop sets which pipe should be split based on dml outputs and dc flags */
    1906           0 :         for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
    1907           0 :                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
    1908           0 :                 int pipe_plane = v->pipe_plane[pipe_idx];
    1909           0 :                 bool split4mpc = context->stream_count == 1 && plane_count == 1
    1910           0 :                                 && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4;
    1911             : 
    1912           0 :                 if (!context->res_ctx.pipe_ctx[i].stream)
    1913           0 :                         continue;
    1914             : 
    1915           0 :                 if (split4mpc || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 4)
    1916           0 :                         split[i] = 4;
    1917           0 :                 else if (force_split || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 2)
    1918           0 :                                 split[i] = 2;
    1919             : 
    1920           0 :                 if ((pipe->stream->view_format ==
    1921           0 :                                 VIEW_3D_FORMAT_SIDE_BY_SIDE ||
    1922             :                                 pipe->stream->view_format ==
    1923           0 :                                 VIEW_3D_FORMAT_TOP_AND_BOTTOM) &&
    1924           0 :                                 (pipe->stream->timing.timing_3d_format ==
    1925           0 :                                 TIMING_3D_FORMAT_TOP_AND_BOTTOM ||
    1926             :                                  pipe->stream->timing.timing_3d_format ==
    1927             :                                 TIMING_3D_FORMAT_SIDE_BY_SIDE))
    1928           0 :                         split[i] = 2;
    1929           0 :                 if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) {
    1930           0 :                         split[i] = 2;
    1931           0 :                         v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_2to1;
    1932             :                 }
    1933           0 :                 if (dc->debug.force_odm_combine_4to1 & (1 << pipe->stream_res.tg->inst)) {
    1934           0 :                         split[i] = 4;
    1935           0 :                         v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_4to1;
    1936             :                 }
    1937             :                 /*420 format workaround*/
    1938           0 :                 if (pipe->stream->timing.h_addressable > 7680 &&
    1939           0 :                                 pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
    1940           0 :                         split[i] = 4;
    1941             :                 }
    1942           0 :                 v->ODMCombineEnabled[pipe_plane] =
    1943           0 :                         v->ODMCombineEnablePerState[vlevel][pipe_plane];
    1944             : 
    1945           0 :                 if (v->ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) {
    1946           0 :                         if (get_num_mpc_splits(pipe) == 1) {
    1947             :                                 /*If need split for mpc but 2 way split already*/
    1948           0 :                                 if (split[i] == 4)
    1949           0 :                                         split[i] = 2; /* 2 -> 4 MPC */
    1950           0 :                                 else if (split[i] == 2)
    1951           0 :                                         split[i] = 0; /* 2 -> 2 MPC */
    1952           0 :                                 else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state)
    1953           0 :                                         merge[i] = true; /* 2 -> 1 MPC */
    1954           0 :                         } else if (get_num_mpc_splits(pipe) == 3) {
    1955             :                                 /*If need split for mpc but 4 way split already*/
    1956           0 :                                 if (split[i] == 2 && ((pipe->top_pipe && !pipe->top_pipe->top_pipe)
    1957           0 :                                                 || !pipe->bottom_pipe)) {
    1958           0 :                                         merge[i] = true; /* 4 -> 2 MPC */
    1959           0 :                                 } else if (split[i] == 0 && pipe->top_pipe &&
    1960           0 :                                                 pipe->top_pipe->plane_state == pipe->plane_state)
    1961           0 :                                         merge[i] = true; /* 4 -> 1 MPC */
    1962           0 :                                 split[i] = 0;
    1963           0 :                         } else if (get_num_odm_splits(pipe)) {
    1964             :                                 /* ODM -> MPC transition */
    1965           0 :                                 if (pipe->prev_odm_pipe) {
    1966           0 :                                         split[i] = 0;
    1967           0 :                                         merge[i] = true;
    1968             :                                 }
    1969             :                         }
    1970             :                 } else {
    1971           0 :                         if (get_num_odm_splits(pipe) == 1) {
    1972             :                                 /*If need split for odm but 2 way split already*/
    1973           0 :                                 if (split[i] == 4)
    1974           0 :                                         split[i] = 2; /* 2 -> 4 ODM */
    1975           0 :                                 else if (split[i] == 2)
    1976           0 :                                         split[i] = 0; /* 2 -> 2 ODM */
    1977           0 :                                 else if (pipe->prev_odm_pipe) {
    1978           0 :                                         ASSERT(0); /* NOT expected yet */
    1979           0 :                                         merge[i] = true; /* exit ODM */
    1980             :                                 }
    1981           0 :                         } else if (get_num_odm_splits(pipe) == 3) {
    1982             :                                 /*If need split for odm but 4 way split already*/
    1983           0 :                                 if (split[i] == 2 && ((pipe->prev_odm_pipe && !pipe->prev_odm_pipe->prev_odm_pipe)
    1984           0 :                                                 || !pipe->next_odm_pipe)) {
    1985           0 :                                         merge[i] = true; /* 4 -> 2 ODM */
    1986           0 :                                 } else if (split[i] == 0 && pipe->prev_odm_pipe) {
    1987           0 :                                         ASSERT(0); /* NOT expected yet */
    1988           0 :                                         merge[i] = true; /* exit ODM */
    1989             :                                 }
    1990           0 :                                 split[i] = 0;
    1991           0 :                         } else if (get_num_mpc_splits(pipe)) {
    1992             :                                 /* MPC -> ODM transition */
    1993           0 :                                 ASSERT(0); /* NOT expected yet */
    1994           0 :                                 if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) {
    1995           0 :                                         split[i] = 0;
    1996           0 :                                         merge[i] = true;
    1997             :                                 }
    1998             :                         }
    1999             :                 }
    2000             : 
    2001             :                 /* Adjust dppclk when split is forced, do not bother with dispclk */
    2002           0 :                 if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] == 1) {
    2003           0 :                         DC_FP_START();
    2004           0 :                         dcn20_fpu_adjust_dppclk(v, vlevel, max_mpc_comb, pipe_idx, false);
    2005           0 :                         DC_FP_END();
    2006             :                 }
    2007           0 :                 pipe_idx++;
    2008             :         }
    2009             : 
    2010           0 :         return vlevel;
    2011             : }
    2012             : 
    2013           0 : 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           0 :         bool out = false;
    2023           0 :         int split[MAX_PIPES] = { 0 };
    2024             :         int pipe_cnt, i, pipe_idx, vlevel;
    2025             : 
    2026           0 :         ASSERT(pipes);
    2027           0 :         if (!pipes)
    2028             :                 return false;
    2029             : 
    2030           0 :         dcn20_merge_pipes_for_validate(dc, context);
    2031             : 
    2032           0 :         DC_FP_START();
    2033           0 :         pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
    2034           0 :         DC_FP_END();
    2035             : 
    2036           0 :         *pipe_cnt_out = pipe_cnt;
    2037             : 
    2038           0 :         if (!pipe_cnt) {
    2039             :                 out = true;
    2040             :                 goto validate_out;
    2041             :         }
    2042             : 
    2043           0 :         vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
    2044             : 
    2045           0 :         if (vlevel > context->bw_ctx.dml.soc.num_states)
    2046             :                 goto validate_fail;
    2047             : 
    2048           0 :         vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL);
    2049             : 
    2050             :         /*initialize pipe_just_split_from to invalid idx*/
    2051           0 :         for (i = 0; i < MAX_PIPES; i++)
    2052           0 :                 pipe_split_from[i] = -1;
    2053             : 
    2054           0 :         for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) {
    2055           0 :                 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
    2056           0 :                 struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe;
    2057             : 
    2058           0 :                 if (!pipe->stream || pipe_split_from[i] >= 0)
    2059           0 :                         continue;
    2060             : 
    2061           0 :                 pipe_idx++;
    2062             : 
    2063           0 :                 if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
    2064           0 :                         hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
    2065           0 :                         ASSERT(hsplit_pipe);
    2066           0 :                         if (!dcn20_split_stream_for_odm(
    2067             :                                         dc, &context->res_ctx,
    2068             :                                         pipe, hsplit_pipe))
    2069             :                                 goto validate_fail;
    2070           0 :                         pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
    2071           0 :                         dcn20_build_mapped_resource(dc, context, pipe->stream);
    2072             :                 }
    2073             : 
    2074           0 :                 if (!pipe->plane_state)
    2075           0 :                         continue;
    2076             :                 /* Skip 2nd half of already split pipe */
    2077           0 :                 if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state)
    2078           0 :                         continue;
    2079             : 
    2080             :                 /* We do not support mpo + odm at the moment */
    2081           0 :                 if (hsplit_pipe && hsplit_pipe->plane_state != pipe->plane_state
    2082           0 :                                 && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx])
    2083             :                         goto validate_fail;
    2084             : 
    2085           0 :                 if (split[i] == 2) {
    2086           0 :                         if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) {
    2087             :                                 /* pipe not split previously needs split */
    2088           0 :                                 hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
    2089           0 :                                 ASSERT(hsplit_pipe);
    2090           0 :                                 if (!hsplit_pipe) {
    2091           0 :                                         DC_FP_START();
    2092           0 :                                         dcn20_fpu_adjust_dppclk(&context->bw_ctx.dml.vba, vlevel, context->bw_ctx.dml.vba.maxMpcComb, pipe_idx, true);
    2093           0 :                                         DC_FP_END();
    2094           0 :                                         continue;
    2095             :                                 }
    2096           0 :                                 if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
    2097           0 :                                         if (!dcn20_split_stream_for_odm(
    2098             :                                                         dc, &context->res_ctx,
    2099             :                                                         pipe, hsplit_pipe))
    2100             :                                                 goto validate_fail;
    2101           0 :                                         dcn20_build_mapped_resource(dc, context, pipe->stream);
    2102             :                                 } else {
    2103           0 :                                         dcn20_split_stream_for_mpc(
    2104           0 :                                                         &context->res_ctx, dc->res_pool,
    2105             :                                                         pipe, hsplit_pipe);
    2106           0 :                                         resource_build_scaling_params(pipe);
    2107           0 :                                         resource_build_scaling_params(hsplit_pipe);
    2108             :                                 }
    2109           0 :                                 pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
    2110             :                         }
    2111           0 :                 } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) {
    2112             :                         /* merge should already have been done */
    2113           0 :                         ASSERT(0);
    2114             :                 }
    2115             :         }
    2116             :         /* Actual dsc count per stream dsc validation*/
    2117           0 :         if (!dcn20_validate_dsc(dc, context)) {
    2118           0 :                 context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] =
    2119             :                                 DML_FAIL_DSC_VALIDATION_FAILURE;
    2120           0 :                 goto validate_fail;
    2121             :         }
    2122             : 
    2123           0 :         *vlevel_out = vlevel;
    2124             : 
    2125           0 :         out = true;
    2126           0 :         goto validate_out;
    2127             : 
    2128             : validate_fail:
    2129             :         out = false;
    2130             : 
    2131             : validate_out:
    2132             :         return out;
    2133             : }
    2134             : 
    2135           0 : bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
    2136             :                 bool fast_validate)
    2137             : {
    2138             :         bool voltage_supported;
    2139           0 :         DC_FP_START();
    2140           0 :         voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate);
    2141           0 :         DC_FP_END();
    2142           0 :         return voltage_supported;
    2143             : }
    2144             : 
    2145           0 : 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           0 :         struct resource_context *res_ctx = &state->res_ctx;
    2151           0 :         struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
    2152           0 :         struct pipe_ctx *idle_pipe = find_idle_secondary_pipe(res_ctx, pool, head_pipe);
    2153             : 
    2154           0 :         if (!head_pipe)
    2155           0 :                 ASSERT(0);
    2156             : 
    2157           0 :         if (!idle_pipe)
    2158             :                 return NULL;
    2159             : 
    2160           0 :         idle_pipe->stream = head_pipe->stream;
    2161           0 :         idle_pipe->stream_res.tg = head_pipe->stream_res.tg;
    2162           0 :         idle_pipe->stream_res.opp = head_pipe->stream_res.opp;
    2163             : 
    2164           0 :         idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];
    2165           0 :         idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx];
    2166           0 :         idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx];
    2167           0 :         idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst;
    2168             : 
    2169           0 :         return idle_pipe;
    2170             : }
    2171             : 
    2172           0 : 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           0 :         return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
    2177             :                         dc->res_pool->hubbub,
    2178             :                         input,
    2179             :                         output);
    2180             : }
    2181             : 
    2182           0 : static void dcn20_destroy_resource_pool(struct resource_pool **pool)
    2183             : {
    2184           0 :         struct dcn20_resource_pool *dcn20_pool = TO_DCN20_RES_POOL(*pool);
    2185             : 
    2186           0 :         dcn20_resource_destruct(dcn20_pool);
    2187           0 :         kfree(dcn20_pool);
    2188           0 :         *pool = NULL;
    2189           0 : }
    2190             : 
    2191             : 
    2192             : static struct dc_cap_funcs cap_funcs = {
    2193             :         .get_dcc_compression_cap = dcn20_get_dcc_compression_cap
    2194             : };
    2195             : 
    2196             : 
    2197           0 : enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state)
    2198             : {
    2199           0 :         enum surface_pixel_format surf_pix_format = plane_state->format;
    2200           0 :         unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format);
    2201             : 
    2202           0 :         enum swizzle_mode_values swizzle = DC_SW_LINEAR;
    2203             : 
    2204           0 :         if (bpp == 64)
    2205             :                 swizzle = DC_SW_64KB_D;
    2206             :         else
    2207           0 :                 swizzle = DC_SW_64KB_S;
    2208             : 
    2209           0 :         plane_state->tiling_info.gfx9.swizzle = swizzle;
    2210           0 :         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           0 : bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
    2230             : {
    2231             :         int i;
    2232           0 :         uint32_t pipe_count = pool->res_cap->num_dwb;
    2233             : 
    2234           0 :         for (i = 0; i < pipe_count; i++) {
    2235           0 :                 struct dcn20_dwbc *dwbc20 = kzalloc(sizeof(struct dcn20_dwbc),
    2236             :                                                     GFP_KERNEL);
    2237             : 
    2238           0 :                 if (!dwbc20) {
    2239           0 :                         dm_error("DC: failed to create dwbc20!\n");
    2240           0 :                         return false;
    2241             :                 }
    2242           0 :                 dcn20_dwbc_construct(dwbc20, ctx,
    2243             :                                 &dwbc20_regs[i],
    2244             :                                 &dwbc20_shift,
    2245             :                                 &dwbc20_mask,
    2246             :                                 i);
    2247           0 :                 pool->dwbc[i] = &dwbc20->base;
    2248             :         }
    2249             :         return true;
    2250             : }
    2251             : 
    2252           0 : bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
    2253             : {
    2254             :         int i;
    2255           0 :         uint32_t pipe_count = pool->res_cap->num_dwb;
    2256             : 
    2257           0 :         ASSERT(pipe_count > 0);
    2258             : 
    2259           0 :         for (i = 0; i < pipe_count; i++) {
    2260           0 :                 struct dcn20_mmhubbub *mcif_wb20 = kzalloc(sizeof(struct dcn20_mmhubbub),
    2261             :                                                     GFP_KERNEL);
    2262             : 
    2263           0 :                 if (!mcif_wb20) {
    2264           0 :                         dm_error("DC: failed to create mcif_wb20!\n");
    2265           0 :                         return false;
    2266             :                 }
    2267             : 
    2268           0 :                 dcn20_mmhubbub_construct(mcif_wb20, ctx,
    2269             :                                 &mcif_wb20_regs[i],
    2270             :                                 &mcif_wb20_shift,
    2271             :                                 &mcif_wb20_mask,
    2272             :                                 i);
    2273             : 
    2274           0 :                 pool->mcif_wb[i] = &mcif_wb20->base;
    2275             :         }
    2276             :         return true;
    2277             : }
    2278             : 
    2279           0 : static struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx)
    2280             : {
    2281           0 :         struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_ATOMIC);
    2282             : 
    2283           0 :         if (!pp_smu)
    2284             :                 return pp_smu;
    2285             : 
    2286           0 :         dm_pp_get_funcs(ctx, pp_smu);
    2287             : 
    2288           0 :         if (pp_smu->ctx.ver != PP_SMU_VER_NV)
    2289           0 :                 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           0 :         if (pp_smu && *pp_smu) {
    2297           0 :                 kfree(*pp_smu);
    2298           0 :                 *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           0 :         if (ASICREV_IS_NAVI14_M(hw_internal_rev))
    2306             :                 return &dcn2_0_nv14_soc;
    2307             : 
    2308           0 :         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           0 :         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           0 : static bool init_soc_bounding_box(struct dc *dc,
    2331             :                                   struct dcn20_resource_pool *pool)
    2332             : {
    2333           0 :         struct _vcs_dpi_soc_bounding_box_st *loaded_bb =
    2334           0 :                         get_asic_rev_soc_bb(dc->ctx->asic_id.hw_internal_rev);
    2335           0 :         struct _vcs_dpi_ip_params_st *loaded_ip =
    2336           0 :                         get_asic_rev_ip_params(dc->ctx->asic_id.hw_internal_rev);
    2337             : 
    2338             :         DC_LOGGER_INIT(dc->ctx->logger);
    2339             : 
    2340           0 :         if (pool->base.pp_smu) {
    2341           0 :                 struct pp_smu_nv_clock_table max_clocks = {0};
    2342           0 :                 unsigned int uclk_states[8] = {0};
    2343           0 :                 unsigned int num_states = 0;
    2344             :                 enum pp_smu_status status;
    2345           0 :                 bool clock_limits_available = false;
    2346           0 :                 bool uclk_states_available = false;
    2347             : 
    2348           0 :                 if (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) {
    2349           0 :                         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           0 :                         uclk_states_available = (status == PP_SMU_RESULT_OK);
    2353             :                 }
    2354             : 
    2355           0 :                 if (pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) {
    2356           0 :                         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           0 :                         if (max_clocks.dcfClockInKhz >= max_clocks.socClockInKhz)
    2361           0 :                                 max_clocks.dcfClockInKhz = max_clocks.socClockInKhz - 1000;
    2362           0 :                         clock_limits_available = (status == PP_SMU_RESULT_OK);
    2363             :                 }
    2364             : 
    2365           0 :                 if (clock_limits_available && uclk_states_available && num_states) {
    2366           0 :                         DC_FP_START();
    2367           0 :                         dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states);
    2368           0 :                         DC_FP_END();
    2369           0 :                 } else if (clock_limits_available) {
    2370           0 :                         DC_FP_START();
    2371           0 :                         dcn20_cap_soc_clocks(loaded_bb, max_clocks);
    2372           0 :                         DC_FP_END();
    2373             :                 }
    2374             :         }
    2375             : 
    2376           0 :         loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
    2377           0 :         loaded_ip->max_num_dpp = pool->base.pipe_count;
    2378           0 :         DC_FP_START();
    2379           0 :         dcn20_patch_bounding_box(dc, loaded_bb);
    2380           0 :         DC_FP_END();
    2381           0 :         return true;
    2382             : }
    2383             : 
    2384           0 : 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           0 :         struct dc_context *ctx = dc->ctx;
    2391             :         struct irq_service_init_data init_data;
    2392           0 :         struct ddc_service_init_data ddc_init_data = {0};
    2393           0 :         struct _vcs_dpi_soc_bounding_box_st *loaded_bb =
    2394           0 :                         get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev);
    2395           0 :         struct _vcs_dpi_ip_params_st *loaded_ip =
    2396           0 :                         get_asic_rev_ip_params(ctx->asic_id.hw_internal_rev);
    2397           0 :         enum dml_project dml_project_version =
    2398             :                         get_dml_project_version(ctx->asic_id.hw_internal_rev);
    2399             : 
    2400           0 :         ctx->dc_bios->regs = &bios_regs;
    2401           0 :         pool->base.funcs = &dcn20_res_pool_funcs;
    2402             : 
    2403           0 :         if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) {
    2404           0 :                 pool->base.res_cap = &res_cap_nv14;
    2405           0 :                 pool->base.pipe_count = 5;
    2406           0 :                 pool->base.mpcc_count = 5;
    2407             :         } else {
    2408           0 :                 pool->base.res_cap = &res_cap_nv10;
    2409           0 :                 pool->base.pipe_count = 6;
    2410           0 :                 pool->base.mpcc_count = 6;
    2411             :         }
    2412             :         /*************************************************
    2413             :          *  Resource + asic cap harcoding                *
    2414             :          *************************************************/
    2415           0 :         pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
    2416             : 
    2417           0 :         dc->caps.max_downscale_ratio = 200;
    2418           0 :         dc->caps.i2c_speed_in_khz = 100;
    2419           0 :         dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/
    2420           0 :         dc->caps.max_cursor_size = 256;
    2421           0 :         dc->caps.min_horizontal_blanking_period = 80;
    2422           0 :         dc->caps.dmdata_alloc_size = 2048;
    2423             : 
    2424           0 :         dc->caps.max_slave_planes = 1;
    2425           0 :         dc->caps.max_slave_yuv_planes = 1;
    2426           0 :         dc->caps.max_slave_rgb_planes = 1;
    2427           0 :         dc->caps.post_blend_color_processing = true;
    2428           0 :         dc->caps.force_dp_tps4_for_cp2520 = true;
    2429           0 :         dc->caps.extended_aux_timeout_support = true;
    2430             : 
    2431             :         /* Color pipeline capabilities */
    2432           0 :         dc->caps.color.dpp.dcn_arch = 1;
    2433           0 :         dc->caps.color.dpp.input_lut_shared = 0;
    2434           0 :         dc->caps.color.dpp.icsc = 1;
    2435           0 :         dc->caps.color.dpp.dgam_ram = 1;
    2436           0 :         dc->caps.color.dpp.dgam_rom_caps.srgb = 1;
    2437           0 :         dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;
    2438           0 :         dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0;
    2439           0 :         dc->caps.color.dpp.dgam_rom_caps.pq = 0;
    2440           0 :         dc->caps.color.dpp.dgam_rom_caps.hlg = 0;
    2441           0 :         dc->caps.color.dpp.post_csc = 0;
    2442           0 :         dc->caps.color.dpp.gamma_corr = 0;
    2443           0 :         dc->caps.color.dpp.dgam_rom_for_yuv = 1;
    2444             : 
    2445           0 :         dc->caps.color.dpp.hw_3d_lut = 1;
    2446           0 :         dc->caps.color.dpp.ogam_ram = 1;
    2447             :         // no OGAM ROM on DCN2, only MPC ROM
    2448           0 :         dc->caps.color.dpp.ogam_rom_caps.srgb = 0;
    2449           0 :         dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;
    2450           0 :         dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;
    2451           0 :         dc->caps.color.dpp.ogam_rom_caps.pq = 0;
    2452           0 :         dc->caps.color.dpp.ogam_rom_caps.hlg = 0;
    2453           0 :         dc->caps.color.dpp.ocsc = 0;
    2454             : 
    2455           0 :         dc->caps.color.mpc.gamut_remap = 0;
    2456           0 :         dc->caps.color.mpc.num_3dluts = 0;
    2457           0 :         dc->caps.color.mpc.shared_3d_lut = 0;
    2458           0 :         dc->caps.color.mpc.ogam_ram = 1;
    2459           0 :         dc->caps.color.mpc.ogam_rom_caps.srgb = 0;
    2460           0 :         dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;
    2461           0 :         dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;
    2462           0 :         dc->caps.color.mpc.ogam_rom_caps.pq = 0;
    2463           0 :         dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
    2464           0 :         dc->caps.color.mpc.ocsc = 1;
    2465             : 
    2466           0 :         dc->caps.dp_hdmi21_pcon_support = true;
    2467             : 
    2468           0 :         if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) {
    2469           0 :                 dc->debug = debug_defaults_drv;
    2470           0 :         } else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
    2471           0 :                 pool->base.pipe_count = 4;
    2472           0 :                 pool->base.mpcc_count = pool->base.pipe_count;
    2473           0 :                 dc->debug = debug_defaults_diags;
    2474             :         } else {
    2475           0 :                 dc->debug = debug_defaults_diags;
    2476             :         }
    2477             :         //dcn2.0x
    2478           0 :         dc->work_arounds.dedcn20_305_wa = true;
    2479             : 
    2480             :         // Init the vm_helper
    2481           0 :         if (dc->vm_helper)
    2482           0 :                 vm_helper_init(dc->vm_helper, 16);
    2483             : 
    2484             :         /*************************************************
    2485             :          *  Create resources                             *
    2486             :          *************************************************/
    2487             : 
    2488           0 :         pool->base.clock_sources[DCN20_CLK_SRC_PLL0] =
    2489           0 :                         dcn20_clock_source_create(ctx, ctx->dc_bios,
    2490             :                                 CLOCK_SOURCE_COMBO_PHY_PLL0,
    2491             :                                 &clk_src_regs[0], false);
    2492           0 :         pool->base.clock_sources[DCN20_CLK_SRC_PLL1] =
    2493           0 :                         dcn20_clock_source_create(ctx, ctx->dc_bios,
    2494             :                                 CLOCK_SOURCE_COMBO_PHY_PLL1,
    2495             :                                 &clk_src_regs[1], false);
    2496           0 :         pool->base.clock_sources[DCN20_CLK_SRC_PLL2] =
    2497           0 :                         dcn20_clock_source_create(ctx, ctx->dc_bios,
    2498             :                                 CLOCK_SOURCE_COMBO_PHY_PLL2,
    2499             :                                 &clk_src_regs[2], false);
    2500           0 :         pool->base.clock_sources[DCN20_CLK_SRC_PLL3] =
    2501           0 :                         dcn20_clock_source_create(ctx, ctx->dc_bios,
    2502             :                                 CLOCK_SOURCE_COMBO_PHY_PLL3,
    2503             :                                 &clk_src_regs[3], false);
    2504           0 :         pool->base.clock_sources[DCN20_CLK_SRC_PLL4] =
    2505           0 :                         dcn20_clock_source_create(ctx, ctx->dc_bios,
    2506             :                                 CLOCK_SOURCE_COMBO_PHY_PLL4,
    2507             :                                 &clk_src_regs[4], false);
    2508           0 :         pool->base.clock_sources[DCN20_CLK_SRC_PLL5] =
    2509           0 :                         dcn20_clock_source_create(ctx, ctx->dc_bios,
    2510             :                                 CLOCK_SOURCE_COMBO_PHY_PLL5,
    2511             :                                 &clk_src_regs[5], false);
    2512           0 :         pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL;
    2513             :         /* todo: not reuse phy_pll registers */
    2514           0 :         pool->base.dp_clock_source =
    2515           0 :                         dcn20_clock_source_create(ctx, ctx->dc_bios,
    2516             :                                 CLOCK_SOURCE_ID_DP_DTO,
    2517             :                                 &clk_src_regs[0], true);
    2518             : 
    2519           0 :         for (i = 0; i < pool->base.clk_src_count; i++) {
    2520           0 :                 if (pool->base.clock_sources[i] == NULL) {
    2521           0 :                         dm_error("DC: failed to create clock sources!\n");
    2522           0 :                         BREAK_TO_DEBUGGER();
    2523           0 :                         goto create_fail;
    2524             :                 }
    2525             :         }
    2526             : 
    2527           0 :         pool->base.dccg = dccg2_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);
    2528           0 :         if (pool->base.dccg == NULL) {
    2529           0 :                 dm_error("DC: failed to create dccg!\n");
    2530           0 :                 BREAK_TO_DEBUGGER();
    2531           0 :                 goto create_fail;
    2532             :         }
    2533             : 
    2534           0 :         pool->base.dmcu = dcn20_dmcu_create(ctx,
    2535             :                         &dmcu_regs,
    2536             :                         &dmcu_shift,
    2537             :                         &dmcu_mask);
    2538           0 :         if (pool->base.dmcu == NULL) {
    2539           0 :                 dm_error("DC: failed to create dmcu!\n");
    2540           0 :                 BREAK_TO_DEBUGGER();
    2541           0 :                 goto create_fail;
    2542             :         }
    2543             : 
    2544           0 :         pool->base.abm = dce_abm_create(ctx,
    2545             :                         &abm_regs,
    2546             :                         &abm_shift,
    2547             :                         &abm_mask);
    2548           0 :         if (pool->base.abm == NULL) {
    2549           0 :                 dm_error("DC: failed to create abm!\n");
    2550           0 :                 BREAK_TO_DEBUGGER();
    2551           0 :                 goto create_fail;
    2552             :         }
    2553             : 
    2554           0 :         pool->base.pp_smu = dcn20_pp_smu_create(ctx);
    2555             : 
    2556             : 
    2557           0 :         if (!init_soc_bounding_box(dc, pool)) {
    2558           0 :                 dm_error("DC: failed to initialize soc bounding box!\n");
    2559           0 :                 BREAK_TO_DEBUGGER();
    2560           0 :                 goto create_fail;
    2561             :         }
    2562             : 
    2563           0 :         dml_init_instance(&dc->dml, loaded_bb, loaded_ip, dml_project_version);
    2564             : 
    2565           0 :         if (!dc->debug.disable_pplib_wm_range) {
    2566           0 :                 struct pp_smu_wm_range_sets ranges = {0};
    2567           0 :                 int i = 0;
    2568             : 
    2569             :                 ranges.num_reader_wm_sets = 0;
    2570             : 
    2571           0 :                 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           0 :                         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           0 :                         ranges.reader_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
    2577             : 
    2578           0 :                         ranges.num_reader_wm_sets = 1;
    2579           0 :                 } else if (loaded_bb->num_states > 1) {
    2580           0 :                         for (i = 0; i < 4 && i < loaded_bb->num_states; i++) {
    2581           0 :                                 ranges.reader_wm_sets[i].wm_inst = i;
    2582           0 :                                 ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
    2583           0 :                                 ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
    2584           0 :                                 DC_FP_START();
    2585           0 :                                 dcn20_fpu_set_wm_ranges(i, &ranges, loaded_bb);
    2586           0 :                                 DC_FP_END();
    2587             : 
    2588           0 :                                 ranges.num_reader_wm_sets = i + 1;
    2589             :                         }
    2590             : 
    2591           0 :                         ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
    2592           0 :                         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           0 :                 ranges.num_writer_wm_sets = 1;
    2596             : 
    2597           0 :                 ranges.writer_wm_sets[0].wm_inst = 0;
    2598           0 :                 ranges.writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
    2599           0 :                 ranges.writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
    2600           0 :                 ranges.writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
    2601           0 :                 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           0 :                 if (pool->base.pp_smu->nv_funcs.set_wm_ranges)
    2605           0 :                         pool->base.pp_smu->nv_funcs.set_wm_ranges(&pool->base.pp_smu->nv_funcs.pp_smu, &ranges);
    2606             :         }
    2607             : 
    2608           0 :         init_data.ctx = dc->ctx;
    2609           0 :         pool->base.irqs = dal_irq_service_dcn20_create(&init_data);
    2610           0 :         if (!pool->base.irqs)
    2611             :                 goto create_fail;
    2612             : 
    2613             :         /* mem input -> ipp -> dpp -> opp -> TG */
    2614           0 :         for (i = 0; i < pool->base.pipe_count; i++) {
    2615           0 :                 pool->base.hubps[i] = dcn20_hubp_create(ctx, i);
    2616           0 :                 if (pool->base.hubps[i] == NULL) {
    2617           0 :                         BREAK_TO_DEBUGGER();
    2618           0 :                         dm_error(
    2619             :                                 "DC: failed to create memory input!\n");
    2620           0 :                         goto create_fail;
    2621             :                 }
    2622             : 
    2623           0 :                 pool->base.ipps[i] = dcn20_ipp_create(ctx, i);
    2624           0 :                 if (pool->base.ipps[i] == NULL) {
    2625           0 :                         BREAK_TO_DEBUGGER();
    2626           0 :                         dm_error(
    2627             :                                 "DC: failed to create input pixel processor!\n");
    2628           0 :                         goto create_fail;
    2629             :                 }
    2630             : 
    2631           0 :                 pool->base.dpps[i] = dcn20_dpp_create(ctx, i);
    2632           0 :                 if (pool->base.dpps[i] == NULL) {
    2633           0 :                         BREAK_TO_DEBUGGER();
    2634           0 :                         dm_error(
    2635             :                                 "DC: failed to create dpps!\n");
    2636           0 :                         goto create_fail;
    2637             :                 }
    2638             :         }
    2639           0 :         for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
    2640           0 :                 pool->base.engines[i] = dcn20_aux_engine_create(ctx, i);
    2641           0 :                 if (pool->base.engines[i] == NULL) {
    2642           0 :                         BREAK_TO_DEBUGGER();
    2643           0 :                         dm_error(
    2644             :                                 "DC:failed to create aux engine!!\n");
    2645           0 :                         goto create_fail;
    2646             :                 }
    2647           0 :                 pool->base.hw_i2cs[i] = dcn20_i2c_hw_create(ctx, i);
    2648           0 :                 if (pool->base.hw_i2cs[i] == NULL) {
    2649           0 :                         BREAK_TO_DEBUGGER();
    2650           0 :                         dm_error(
    2651             :                                 "DC:failed to create hw i2c!!\n");
    2652           0 :                         goto create_fail;
    2653             :                 }
    2654           0 :                 pool->base.sw_i2cs[i] = NULL;
    2655             :         }
    2656             : 
    2657           0 :         for (i = 0; i < pool->base.res_cap->num_opp; i++) {
    2658           0 :                 pool->base.opps[i] = dcn20_opp_create(ctx, i);
    2659           0 :                 if (pool->base.opps[i] == NULL) {
    2660           0 :                         BREAK_TO_DEBUGGER();
    2661           0 :                         dm_error(
    2662             :                                 "DC: failed to create output pixel processor!\n");
    2663           0 :                         goto create_fail;
    2664             :                 }
    2665             :         }
    2666             : 
    2667           0 :         for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
    2668           0 :                 pool->base.timing_generators[i] = dcn20_timing_generator_create(
    2669             :                                 ctx, i);
    2670           0 :                 if (pool->base.timing_generators[i] == NULL) {
    2671           0 :                         BREAK_TO_DEBUGGER();
    2672           0 :                         dm_error("DC: failed to create tg!\n");
    2673           0 :                         goto create_fail;
    2674             :                 }
    2675             :         }
    2676             : 
    2677           0 :         pool->base.timing_generator_count = i;
    2678             : 
    2679           0 :         pool->base.mpc = dcn20_mpc_create(ctx);
    2680           0 :         if (pool->base.mpc == NULL) {
    2681           0 :                 BREAK_TO_DEBUGGER();
    2682           0 :                 dm_error("DC: failed to create mpc!\n");
    2683           0 :                 goto create_fail;
    2684             :         }
    2685             : 
    2686           0 :         pool->base.hubbub = dcn20_hubbub_create(ctx);
    2687           0 :         if (pool->base.hubbub == NULL) {
    2688           0 :                 BREAK_TO_DEBUGGER();
    2689           0 :                 dm_error("DC: failed to create hubbub!\n");
    2690           0 :                 goto create_fail;
    2691             :         }
    2692             : 
    2693           0 :         for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
    2694           0 :                 pool->base.dscs[i] = dcn20_dsc_create(ctx, i);
    2695           0 :                 if (pool->base.dscs[i] == NULL) {
    2696           0 :                         BREAK_TO_DEBUGGER();
    2697           0 :                         dm_error("DC: failed to create display stream compressor %d!\n", i);
    2698           0 :                         goto create_fail;
    2699             :                 }
    2700             :         }
    2701             : 
    2702           0 :         if (!dcn20_dwbc_create(ctx, &pool->base)) {
    2703           0 :                 BREAK_TO_DEBUGGER();
    2704           0 :                 dm_error("DC: failed to create dwbc!\n");
    2705           0 :                 goto create_fail;
    2706             :         }
    2707           0 :         if (!dcn20_mmhubbub_create(ctx, &pool->base)) {
    2708           0 :                 BREAK_TO_DEBUGGER();
    2709           0 :                 dm_error("DC: failed to create mcif_wb!\n");
    2710           0 :                 goto create_fail;
    2711             :         }
    2712             : 
    2713           0 :         if (!resource_construct(num_virtual_links, dc, &pool->base,
    2714           0 :                         (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ?
    2715             :                         &res_create_funcs : &res_create_maximus_funcs)))
    2716             :                         goto create_fail;
    2717             : 
    2718           0 :         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           0 :         if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) {
    2727           0 :                 dc->hwseq->funcs.enable_power_gating_plane = NULL;
    2728           0 :                 dc->debug.disable_dpp_power_gate = true;
    2729           0 :                 dc->debug.disable_hubp_power_gate = true;
    2730             :         }
    2731             : 
    2732             : 
    2733           0 :         dc->caps.max_planes =  pool->base.pipe_count;
    2734             : 
    2735           0 :         for (i = 0; i < dc->caps.max_planes; ++i)
    2736           0 :                 dc->caps.planes[i] = plane_cap;
    2737             : 
    2738           0 :         dc->cap_funcs = cap_funcs;
    2739             : 
    2740           0 :         if (dc->ctx->dc_bios->fw_info.oem_i2c_present) {
    2741           0 :                 ddc_init_data.ctx = dc->ctx;
    2742           0 :                 ddc_init_data.link = NULL;
    2743           0 :                 ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;
    2744           0 :                 ddc_init_data.id.enum_id = 0;
    2745           0 :                 ddc_init_data.id.type = OBJECT_TYPE_GENERIC;
    2746           0 :                 pool->base.oem_device = dal_ddc_service_create(&ddc_init_data);
    2747             :         } else {
    2748           0 :                 pool->base.oem_device = NULL;
    2749             :         }
    2750             : 
    2751             :         return true;
    2752             : 
    2753             : create_fail:
    2754             : 
    2755           0 :         dcn20_resource_destruct(pool);
    2756             : 
    2757           0 :         return false;
    2758             : }
    2759             : 
    2760           0 : struct resource_pool *dcn20_create_resource_pool(
    2761             :                 const struct dc_init_data *init_data,
    2762             :                 struct dc *dc)
    2763             : {
    2764           0 :         struct dcn20_resource_pool *pool =
    2765             :                 kzalloc(sizeof(struct dcn20_resource_pool), GFP_ATOMIC);
    2766             : 
    2767           0 :         if (!pool)
    2768             :                 return NULL;
    2769             : 
    2770           0 :         if (dcn20_resource_construct(init_data->num_virtual_links, dc, pool))
    2771           0 :                 return &pool->base;
    2772             : 
    2773           0 :         BREAK_TO_DEBUGGER();
    2774           0 :         kfree(pool);
    2775           0 :         return NULL;
    2776             : }

Generated by: LCOV version 1.14