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"
34d99f1387SBhawanpreet Lakha #include "dcn30_mpc.h"
35d99f1387SBhawanpreet Lakha #include "dcn30_dpp.h"
36d99f1387SBhawanpreet Lakha #include "dcn10/dcn10_cm_common.h"
37d99f1387SBhawanpreet Lakha #include "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"
51c2fbe663SFelipe Clark #include "../dcn20/dcn20_hwseq.h"
52c2fbe663SFelipe Clark #include "dcn30_resource.h"
536ca7415fSWenjing Liu #include "link.h"
54d99f1387SBhawanpreet Lakha 
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_set_blend_lut(struct pipe_ctx * pipe_ctx,const struct dc_plane_state * plane_state)72d99f1387SBhawanpreet Lakha bool dcn30_set_blend_lut(
73d99f1387SBhawanpreet Lakha 	struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
74d99f1387SBhawanpreet Lakha {
75d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
76d99f1387SBhawanpreet Lakha 	bool result = true;
77d99f1387SBhawanpreet Lakha 	struct pwl_params *blend_lut = NULL;
78d99f1387SBhawanpreet Lakha 
79d99f1387SBhawanpreet Lakha 	if (plane_state->blend_tf) {
80d99f1387SBhawanpreet Lakha 		if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
81d99f1387SBhawanpreet Lakha 			blend_lut = &plane_state->blend_tf->pwl;
82d99f1387SBhawanpreet Lakha 		else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
83d99f1387SBhawanpreet Lakha 			cm3_helper_translate_curve_to_hw_format(
84d99f1387SBhawanpreet Lakha 					plane_state->blend_tf, &dpp_base->regamma_params, false);
85d99f1387SBhawanpreet Lakha 			blend_lut = &dpp_base->regamma_params;
86d99f1387SBhawanpreet Lakha 		}
87d99f1387SBhawanpreet Lakha 	}
88d99f1387SBhawanpreet Lakha 	result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
89d99f1387SBhawanpreet Lakha 
90d99f1387SBhawanpreet Lakha 	return result;
91d99f1387SBhawanpreet Lakha }
92d99f1387SBhawanpreet Lakha 
dcn30_set_mpc_shaper_3dlut(struct pipe_ctx * pipe_ctx,const struct dc_stream_state * stream)9394369589SMelissa Wen static bool dcn30_set_mpc_shaper_3dlut(struct pipe_ctx *pipe_ctx,
9494369589SMelissa Wen 				       const struct dc_stream_state *stream)
95d99f1387SBhawanpreet Lakha {
96d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
97d99f1387SBhawanpreet Lakha 	int mpcc_id = pipe_ctx->plane_res.hubp->inst;
98d99f1387SBhawanpreet Lakha 	struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
99d99f1387SBhawanpreet Lakha 	bool result = false;
100d99f1387SBhawanpreet Lakha 	int acquired_rmu = 0;
101d99f1387SBhawanpreet Lakha 	int mpcc_id_projected = 0;
102d99f1387SBhawanpreet Lakha 
103d99f1387SBhawanpreet Lakha 	const struct pwl_params *shaper_lut = NULL;
104d99f1387SBhawanpreet Lakha 	//get the shaper lut params
105d99f1387SBhawanpreet Lakha 	if (stream->func_shaper) {
10694369589SMelissa Wen 		if (stream->func_shaper->type == TF_TYPE_HWPWL) {
107d99f1387SBhawanpreet Lakha 			shaper_lut = &stream->func_shaper->pwl;
10894369589SMelissa Wen 		} else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
10927fc10d1SHarry Wentland 			cm_helper_translate_curve_to_hw_format(stream->ctx, stream->func_shaper,
110d99f1387SBhawanpreet Lakha 							       &dpp_base->shaper_params, true);
111d99f1387SBhawanpreet Lakha 			shaper_lut = &dpp_base->shaper_params;
112d99f1387SBhawanpreet Lakha 		}
113d99f1387SBhawanpreet Lakha 	}
114d99f1387SBhawanpreet Lakha 
115d99f1387SBhawanpreet Lakha 	if (stream->lut3d_func &&
116d99f1387SBhawanpreet Lakha 	    stream->lut3d_func->state.bits.initialized == 1 &&
117d99f1387SBhawanpreet Lakha 	    stream->lut3d_func->state.bits.rmu_idx_valid == 1) {
118d99f1387SBhawanpreet Lakha 		if (stream->lut3d_func->state.bits.rmu_mux_num == 0)
119d99f1387SBhawanpreet Lakha 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu0_mux;
120d99f1387SBhawanpreet Lakha 		else if (stream->lut3d_func->state.bits.rmu_mux_num == 1)
121d99f1387SBhawanpreet Lakha 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu1_mux;
122d99f1387SBhawanpreet Lakha 		else if (stream->lut3d_func->state.bits.rmu_mux_num == 2)
123d99f1387SBhawanpreet Lakha 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu2_mux;
124d99f1387SBhawanpreet Lakha 		if (mpcc_id_projected != mpcc_id)
125d99f1387SBhawanpreet Lakha 			BREAK_TO_DEBUGGER();
12694369589SMelissa Wen 		/* find the reason why logical layer assigned a different
12794369589SMelissa Wen 		 * mpcc_id into acquire_post_bldn_3dlut
12894369589SMelissa Wen 		 */
129d99f1387SBhawanpreet Lakha 		acquired_rmu = mpc->funcs->acquire_rmu(mpc, mpcc_id,
130d99f1387SBhawanpreet Lakha 						       stream->lut3d_func->state.bits.rmu_mux_num);
131d99f1387SBhawanpreet Lakha 		if (acquired_rmu != stream->lut3d_func->state.bits.rmu_mux_num)
132d99f1387SBhawanpreet Lakha 			BREAK_TO_DEBUGGER();
13394369589SMelissa Wen 
13494369589SMelissa Wen 		result = mpc->funcs->program_3dlut(mpc, &stream->lut3d_func->lut_3d,
135d99f1387SBhawanpreet Lakha 						   stream->lut3d_func->state.bits.rmu_mux_num);
136d99f1387SBhawanpreet Lakha 		result = mpc->funcs->program_shaper(mpc, shaper_lut,
137d99f1387SBhawanpreet Lakha 						    stream->lut3d_func->state.bits.rmu_mux_num);
13894369589SMelissa Wen 	} else {
13994369589SMelissa Wen 		// loop through the available mux and release the requested mpcc_id
140d99f1387SBhawanpreet Lakha 		mpc->funcs->release_rmu(mpc, mpcc_id);
14194369589SMelissa Wen 	}
142d99f1387SBhawanpreet Lakha 
143d99f1387SBhawanpreet Lakha 	return result;
144d99f1387SBhawanpreet Lakha }
145d99f1387SBhawanpreet Lakha 
dcn30_set_input_transfer_func(struct dc * dc,struct pipe_ctx * pipe_ctx,const struct dc_plane_state * plane_state)146d99f1387SBhawanpreet Lakha bool dcn30_set_input_transfer_func(struct dc *dc,
147d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx,
148d99f1387SBhawanpreet Lakha 				const struct dc_plane_state *plane_state)
149d99f1387SBhawanpreet Lakha {
150d99f1387SBhawanpreet Lakha 	struct dce_hwseq *hws = dc->hwseq;
151d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
152d99f1387SBhawanpreet Lakha 	enum dc_transfer_func_predefined tf;
153d99f1387SBhawanpreet Lakha 	bool result = true;
154d99f1387SBhawanpreet Lakha 	struct pwl_params *params = NULL;
155d99f1387SBhawanpreet Lakha 
156d99f1387SBhawanpreet Lakha 	if (dpp_base == NULL || plane_state == NULL)
157d99f1387SBhawanpreet Lakha 		return false;
158d99f1387SBhawanpreet Lakha 
159d99f1387SBhawanpreet Lakha 	tf = TRANSFER_FUNCTION_UNITY;
160d99f1387SBhawanpreet Lakha 
161d99f1387SBhawanpreet Lakha 	if (plane_state->in_transfer_func &&
162d99f1387SBhawanpreet Lakha 		plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED)
163d99f1387SBhawanpreet Lakha 		tf = plane_state->in_transfer_func->tf;
164d99f1387SBhawanpreet Lakha 
165d99f1387SBhawanpreet Lakha 	dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
166d99f1387SBhawanpreet Lakha 
167d99f1387SBhawanpreet Lakha 	if (plane_state->in_transfer_func) {
168d99f1387SBhawanpreet Lakha 		if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL)
169d99f1387SBhawanpreet Lakha 			params = &plane_state->in_transfer_func->pwl;
170d99f1387SBhawanpreet Lakha 		else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS &&
171d99f1387SBhawanpreet Lakha 			cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func,
172d99f1387SBhawanpreet Lakha 					&dpp_base->degamma_params, false))
173d99f1387SBhawanpreet Lakha 			params = &dpp_base->degamma_params;
174d99f1387SBhawanpreet Lakha 	}
175d99f1387SBhawanpreet Lakha 
176d99f1387SBhawanpreet Lakha 	result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
177d99f1387SBhawanpreet Lakha 
178d99f1387SBhawanpreet Lakha 	if (pipe_ctx->stream_res.opp && pipe_ctx->stream_res.opp->ctx) {
179d99f1387SBhawanpreet Lakha 		if (dpp_base->funcs->dpp_program_blnd_lut)
180d99f1387SBhawanpreet Lakha 			hws->funcs.set_blend_lut(pipe_ctx, plane_state);
181d99f1387SBhawanpreet Lakha 		if (dpp_base->funcs->dpp_program_shaper_lut &&
182d99f1387SBhawanpreet Lakha 				dpp_base->funcs->dpp_program_3dlut)
183d99f1387SBhawanpreet Lakha 			hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state);
184d99f1387SBhawanpreet Lakha 	}
185d99f1387SBhawanpreet Lakha 
186d99f1387SBhawanpreet Lakha 	return result;
187d99f1387SBhawanpreet Lakha }
188d99f1387SBhawanpreet Lakha 
dcn30_set_output_transfer_func(struct dc * dc,struct pipe_ctx * pipe_ctx,const struct dc_stream_state * stream)189d99f1387SBhawanpreet Lakha bool dcn30_set_output_transfer_func(struct dc *dc,
190d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx,
191d99f1387SBhawanpreet Lakha 				const struct dc_stream_state *stream)
192d99f1387SBhawanpreet Lakha {
193d99f1387SBhawanpreet Lakha 	int mpcc_id = pipe_ctx->plane_res.hubp->inst;
194d99f1387SBhawanpreet Lakha 	struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
195d99f1387SBhawanpreet Lakha 	struct pwl_params *params = NULL;
196d99f1387SBhawanpreet Lakha 	bool ret = false;
197d99f1387SBhawanpreet Lakha 
198d99f1387SBhawanpreet Lakha 	/* program OGAM or 3DLUT only for the top pipe*/
199d99f1387SBhawanpreet Lakha 	if (pipe_ctx->top_pipe == NULL) {
200d99f1387SBhawanpreet Lakha 		/*program rmu shaper and 3dlut in MPC*/
201d99f1387SBhawanpreet Lakha 		ret = dcn30_set_mpc_shaper_3dlut(pipe_ctx, stream);
202d99f1387SBhawanpreet Lakha 		if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
203d99f1387SBhawanpreet Lakha 			if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
204d99f1387SBhawanpreet Lakha 				params = &stream->out_transfer_func->pwl;
205d99f1387SBhawanpreet Lakha 			else if (pipe_ctx->stream->out_transfer_func->type ==
206d99f1387SBhawanpreet Lakha 					TF_TYPE_DISTRIBUTED_POINTS &&
207d99f1387SBhawanpreet Lakha 					cm3_helper_translate_curve_to_hw_format(
208d99f1387SBhawanpreet Lakha 					stream->out_transfer_func,
209d99f1387SBhawanpreet Lakha 					&mpc->blender_params, false))
210d99f1387SBhawanpreet Lakha 				params = &mpc->blender_params;
211d99f1387SBhawanpreet Lakha 			 /* there are no ROM LUTs in OUTGAM */
212d99f1387SBhawanpreet Lakha 			if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
213d99f1387SBhawanpreet Lakha 				BREAK_TO_DEBUGGER();
214d99f1387SBhawanpreet Lakha 		}
215d99f1387SBhawanpreet Lakha 	}
216d99f1387SBhawanpreet Lakha 
217d99f1387SBhawanpreet Lakha 	mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
218d99f1387SBhawanpreet Lakha 	return ret;
219d99f1387SBhawanpreet Lakha }
220d99f1387SBhawanpreet Lakha 
dcn30_set_writeback(struct dc * dc,struct dc_writeback_info * wb_info,struct dc_state * context)221d99f1387SBhawanpreet Lakha static void dcn30_set_writeback(
222d99f1387SBhawanpreet Lakha 		struct dc *dc,
223d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
224d99f1387SBhawanpreet Lakha 		struct dc_state *context)
225d99f1387SBhawanpreet Lakha {
226d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
227d99f1387SBhawanpreet Lakha 	struct mcif_buf_params *mcif_buf_params;
228d99f1387SBhawanpreet Lakha 
229d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES);
230d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->wb_enabled);
231d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->mpcc_inst >= 0);
2320b02e1fdSJoshua Aberback 	ASSERT(wb_info->mpcc_inst < dc->res_pool->mpcc_count);
233d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
234d99f1387SBhawanpreet Lakha 	mcif_buf_params = &wb_info->mcif_buf_params;
235d99f1387SBhawanpreet Lakha 
236d99f1387SBhawanpreet Lakha 	/* set DWB MPC mux */
237d99f1387SBhawanpreet Lakha 	dc->res_pool->mpc->funcs->set_dwb_mux(dc->res_pool->mpc,
238d99f1387SBhawanpreet Lakha 			wb_info->dwb_pipe_inst, wb_info->mpcc_inst);
239d99f1387SBhawanpreet Lakha 	/* set MCIF_WB buffer and arbitration configuration */
240d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->config_mcif_buf(mcif_wb, mcif_buf_params, wb_info->dwb_params.dest_height);
241d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
242d99f1387SBhawanpreet Lakha }
243d99f1387SBhawanpreet Lakha 
dcn30_update_writeback(struct dc * dc,struct dc_writeback_info * wb_info,struct dc_state * context)244d99f1387SBhawanpreet Lakha void dcn30_update_writeback(
245d99f1387SBhawanpreet Lakha 		struct dc *dc,
246d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
247d99f1387SBhawanpreet Lakha 		struct dc_state *context)
248d99f1387SBhawanpreet Lakha {
249d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
250d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
251d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
252d99f1387SBhawanpreet Lakha 		__func__, wb_info->dwb_pipe_inst,\
253d99f1387SBhawanpreet Lakha 		wb_info->mpcc_inst);
254d99f1387SBhawanpreet Lakha 
255d99f1387SBhawanpreet Lakha 	dcn30_set_writeback(dc, wb_info, context);
256d99f1387SBhawanpreet Lakha 
257d99f1387SBhawanpreet Lakha 	/* update DWB */
258d99f1387SBhawanpreet Lakha 	dwb->funcs->update(dwb, &wb_info->dwb_params);
259d99f1387SBhawanpreet Lakha }
260d99f1387SBhawanpreet Lakha 
dcn30_mmhubbub_warmup(struct dc * dc,unsigned int num_dwb,struct dc_writeback_info * wb_info)261d99f1387SBhawanpreet Lakha bool dcn30_mmhubbub_warmup(
262d99f1387SBhawanpreet Lakha 	struct dc *dc,
263d99f1387SBhawanpreet Lakha 	unsigned int num_dwb,
264d99f1387SBhawanpreet Lakha 	struct dc_writeback_info *wb_info)
265d99f1387SBhawanpreet Lakha {
266d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
267d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
268d99f1387SBhawanpreet Lakha 	struct mcif_warmup_params warmup_params = {0};
269d99f1387SBhawanpreet Lakha 	unsigned int  i, i_buf;
270d99f1387SBhawanpreet Lakha 	/*make sure there is no active DWB eanbled */
271d99f1387SBhawanpreet Lakha 	for (i = 0; i < num_dwb; i++) {
272d99f1387SBhawanpreet Lakha 		dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst];
273d99f1387SBhawanpreet Lakha 		if (dwb->dwb_is_efc_transition || dwb->dwb_is_drc) {
274d99f1387SBhawanpreet Lakha 			/*can not do warmup while any dwb enabled*/
275d99f1387SBhawanpreet Lakha 			return false;
276d99f1387SBhawanpreet Lakha 		}
277d99f1387SBhawanpreet Lakha 	}
278d99f1387SBhawanpreet Lakha 
279d99f1387SBhawanpreet Lakha 	if (wb_info->mcif_warmup_params.p_vmid == 0)
280d99f1387SBhawanpreet Lakha 		return false;
281d99f1387SBhawanpreet Lakha 
282d99f1387SBhawanpreet Lakha 	/*check whether this is new interface: warmup big buffer once*/
283d99f1387SBhawanpreet Lakha 	if (wb_info->mcif_warmup_params.start_address.quad_part != 0 &&
284d99f1387SBhawanpreet Lakha 		wb_info->mcif_warmup_params.region_size != 0) {
285d99f1387SBhawanpreet Lakha 		/*mmhubbub is shared, so it does not matter which MCIF*/
286d99f1387SBhawanpreet Lakha 		mcif_wb = dc->res_pool->mcif_wb[0];
287d99f1387SBhawanpreet Lakha 		/*warmup a big chunk of VM buffer at once*/
288d99f1387SBhawanpreet Lakha 		warmup_params.start_address.quad_part = wb_info->mcif_warmup_params.start_address.quad_part;
289d99f1387SBhawanpreet Lakha 		warmup_params.address_increment =  wb_info->mcif_warmup_params.region_size;
290d99f1387SBhawanpreet Lakha 		warmup_params.region_size = wb_info->mcif_warmup_params.region_size;
291d99f1387SBhawanpreet Lakha 		warmup_params.p_vmid = wb_info->mcif_warmup_params.p_vmid;
292d99f1387SBhawanpreet Lakha 
293d99f1387SBhawanpreet Lakha 		if (warmup_params.address_increment == 0)
294d99f1387SBhawanpreet Lakha 			warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes;
295d99f1387SBhawanpreet Lakha 
296d99f1387SBhawanpreet Lakha 		mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params);
297d99f1387SBhawanpreet Lakha 		return true;
298d99f1387SBhawanpreet Lakha 	}
299d99f1387SBhawanpreet Lakha 	/*following is the original: warmup each DWB's mcif buffer*/
300d99f1387SBhawanpreet Lakha 	for (i = 0; i < num_dwb; i++) {
301d99f1387SBhawanpreet Lakha 		dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst];
302d99f1387SBhawanpreet Lakha 		mcif_wb = dc->res_pool->mcif_wb[wb_info[i].dwb_pipe_inst];
303d99f1387SBhawanpreet Lakha 		/*warmup is for VM mode only*/
304d99f1387SBhawanpreet Lakha 		if (wb_info[i].mcif_buf_params.p_vmid == 0)
305d99f1387SBhawanpreet Lakha 			return false;
306d99f1387SBhawanpreet Lakha 
307d99f1387SBhawanpreet Lakha 		/* Warmup MCIF_WB */
308d99f1387SBhawanpreet Lakha 		for (i_buf = 0; i_buf < MCIF_BUF_COUNT; i_buf++) {
309d99f1387SBhawanpreet Lakha 			warmup_params.start_address.quad_part = wb_info[i].mcif_buf_params.luma_address[i_buf];
310d99f1387SBhawanpreet Lakha 			warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes;
311d99f1387SBhawanpreet Lakha 			warmup_params.region_size = wb_info[i].mcif_buf_params.luma_pitch * wb_info[i].dwb_params.dest_height;
312d99f1387SBhawanpreet Lakha 			warmup_params.p_vmid = wb_info[i].mcif_buf_params.p_vmid;
313d99f1387SBhawanpreet Lakha 			mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params);
314d99f1387SBhawanpreet Lakha 		}
315d99f1387SBhawanpreet Lakha 	}
316d99f1387SBhawanpreet Lakha 	return true;
317d99f1387SBhawanpreet Lakha }
318d99f1387SBhawanpreet Lakha 
dcn30_enable_writeback(struct dc * dc,struct dc_writeback_info * wb_info,struct dc_state * context)319d99f1387SBhawanpreet Lakha void dcn30_enable_writeback(
320d99f1387SBhawanpreet Lakha 		struct dc *dc,
321d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
322d99f1387SBhawanpreet Lakha 		struct dc_state *context)
323d99f1387SBhawanpreet Lakha {
324d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
325d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
326d99f1387SBhawanpreet Lakha 
327d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
328d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
329d99f1387SBhawanpreet Lakha 
330d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
331d99f1387SBhawanpreet Lakha 		__func__, wb_info->dwb_pipe_inst,\
332d99f1387SBhawanpreet Lakha 		wb_info->mpcc_inst);
333d99f1387SBhawanpreet Lakha 	/* Update writeback pipe */
334d99f1387SBhawanpreet Lakha 	dcn30_set_writeback(dc, wb_info, context);
335d99f1387SBhawanpreet Lakha 
336d99f1387SBhawanpreet Lakha 	/* Enable MCIF_WB */
337d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->enable_mcif(mcif_wb);
338d99f1387SBhawanpreet Lakha 	/* Enable DWB */
339d99f1387SBhawanpreet Lakha 	dwb->funcs->enable(dwb, &wb_info->dwb_params);
340d99f1387SBhawanpreet Lakha }
341d99f1387SBhawanpreet Lakha 
dcn30_disable_writeback(struct dc * dc,unsigned int dwb_pipe_inst)342d99f1387SBhawanpreet Lakha void dcn30_disable_writeback(
343d99f1387SBhawanpreet Lakha 		struct dc *dc,
344d99f1387SBhawanpreet Lakha 		unsigned int dwb_pipe_inst)
345d99f1387SBhawanpreet Lakha {
346d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
347d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
348d99f1387SBhawanpreet Lakha 
349d99f1387SBhawanpreet Lakha 	ASSERT(dwb_pipe_inst < MAX_DWB_PIPES);
350d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[dwb_pipe_inst];
351d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst];
352d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d",\
353d99f1387SBhawanpreet Lakha 		__func__, dwb_pipe_inst);
354d99f1387SBhawanpreet Lakha 
355d99f1387SBhawanpreet Lakha 	/* disable DWB */
356d99f1387SBhawanpreet Lakha 	dwb->funcs->disable(dwb);
357d99f1387SBhawanpreet Lakha 	/* disable MCIF */
358d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->disable_mcif(mcif_wb);
359d99f1387SBhawanpreet Lakha 	/* disable MPC DWB mux */
360d99f1387SBhawanpreet Lakha 	dc->res_pool->mpc->funcs->disable_dwb_mux(dc->res_pool->mpc, dwb_pipe_inst);
361d99f1387SBhawanpreet Lakha }
362d99f1387SBhawanpreet Lakha 
dcn30_program_all_writeback_pipes_in_tree(struct dc * dc,const struct dc_stream_state * stream,struct dc_state * context)363d99f1387SBhawanpreet Lakha void dcn30_program_all_writeback_pipes_in_tree(
364d99f1387SBhawanpreet Lakha 		struct dc *dc,
365d99f1387SBhawanpreet Lakha 		const struct dc_stream_state *stream,
366d99f1387SBhawanpreet Lakha 		struct dc_state *context)
367d99f1387SBhawanpreet Lakha {
368d99f1387SBhawanpreet Lakha 	struct dc_writeback_info wb_info;
369d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
370d99f1387SBhawanpreet Lakha 	struct dc_stream_status *stream_status = NULL;
371d99f1387SBhawanpreet Lakha 	int i_wb, i_pipe, i_stream;
372d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s", __func__);
373d99f1387SBhawanpreet Lakha 
374d99f1387SBhawanpreet Lakha 	ASSERT(stream);
375d99f1387SBhawanpreet Lakha 	for (i_stream = 0; i_stream < context->stream_count; i_stream++) {
376d99f1387SBhawanpreet Lakha 		if (context->streams[i_stream] == stream) {
377d99f1387SBhawanpreet Lakha 			stream_status = &context->stream_status[i_stream];
378d99f1387SBhawanpreet Lakha 			break;
379d99f1387SBhawanpreet Lakha 		}
380d99f1387SBhawanpreet Lakha 	}
381d99f1387SBhawanpreet Lakha 	ASSERT(stream_status);
382d99f1387SBhawanpreet Lakha 
383d99f1387SBhawanpreet Lakha 	ASSERT(stream->num_wb_info <= dc->res_pool->res_cap->num_dwb);
384d99f1387SBhawanpreet Lakha 	/* For each writeback pipe */
385d99f1387SBhawanpreet Lakha 	for (i_wb = 0; i_wb < stream->num_wb_info; i_wb++) {
386d99f1387SBhawanpreet Lakha 
387d99f1387SBhawanpreet Lakha 		/* copy writeback info to local non-const so mpcc_inst can be set */
388d99f1387SBhawanpreet Lakha 		wb_info = stream->writeback_info[i_wb];
389d99f1387SBhawanpreet Lakha 		if (wb_info.wb_enabled) {
390d99f1387SBhawanpreet Lakha 
391d99f1387SBhawanpreet Lakha 			/* get the MPCC instance for writeback_source_plane */
392d99f1387SBhawanpreet Lakha 			wb_info.mpcc_inst = -1;
393d99f1387SBhawanpreet Lakha 			for (i_pipe = 0; i_pipe < dc->res_pool->pipe_count; i_pipe++) {
394d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i_pipe];
395d99f1387SBhawanpreet Lakha 
39682367e7fSRoy Chan 				if (!pipe_ctx->plane_state)
39782367e7fSRoy Chan 					continue;
39882367e7fSRoy Chan 
399d99f1387SBhawanpreet Lakha 				if (pipe_ctx->plane_state == wb_info.writeback_source_plane) {
400d99f1387SBhawanpreet Lakha 					wb_info.mpcc_inst = pipe_ctx->plane_res.mpcc_inst;
401d99f1387SBhawanpreet Lakha 					break;
402d99f1387SBhawanpreet Lakha 				}
403d99f1387SBhawanpreet Lakha 			}
40482367e7fSRoy Chan 
40582367e7fSRoy Chan 			if (wb_info.mpcc_inst == -1) {
40682367e7fSRoy Chan 				/* Disable writeback pipe and disconnect from MPCC
40782367e7fSRoy Chan 				 * if source plane has been removed
40882367e7fSRoy Chan 				 */
40982367e7fSRoy Chan 				dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst);
41082367e7fSRoy Chan 				continue;
41182367e7fSRoy Chan 			}
412d99f1387SBhawanpreet Lakha 
413d99f1387SBhawanpreet Lakha 			ASSERT(wb_info.dwb_pipe_inst < dc->res_pool->res_cap->num_dwb);
414d99f1387SBhawanpreet Lakha 			dwb = dc->res_pool->dwbc[wb_info.dwb_pipe_inst];
415d99f1387SBhawanpreet Lakha 			if (dwb->funcs->is_enabled(dwb)) {
416d99f1387SBhawanpreet Lakha 				/* writeback pipe already enabled, only need to update */
417d99f1387SBhawanpreet Lakha 				dc->hwss.update_writeback(dc, &wb_info, context);
418d99f1387SBhawanpreet Lakha 			} else {
419d99f1387SBhawanpreet Lakha 				/* Enable writeback pipe and connect to MPCC */
420d99f1387SBhawanpreet Lakha 				dc->hwss.enable_writeback(dc, &wb_info, context);
421d99f1387SBhawanpreet Lakha 			}
422d99f1387SBhawanpreet Lakha 		} else {
423d99f1387SBhawanpreet Lakha 			/* Disable writeback pipe and disconnect from MPCC */
424d99f1387SBhawanpreet Lakha 			dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst);
425d99f1387SBhawanpreet Lakha 		}
426d99f1387SBhawanpreet Lakha 	}
427d99f1387SBhawanpreet Lakha }
428d99f1387SBhawanpreet Lakha 
dcn30_init_hw(struct dc * dc)429d99f1387SBhawanpreet Lakha void dcn30_init_hw(struct dc *dc)
430d99f1387SBhawanpreet Lakha {
431d99f1387SBhawanpreet Lakha 	struct abm **abms = dc->res_pool->multiple_abms;
432d99f1387SBhawanpreet Lakha 	struct dce_hwseq *hws = dc->hwseq;
433d99f1387SBhawanpreet Lakha 	struct dc_bios *dcb = dc->ctx->dc_bios;
434d99f1387SBhawanpreet Lakha 	struct resource_pool *res_pool = dc->res_pool;
435ebd1e719SLeo (Hanghong) Ma 	int i;
43645a1261bSJake Wang 	int edp_num;
437d99f1387SBhawanpreet Lakha 	uint32_t backlight = MAX_BACKLIGHT_LEVEL;
438d99f1387SBhawanpreet Lakha 
439d99f1387SBhawanpreet Lakha 	if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
440d99f1387SBhawanpreet Lakha 		dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
441d99f1387SBhawanpreet Lakha 
442d99f1387SBhawanpreet Lakha 	// Initialize the dccg
443d99f1387SBhawanpreet Lakha 	if (res_pool->dccg->funcs->dccg_init)
444d99f1387SBhawanpreet Lakha 		res_pool->dccg->funcs->dccg_init(res_pool->dccg);
445d99f1387SBhawanpreet Lakha 
446d99f1387SBhawanpreet Lakha 	if (!dcb->funcs->is_accelerated_mode(dcb)) {
447d99f1387SBhawanpreet Lakha 		hws->funcs.bios_golden_init(dc);
448d99f1387SBhawanpreet Lakha 		hws->funcs.disable_vga(dc->hwseq);
449d99f1387SBhawanpreet Lakha 	}
450d99f1387SBhawanpreet Lakha 
45196879ad3SJacky Liao 	if (dc->debug.enable_mem_low_power.bits.dmcu) {
45296879ad3SJacky Liao 		// Force ERAM to shutdown if DMCU is not enabled
45396879ad3SJacky Liao 		if (dc->debug.disable_dmcu || dc->config.disable_dmcu) {
45496879ad3SJacky Liao 			REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3);
45596879ad3SJacky Liao 		}
45696879ad3SJacky Liao 	}
45796879ad3SJacky Liao 
458cae78e03SJacky Liao 	// Set default OPTC memory power states
459cae78e03SJacky Liao 	if (dc->debug.enable_mem_low_power.bits.optc) {
460cae78e03SJacky Liao 		// Shutdown when unassigned and light sleep in VBLANK
461cae78e03SJacky Liao 		REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
462cae78e03SJacky Liao 	}
463cae78e03SJacky Liao 
46439619d50SAurabindo Pillai 	if (dc->debug.enable_mem_low_power.bits.vga) {
46539619d50SAurabindo Pillai 		// Power down VGA memory
46639619d50SAurabindo Pillai 		REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
46739619d50SAurabindo Pillai 	}
46839619d50SAurabindo Pillai 
469d99f1387SBhawanpreet Lakha 	if (dc->ctx->dc_bios->fw_info_valid) {
470d99f1387SBhawanpreet Lakha 		res_pool->ref_clocks.xtalin_clock_inKhz =
471d99f1387SBhawanpreet Lakha 				dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
472d99f1387SBhawanpreet Lakha 
473d99f1387SBhawanpreet Lakha 		if (res_pool->dccg && res_pool->hubbub) {
474d99f1387SBhawanpreet Lakha 
475d99f1387SBhawanpreet Lakha 			(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
476d99f1387SBhawanpreet Lakha 					dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
477d99f1387SBhawanpreet Lakha 					&res_pool->ref_clocks.dccg_ref_clock_inKhz);
478d99f1387SBhawanpreet Lakha 
479d99f1387SBhawanpreet Lakha 			(res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
480d99f1387SBhawanpreet Lakha 					res_pool->ref_clocks.dccg_ref_clock_inKhz,
481d99f1387SBhawanpreet Lakha 					&res_pool->ref_clocks.dchub_ref_clock_inKhz);
482d99f1387SBhawanpreet Lakha 		} else {
483d99f1387SBhawanpreet Lakha 			// Not all ASICs have DCCG sw component
484d99f1387SBhawanpreet Lakha 			res_pool->ref_clocks.dccg_ref_clock_inKhz =
485d99f1387SBhawanpreet Lakha 					res_pool->ref_clocks.xtalin_clock_inKhz;
486d99f1387SBhawanpreet Lakha 			res_pool->ref_clocks.dchub_ref_clock_inKhz =
487d99f1387SBhawanpreet Lakha 					res_pool->ref_clocks.xtalin_clock_inKhz;
488d99f1387SBhawanpreet Lakha 		}
489d99f1387SBhawanpreet Lakha 	} else
490d99f1387SBhawanpreet Lakha 		ASSERT_CRITICAL(false);
491d99f1387SBhawanpreet Lakha 
492d99f1387SBhawanpreet Lakha 	for (i = 0; i < dc->link_count; i++) {
493d99f1387SBhawanpreet Lakha 		/* Power up AND update implementation according to the
494d99f1387SBhawanpreet Lakha 		 * required signal (which may be different from the
495d99f1387SBhawanpreet Lakha 		 * default signal on connector).
496d99f1387SBhawanpreet Lakha 		 */
497d99f1387SBhawanpreet Lakha 		struct dc_link *link = dc->links[i];
498d99f1387SBhawanpreet Lakha 
499d99f1387SBhawanpreet Lakha 		link->link_enc->funcs->hw_init(link->link_enc);
5000f782777SMartin Leung 
5010f782777SMartin Leung 		/* Check for enabled DIG to identify enabled display */
5020f782777SMartin Leung 		if (link->link_enc->funcs->is_dig_enabled &&
50330ffa74aSJingwen Zhu 			link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
5040f782777SMartin Leung 			link->link_status.link_active = true;
50530ffa74aSJingwen Zhu 			if (link->link_enc->funcs->fec_is_active &&
50630ffa74aSJingwen Zhu 					link->link_enc->funcs->fec_is_active(link->link_enc))
50730ffa74aSJingwen Zhu 				link->fec_state = dc_link_fec_enabled;
50830ffa74aSJingwen Zhu 		}
509d99f1387SBhawanpreet Lakha 	}
510d99f1387SBhawanpreet Lakha 
5110f782777SMartin Leung 	/* we want to turn off all dp displays before doing detection */
51298ce7d32SWenjing Liu 	dc->link_srv->blank_all_dp_displays(dc);
513d99f1387SBhawanpreet Lakha 
514384bd90dSRoman Li 	if (hws->funcs.enable_power_gating_plane)
515384bd90dSRoman Li 		hws->funcs.enable_power_gating_plane(dc->hwseq, true);
516384bd90dSRoman Li 
5170f782777SMartin Leung 	/* If taking control over from VBIOS, we may want to optimize our first
5180f782777SMartin Leung 	 * mode set, so we need to skip powering down pipes until we know which
5190f782777SMartin Leung 	 * pipes we want to use.
5200f782777SMartin Leung 	 * Otherwise, if taking control is not possible, we need to power
5210f782777SMartin Leung 	 * everything down.
5220f782777SMartin Leung 	 */
5237aba117aSJarif Aftab 	if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
5240f782777SMartin Leung 		hws->funcs.init_pipes(dc, dc->current_state);
5250f782777SMartin Leung 		if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
5260f782777SMartin Leung 			dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
5270f782777SMartin Leung 					!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
528d99f1387SBhawanpreet Lakha 	}
529d99f1387SBhawanpreet Lakha 
5300f782777SMartin Leung 	/* In headless boot cases, DIG may be turned
5310f782777SMartin Leung 	 * on which causes HW/SW discrepancies.
5320f782777SMartin Leung 	 * To avoid this, power down hardware on boot
5330f782777SMartin Leung 	 * if DIG is turned on and seamless boot not enabled
5340f782777SMartin Leung 	 */
5357aba117aSJarif Aftab 	if (!dc->config.seamless_boot_edp_requested) {
53645a1261bSJake Wang 		struct dc_link *edp_links[MAX_NUM_EDP];
5373addbde2SJake Wang 		struct dc_link *edp_link = NULL;
538d99f1387SBhawanpreet Lakha 
5397ae1dbe6SWenjing Liu 		dc_get_edp_links(dc, edp_links, &edp_num);
5403addbde2SJake Wang 		if (edp_num)
5413addbde2SJake Wang 			edp_link = edp_links[0];
5423addbde2SJake Wang 		if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
5430f782777SMartin Leung 				edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
5440f782777SMartin Leung 				dc->hwss.edp_backlight_control &&
5450f782777SMartin Leung 				dc->hwss.power_down &&
5460f782777SMartin Leung 				dc->hwss.edp_power_control) {
5470f782777SMartin Leung 			dc->hwss.edp_backlight_control(edp_link, false);
5480f782777SMartin Leung 			dc->hwss.power_down(dc);
5490f782777SMartin Leung 			dc->hwss.edp_power_control(edp_link, false);
5500f782777SMartin Leung 		} else {
5510f782777SMartin Leung 			for (i = 0; i < dc->link_count; i++) {
5520f782777SMartin Leung 				struct dc_link *link = dc->links[i];
5530f782777SMartin Leung 
5540f782777SMartin Leung 				if (link->link_enc->funcs->is_dig_enabled &&
5550f782777SMartin Leung 						link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
5560f782777SMartin Leung 						dc->hwss.power_down) {
5570f782777SMartin Leung 					dc->hwss.power_down(dc);
5580f782777SMartin Leung 					break;
559d99f1387SBhawanpreet Lakha 				}
560d99f1387SBhawanpreet Lakha 
561d99f1387SBhawanpreet Lakha 			}
562d99f1387SBhawanpreet Lakha 		}
563d99f1387SBhawanpreet Lakha 	}
564d99f1387SBhawanpreet Lakha 
565d99f1387SBhawanpreet Lakha 	for (i = 0; i < res_pool->audio_count; i++) {
566d99f1387SBhawanpreet Lakha 		struct audio *audio = res_pool->audios[i];
567d99f1387SBhawanpreet Lakha 
568d99f1387SBhawanpreet Lakha 		audio->funcs->hw_init(audio);
569d99f1387SBhawanpreet Lakha 	}
570d99f1387SBhawanpreet Lakha 
571d99f1387SBhawanpreet Lakha 	for (i = 0; i < dc->link_count; i++) {
572d99f1387SBhawanpreet Lakha 		struct dc_link *link = dc->links[i];
573d99f1387SBhawanpreet Lakha 
574d99f1387SBhawanpreet Lakha 		if (link->panel_cntl)
575d99f1387SBhawanpreet Lakha 			backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
576d99f1387SBhawanpreet Lakha 	}
577d99f1387SBhawanpreet Lakha 
578d99f1387SBhawanpreet Lakha 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
579d99f1387SBhawanpreet Lakha 		if (abms[i] != NULL)
580d99f1387SBhawanpreet Lakha 			abms[i]->funcs->abm_init(abms[i], backlight);
581d99f1387SBhawanpreet Lakha 	}
582d99f1387SBhawanpreet Lakha 
583d99f1387SBhawanpreet Lakha 	/* power AFMT HDMI memory TODO: may move to dis/en output save power*/
584d99f1387SBhawanpreet Lakha 	REG_WRITE(DIO_MEM_PWR_CTRL, 0);
585d99f1387SBhawanpreet Lakha 
586d99f1387SBhawanpreet Lakha 	if (!dc->debug.disable_clock_gate) {
587d99f1387SBhawanpreet Lakha 		/* enable all DCN clock gating */
588d99f1387SBhawanpreet Lakha 		REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
589d99f1387SBhawanpreet Lakha 
590d99f1387SBhawanpreet Lakha 		REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
591d99f1387SBhawanpreet Lakha 
592d99f1387SBhawanpreet Lakha 		REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
593d99f1387SBhawanpreet Lakha 	}
594d99f1387SBhawanpreet Lakha 
59554e8094aSYongqiang Sun 	if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
59654e8094aSYongqiang Sun 		dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
59754e8094aSYongqiang Sun 
598d99f1387SBhawanpreet Lakha 	if (dc->clk_mgr->funcs->notify_wm_ranges)
599d99f1387SBhawanpreet Lakha 		dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
600d99f1387SBhawanpreet Lakha 
60137403cedSAyush Gupta 	//if softmax is enabled then hardmax will be set by a different call
60237403cedSAyush Gupta 	if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
603d99f1387SBhawanpreet Lakha 		dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
6043e190955SJoshua Aberback 
6053e190955SJoshua Aberback 	if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
6063e190955SJoshua Aberback 		dc->res_pool->hubbub->funcs->force_pstate_change_control(
6073e190955SJoshua Aberback 				dc->res_pool->hubbub, false, false);
608ba5a5371SNicholas Kazlauskas 	if (dc->res_pool->hubbub->funcs->init_crb)
609ba5a5371SNicholas Kazlauskas 		dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
610ba5a5371SNicholas Kazlauskas 
611c2fbe663SFelipe Clark 	// Get DMCUB capabilities
612e97cc04fSJosip Pavic 	dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
613c2fbe663SFelipe Clark 	dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
61400fa7f03SRodrigo Siqueira 	dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch;
615d99f1387SBhawanpreet Lakha }
616d99f1387SBhawanpreet Lakha 
dcn30_set_avmute(struct pipe_ctx * pipe_ctx,bool enable)617d99f1387SBhawanpreet Lakha void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
618d99f1387SBhawanpreet Lakha {
619d99f1387SBhawanpreet Lakha 	if (pipe_ctx == NULL)
620d99f1387SBhawanpreet Lakha 		return;
621d99f1387SBhawanpreet Lakha 
622066bbc43SLeo Ma 	if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL) {
623d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->set_avmute(
624d99f1387SBhawanpreet Lakha 				pipe_ctx->stream_res.stream_enc,
625d99f1387SBhawanpreet Lakha 				enable);
626066bbc43SLeo Ma 
627066bbc43SLeo Ma 		/* Wait for two frame to make sure AV mute is sent out */
628066bbc43SLeo Ma 		if (enable) {
629066bbc43SLeo Ma 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
630066bbc43SLeo Ma 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
631066bbc43SLeo Ma 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
632066bbc43SLeo Ma 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
633066bbc43SLeo Ma 			pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
634066bbc43SLeo Ma 		}
635066bbc43SLeo Ma 	}
636d99f1387SBhawanpreet Lakha }
637d99f1387SBhawanpreet Lakha 
dcn30_update_info_frame(struct pipe_ctx * pipe_ctx)638d99f1387SBhawanpreet Lakha void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx)
639d99f1387SBhawanpreet Lakha {
640d99f1387SBhawanpreet Lakha 	bool is_hdmi_tmds;
641d99f1387SBhawanpreet Lakha 	bool is_dp;
642d99f1387SBhawanpreet Lakha 
643d99f1387SBhawanpreet Lakha 	ASSERT(pipe_ctx->stream);
644d99f1387SBhawanpreet Lakha 
645d99f1387SBhawanpreet Lakha 	if (pipe_ctx->stream_res.stream_enc == NULL)
646d99f1387SBhawanpreet Lakha 		return;  /* this is not root pipe */
647d99f1387SBhawanpreet Lakha 
648d99f1387SBhawanpreet Lakha 	is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
649d99f1387SBhawanpreet Lakha 	is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
650d99f1387SBhawanpreet Lakha 
65109b07f7aSLeo (Hanghong) Ma 	if (!is_hdmi_tmds && !is_dp)
652d99f1387SBhawanpreet Lakha 		return;
653d99f1387SBhawanpreet Lakha 
654d99f1387SBhawanpreet Lakha 	if (is_hdmi_tmds)
655d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
656d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.stream_enc,
657d99f1387SBhawanpreet Lakha 			&pipe_ctx->stream_res.encoder_info_frame);
658e95afc1cSSung Joon Kim 	else {
659e95afc1cSSung Joon Kim 		if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num)
660e95afc1cSSung Joon Kim 			pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num(
661e95afc1cSSung Joon Kim 				pipe_ctx->stream_res.stream_enc,
662e95afc1cSSung Joon Kim 				&pipe_ctx->stream_res.encoder_info_frame);
663e95afc1cSSung Joon Kim 
664d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
665d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.stream_enc,
666d99f1387SBhawanpreet Lakha 			&pipe_ctx->stream_res.encoder_info_frame);
667d99f1387SBhawanpreet Lakha 	}
668e95afc1cSSung Joon Kim }
669d99f1387SBhawanpreet Lakha 
dcn30_program_dmdata_engine(struct pipe_ctx * pipe_ctx)670d99f1387SBhawanpreet Lakha void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
671d99f1387SBhawanpreet Lakha {
672d99f1387SBhawanpreet Lakha 	struct dc_stream_state    *stream     = pipe_ctx->stream;
673d99f1387SBhawanpreet Lakha 	struct hubp               *hubp       = pipe_ctx->plane_res.hubp;
674d99f1387SBhawanpreet Lakha 	bool                       enable     = false;
675d99f1387SBhawanpreet Lakha 	struct stream_encoder     *stream_enc = pipe_ctx->stream_res.stream_enc;
676d99f1387SBhawanpreet Lakha 	enum dynamic_metadata_mode mode       = dc_is_dp_signal(stream->signal)
677d99f1387SBhawanpreet Lakha 							? dmdata_dp
678d99f1387SBhawanpreet Lakha 							: dmdata_hdmi;
679d99f1387SBhawanpreet Lakha 
680d99f1387SBhawanpreet Lakha 	/* if using dynamic meta, don't set up generic infopackets */
681d99f1387SBhawanpreet Lakha 	if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
682d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
683d99f1387SBhawanpreet Lakha 		enable = true;
684d99f1387SBhawanpreet Lakha 	}
685d99f1387SBhawanpreet Lakha 
686d99f1387SBhawanpreet Lakha 	if (!hubp)
687d99f1387SBhawanpreet Lakha 		return;
688d99f1387SBhawanpreet Lakha 
689d99f1387SBhawanpreet Lakha 	if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
690d99f1387SBhawanpreet Lakha 		return;
691d99f1387SBhawanpreet Lakha 
692d99f1387SBhawanpreet Lakha 	stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
693d99f1387SBhawanpreet Lakha 							hubp->inst, mode);
694d99f1387SBhawanpreet Lakha }
695d99f1387SBhawanpreet Lakha 
dcn30_apply_idle_power_optimizations(struct dc * dc,bool enable)696d99f1387SBhawanpreet Lakha bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
697d99f1387SBhawanpreet Lakha {
69852f2e83eSBhawanpreet Lakha 	union dmub_rb_cmd cmd;
69952f2e83eSBhawanpreet Lakha 	uint32_t tmr_delay = 0, tmr_scale = 0;
700ea7154d8SBhawanpreet Lakha 	struct dc_cursor_attributes cursor_attr;
701ea7154d8SBhawanpreet Lakha 	bool cursor_cache_enable = false;
702ea7154d8SBhawanpreet Lakha 	struct dc_stream_state *stream = NULL;
703ea7154d8SBhawanpreet Lakha 	struct dc_plane_state *plane = NULL;
70452f2e83eSBhawanpreet Lakha 
705d99f1387SBhawanpreet Lakha 	if (!dc->ctx->dmub_srv)
706d99f1387SBhawanpreet Lakha 		return false;
707d99f1387SBhawanpreet Lakha 
708d99f1387SBhawanpreet Lakha 	if (enable) {
70948e48e59SZhan Liu 		if (dc->current_state) {
71048e48e59SZhan Liu 			int i;
711d99f1387SBhawanpreet Lakha 
71248e48e59SZhan Liu 			/* First, check no-memory-requests case */
71348e48e59SZhan Liu 			for (i = 0; i < dc->current_state->stream_count; i++) {
714ea7154d8SBhawanpreet Lakha 				if (dc->current_state->stream_status[i].plane_count)
71548e48e59SZhan Liu 					/* Fail eligibility on a visible stream */
71648e48e59SZhan Liu 					break;
71748e48e59SZhan Liu 			}
71852f2e83eSBhawanpreet Lakha 
719ea7154d8SBhawanpreet Lakha 			if (i == dc->current_state->stream_count) {
720ea7154d8SBhawanpreet Lakha 				/* Enable no-memory-requests case */
721ea7154d8SBhawanpreet Lakha 				memset(&cmd, 0, sizeof(cmd));
722ea7154d8SBhawanpreet Lakha 				cmd.mall.header.type = DMUB_CMD__MALL;
723ea7154d8SBhawanpreet Lakha 				cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ;
724ea7154d8SBhawanpreet Lakha 				cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
725ea7154d8SBhawanpreet Lakha 
726e97cc04fSJosip Pavic 				dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
727ea7154d8SBhawanpreet Lakha 
728ea7154d8SBhawanpreet Lakha 				return true;
729a87a9a73SAlex Deucher 			}
730a87a9a73SAlex Deucher 
731ea7154d8SBhawanpreet Lakha 			stream = dc->current_state->streams[0];
732ea7154d8SBhawanpreet Lakha 			plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL);
733ea7154d8SBhawanpreet Lakha 
734ea7154d8SBhawanpreet Lakha 			if (stream && plane) {
735ea7154d8SBhawanpreet Lakha 				cursor_cache_enable = stream->cursor_position.enable &&
736ea7154d8SBhawanpreet Lakha 						plane->address.grph.cursor_cache_addr.quad_part;
737ea7154d8SBhawanpreet Lakha 				cursor_attr = stream->cursor_attributes;
738ea7154d8SBhawanpreet Lakha 			}
73952f2e83eSBhawanpreet Lakha 
74052f2e83eSBhawanpreet Lakha 			/*
741ea7154d8SBhawanpreet Lakha 			 * Second, check MALL eligibility
742ea7154d8SBhawanpreet Lakha 			 *
743ea7154d8SBhawanpreet Lakha 			 * single display only, single surface only, 8 and 16 bit formats only, no VM,
744ea7154d8SBhawanpreet Lakha 			 * do not use MALL for displays that support PSR as they use D0i3.2 in DMCUB FW
745ea7154d8SBhawanpreet Lakha 			 *
746ea7154d8SBhawanpreet Lakha 			 * TODO: When we implement multi-display, PSR displays will be allowed if there is
747ea7154d8SBhawanpreet Lakha 			 * a non-PSR display present, since in that case we can't do D0i3.2
748ea7154d8SBhawanpreet Lakha 			 */
749ea7154d8SBhawanpreet Lakha 			if (dc->current_state->stream_count == 1 &&
750ea7154d8SBhawanpreet Lakha 					stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED &&
751ea7154d8SBhawanpreet Lakha 					dc->current_state->stream_status[0].plane_count == 1 &&
752ea7154d8SBhawanpreet Lakha 					plane->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F &&
753ea7154d8SBhawanpreet Lakha 					plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 &&
754ea7154d8SBhawanpreet Lakha 					plane->address.page_table_base.quad_part == 0 &&
755ea7154d8SBhawanpreet Lakha 					dc->hwss.does_plane_fit_in_mall &&
756ea7154d8SBhawanpreet Lakha 					dc->hwss.does_plane_fit_in_mall(dc, plane,
757ea7154d8SBhawanpreet Lakha 							cursor_cache_enable ? &cursor_attr : NULL)) {
758ea7154d8SBhawanpreet Lakha 				unsigned int v_total = stream->adjust.v_total_max ?
759ea7154d8SBhawanpreet Lakha 						stream->adjust.v_total_max : stream->timing.v_total;
7609024fb08SLang Yu 				unsigned int refresh_hz = div_u64((unsigned long long) stream->timing.pix_clk_100hz *
7619024fb08SLang Yu 						100LL, (v_total * stream->timing.h_total));
762ea7154d8SBhawanpreet Lakha 
763ea7154d8SBhawanpreet Lakha 				/*
764ea7154d8SBhawanpreet Lakha 				 * one frame time in microsec:
765ea7154d8SBhawanpreet Lakha 				 * Delay_Us = 1000000 / refresh
766ea7154d8SBhawanpreet Lakha 				 * dynamic_delay_us = 1000000 / refresh + 2 * stutter_period
767ea7154d8SBhawanpreet Lakha 				 *
768ea7154d8SBhawanpreet Lakha 				 * one frame time modified by 'additional timer percent' (p):
769ea7154d8SBhawanpreet Lakha 				 * Delay_Us_modified = dynamic_delay_us + dynamic_delay_us * p / 100
770ea7154d8SBhawanpreet Lakha 				 *                   = dynamic_delay_us * (1 + p / 100)
771ea7154d8SBhawanpreet Lakha 				 *                   = (1000000 / refresh + 2 * stutter_period) * (100 + p) / 100
772ea7154d8SBhawanpreet Lakha 				 *                   = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh)
773ea7154d8SBhawanpreet Lakha 				 *
774ea7154d8SBhawanpreet Lakha 				 * formula for timer duration based on parameters, from regspec:
775ea7154d8SBhawanpreet Lakha 				 * dynamic_delay_us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
776ea7154d8SBhawanpreet Lakha 				 *
777ea7154d8SBhawanpreet Lakha 				 * dynamic_delay_us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
778ea7154d8SBhawanpreet Lakha 				 * (dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly
779ea7154d8SBhawanpreet Lakha 				 * MallFrameCacheTmrDly = ((dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale) - 64
780ea7154d8SBhawanpreet Lakha 				 *                      = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64
781ea7154d8SBhawanpreet Lakha 				 *                      = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64
78252f2e83eSBhawanpreet Lakha 				 *
78352f2e83eSBhawanpreet Lakha 				 * need to round up the result of the division before the subtraction
78452f2e83eSBhawanpreet Lakha 				 */
785ea7154d8SBhawanpreet Lakha 				unsigned int denom = refresh_hz * 6528;
786ea7154d8SBhawanpreet Lakha 				unsigned int stutter_period = dc->current_state->perf_params.stutter_period_us;
787ea7154d8SBhawanpreet Lakha 
7889024fb08SLang Yu 				tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) *
7899024fb08SLang Yu 						(100LL + dc->debug.mall_additional_timer_percent) + denom - 1),
790ea7154d8SBhawanpreet Lakha 						denom) - 64LL;
79152f2e83eSBhawanpreet Lakha 
7923bb68cecSBhawanpreet Lakha 				/* In some cases the stutter period is really big (tiny modes) in these
7933bb68cecSBhawanpreet Lakha 				 * cases MALL cant be enabled, So skip these cases to avoid a ASSERT()
7943bb68cecSBhawanpreet Lakha 				 *
7953bb68cecSBhawanpreet Lakha 				 * We can check if stutter_period is more than 1/10th the frame time to
7963bb68cecSBhawanpreet Lakha 				 * consider if we can actually meet the range of hysteresis timer
7973bb68cecSBhawanpreet Lakha 				 */
7983bb68cecSBhawanpreet Lakha 				if (stutter_period > 100000/refresh_hz)
7993bb68cecSBhawanpreet Lakha 					return false;
8003bb68cecSBhawanpreet Lakha 
80152f2e83eSBhawanpreet Lakha 				/* scale should be increased until it fits into 6 bits */
80252f2e83eSBhawanpreet Lakha 				while (tmr_delay & ~0x3F) {
80352f2e83eSBhawanpreet Lakha 					tmr_scale++;
80452f2e83eSBhawanpreet Lakha 
80552f2e83eSBhawanpreet Lakha 					if (tmr_scale > 3) {
806ea7154d8SBhawanpreet Lakha 						/* Delay exceeds range of hysteresis timer */
80752f2e83eSBhawanpreet Lakha 						ASSERT(false);
80852f2e83eSBhawanpreet Lakha 						return false;
80952f2e83eSBhawanpreet Lakha 					}
81052f2e83eSBhawanpreet Lakha 
81152f2e83eSBhawanpreet Lakha 					denom *= 2;
8129024fb08SLang Yu 					tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) *
8139024fb08SLang Yu 							(100LL + dc->debug.mall_additional_timer_percent) + denom - 1),
814ea7154d8SBhawanpreet Lakha 							denom) - 64LL;
815ea7154d8SBhawanpreet Lakha 				}
816ea7154d8SBhawanpreet Lakha 
817ea7154d8SBhawanpreet Lakha 				/* Copy HW cursor */
818ea7154d8SBhawanpreet Lakha 				if (cursor_cache_enable) {
819ea7154d8SBhawanpreet Lakha 					memset(&cmd, 0, sizeof(cmd));
820ea7154d8SBhawanpreet Lakha 					cmd.mall.header.type = DMUB_CMD__MALL;
821ea7154d8SBhawanpreet Lakha 					cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_COPY_CURSOR;
822ea7154d8SBhawanpreet Lakha 					cmd.mall.header.payload_bytes =
823ea7154d8SBhawanpreet Lakha 							sizeof(cmd.mall) - sizeof(cmd.mall.header);
824ea7154d8SBhawanpreet Lakha 
825ea7154d8SBhawanpreet Lakha 					switch (cursor_attr.color_format) {
826ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_MONO:
827ea7154d8SBhawanpreet Lakha 						cmd.mall.cursor_bpp = 2;
828ea7154d8SBhawanpreet Lakha 						break;
829ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_COLOR_1BIT_AND:
830ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
831ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
832ea7154d8SBhawanpreet Lakha 						cmd.mall.cursor_bpp = 32;
833ea7154d8SBhawanpreet Lakha 						break;
834ea7154d8SBhawanpreet Lakha 
835ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
836ea7154d8SBhawanpreet Lakha 					case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
837ea7154d8SBhawanpreet Lakha 						cmd.mall.cursor_bpp = 64;
838ea7154d8SBhawanpreet Lakha 						break;
839ea7154d8SBhawanpreet Lakha 					}
840ea7154d8SBhawanpreet Lakha 
841ea7154d8SBhawanpreet Lakha 					cmd.mall.cursor_copy_src.quad_part = cursor_attr.address.quad_part;
842ea7154d8SBhawanpreet Lakha 					cmd.mall.cursor_copy_dst.quad_part =
843554ba183SJoshua Aberback 							(plane->address.grph.cursor_cache_addr.quad_part + 2047) & ~2047;
844ea7154d8SBhawanpreet Lakha 					cmd.mall.cursor_width = cursor_attr.width;
845ea7154d8SBhawanpreet Lakha 					cmd.mall.cursor_height = cursor_attr.height;
846ea7154d8SBhawanpreet Lakha 					cmd.mall.cursor_pitch = cursor_attr.pitch;
847ea7154d8SBhawanpreet Lakha 
848e97cc04fSJosip Pavic 					dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
849ea7154d8SBhawanpreet Lakha 
850ea7154d8SBhawanpreet Lakha 					/* Use copied cursor, and it's okay to not switch back */
851554ba183SJoshua Aberback 					cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part;
852ea7154d8SBhawanpreet Lakha 					dc_stream_set_cursor_attributes(stream, &cursor_attr);
85352f2e83eSBhawanpreet Lakha 				}
85452f2e83eSBhawanpreet Lakha 
85552f2e83eSBhawanpreet Lakha 				/* Enable MALL */
85652f2e83eSBhawanpreet Lakha 				memset(&cmd, 0, sizeof(cmd));
85752f2e83eSBhawanpreet Lakha 				cmd.mall.header.type = DMUB_CMD__MALL;
858ea7154d8SBhawanpreet Lakha 				cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_ALLOW;
859ea7154d8SBhawanpreet Lakha 				cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
86052f2e83eSBhawanpreet Lakha 				cmd.mall.tmr_delay = tmr_delay;
86152f2e83eSBhawanpreet Lakha 				cmd.mall.tmr_scale = tmr_scale;
862ea7154d8SBhawanpreet Lakha 				cmd.mall.debug_bits = dc->debug.mall_error_as_fatal;
86352f2e83eSBhawanpreet Lakha 
864e97cc04fSJosip Pavic 				dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
86552f2e83eSBhawanpreet Lakha 
86652f2e83eSBhawanpreet Lakha 				return true;
86752f2e83eSBhawanpreet Lakha 			}
868d99f1387SBhawanpreet Lakha 		}
869d99f1387SBhawanpreet Lakha 
87048e48e59SZhan Liu 		/* No applicable optimizations */
871d99f1387SBhawanpreet Lakha 		return false;
872d99f1387SBhawanpreet Lakha 	}
873d99f1387SBhawanpreet Lakha 
87452f2e83eSBhawanpreet Lakha 	/* Disable MALL */
87552f2e83eSBhawanpreet Lakha 	memset(&cmd, 0, sizeof(cmd));
87652f2e83eSBhawanpreet Lakha 	cmd.mall.header.type = DMUB_CMD__MALL;
87752f2e83eSBhawanpreet Lakha 	cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_DISALLOW;
87852f2e83eSBhawanpreet Lakha 	cmd.mall.header.payload_bytes =
87952f2e83eSBhawanpreet Lakha 		sizeof(cmd.mall) - sizeof(cmd.mall.header);
88052f2e83eSBhawanpreet Lakha 
881e97cc04fSJosip Pavic 	dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
88252f2e83eSBhawanpreet Lakha 
883d99f1387SBhawanpreet Lakha 	return true;
884d99f1387SBhawanpreet Lakha }
8853e190955SJoshua Aberback 
dcn30_does_plane_fit_in_mall(struct dc * dc,struct dc_plane_state * plane,struct dc_cursor_attributes * cursor_attr)8867fc75382SBhawanpreet Lakha bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, struct dc_cursor_attributes *cursor_attr)
887e74c8a46SJoshua Aberback {
888e74c8a46SJoshua Aberback 	// add meta size?
889e74c8a46SJoshua Aberback 	unsigned int surface_size = plane->plane_size.surface_pitch * plane->plane_size.surface_size.height *
890e74c8a46SJoshua Aberback 			(plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4);
891e74c8a46SJoshua Aberback 	unsigned int mall_size = dc->caps.mall_size_total;
8927fc75382SBhawanpreet Lakha 	unsigned int cursor_size = 0;
893e74c8a46SJoshua Aberback 
894e74c8a46SJoshua Aberback 	if (dc->debug.mall_size_override)
895e74c8a46SJoshua Aberback 		mall_size = 1024 * 1024 * dc->debug.mall_size_override;
896e74c8a46SJoshua Aberback 
8977fc75382SBhawanpreet Lakha 	if (cursor_attr) {
8987fc75382SBhawanpreet Lakha 		cursor_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size;
8997fc75382SBhawanpreet Lakha 
9007fc75382SBhawanpreet Lakha 		switch (cursor_attr->color_format) {
9017fc75382SBhawanpreet Lakha 		case CURSOR_MODE_MONO:
9027fc75382SBhawanpreet Lakha 			cursor_size /= 2;
9037fc75382SBhawanpreet Lakha 			break;
9047fc75382SBhawanpreet Lakha 		case CURSOR_MODE_COLOR_1BIT_AND:
9057fc75382SBhawanpreet Lakha 		case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
9067fc75382SBhawanpreet Lakha 		case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
9077fc75382SBhawanpreet Lakha 			cursor_size *= 4;
9087fc75382SBhawanpreet Lakha 			break;
9097fc75382SBhawanpreet Lakha 
9107fc75382SBhawanpreet Lakha 		case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
9117fc75382SBhawanpreet Lakha 		case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
9127fc75382SBhawanpreet Lakha 			cursor_size *= 8;
9137fc75382SBhawanpreet Lakha 			break;
9147fc75382SBhawanpreet Lakha 		}
9157fc75382SBhawanpreet Lakha 	}
9167fc75382SBhawanpreet Lakha 
9177fc75382SBhawanpreet Lakha 	return (surface_size + cursor_size) < mall_size;
918e74c8a46SJoshua Aberback }
919e74c8a46SJoshua Aberback 
dcn30_hardware_release(struct dc * dc)9203e190955SJoshua Aberback void dcn30_hardware_release(struct dc *dc)
9213e190955SJoshua Aberback {
922b0f5b100SAlvin Lee 	bool subvp_in_use = false;
923ca86bbddSJosip Pavic 	uint32_t i;
92400fa7f03SRodrigo Siqueira 
925b0f5b100SAlvin Lee 	dc_dmub_srv_p_state_delegate(dc, false, NULL);
926b0f5b100SAlvin Lee 	dc_dmub_setup_subvp_dmub_command(dc, dc->current_state, false);
927b0f5b100SAlvin Lee 
928b0f5b100SAlvin Lee 	/* SubVP treated the same way as FPO. If driver disable and
929b0f5b100SAlvin Lee 	 * we are using a SubVP config, disable and force on DCN side
930b0f5b100SAlvin Lee 	 * to prevent P-State hang on driver enable.
931b0f5b100SAlvin Lee 	 */
932b0f5b100SAlvin Lee 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
933b0f5b100SAlvin Lee 		struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
934b0f5b100SAlvin Lee 
935b0f5b100SAlvin Lee 		if (!pipe->stream)
936b0f5b100SAlvin Lee 			continue;
937b0f5b100SAlvin Lee 
938b0f5b100SAlvin Lee 		if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
939b0f5b100SAlvin Lee 			subvp_in_use = true;
940b0f5b100SAlvin Lee 			break;
941b0f5b100SAlvin Lee 		}
942b0f5b100SAlvin Lee 	}
94300fa7f03SRodrigo Siqueira 	/* If pstate unsupported, or still supported
94400fa7f03SRodrigo Siqueira 	 * by firmware, force it supported by dcn
94500fa7f03SRodrigo Siqueira 	 */
94600fa7f03SRodrigo Siqueira 	if (dc->current_state)
947b0f5b100SAlvin Lee 		if ((!dc->clk_mgr->clks.p_state_change_support || subvp_in_use ||
94800fa7f03SRodrigo Siqueira 				dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) &&
9493e190955SJoshua Aberback 				dc->res_pool->hubbub->funcs->force_pstate_change_control)
9503e190955SJoshua Aberback 			dc->res_pool->hubbub->funcs->force_pstate_change_control(
9513e190955SJoshua Aberback 					dc->res_pool->hubbub, true, true);
9523e190955SJoshua Aberback }
95336f87850SJoshua Aberback 
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)954dbf5256bSJoshua Aberback void dcn30_set_disp_pattern_generator(const struct dc *dc,
955dbf5256bSJoshua Aberback 		struct pipe_ctx *pipe_ctx,
956dbf5256bSJoshua Aberback 		enum controller_dp_test_pattern test_pattern,
957dbf5256bSJoshua Aberback 		enum controller_dp_color_space color_space,
958dbf5256bSJoshua Aberback 		enum dc_color_depth color_depth,
959dbf5256bSJoshua Aberback 		const struct tg_color *solid_color,
960dbf5256bSJoshua Aberback 		int width, int height, int offset)
96136f87850SJoshua Aberback {
962214d72f6SAurabindo Pillai 	pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
963214d72f6SAurabindo Pillai 			color_space, color_depth, solid_color, width, height, offset);
96436f87850SJoshua Aberback }
965c2fbe663SFelipe Clark 
dcn30_prepare_bandwidth(struct dc * dc,struct dc_state * context)966c2fbe663SFelipe Clark void dcn30_prepare_bandwidth(struct dc *dc,
967c2fbe663SFelipe Clark 	struct dc_state *context)
968c2fbe663SFelipe Clark {
9693b6df06fSWesley Chalmers 	bool p_state_change_support = context->bw_ctx.bw.dcn.clk.p_state_change_support;
9703b6df06fSWesley Chalmers 	/* Any transition into an FPO config should disable MCLK switching first to avoid
9713b6df06fSWesley Chalmers 	 * driver and FW P-State synchronization issues.
9723b6df06fSWesley Chalmers 	 */
9733b6df06fSWesley Chalmers 	if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dc->clk_mgr->clks.fw_based_mclk_switching) {
97409c8cbedSWesley Chalmers 		dc->optimized_required = true;
97509c8cbedSWesley Chalmers 		context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
97609c8cbedSWesley Chalmers 	}
97709c8cbedSWesley Chalmers 
978c2fbe663SFelipe Clark 	if (dc->clk_mgr->dc_mode_softmax_enabled)
979c2fbe663SFelipe Clark 		if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
980c2fbe663SFelipe Clark 				context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
981c2fbe663SFelipe Clark 			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);
982c2fbe663SFelipe Clark 
983c2fbe663SFelipe Clark 	dcn20_prepare_bandwidth(dc, context);
9843b6df06fSWesley Chalmers 	/*
9853b6df06fSWesley Chalmers 	 * enabled -> enabled: do not disable
9863b6df06fSWesley Chalmers 	 * enabled -> disabled: disable
9873b6df06fSWesley Chalmers 	 * disabled -> enabled: don't care
9883b6df06fSWesley Chalmers 	 * disabled -> disabled: don't care
9893b6df06fSWesley Chalmers 	 */
9903b6df06fSWesley Chalmers 	if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching)
99109c8cbedSWesley Chalmers 		dc_dmub_srv_p_state_delegate(dc, false, context);
9923b6df06fSWesley Chalmers 
9933b6df06fSWesley Chalmers 	if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dc->clk_mgr->clks.fw_based_mclk_switching) {
9943b6df06fSWesley Chalmers 		/* After disabling P-State, restore the original value to ensure we get the correct P-State
9953b6df06fSWesley Chalmers 		 * on the next optimize. */
9963b6df06fSWesley Chalmers 		context->bw_ctx.bw.dcn.clk.p_state_change_support = p_state_change_support;
9973b6df06fSWesley Chalmers 	}
998c2fbe663SFelipe Clark }
999c2fbe663SFelipe Clark 
dcn30_set_static_screen_control(struct pipe_ctx ** pipe_ctx,int num_pipes,const struct dc_static_screen_params * params)1000a9366b94SSungHuai Wang void dcn30_set_static_screen_control(struct pipe_ctx **pipe_ctx,
1001a9366b94SSungHuai Wang 		int num_pipes, const struct dc_static_screen_params *params)
1002a9366b94SSungHuai Wang {
1003a9366b94SSungHuai Wang 	unsigned int i;
1004a9366b94SSungHuai Wang 	unsigned int triggers = 0;
1005a9366b94SSungHuai Wang 
1006a9366b94SSungHuai Wang 	if (params->triggers.surface_update)
1007a9366b94SSungHuai Wang 		triggers |= 0x100;
1008a9366b94SSungHuai Wang 	if (params->triggers.cursor_update)
1009a9366b94SSungHuai Wang 		triggers |= 0x8;
1010a9366b94SSungHuai Wang 	if (params->triggers.force_trigger)
1011a9366b94SSungHuai Wang 		triggers |= 0x1;
1012a9366b94SSungHuai Wang 
1013a9366b94SSungHuai Wang 	for (i = 0; i < num_pipes; i++)
1014a9366b94SSungHuai Wang 		pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(pipe_ctx[i]->stream_res.tg,
1015a9366b94SSungHuai Wang 					triggers, params->num_frames);
1016a9366b94SSungHuai Wang }
1017