1// SPDX-License-Identifier: MIT
2/*
3 * Copyright 2022 Advanced Micro Devices, Inc.
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 "dcn32_init.h"
31
32#include "resource.h"
33#include "include/irq_service_interface.h"
34#include "dcn32_resource.h"
35
36#include "dcn20/dcn20_resource.h"
37#include "dcn30/dcn30_resource.h"
38
39#include "dcn10/dcn10_ipp.h"
40#include "dcn30/dcn30_hubbub.h"
41#include "dcn31/dcn31_hubbub.h"
42#include "dcn32/dcn32_hubbub.h"
43#include "dcn32/dcn32_mpc.h"
44#include "dcn32_hubp.h"
45#include "irq/dcn32/irq_service_dcn32.h"
46#include "dcn32/dcn32_dpp.h"
47#include "dcn32/dcn32_optc.h"
48#include "dcn20/dcn20_hwseq.h"
49#include "dcn30/dcn30_hwseq.h"
50#include "dce110/dce110_hw_sequencer.h"
51#include "dcn30/dcn30_opp.h"
52#include "dcn20/dcn20_dsc.h"
53#include "dcn30/dcn30_vpg.h"
54#include "dcn30/dcn30_afmt.h"
55#include "dcn30/dcn30_dio_stream_encoder.h"
56#include "dcn32/dcn32_dio_stream_encoder.h"
57#include "dcn31/dcn31_hpo_dp_stream_encoder.h"
58#include "dcn31/dcn31_hpo_dp_link_encoder.h"
59#include "dcn32/dcn32_hpo_dp_link_encoder.h"
60#include "dcn31/dcn31_apg.h"
61#include "dcn31/dcn31_dio_link_encoder.h"
62#include "dcn32/dcn32_dio_link_encoder.h"
63#include "dce/dce_clock_source.h"
64#include "dce/dce_audio.h"
65#include "dce/dce_hwseq.h"
66#include "clk_mgr.h"
67#include "virtual/virtual_stream_encoder.h"
68#include "dml/display_mode_vba.h"
69#include "dcn32/dcn32_dccg.h"
70#include "dcn10/dcn10_resource.h"
71#include "link.h"
72#include "dcn31/dcn31_panel_cntl.h"
73
74#include "dcn30/dcn30_dwb.h"
75#include "dcn32/dcn32_mmhubbub.h"
76
77#include "dcn/dcn_3_2_0_offset.h"
78#include "dcn/dcn_3_2_0_sh_mask.h"
79#include "nbio/nbio_4_3_0_offset.h"
80
81#include "reg_helper.h"
82#include "dce/dmub_abm.h"
83#include "dce/dmub_psr.h"
84#include "dce/dce_aux.h"
85#include "dce/dce_i2c.h"
86
87#include "dml/dcn30/display_mode_vba_30.h"
88#include "vm_helper.h"
89#include "dcn20/dcn20_vmid.h"
90#include "dml/dcn32/dcn32_fpu.h"
91
92#define DC_LOGGER_INIT(logger)
93
94enum dcn32_clk_src_array_id {
95	DCN32_CLK_SRC_PLL0,
96	DCN32_CLK_SRC_PLL1,
97	DCN32_CLK_SRC_PLL2,
98	DCN32_CLK_SRC_PLL3,
99	DCN32_CLK_SRC_PLL4,
100	DCN32_CLK_SRC_TOTAL
101};
102
103/* begin *********************
104 * macros to expend register list macro defined in HW object header file
105 */
106
107/* DCN */
108#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]
109
110#define BASE(seg) BASE_INNER(seg)
111
112#define SR(reg_name)\
113		REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) +  \
114					reg ## reg_name
115#define SR_ARR(reg_name, id) \
116	REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name
117
118#define SR_ARR_INIT(reg_name, id, value) \
119	REG_STRUCT[id].reg_name = value
120
121#define SRI(reg_name, block, id)\
122	REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
123		reg ## block ## id ## _ ## reg_name
124
125#define SRI_ARR(reg_name, block, id)\
126	REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
127		reg ## block ## id ## _ ## reg_name
128
129#define SR_ARR_I2C(reg_name, id) \
130	REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name
131
132#define SRI_ARR_I2C(reg_name, block, id)\
133	REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
134		reg ## block ## id ## _ ## reg_name
135
136#define SRI_ARR_ALPHABET(reg_name, block, index, id)\
137	REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
138		reg ## block ## id ## _ ## reg_name
139
140#define SRI2(reg_name, block, id)\
141	.reg_name = BASE(reg ## reg_name ## _BASE_IDX) +	\
142		reg ## reg_name
143#define SRI2_ARR(reg_name, block, id)\
144	REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) +	\
145		reg ## reg_name
146
147#define SRIR(var_name, reg_name, block, id)\
148	.var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
149		reg ## block ## id ## _ ## reg_name
150
151#define SRII(reg_name, block, id)\
152	REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
153					reg ## block ## id ## _ ## reg_name
154
155#define SRII_ARR_2(reg_name, block, id, inst)\
156	REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
157		reg ## block ## id ## _ ## reg_name
158
159#define SRII_MPC_RMU(reg_name, block, id)\
160	.RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
161		reg ## block ## id ## _ ## reg_name
162
163#define SRII_DWB(reg_name, temp_name, block, id)\
164	REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
165		reg ## block ## id ## _ ## temp_name
166
167#define SF_DWB2(reg_name, block, id, field_name, post_fix)	\
168	.field_name = reg_name ## __ ## field_name ## post_fix
169
170#define DCCG_SRII(reg_name, block, id)\
171	REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
172		reg ## block ## id ## _ ## reg_name
173
174#define VUPDATE_SRII(reg_name, block, id)\
175	REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \
176		reg ## reg_name ## _ ## block ## id
177
178/* NBIO */
179#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg]
180
181#define NBIO_BASE(seg) \
182	NBIO_BASE_INNER(seg)
183
184#define NBIO_SR(reg_name)\
185	REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \
186			regBIF_BX0_ ## reg_name
187#define NBIO_SR_ARR(reg_name, id)\
188	REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \
189		regBIF_BX0_ ## reg_name
190
191#undef CTX
192#define CTX ctx
193#define REG(reg_name) \
194	(ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)
195
196static struct bios_registers bios_regs;
197
198#define bios_regs_init() \
199		( \
200		NBIO_SR(BIOS_SCRATCH_3),\
201		NBIO_SR(BIOS_SCRATCH_6)\
202		)
203
204#define clk_src_regs_init(index, pllid)\
205	CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid)
206
207static struct dce110_clk_src_regs clk_src_regs[5];
208
209static const struct dce110_clk_src_shift cs_shift = {
210		CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT)
211};
212
213static const struct dce110_clk_src_mask cs_mask = {
214		CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK)
215};
216
217#define abm_regs_init(id)\
218		ABM_DCN32_REG_LIST_RI(id)
219
220static struct dce_abm_registers abm_regs[4];
221
222static const struct dce_abm_shift abm_shift = {
223		ABM_MASK_SH_LIST_DCN32(__SHIFT)
224};
225
226static const struct dce_abm_mask abm_mask = {
227		ABM_MASK_SH_LIST_DCN32(_MASK)
228};
229
230#define audio_regs_init(id)\
231		AUD_COMMON_REG_LIST_RI(id)
232
233static struct dce_audio_registers audio_regs[5];
234
235#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\
236		SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
237		SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
238		AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)
239
240static const struct dce_audio_shift audio_shift = {
241		DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)
242};
243
244static const struct dce_audio_mask audio_mask = {
245		DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)
246};
247
248#define vpg_regs_init(id)\
249	VPG_DCN3_REG_LIST_RI(id)
250
251static struct dcn30_vpg_registers vpg_regs[10];
252
253static const struct dcn30_vpg_shift vpg_shift = {
254	DCN3_VPG_MASK_SH_LIST(__SHIFT)
255};
256
257static const struct dcn30_vpg_mask vpg_mask = {
258	DCN3_VPG_MASK_SH_LIST(_MASK)
259};
260
261#define afmt_regs_init(id)\
262	AFMT_DCN3_REG_LIST_RI(id)
263
264static struct dcn30_afmt_registers afmt_regs[6];
265
266static const struct dcn30_afmt_shift afmt_shift = {
267	DCN3_AFMT_MASK_SH_LIST(__SHIFT)
268};
269
270static const struct dcn30_afmt_mask afmt_mask = {
271	DCN3_AFMT_MASK_SH_LIST(_MASK)
272};
273
274#define apg_regs_init(id)\
275	APG_DCN31_REG_LIST_RI(id)
276
277static struct dcn31_apg_registers apg_regs[4];
278
279static const struct dcn31_apg_shift apg_shift = {
280	DCN31_APG_MASK_SH_LIST(__SHIFT)
281};
282
283static const struct dcn31_apg_mask apg_mask = {
284		DCN31_APG_MASK_SH_LIST(_MASK)
285};
286
287#define stream_enc_regs_init(id)\
288	SE_DCN32_REG_LIST_RI(id)
289
290static struct dcn10_stream_enc_registers stream_enc_regs[5];
291
292static const struct dcn10_stream_encoder_shift se_shift = {
293		SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT)
294};
295
296static const struct dcn10_stream_encoder_mask se_mask = {
297		SE_COMMON_MASK_SH_LIST_DCN32(_MASK)
298};
299
300
301#define aux_regs_init(id)\
302	DCN2_AUX_REG_LIST_RI(id)
303
304static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5];
305
306#define hpd_regs_init(id)\
307	HPD_REG_LIST_RI(id)
308
309static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];
310
311#define link_regs_init(id, phyid)\
312	( \
313	LE_DCN31_REG_LIST_RI(id), \
314	UNIPHY_DCN2_REG_LIST_RI(id, phyid)\
315	)
316	/*DPCS_DCN31_REG_LIST(id),*/ \
317
318static struct dcn10_link_enc_registers link_enc_regs[5];
319
320static const struct dcn10_link_enc_shift le_shift = {
321	LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \
322	//DPCS_DCN31_MASK_SH_LIST(__SHIFT)
323};
324
325static const struct dcn10_link_enc_mask le_mask = {
326	LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \
327	//DPCS_DCN31_MASK_SH_LIST(_MASK)
328};
329
330#define hpo_dp_stream_encoder_reg_init(id)\
331	DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id)
332
333static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4];
334
335static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = {
336	DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT)
337};
338
339static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = {
340	DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)
341};
342
343
344#define hpo_dp_link_encoder_reg_init(id)\
345	DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id)
346	/*DCN3_1_RDPCSTX_REG_LIST(0),*/
347	/*DCN3_1_RDPCSTX_REG_LIST(1),*/
348	/*DCN3_1_RDPCSTX_REG_LIST(2),*/
349	/*DCN3_1_RDPCSTX_REG_LIST(3),*/
350
351static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2];
352
353static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = {
354	DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT)
355};
356
357static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = {
358	DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK)
359};
360
361#define dpp_regs_init(id)\
362	DPP_REG_LIST_DCN30_COMMON_RI(id)
363
364static struct dcn3_dpp_registers dpp_regs[4];
365
366static const struct dcn3_dpp_shift tf_shift = {
367		DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT)
368};
369
370static const struct dcn3_dpp_mask tf_mask = {
371		DPP_REG_LIST_SH_MASK_DCN30_COMMON(_MASK)
372};
373
374
375#define opp_regs_init(id)\
376	OPP_REG_LIST_DCN30_RI(id)
377
378static struct dcn20_opp_registers opp_regs[4];
379
380static const struct dcn20_opp_shift opp_shift = {
381	OPP_MASK_SH_LIST_DCN20(__SHIFT)
382};
383
384static const struct dcn20_opp_mask opp_mask = {
385	OPP_MASK_SH_LIST_DCN20(_MASK)
386};
387
388#define aux_engine_regs_init(id)\
389	( \
390	AUX_COMMON_REG_LIST0_RI(id), \
391	SR_ARR_INIT(AUXN_IMPCAL, id, 0), \
392	SR_ARR_INIT(AUXP_IMPCAL, id, 0), \
393	SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \
394	SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\
395	)
396
397static struct dce110_aux_registers aux_engine_regs[5];
398
399static const struct dce110_aux_registers_shift aux_shift = {
400	DCN_AUX_MASK_SH_LIST(__SHIFT)
401};
402
403static const struct dce110_aux_registers_mask aux_mask = {
404	DCN_AUX_MASK_SH_LIST(_MASK)
405};
406
407#define dwbc_regs_dcn3_init(id)\
408	DWBC_COMMON_REG_LIST_DCN30_RI(id)
409
410static struct dcn30_dwbc_registers dwbc30_regs[1];
411
412static const struct dcn30_dwbc_shift dwbc30_shift = {
413	DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)
414};
415
416static const struct dcn30_dwbc_mask dwbc30_mask = {
417	DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK)
418};
419
420#define mcif_wb_regs_dcn3_init(id)\
421	MCIF_WB_COMMON_REG_LIST_DCN32_RI(id)
422
423static struct dcn30_mmhubbub_registers mcif_wb30_regs[1];
424
425static const struct dcn30_mmhubbub_shift mcif_wb30_shift = {
426	MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT)
427};
428
429static const struct dcn30_mmhubbub_mask mcif_wb30_mask = {
430	MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK)
431};
432
433#define dsc_regsDCN20_init(id)\
434	DSC_REG_LIST_DCN20_RI(id)
435
436static struct dcn20_dsc_registers dsc_regs[4];
437
438static const struct dcn20_dsc_shift dsc_shift = {
439	DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)
440};
441
442static const struct dcn20_dsc_mask dsc_mask = {
443	DSC_REG_LIST_SH_MASK_DCN20(_MASK)
444};
445
446static struct dcn30_mpc_registers mpc_regs;
447
448#define dcn_mpc_regs_init() \
449	MPC_REG_LIST_DCN3_2_RI(0),\
450	MPC_REG_LIST_DCN3_2_RI(1),\
451	MPC_REG_LIST_DCN3_2_RI(2),\
452	MPC_REG_LIST_DCN3_2_RI(3),\
453	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\
454	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\
455	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\
456	MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\
457	MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0)
458
459static const struct dcn30_mpc_shift mpc_shift = {
460	MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT)
461};
462
463static const struct dcn30_mpc_mask mpc_mask = {
464	MPC_COMMON_MASK_SH_LIST_DCN32(_MASK)
465};
466
467#define optc_regs_init(id)\
468	OPTC_COMMON_REG_LIST_DCN3_2_RI(id)
469
470static struct dcn_optc_registers optc_regs[4];
471
472static const struct dcn_optc_shift optc_shift = {
473	OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT)
474};
475
476static const struct dcn_optc_mask optc_mask = {
477	OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK)
478};
479
480#define hubp_regs_init(id)\
481	HUBP_REG_LIST_DCN32_RI(id)
482
483static struct dcn_hubp2_registers hubp_regs[4];
484
485
486static const struct dcn_hubp2_shift hubp_shift = {
487		HUBP_MASK_SH_LIST_DCN32(__SHIFT)
488};
489
490static const struct dcn_hubp2_mask hubp_mask = {
491		HUBP_MASK_SH_LIST_DCN32(_MASK)
492};
493
494static struct dcn_hubbub_registers hubbub_reg;
495#define hubbub_reg_init()\
496		HUBBUB_REG_LIST_DCN32_RI(0)
497
498static const struct dcn_hubbub_shift hubbub_shift = {
499		HUBBUB_MASK_SH_LIST_DCN32(__SHIFT)
500};
501
502static const struct dcn_hubbub_mask hubbub_mask = {
503		HUBBUB_MASK_SH_LIST_DCN32(_MASK)
504};
505
506static struct dccg_registers dccg_regs;
507
508#define dccg_regs_init()\
509	DCCG_REG_LIST_DCN32_RI()
510
511static const struct dccg_shift dccg_shift = {
512		DCCG_MASK_SH_LIST_DCN32(__SHIFT)
513};
514
515static const struct dccg_mask dccg_mask = {
516		DCCG_MASK_SH_LIST_DCN32(_MASK)
517};
518
519
520#define SRII2(reg_name_pre, reg_name_post, id)\
521	.reg_name_pre ## _ ##  reg_name_post[id] = BASE(reg ## reg_name_pre \
522			## id ## _ ## reg_name_post ## _BASE_IDX) + \
523			reg ## reg_name_pre ## id ## _ ## reg_name_post
524
525
526#define HWSEQ_DCN32_REG_LIST()\
527	SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
528	SR(DIO_MEM_PWR_CTRL), \
529	SR(ODM_MEM_PWR_CTRL3), \
530	SR(MMHUBBUB_MEM_PWR_CNTL), \
531	SR(DCCG_GATE_DISABLE_CNTL), \
532	SR(DCCG_GATE_DISABLE_CNTL2), \
533	SR(DCFCLK_CNTL),\
534	SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \
535	SRII(PIXEL_RATE_CNTL, OTG, 0), \
536	SRII(PIXEL_RATE_CNTL, OTG, 1),\
537	SRII(PIXEL_RATE_CNTL, OTG, 2),\
538	SRII(PIXEL_RATE_CNTL, OTG, 3),\
539	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\
540	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\
541	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\
542	SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\
543	SR(MICROSECOND_TIME_BASE_DIV), \
544	SR(MILLISECOND_TIME_BASE_DIV), \
545	SR(DISPCLK_FREQ_CHANGE_CNTL), \
546	SR(RBBMIF_TIMEOUT_DIS), \
547	SR(RBBMIF_TIMEOUT_DIS_2), \
548	SR(DCHUBBUB_CRC_CTRL), \
549	SR(DPP_TOP0_DPP_CRC_CTRL), \
550	SR(DPP_TOP0_DPP_CRC_VAL_B_A), \
551	SR(DPP_TOP0_DPP_CRC_VAL_R_G), \
552	SR(MPC_CRC_CTRL), \
553	SR(MPC_CRC_RESULT_GB), \
554	SR(MPC_CRC_RESULT_C), \
555	SR(MPC_CRC_RESULT_AR), \
556	SR(DOMAIN0_PG_CONFIG), \
557	SR(DOMAIN1_PG_CONFIG), \
558	SR(DOMAIN2_PG_CONFIG), \
559	SR(DOMAIN3_PG_CONFIG), \
560	SR(DOMAIN16_PG_CONFIG), \
561	SR(DOMAIN17_PG_CONFIG), \
562	SR(DOMAIN18_PG_CONFIG), \
563	SR(DOMAIN19_PG_CONFIG), \
564	SR(DOMAIN0_PG_STATUS), \
565	SR(DOMAIN1_PG_STATUS), \
566	SR(DOMAIN2_PG_STATUS), \
567	SR(DOMAIN3_PG_STATUS), \
568	SR(DOMAIN16_PG_STATUS), \
569	SR(DOMAIN17_PG_STATUS), \
570	SR(DOMAIN18_PG_STATUS), \
571	SR(DOMAIN19_PG_STATUS), \
572	SR(D1VGA_CONTROL), \
573	SR(D2VGA_CONTROL), \
574	SR(D3VGA_CONTROL), \
575	SR(D4VGA_CONTROL), \
576	SR(D5VGA_CONTROL), \
577	SR(D6VGA_CONTROL), \
578	SR(DC_IP_REQUEST_CNTL), \
579	SR(AZALIA_AUDIO_DTO), \
580	SR(AZALIA_CONTROLLER_CLOCK_GATING)
581
582static struct dce_hwseq_registers hwseq_reg;
583
584#define hwseq_reg_init()\
585	HWSEQ_DCN32_REG_LIST()
586
587#define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\
588	HWSEQ_DCN_MASK_SH_LIST(mask_sh), \
589	HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
590	HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
591	HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
592	HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
593	HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
594	HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
595	HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
596	HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
597	HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
598	HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
599	HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
600	HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
601	HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
602	HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
603	HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
604	HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
605	HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
606	HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
607	HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
608	HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
609	HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
610	HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
611	HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
612	HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
613	HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
614	HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
615	HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \
616	HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \
617	HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \
618	HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \
619	HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh)
620
621static const struct dce_hwseq_shift hwseq_shift = {
622		HWSEQ_DCN32_MASK_SH_LIST(__SHIFT)
623};
624
625static const struct dce_hwseq_mask hwseq_mask = {
626		HWSEQ_DCN32_MASK_SH_LIST(_MASK)
627};
628#define vmid_regs_init(id)\
629		DCN20_VMID_REG_LIST_RI(id)
630
631static struct dcn_vmid_registers vmid_regs[16];
632
633static const struct dcn20_vmid_shift vmid_shifts = {
634		DCN20_VMID_MASK_SH_LIST(__SHIFT)
635};
636
637static const struct dcn20_vmid_mask vmid_masks = {
638		DCN20_VMID_MASK_SH_LIST(_MASK)
639};
640
641static const struct resource_caps res_cap_dcn32 = {
642	.num_timing_generator = 4,
643	.num_opp = 4,
644	.num_video_plane = 4,
645	.num_audio = 5,
646	.num_stream_encoder = 5,
647	.num_hpo_dp_stream_encoder = 4,
648	.num_hpo_dp_link_encoder = 2,
649	.num_pll = 5,
650	.num_dwb = 1,
651	.num_ddc = 5,
652	.num_vmid = 16,
653	.num_mpc_3dlut = 4,
654	.num_dsc = 4,
655};
656
657static const struct dc_plane_cap plane_cap = {
658	.type = DC_PLANE_TYPE_DCN_UNIVERSAL,
659	.per_pixel_alpha = true,
660
661	.pixel_format_support = {
662			.argb8888 = true,
663			.nv12 = true,
664			.fp16 = true,
665			.p010 = true,
666			.ayuv = false,
667	},
668
669	.max_upscale_factor = {
670			.argb8888 = 16000,
671			.nv12 = 16000,
672			.fp16 = 16000
673	},
674
675	// 6:1 downscaling ratio: 1000/6 = 166.666
676	.max_downscale_factor = {
677			.argb8888 = 167,
678			.nv12 = 167,
679			.fp16 = 167
680	},
681	64,
682	64
683};
684
685static const struct dc_debug_options debug_defaults_drv = {
686	.disable_dmcu = true,
687	.force_abm_enable = false,
688	.timing_trace = false,
689	.clock_trace = true,
690	.disable_pplib_clock_request = false,
691	.pipe_split_policy = MPC_SPLIT_AVOID, // Due to CRB, no need to MPC split anymore
692	.force_single_disp_pipe_split = false,
693	.disable_dcc = DCC_ENABLE,
694	.vsr_support = true,
695	.performance_trace = false,
696	.max_downscale_src_width = 7680,/*upto 8K*/
697	.disable_pplib_wm_range = false,
698	.scl_reset_length10 = true,
699	.sanity_checks = false,
700	.underflow_assert_delay_us = 0xFFFFFFFF,
701	.dwb_fi_phase = -1, // -1 = disable,
702	.dmub_command_table = true,
703	.enable_mem_low_power = {
704		.bits = {
705			.vga = false,
706			.i2c = false,
707			.dmcu = false, // This is previously known to cause hang on S3 cycles if enabled
708			.dscl = false,
709			.cm = false,
710			.mpc = false,
711			.optc = true,
712		}
713	},
714	.use_max_lb = true,
715	.force_disable_subvp = false,
716	.exit_idle_opt_for_cursor_updates = true,
717	.enable_single_display_2to1_odm_policy = true,
718
719	/* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/
720	.enable_double_buffered_dsc_pg_support = true,
721	.enable_dp_dig_pixel_rate_div_policy = 1,
722	.allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback"
723	.alloc_extra_way_for_cursor = true,
724	.min_prefetch_in_strobe_ns = 60000, // 60us
725	.disable_unbounded_requesting = false,
726	.override_dispclk_programming = true,
727	.disable_fpo_optimizations = false,
728	.fpo_vactive_margin_us = 2000, // 2000us
729	.disable_fpo_vactive = false,
730	.disable_boot_optimizations = false,
731	.disable_subvp_high_refresh = false,
732	.disable_dp_plus_plus_wa = true,
733	.fpo_vactive_min_active_margin_us = 200,
734	.fpo_vactive_max_blank_us = 1000,
735	.enable_legacy_fast_update = false,
736};
737
738static struct dce_aux *dcn32_aux_engine_create(
739	struct dc_context *ctx,
740	uint32_t inst)
741{
742	struct aux_engine_dce110 *aux_engine =
743		kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);
744
745	if (!aux_engine)
746		return NULL;
747
748#undef REG_STRUCT
749#define REG_STRUCT aux_engine_regs
750	aux_engine_regs_init(0),
751	aux_engine_regs_init(1),
752	aux_engine_regs_init(2),
753	aux_engine_regs_init(3),
754	aux_engine_regs_init(4);
755
756	dce110_aux_engine_construct(aux_engine, ctx, inst,
757				    SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
758				    &aux_engine_regs[inst],
759					&aux_mask,
760					&aux_shift,
761					ctx->dc->caps.extended_aux_timeout_support);
762
763	return &aux_engine->base;
764}
765#define i2c_inst_regs_init(id)\
766	I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id)
767
768static struct dce_i2c_registers i2c_hw_regs[5];
769
770static const struct dce_i2c_shift i2c_shifts = {
771		I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT)
772};
773
774static const struct dce_i2c_mask i2c_masks = {
775		I2C_COMMON_MASK_SH_LIST_DCN30(_MASK)
776};
777
778static struct dce_i2c_hw *dcn32_i2c_hw_create(
779	struct dc_context *ctx,
780	uint32_t inst)
781{
782	struct dce_i2c_hw *dce_i2c_hw =
783		kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);
784
785	if (!dce_i2c_hw)
786		return NULL;
787
788#undef REG_STRUCT
789#define REG_STRUCT i2c_hw_regs
790	i2c_inst_regs_init(1),
791	i2c_inst_regs_init(2),
792	i2c_inst_regs_init(3),
793	i2c_inst_regs_init(4),
794	i2c_inst_regs_init(5);
795
796	dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,
797				    &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);
798
799	return dce_i2c_hw;
800}
801
802static struct clock_source *dcn32_clock_source_create(
803		struct dc_context *ctx,
804		struct dc_bios *bios,
805		enum clock_source_id id,
806		const struct dce110_clk_src_regs *regs,
807		bool dp_clk_src)
808{
809	struct dce110_clk_src *clk_src =
810		kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL);
811
812	if (!clk_src)
813		return NULL;
814
815	if (dcn31_clk_src_construct(clk_src, ctx, bios, id,
816			regs, &cs_shift, &cs_mask)) {
817		clk_src->base.dp_clk_src = dp_clk_src;
818		return &clk_src->base;
819	}
820
821	kfree(clk_src);
822	BREAK_TO_DEBUGGER();
823	return NULL;
824}
825
826static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx)
827{
828	int i;
829
830	struct dcn20_hubbub *hubbub2 = kzalloc(sizeof(struct dcn20_hubbub),
831					  GFP_KERNEL);
832
833	if (!hubbub2)
834		return NULL;
835
836#undef REG_STRUCT
837#define REG_STRUCT hubbub_reg
838	hubbub_reg_init();
839
840#undef REG_STRUCT
841#define REG_STRUCT vmid_regs
842	vmid_regs_init(0),
843	vmid_regs_init(1),
844	vmid_regs_init(2),
845	vmid_regs_init(3),
846	vmid_regs_init(4),
847	vmid_regs_init(5),
848	vmid_regs_init(6),
849	vmid_regs_init(7),
850	vmid_regs_init(8),
851	vmid_regs_init(9),
852	vmid_regs_init(10),
853	vmid_regs_init(11),
854	vmid_regs_init(12),
855	vmid_regs_init(13),
856	vmid_regs_init(14),
857	vmid_regs_init(15);
858
859	hubbub32_construct(hubbub2, ctx,
860			&hubbub_reg,
861			&hubbub_shift,
862			&hubbub_mask,
863			ctx->dc->dml.ip.det_buffer_size_kbytes,
864			ctx->dc->dml.ip.pixel_chunk_size_kbytes,
865			ctx->dc->dml.ip.config_return_buffer_size_in_kbytes);
866
867
868	for (i = 0; i < res_cap_dcn32.num_vmid; i++) {
869		struct dcn20_vmid *vmid = &hubbub2->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 &hubbub2->base;
879}
880
881static struct hubp *dcn32_hubp_create(
882	struct dc_context *ctx,
883	uint32_t inst)
884{
885	struct dcn20_hubp *hubp2 =
886		kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL);
887
888	if (!hubp2)
889		return NULL;
890
891#undef REG_STRUCT
892#define REG_STRUCT hubp_regs
893	hubp_regs_init(0),
894	hubp_regs_init(1),
895	hubp_regs_init(2),
896	hubp_regs_init(3);
897
898	if (hubp32_construct(hubp2, ctx, inst,
899			&hubp_regs[inst], &hubp_shift, &hubp_mask))
900		return &hubp2->base;
901
902	BREAK_TO_DEBUGGER();
903	kfree(hubp2);
904	return NULL;
905}
906
907static void dcn32_dpp_destroy(struct dpp **dpp)
908{
909	kfree(TO_DCN30_DPP(*dpp));
910	*dpp = NULL;
911}
912
913static struct dpp *dcn32_dpp_create(
914	struct dc_context *ctx,
915	uint32_t inst)
916{
917	struct dcn3_dpp *dpp3 =
918		kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL);
919
920	if (!dpp3)
921		return NULL;
922
923#undef REG_STRUCT
924#define REG_STRUCT dpp_regs
925	dpp_regs_init(0),
926	dpp_regs_init(1),
927	dpp_regs_init(2),
928	dpp_regs_init(3);
929
930	if (dpp32_construct(dpp3, ctx, inst,
931			&dpp_regs[inst], &tf_shift, &tf_mask))
932		return &dpp3->base;
933
934	BREAK_TO_DEBUGGER();
935	kfree(dpp3);
936	return NULL;
937}
938
939static struct mpc *dcn32_mpc_create(
940		struct dc_context *ctx,
941		int num_mpcc,
942		int num_rmu)
943{
944	struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc),
945					  GFP_KERNEL);
946
947	if (!mpc30)
948		return NULL;
949
950#undef REG_STRUCT
951#define REG_STRUCT mpc_regs
952	dcn_mpc_regs_init();
953
954	dcn32_mpc_construct(mpc30, ctx,
955			&mpc_regs,
956			&mpc_shift,
957			&mpc_mask,
958			num_mpcc,
959			num_rmu);
960
961	return &mpc30->base;
962}
963
964static struct output_pixel_processor *dcn32_opp_create(
965	struct dc_context *ctx, uint32_t inst)
966{
967	struct dcn20_opp *opp2 =
968		kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL);
969
970	if (!opp2) {
971		BREAK_TO_DEBUGGER();
972		return NULL;
973	}
974
975#undef REG_STRUCT
976#define REG_STRUCT opp_regs
977	opp_regs_init(0),
978	opp_regs_init(1),
979	opp_regs_init(2),
980	opp_regs_init(3);
981
982	dcn20_opp_construct(opp2, ctx, inst,
983			&opp_regs[inst], &opp_shift, &opp_mask);
984	return &opp2->base;
985}
986
987
988static struct timing_generator *dcn32_timing_generator_create(
989		struct dc_context *ctx,
990		uint32_t instance)
991{
992	struct optc *tgn10 =
993		kzalloc(sizeof(struct optc), GFP_KERNEL);
994
995	if (!tgn10)
996		return NULL;
997
998#undef REG_STRUCT
999#define REG_STRUCT optc_regs
1000	optc_regs_init(0),
1001	optc_regs_init(1),
1002	optc_regs_init(2),
1003	optc_regs_init(3);
1004
1005	tgn10->base.inst = instance;
1006	tgn10->base.ctx = ctx;
1007
1008	tgn10->tg_regs = &optc_regs[instance];
1009	tgn10->tg_shift = &optc_shift;
1010	tgn10->tg_mask = &optc_mask;
1011
1012	dcn32_timing_generator_init(tgn10);
1013
1014	return &tgn10->base;
1015}
1016
1017static const struct encoder_feature_support link_enc_feature = {
1018		.max_hdmi_deep_color = COLOR_DEPTH_121212,
1019		.max_hdmi_pixel_clock = 600000,
1020		.hdmi_ycbcr420_supported = true,
1021		.dp_ycbcr420_supported = true,
1022		.fec_supported = true,
1023		.flags.bits.IS_HBR2_CAPABLE = true,
1024		.flags.bits.IS_HBR3_CAPABLE = true,
1025		.flags.bits.IS_TPS3_CAPABLE = true,
1026		.flags.bits.IS_TPS4_CAPABLE = true
1027};
1028
1029static struct link_encoder *dcn32_link_encoder_create(
1030	struct dc_context *ctx,
1031	const struct encoder_init_data *enc_init_data)
1032{
1033	struct dcn20_link_encoder *enc20 =
1034		kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
1035
1036	if (!enc20)
1037		return NULL;
1038
1039#undef REG_STRUCT
1040#define REG_STRUCT link_enc_aux_regs
1041	aux_regs_init(0),
1042	aux_regs_init(1),
1043	aux_regs_init(2),
1044	aux_regs_init(3),
1045	aux_regs_init(4);
1046
1047#undef REG_STRUCT
1048#define REG_STRUCT link_enc_hpd_regs
1049	hpd_regs_init(0),
1050	hpd_regs_init(1),
1051	hpd_regs_init(2),
1052	hpd_regs_init(3),
1053	hpd_regs_init(4);
1054
1055#undef REG_STRUCT
1056#define REG_STRUCT link_enc_regs
1057	link_regs_init(0, A),
1058	link_regs_init(1, B),
1059	link_regs_init(2, C),
1060	link_regs_init(3, D),
1061	link_regs_init(4, E);
1062
1063	dcn32_link_encoder_construct(enc20,
1064			enc_init_data,
1065			&link_enc_feature,
1066			&link_enc_regs[enc_init_data->transmitter],
1067			&link_enc_aux_regs[enc_init_data->channel - 1],
1068			&link_enc_hpd_regs[enc_init_data->hpd_source],
1069			&le_shift,
1070			&le_mask);
1071
1072	return &enc20->enc10.base;
1073}
1074
1075struct panel_cntl *dcn32_panel_cntl_create(const struct panel_cntl_init_data *init_data)
1076{
1077	struct dcn31_panel_cntl *panel_cntl =
1078		kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL);
1079
1080	if (!panel_cntl)
1081		return NULL;
1082
1083	dcn31_panel_cntl_construct(panel_cntl, init_data);
1084
1085	return &panel_cntl->base;
1086}
1087
1088static void read_dce_straps(
1089	struct dc_context *ctx,
1090	struct resource_straps *straps)
1091{
1092	generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS,
1093		FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);
1094
1095}
1096
1097static struct audio *dcn32_create_audio(
1098		struct dc_context *ctx, unsigned int inst)
1099{
1100
1101#undef REG_STRUCT
1102#define REG_STRUCT audio_regs
1103	audio_regs_init(0),
1104	audio_regs_init(1),
1105	audio_regs_init(2),
1106	audio_regs_init(3),
1107	audio_regs_init(4);
1108
1109	return dce_audio_create(ctx, inst,
1110			&audio_regs[inst], &audio_shift, &audio_mask);
1111}
1112
1113static struct vpg *dcn32_vpg_create(
1114	struct dc_context *ctx,
1115	uint32_t inst)
1116{
1117	struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL);
1118
1119	if (!vpg3)
1120		return NULL;
1121
1122#undef REG_STRUCT
1123#define REG_STRUCT vpg_regs
1124	vpg_regs_init(0),
1125	vpg_regs_init(1),
1126	vpg_regs_init(2),
1127	vpg_regs_init(3),
1128	vpg_regs_init(4),
1129	vpg_regs_init(5),
1130	vpg_regs_init(6),
1131	vpg_regs_init(7),
1132	vpg_regs_init(8),
1133	vpg_regs_init(9);
1134
1135	vpg3_construct(vpg3, ctx, inst,
1136			&vpg_regs[inst],
1137			&vpg_shift,
1138			&vpg_mask);
1139
1140	return &vpg3->base;
1141}
1142
1143static struct afmt *dcn32_afmt_create(
1144	struct dc_context *ctx,
1145	uint32_t inst)
1146{
1147	struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL);
1148
1149	if (!afmt3)
1150		return NULL;
1151
1152#undef REG_STRUCT
1153#define REG_STRUCT afmt_regs
1154	afmt_regs_init(0),
1155	afmt_regs_init(1),
1156	afmt_regs_init(2),
1157	afmt_regs_init(3),
1158	afmt_regs_init(4),
1159	afmt_regs_init(5);
1160
1161	afmt3_construct(afmt3, ctx, inst,
1162			&afmt_regs[inst],
1163			&afmt_shift,
1164			&afmt_mask);
1165
1166	return &afmt3->base;
1167}
1168
1169static struct apg *dcn31_apg_create(
1170	struct dc_context *ctx,
1171	uint32_t inst)
1172{
1173	struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL);
1174
1175	if (!apg31)
1176		return NULL;
1177
1178#undef REG_STRUCT
1179#define REG_STRUCT apg_regs
1180	apg_regs_init(0),
1181	apg_regs_init(1),
1182	apg_regs_init(2),
1183	apg_regs_init(3);
1184
1185	apg31_construct(apg31, ctx, inst,
1186			&apg_regs[inst],
1187			&apg_shift,
1188			&apg_mask);
1189
1190	return &apg31->base;
1191}
1192
1193static struct stream_encoder *dcn32_stream_encoder_create(
1194	enum engine_id eng_id,
1195	struct dc_context *ctx)
1196{
1197	struct dcn10_stream_encoder *enc1;
1198	struct vpg *vpg;
1199	struct afmt *afmt;
1200	int vpg_inst;
1201	int afmt_inst;
1202
1203	/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
1204	if (eng_id <= ENGINE_ID_DIGF) {
1205		vpg_inst = eng_id;
1206		afmt_inst = eng_id;
1207	} else
1208		return NULL;
1209
1210	enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
1211	vpg = dcn32_vpg_create(ctx, vpg_inst);
1212	afmt = dcn32_afmt_create(ctx, afmt_inst);
1213
1214	if (!enc1 || !vpg || !afmt) {
1215		kfree(enc1);
1216		kfree(vpg);
1217		kfree(afmt);
1218		return NULL;
1219	}
1220
1221#undef REG_STRUCT
1222#define REG_STRUCT stream_enc_regs
1223	stream_enc_regs_init(0),
1224	stream_enc_regs_init(1),
1225	stream_enc_regs_init(2),
1226	stream_enc_regs_init(3),
1227	stream_enc_regs_init(4);
1228
1229	dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,
1230					eng_id, vpg, afmt,
1231					&stream_enc_regs[eng_id],
1232					&se_shift, &se_mask);
1233
1234	return &enc1->base;
1235}
1236
1237static struct hpo_dp_stream_encoder *dcn32_hpo_dp_stream_encoder_create(
1238	enum engine_id eng_id,
1239	struct dc_context *ctx)
1240{
1241	struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31;
1242	struct vpg *vpg;
1243	struct apg *apg;
1244	uint32_t hpo_dp_inst;
1245	uint32_t vpg_inst;
1246	uint32_t apg_inst;
1247
1248	ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3));
1249	hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0;
1250
1251	/* Mapping of VPG register blocks to HPO DP block instance:
1252	 * VPG[6] -> HPO_DP[0]
1253	 * VPG[7] -> HPO_DP[1]
1254	 * VPG[8] -> HPO_DP[2]
1255	 * VPG[9] -> HPO_DP[3]
1256	 */
1257	vpg_inst = hpo_dp_inst + 6;
1258
1259	/* Mapping of APG register blocks to HPO DP block instance:
1260	 * APG[0] -> HPO_DP[0]
1261	 * APG[1] -> HPO_DP[1]
1262	 * APG[2] -> HPO_DP[2]
1263	 * APG[3] -> HPO_DP[3]
1264	 */
1265	apg_inst = hpo_dp_inst;
1266
1267	/* allocate HPO stream encoder and create VPG sub-block */
1268	hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL);
1269	vpg = dcn32_vpg_create(ctx, vpg_inst);
1270	apg = dcn31_apg_create(ctx, apg_inst);
1271
1272	if (!hpo_dp_enc31 || !vpg || !apg) {
1273		kfree(hpo_dp_enc31);
1274		kfree(vpg);
1275		kfree(apg);
1276		return NULL;
1277	}
1278
1279#undef REG_STRUCT
1280#define REG_STRUCT hpo_dp_stream_enc_regs
1281	hpo_dp_stream_encoder_reg_init(0),
1282	hpo_dp_stream_encoder_reg_init(1),
1283	hpo_dp_stream_encoder_reg_init(2),
1284	hpo_dp_stream_encoder_reg_init(3);
1285
1286	dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios,
1287					hpo_dp_inst, eng_id, vpg, apg,
1288					&hpo_dp_stream_enc_regs[hpo_dp_inst],
1289					&hpo_dp_se_shift, &hpo_dp_se_mask);
1290
1291	return &hpo_dp_enc31->base;
1292}
1293
1294static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create(
1295	uint8_t inst,
1296	struct dc_context *ctx)
1297{
1298	struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31;
1299
1300	/* allocate HPO link encoder */
1301	hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
1302
1303#undef REG_STRUCT
1304#define REG_STRUCT hpo_dp_link_enc_regs
1305	hpo_dp_link_encoder_reg_init(0),
1306	hpo_dp_link_encoder_reg_init(1);
1307
1308	hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst,
1309					&hpo_dp_link_enc_regs[inst],
1310					&hpo_dp_le_shift, &hpo_dp_le_mask);
1311
1312	return &hpo_dp_enc31->base;
1313}
1314
1315static struct dce_hwseq *dcn32_hwseq_create(
1316	struct dc_context *ctx)
1317{
1318	struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
1319
1320#undef REG_STRUCT
1321#define REG_STRUCT hwseq_reg
1322	hwseq_reg_init();
1323
1324	if (hws) {
1325		hws->ctx = ctx;
1326		hws->regs = &hwseq_reg;
1327		hws->shifts = &hwseq_shift;
1328		hws->masks = &hwseq_mask;
1329	}
1330	return hws;
1331}
1332static const struct resource_create_funcs res_create_funcs = {
1333	.read_dce_straps = read_dce_straps,
1334	.create_audio = dcn32_create_audio,
1335	.create_stream_encoder = dcn32_stream_encoder_create,
1336	.create_hpo_dp_stream_encoder = dcn32_hpo_dp_stream_encoder_create,
1337	.create_hpo_dp_link_encoder = dcn32_hpo_dp_link_encoder_create,
1338	.create_hwseq = dcn32_hwseq_create,
1339};
1340
1341static void dcn32_resource_destruct(struct dcn32_resource_pool *pool)
1342{
1343	unsigned int i;
1344
1345	for (i = 0; i < pool->base.stream_enc_count; i++) {
1346		if (pool->base.stream_enc[i] != NULL) {
1347			if (pool->base.stream_enc[i]->vpg != NULL) {
1348				kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg));
1349				pool->base.stream_enc[i]->vpg = NULL;
1350			}
1351			if (pool->base.stream_enc[i]->afmt != NULL) {
1352				kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt));
1353				pool->base.stream_enc[i]->afmt = NULL;
1354			}
1355			kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));
1356			pool->base.stream_enc[i] = NULL;
1357		}
1358	}
1359
1360	for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) {
1361		if (pool->base.hpo_dp_stream_enc[i] != NULL) {
1362			if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) {
1363				kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg));
1364				pool->base.hpo_dp_stream_enc[i]->vpg = NULL;
1365			}
1366			if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) {
1367				kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg));
1368				pool->base.hpo_dp_stream_enc[i]->apg = NULL;
1369			}
1370			kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i]));
1371			pool->base.hpo_dp_stream_enc[i] = NULL;
1372		}
1373	}
1374
1375	for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) {
1376		if (pool->base.hpo_dp_link_enc[i] != NULL) {
1377			kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i]));
1378			pool->base.hpo_dp_link_enc[i] = NULL;
1379		}
1380	}
1381
1382	for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
1383		if (pool->base.dscs[i] != NULL)
1384			dcn20_dsc_destroy(&pool->base.dscs[i]);
1385	}
1386
1387	if (pool->base.mpc != NULL) {
1388		kfree(TO_DCN20_MPC(pool->base.mpc));
1389		pool->base.mpc = NULL;
1390	}
1391	if (pool->base.hubbub != NULL) {
1392		kfree(TO_DCN20_HUBBUB(pool->base.hubbub));
1393		pool->base.hubbub = NULL;
1394	}
1395	for (i = 0; i < pool->base.pipe_count; i++) {
1396		if (pool->base.dpps[i] != NULL)
1397			dcn32_dpp_destroy(&pool->base.dpps[i]);
1398
1399		if (pool->base.ipps[i] != NULL)
1400			pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);
1401
1402		if (pool->base.hubps[i] != NULL) {
1403			kfree(TO_DCN20_HUBP(pool->base.hubps[i]));
1404			pool->base.hubps[i] = NULL;
1405		}
1406
1407		if (pool->base.irqs != NULL) {
1408			dal_irq_service_destroy(&pool->base.irqs);
1409		}
1410	}
1411
1412	for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
1413		if (pool->base.engines[i] != NULL)
1414			dce110_engine_destroy(&pool->base.engines[i]);
1415		if (pool->base.hw_i2cs[i] != NULL) {
1416			kfree(pool->base.hw_i2cs[i]);
1417			pool->base.hw_i2cs[i] = NULL;
1418		}
1419		if (pool->base.sw_i2cs[i] != NULL) {
1420			kfree(pool->base.sw_i2cs[i]);
1421			pool->base.sw_i2cs[i] = NULL;
1422		}
1423	}
1424
1425	for (i = 0; i < pool->base.res_cap->num_opp; i++) {
1426		if (pool->base.opps[i] != NULL)
1427			pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
1428	}
1429
1430	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
1431		if (pool->base.timing_generators[i] != NULL)	{
1432			kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
1433			pool->base.timing_generators[i] = NULL;
1434		}
1435	}
1436
1437	for (i = 0; i < pool->base.res_cap->num_dwb; i++) {
1438		if (pool->base.dwbc[i] != NULL) {
1439			kfree(TO_DCN30_DWBC(pool->base.dwbc[i]));
1440			pool->base.dwbc[i] = NULL;
1441		}
1442		if (pool->base.mcif_wb[i] != NULL) {
1443			kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i]));
1444			pool->base.mcif_wb[i] = NULL;
1445		}
1446	}
1447
1448	for (i = 0; i < pool->base.audio_count; i++) {
1449		if (pool->base.audios[i])
1450			dce_aud_destroy(&pool->base.audios[i]);
1451	}
1452
1453	for (i = 0; i < pool->base.clk_src_count; i++) {
1454		if (pool->base.clock_sources[i] != NULL) {
1455			dcn20_clock_source_destroy(&pool->base.clock_sources[i]);
1456			pool->base.clock_sources[i] = NULL;
1457		}
1458	}
1459
1460	for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) {
1461		if (pool->base.mpc_lut[i] != NULL) {
1462			dc_3dlut_func_release(pool->base.mpc_lut[i]);
1463			pool->base.mpc_lut[i] = NULL;
1464		}
1465		if (pool->base.mpc_shaper[i] != NULL) {
1466			dc_transfer_func_release(pool->base.mpc_shaper[i]);
1467			pool->base.mpc_shaper[i] = NULL;
1468		}
1469	}
1470
1471	if (pool->base.dp_clock_source != NULL) {
1472		dcn20_clock_source_destroy(&pool->base.dp_clock_source);
1473		pool->base.dp_clock_source = NULL;
1474	}
1475
1476	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
1477		if (pool->base.multiple_abms[i] != NULL)
1478			dce_abm_destroy(&pool->base.multiple_abms[i]);
1479	}
1480
1481	if (pool->base.psr != NULL)
1482		dmub_psr_destroy(&pool->base.psr);
1483
1484	if (pool->base.dccg != NULL)
1485		dcn_dccg_destroy(&pool->base.dccg);
1486
1487	if (pool->base.oem_device != NULL) {
1488		struct dc *dc = pool->base.oem_device->ctx->dc;
1489
1490		dc->link_srv->destroy_ddc_service(&pool->base.oem_device);
1491	}
1492}
1493
1494
1495static bool dcn32_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
1496{
1497	int i;
1498	uint32_t dwb_count = pool->res_cap->num_dwb;
1499
1500	for (i = 0; i < dwb_count; i++) {
1501		struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc),
1502						    GFP_KERNEL);
1503
1504		if (!dwbc30) {
1505			dm_error("DC: failed to create dwbc30!\n");
1506			return false;
1507		}
1508
1509#undef REG_STRUCT
1510#define REG_STRUCT dwbc30_regs
1511		dwbc_regs_dcn3_init(0);
1512
1513		dcn30_dwbc_construct(dwbc30, ctx,
1514				&dwbc30_regs[i],
1515				&dwbc30_shift,
1516				&dwbc30_mask,
1517				i);
1518
1519		pool->dwbc[i] = &dwbc30->base;
1520	}
1521	return true;
1522}
1523
1524static bool dcn32_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
1525{
1526	int i;
1527	uint32_t dwb_count = pool->res_cap->num_dwb;
1528
1529	for (i = 0; i < dwb_count; i++) {
1530		struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub),
1531						    GFP_KERNEL);
1532
1533		if (!mcif_wb30) {
1534			dm_error("DC: failed to create mcif_wb30!\n");
1535			return false;
1536		}
1537
1538#undef REG_STRUCT
1539#define REG_STRUCT mcif_wb30_regs
1540		mcif_wb_regs_dcn3_init(0);
1541
1542		dcn32_mmhubbub_construct(mcif_wb30, ctx,
1543				&mcif_wb30_regs[i],
1544				&mcif_wb30_shift,
1545				&mcif_wb30_mask,
1546				i);
1547
1548		pool->mcif_wb[i] = &mcif_wb30->base;
1549	}
1550	return true;
1551}
1552
1553static struct display_stream_compressor *dcn32_dsc_create(
1554	struct dc_context *ctx, uint32_t inst)
1555{
1556	struct dcn20_dsc *dsc =
1557		kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL);
1558
1559	if (!dsc) {
1560		BREAK_TO_DEBUGGER();
1561		return NULL;
1562	}
1563
1564#undef REG_STRUCT
1565#define REG_STRUCT dsc_regs
1566	dsc_regsDCN20_init(0),
1567	dsc_regsDCN20_init(1),
1568	dsc_regsDCN20_init(2),
1569	dsc_regsDCN20_init(3);
1570
1571	dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
1572
1573	dsc->max_image_width = 6016;
1574
1575	return &dsc->base;
1576}
1577
1578static void dcn32_destroy_resource_pool(struct resource_pool **pool)
1579{
1580	struct dcn32_resource_pool *dcn32_pool = TO_DCN32_RES_POOL(*pool);
1581
1582	dcn32_resource_destruct(dcn32_pool);
1583	kfree(dcn32_pool);
1584	*pool = NULL;
1585}
1586
1587bool dcn32_acquire_post_bldn_3dlut(
1588		struct resource_context *res_ctx,
1589		const struct resource_pool *pool,
1590		int mpcc_id,
1591		struct dc_3dlut **lut,
1592		struct dc_transfer_func **shaper)
1593{
1594	bool ret = false;
1595
1596	ASSERT(*lut == NULL && *shaper == NULL);
1597	*lut = NULL;
1598	*shaper = NULL;
1599
1600	if (!res_ctx->is_mpc_3dlut_acquired[mpcc_id]) {
1601		*lut = pool->mpc_lut[mpcc_id];
1602		*shaper = pool->mpc_shaper[mpcc_id];
1603		res_ctx->is_mpc_3dlut_acquired[mpcc_id] = true;
1604		ret = true;
1605	}
1606	return ret;
1607}
1608
1609bool dcn32_release_post_bldn_3dlut(
1610		struct resource_context *res_ctx,
1611		const struct resource_pool *pool,
1612		struct dc_3dlut **lut,
1613		struct dc_transfer_func **shaper)
1614{
1615	int i;
1616	bool ret = false;
1617
1618	for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) {
1619		if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) {
1620			res_ctx->is_mpc_3dlut_acquired[i] = false;
1621			pool->mpc_lut[i]->state.raw = 0;
1622			*lut = NULL;
1623			*shaper = NULL;
1624			ret = true;
1625			break;
1626		}
1627	}
1628	return ret;
1629}
1630
1631static void dcn32_enable_phantom_plane(struct dc *dc,
1632		struct dc_state *context,
1633		struct dc_stream_state *phantom_stream,
1634		unsigned int dc_pipe_idx)
1635{
1636	struct dc_plane_state *phantom_plane = NULL;
1637	struct dc_plane_state *prev_phantom_plane = NULL;
1638	struct pipe_ctx *curr_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];
1639
1640	while (curr_pipe) {
1641		if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state)
1642			phantom_plane = prev_phantom_plane;
1643		else
1644			phantom_plane = dc_create_plane_state(dc);
1645
1646		memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address));
1647		memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality,
1648				sizeof(phantom_plane->scaling_quality));
1649		memcpy(&phantom_plane->src_rect, &curr_pipe->plane_state->src_rect, sizeof(phantom_plane->src_rect));
1650		memcpy(&phantom_plane->dst_rect, &curr_pipe->plane_state->dst_rect, sizeof(phantom_plane->dst_rect));
1651		memcpy(&phantom_plane->clip_rect, &curr_pipe->plane_state->clip_rect, sizeof(phantom_plane->clip_rect));
1652		memcpy(&phantom_plane->plane_size, &curr_pipe->plane_state->plane_size,
1653				sizeof(phantom_plane->plane_size));
1654		memcpy(&phantom_plane->tiling_info, &curr_pipe->plane_state->tiling_info,
1655				sizeof(phantom_plane->tiling_info));
1656		memcpy(&phantom_plane->dcc, &curr_pipe->plane_state->dcc, sizeof(phantom_plane->dcc));
1657		phantom_plane->format = curr_pipe->plane_state->format;
1658		phantom_plane->rotation = curr_pipe->plane_state->rotation;
1659		phantom_plane->visible = curr_pipe->plane_state->visible;
1660
1661		/* Shadow pipe has small viewport. */
1662		phantom_plane->clip_rect.y = 0;
1663		phantom_plane->clip_rect.height = phantom_stream->src.height;
1664
1665		phantom_plane->is_phantom = true;
1666
1667		dc_add_plane_to_context(dc, phantom_stream, phantom_plane, context);
1668
1669		curr_pipe = curr_pipe->bottom_pipe;
1670		prev_phantom_plane = phantom_plane;
1671	}
1672}
1673
1674static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc,
1675		struct dc_state *context,
1676		display_e2e_pipe_params_st *pipes,
1677		unsigned int pipe_cnt,
1678		unsigned int dc_pipe_idx)
1679{
1680	struct dc_stream_state *phantom_stream = NULL;
1681	struct pipe_ctx *ref_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];
1682
1683	phantom_stream = dc_create_stream_for_sink(ref_pipe->stream->sink);
1684	phantom_stream->signal = SIGNAL_TYPE_VIRTUAL;
1685	phantom_stream->dpms_off = true;
1686	phantom_stream->mall_stream_config.type = SUBVP_PHANTOM;
1687	phantom_stream->mall_stream_config.paired_stream = ref_pipe->stream;
1688	ref_pipe->stream->mall_stream_config.type = SUBVP_MAIN;
1689	ref_pipe->stream->mall_stream_config.paired_stream = phantom_stream;
1690
1691	/* stream has limited viewport and small timing */
1692	memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing));
1693	memcpy(&phantom_stream->src, &ref_pipe->stream->src, sizeof(phantom_stream->src));
1694	memcpy(&phantom_stream->dst, &ref_pipe->stream->dst, sizeof(phantom_stream->dst));
1695	DC_FP_START();
1696	dcn32_set_phantom_stream_timing(dc, context, ref_pipe, phantom_stream, pipes, pipe_cnt, dc_pipe_idx);
1697	DC_FP_END();
1698
1699	dc_add_stream_to_ctx(dc, context, phantom_stream);
1700	return phantom_stream;
1701}
1702
1703void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context)
1704{
1705	int i;
1706	struct dc_plane_state *phantom_plane = NULL;
1707	struct dc_stream_state *phantom_stream = NULL;
1708
1709	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1710		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1711
1712		if (resource_is_pipe_type(pipe, OTG_MASTER) &&
1713				resource_is_pipe_type(pipe, DPP_PIPE) &&
1714				pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
1715			phantom_plane = pipe->plane_state;
1716			phantom_stream = pipe->stream;
1717
1718			dc_plane_state_retain(phantom_plane);
1719			dc_stream_retain(phantom_stream);
1720		}
1721	}
1722}
1723
1724// return true if removed piped from ctx, false otherwise
1725bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context, bool fast_update)
1726{
1727	int i;
1728	bool removed_pipe = false;
1729	struct dc_plane_state *phantom_plane = NULL;
1730	struct dc_stream_state *phantom_stream = NULL;
1731
1732	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1733		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1734		// build scaling params for phantom pipes
1735		if (pipe->plane_state && pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
1736			phantom_plane = pipe->plane_state;
1737			phantom_stream = pipe->stream;
1738
1739			dc_rem_all_planes_for_stream(dc, pipe->stream, context);
1740			dc_remove_stream_from_ctx(dc, context, pipe->stream);
1741
1742			/* Ref count is incremented on allocation and also when added to the context.
1743			 * Therefore we must call release for the the phantom plane and stream once
1744			 * they are removed from the ctx to finally decrement the refcount to 0 to free.
1745			 */
1746			dc_plane_state_release(phantom_plane);
1747			dc_stream_release(phantom_stream);
1748
1749			removed_pipe = true;
1750		}
1751
1752		/* For non-full updates, a shallow copy of the current state
1753		 * is created. In this case we don't want to erase the current
1754		 * state (there can be 2 HIRQL threads, one in flip, and one in
1755		 * checkMPO) that can cause a race condition.
1756		 *
1757		 * This is just a workaround, needs a proper fix.
1758		 */
1759		if (!fast_update) {
1760			// Clear all phantom stream info
1761			if (pipe->stream) {
1762				pipe->stream->mall_stream_config.type = SUBVP_NONE;
1763				pipe->stream->mall_stream_config.paired_stream = NULL;
1764			}
1765
1766			if (pipe->plane_state) {
1767				pipe->plane_state->is_phantom = false;
1768			}
1769		}
1770	}
1771	return removed_pipe;
1772}
1773
1774/* TODO: Input to this function should indicate which pipe indexes (or streams)
1775 * require a phantom pipe / stream
1776 */
1777void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context,
1778		display_e2e_pipe_params_st *pipes,
1779		unsigned int pipe_cnt,
1780		unsigned int index)
1781{
1782	struct dc_stream_state *phantom_stream = NULL;
1783	unsigned int i;
1784
1785	// The index of the DC pipe passed into this function is guarenteed to
1786	// be a valid candidate for SubVP (i.e. has a plane, stream, doesn't
1787	// already have phantom pipe assigned, etc.) by previous checks.
1788	phantom_stream = dcn32_enable_phantom_stream(dc, context, pipes, pipe_cnt, index);
1789	dcn32_enable_phantom_plane(dc, context, phantom_stream, index);
1790
1791	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1792		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1793
1794		// Build scaling params for phantom pipes which were newly added.
1795		// We determine which phantom pipes were added by comparing with
1796		// the phantom stream.
1797		if (pipe->plane_state && pipe->stream && pipe->stream == phantom_stream &&
1798				pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
1799			pipe->stream->use_dynamic_meta = false;
1800			pipe->plane_state->flip_immediate = false;
1801			if (!resource_build_scaling_params(pipe)) {
1802				// Log / remove phantom pipes since failed to build scaling params
1803			}
1804		}
1805	}
1806}
1807
1808bool dcn32_validate_bandwidth(struct dc *dc,
1809		struct dc_state *context,
1810		bool fast_validate)
1811{
1812	bool out = false;
1813
1814	BW_VAL_TRACE_SETUP();
1815
1816	int vlevel = 0;
1817	int pipe_cnt = 0;
1818	display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
1819	struct mall_temp_config mall_temp_config;
1820
1821	/* To handle Freesync properly, setting FreeSync DML parameters
1822	 * to its default state for the first stage of validation
1823	 */
1824	context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
1825	context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true;
1826
1827	DC_LOGGER_INIT(dc->ctx->logger);
1828
1829	/* For fast validation, there are situations where a shallow copy of
1830	 * of the dc->current_state is created for the validation. In this case
1831	 * we want to save and restore the mall config because we always
1832	 * teardown subvp at the beginning of validation (and don't attempt
1833	 * to add it back if it's fast validation). If we don't restore the
1834	 * subvp config in cases of fast validation + shallow copy of the
1835	 * dc->current_state, the dc->current_state will have a partially
1836	 * removed subvp state when we did not intend to remove it.
1837	 */
1838	if (fast_validate) {
1839		memset(&mall_temp_config, 0, sizeof(mall_temp_config));
1840		dcn32_save_mall_state(dc, context, &mall_temp_config);
1841	}
1842
1843	BW_VAL_TRACE_COUNT();
1844
1845	DC_FP_START();
1846	out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);
1847	DC_FP_END();
1848
1849	if (fast_validate)
1850		dcn32_restore_mall_state(dc, context, &mall_temp_config);
1851
1852	if (pipe_cnt == 0)
1853		goto validate_out;
1854
1855	if (!out)
1856		goto validate_fail;
1857
1858	BW_VAL_TRACE_END_VOLTAGE_LEVEL();
1859
1860	if (fast_validate) {
1861		BW_VAL_TRACE_SKIP(fast);
1862		goto validate_out;
1863	}
1864
1865	dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
1866
1867	dcn32_override_min_req_memclk(dc, context);
1868
1869	BW_VAL_TRACE_END_WATERMARKS();
1870
1871	goto validate_out;
1872
1873validate_fail:
1874	DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n",
1875		dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]));
1876
1877	BW_VAL_TRACE_SKIP(fail);
1878	out = false;
1879
1880validate_out:
1881	kfree(pipes);
1882
1883	BW_VAL_TRACE_FINISH();
1884
1885	return out;
1886}
1887
1888int dcn32_populate_dml_pipes_from_context(
1889	struct dc *dc, struct dc_state *context,
1890	display_e2e_pipe_params_st *pipes,
1891	bool fast_validate)
1892{
1893	int i, pipe_cnt;
1894	struct resource_context *res_ctx = &context->res_ctx;
1895	struct pipe_ctx *pipe = NULL;
1896	bool subvp_in_use = false;
1897	struct dc_crtc_timing *timing;
1898	bool vsr_odm_support = false;
1899
1900	dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
1901
1902	/* Determine whether we will apply ODM 2to1 policy:
1903	 * Applies to single display and where the number of planes is less than 3.
1904	 * For 3 plane case ( 2 MPO planes ), we will not set the policy for the MPO pipes.
1905	 *
1906	 * Apply pipe split policy first so we can predict the pipe split correctly
1907	 * (dcn32_predict_pipe_split).
1908	 */
1909	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
1910		if (!res_ctx->pipe_ctx[i].stream)
1911			continue;
1912		pipe = &res_ctx->pipe_ctx[i];
1913		timing = &pipe->stream->timing;
1914
1915		pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
1916		vsr_odm_support = (res_ctx->pipe_ctx[i].stream->src.width >= 5120 &&
1917				res_ctx->pipe_ctx[i].stream->src.width > res_ctx->pipe_ctx[i].stream->dst.width);
1918		if (context->stream_count == 1 &&
1919				context->stream_status[0].plane_count == 1 &&
1920				!dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&
1921				is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) &&
1922				pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ &&
1923				dc->debug.enable_single_display_2to1_odm_policy &&
1924				!vsr_odm_support) { //excluding 2to1 ODM combine on >= 5k vsr
1925			pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
1926		}
1927		pipe_cnt++;
1928	}
1929
1930	for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
1931
1932		if (!res_ctx->pipe_ctx[i].stream)
1933			continue;
1934		pipe = &res_ctx->pipe_ctx[i];
1935		timing = &pipe->stream->timing;
1936
1937		pipes[pipe_cnt].pipe.src.gpuvm = true;
1938		DC_FP_START();
1939		dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt);
1940		DC_FP_END();
1941		pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
1942		pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet
1943		pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
1944		pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19;
1945
1946		/* Only populate DML input with subvp info for full updates.
1947		 * This is just a workaround -- needs a proper fix.
1948		 */
1949		if (!fast_validate) {
1950			switch (pipe->stream->mall_stream_config.type) {
1951			case SUBVP_MAIN:
1952				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport;
1953				subvp_in_use = true;
1954				break;
1955			case SUBVP_PHANTOM:
1956				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_phantom_pipe;
1957				pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;
1958				// Disallow unbounded req for SubVP according to DCHUB programming guide
1959				pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
1960				break;
1961			case SUBVP_NONE:
1962				pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_disable;
1963				pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;
1964				break;
1965			default:
1966				break;
1967			}
1968		}
1969
1970		pipes[pipe_cnt].dout.dsc_input_bpc = 0;
1971		if (pipes[pipe_cnt].dout.dsc_enable) {
1972			switch (timing->display_color_depth) {
1973			case COLOR_DEPTH_888:
1974				pipes[pipe_cnt].dout.dsc_input_bpc = 8;
1975				break;
1976			case COLOR_DEPTH_101010:
1977				pipes[pipe_cnt].dout.dsc_input_bpc = 10;
1978				break;
1979			case COLOR_DEPTH_121212:
1980				pipes[pipe_cnt].dout.dsc_input_bpc = 12;
1981				break;
1982			default:
1983				ASSERT(0);
1984				break;
1985			}
1986		}
1987
1988		DC_FP_START();
1989		dcn32_predict_pipe_split(context, &pipes[pipe_cnt]);
1990		DC_FP_END();
1991
1992		pipe_cnt++;
1993	}
1994
1995	/* For DET allocation, we don't want to use DML policy (not optimal for utilizing all
1996	 * the DET available for each pipe). Use the DET override input to maintain our driver
1997	 * policy.
1998	 */
1999	dcn32_set_det_allocations(dc, context, pipes);
2000
2001	// In general cases we want to keep the dram clock change requirement
2002	// (prefer configs that support MCLK switch). Only override to false
2003	// for SubVP
2004	if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || subvp_in_use)
2005		context->bw_ctx.dml.soc.dram_clock_change_requirement_final = false;
2006	else
2007		context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true;
2008
2009	return pipe_cnt;
2010}
2011
2012static struct dc_cap_funcs cap_funcs = {
2013	.get_dcc_compression_cap = dcn20_get_dcc_compression_cap
2014};
2015
2016void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context,
2017				display_e2e_pipe_params_st *pipes,
2018				int pipe_cnt,
2019				int vlevel)
2020{
2021    DC_FP_START();
2022    dcn32_calculate_wm_and_dlg_fpu(dc, context, pipes, pipe_cnt, vlevel);
2023    DC_FP_END();
2024}
2025
2026static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
2027{
2028	DC_FP_START();
2029	dcn32_update_bw_bounding_box_fpu(dc, bw_params);
2030	DC_FP_END();
2031}
2032
2033static struct resource_funcs dcn32_res_pool_funcs = {
2034	.destroy = dcn32_destroy_resource_pool,
2035	.link_enc_create = dcn32_link_encoder_create,
2036	.link_enc_create_minimal = NULL,
2037	.panel_cntl_create = dcn32_panel_cntl_create,
2038	.validate_bandwidth = dcn32_validate_bandwidth,
2039	.calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg,
2040	.populate_dml_pipes = dcn32_populate_dml_pipes_from_context,
2041	.acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe,
2042	.add_stream_to_ctx = dcn30_add_stream_to_ctx,
2043	.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
2044	.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
2045	.populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,
2046	.set_mcif_arb_params = dcn30_set_mcif_arb_params,
2047	.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
2048	.acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut,
2049	.release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut,
2050	.update_bw_bounding_box = dcn32_update_bw_bounding_box,
2051	.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
2052	.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
2053	.add_phantom_pipes = dcn32_add_phantom_pipes,
2054	.remove_phantom_pipes = dcn32_remove_phantom_pipes,
2055	.retain_phantom_pipes = dcn32_retain_phantom_pipes,
2056	.save_mall_state = dcn32_save_mall_state,
2057	.restore_mall_state = dcn32_restore_mall_state,
2058};
2059
2060static uint32_t read_pipe_fuses(struct dc_context *ctx)
2061{
2062	uint32_t value = REG_READ(CC_DC_PIPE_DIS);
2063	/* DCN32 support max 4 pipes */
2064	value = value & 0xf;
2065	return value;
2066}
2067
2068
2069static bool dcn32_resource_construct(
2070	uint8_t num_virtual_links,
2071	struct dc *dc,
2072	struct dcn32_resource_pool *pool)
2073{
2074	int i, j;
2075	struct dc_context *ctx = dc->ctx;
2076	struct irq_service_init_data init_data;
2077	struct ddc_service_init_data ddc_init_data = {0};
2078	uint32_t pipe_fuses = 0;
2079	uint32_t num_pipes  = 4;
2080
2081#undef REG_STRUCT
2082#define REG_STRUCT bios_regs
2083	bios_regs_init();
2084
2085#undef REG_STRUCT
2086#define REG_STRUCT clk_src_regs
2087	clk_src_regs_init(0, A),
2088	clk_src_regs_init(1, B),
2089	clk_src_regs_init(2, C),
2090	clk_src_regs_init(3, D),
2091	clk_src_regs_init(4, E);
2092
2093#undef REG_STRUCT
2094#define REG_STRUCT abm_regs
2095	abm_regs_init(0),
2096	abm_regs_init(1),
2097	abm_regs_init(2),
2098	abm_regs_init(3);
2099
2100#undef REG_STRUCT
2101#define REG_STRUCT dccg_regs
2102	dccg_regs_init();
2103
2104	DC_FP_START();
2105
2106	ctx->dc_bios->regs = &bios_regs;
2107
2108	pool->base.res_cap = &res_cap_dcn32;
2109	/* max number of pipes for ASIC before checking for pipe fuses */
2110	num_pipes  = pool->base.res_cap->num_timing_generator;
2111	pipe_fuses = read_pipe_fuses(ctx);
2112
2113	for (i = 0; i < pool->base.res_cap->num_timing_generator; i++)
2114		if (pipe_fuses & 1 << i)
2115			num_pipes--;
2116
2117	if (pipe_fuses & 1)
2118		ASSERT(0); //Unexpected - Pipe 0 should always be fully functional!
2119
2120	if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK)
2121		ASSERT(0); //Entire DCN is harvested!
2122
2123	/* within dml lib, initial value is hard coded, if ASIC pipe is fused, the
2124	 * value will be changed, update max_num_dpp and max_num_otg for dml.
2125	 */
2126	dcn3_2_ip.max_num_dpp = num_pipes;
2127	dcn3_2_ip.max_num_otg = num_pipes;
2128
2129	pool->base.funcs = &dcn32_res_pool_funcs;
2130
2131	/*************************************************
2132	 *  Resource + asic cap harcoding                *
2133	 *************************************************/
2134	pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
2135	pool->base.timing_generator_count = num_pipes;
2136	pool->base.pipe_count = num_pipes;
2137	pool->base.mpcc_count = num_pipes;
2138	dc->caps.max_downscale_ratio = 600;
2139	dc->caps.i2c_speed_in_khz = 100;
2140	dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/
2141	/* TODO: Bring max_cursor_size back to 256 after subvp cursor corruption is fixed*/
2142	dc->caps.max_cursor_size = 64;
2143	dc->caps.min_horizontal_blanking_period = 80;
2144	dc->caps.dmdata_alloc_size = 2048;
2145	dc->caps.mall_size_per_mem_channel = 4;
2146	dc->caps.mall_size_total = 0;
2147	dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;
2148
2149	dc->caps.cache_line_size = 64;
2150	dc->caps.cache_num_ways = 16;
2151
2152	/* Calculate the available MALL space */
2153	dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall(
2154		dc, dc->ctx->dc_bios->vram_info.num_chans) *
2155		dc->caps.mall_size_per_mem_channel * 1024 * 1024;
2156	dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;
2157
2158	dc->caps.subvp_fw_processing_delay_us = 15;
2159	dc->caps.subvp_drr_max_vblank_margin_us = 40;
2160	dc->caps.subvp_prefetch_end_to_mall_start_us = 15;
2161	dc->caps.subvp_swath_height_margin_lines = 16;
2162	dc->caps.subvp_pstate_allow_width_us = 20;
2163	dc->caps.subvp_vertical_int_margin_us = 30;
2164	dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin
2165
2166	dc->caps.max_slave_planes = 2;
2167	dc->caps.max_slave_yuv_planes = 2;
2168	dc->caps.max_slave_rgb_planes = 2;
2169	dc->caps.post_blend_color_processing = true;
2170	dc->caps.force_dp_tps4_for_cp2520 = true;
2171	if (dc->config.forceHBR2CP2520)
2172		dc->caps.force_dp_tps4_for_cp2520 = false;
2173	dc->caps.dp_hpo = true;
2174	dc->caps.dp_hdmi21_pcon_support = true;
2175	dc->caps.edp_dsc_support = true;
2176	dc->caps.extended_aux_timeout_support = true;
2177	dc->caps.dmcub_support = true;
2178	dc->caps.seamless_odm = true;
2179	dc->caps.max_v_total = (1 << 15) - 1;
2180
2181	/* Color pipeline capabilities */
2182	dc->caps.color.dpp.dcn_arch = 1;
2183	dc->caps.color.dpp.input_lut_shared = 0;
2184	dc->caps.color.dpp.icsc = 1;
2185	dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr
2186	dc->caps.color.dpp.dgam_rom_caps.srgb = 1;
2187	dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;
2188	dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1;
2189	dc->caps.color.dpp.dgam_rom_caps.pq = 1;
2190	dc->caps.color.dpp.dgam_rom_caps.hlg = 1;
2191	dc->caps.color.dpp.post_csc = 1;
2192	dc->caps.color.dpp.gamma_corr = 1;
2193	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
2194
2195	dc->caps.color.dpp.hw_3d_lut = 1;
2196	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
2197	// no OGAM ROM on DCN2 and later ASICs
2198	dc->caps.color.dpp.ogam_rom_caps.srgb = 0;
2199	dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;
2200	dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;
2201	dc->caps.color.dpp.ogam_rom_caps.pq = 0;
2202	dc->caps.color.dpp.ogam_rom_caps.hlg = 0;
2203	dc->caps.color.dpp.ocsc = 0;
2204
2205	dc->caps.color.mpc.gamut_remap = 1;
2206	dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //4, configurable to be before or after BLND in MPCC
2207	dc->caps.color.mpc.ogam_ram = 1;
2208	dc->caps.color.mpc.ogam_rom_caps.srgb = 0;
2209	dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;
2210	dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;
2211	dc->caps.color.mpc.ogam_rom_caps.pq = 0;
2212	dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
2213	dc->caps.color.mpc.ocsc = 1;
2214
2215	/* Use pipe context based otg sync logic */
2216	dc->config.use_pipe_ctx_sync_logic = true;
2217
2218	dc->config.dc_mode_clk_limit_support = true;
2219	/* read VBIOS LTTPR caps */
2220	{
2221		if (ctx->dc_bios->funcs->get_lttpr_caps) {
2222			enum bp_result bp_query_result;
2223			uint8_t is_vbios_lttpr_enable = 0;
2224
2225			bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
2226			dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
2227		}
2228
2229		/* interop bit is implicit */
2230		{
2231			dc->caps.vbios_lttpr_aware = true;
2232		}
2233	}
2234
2235	if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
2236		dc->debug = debug_defaults_drv;
2237
2238	// Init the vm_helper
2239	if (dc->vm_helper)
2240		vm_helper_init(dc->vm_helper, 16);
2241
2242	/*************************************************
2243	 *  Create resources                             *
2244	 *************************************************/
2245
2246	/* Clock Sources for Pixel Clock*/
2247	pool->base.clock_sources[DCN32_CLK_SRC_PLL0] =
2248			dcn32_clock_source_create(ctx, ctx->dc_bios,
2249				CLOCK_SOURCE_COMBO_PHY_PLL0,
2250				&clk_src_regs[0], false);
2251	pool->base.clock_sources[DCN32_CLK_SRC_PLL1] =
2252			dcn32_clock_source_create(ctx, ctx->dc_bios,
2253				CLOCK_SOURCE_COMBO_PHY_PLL1,
2254				&clk_src_regs[1], false);
2255	pool->base.clock_sources[DCN32_CLK_SRC_PLL2] =
2256			dcn32_clock_source_create(ctx, ctx->dc_bios,
2257				CLOCK_SOURCE_COMBO_PHY_PLL2,
2258				&clk_src_regs[2], false);
2259	pool->base.clock_sources[DCN32_CLK_SRC_PLL3] =
2260			dcn32_clock_source_create(ctx, ctx->dc_bios,
2261				CLOCK_SOURCE_COMBO_PHY_PLL3,
2262				&clk_src_regs[3], false);
2263	pool->base.clock_sources[DCN32_CLK_SRC_PLL4] =
2264			dcn32_clock_source_create(ctx, ctx->dc_bios,
2265				CLOCK_SOURCE_COMBO_PHY_PLL4,
2266				&clk_src_regs[4], false);
2267
2268	pool->base.clk_src_count = DCN32_CLK_SRC_TOTAL;
2269
2270	/* todo: not reuse phy_pll registers */
2271	pool->base.dp_clock_source =
2272			dcn32_clock_source_create(ctx, ctx->dc_bios,
2273				CLOCK_SOURCE_ID_DP_DTO,
2274				&clk_src_regs[0], true);
2275
2276	for (i = 0; i < pool->base.clk_src_count; i++) {
2277		if (pool->base.clock_sources[i] == NULL) {
2278			dm_error("DC: failed to create clock sources!\n");
2279			BREAK_TO_DEBUGGER();
2280			goto create_fail;
2281		}
2282	}
2283
2284	/* DCCG */
2285	pool->base.dccg = dccg32_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);
2286	if (pool->base.dccg == NULL) {
2287		dm_error("DC: failed to create dccg!\n");
2288		BREAK_TO_DEBUGGER();
2289		goto create_fail;
2290	}
2291
2292	/* DML */
2293	dml_init_instance(&dc->dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32);
2294
2295	/* IRQ Service */
2296	init_data.ctx = dc->ctx;
2297	pool->base.irqs = dal_irq_service_dcn32_create(&init_data);
2298	if (!pool->base.irqs)
2299		goto create_fail;
2300
2301	/* HUBBUB */
2302	pool->base.hubbub = dcn32_hubbub_create(ctx);
2303	if (pool->base.hubbub == NULL) {
2304		BREAK_TO_DEBUGGER();
2305		dm_error("DC: failed to create hubbub!\n");
2306		goto create_fail;
2307	}
2308
2309	/* HUBPs, DPPs, OPPs, TGs, ABMs */
2310	for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {
2311
2312		/* if pipe is disabled, skip instance of HW pipe,
2313		 * i.e, skip ASIC register instance
2314		 */
2315		if (pipe_fuses & 1 << i)
2316			continue;
2317
2318		/* HUBPs */
2319		pool->base.hubps[j] = dcn32_hubp_create(ctx, i);
2320		if (pool->base.hubps[j] == NULL) {
2321			BREAK_TO_DEBUGGER();
2322			dm_error(
2323				"DC: failed to create hubps!\n");
2324			goto create_fail;
2325		}
2326
2327		/* DPPs */
2328		pool->base.dpps[j] = dcn32_dpp_create(ctx, i);
2329		if (pool->base.dpps[j] == NULL) {
2330			BREAK_TO_DEBUGGER();
2331			dm_error(
2332				"DC: failed to create dpps!\n");
2333			goto create_fail;
2334		}
2335
2336		/* OPPs */
2337		pool->base.opps[j] = dcn32_opp_create(ctx, i);
2338		if (pool->base.opps[j] == NULL) {
2339			BREAK_TO_DEBUGGER();
2340			dm_error(
2341				"DC: failed to create output pixel processor!\n");
2342			goto create_fail;
2343		}
2344
2345		/* TGs */
2346		pool->base.timing_generators[j] = dcn32_timing_generator_create(
2347				ctx, i);
2348		if (pool->base.timing_generators[j] == NULL) {
2349			BREAK_TO_DEBUGGER();
2350			dm_error("DC: failed to create tg!\n");
2351			goto create_fail;
2352		}
2353
2354		/* ABMs */
2355		pool->base.multiple_abms[j] = dmub_abm_create(ctx,
2356				&abm_regs[i],
2357				&abm_shift,
2358				&abm_mask);
2359		if (pool->base.multiple_abms[j] == NULL) {
2360			dm_error("DC: failed to create abm for pipe %d!\n", i);
2361			BREAK_TO_DEBUGGER();
2362			goto create_fail;
2363		}
2364
2365		/* index for resource pool arrays for next valid pipe */
2366		j++;
2367	}
2368
2369	/* PSR */
2370	pool->base.psr = dmub_psr_create(ctx);
2371	if (pool->base.psr == NULL) {
2372		dm_error("DC: failed to create psr obj!\n");
2373		BREAK_TO_DEBUGGER();
2374		goto create_fail;
2375	}
2376
2377	/* MPCCs */
2378	pool->base.mpc = dcn32_mpc_create(ctx, pool->base.res_cap->num_timing_generator, pool->base.res_cap->num_mpc_3dlut);
2379	if (pool->base.mpc == NULL) {
2380		BREAK_TO_DEBUGGER();
2381		dm_error("DC: failed to create mpc!\n");
2382		goto create_fail;
2383	}
2384
2385	/* DSCs */
2386	for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
2387		pool->base.dscs[i] = dcn32_dsc_create(ctx, i);
2388		if (pool->base.dscs[i] == NULL) {
2389			BREAK_TO_DEBUGGER();
2390			dm_error("DC: failed to create display stream compressor %d!\n", i);
2391			goto create_fail;
2392		}
2393	}
2394
2395	/* DWB */
2396	if (!dcn32_dwbc_create(ctx, &pool->base)) {
2397		BREAK_TO_DEBUGGER();
2398		dm_error("DC: failed to create dwbc!\n");
2399		goto create_fail;
2400	}
2401
2402	/* MMHUBBUB */
2403	if (!dcn32_mmhubbub_create(ctx, &pool->base)) {
2404		BREAK_TO_DEBUGGER();
2405		dm_error("DC: failed to create mcif_wb!\n");
2406		goto create_fail;
2407	}
2408
2409	/* AUX and I2C */
2410	for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
2411		pool->base.engines[i] = dcn32_aux_engine_create(ctx, i);
2412		if (pool->base.engines[i] == NULL) {
2413			BREAK_TO_DEBUGGER();
2414			dm_error(
2415				"DC:failed to create aux engine!!\n");
2416			goto create_fail;
2417		}
2418		pool->base.hw_i2cs[i] = dcn32_i2c_hw_create(ctx, i);
2419		if (pool->base.hw_i2cs[i] == NULL) {
2420			BREAK_TO_DEBUGGER();
2421			dm_error(
2422				"DC:failed to create hw i2c!!\n");
2423			goto create_fail;
2424		}
2425		pool->base.sw_i2cs[i] = NULL;
2426	}
2427
2428	/* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */
2429	if (!resource_construct(num_virtual_links, dc, &pool->base,
2430			&res_create_funcs))
2431		goto create_fail;
2432
2433	/* HW Sequencer init functions and Plane caps */
2434	dcn32_hw_sequencer_init_functions(dc);
2435
2436	dc->caps.max_planes =  pool->base.pipe_count;
2437
2438	for (i = 0; i < dc->caps.max_planes; ++i)
2439		dc->caps.planes[i] = plane_cap;
2440
2441	dc->cap_funcs = cap_funcs;
2442
2443	if (dc->ctx->dc_bios->fw_info.oem_i2c_present) {
2444		ddc_init_data.ctx = dc->ctx;
2445		ddc_init_data.link = NULL;
2446		ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;
2447		ddc_init_data.id.enum_id = 0;
2448		ddc_init_data.id.type = OBJECT_TYPE_GENERIC;
2449		pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data);
2450	} else {
2451		pool->base.oem_device = NULL;
2452	}
2453
2454	if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0))
2455		dc->config.sdpif_request_limit_words_per_umc = 16;
2456
2457	DC_FP_END();
2458
2459	return true;
2460
2461create_fail:
2462
2463	DC_FP_END();
2464
2465	dcn32_resource_destruct(pool);
2466
2467	return false;
2468}
2469
2470struct resource_pool *dcn32_create_resource_pool(
2471		const struct dc_init_data *init_data,
2472		struct dc *dc)
2473{
2474	struct dcn32_resource_pool *pool =
2475		kzalloc(sizeof(struct dcn32_resource_pool), GFP_KERNEL);
2476
2477	if (!pool)
2478		return NULL;
2479
2480	if (dcn32_resource_construct(init_data->num_virtual_links, dc, pool))
2481		return &pool->base;
2482
2483	BREAK_TO_DEBUGGER();
2484	kfree(pool);
2485	return NULL;
2486}
2487
2488/*
2489 * Find the most optimal free pipe from res_ctx, which could be used as a
2490 * secondary dpp pipe for input opp head pipe.
2491 *
2492 * a free pipe - a pipe in input res_ctx not yet used for any streams or
2493 * planes.
2494 * secondary dpp pipe - a pipe gets inserted to a head OPP pipe's MPC blending
2495 * tree. This is typical used for rendering MPO planes or additional offset
2496 * areas in MPCC combine.
2497 *
2498 * Hardware Transition Minimization Algorithm for Finding a Secondary DPP Pipe
2499 * -------------------------------------------------------------------------
2500 *
2501 * PROBLEM:
2502 *
2503 * 1. There is a hardware limitation that a secondary DPP pipe cannot be
2504 * transferred from one MPC blending tree to the other in a single frame.
2505 * Otherwise it could cause glitches on the screen.
2506 *
2507 * For instance, we cannot transition from state 1 to state 2 in one frame. This
2508 * is because PIPE1 is transferred from PIPE0's MPC blending tree over to
2509 * PIPE2's MPC blending tree, which is not supported by hardware.
2510 * To support this transition we need to first remove PIPE1 from PIPE0's MPC
2511 * blending tree in one frame and then insert PIPE1 to PIPE2's MPC blending tree
2512 * in the next frame. This is not optimal as it will delay the flip for two
2513 * frames.
2514 *
2515 *	State 1:
2516 *	PIPE0 -- secondary DPP pipe --> (PIPE1)
2517 *	PIPE2 -- secondary DPP pipe --> NONE
2518 *
2519 *	State 2:
2520 *	PIPE0 -- secondary DPP pipe --> NONE
2521 *	PIPE2 -- secondary DPP pipe --> (PIPE1)
2522 *
2523 * 2. We want to in general minimize the unnecessary changes in pipe topology.
2524 * If a pipe is already added in current blending tree and there are no changes
2525 * to plane topology, we don't want to swap it with another free pipe
2526 * unnecessarily in every update. Powering up and down a pipe would require a
2527 * full update which delays the flip for 1 frame. If we use the original pipe
2528 * we don't have to toggle its power. So we can flip faster.
2529 */
2530static int find_optimal_free_pipe_as_secondary_dpp_pipe(
2531		const struct resource_context *cur_res_ctx,
2532		struct resource_context *new_res_ctx,
2533		const struct resource_pool *pool,
2534		const struct pipe_ctx *new_opp_head)
2535{
2536	const struct pipe_ctx *cur_opp_head;
2537	int free_pipe_idx;
2538
2539	cur_opp_head = &cur_res_ctx->pipe_ctx[new_opp_head->pipe_idx];
2540	free_pipe_idx = resource_find_free_pipe_used_in_cur_mpc_blending_tree(
2541			cur_res_ctx, new_res_ctx, cur_opp_head);
2542
2543	/* Up until here if we have not found a free secondary pipe, we will
2544	 * need to wait for at least one frame to complete the transition
2545	 * sequence.
2546	 */
2547	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)
2548		free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx(
2549				cur_res_ctx, new_res_ctx, pool);
2550
2551	/* Up until here if we have not found a free secondary pipe, we will
2552	 * need to wait for at least two frames to complete the transition
2553	 * sequence. It really doesn't matter which pipe we decide take from
2554	 * current enabled pipes. It won't save our frame time when we swap only
2555	 * one pipe or more pipes.
2556	 */
2557	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)
2558		free_pipe_idx = resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine(
2559				cur_res_ctx, new_res_ctx, pool);
2560
2561	if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND)
2562		free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool);
2563
2564	return free_pipe_idx;
2565}
2566
2567static struct pipe_ctx *find_idle_secondary_pipe_check_mpo(
2568		struct resource_context *res_ctx,
2569		const struct resource_pool *pool,
2570		const struct pipe_ctx *primary_pipe)
2571{
2572	int i;
2573	struct pipe_ctx *secondary_pipe = NULL;
2574	struct pipe_ctx *next_odm_mpo_pipe = NULL;
2575	int primary_index, preferred_pipe_idx;
2576	struct pipe_ctx *old_primary_pipe = NULL;
2577
2578	/*
2579	 * Modified from find_idle_secondary_pipe
2580	 * With windowed MPO and ODM, we want to avoid the case where we want a
2581	 *  free pipe for the left side but the free pipe is being used on the
2582	 *  right side.
2583	 * Add check on current_state if the primary_pipe is the left side,
2584	 *  to check the right side ( primary_pipe->next_odm_pipe ) to see if
2585	 *  it is using a pipe for MPO ( primary_pipe->next_odm_pipe->bottom_pipe )
2586	 * - If so, then don't use this pipe
2587	 * EXCEPTION - 3 plane ( 2 MPO plane ) case
2588	 * - in this case, the primary pipe has already gotten a free pipe for the
2589	 *  MPO window in the left
2590	 * - when it tries to get a free pipe for the MPO window on the right,
2591	 *  it will see that it is already assigned to the right side
2592	 *  ( primary_pipe->next_odm_pipe ).  But in this case, we want this
2593	 *  free pipe, since it will be for the right side.  So add an
2594	 *  additional condition, that skipping the free pipe on the right only
2595	 *  applies if the primary pipe has no bottom pipe currently assigned
2596	 */
2597	if (primary_pipe) {
2598		primary_index = primary_pipe->pipe_idx;
2599		old_primary_pipe = &primary_pipe->stream->ctx->dc->current_state->res_ctx.pipe_ctx[primary_index];
2600		if ((old_primary_pipe->next_odm_pipe) && (old_primary_pipe->next_odm_pipe->bottom_pipe)
2601			&& (!primary_pipe->bottom_pipe))
2602			next_odm_mpo_pipe = old_primary_pipe->next_odm_pipe->bottom_pipe;
2603
2604		preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
2605		if ((res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) &&
2606			!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == preferred_pipe_idx)) {
2607			secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
2608			secondary_pipe->pipe_idx = preferred_pipe_idx;
2609		}
2610	}
2611
2612	/*
2613	 * search backwards for the second pipe to keep pipe
2614	 * assignment more consistent
2615	 */
2616	if (!secondary_pipe)
2617		for (i = pool->pipe_count - 1; i >= 0; i--) {
2618			if ((res_ctx->pipe_ctx[i].stream == NULL) &&
2619				!(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == i)) {
2620				secondary_pipe = &res_ctx->pipe_ctx[i];
2621				secondary_pipe->pipe_idx = i;
2622				break;
2623			}
2624		}
2625
2626	return secondary_pipe;
2627}
2628
2629static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
2630		struct dc_state *state,
2631		const struct resource_pool *pool,
2632		struct dc_stream_state *stream,
2633		const struct pipe_ctx *head_pipe)
2634{
2635	struct resource_context *res_ctx = &state->res_ctx;
2636	struct pipe_ctx *idle_pipe, *pipe;
2637	struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx;
2638	int head_index;
2639
2640	if (!head_pipe)
2641		ASSERT(0);
2642
2643	/*
2644	 * Modified from dcn20_acquire_idle_pipe_for_layer
2645	 * Check if head_pipe in old_context already has bottom_pipe allocated.
2646	 * - If so, check if that pipe is available in the current context.
2647	 * --  If so, reuse pipe from old_context
2648	 */
2649	head_index = head_pipe->pipe_idx;
2650	pipe = &old_ctx->pipe_ctx[head_index];
2651	if (pipe->bottom_pipe && res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx].stream == NULL) {
2652		idle_pipe = &res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx];
2653		idle_pipe->pipe_idx = pipe->bottom_pipe->pipe_idx;
2654	} else {
2655		idle_pipe = find_idle_secondary_pipe_check_mpo(res_ctx, pool, head_pipe);
2656		if (!idle_pipe)
2657			return NULL;
2658	}
2659
2660	idle_pipe->stream = head_pipe->stream;
2661	idle_pipe->stream_res.tg = head_pipe->stream_res.tg;
2662	idle_pipe->stream_res.opp = head_pipe->stream_res.opp;
2663
2664	idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx];
2665	idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx];
2666	idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx];
2667	idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst;
2668
2669	return idle_pipe;
2670}
2671
2672struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe(
2673		const struct dc_state *cur_ctx,
2674		struct dc_state *new_ctx,
2675		const struct resource_pool *pool,
2676		const struct pipe_ctx *opp_head_pipe)
2677{
2678
2679	int free_pipe_idx;
2680	struct pipe_ctx *free_pipe;
2681
2682	if (!opp_head_pipe->stream->ctx->dc->config.enable_windowed_mpo_odm)
2683		return dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
2684				new_ctx, pool, opp_head_pipe->stream, opp_head_pipe);
2685
2686	free_pipe_idx = find_optimal_free_pipe_as_secondary_dpp_pipe(
2687					&cur_ctx->res_ctx, &new_ctx->res_ctx,
2688					pool, opp_head_pipe);
2689	if (free_pipe_idx >= 0) {
2690		free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx];
2691		free_pipe->pipe_idx = free_pipe_idx;
2692		free_pipe->stream = opp_head_pipe->stream;
2693		free_pipe->stream_res.tg = opp_head_pipe->stream_res.tg;
2694		free_pipe->stream_res.opp = opp_head_pipe->stream_res.opp;
2695
2696		free_pipe->plane_res.hubp = pool->hubps[free_pipe->pipe_idx];
2697		free_pipe->plane_res.ipp = pool->ipps[free_pipe->pipe_idx];
2698		free_pipe->plane_res.dpp = pool->dpps[free_pipe->pipe_idx];
2699		free_pipe->plane_res.mpcc_inst =
2700				pool->dpps[free_pipe->pipe_idx]->inst;
2701	} else {
2702		ASSERT(opp_head_pipe);
2703		free_pipe = NULL;
2704	}
2705
2706	return free_pipe;
2707}
2708
2709unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans)
2710{
2711	/*
2712	 * DCN32 and DCN321 SKUs may have different sizes for MALL
2713	 *  but we may not be able to access all the MALL space.
2714	 *  If the num_chans is power of 2, then we can access all
2715	 *  of the available MALL space.  Otherwise, we can only
2716	 *  access:
2717	 *
2718	 *  max_cab_size_in_bytes = total_cache_size_in_bytes *
2719	 *    ((2^floor(log2(num_chans)))/num_chans)
2720	 *
2721	 * Calculating the MALL sizes for all available SKUs, we
2722	 *  have come up with the follow simplified check.
2723	 * - we have max_chans which provides the max MALL size.
2724	 *  Each chans supports 4MB of MALL so:
2725	 *
2726	 *  total_cache_size_in_bytes = max_chans * 4 MB
2727	 *
2728	 * - we have avail_chans which shows the number of channels
2729	 *  we can use if we can't access the entire MALL space.
2730	 *  It is generally half of max_chans
2731	 * - so we use the following checks:
2732	 *
2733	 *   if (num_chans == max_chans), return max_chans
2734	 *   if (num_chans < max_chans), return avail_chans
2735	 *
2736	 * - exception is GC_11_0_0 where we can't access max_chans,
2737	 *  so we define max_avail_chans as the maximum available
2738	 *  MALL space
2739	 *
2740	 */
2741	int gc_11_0_0_max_chans = 48;
2742	int gc_11_0_0_max_avail_chans = 32;
2743	int gc_11_0_0_avail_chans = 16;
2744	int gc_11_0_3_max_chans = 16;
2745	int gc_11_0_3_avail_chans = 8;
2746	int gc_11_0_2_max_chans = 8;
2747	int gc_11_0_2_avail_chans = 4;
2748
2749	if (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev)) {
2750		return (num_chans == gc_11_0_0_max_chans) ?
2751			gc_11_0_0_max_avail_chans : gc_11_0_0_avail_chans;
2752	} else if (ASICREV_IS_GC_11_0_2(dc->ctx->asic_id.hw_internal_rev)) {
2753		return (num_chans == gc_11_0_2_max_chans) ?
2754			gc_11_0_2_max_chans : gc_11_0_2_avail_chans;
2755	} else { // if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev)) {
2756		return (num_chans == gc_11_0_3_max_chans) ?
2757			gc_11_0_3_max_chans : gc_11_0_3_avail_chans;
2758	}
2759}
2760