File Index
Files and directories
Sign in
FILE

dcn20_resource.c

File preview with syntax highlighting.

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