xref: /linux/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c (revision 69e3be6893a7e668660b05a966bead82bbddb01d)
1d99f1387SBhawanpreet Lakha /*
2d99f1387SBhawanpreet Lakha  * Copyright 2020 Advanced Micro Devices, Inc.
3d99f1387SBhawanpreet Lakha  *
4d99f1387SBhawanpreet Lakha  * Permission is hereby granted, free of charge, to any person obtaining a
5d99f1387SBhawanpreet Lakha  * copy of this software and associated documentation files (the "Software"),
6d99f1387SBhawanpreet Lakha  * to deal in the Software without restriction, including without limitation
7d99f1387SBhawanpreet Lakha  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d99f1387SBhawanpreet Lakha  * and/or sell copies of the Software, and to permit persons to whom the
9d99f1387SBhawanpreet Lakha  * Software is furnished to do so, subject to the following conditions:
10d99f1387SBhawanpreet Lakha  *
11d99f1387SBhawanpreet Lakha  * The above copyright notice and this permission notice shall be included in
12d99f1387SBhawanpreet Lakha  * all copies or substantial portions of the Software.
13d99f1387SBhawanpreet Lakha  *
14d99f1387SBhawanpreet Lakha  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d99f1387SBhawanpreet Lakha  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d99f1387SBhawanpreet Lakha  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17d99f1387SBhawanpreet Lakha  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d99f1387SBhawanpreet Lakha  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d99f1387SBhawanpreet Lakha  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d99f1387SBhawanpreet Lakha  * OTHER DEALINGS IN THE SOFTWARE.
21d99f1387SBhawanpreet Lakha  *
22d99f1387SBhawanpreet Lakha  * Authors: AMD
23d99f1387SBhawanpreet Lakha  *
24d99f1387SBhawanpreet Lakha  */
25d99f1387SBhawanpreet Lakha 
26d99f1387SBhawanpreet Lakha 
27d99f1387SBhawanpreet Lakha #include "dm_services.h"
28d99f1387SBhawanpreet Lakha #include "dm_helpers.h"
29d99f1387SBhawanpreet Lakha #include "core_types.h"
30d99f1387SBhawanpreet Lakha #include "resource.h"
31d99f1387SBhawanpreet Lakha #include "dcn30_hwseq.h"
32d99f1387SBhawanpreet Lakha #include "dccg.h"
33d99f1387SBhawanpreet Lakha #include "dce/dce_hwseq.h"
34e53524cdSMounika Adhuri #include "dcn30/dcn30_mpc.h"
35e53524cdSMounika Adhuri #include "dcn30/dcn30_dpp.h"
36d99f1387SBhawanpreet Lakha #include "dcn10/dcn10_cm_common.h"
37e53524cdSMounika Adhuri #include "dcn30/dcn30_cm_common.h"
38d99f1387SBhawanpreet Lakha #include "reg_helper.h"
39d99f1387SBhawanpreet Lakha #include "abm.h"
40d99f1387SBhawanpreet Lakha #include "clk_mgr.h"
41d99f1387SBhawanpreet Lakha #include "hubp.h"
42d99f1387SBhawanpreet Lakha #include "dchubbub.h"
43d99f1387SBhawanpreet Lakha #include "timing_generator.h"
44d99f1387SBhawanpreet Lakha #include "opp.h"
45d99f1387SBhawanpreet Lakha #include "ipp.h"
46d99f1387SBhawanpreet Lakha #include "mpc.h"
47d99f1387SBhawanpreet Lakha #include "mcif_wb.h"
48d99f1387SBhawanpreet Lakha #include "dc_dmub_srv.h"
490f782777SMartin Leung #include "link_hwss.h"
500f782777SMartin Leung #include "dpcd_defs.h"
51e53524cdSMounika Adhuri #include "dcn20/dcn20_hwseq.h"
52e53524cdSMounika Adhuri #include "dcn30/dcn30_resource.h"
536ca7415fSWenjing Liu #include "link_service.h"
5409a4ec5dSDillon Varone #include "dc_state_priv.h"
55d99f1387SBhawanpreet Lakha 
56d99f1387SBhawanpreet Lakha 
57d99f1387SBhawanpreet Lakha 
58d99f1387SBhawanpreet Lakha #define DC_LOGGER_INIT(logger)
59d99f1387SBhawanpreet Lakha 
60d99f1387SBhawanpreet Lakha #define CTX \
61d99f1387SBhawanpreet Lakha 	hws->ctx
62d99f1387SBhawanpreet Lakha #define REG(reg)\
63d99f1387SBhawanpreet Lakha 	hws->regs->reg
64d99f1387SBhawanpreet Lakha #define DC_LOGGER \
65d99f1387SBhawanpreet Lakha 		dc->ctx->logger
66d99f1387SBhawanpreet Lakha 
67d99f1387SBhawanpreet Lakha 
68d99f1387SBhawanpreet Lakha #undef FN
69d99f1387SBhawanpreet Lakha #define FN(reg_name, field_name) \
70d99f1387SBhawanpreet Lakha 	hws->shifts->field_name, hws->masks->field_name
71d99f1387SBhawanpreet Lakha 
dcn30_log_color_state(struct dc * dc,struct dc_log_buffer_ctx * log_ctx)72060963bfSMelissa Wen void dcn30_log_color_state(struct dc *dc,
73060963bfSMelissa Wen 			   struct dc_log_buffer_ctx *log_ctx)
74060963bfSMelissa Wen {
75060963bfSMelissa Wen 	struct dc_context *dc_ctx = dc->ctx;
76060963bfSMelissa Wen 	struct resource_pool *pool = dc->res_pool;
77060963bfSMelissa Wen 	bool is_gamut_remap_available = false;
78060963bfSMelissa Wen 	int i;
79060963bfSMelissa Wen 
80060963bfSMelissa Wen 	DTN_INFO("DPP:  DGAM ROM  DGAM ROM type  DGAM LUT  SHAPER mode"
81060963bfSMelissa Wen 		 "  3DLUT mode  3DLUT bit depth  3DLUT size  RGAM mode"
82060963bfSMelissa Wen 		 "  GAMUT adjust  "
83060963bfSMelissa Wen 		 "C11        C12        C13        C14        "
84060963bfSMelissa Wen 		 "C21        C22        C23        C24        "
85060963bfSMelissa Wen 		 "C31        C32        C33        C34        \n");
86060963bfSMelissa Wen 
87060963bfSMelissa Wen 	for (i = 0; i < pool->pipe_count; i++) {
88060963bfSMelissa Wen 		struct dpp *dpp = pool->dpps[i];
89060963bfSMelissa Wen 		struct dcn_dpp_state s = {0};
90060963bfSMelissa Wen 
91060963bfSMelissa Wen 		dpp->funcs->dpp_read_state(dpp, &s);
92060963bfSMelissa Wen 
93060963bfSMelissa Wen 		if (dpp->funcs->dpp_get_gamut_remap) {
94060963bfSMelissa Wen 			dpp->funcs->dpp_get_gamut_remap(dpp, &s.gamut_remap);
95060963bfSMelissa Wen 			is_gamut_remap_available = true;
96060963bfSMelissa Wen 		}
97060963bfSMelissa Wen 
98060963bfSMelissa Wen 		if (!s.is_enabled)
99060963bfSMelissa Wen 			continue;
100060963bfSMelissa Wen 
101060963bfSMelissa Wen 		DTN_INFO("[%2d]:  %7x  %13s  %8s  %11s  %10s  %15s  %10s  %9s",
102060963bfSMelissa Wen 			dpp->inst,
103060963bfSMelissa Wen 			s.pre_dgam_mode,
104060963bfSMelissa Wen 			(s.pre_dgam_select == 0) ? "sRGB" :
105060963bfSMelissa Wen 			 ((s.pre_dgam_select == 1) ? "Gamma 2.2" :
106060963bfSMelissa Wen 			 ((s.pre_dgam_select == 2) ? "Gamma 2.4" :
107060963bfSMelissa Wen 			 ((s.pre_dgam_select == 3) ? "Gamma 2.6" :
108060963bfSMelissa Wen 			 ((s.pre_dgam_select == 4) ? "BT.709" :
109060963bfSMelissa Wen 			 ((s.pre_dgam_select == 5) ? "PQ" :
110060963bfSMelissa Wen 			 ((s.pre_dgam_select == 6) ? "HLG" :
111060963bfSMelissa Wen 						     "Unknown")))))),
112060963bfSMelissa Wen 			(s.gamcor_mode == 0) ? "Bypass" :
113060963bfSMelissa Wen 			 ((s.gamcor_mode == 1) ? "RAM A" :
114060963bfSMelissa Wen 						 "RAM B"),
115060963bfSMelissa Wen 			(s.shaper_lut_mode == 1) ? "RAM A" :
116060963bfSMelissa Wen 			 ((s.shaper_lut_mode == 2) ? "RAM B" :
117060963bfSMelissa Wen 						     "Bypass"),
118060963bfSMelissa Wen 			(s.lut3d_mode == 1) ? "RAM A" :
119060963bfSMelissa Wen 			 ((s.lut3d_mode == 2) ? "RAM B" :
120060963bfSMelissa Wen 						"Bypass"),
121060963bfSMelissa Wen 			(s.lut3d_bit_depth <= 0) ? "12-bit" : "10-bit",
122060963bfSMelissa Wen 			(s.lut3d_size == 0) ? "17x17x17" : "9x9x9",
123060963bfSMelissa Wen 			(s.rgam_lut_mode == 0) ? "Bypass" :
124060963bfSMelissa Wen 			 ((s.rgam_lut_mode == 1) ? "RAM A" :
125060963bfSMelissa Wen 						   "RAM B"));
126060963bfSMelissa Wen 
127060963bfSMelissa Wen 		if (is_gamut_remap_available) {
128060963bfSMelissa Wen 			DTN_INFO("  %12s  "
129060963bfSMelissa Wen 				 "%010lld %010lld %010lld %010lld "
130060963bfSMelissa Wen 				 "%010lld %010lld %010lld %010lld "
131060963bfSMelissa Wen 				 "%010lld %010lld %010lld %010lld",
132060963bfSMelissa Wen 
133060963bfSMelissa Wen 			(s.gamut_remap.gamut_adjust_type == 0) ? "Bypass" :
134060963bfSMelissa Wen 				((s.gamut_remap.gamut_adjust_type == 1) ? "HW" :
135060963bfSMelissa Wen 									  "SW"),
136060963bfSMelissa Wen 			s.gamut_remap.temperature_matrix[0].value,
137060963bfSMelissa Wen 			s.gamut_remap.temperature_matrix[1].value,
138060963bfSMelissa Wen 			s.gamut_remap.temperature_matrix[2].value,
139060963bfSMelissa Wen 			s.gamut_remap.temperature_matrix[3].value,
140060963bfSMelissa Wen 			s.gamut_remap.temperature_matrix[4].value,
141060963bfSMelissa Wen 			s.gamut_remap.temperature_matrix[5].value,
142060963bfSMelissa Wen 			s.gamut_remap.temperature_matrix[6].value,
143f5be15bbSMelissa Wen 			s.gamut_remap.temperature_matrix[7].value,
144f5be15bbSMelissa Wen 			s.gamut_remap.temperature_matrix[8].value,
145f5be15bbSMelissa Wen 			s.gamut_remap.temperature_matrix[9].value,
146f5be15bbSMelissa Wen 			s.gamut_remap.temperature_matrix[10].value,
147f5be15bbSMelissa Wen 			s.gamut_remap.temperature_matrix[11].value);
148f5be15bbSMelissa Wen 		}
149f5be15bbSMelissa Wen 
150f5be15bbSMelissa Wen 		DTN_INFO("\n");
151f5be15bbSMelissa Wen 	}
152f5be15bbSMelissa Wen 	DTN_INFO("\n");
153f5be15bbSMelissa Wen 	DTN_INFO("DPP Color Caps: input_lut_shared:%d  icsc:%d"
154f5be15bbSMelissa Wen 		 "  dgam_ram:%d  dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d"
155f5be15bbSMelissa Wen 		 "  post_csc:%d  gamcor:%d  dgam_rom_for_yuv:%d  3d_lut:%d"
156f5be15bbSMelissa Wen 		 "  blnd_lut:%d  oscs:%d\n\n",
157f5be15bbSMelissa Wen 		 dc->caps.color.dpp.input_lut_shared,
158f5be15bbSMelissa Wen 		 dc->caps.color.dpp.icsc,
159f5be15bbSMelissa Wen 		 dc->caps.color.dpp.dgam_ram,
160f5be15bbSMelissa Wen 		 dc->caps.color.dpp.dgam_rom_caps.srgb,
161060963bfSMelissa Wen 		 dc->caps.color.dpp.dgam_rom_caps.bt2020,
162060963bfSMelissa Wen 		 dc->caps.color.dpp.dgam_rom_caps.gamma2_2,
163060963bfSMelissa Wen 		 dc->caps.color.dpp.dgam_rom_caps.pq,
164060963bfSMelissa Wen 		 dc->caps.color.dpp.dgam_rom_caps.hlg,
165060963bfSMelissa Wen 		 dc->caps.color.dpp.post_csc,
166060963bfSMelissa Wen 		 dc->caps.color.dpp.gamma_corr,
167060963bfSMelissa Wen 		 dc->caps.color.dpp.dgam_rom_for_yuv,
168060963bfSMelissa Wen 		 dc->caps.color.dpp.hw_3d_lut,
169060963bfSMelissa Wen 		 dc->caps.color.dpp.ogam_ram,
170060963bfSMelissa Wen 		 dc->caps.color.dpp.ocsc);
171060963bfSMelissa Wen 
172060963bfSMelissa Wen 	DTN_INFO("MPCC:  OPP  DPP  MPCCBOT  MODE  ALPHA_MODE  PREMULT  OVERLAP_ONLY  IDLE"
173060963bfSMelissa Wen 		 "  SHAPER mode  3DLUT mode  3DLUT bit-depth  3DLUT size  OGAM mode  OGAM LUT"
174060963bfSMelissa Wen 		 "  GAMUT adjust  "
175060963bfSMelissa Wen 		 "C11        C12        C13        C14        "
176060963bfSMelissa Wen 		 "C21        C22        C23        C24        "
177060963bfSMelissa Wen 		 "C31        C32        C33        C34        \n");
178060963bfSMelissa Wen 
179060963bfSMelissa Wen 	for (i = 0; i < pool->mpcc_count; i++) {
180060963bfSMelissa Wen 		struct mpcc_state s = {0};
181060963bfSMelissa Wen 
182060963bfSMelissa Wen 		pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
183060963bfSMelissa Wen 		mpc3_get_gamut_remap(pool->mpc, i,  &s.gamut_remap);
184060963bfSMelissa Wen 
185060963bfSMelissa Wen 		if (s.opp_id != 0xf)
186060963bfSMelissa Wen 			DTN_INFO("[%2d]:  %2xh  %2xh  %6xh  %4d  %10d  %7d  %12d  %4d  %11s %11s %16s %11s %10s %9s"
187060963bfSMelissa Wen 				 "  %-12s  "
188060963bfSMelissa Wen 				 "%010lld %010lld %010lld %010lld "
189060963bfSMelissa Wen 				 "%010lld %010lld %010lld %010lld "
190060963bfSMelissa Wen 				 "%010lld %010lld %010lld %010lld\n",
191060963bfSMelissa Wen 				i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
192060963bfSMelissa Wen 				s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
193060963bfSMelissa Wen 				s.idle,
194060963bfSMelissa Wen 				(s.shaper_lut_mode == 1) ? "RAM A" :
195060963bfSMelissa Wen 				 ((s.shaper_lut_mode == 2) ? "RAM B" :
196060963bfSMelissa Wen 							     "Bypass"),
197060963bfSMelissa Wen 				(s.lut3d_mode == 1) ? "RAM A" :
198060963bfSMelissa Wen 				 ((s.lut3d_mode == 2) ? "RAM B" :
199060963bfSMelissa Wen 							"Bypass"),
200060963bfSMelissa Wen 				(s.lut3d_bit_depth <= 0) ? "12-bit" : "10-bit",
201060963bfSMelissa Wen 				(s.lut3d_size == 0) ? "17x17x17" : "9x9x9",
202060963bfSMelissa Wen 				(s.rgam_mode == 0) ? "Bypass" :
203060963bfSMelissa Wen 				 ((s.rgam_mode == 2) ? "RAM" :
204060963bfSMelissa Wen 						       "Unknown"),
205060963bfSMelissa Wen 				(s.rgam_mode == 1) ? "B" : "A",
206060963bfSMelissa Wen 				(s.gamut_remap.gamut_adjust_type == 0) ? "Bypass" :
207060963bfSMelissa Wen 					((s.gamut_remap.gamut_adjust_type == 1) ? "HW" :
208060963bfSMelissa Wen 										  "SW"),
209060963bfSMelissa Wen 				s.gamut_remap.temperature_matrix[0].value,
210060963bfSMelissa Wen 				s.gamut_remap.temperature_matrix[1].value,
211060963bfSMelissa Wen 				s.gamut_remap.temperature_matrix[2].value,
212060963bfSMelissa Wen 				s.gamut_remap.temperature_matrix[3].value,
213060963bfSMelissa Wen 				s.gamut_remap.temperature_matrix[4].value,
214f5be15bbSMelissa Wen 				s.gamut_remap.temperature_matrix[5].value,
215f5be15bbSMelissa Wen 				s.gamut_remap.temperature_matrix[6].value,
216f5be15bbSMelissa Wen 				s.gamut_remap.temperature_matrix[7].value,
217f5be15bbSMelissa Wen 				s.gamut_remap.temperature_matrix[8].value,
218f5be15bbSMelissa Wen 				s.gamut_remap.temperature_matrix[9].value,
219060963bfSMelissa Wen 				s.gamut_remap.temperature_matrix[10].value,
220060963bfSMelissa Wen 				s.gamut_remap.temperature_matrix[11].value);
221d99f1387SBhawanpreet Lakha 
222d99f1387SBhawanpreet Lakha 	}
223d99f1387SBhawanpreet Lakha 	DTN_INFO("\n");
224d99f1387SBhawanpreet Lakha 	DTN_INFO("MPC Color Caps: gamut_remap:%d, 3dlut:%d, ogam_ram:%d, ocsc:%d\n\n",
225d99f1387SBhawanpreet Lakha 		 dc->caps.color.mpc.gamut_remap,
226d99f1387SBhawanpreet Lakha 		 dc->caps.color.mpc.num_3dluts,
227d99f1387SBhawanpreet Lakha 		 dc->caps.color.mpc.ogam_ram,
228d99f1387SBhawanpreet Lakha 		 dc->caps.color.mpc.ocsc);
229d99f1387SBhawanpreet Lakha }
230d99f1387SBhawanpreet Lakha 
dcn30_set_blend_lut(struct pipe_ctx * pipe_ctx,const struct dc_plane_state * plane_state)231d99f1387SBhawanpreet Lakha bool dcn30_set_blend_lut(
232d99f1387SBhawanpreet Lakha 	struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
233d99f1387SBhawanpreet Lakha {
234d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
235d99f1387SBhawanpreet Lakha 	bool result = true;
236d99f1387SBhawanpreet Lakha 	const struct pwl_params *blend_lut = NULL;
237d99f1387SBhawanpreet Lakha 
238d99f1387SBhawanpreet Lakha 	if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
239d99f1387SBhawanpreet Lakha 		blend_lut = &plane_state->blend_tf.pwl;
240d99f1387SBhawanpreet Lakha 	else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
241d99f1387SBhawanpreet Lakha 		result = cm3_helper_translate_curve_to_hw_format(
24294369589SMelissa Wen 				&plane_state->blend_tf, &dpp_base->regamma_params, false);
24394369589SMelissa Wen 		if (!result)
244d99f1387SBhawanpreet Lakha 			return result;
245d99f1387SBhawanpreet Lakha 
246d99f1387SBhawanpreet Lakha 		blend_lut = &dpp_base->regamma_params;
247d99f1387SBhawanpreet Lakha 	}
248d99f1387SBhawanpreet Lakha 	result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
249d99f1387SBhawanpreet Lakha 
250d99f1387SBhawanpreet Lakha 	return result;
251d99f1387SBhawanpreet Lakha }
252d99f1387SBhawanpreet Lakha 
dcn30_set_mpc_shaper_3dlut(struct pipe_ctx * pipe_ctx,const struct dc_stream_state * stream)253d99f1387SBhawanpreet Lakha static bool dcn30_set_mpc_shaper_3dlut(struct pipe_ctx *pipe_ctx,
254d99f1387SBhawanpreet Lakha 				       const struct dc_stream_state *stream)
25594369589SMelissa Wen {
256d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
25794369589SMelissa Wen 	int mpcc_id = pipe_ctx->plane_res.hubp->inst;
25827fc10d1SHarry Wentland 	struct dc *dc = pipe_ctx->stream->ctx->dc;
259d99f1387SBhawanpreet Lakha 	struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
260d99f1387SBhawanpreet Lakha 	bool result = false;
261d99f1387SBhawanpreet Lakha 	int acquired_rmu = 0;
262d99f1387SBhawanpreet Lakha 	int mpcc_id_projected = 0;
263d99f1387SBhawanpreet Lakha 
264d99f1387SBhawanpreet Lakha 	const struct pwl_params *shaper_lut = NULL;
265d99f1387SBhawanpreet Lakha 	//get the shaper lut params
266d99f1387SBhawanpreet Lakha 	if (stream->func_shaper) {
267d99f1387SBhawanpreet Lakha 		if (stream->func_shaper->type == TF_TYPE_HWPWL) {
268d99f1387SBhawanpreet Lakha 			shaper_lut = &stream->func_shaper->pwl;
269d99f1387SBhawanpreet Lakha 		} else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
270d99f1387SBhawanpreet Lakha 			cm_helper_translate_curve_to_hw_format(stream->ctx, stream->func_shaper,
271d99f1387SBhawanpreet Lakha 							       &dpp_base->shaper_params, true);
272d99f1387SBhawanpreet Lakha 			shaper_lut = &dpp_base->shaper_params;
273d99f1387SBhawanpreet Lakha 		}
274d99f1387SBhawanpreet Lakha 	}
27594369589SMelissa Wen 
27694369589SMelissa Wen 	if (stream->lut3d_func &&
27794369589SMelissa Wen 	    stream->lut3d_func->state.bits.initialized == 1 &&
278d99f1387SBhawanpreet Lakha 	    stream->lut3d_func->state.bits.rmu_idx_valid == 1) {
279d99f1387SBhawanpreet Lakha 		if (stream->lut3d_func->state.bits.rmu_mux_num == 0)
280d99f1387SBhawanpreet Lakha 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu0_mux;
281d99f1387SBhawanpreet Lakha 		else if (stream->lut3d_func->state.bits.rmu_mux_num == 1)
28294369589SMelissa Wen 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu1_mux;
28394369589SMelissa Wen 		else if (stream->lut3d_func->state.bits.rmu_mux_num == 2)
284d99f1387SBhawanpreet Lakha 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu2_mux;
285d99f1387SBhawanpreet Lakha 		if (mpcc_id_projected != mpcc_id)
286d99f1387SBhawanpreet Lakha 			BREAK_TO_DEBUGGER();
28794369589SMelissa Wen 		/* find the reason why logical layer assigned a different
28894369589SMelissa Wen 		 * mpcc_id into acquire_post_bldn_3dlut
289d99f1387SBhawanpreet Lakha 		 */
29094369589SMelissa Wen 		acquired_rmu = mpc->funcs->acquire_rmu(mpc, mpcc_id,
291d99f1387SBhawanpreet Lakha 						       stream->lut3d_func->state.bits.rmu_mux_num);
292d99f1387SBhawanpreet Lakha 		if (acquired_rmu != stream->lut3d_func->state.bits.rmu_mux_num)
293d99f1387SBhawanpreet Lakha 			BREAK_TO_DEBUGGER();
294d99f1387SBhawanpreet Lakha 
295d99f1387SBhawanpreet Lakha 		result = mpc->funcs->program_3dlut(mpc, &stream->lut3d_func->lut_3d,
296d99f1387SBhawanpreet Lakha 						   stream->lut3d_func->state.bits.rmu_mux_num);
297d99f1387SBhawanpreet Lakha 		if (!result)
298d99f1387SBhawanpreet Lakha 			DC_LOG_ERROR("%s: program_3dlut failed\n", __func__);
299d99f1387SBhawanpreet Lakha 
300d99f1387SBhawanpreet Lakha 		result = mpc->funcs->program_shaper(mpc, shaper_lut,
301d99f1387SBhawanpreet Lakha 						    stream->lut3d_func->state.bits.rmu_mux_num);
302d99f1387SBhawanpreet Lakha 		if (!result)
303d99f1387SBhawanpreet Lakha 			DC_LOG_ERROR("%s: program_shaper failed\n", __func__);
304d99f1387SBhawanpreet Lakha 
305d99f1387SBhawanpreet Lakha 	} else {
306d99f1387SBhawanpreet Lakha 		// loop through the available mux and release the requested mpcc_id
307d99f1387SBhawanpreet Lakha 		mpc->funcs->release_rmu(mpc, mpcc_id);
308d99f1387SBhawanpreet Lakha 	}
309d99f1387SBhawanpreet Lakha 
310d99f1387SBhawanpreet Lakha 	return result;
311d99f1387SBhawanpreet Lakha }
312d99f1387SBhawanpreet Lakha 
dcn30_set_input_transfer_func(struct dc * dc,struct pipe_ctx * pipe_ctx,const struct dc_plane_state * plane_state)313d99f1387SBhawanpreet Lakha bool dcn30_set_input_transfer_func(struct dc *dc,
314d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx,
315d99f1387SBhawanpreet Lakha 				const struct dc_plane_state *plane_state)
316d99f1387SBhawanpreet Lakha {
317d99f1387SBhawanpreet Lakha 	struct dce_hwseq *hws = dc->hwseq;
318d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
319d99f1387SBhawanpreet Lakha 	enum dc_transfer_func_predefined tf;
320d99f1387SBhawanpreet Lakha 	bool result = true;
321d99f1387SBhawanpreet Lakha 	const struct pwl_params *params = NULL;
322d99f1387SBhawanpreet Lakha 
323d99f1387SBhawanpreet Lakha 	if (dpp_base == NULL || plane_state == NULL)
324d99f1387SBhawanpreet Lakha 		return false;
325d99f1387SBhawanpreet Lakha 
326d99f1387SBhawanpreet Lakha 	tf = TRANSFER_FUNCTION_UNITY;
327d99f1387SBhawanpreet Lakha 
328d99f1387SBhawanpreet Lakha 	if (plane_state->in_transfer_func.type == TF_TYPE_PREDEFINED)
329d99f1387SBhawanpreet Lakha 		tf = plane_state->in_transfer_func.tf;
330d99f1387SBhawanpreet Lakha 
331d99f1387SBhawanpreet Lakha 	dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
332d99f1387SBhawanpreet Lakha 
333d99f1387SBhawanpreet Lakha 	if (plane_state->in_transfer_func.type == TF_TYPE_HWPWL)
334d99f1387SBhawanpreet Lakha 		params = &plane_state->in_transfer_func.pwl;
335d99f1387SBhawanpreet Lakha 	else if (plane_state->in_transfer_func.type == TF_TYPE_DISTRIBUTED_POINTS &&
336d99f1387SBhawanpreet Lakha 		cm3_helper_translate_curve_to_hw_format(&plane_state->in_transfer_func,
337d99f1387SBhawanpreet Lakha 				&dpp_base->degamma_params, false))
33841801c6bSMelissa Wen 		params = &dpp_base->degamma_params;
33941801c6bSMelissa Wen 
34041801c6bSMelissa Wen 	result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
34141801c6bSMelissa Wen 
34241801c6bSMelissa Wen 	if (pipe_ctx->stream_res.opp && pipe_ctx->stream_res.opp->ctx) {
34341801c6bSMelissa Wen 		if (dpp_base->funcs->dpp_program_blnd_lut)
34441801c6bSMelissa Wen 			hws->funcs.set_blend_lut(pipe_ctx, plane_state);
34541801c6bSMelissa Wen 		if (dpp_base->funcs->dpp_program_shaper_lut &&
34641801c6bSMelissa Wen 				dpp_base->funcs->dpp_program_3dlut)
34741801c6bSMelissa Wen 			hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state);
34841801c6bSMelissa Wen 	}
34941801c6bSMelissa Wen 
35041801c6bSMelissa Wen 	return result;
35141801c6bSMelissa Wen }
35241801c6bSMelissa Wen 
dcn30_program_gamut_remap(struct pipe_ctx * pipe_ctx)35341801c6bSMelissa Wen void dcn30_program_gamut_remap(struct pipe_ctx *pipe_ctx)
35441801c6bSMelissa Wen {
35541801c6bSMelissa Wen 	int i = 0;
35641801c6bSMelissa Wen 	struct dpp_grph_csc_adjustment dpp_adjust;
35741801c6bSMelissa Wen 	struct mpc_grph_gamut_adjustment mpc_adjust;
35841801c6bSMelissa Wen 	int mpcc_id = pipe_ctx->plane_res.hubp->inst;
35941801c6bSMelissa Wen 	struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
36041801c6bSMelissa Wen 
36141801c6bSMelissa Wen 	memset(&dpp_adjust, 0, sizeof(dpp_adjust));
36241801c6bSMelissa Wen 	dpp_adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
36341801c6bSMelissa Wen 
36441801c6bSMelissa Wen 	if (pipe_ctx->plane_state &&
36541801c6bSMelissa Wen 	    pipe_ctx->plane_state->gamut_remap_matrix.enable_remap == true) {
36641801c6bSMelissa Wen 		dpp_adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
36741801c6bSMelissa Wen 		for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
36841801c6bSMelissa Wen 			dpp_adjust.temperature_matrix[i] =
36941801c6bSMelissa Wen 				pipe_ctx->plane_state->gamut_remap_matrix.matrix[i];
37041801c6bSMelissa Wen 	}
37141801c6bSMelissa Wen 
37241801c6bSMelissa Wen 	pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp,
37341801c6bSMelissa Wen 							    &dpp_adjust);
37441801c6bSMelissa Wen 
375d99f1387SBhawanpreet Lakha 	memset(&mpc_adjust, 0, sizeof(mpc_adjust));
376d99f1387SBhawanpreet Lakha 	mpc_adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
377d99f1387SBhawanpreet Lakha 
378d99f1387SBhawanpreet Lakha 	if (pipe_ctx->top_pipe == NULL) {
379d99f1387SBhawanpreet Lakha 		if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
380d99f1387SBhawanpreet Lakha 			mpc_adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
381d99f1387SBhawanpreet Lakha 			for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
382d99f1387SBhawanpreet Lakha 				mpc_adjust.temperature_matrix[i] =
383d99f1387SBhawanpreet Lakha 					pipe_ctx->stream->gamut_remap_matrix.matrix[i];
384d99f1387SBhawanpreet Lakha 		}
385d99f1387SBhawanpreet Lakha 	}
386d99f1387SBhawanpreet Lakha 
387d99f1387SBhawanpreet Lakha 	mpc->funcs->set_gamut_remap(mpc, mpcc_id, &mpc_adjust);
388d99f1387SBhawanpreet Lakha }
389d99f1387SBhawanpreet Lakha 
dcn30_set_output_transfer_func(struct dc * dc,struct pipe_ctx * pipe_ctx,const struct dc_stream_state * stream)390d99f1387SBhawanpreet Lakha bool dcn30_set_output_transfer_func(struct dc *dc,
391d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx,
392d99f1387SBhawanpreet Lakha 				const struct dc_stream_state *stream)
393d99f1387SBhawanpreet Lakha {
394d99f1387SBhawanpreet Lakha 	int mpcc_id = pipe_ctx->plane_res.hubp->inst;
395d99f1387SBhawanpreet Lakha 	struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
396d99f1387SBhawanpreet Lakha 	const struct pwl_params *params = NULL;
397d99f1387SBhawanpreet Lakha 	bool ret = false;
398d99f1387SBhawanpreet Lakha 
399d99f1387SBhawanpreet Lakha 	/* program OGAM or 3DLUT only for the top pipe*/
400d99f1387SBhawanpreet Lakha 	if (pipe_ctx->top_pipe == NULL) {
401d99f1387SBhawanpreet Lakha 		/*program rmu shaper and 3dlut in MPC*/
402d99f1387SBhawanpreet Lakha 		ret = dcn30_set_mpc_shaper_3dlut(pipe_ctx, stream);
403d99f1387SBhawanpreet Lakha 		if (ret == false && mpc->funcs->set_output_gamma) {
404d99f1387SBhawanpreet Lakha 			if (stream->out_transfer_func.type == TF_TYPE_HWPWL)
405d99f1387SBhawanpreet Lakha 				params = &stream->out_transfer_func.pwl;
406d99f1387SBhawanpreet Lakha 			else if (pipe_ctx->stream->out_transfer_func.type ==
407d99f1387SBhawanpreet Lakha 					TF_TYPE_DISTRIBUTED_POINTS &&
408d99f1387SBhawanpreet Lakha 					cm3_helper_translate_curve_to_hw_format(
409d99f1387SBhawanpreet Lakha 					&stream->out_transfer_func,
410d99f1387SBhawanpreet Lakha 					&mpc->blender_params, false))
411d99f1387SBhawanpreet Lakha 				params = &mpc->blender_params;
412d99f1387SBhawanpreet Lakha 			 /* there are no ROM LUTs in OUTGAM */
413d99f1387SBhawanpreet Lakha 			if (stream->out_transfer_func.type == TF_TYPE_PREDEFINED)
414d99f1387SBhawanpreet Lakha 				BREAK_TO_DEBUGGER();
415d99f1387SBhawanpreet Lakha 		}
416d99f1387SBhawanpreet Lakha 	}
417d99f1387SBhawanpreet Lakha 
4180b02e1fdSJoshua Aberback 	if (mpc->funcs->set_output_gamma)
419d99f1387SBhawanpreet Lakha 		mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
420d99f1387SBhawanpreet Lakha 	else
421d99f1387SBhawanpreet Lakha 		DC_LOG_ERROR("%s: set_output_gamma function pointer is NULL.\n", __func__);
422d99f1387SBhawanpreet Lakha 
423d99f1387SBhawanpreet Lakha 	return ret;
424d99f1387SBhawanpreet Lakha }
425d99f1387SBhawanpreet Lakha 
dcn30_set_writeback(struct dc * dc,struct dc_writeback_info * wb_info,struct dc_state * context)426d99f1387SBhawanpreet Lakha static void dcn30_set_writeback(
427d99f1387SBhawanpreet Lakha 		struct dc *dc,
428d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
429d99f1387SBhawanpreet Lakha 		struct dc_state *context)
430d99f1387SBhawanpreet Lakha {
431d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
432d99f1387SBhawanpreet Lakha 	struct mcif_buf_params *mcif_buf_params;
433d99f1387SBhawanpreet Lakha 
434d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES);
435d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->wb_enabled);
436d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->mpcc_inst >= 0);
437d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->mpcc_inst < dc->res_pool->mpcc_count);
438d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
439d99f1387SBhawanpreet Lakha 	mcif_buf_params = &wb_info->mcif_buf_params;
440d99f1387SBhawanpreet Lakha 
441d99f1387SBhawanpreet Lakha 	/* set DWB MPC mux */
442d99f1387SBhawanpreet Lakha 	dc->res_pool->mpc->funcs->set_dwb_mux(dc->res_pool->mpc,
443d99f1387SBhawanpreet Lakha 			wb_info->dwb_pipe_inst, wb_info->mpcc_inst);
444d99f1387SBhawanpreet Lakha 	/* set MCIF_WB buffer and arbitration configuration */
445d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->config_mcif_buf(mcif_wb, mcif_buf_params, wb_info->dwb_params.dest_height);
446d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
447d99f1387SBhawanpreet Lakha }
448d99f1387SBhawanpreet Lakha 
dcn30_update_writeback(struct dc * dc,struct dc_writeback_info * wb_info,struct dc_state * context)449d99f1387SBhawanpreet Lakha void dcn30_update_writeback(
450d99f1387SBhawanpreet Lakha 		struct dc *dc,
451d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
452d99f1387SBhawanpreet Lakha 		struct dc_state *context)
453d99f1387SBhawanpreet Lakha {
454d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
455d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
456d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
457d99f1387SBhawanpreet Lakha 		__func__, wb_info->dwb_pipe_inst,\
458d99f1387SBhawanpreet Lakha 		wb_info->mpcc_inst);
459d99f1387SBhawanpreet Lakha 
460d99f1387SBhawanpreet Lakha 	dcn30_set_writeback(dc, wb_info, context);
461d99f1387SBhawanpreet Lakha 
462d99f1387SBhawanpreet Lakha 	/* update DWB */
463d99f1387SBhawanpreet Lakha 	dwb->funcs->update(dwb, &wb_info->dwb_params);
464d99f1387SBhawanpreet Lakha }
465d99f1387SBhawanpreet Lakha 
dcn30_mmhubbub_warmup(struct dc * dc,unsigned int num_dwb,struct dc_writeback_info * wb_info)466d99f1387SBhawanpreet Lakha bool dcn30_mmhubbub_warmup(
467d99f1387SBhawanpreet Lakha 	struct dc *dc,
468d99f1387SBhawanpreet Lakha 	unsigned int num_dwb,
469d99f1387SBhawanpreet Lakha 	struct dc_writeback_info *wb_info)
470d99f1387SBhawanpreet Lakha {
471d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
472d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
473d99f1387SBhawanpreet Lakha 	struct mcif_warmup_params warmup_params = {0};
474d99f1387SBhawanpreet Lakha 	unsigned int  i, i_buf;
475d99f1387SBhawanpreet Lakha 	/* make sure there is no active DWB enabled */
476d99f1387SBhawanpreet Lakha 	for (i = 0; i < num_dwb; i++) {
477d99f1387SBhawanpreet Lakha 		dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst];
478d99f1387SBhawanpreet Lakha 		if (dwb->dwb_is_efc_transition || dwb->dwb_is_drc) {
479d99f1387SBhawanpreet Lakha 			/*can not do warmup while any dwb enabled*/
480d99f1387SBhawanpreet Lakha 			return false;
481d99f1387SBhawanpreet Lakha 		}
482d99f1387SBhawanpreet Lakha 	}
483d99f1387SBhawanpreet Lakha 
484d99f1387SBhawanpreet Lakha 	if (wb_info->mcif_warmup_params.p_vmid == 0)
485d99f1387SBhawanpreet Lakha 		return false;
486d99f1387SBhawanpreet Lakha 
487d99f1387SBhawanpreet Lakha 	/*check whether this is new interface: warmup big buffer once*/
488d99f1387SBhawanpreet Lakha 	if (wb_info->mcif_warmup_params.start_address.quad_part != 0 &&
489d99f1387SBhawanpreet Lakha 		wb_info->mcif_warmup_params.region_size != 0) {
490d99f1387SBhawanpreet Lakha 		/*mmhubbub is shared, so it does not matter which MCIF*/
491d99f1387SBhawanpreet Lakha 		mcif_wb = dc->res_pool->mcif_wb[0];
492d99f1387SBhawanpreet Lakha 		/*warmup a big chunk of VM buffer at once*/
493d99f1387SBhawanpreet Lakha 		warmup_params.start_address.quad_part = wb_info->mcif_warmup_params.start_address.quad_part;
494d99f1387SBhawanpreet Lakha 		warmup_params.address_increment =  wb_info->mcif_warmup_params.region_size;
495d99f1387SBhawanpreet Lakha 		warmup_params.region_size = wb_info->mcif_warmup_params.region_size;
496d99f1387SBhawanpreet Lakha 		warmup_params.p_vmid = wb_info->mcif_warmup_params.p_vmid;
497d99f1387SBhawanpreet Lakha 
498d99f1387SBhawanpreet Lakha 		if (warmup_params.address_increment == 0)
499d99f1387SBhawanpreet Lakha 			warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes;
500d99f1387SBhawanpreet Lakha 
501d99f1387SBhawanpreet Lakha 		mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params);
502d99f1387SBhawanpreet Lakha 		return true;
503d99f1387SBhawanpreet Lakha 	}
504d99f1387SBhawanpreet Lakha 	/*following is the original: warmup each DWB's mcif buffer*/
505d99f1387SBhawanpreet Lakha 	for (i = 0; i < num_dwb; i++) {
506d99f1387SBhawanpreet Lakha 		mcif_wb = dc->res_pool->mcif_wb[wb_info[i].dwb_pipe_inst];
507d99f1387SBhawanpreet Lakha 		/*warmup is for VM mode only*/
508d99f1387SBhawanpreet Lakha 		if (wb_info[i].mcif_buf_params.p_vmid == 0)
509d99f1387SBhawanpreet Lakha 			return false;
510d99f1387SBhawanpreet Lakha 
511d99f1387SBhawanpreet Lakha 		/* Warmup MCIF_WB */
512d99f1387SBhawanpreet Lakha 		for (i_buf = 0; i_buf < MCIF_BUF_COUNT; i_buf++) {
513d99f1387SBhawanpreet Lakha 			warmup_params.start_address.quad_part = wb_info[i].mcif_buf_params.luma_address[i_buf];
514d99f1387SBhawanpreet Lakha 			warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes;
515d99f1387SBhawanpreet Lakha 			warmup_params.region_size = wb_info[i].mcif_buf_params.luma_pitch * wb_info[i].dwb_params.dest_height;
516d99f1387SBhawanpreet Lakha 			warmup_params.p_vmid = wb_info[i].mcif_buf_params.p_vmid;
517d99f1387SBhawanpreet Lakha 			mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params);
518d99f1387SBhawanpreet Lakha 		}
519f772f902SAlex Hung 	}
520f772f902SAlex Hung 	return true;
521f772f902SAlex Hung }
522f772f902SAlex Hung 
dcn30_enable_writeback(struct dc * dc,struct dc_writeback_info * wb_info,struct dc_state * context)523d99f1387SBhawanpreet Lakha void dcn30_enable_writeback(
524d99f1387SBhawanpreet Lakha 		struct dc *dc,
525d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
526d99f1387SBhawanpreet Lakha 		struct dc_state *context)
527d99f1387SBhawanpreet Lakha {
528d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
529d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
530d99f1387SBhawanpreet Lakha 
531d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
532d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
533d99f1387SBhawanpreet Lakha 
534d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
535d99f1387SBhawanpreet Lakha 		__func__, wb_info->dwb_pipe_inst,\
536d99f1387SBhawanpreet Lakha 		wb_info->mpcc_inst);
537d99f1387SBhawanpreet Lakha 
538d99f1387SBhawanpreet Lakha 	/* Warmup interface */
539d99f1387SBhawanpreet Lakha 	dcn30_mmhubbub_warmup(dc, 1, wb_info);
540d99f1387SBhawanpreet Lakha 
541d99f1387SBhawanpreet Lakha 	/* Update writeback pipe */
542d99f1387SBhawanpreet Lakha 	dcn30_set_writeback(dc, wb_info, context);
543d99f1387SBhawanpreet Lakha 
544d99f1387SBhawanpreet Lakha 	/* Enable MCIF_WB */
545d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->enable_mcif(mcif_wb);
546d99f1387SBhawanpreet Lakha 	/* Enable DWB */
547d99f1387SBhawanpreet Lakha 	dwb->funcs->enable(dwb, &wb_info->dwb_params);
548d99f1387SBhawanpreet Lakha }
549d99f1387SBhawanpreet Lakha 
dcn30_disable_writeback(struct dc * dc,unsigned int dwb_pipe_inst)550d99f1387SBhawanpreet Lakha void dcn30_disable_writeback(
551d99f1387SBhawanpreet Lakha 		struct dc *dc,
552d99f1387SBhawanpreet Lakha 		unsigned int dwb_pipe_inst)
553d99f1387SBhawanpreet Lakha {
554d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
555d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
556d99f1387SBhawanpreet Lakha 
557d99f1387SBhawanpreet Lakha 	ASSERT(dwb_pipe_inst < MAX_DWB_PIPES);
558d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[dwb_pipe_inst];
559d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst];
560d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d",\
561d99f1387SBhawanpreet Lakha 		__func__, dwb_pipe_inst);
562d99f1387SBhawanpreet Lakha 
563d99f1387SBhawanpreet Lakha 	/* disable DWB */
564d99f1387SBhawanpreet Lakha 	dwb->funcs->disable(dwb);
565d99f1387SBhawanpreet Lakha 	/* disable MCIF */
566d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->disable_mcif(mcif_wb);
567d99f1387SBhawanpreet Lakha 	/* disable MPC DWB mux */
568d99f1387SBhawanpreet Lakha 	dc->res_pool->mpc->funcs->disable_dwb_mux(dc->res_pool->mpc, dwb_pipe_inst);
569d99f1387SBhawanpreet Lakha }
570d99f1387SBhawanpreet Lakha 
dcn30_program_all_writeback_pipes_in_tree(struct dc * dc,const struct dc_stream_state * stream,struct dc_state * context)571d99f1387SBhawanpreet Lakha void dcn30_program_all_writeback_pipes_in_tree(
572d99f1387SBhawanpreet Lakha 		struct dc *dc,
573d99f1387SBhawanpreet Lakha 		const struct dc_stream_state *stream,
574d99f1387SBhawanpreet Lakha 		struct dc_state *context)
575d99f1387SBhawanpreet Lakha {
576d99f1387SBhawanpreet Lakha 	struct dc_writeback_info wb_info;
577d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
578d99f1387SBhawanpreet Lakha 	struct dc_stream_status *stream_status = NULL;
579d99f1387SBhawanpreet Lakha 	int i_wb, i_pipe, i_stream;
580d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s", __func__);
581d99f1387SBhawanpreet Lakha 
582d99f1387SBhawanpreet Lakha 	ASSERT(stream);
583d99f1387SBhawanpreet Lakha 	for (i_stream = 0; i_stream < context->stream_count; i_stream++) {
584d99f1387SBhawanpreet Lakha 		if (context->streams[i_stream] == stream) {
585d99f1387SBhawanpreet Lakha 			stream_status = &context->stream_status[i_stream];
58682367e7fSRoy Chan 			break;
58782367e7fSRoy Chan 		}
58882367e7fSRoy Chan 	}
589d99f1387SBhawanpreet Lakha 	ASSERT(stream_status);
590d99f1387SBhawanpreet Lakha 
591d99f1387SBhawanpreet Lakha 	ASSERT(stream->num_wb_info <= dc->res_pool->res_cap->num_dwb);
592d99f1387SBhawanpreet Lakha 	/* For each writeback pipe */
593d99f1387SBhawanpreet Lakha 	for (i_wb = 0; i_wb < stream->num_wb_info; i_wb++) {
59482367e7fSRoy Chan 
59582367e7fSRoy Chan 		/* copy writeback info to local non-const so mpcc_inst can be set */
59682367e7fSRoy Chan 		wb_info = stream->writeback_info[i_wb];
59782367e7fSRoy Chan 		if (wb_info.wb_enabled) {
59882367e7fSRoy Chan 
59982367e7fSRoy Chan 			/* get the MPCC instance for writeback_source_plane */
60082367e7fSRoy Chan 			wb_info.mpcc_inst = -1;
60182367e7fSRoy Chan 			for (i_pipe = 0; i_pipe < dc->res_pool->pipe_count; i_pipe++) {
602d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i_pipe];
603d99f1387SBhawanpreet Lakha 
604d99f1387SBhawanpreet Lakha 				if (!pipe_ctx->plane_state)
605d99f1387SBhawanpreet Lakha 					continue;
606d99f1387SBhawanpreet Lakha 
607d99f1387SBhawanpreet Lakha 				if (pipe_ctx->plane_state == wb_info.writeback_source_plane) {
608d99f1387SBhawanpreet Lakha 					wb_info.mpcc_inst = pipe_ctx->plane_res.mpcc_inst;
609d99f1387SBhawanpreet Lakha 					break;
610d99f1387SBhawanpreet Lakha 				}
611d99f1387SBhawanpreet Lakha 			}
612d99f1387SBhawanpreet Lakha 
613d99f1387SBhawanpreet Lakha 			if (wb_info.mpcc_inst == -1) {
614d99f1387SBhawanpreet Lakha 				/* Disable writeback pipe and disconnect from MPCC
615d99f1387SBhawanpreet Lakha 				 * if source plane has been removed
616d99f1387SBhawanpreet Lakha 				 */
617d99f1387SBhawanpreet Lakha 				dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst);
618d99f1387SBhawanpreet Lakha 				continue;
619d99f1387SBhawanpreet Lakha 			}
620d99f1387SBhawanpreet Lakha 
621d99f1387SBhawanpreet Lakha 			ASSERT(wb_info.dwb_pipe_inst < dc->res_pool->res_cap->num_dwb);
622d99f1387SBhawanpreet Lakha 			dwb = dc->res_pool->dwbc[wb_info.dwb_pipe_inst];
623d99f1387SBhawanpreet Lakha 			if (dwb->funcs->is_enabled(dwb)) {
624d99f1387SBhawanpreet Lakha 				/* writeback pipe already enabled, only need to update */
625ebd1e719SLeo (Hanghong) Ma 				dc->hwss.update_writeback(dc, &wb_info, context);
62645a1261bSJake Wang 			} else {
627d99f1387SBhawanpreet Lakha 				/* Enable writeback pipe and connect to MPCC */
628ee8ed250SCamille Cho 				dc->hwss.enable_writeback(dc, &wb_info, context);
629d99f1387SBhawanpreet Lakha 			}
630d99f1387SBhawanpreet Lakha 		} else {
631d99f1387SBhawanpreet Lakha 			/* Disable writeback pipe and disconnect from MPCC */
632d99f1387SBhawanpreet Lakha 			dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst);
633d99f1387SBhawanpreet Lakha 		}
634d99f1387SBhawanpreet Lakha 	}
635d99f1387SBhawanpreet Lakha }
636d99f1387SBhawanpreet Lakha 
dcn30_init_hw(struct dc * dc)637d99f1387SBhawanpreet Lakha void dcn30_init_hw(struct dc *dc)
638d99f1387SBhawanpreet Lakha {
639d99f1387SBhawanpreet Lakha 	struct abm **abms = dc->res_pool->multiple_abms;
640d99f1387SBhawanpreet Lakha 	struct dce_hwseq *hws = dc->hwseq;
641d99f1387SBhawanpreet Lakha 	struct dc_bios *dcb = dc->ctx->dc_bios;
64296879ad3SJacky Liao 	struct resource_pool *res_pool = dc->res_pool;
64396879ad3SJacky Liao 	int i;
64496879ad3SJacky Liao 	int edp_num;
64596879ad3SJacky Liao 	uint32_t backlight = MAX_BACKLIGHT_LEVEL;
64696879ad3SJacky Liao 	uint32_t user_level = MAX_BACKLIGHT_LEVEL;
64796879ad3SJacky Liao 
64896879ad3SJacky Liao 	if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks)
649cae78e03SJacky Liao 		dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
650cae78e03SJacky Liao 
651cae78e03SJacky Liao 	// Initialize the dccg
652cae78e03SJacky Liao 	if (res_pool->dccg->funcs->dccg_init)
653cae78e03SJacky Liao 		res_pool->dccg->funcs->dccg_init(res_pool->dccg);
654cae78e03SJacky Liao 
65539619d50SAurabindo Pillai 	if (!dcb->funcs->is_accelerated_mode(dcb)) {
65639619d50SAurabindo Pillai 		hws->funcs.bios_golden_init(dc);
65739619d50SAurabindo Pillai 		hws->funcs.disable_vga(dc->hwseq);
65839619d50SAurabindo Pillai 	}
65939619d50SAurabindo Pillai 
660d99f1387SBhawanpreet Lakha 	if (dc->debug.enable_mem_low_power.bits.dmcu) {
661d99f1387SBhawanpreet Lakha 		// Force ERAM to shutdown if DMCU is not enabled
662d99f1387SBhawanpreet Lakha 		if (dc->debug.disable_dmcu || dc->config.disable_dmcu) {
663d99f1387SBhawanpreet Lakha 			REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3);
664d99f1387SBhawanpreet Lakha 		}
665d99f1387SBhawanpreet Lakha 	}
666d99f1387SBhawanpreet Lakha 
667d99f1387SBhawanpreet Lakha 	// Set default OPTC memory power states
668d99f1387SBhawanpreet Lakha 	if (dc->debug.enable_mem_low_power.bits.optc) {
669d99f1387SBhawanpreet Lakha 		// Shutdown when unassigned and light sleep in VBLANK
670d99f1387SBhawanpreet Lakha 		REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
671d99f1387SBhawanpreet Lakha 	}
672d99f1387SBhawanpreet Lakha 
673d99f1387SBhawanpreet Lakha 	if (dc->debug.enable_mem_low_power.bits.vga) {
674d99f1387SBhawanpreet Lakha 		// Power down VGA memory
675d99f1387SBhawanpreet Lakha 		REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
676d99f1387SBhawanpreet Lakha 	}
677d99f1387SBhawanpreet Lakha 
678d99f1387SBhawanpreet Lakha 	if (dc->ctx->dc_bios->fw_info_valid) {
679d99f1387SBhawanpreet Lakha 		res_pool->ref_clocks.xtalin_clock_inKhz =
680d99f1387SBhawanpreet Lakha 				dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
681d99f1387SBhawanpreet Lakha 
682d99f1387SBhawanpreet Lakha 		if (res_pool->hubbub) {
683d99f1387SBhawanpreet Lakha 
684d99f1387SBhawanpreet Lakha 			(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
685d99f1387SBhawanpreet Lakha 					dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
686d99f1387SBhawanpreet Lakha 					&res_pool->ref_clocks.dccg_ref_clock_inKhz);
687d99f1387SBhawanpreet Lakha 
688d99f1387SBhawanpreet Lakha 			(res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
689d99f1387SBhawanpreet Lakha 					res_pool->ref_clocks.dccg_ref_clock_inKhz,
690d99f1387SBhawanpreet Lakha 					&res_pool->ref_clocks.dchub_ref_clock_inKhz);
6910f782777SMartin Leung 		} else {
6920f782777SMartin Leung 			// Not all ASICs have DCCG sw component
6930f782777SMartin Leung 			res_pool->ref_clocks.dccg_ref_clock_inKhz =
69430ffa74aSJingwen Zhu 					res_pool->ref_clocks.xtalin_clock_inKhz;
6950f782777SMartin Leung 			res_pool->ref_clocks.dchub_ref_clock_inKhz =
69630ffa74aSJingwen Zhu 					res_pool->ref_clocks.xtalin_clock_inKhz;
69730ffa74aSJingwen Zhu 		}
69830ffa74aSJingwen Zhu 	} else
69930ffa74aSJingwen Zhu 		ASSERT_CRITICAL(false);
700d99f1387SBhawanpreet Lakha 
701d99f1387SBhawanpreet Lakha 	for (i = 0; i < dc->link_count; i++) {
7020f782777SMartin Leung 		/* Power up AND update implementation according to the
70398ce7d32SWenjing Liu 		 * required signal (which may be different from the
704d99f1387SBhawanpreet Lakha 		 * default signal on connector).
705384bd90dSRoman Li 		 */
706384bd90dSRoman Li 		struct dc_link *link = dc->links[i];
707384bd90dSRoman Li 
7080f782777SMartin Leung 		link->link_enc->funcs->hw_init(link->link_enc);
7090f782777SMartin Leung 
7100f782777SMartin Leung 		/* Check for enabled DIG to identify enabled display */
7110f782777SMartin Leung 		if (link->link_enc->funcs->is_dig_enabled &&
7120f782777SMartin Leung 			link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
7130f782777SMartin Leung 			link->link_status.link_active = true;
7147aba117aSJarif Aftab 			if (link->link_enc->funcs->fec_is_active &&
7150f782777SMartin Leung 					link->link_enc->funcs->fec_is_active(link->link_enc))
7160f782777SMartin Leung 				link->fec_state = dc_link_fec_enabled;
7170f782777SMartin Leung 		}
7180f782777SMartin Leung 	}
719d99f1387SBhawanpreet Lakha 
720d99f1387SBhawanpreet Lakha 	/* we want to turn off all dp displays before doing detection */
7210f782777SMartin Leung 	dc->link_srv->blank_all_dp_displays(dc);
7220f782777SMartin Leung 
7230f782777SMartin Leung 	if (hws->funcs.enable_power_gating_plane)
7240f782777SMartin Leung 		hws->funcs.enable_power_gating_plane(dc->hwseq, true);
7250f782777SMartin Leung 
7267aba117aSJarif Aftab 	/* If taking control over from VBIOS, we may want to optimize our first
72745a1261bSJake Wang 	 * mode set, so we need to skip powering down pipes until we know which
7283addbde2SJake Wang 	 * pipes we want to use.
729d99f1387SBhawanpreet Lakha 	 * Otherwise, if taking control is not possible, we need to power
7307ae1dbe6SWenjing Liu 	 * everything down.
7313addbde2SJake Wang 	 */
7323addbde2SJake Wang 	if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
7333addbde2SJake Wang 		hws->funcs.init_pipes(dc, dc->current_state);
7340f782777SMartin Leung 		if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
7350f782777SMartin Leung 			dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
7360f782777SMartin Leung 					!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
7370f782777SMartin Leung 	}
7380f782777SMartin Leung 
7390f782777SMartin Leung 	/* In headless boot cases, DIG may be turned
7400f782777SMartin Leung 	 * on which causes HW/SW discrepancies.
7410f782777SMartin Leung 	 * To avoid this, power down hardware on boot
7420f782777SMartin Leung 	 * if DIG is turned on and seamless boot not enabled
7430f782777SMartin Leung 	 */
7440f782777SMartin Leung 	if (!dc->config.seamless_boot_edp_requested) {
7450f782777SMartin Leung 		struct dc_link *edp_links[MAX_NUM_EDP];
7460f782777SMartin Leung 		struct dc_link *edp_link = NULL;
7470f782777SMartin Leung 
7480f782777SMartin Leung 		dc_get_edp_links(dc, edp_links, &edp_num);
7490f782777SMartin Leung 		if (edp_num)
750d99f1387SBhawanpreet Lakha 			edp_link = edp_links[0];
751d99f1387SBhawanpreet Lakha 		if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
752d99f1387SBhawanpreet Lakha 				edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
753d99f1387SBhawanpreet Lakha 				dc->hwss.edp_backlight_control &&
754d99f1387SBhawanpreet Lakha 				hws->funcs.power_down &&
755d99f1387SBhawanpreet Lakha 				dc->hwss.edp_power_control) {
756d99f1387SBhawanpreet Lakha 			dc->hwss.edp_backlight_control(edp_link, false);
757d99f1387SBhawanpreet Lakha 			hws->funcs.power_down(dc);
758d99f1387SBhawanpreet Lakha 			dc->hwss.edp_power_control(edp_link, false);
759d99f1387SBhawanpreet Lakha 		} else {
760d99f1387SBhawanpreet Lakha 			for (i = 0; i < dc->link_count; i++) {
761d99f1387SBhawanpreet Lakha 				struct dc_link *link = dc->links[i];
762d99f1387SBhawanpreet Lakha 
763d99f1387SBhawanpreet Lakha 				if (link->link_enc->funcs->is_dig_enabled &&
764d99f1387SBhawanpreet Lakha 						link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
765ee8ed250SCamille Cho 						hws->funcs.power_down) {
766d99f1387SBhawanpreet Lakha 					hws->funcs.power_down(dc);
767ee8ed250SCamille Cho 					break;
768ee8ed250SCamille Cho 				}
769d99f1387SBhawanpreet Lakha 
770d99f1387SBhawanpreet Lakha 			}
771d99f1387SBhawanpreet Lakha 		}
772d99f1387SBhawanpreet Lakha 	}
773ee8ed250SCamille Cho 
774d99f1387SBhawanpreet Lakha 	for (i = 0; i < res_pool->audio_count; i++) {
775d99f1387SBhawanpreet Lakha 		struct audio *audio = res_pool->audios[i];
776d99f1387SBhawanpreet Lakha 
777d99f1387SBhawanpreet Lakha 		audio->funcs->hw_init(audio);
778d99f1387SBhawanpreet Lakha 	}
779d99f1387SBhawanpreet Lakha 
780d99f1387SBhawanpreet Lakha 	for (i = 0; i < dc->link_count; i++) {
781d99f1387SBhawanpreet Lakha 		struct dc_link *link = dc->links[i];
782d99f1387SBhawanpreet Lakha 
783d99f1387SBhawanpreet Lakha 		if (link->panel_cntl) {
784d99f1387SBhawanpreet Lakha 			backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
785d99f1387SBhawanpreet Lakha 			user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
786d99f1387SBhawanpreet Lakha 		}
787d99f1387SBhawanpreet Lakha 	}
78854e8094aSYongqiang Sun 
78954e8094aSYongqiang Sun 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
79054e8094aSYongqiang Sun 		if (abms[i] != NULL)
791d99f1387SBhawanpreet Lakha 			abms[i]->funcs->abm_init(abms[i], backlight, user_level);
792d99f1387SBhawanpreet Lakha 	}
793d99f1387SBhawanpreet Lakha 
79437403cedSAyush Gupta 	/* power AFMT HDMI memory TODO: may move to dis/en output save power*/
79537403cedSAyush Gupta 	REG_WRITE(DIO_MEM_PWR_CTRL, 0);
796d99f1387SBhawanpreet Lakha 
7973e190955SJoshua Aberback 	if (!dc->debug.disable_clock_gate) {
7983e190955SJoshua Aberback 		/* enable all DCN clock gating */
7993e190955SJoshua Aberback 		REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
8003e190955SJoshua Aberback 
801ba5a5371SNicholas Kazlauskas 		REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
802ba5a5371SNicholas Kazlauskas 
803ba5a5371SNicholas Kazlauskas 		REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
804c2fbe663SFelipe Clark 	}
805e97cc04fSJosip Pavic 
806c2fbe663SFelipe Clark 	if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
80700fa7f03SRodrigo Siqueira 		dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
808d99f1387SBhawanpreet Lakha 
809d99f1387SBhawanpreet Lakha 	if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
810d99f1387SBhawanpreet Lakha 		dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
811d99f1387SBhawanpreet Lakha 
812d99f1387SBhawanpreet Lakha 	//if softmax is enabled then hardmax will be set by a different call
813d99f1387SBhawanpreet Lakha 	if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->set_hard_max_memclk &&
814d99f1387SBhawanpreet Lakha 	    !dc->clk_mgr->dc_mode_softmax_enabled)
815*69e3be68SLeo Ma 		dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
816d99f1387SBhawanpreet Lakha 
817d99f1387SBhawanpreet Lakha 	if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
818d99f1387SBhawanpreet Lakha 		dc->res_pool->hubbub->funcs->force_pstate_change_control(
819*69e3be68SLeo Ma 				dc->res_pool->hubbub, false, false);
820*69e3be68SLeo Ma 	if (dc->res_pool->hubbub->funcs->init_crb)
821*69e3be68SLeo Ma 		dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
822*69e3be68SLeo Ma 
823*69e3be68SLeo Ma 	// Get DMCUB capabilities
824*69e3be68SLeo Ma 	dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
825*69e3be68SLeo Ma 	dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
826*69e3be68SLeo Ma 	dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
827*69e3be68SLeo Ma }
828*69e3be68SLeo Ma 
dcn30_set_avmute(struct pipe_ctx * pipe_ctx,bool enable)829d99f1387SBhawanpreet Lakha void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
830d99f1387SBhawanpreet Lakha {
831d99f1387SBhawanpreet Lakha 	if (pipe_ctx == NULL)
832d99f1387SBhawanpreet Lakha 		return;
833d99f1387SBhawanpreet Lakha 
834d99f1387SBhawanpreet Lakha 	if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL) {
835d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->set_avmute(
836d99f1387SBhawanpreet Lakha 				pipe_ctx->stream_res.stream_enc,
837d99f1387SBhawanpreet Lakha 				enable);
838d99f1387SBhawanpreet Lakha 
839d99f1387SBhawanpreet Lakha 		/* Wait for two frame to make sure AV mute is sent out */
840d99f1387SBhawanpreet Lakha 		if (enable && pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) {
841d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
842d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
843d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
84409b07f7aSLeo (Hanghong) Ma 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
845d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
846d99f1387SBhawanpreet Lakha 		}
847d99f1387SBhawanpreet Lakha 	}
848d99f1387SBhawanpreet Lakha }
849d99f1387SBhawanpreet Lakha 
dcn30_update_info_frame(struct pipe_ctx * pipe_ctx)850d99f1387SBhawanpreet Lakha void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx)
851e95afc1cSSung Joon Kim {
852e95afc1cSSung Joon Kim 	bool is_hdmi_tmds;
853e95afc1cSSung Joon Kim 	bool is_dp;
854e95afc1cSSung Joon Kim 
855e95afc1cSSung Joon Kim 	ASSERT(pipe_ctx->stream);
856e95afc1cSSung Joon Kim 
857d99f1387SBhawanpreet Lakha 	if (pipe_ctx->stream_res.stream_enc == NULL)
858d99f1387SBhawanpreet Lakha 		return;  /* this is not root pipe */
859d99f1387SBhawanpreet Lakha 
860d99f1387SBhawanpreet Lakha 	is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
861e95afc1cSSung Joon Kim 	is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
862d99f1387SBhawanpreet Lakha 
863d99f1387SBhawanpreet Lakha 	if (!is_hdmi_tmds && !is_dp)
864d99f1387SBhawanpreet Lakha 		return;
865d99f1387SBhawanpreet Lakha 
866d99f1387SBhawanpreet Lakha 	if (is_hdmi_tmds)
867d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
868d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.stream_enc,
869d99f1387SBhawanpreet Lakha 			&pipe_ctx->stream_res.encoder_info_frame);
870d99f1387SBhawanpreet Lakha 	else {
871d99f1387SBhawanpreet Lakha 		if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num)
872d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num(
873d99f1387SBhawanpreet Lakha 				pipe_ctx->stream_res.stream_enc,
874d99f1387SBhawanpreet Lakha 				&pipe_ctx->stream_res.encoder_info_frame);
875d99f1387SBhawanpreet Lakha 
876d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
877d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.stream_enc,
878d99f1387SBhawanpreet Lakha 			&pipe_ctx->stream_res.encoder_info_frame);
879d99f1387SBhawanpreet Lakha 	}
880d99f1387SBhawanpreet Lakha }
881d99f1387SBhawanpreet Lakha 
dcn30_program_dmdata_engine(struct pipe_ctx * pipe_ctx)882d99f1387SBhawanpreet Lakha void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
883d99f1387SBhawanpreet Lakha {
884d99f1387SBhawanpreet Lakha 	struct dc_stream_state    *stream     = pipe_ctx->stream;
885d99f1387SBhawanpreet Lakha 	struct hubp               *hubp       = pipe_ctx->plane_res.hubp;
886d99f1387SBhawanpreet Lakha 	bool                       enable     = false;
887d99f1387SBhawanpreet Lakha 	struct stream_encoder     *stream_enc = pipe_ctx->stream_res.stream_enc;
888d99f1387SBhawanpreet Lakha 	enum dynamic_metadata_mode mode       = dc_is_dp_signal(stream->signal)
889d99f1387SBhawanpreet Lakha 							? dmdata_dp
890d99f1387SBhawanpreet Lakha 							: dmdata_hdmi;
89152f2e83eSBhawanpreet Lakha 
89252f2e83eSBhawanpreet Lakha 	/* if using dynamic meta, don't set up generic infopackets */
893ea7154d8SBhawanpreet Lakha 	if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
894ea7154d8SBhawanpreet Lakha 		pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
895ea7154d8SBhawanpreet Lakha 		enable = true;
896ea7154d8SBhawanpreet Lakha 	}
89752f2e83eSBhawanpreet Lakha 
898d99f1387SBhawanpreet Lakha 	if (!hubp)
899d99f1387SBhawanpreet Lakha 		return;
900d99f1387SBhawanpreet Lakha 
901d99f1387SBhawanpreet Lakha 	if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
90248e48e59SZhan Liu 		return;
90348e48e59SZhan Liu 
904d99f1387SBhawanpreet Lakha 	stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
90548e48e59SZhan Liu 							hubp->inst, mode);
90648e48e59SZhan Liu }
907ea7154d8SBhawanpreet Lakha 
dcn30_apply_idle_power_optimizations(struct dc * dc,bool enable)90848e48e59SZhan Liu bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
90948e48e59SZhan Liu {
91048e48e59SZhan Liu 	union dmub_rb_cmd cmd;
91152f2e83eSBhawanpreet Lakha 	uint32_t tmr_delay = 0, tmr_scale = 0;
912ea7154d8SBhawanpreet Lakha 	struct dc_cursor_attributes cursor_attr = {0};
913ea7154d8SBhawanpreet Lakha 	bool cursor_cache_enable = false;
914ea7154d8SBhawanpreet Lakha 	struct dc_stream_state *stream = NULL;
915ea7154d8SBhawanpreet Lakha 	struct dc_plane_state *plane = NULL;
916ea7154d8SBhawanpreet Lakha 
917ea7154d8SBhawanpreet Lakha 	if (!dc->ctx->dmub_srv)
918ea7154d8SBhawanpreet Lakha 		return false;
91988927808SNicholas Kazlauskas 
920ea7154d8SBhawanpreet Lakha 	if (enable) {
921ea7154d8SBhawanpreet Lakha 		if (dc->current_state) {
922a87a9a73SAlex Deucher 			int i;
923a87a9a73SAlex Deucher 
924ea7154d8SBhawanpreet Lakha 			/* First, check no-memory-requests case */
925ea7154d8SBhawanpreet Lakha 			for (i = 0; i < dc->current_state->stream_count; i++) {
926ea7154d8SBhawanpreet Lakha 				if (dc->current_state->stream_status[i].plane_count)
927ea7154d8SBhawanpreet Lakha 					/* Fail eligibility on a visible stream */
928ea7154d8SBhawanpreet Lakha 					break;
929ea7154d8SBhawanpreet Lakha 			}
930ea7154d8SBhawanpreet Lakha 
931ea7154d8SBhawanpreet Lakha 			if (i == dc->current_state->stream_count) {
93252f2e83eSBhawanpreet Lakha 				/* Enable no-memory-requests case */
93352f2e83eSBhawanpreet Lakha 				memset(&cmd, 0, sizeof(cmd));
934ea7154d8SBhawanpreet Lakha 				cmd.mall.header.type = DMUB_CMD__MALL;
935ea7154d8SBhawanpreet Lakha 				cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ;
936ea7154d8SBhawanpreet Lakha 				cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
937ea7154d8SBhawanpreet Lakha 
938ea7154d8SBhawanpreet Lakha 				dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
939ea7154d8SBhawanpreet Lakha 
940ea7154d8SBhawanpreet Lakha 				return true;
941ea7154d8SBhawanpreet Lakha 			}
942ea7154d8SBhawanpreet Lakha 
943ea7154d8SBhawanpreet Lakha 			stream = dc->current_state->streams[0];
944ea7154d8SBhawanpreet Lakha 			plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL);
945ea7154d8SBhawanpreet Lakha 
946ea7154d8SBhawanpreet Lakha 			if (!stream || !plane)
947ea7154d8SBhawanpreet Lakha 				return false;
948ea7154d8SBhawanpreet Lakha 
949ea7154d8SBhawanpreet Lakha 			if (stream && plane) {
950ea7154d8SBhawanpreet Lakha 				cursor_cache_enable = stream->cursor_position.enable &&
951ea7154d8SBhawanpreet Lakha 						plane->address.grph.cursor_cache_addr.quad_part;
952ea7154d8SBhawanpreet Lakha 				cursor_attr = stream->cursor_attributes;
9539024fb08SLang Yu 			}
9549024fb08SLang Yu 
955ea7154d8SBhawanpreet Lakha 			/*
956ea7154d8SBhawanpreet Lakha 			 * Second, check MALL eligibility
957ea7154d8SBhawanpreet Lakha 			 *
958ea7154d8SBhawanpreet Lakha 			 * single display only, single surface only, 8 and 16 bit formats only, no VM,
959ea7154d8SBhawanpreet Lakha 			 * do not use MALL for displays that support PSR as they use D0i3.2 in DMCUB FW
960ea7154d8SBhawanpreet Lakha 			 *
961ea7154d8SBhawanpreet Lakha 			 * TODO: When we implement multi-display, PSR displays will be allowed if there is
962ea7154d8SBhawanpreet Lakha 			 * a non-PSR display present, since in that case we can't do D0i3.2
963ea7154d8SBhawanpreet Lakha 			 */
964ea7154d8SBhawanpreet Lakha 			if (dc->current_state->stream_count == 1 &&
965ea7154d8SBhawanpreet Lakha 					stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED &&
966ea7154d8SBhawanpreet Lakha 					dc->current_state->stream_status[0].plane_count == 1 &&
967ea7154d8SBhawanpreet Lakha 					plane->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F &&
968ea7154d8SBhawanpreet Lakha 					plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 &&
969ea7154d8SBhawanpreet Lakha 					plane->address.page_table_base.quad_part == 0 &&
970ea7154d8SBhawanpreet Lakha 					dc->hwss.does_plane_fit_in_mall &&
971ea7154d8SBhawanpreet Lakha 					dc->hwss.does_plane_fit_in_mall(dc, plane->plane_size.surface_pitch,
972ea7154d8SBhawanpreet Lakha 							plane->plane_size.surface_size.height, plane->format,
973ea7154d8SBhawanpreet Lakha 							cursor_cache_enable ? &cursor_attr : NULL)) {
974ea7154d8SBhawanpreet Lakha 				unsigned int v_total = stream->adjust.v_total_max ?
97552f2e83eSBhawanpreet Lakha 						stream->adjust.v_total_max : stream->timing.v_total;
97652f2e83eSBhawanpreet Lakha 				unsigned int refresh_hz = div_u64((unsigned long long) stream->timing.pix_clk_100hz *
97752f2e83eSBhawanpreet Lakha 						100LL, (v_total * stream->timing.h_total));
978ea7154d8SBhawanpreet Lakha 
979ea7154d8SBhawanpreet Lakha 				/*
980ea7154d8SBhawanpreet Lakha 				 * one frame time in microsec:
9819024fb08SLang Yu 				 * Delay_Us = 1000000 / refresh
9829024fb08SLang Yu 				 * dynamic_delay_us = 1000000 / refresh + 2 * stutter_period
983ea7154d8SBhawanpreet Lakha 				 *
98452f2e83eSBhawanpreet Lakha 				 * one frame time modified by 'additional timer percent' (p):
9853bb68cecSBhawanpreet Lakha 				 * Delay_Us_modified = dynamic_delay_us + dynamic_delay_us * p / 100
9863bb68cecSBhawanpreet Lakha 				 *                   = dynamic_delay_us * (1 + p / 100)
9873bb68cecSBhawanpreet Lakha 				 *                   = (1000000 / refresh + 2 * stutter_period) * (100 + p) / 100
9883bb68cecSBhawanpreet Lakha 				 *                   = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh)
9893bb68cecSBhawanpreet Lakha 				 *
9903bb68cecSBhawanpreet Lakha 				 * formula for timer duration based on parameters, from regspec:
9913bb68cecSBhawanpreet Lakha 				 * dynamic_delay_us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
9923bb68cecSBhawanpreet Lakha 				 *
9933bb68cecSBhawanpreet Lakha 				 * dynamic_delay_us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
99452f2e83eSBhawanpreet Lakha 				 * (dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly
99552f2e83eSBhawanpreet Lakha 				 * MallFrameCacheTmrDly = ((dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale) - 64
99652f2e83eSBhawanpreet Lakha 				 *                      = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64
99752f2e83eSBhawanpreet Lakha 				 *                      = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64
99852f2e83eSBhawanpreet Lakha 				 *
999ea7154d8SBhawanpreet Lakha 				 * need to round up the result of the division before the subtraction
100052f2e83eSBhawanpreet Lakha 				 */
100152f2e83eSBhawanpreet Lakha 				unsigned int denom = refresh_hz * 6528;
100252f2e83eSBhawanpreet Lakha 				unsigned int stutter_period = dc->current_state->perf_params.stutter_period_us;
100352f2e83eSBhawanpreet Lakha 
100452f2e83eSBhawanpreet Lakha 				tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) *
10059024fb08SLang Yu 						(100LL + dc->debug.mall_additional_timer_percent) + denom - 1),
10069024fb08SLang Yu 						denom) - 64LL;
1007ea7154d8SBhawanpreet Lakha 
1008ea7154d8SBhawanpreet Lakha 				/* In some cases the stutter period is really big (tiny modes) in these
1009ea7154d8SBhawanpreet Lakha 				 * cases MALL cant be enabled, So skip these cases to avoid a ASSERT()
1010ea7154d8SBhawanpreet Lakha 				 *
1011ea7154d8SBhawanpreet Lakha 				 * We can check if stutter_period is more than 1/10th the frame time to
1012ea7154d8SBhawanpreet Lakha 				 * consider if we can actually meet the range of hysteresis timer
1013ea7154d8SBhawanpreet Lakha 				 */
1014ea7154d8SBhawanpreet Lakha 				if (stutter_period > 100000/refresh_hz)
1015ea7154d8SBhawanpreet Lakha 					return false;
1016ea7154d8SBhawanpreet Lakha 
1017ea7154d8SBhawanpreet Lakha 				/* scale should be increased until it fits into 6 bits */
1018ea7154d8SBhawanpreet Lakha 				while (tmr_delay & ~0x3F) {
1019ea7154d8SBhawanpreet Lakha 					tmr_scale++;
1020ea7154d8SBhawanpreet Lakha 
1021ea7154d8SBhawanpreet Lakha 					if (tmr_scale > 3) {
1022ea7154d8SBhawanpreet Lakha 						/* Delay exceeds range of hysteresis timer */
1023ea7154d8SBhawanpreet Lakha 						ASSERT(false);
1024ea7154d8SBhawanpreet Lakha 						return false;
1025ea7154d8SBhawanpreet Lakha 					}
1026ea7154d8SBhawanpreet Lakha 
1027ea7154d8SBhawanpreet Lakha 					denom *= 2;
1028ea7154d8SBhawanpreet Lakha 					tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) *
1029ea7154d8SBhawanpreet Lakha 							(100LL + dc->debug.mall_additional_timer_percent) + denom - 1),
1030ea7154d8SBhawanpreet Lakha 							denom) - 64LL;
1031ea7154d8SBhawanpreet Lakha 				}
1032ea7154d8SBhawanpreet Lakha 
1033ea7154d8SBhawanpreet Lakha 				/* Copy HW cursor */
1034ea7154d8SBhawanpreet Lakha 				if (cursor_cache_enable) {
1035ea7154d8SBhawanpreet Lakha 					memset(&cmd, 0, sizeof(cmd));
1036554ba183SJoshua Aberback 					cmd.mall.header.type = DMUB_CMD__MALL;
1037ea7154d8SBhawanpreet Lakha 					cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_COPY_CURSOR;
1038ea7154d8SBhawanpreet Lakha 					cmd.mall.header.payload_bytes =
1039ea7154d8SBhawanpreet Lakha 							sizeof(cmd.mall) - sizeof(cmd.mall.header);
1040ea7154d8SBhawanpreet Lakha 
104188927808SNicholas Kazlauskas 					switch (cursor_attr.color_format) {
1042ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_MONO:
1043ea7154d8SBhawanpreet Lakha 						cmd.mall.cursor_bpp = 2;
1044554ba183SJoshua Aberback 						break;
1045ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_COLOR_1BIT_AND:
104652f2e83eSBhawanpreet Lakha 					case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
104752f2e83eSBhawanpreet Lakha 					case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
104852f2e83eSBhawanpreet Lakha 						cmd.mall.cursor_bpp = 32;
104952f2e83eSBhawanpreet Lakha 						break;
105052f2e83eSBhawanpreet Lakha 
1051ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
1052ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
105352f2e83eSBhawanpreet Lakha 						cmd.mall.cursor_bpp = 64;
105452f2e83eSBhawanpreet Lakha 						break;
1055ea7154d8SBhawanpreet Lakha 					}
105652f2e83eSBhawanpreet Lakha 
105788927808SNicholas Kazlauskas 					cmd.mall.cursor_copy_src.quad_part = cursor_attr.address.quad_part;
105852f2e83eSBhawanpreet Lakha 					cmd.mall.cursor_copy_dst.quad_part =
105952f2e83eSBhawanpreet Lakha 							(plane->address.grph.cursor_cache_addr.quad_part + 2047) & ~2047;
106052f2e83eSBhawanpreet Lakha 					cmd.mall.cursor_width = cursor_attr.width;
1061d99f1387SBhawanpreet Lakha 					cmd.mall.cursor_height = cursor_attr.height;
1062d99f1387SBhawanpreet Lakha 					cmd.mall.cursor_pitch = cursor_attr.pitch;
106348e48e59SZhan Liu 
1064d99f1387SBhawanpreet Lakha 					dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
1065d99f1387SBhawanpreet Lakha 
1066d99f1387SBhawanpreet Lakha 					/* Use copied cursor, and it's okay to not switch back */
106752f2e83eSBhawanpreet Lakha 					cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part;
106852f2e83eSBhawanpreet Lakha 					dc_stream_program_cursor_attributes(stream, &cursor_attr);
106952f2e83eSBhawanpreet Lakha 				}
107052f2e83eSBhawanpreet Lakha 
107152f2e83eSBhawanpreet Lakha 				/* Enable MALL */
107252f2e83eSBhawanpreet Lakha 				memset(&cmd, 0, sizeof(cmd));
107352f2e83eSBhawanpreet Lakha 				cmd.mall.header.type = DMUB_CMD__MALL;
107488927808SNicholas Kazlauskas 				cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_ALLOW;
107552f2e83eSBhawanpreet Lakha 				cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
1076d99f1387SBhawanpreet Lakha 				cmd.mall.tmr_delay = tmr_delay;
1077d99f1387SBhawanpreet Lakha 				cmd.mall.tmr_scale = tmr_scale;
10783e190955SJoshua Aberback 				cmd.mall.debug_bits = dc->debug.mall_error_as_fatal;
10797fc75382SBhawanpreet Lakha 
1080e74c8a46SJoshua Aberback 				dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
1081e74c8a46SJoshua Aberback 
1082e74c8a46SJoshua Aberback 				return true;
1083e74c8a46SJoshua Aberback 			}
1084e74c8a46SJoshua Aberback 		}
10857fc75382SBhawanpreet Lakha 
1086e74c8a46SJoshua Aberback 		/* No applicable optimizations */
1087e74c8a46SJoshua Aberback 		return false;
1088e74c8a46SJoshua Aberback 	}
1089e74c8a46SJoshua Aberback 
10907fc75382SBhawanpreet Lakha 	/* Disable MALL */
10917fc75382SBhawanpreet Lakha 	memset(&cmd, 0, sizeof(cmd));
10927fc75382SBhawanpreet Lakha 	cmd.mall.header.type = DMUB_CMD__MALL;
10937fc75382SBhawanpreet Lakha 	cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_DISALLOW;
10947fc75382SBhawanpreet Lakha 	cmd.mall.header.payload_bytes =
10957fc75382SBhawanpreet Lakha 		sizeof(cmd.mall) - sizeof(cmd.mall.header);
10967fc75382SBhawanpreet Lakha 
10977fc75382SBhawanpreet Lakha 	dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
10987fc75382SBhawanpreet Lakha 
10997fc75382SBhawanpreet Lakha 	return true;
11007fc75382SBhawanpreet Lakha }
11017fc75382SBhawanpreet Lakha 
dcn30_does_plane_fit_in_mall(struct dc * dc,unsigned int pitch,unsigned int height,enum surface_pixel_format format,struct dc_cursor_attributes * cursor_attr)11027fc75382SBhawanpreet Lakha bool dcn30_does_plane_fit_in_mall(struct dc *dc,
11037fc75382SBhawanpreet Lakha 		unsigned int pitch,
11047fc75382SBhawanpreet Lakha 		unsigned int height,
11057fc75382SBhawanpreet Lakha 		enum surface_pixel_format format,
11067fc75382SBhawanpreet Lakha 		struct dc_cursor_attributes *cursor_attr)
11077fc75382SBhawanpreet Lakha {
11087fc75382SBhawanpreet Lakha 	// add meta size?
11097fc75382SBhawanpreet Lakha 	unsigned int surface_size = pitch * height *
11107fc75382SBhawanpreet Lakha 			(format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4);
1111e74c8a46SJoshua Aberback 	unsigned int mall_size = dc->caps.mall_size_total;
1112e74c8a46SJoshua Aberback 	unsigned int cursor_size = 0;
11133e190955SJoshua Aberback 
11143e190955SJoshua Aberback 	if (dc->debug.mall_size_override)
1115b0f5b100SAlvin Lee 		mall_size = 1024 * 1024 * dc->debug.mall_size_override;
1116ca86bbddSJosip Pavic 
111700fa7f03SRodrigo Siqueira 	if (cursor_attr) {
1118b0f5b100SAlvin Lee 		cursor_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size;
1119b0f5b100SAlvin Lee 
1120b0f5b100SAlvin Lee 		switch (cursor_attr->color_format) {
1121b0f5b100SAlvin Lee 		case CURSOR_MODE_MONO:
1122b0f5b100SAlvin Lee 			cursor_size /= 2;
1123b0f5b100SAlvin Lee 			break;
1124b0f5b100SAlvin Lee 		case CURSOR_MODE_COLOR_1BIT_AND:
1125b0f5b100SAlvin Lee 		case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
1126b0f5b100SAlvin Lee 		case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
1127b0f5b100SAlvin Lee 			cursor_size *= 4;
1128b0f5b100SAlvin Lee 			break;
1129b0f5b100SAlvin Lee 
1130b0f5b100SAlvin Lee 		case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
113109a4ec5dSDillon Varone 		case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
1132b0f5b100SAlvin Lee 			cursor_size *= 8;
1133b0f5b100SAlvin Lee 			break;
1134b0f5b100SAlvin Lee 		}
1135b0f5b100SAlvin Lee 	}
113600fa7f03SRodrigo Siqueira 
113700fa7f03SRodrigo Siqueira 	return (surface_size + cursor_size) < mall_size;
113800fa7f03SRodrigo Siqueira }
113900fa7f03SRodrigo Siqueira 
dcn30_hardware_release(struct dc * dc)1140b0f5b100SAlvin Lee void dcn30_hardware_release(struct dc *dc)
114100fa7f03SRodrigo Siqueira {
11423e190955SJoshua Aberback 	bool subvp_in_use = false;
11433e190955SJoshua Aberback 	uint32_t i;
11443e190955SJoshua Aberback 
11453e190955SJoshua Aberback 	dc_dmub_srv_p_state_delegate(dc, false, NULL);
114636f87850SJoshua Aberback 	dc_dmub_setup_subvp_dmub_command(dc, dc->current_state, false);
1147dbf5256bSJoshua Aberback 
1148dbf5256bSJoshua Aberback 	/* SubVP treated the same way as FPO. If driver disable and
1149dbf5256bSJoshua Aberback 	 * we are using a SubVP config, disable and force on DCN side
1150dbf5256bSJoshua Aberback 	 * to prevent P-State hang on driver enable.
1151dbf5256bSJoshua Aberback 	 */
1152dbf5256bSJoshua Aberback 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
1153dbf5256bSJoshua Aberback 		struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
115436f87850SJoshua Aberback 
1155214d72f6SAurabindo Pillai 		if (!pipe->stream)
1156214d72f6SAurabindo Pillai 			continue;
115736f87850SJoshua Aberback 
1158c2fbe663SFelipe Clark 		if (dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_MAIN) {
1159c2fbe663SFelipe Clark 			subvp_in_use = true;
1160c2fbe663SFelipe Clark 			break;
1161c2fbe663SFelipe Clark 		}
1162f583db81SAlvin Lee 	}
116309c8cbedSWesley Chalmers 	/* If pstate unsupported, or still supported
116409c8cbedSWesley Chalmers 	 * by firmware, force it supported by dcn
116509c8cbedSWesley Chalmers 	 */
116609c8cbedSWesley Chalmers 	if (dc->current_state)
1167c2fbe663SFelipe Clark 		if ((!dc->clk_mgr->clks.p_state_change_support || subvp_in_use ||
1168c2fbe663SFelipe Clark 				dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) &&
1169c2fbe663SFelipe Clark 				dc->res_pool->hubbub->funcs->force_pstate_change_control)
1170c2fbe663SFelipe Clark 			dc->res_pool->hubbub->funcs->force_pstate_change_control(
1171c2fbe663SFelipe Clark 					dc->res_pool->hubbub, true, true);
1172c2fbe663SFelipe Clark }
11733b6df06fSWesley Chalmers 
dcn30_set_disp_pattern_generator(const struct dc * dc,struct pipe_ctx * pipe_ctx,enum controller_dp_test_pattern test_pattern,enum controller_dp_color_space color_space,enum dc_color_depth color_depth,const struct tg_color * solid_color,int width,int height,int offset)1174f583db81SAlvin Lee void dcn30_set_disp_pattern_generator(const struct dc *dc,
1175f583db81SAlvin Lee 		struct pipe_ctx *pipe_ctx,
1176c2fbe663SFelipe Clark 		enum controller_dp_test_pattern test_pattern,
1177 		enum controller_dp_color_space color_space,
1178 		enum dc_color_depth color_depth,
1179 		const struct tg_color *solid_color,
1180 		int width, int height, int offset)
1181 {
1182 	pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
1183 			color_space, color_depth, solid_color, width, height, offset);
1184 }
1185 
dcn30_prepare_bandwidth(struct dc * dc,struct dc_state * context)1186 void dcn30_prepare_bandwidth(struct dc *dc,
1187 	struct dc_state *context)
1188 {
1189 	if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching && !dc->clk_mgr->clks.fw_based_mclk_switching) {
1190 		dc->optimized_required = true;
1191 		context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
1192 	}
1193 
1194 	if (dc->clk_mgr->dc_mode_softmax_enabled)
1195 		if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
1196 				context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
1197 			dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
1198 
1199 	dcn20_prepare_bandwidth(dc, context);
1200 
1201 	if (!dc->clk_mgr->clks.fw_based_mclk_switching)
1202 		dc_dmub_srv_p_state_delegate(dc, false, context);
1203 }
1204 
dcn30_wait_for_all_pending_updates(const struct pipe_ctx * pipe_ctx)1205 void dcn30_wait_for_all_pending_updates(const struct pipe_ctx *pipe_ctx)
1206 {
1207 	struct timing_generator *tg = pipe_ctx->stream_res.tg;
1208 	bool pending_updates = false;
1209 	unsigned int i;
1210 
1211 	if (tg && tg->funcs->is_tg_enabled(tg)) {
1212 		// Poll for 100ms maximum
1213 		for (i = 0; i < 100000; i++) {
1214 			pending_updates = false;
1215 			if (tg->funcs->get_optc_double_buffer_pending)
1216 				pending_updates |= tg->funcs->get_optc_double_buffer_pending(tg);
1217 
1218 			if (tg->funcs->get_otg_double_buffer_pending)
1219 				pending_updates |= tg->funcs->get_otg_double_buffer_pending(tg);
1220 
1221 			if (tg->funcs->get_pipe_update_pending && pipe_ctx->plane_state)
1222 				pending_updates |= tg->funcs->get_pipe_update_pending(tg);
1223 
1224 			if (!pending_updates)
1225 				break;
1226 
1227 			udelay(1);
1228 		}
1229 	}
1230 }
1231 
dcn30_get_underflow_debug_data(const struct dc * dc,struct timing_generator * tg,struct dc_underflow_debug_data * out_data)1232 void dcn30_get_underflow_debug_data(const struct dc *dc,
1233 	struct timing_generator *tg,
1234 	struct dc_underflow_debug_data *out_data)
1235 {
1236 	struct hubbub *hubbub = dc->res_pool->hubbub;
1237 
1238 	if (tg) {
1239 		uint32_t v_blank_start = 0, v_blank_end = 0;
1240 
1241 		out_data->otg_inst = tg->inst;
1242 
1243 		tg->funcs->get_scanoutpos(tg,
1244 					  &v_blank_start,
1245 					  &v_blank_end,
1246 					  &out_data->h_position,
1247 					  &out_data->v_position);
1248 
1249 		out_data->otg_frame_count = tg->funcs->get_frame_count(tg);
1250 
1251 		out_data->otg_underflow = tg->funcs->is_optc_underflow_occurred(tg);
1252 	}
1253 
1254 	for (int i = 0; i < MAX_PIPES; i++) {
1255 		struct hubp *hubp = dc->res_pool->hubps[i];
1256 
1257 		if (hubp) {
1258 			if (hubp->funcs->hubp_get_underflow_status)
1259 				out_data->hubps[i].hubp_underflow = hubp->funcs->hubp_get_underflow_status(hubp);
1260 
1261 			if (hubp->funcs->hubp_in_blank)
1262 				out_data->hubps[i].hubp_in_blank = hubp->funcs->hubp_in_blank(hubp);
1263 
1264 			if (hubp->funcs->hubp_get_current_read_line)
1265 				out_data->hubps[i].hubp_readline = hubp->funcs->hubp_get_current_read_line(hubp);
1266 
1267 			if (hubp->funcs->hubp_get_det_config_error)
1268 				out_data->hubps[i].det_config_error = hubp->funcs->hubp_get_det_config_error(hubp);
1269 		}
1270 	}
1271 
1272 	if (hubbub->funcs->get_det_sizes)
1273 		hubbub->funcs->get_det_sizes(hubbub, out_data->curr_det_sizes, out_data->target_det_sizes);
1274 
1275 	if (hubbub->funcs->compbuf_config_error)
1276 		out_data->compbuf_config_error = hubbub->funcs->compbuf_config_error(hubbub);
1277 
1278 }
1279