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"
51d99f1387SBhawanpreet Lakha 
52d99f1387SBhawanpreet Lakha 
53d99f1387SBhawanpreet Lakha 
54d99f1387SBhawanpreet Lakha 
55d99f1387SBhawanpreet Lakha #define DC_LOGGER_INIT(logger)
56d99f1387SBhawanpreet Lakha 
57d99f1387SBhawanpreet Lakha #define CTX \
58d99f1387SBhawanpreet Lakha 	hws->ctx
59d99f1387SBhawanpreet Lakha #define REG(reg)\
60d99f1387SBhawanpreet Lakha 	hws->regs->reg
61d99f1387SBhawanpreet Lakha #define DC_LOGGER \
62d99f1387SBhawanpreet Lakha 		dc->ctx->logger
63d99f1387SBhawanpreet Lakha 
64d99f1387SBhawanpreet Lakha 
65d99f1387SBhawanpreet Lakha #undef FN
66d99f1387SBhawanpreet Lakha #define FN(reg_name, field_name) \
67d99f1387SBhawanpreet Lakha 	hws->shifts->field_name, hws->masks->field_name
68d99f1387SBhawanpreet Lakha 
69d99f1387SBhawanpreet Lakha bool dcn30_set_blend_lut(
70d99f1387SBhawanpreet Lakha 	struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
71d99f1387SBhawanpreet Lakha {
72d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
73d99f1387SBhawanpreet Lakha 	bool result = true;
74d99f1387SBhawanpreet Lakha 	struct pwl_params *blend_lut = NULL;
75d99f1387SBhawanpreet Lakha 
76d99f1387SBhawanpreet Lakha 	if (plane_state->blend_tf) {
77d99f1387SBhawanpreet Lakha 		if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
78d99f1387SBhawanpreet Lakha 			blend_lut = &plane_state->blend_tf->pwl;
79d99f1387SBhawanpreet Lakha 		else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
80d99f1387SBhawanpreet Lakha 			cm3_helper_translate_curve_to_hw_format(
81d99f1387SBhawanpreet Lakha 					plane_state->blend_tf, &dpp_base->regamma_params, false);
82d99f1387SBhawanpreet Lakha 			blend_lut = &dpp_base->regamma_params;
83d99f1387SBhawanpreet Lakha 		}
84d99f1387SBhawanpreet Lakha 	}
85d99f1387SBhawanpreet Lakha 	result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
86d99f1387SBhawanpreet Lakha 
87d99f1387SBhawanpreet Lakha 	return result;
88d99f1387SBhawanpreet Lakha }
89d99f1387SBhawanpreet Lakha 
90d99f1387SBhawanpreet Lakha static bool dcn30_set_mpc_shaper_3dlut(
91d99f1387SBhawanpreet Lakha 	struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream)
92d99f1387SBhawanpreet Lakha {
93d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
94d99f1387SBhawanpreet Lakha 	int mpcc_id = pipe_ctx->plane_res.hubp->inst;
95d99f1387SBhawanpreet Lakha 	struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
96d99f1387SBhawanpreet Lakha 	bool result = false;
97d99f1387SBhawanpreet Lakha 	int acquired_rmu = 0;
98d99f1387SBhawanpreet Lakha 	int mpcc_id_projected = 0;
99d99f1387SBhawanpreet Lakha 
100d99f1387SBhawanpreet Lakha 	const struct pwl_params *shaper_lut = NULL;
101d99f1387SBhawanpreet Lakha 	//get the shaper lut params
102d99f1387SBhawanpreet Lakha 	if (stream->func_shaper) {
103d99f1387SBhawanpreet Lakha 		if (stream->func_shaper->type == TF_TYPE_HWPWL)
104d99f1387SBhawanpreet Lakha 			shaper_lut = &stream->func_shaper->pwl;
105d99f1387SBhawanpreet Lakha 		else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
106d99f1387SBhawanpreet Lakha 			cm_helper_translate_curve_to_hw_format(
107d99f1387SBhawanpreet Lakha 					stream->func_shaper,
108d99f1387SBhawanpreet Lakha 					&dpp_base->shaper_params, true);
109d99f1387SBhawanpreet Lakha 			shaper_lut = &dpp_base->shaper_params;
110d99f1387SBhawanpreet Lakha 		}
111d99f1387SBhawanpreet Lakha 	}
112d99f1387SBhawanpreet Lakha 
113d99f1387SBhawanpreet Lakha 	if (stream->lut3d_func &&
114d99f1387SBhawanpreet Lakha 		stream->lut3d_func->state.bits.initialized == 1 &&
115d99f1387SBhawanpreet Lakha 		stream->lut3d_func->state.bits.rmu_idx_valid == 1) {
116d99f1387SBhawanpreet Lakha 		if (stream->lut3d_func->state.bits.rmu_mux_num == 0)
117d99f1387SBhawanpreet Lakha 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu0_mux;
118d99f1387SBhawanpreet Lakha 		else if (stream->lut3d_func->state.bits.rmu_mux_num == 1)
119d99f1387SBhawanpreet Lakha 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu1_mux;
120d99f1387SBhawanpreet Lakha 		else if (stream->lut3d_func->state.bits.rmu_mux_num == 2)
121d99f1387SBhawanpreet Lakha 			mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu2_mux;
122d99f1387SBhawanpreet Lakha 		if (mpcc_id_projected != mpcc_id)
123d99f1387SBhawanpreet Lakha 			BREAK_TO_DEBUGGER();
124d99f1387SBhawanpreet Lakha 		/*find the reason why logical layer assigned a differant mpcc_id into acquire_post_bldn_3dlut*/
125d99f1387SBhawanpreet Lakha 		acquired_rmu = mpc->funcs->acquire_rmu(mpc, mpcc_id,
126d99f1387SBhawanpreet Lakha 				stream->lut3d_func->state.bits.rmu_mux_num);
127d99f1387SBhawanpreet Lakha 		if (acquired_rmu != stream->lut3d_func->state.bits.rmu_mux_num)
128d99f1387SBhawanpreet Lakha 			BREAK_TO_DEBUGGER();
129d99f1387SBhawanpreet Lakha 		result = mpc->funcs->program_3dlut(mpc,
130d99f1387SBhawanpreet Lakha 								&stream->lut3d_func->lut_3d,
131d99f1387SBhawanpreet Lakha 								stream->lut3d_func->state.bits.rmu_mux_num);
132d99f1387SBhawanpreet Lakha 		result = mpc->funcs->program_shaper(mpc, shaper_lut,
133d99f1387SBhawanpreet Lakha 				stream->lut3d_func->state.bits.rmu_mux_num);
134d99f1387SBhawanpreet Lakha 	} else
135d99f1387SBhawanpreet Lakha 		/*loop through the available mux and release the requested mpcc_id*/
136d99f1387SBhawanpreet Lakha 		mpc->funcs->release_rmu(mpc, mpcc_id);
137d99f1387SBhawanpreet Lakha 
138d99f1387SBhawanpreet Lakha 
139d99f1387SBhawanpreet Lakha 	return result;
140d99f1387SBhawanpreet Lakha }
141d99f1387SBhawanpreet Lakha 
142d99f1387SBhawanpreet Lakha bool dcn30_set_input_transfer_func(struct dc *dc,
143d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx,
144d99f1387SBhawanpreet Lakha 				const struct dc_plane_state *plane_state)
145d99f1387SBhawanpreet Lakha {
146d99f1387SBhawanpreet Lakha 	struct dce_hwseq *hws = dc->hwseq;
147d99f1387SBhawanpreet Lakha 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
148d99f1387SBhawanpreet Lakha 	enum dc_transfer_func_predefined tf;
149d99f1387SBhawanpreet Lakha 	bool result = true;
150d99f1387SBhawanpreet Lakha 	struct pwl_params *params = NULL;
151d99f1387SBhawanpreet Lakha 
152d99f1387SBhawanpreet Lakha 	if (dpp_base == NULL || plane_state == NULL)
153d99f1387SBhawanpreet Lakha 		return false;
154d99f1387SBhawanpreet Lakha 
155d99f1387SBhawanpreet Lakha 	tf = TRANSFER_FUNCTION_UNITY;
156d99f1387SBhawanpreet Lakha 
157d99f1387SBhawanpreet Lakha 	if (plane_state->in_transfer_func &&
158d99f1387SBhawanpreet Lakha 		plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED)
159d99f1387SBhawanpreet Lakha 		tf = plane_state->in_transfer_func->tf;
160d99f1387SBhawanpreet Lakha 
161d99f1387SBhawanpreet Lakha 	dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
162d99f1387SBhawanpreet Lakha 
163d99f1387SBhawanpreet Lakha 	if (plane_state->in_transfer_func) {
164d99f1387SBhawanpreet Lakha 		if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL)
165d99f1387SBhawanpreet Lakha 			params = &plane_state->in_transfer_func->pwl;
166d99f1387SBhawanpreet Lakha 		else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS &&
167d99f1387SBhawanpreet Lakha 			cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func,
168d99f1387SBhawanpreet Lakha 					&dpp_base->degamma_params, false))
169d99f1387SBhawanpreet Lakha 			params = &dpp_base->degamma_params;
170d99f1387SBhawanpreet Lakha 	}
171d99f1387SBhawanpreet Lakha 
172d99f1387SBhawanpreet Lakha 	result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
173d99f1387SBhawanpreet Lakha 
174d99f1387SBhawanpreet Lakha 	if (pipe_ctx->stream_res.opp && pipe_ctx->stream_res.opp->ctx) {
175d99f1387SBhawanpreet Lakha 		if (dpp_base->funcs->dpp_program_blnd_lut)
176d99f1387SBhawanpreet Lakha 			hws->funcs.set_blend_lut(pipe_ctx, plane_state);
177d99f1387SBhawanpreet Lakha 		if (dpp_base->funcs->dpp_program_shaper_lut &&
178d99f1387SBhawanpreet Lakha 				dpp_base->funcs->dpp_program_3dlut)
179d99f1387SBhawanpreet Lakha 			hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state);
180d99f1387SBhawanpreet Lakha 	}
181d99f1387SBhawanpreet Lakha 
182d99f1387SBhawanpreet Lakha 	return result;
183d99f1387SBhawanpreet Lakha }
184d99f1387SBhawanpreet Lakha 
185d99f1387SBhawanpreet Lakha bool dcn30_set_output_transfer_func(struct dc *dc,
186d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx,
187d99f1387SBhawanpreet Lakha 				const struct dc_stream_state *stream)
188d99f1387SBhawanpreet Lakha {
189d99f1387SBhawanpreet Lakha 	int mpcc_id = pipe_ctx->plane_res.hubp->inst;
190d99f1387SBhawanpreet Lakha 	struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
191d99f1387SBhawanpreet Lakha 	struct pwl_params *params = NULL;
192d99f1387SBhawanpreet Lakha 	bool ret = false;
193d99f1387SBhawanpreet Lakha 
194d99f1387SBhawanpreet Lakha 	/* program OGAM or 3DLUT only for the top pipe*/
195d99f1387SBhawanpreet Lakha 	if (pipe_ctx->top_pipe == NULL) {
196d99f1387SBhawanpreet Lakha 		/*program rmu shaper and 3dlut in MPC*/
197d99f1387SBhawanpreet Lakha 		ret = dcn30_set_mpc_shaper_3dlut(pipe_ctx, stream);
198d99f1387SBhawanpreet Lakha 		if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
199d99f1387SBhawanpreet Lakha 			if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
200d99f1387SBhawanpreet Lakha 				params = &stream->out_transfer_func->pwl;
201d99f1387SBhawanpreet Lakha 			else if (pipe_ctx->stream->out_transfer_func->type ==
202d99f1387SBhawanpreet Lakha 					TF_TYPE_DISTRIBUTED_POINTS &&
203d99f1387SBhawanpreet Lakha 					cm3_helper_translate_curve_to_hw_format(
204d99f1387SBhawanpreet Lakha 					stream->out_transfer_func,
205d99f1387SBhawanpreet Lakha 					&mpc->blender_params, false))
206d99f1387SBhawanpreet Lakha 				params = &mpc->blender_params;
207d99f1387SBhawanpreet Lakha 			 /* there are no ROM LUTs in OUTGAM */
208d99f1387SBhawanpreet Lakha 			if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
209d99f1387SBhawanpreet Lakha 				BREAK_TO_DEBUGGER();
210d99f1387SBhawanpreet Lakha 		}
211d99f1387SBhawanpreet Lakha 	}
212d99f1387SBhawanpreet Lakha 
213d99f1387SBhawanpreet Lakha 	mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
214d99f1387SBhawanpreet Lakha 	return ret;
215d99f1387SBhawanpreet Lakha }
216d99f1387SBhawanpreet Lakha 
217d99f1387SBhawanpreet Lakha static void dcn30_set_writeback(
218d99f1387SBhawanpreet Lakha 		struct dc *dc,
219d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
220d99f1387SBhawanpreet Lakha 		struct dc_state *context)
221d99f1387SBhawanpreet Lakha {
222d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
223d99f1387SBhawanpreet Lakha 	struct mcif_buf_params *mcif_buf_params;
224d99f1387SBhawanpreet Lakha 
225d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES);
226d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->wb_enabled);
227d99f1387SBhawanpreet Lakha 	ASSERT(wb_info->mpcc_inst >= 0);
2280b02e1fdSJoshua Aberback 	ASSERT(wb_info->mpcc_inst < dc->res_pool->mpcc_count);
229d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
230d99f1387SBhawanpreet Lakha 	mcif_buf_params = &wb_info->mcif_buf_params;
231d99f1387SBhawanpreet Lakha 
232d99f1387SBhawanpreet Lakha 	/* set DWB MPC mux */
233d99f1387SBhawanpreet Lakha 	dc->res_pool->mpc->funcs->set_dwb_mux(dc->res_pool->mpc,
234d99f1387SBhawanpreet Lakha 			wb_info->dwb_pipe_inst, wb_info->mpcc_inst);
235d99f1387SBhawanpreet Lakha 	/* set MCIF_WB buffer and arbitration configuration */
236d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->config_mcif_buf(mcif_wb, mcif_buf_params, wb_info->dwb_params.dest_height);
237d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
238d99f1387SBhawanpreet Lakha }
239d99f1387SBhawanpreet Lakha 
240d99f1387SBhawanpreet Lakha void dcn30_update_writeback(
241d99f1387SBhawanpreet Lakha 		struct dc *dc,
242d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
243d99f1387SBhawanpreet Lakha 		struct dc_state *context)
244d99f1387SBhawanpreet Lakha {
245d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
246d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
247d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
248d99f1387SBhawanpreet Lakha 		__func__, wb_info->dwb_pipe_inst,\
249d99f1387SBhawanpreet Lakha 		wb_info->mpcc_inst);
250d99f1387SBhawanpreet Lakha 
251d99f1387SBhawanpreet Lakha 	dcn30_set_writeback(dc, wb_info, context);
252d99f1387SBhawanpreet Lakha 
253d99f1387SBhawanpreet Lakha 	/* update DWB */
254d99f1387SBhawanpreet Lakha 	dwb->funcs->update(dwb, &wb_info->dwb_params);
255d99f1387SBhawanpreet Lakha }
256d99f1387SBhawanpreet Lakha 
257d99f1387SBhawanpreet Lakha bool dcn30_mmhubbub_warmup(
258d99f1387SBhawanpreet Lakha 	struct dc *dc,
259d99f1387SBhawanpreet Lakha 	unsigned int num_dwb,
260d99f1387SBhawanpreet Lakha 	struct dc_writeback_info *wb_info)
261d99f1387SBhawanpreet Lakha {
262d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
263d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
264d99f1387SBhawanpreet Lakha 	struct mcif_warmup_params warmup_params = {0};
265d99f1387SBhawanpreet Lakha 	unsigned int  i, i_buf;
266d99f1387SBhawanpreet Lakha 	/*make sure there is no active DWB eanbled */
267d99f1387SBhawanpreet Lakha 	for (i = 0; i < num_dwb; i++) {
268d99f1387SBhawanpreet Lakha 		dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst];
269d99f1387SBhawanpreet Lakha 		if (dwb->dwb_is_efc_transition || dwb->dwb_is_drc) {
270d99f1387SBhawanpreet Lakha 			/*can not do warmup while any dwb enabled*/
271d99f1387SBhawanpreet Lakha 			return false;
272d99f1387SBhawanpreet Lakha 		}
273d99f1387SBhawanpreet Lakha 	}
274d99f1387SBhawanpreet Lakha 
275d99f1387SBhawanpreet Lakha 	if (wb_info->mcif_warmup_params.p_vmid == 0)
276d99f1387SBhawanpreet Lakha 		return false;
277d99f1387SBhawanpreet Lakha 
278d99f1387SBhawanpreet Lakha 	/*check whether this is new interface: warmup big buffer once*/
279d99f1387SBhawanpreet Lakha 	if (wb_info->mcif_warmup_params.start_address.quad_part != 0 &&
280d99f1387SBhawanpreet Lakha 		wb_info->mcif_warmup_params.region_size != 0) {
281d99f1387SBhawanpreet Lakha 		/*mmhubbub is shared, so it does not matter which MCIF*/
282d99f1387SBhawanpreet Lakha 		mcif_wb = dc->res_pool->mcif_wb[0];
283d99f1387SBhawanpreet Lakha 		/*warmup a big chunk of VM buffer at once*/
284d99f1387SBhawanpreet Lakha 		warmup_params.start_address.quad_part = wb_info->mcif_warmup_params.start_address.quad_part;
285d99f1387SBhawanpreet Lakha 		warmup_params.address_increment =  wb_info->mcif_warmup_params.region_size;
286d99f1387SBhawanpreet Lakha 		warmup_params.region_size = wb_info->mcif_warmup_params.region_size;
287d99f1387SBhawanpreet Lakha 		warmup_params.p_vmid = wb_info->mcif_warmup_params.p_vmid;
288d99f1387SBhawanpreet Lakha 
289d99f1387SBhawanpreet Lakha 		if (warmup_params.address_increment == 0)
290d99f1387SBhawanpreet Lakha 			warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes;
291d99f1387SBhawanpreet Lakha 
292d99f1387SBhawanpreet Lakha 		mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params);
293d99f1387SBhawanpreet Lakha 		return true;
294d99f1387SBhawanpreet Lakha 	}
295d99f1387SBhawanpreet Lakha 	/*following is the original: warmup each DWB's mcif buffer*/
296d99f1387SBhawanpreet Lakha 	for (i = 0; i < num_dwb; i++) {
297d99f1387SBhawanpreet Lakha 		dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst];
298d99f1387SBhawanpreet Lakha 		mcif_wb = dc->res_pool->mcif_wb[wb_info[i].dwb_pipe_inst];
299d99f1387SBhawanpreet Lakha 		/*warmup is for VM mode only*/
300d99f1387SBhawanpreet Lakha 		if (wb_info[i].mcif_buf_params.p_vmid == 0)
301d99f1387SBhawanpreet Lakha 			return false;
302d99f1387SBhawanpreet Lakha 
303d99f1387SBhawanpreet Lakha 		/* Warmup MCIF_WB */
304d99f1387SBhawanpreet Lakha 		for (i_buf = 0; i_buf < MCIF_BUF_COUNT; i_buf++) {
305d99f1387SBhawanpreet Lakha 			warmup_params.start_address.quad_part = wb_info[i].mcif_buf_params.luma_address[i_buf];
306d99f1387SBhawanpreet Lakha 			warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes;
307d99f1387SBhawanpreet Lakha 			warmup_params.region_size = wb_info[i].mcif_buf_params.luma_pitch * wb_info[i].dwb_params.dest_height;
308d99f1387SBhawanpreet Lakha 			warmup_params.p_vmid = wb_info[i].mcif_buf_params.p_vmid;
309d99f1387SBhawanpreet Lakha 			mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params);
310d99f1387SBhawanpreet Lakha 		}
311d99f1387SBhawanpreet Lakha 	}
312d99f1387SBhawanpreet Lakha 	return true;
313d99f1387SBhawanpreet Lakha }
314d99f1387SBhawanpreet Lakha 
315d99f1387SBhawanpreet Lakha void dcn30_enable_writeback(
316d99f1387SBhawanpreet Lakha 		struct dc *dc,
317d99f1387SBhawanpreet Lakha 		struct dc_writeback_info *wb_info,
318d99f1387SBhawanpreet Lakha 		struct dc_state *context)
319d99f1387SBhawanpreet Lakha {
320d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
321d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
322d99f1387SBhawanpreet Lakha 	struct timing_generator *optc;
323d99f1387SBhawanpreet Lakha 
324d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
325d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
326d99f1387SBhawanpreet Lakha 
327d99f1387SBhawanpreet Lakha 	/* set the OPTC source mux */
328d99f1387SBhawanpreet Lakha 	optc = dc->res_pool->timing_generators[dwb->otg_inst];
329d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\
330d99f1387SBhawanpreet Lakha 		__func__, wb_info->dwb_pipe_inst,\
331d99f1387SBhawanpreet Lakha 		wb_info->mpcc_inst);
332d99f1387SBhawanpreet Lakha 	if (IS_DIAG_DC(dc->ctx->dce_environment)) {
333d99f1387SBhawanpreet Lakha 		/*till diags switch to warmup interface*/
334d99f1387SBhawanpreet Lakha 		dcn30_mmhubbub_warmup(dc, 1, wb_info);
335d99f1387SBhawanpreet Lakha 	}
336d99f1387SBhawanpreet Lakha 	/* Update writeback pipe */
337d99f1387SBhawanpreet Lakha 	dcn30_set_writeback(dc, wb_info, context);
338d99f1387SBhawanpreet Lakha 
339d99f1387SBhawanpreet Lakha 	/* Enable MCIF_WB */
340d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->enable_mcif(mcif_wb);
341d99f1387SBhawanpreet Lakha 	/* Enable DWB */
342d99f1387SBhawanpreet Lakha 	dwb->funcs->enable(dwb, &wb_info->dwb_params);
343d99f1387SBhawanpreet Lakha }
344d99f1387SBhawanpreet Lakha 
345d99f1387SBhawanpreet Lakha void dcn30_disable_writeback(
346d99f1387SBhawanpreet Lakha 		struct dc *dc,
347d99f1387SBhawanpreet Lakha 		unsigned int dwb_pipe_inst)
348d99f1387SBhawanpreet Lakha {
349d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
350d99f1387SBhawanpreet Lakha 	struct mcif_wb *mcif_wb;
351d99f1387SBhawanpreet Lakha 
352d99f1387SBhawanpreet Lakha 	ASSERT(dwb_pipe_inst < MAX_DWB_PIPES);
353d99f1387SBhawanpreet Lakha 	dwb = dc->res_pool->dwbc[dwb_pipe_inst];
354d99f1387SBhawanpreet Lakha 	mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst];
355d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s dwb_pipe_inst = %d",\
356d99f1387SBhawanpreet Lakha 		__func__, dwb_pipe_inst);
357d99f1387SBhawanpreet Lakha 
358d99f1387SBhawanpreet Lakha 	/* disable DWB */
359d99f1387SBhawanpreet Lakha 	dwb->funcs->disable(dwb);
360d99f1387SBhawanpreet Lakha 	/* disable MCIF */
361d99f1387SBhawanpreet Lakha 	mcif_wb->funcs->disable_mcif(mcif_wb);
362d99f1387SBhawanpreet Lakha 	/* disable MPC DWB mux */
363d99f1387SBhawanpreet Lakha 	dc->res_pool->mpc->funcs->disable_dwb_mux(dc->res_pool->mpc, dwb_pipe_inst);
364d99f1387SBhawanpreet Lakha }
365d99f1387SBhawanpreet Lakha 
366d99f1387SBhawanpreet Lakha void dcn30_program_all_writeback_pipes_in_tree(
367d99f1387SBhawanpreet Lakha 		struct dc *dc,
368d99f1387SBhawanpreet Lakha 		const struct dc_stream_state *stream,
369d99f1387SBhawanpreet Lakha 		struct dc_state *context)
370d99f1387SBhawanpreet Lakha {
371d99f1387SBhawanpreet Lakha 	struct dc_writeback_info wb_info;
372d99f1387SBhawanpreet Lakha 	struct dwbc *dwb;
373d99f1387SBhawanpreet Lakha 	struct dc_stream_status *stream_status = NULL;
374d99f1387SBhawanpreet Lakha 	int i_wb, i_pipe, i_stream;
375d99f1387SBhawanpreet Lakha 	DC_LOG_DWB("%s", __func__);
376d99f1387SBhawanpreet Lakha 
377d99f1387SBhawanpreet Lakha 	ASSERT(stream);
378d99f1387SBhawanpreet Lakha 	for (i_stream = 0; i_stream < context->stream_count; i_stream++) {
379d99f1387SBhawanpreet Lakha 		if (context->streams[i_stream] == stream) {
380d99f1387SBhawanpreet Lakha 			stream_status = &context->stream_status[i_stream];
381d99f1387SBhawanpreet Lakha 			break;
382d99f1387SBhawanpreet Lakha 		}
383d99f1387SBhawanpreet Lakha 	}
384d99f1387SBhawanpreet Lakha 	ASSERT(stream_status);
385d99f1387SBhawanpreet Lakha 
386d99f1387SBhawanpreet Lakha 	ASSERT(stream->num_wb_info <= dc->res_pool->res_cap->num_dwb);
387d99f1387SBhawanpreet Lakha 	/* For each writeback pipe */
388d99f1387SBhawanpreet Lakha 	for (i_wb = 0; i_wb < stream->num_wb_info; i_wb++) {
389d99f1387SBhawanpreet Lakha 
390d99f1387SBhawanpreet Lakha 		/* copy writeback info to local non-const so mpcc_inst can be set */
391d99f1387SBhawanpreet Lakha 		wb_info = stream->writeback_info[i_wb];
392d99f1387SBhawanpreet Lakha 		if (wb_info.wb_enabled) {
393d99f1387SBhawanpreet Lakha 
394d99f1387SBhawanpreet Lakha 			/* get the MPCC instance for writeback_source_plane */
395d99f1387SBhawanpreet Lakha 			wb_info.mpcc_inst = -1;
396d99f1387SBhawanpreet Lakha 			for (i_pipe = 0; i_pipe < dc->res_pool->pipe_count; i_pipe++) {
397d99f1387SBhawanpreet Lakha 				struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i_pipe];
398d99f1387SBhawanpreet Lakha 
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 			}
404d99f1387SBhawanpreet Lakha 			ASSERT(wb_info.mpcc_inst != -1);
405d99f1387SBhawanpreet Lakha 
406d99f1387SBhawanpreet Lakha 			ASSERT(wb_info.dwb_pipe_inst < dc->res_pool->res_cap->num_dwb);
407d99f1387SBhawanpreet Lakha 			dwb = dc->res_pool->dwbc[wb_info.dwb_pipe_inst];
408d99f1387SBhawanpreet Lakha 			if (dwb->funcs->is_enabled(dwb)) {
409d99f1387SBhawanpreet Lakha 				/* writeback pipe already enabled, only need to update */
410d99f1387SBhawanpreet Lakha 				dc->hwss.update_writeback(dc, &wb_info, context);
411d99f1387SBhawanpreet Lakha 			} else {
412d99f1387SBhawanpreet Lakha 				/* Enable writeback pipe and connect to MPCC */
413d99f1387SBhawanpreet Lakha 				dc->hwss.enable_writeback(dc, &wb_info, context);
414d99f1387SBhawanpreet Lakha 			}
415d99f1387SBhawanpreet Lakha 		} else {
416d99f1387SBhawanpreet Lakha 			/* Disable writeback pipe and disconnect from MPCC */
417d99f1387SBhawanpreet Lakha 			dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst);
418d99f1387SBhawanpreet Lakha 		}
419d99f1387SBhawanpreet Lakha 	}
420d99f1387SBhawanpreet Lakha }
421d99f1387SBhawanpreet Lakha 
422d99f1387SBhawanpreet Lakha void dcn30_init_hw(struct dc *dc)
423d99f1387SBhawanpreet Lakha {
424d99f1387SBhawanpreet Lakha 	int i, j;
425d99f1387SBhawanpreet Lakha 	struct abm **abms = dc->res_pool->multiple_abms;
426d99f1387SBhawanpreet Lakha 	struct dce_hwseq *hws = dc->hwseq;
427d99f1387SBhawanpreet Lakha 	struct dc_bios *dcb = dc->ctx->dc_bios;
428d99f1387SBhawanpreet Lakha 	struct resource_pool *res_pool = dc->res_pool;
429d99f1387SBhawanpreet Lakha 	uint32_t backlight = MAX_BACKLIGHT_LEVEL;
430d99f1387SBhawanpreet Lakha 
431d99f1387SBhawanpreet Lakha 	if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
432d99f1387SBhawanpreet Lakha 		dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
433d99f1387SBhawanpreet Lakha 
434d99f1387SBhawanpreet Lakha 	// Initialize the dccg
435d99f1387SBhawanpreet Lakha 	if (res_pool->dccg->funcs->dccg_init)
436d99f1387SBhawanpreet Lakha 		res_pool->dccg->funcs->dccg_init(res_pool->dccg);
437d99f1387SBhawanpreet Lakha 
438d99f1387SBhawanpreet Lakha 	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
439d99f1387SBhawanpreet Lakha 
440d99f1387SBhawanpreet Lakha 		REG_WRITE(REFCLK_CNTL, 0);
4410f782777SMartin Leung 		REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
4420f782777SMartin Leung 		REG_WRITE(DIO_MEM_PWR_CTRL, 0);
4430f782777SMartin Leung 
4440f782777SMartin Leung 		if (!dc->debug.disable_clock_gate) {
4450f782777SMartin Leung 			/* enable all DCN clock gating */
4460f782777SMartin Leung 			REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
4470f782777SMartin Leung 
4480f782777SMartin Leung 			REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
4490f782777SMartin Leung 
4500f782777SMartin Leung 			REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
4510f782777SMartin Leung 		}
4520f782777SMartin Leung 
4530f782777SMartin Leung 		//Enable ability to power gate / don't force power on permanently
4540f782777SMartin Leung 		if (hws->funcs.enable_power_gating_plane)
4550f782777SMartin Leung 			hws->funcs.enable_power_gating_plane(hws, true);
4560f782777SMartin Leung 
4570f782777SMartin Leung 		return;
4580f782777SMartin Leung 	}
4590f782777SMartin Leung 
460d99f1387SBhawanpreet Lakha 	if (!dcb->funcs->is_accelerated_mode(dcb)) {
461d99f1387SBhawanpreet Lakha 		hws->funcs.bios_golden_init(dc);
462d99f1387SBhawanpreet Lakha 		hws->funcs.disable_vga(dc->hwseq);
463d99f1387SBhawanpreet Lakha 	}
464d99f1387SBhawanpreet Lakha 
46596879ad3SJacky Liao 	if (dc->debug.enable_mem_low_power.bits.dmcu) {
46696879ad3SJacky Liao 		// Force ERAM to shutdown if DMCU is not enabled
46796879ad3SJacky Liao 		if (dc->debug.disable_dmcu || dc->config.disable_dmcu) {
46896879ad3SJacky Liao 			REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3);
46996879ad3SJacky Liao 		}
47096879ad3SJacky Liao 	}
47196879ad3SJacky Liao 
472cae78e03SJacky Liao 	// Set default OPTC memory power states
473cae78e03SJacky Liao 	if (dc->debug.enable_mem_low_power.bits.optc) {
474cae78e03SJacky Liao 		// Shutdown when unassigned and light sleep in VBLANK
475cae78e03SJacky Liao 		REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
476cae78e03SJacky Liao 	}
477cae78e03SJacky Liao 
478d99f1387SBhawanpreet Lakha 	if (dc->ctx->dc_bios->fw_info_valid) {
479d99f1387SBhawanpreet Lakha 		res_pool->ref_clocks.xtalin_clock_inKhz =
480d99f1387SBhawanpreet Lakha 				dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
481d99f1387SBhawanpreet Lakha 
482d99f1387SBhawanpreet Lakha 		if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
483d99f1387SBhawanpreet Lakha 			if (res_pool->dccg && res_pool->hubbub) {
484d99f1387SBhawanpreet Lakha 
485d99f1387SBhawanpreet Lakha 				(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
486d99f1387SBhawanpreet Lakha 						dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
487d99f1387SBhawanpreet Lakha 						&res_pool->ref_clocks.dccg_ref_clock_inKhz);
488d99f1387SBhawanpreet Lakha 
489d99f1387SBhawanpreet Lakha 				(res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
490d99f1387SBhawanpreet Lakha 						res_pool->ref_clocks.dccg_ref_clock_inKhz,
491d99f1387SBhawanpreet Lakha 						&res_pool->ref_clocks.dchub_ref_clock_inKhz);
492d99f1387SBhawanpreet Lakha 			} else {
493d99f1387SBhawanpreet Lakha 				// Not all ASICs have DCCG sw component
494d99f1387SBhawanpreet Lakha 				res_pool->ref_clocks.dccg_ref_clock_inKhz =
495d99f1387SBhawanpreet Lakha 						res_pool->ref_clocks.xtalin_clock_inKhz;
496d99f1387SBhawanpreet Lakha 				res_pool->ref_clocks.dchub_ref_clock_inKhz =
497d99f1387SBhawanpreet Lakha 						res_pool->ref_clocks.xtalin_clock_inKhz;
498d99f1387SBhawanpreet Lakha 			}
499d99f1387SBhawanpreet Lakha 		}
500d99f1387SBhawanpreet Lakha 	} else
501d99f1387SBhawanpreet Lakha 		ASSERT_CRITICAL(false);
502d99f1387SBhawanpreet Lakha 
503d99f1387SBhawanpreet Lakha 	for (i = 0; i < dc->link_count; i++) {
504d99f1387SBhawanpreet Lakha 		/* Power up AND update implementation according to the
505d99f1387SBhawanpreet Lakha 		 * required signal (which may be different from the
506d99f1387SBhawanpreet Lakha 		 * default signal on connector).
507d99f1387SBhawanpreet Lakha 		 */
508d99f1387SBhawanpreet Lakha 		struct dc_link *link = dc->links[i];
509d99f1387SBhawanpreet Lakha 
510d99f1387SBhawanpreet Lakha 		link->link_enc->funcs->hw_init(link->link_enc);
5110f782777SMartin Leung 
5120f782777SMartin Leung 		/* Check for enabled DIG to identify enabled display */
5130f782777SMartin Leung 		if (link->link_enc->funcs->is_dig_enabled &&
5140f782777SMartin Leung 			link->link_enc->funcs->is_dig_enabled(link->link_enc))
5150f782777SMartin Leung 			link->link_status.link_active = true;
516d99f1387SBhawanpreet Lakha 	}
517d99f1387SBhawanpreet Lakha 
518d99f1387SBhawanpreet Lakha 	/* Power gate DSCs */
519d99f1387SBhawanpreet Lakha 	for (i = 0; i < res_pool->res_cap->num_dsc; i++)
5200f782777SMartin Leung 		if (hws->funcs.dsc_pg_control != NULL)
521d99f1387SBhawanpreet Lakha 			hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
522d99f1387SBhawanpreet Lakha 
5230f782777SMartin Leung 	/* we want to turn off all dp displays before doing detection */
5240f782777SMartin Leung 	if (dc->config.power_down_display_on_boot) {
5250f782777SMartin Leung 		uint8_t dpcd_power_state = '\0';
5260f782777SMartin Leung 		enum dc_status status = DC_ERROR_UNEXPECTED;
527d99f1387SBhawanpreet Lakha 
5280f782777SMartin Leung 		for (i = 0; i < dc->link_count; i++) {
5290f782777SMartin Leung 			if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)
5300f782777SMartin Leung 				continue;
5310f782777SMartin Leung 
5320f782777SMartin Leung 			/* if any of the displays are lit up turn them off */
5330f782777SMartin Leung 			status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
5340f782777SMartin Leung 						     &dpcd_power_state, sizeof(dpcd_power_state));
5350f782777SMartin Leung 			if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) {
5360f782777SMartin Leung 				/* blank dp stream before power off receiver*/
5370f782777SMartin Leung 				if (dc->links[i]->link_enc->funcs->get_dig_frontend) {
5380f782777SMartin Leung 					unsigned int fe;
5390f782777SMartin Leung 
5400f782777SMartin Leung 					fe = dc->links[i]->link_enc->funcs->get_dig_frontend(
5410f782777SMartin Leung 										dc->links[i]->link_enc);
5420f782777SMartin Leung 
5430f782777SMartin Leung 					for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
5440f782777SMartin Leung 						if (fe == dc->res_pool->stream_enc[j]->id) {
5450f782777SMartin Leung 							dc->res_pool->stream_enc[j]->funcs->dp_blank(
5460f782777SMartin Leung 										dc->res_pool->stream_enc[j]);
5470f782777SMartin Leung 							break;
5480f782777SMartin Leung 						}
5490f782777SMartin Leung 					}
5500f782777SMartin Leung 				}
5510f782777SMartin Leung 				dp_receiver_power_ctrl(dc->links[i], false);
5520f782777SMartin Leung 			}
5530f782777SMartin Leung 		}
554d99f1387SBhawanpreet Lakha 	}
555d99f1387SBhawanpreet Lakha 
5560f782777SMartin Leung 	/* If taking control over from VBIOS, we may want to optimize our first
5570f782777SMartin Leung 	 * mode set, so we need to skip powering down pipes until we know which
5580f782777SMartin Leung 	 * pipes we want to use.
5590f782777SMartin Leung 	 * Otherwise, if taking control is not possible, we need to power
5600f782777SMartin Leung 	 * everything down.
5610f782777SMartin Leung 	 */
5620f782777SMartin Leung 	if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
5630f782777SMartin Leung 		hws->funcs.init_pipes(dc, dc->current_state);
5640f782777SMartin Leung 		if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
5650f782777SMartin Leung 			dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
5660f782777SMartin Leung 					!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
567d99f1387SBhawanpreet Lakha 	}
568d99f1387SBhawanpreet Lakha 
5690f782777SMartin Leung 	/* In headless boot cases, DIG may be turned
5700f782777SMartin Leung 	 * on which causes HW/SW discrepancies.
5710f782777SMartin Leung 	 * To avoid this, power down hardware on boot
5720f782777SMartin Leung 	 * if DIG is turned on and seamless boot not enabled
5730f782777SMartin Leung 	 */
5740f782777SMartin Leung 	if (dc->config.power_down_display_on_boot) {
5750f782777SMartin Leung 		struct dc_link *edp_link = get_edp_link(dc);
576d99f1387SBhawanpreet Lakha 
5770f782777SMartin Leung 		if (edp_link &&
5780f782777SMartin Leung 				edp_link->link_enc->funcs->is_dig_enabled &&
5790f782777SMartin Leung 				edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
5800f782777SMartin Leung 				dc->hwss.edp_backlight_control &&
5810f782777SMartin Leung 				dc->hwss.power_down &&
5820f782777SMartin Leung 				dc->hwss.edp_power_control) {
5830f782777SMartin Leung 			dc->hwss.edp_backlight_control(edp_link, false);
5840f782777SMartin Leung 			dc->hwss.power_down(dc);
5850f782777SMartin Leung 			dc->hwss.edp_power_control(edp_link, false);
5860f782777SMartin Leung 		} else {
5870f782777SMartin Leung 			for (i = 0; i < dc->link_count; i++) {
5880f782777SMartin Leung 				struct dc_link *link = dc->links[i];
5890f782777SMartin Leung 
5900f782777SMartin Leung 				if (link->link_enc->funcs->is_dig_enabled &&
5910f782777SMartin Leung 						link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
5920f782777SMartin Leung 						dc->hwss.power_down) {
5930f782777SMartin Leung 					dc->hwss.power_down(dc);
5940f782777SMartin Leung 					break;
595d99f1387SBhawanpreet Lakha 				}
596d99f1387SBhawanpreet Lakha 
597d99f1387SBhawanpreet Lakha 			}
598d99f1387SBhawanpreet Lakha 		}
599d99f1387SBhawanpreet Lakha 	}
600d99f1387SBhawanpreet Lakha 
601d99f1387SBhawanpreet Lakha 	for (i = 0; i < res_pool->audio_count; i++) {
602d99f1387SBhawanpreet Lakha 		struct audio *audio = res_pool->audios[i];
603d99f1387SBhawanpreet Lakha 
604d99f1387SBhawanpreet Lakha 		audio->funcs->hw_init(audio);
605d99f1387SBhawanpreet Lakha 	}
606d99f1387SBhawanpreet Lakha 
607d99f1387SBhawanpreet Lakha 	for (i = 0; i < dc->link_count; i++) {
608d99f1387SBhawanpreet Lakha 		struct dc_link *link = dc->links[i];
609d99f1387SBhawanpreet Lakha 
610d99f1387SBhawanpreet Lakha 		if (link->panel_cntl)
611d99f1387SBhawanpreet Lakha 			backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
612d99f1387SBhawanpreet Lakha 	}
613d99f1387SBhawanpreet Lakha 
614d99f1387SBhawanpreet Lakha 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
615d99f1387SBhawanpreet Lakha 		if (abms[i] != NULL)
616d99f1387SBhawanpreet Lakha 			abms[i]->funcs->abm_init(abms[i], backlight);
617d99f1387SBhawanpreet Lakha 	}
618d99f1387SBhawanpreet Lakha 
619d99f1387SBhawanpreet Lakha 	/* power AFMT HDMI memory TODO: may move to dis/en output save power*/
620d99f1387SBhawanpreet Lakha 	REG_WRITE(DIO_MEM_PWR_CTRL, 0);
621d99f1387SBhawanpreet Lakha 
622d99f1387SBhawanpreet Lakha 	if (!dc->debug.disable_clock_gate) {
623d99f1387SBhawanpreet Lakha 		/* enable all DCN clock gating */
624d99f1387SBhawanpreet Lakha 		REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
625d99f1387SBhawanpreet Lakha 
626d99f1387SBhawanpreet Lakha 		REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
627d99f1387SBhawanpreet Lakha 
628d99f1387SBhawanpreet Lakha 		REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
629d99f1387SBhawanpreet Lakha 	}
6300f782777SMartin Leung 	if (hws->funcs.enable_power_gating_plane)
6310f782777SMartin Leung 		hws->funcs.enable_power_gating_plane(dc->hwseq, true);
632d99f1387SBhawanpreet Lakha 
63354e8094aSYongqiang Sun 	if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
63454e8094aSYongqiang Sun 		dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
63554e8094aSYongqiang Sun 
636d99f1387SBhawanpreet Lakha 	if (dc->clk_mgr->funcs->notify_wm_ranges)
637d99f1387SBhawanpreet Lakha 		dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
638d99f1387SBhawanpreet Lakha 
639d99f1387SBhawanpreet Lakha 	if (dc->clk_mgr->funcs->set_hard_max_memclk)
640d99f1387SBhawanpreet Lakha 		dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
6413e190955SJoshua Aberback 
6423e190955SJoshua Aberback 	if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
6433e190955SJoshua Aberback 		dc->res_pool->hubbub->funcs->force_pstate_change_control(
6443e190955SJoshua Aberback 				dc->res_pool->hubbub, false, false);
645d99f1387SBhawanpreet Lakha }
646d99f1387SBhawanpreet Lakha 
647d99f1387SBhawanpreet Lakha void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
648d99f1387SBhawanpreet Lakha {
649d99f1387SBhawanpreet Lakha 	if (pipe_ctx == NULL)
650d99f1387SBhawanpreet Lakha 		return;
651d99f1387SBhawanpreet Lakha 
652d99f1387SBhawanpreet Lakha 	if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL)
653d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->set_avmute(
654d99f1387SBhawanpreet Lakha 				pipe_ctx->stream_res.stream_enc,
655d99f1387SBhawanpreet Lakha 				enable);
656d99f1387SBhawanpreet Lakha }
657d99f1387SBhawanpreet Lakha 
658d99f1387SBhawanpreet Lakha void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx)
659d99f1387SBhawanpreet Lakha {
660d99f1387SBhawanpreet Lakha 	bool is_hdmi_tmds;
661d99f1387SBhawanpreet Lakha 	bool is_dp;
662d99f1387SBhawanpreet Lakha 
663d99f1387SBhawanpreet Lakha 	ASSERT(pipe_ctx->stream);
664d99f1387SBhawanpreet Lakha 
665d99f1387SBhawanpreet Lakha 	if (pipe_ctx->stream_res.stream_enc == NULL)
666d99f1387SBhawanpreet Lakha 		return;  /* this is not root pipe */
667d99f1387SBhawanpreet Lakha 
668d99f1387SBhawanpreet Lakha 	is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
669d99f1387SBhawanpreet Lakha 	is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
670d99f1387SBhawanpreet Lakha 
67109b07f7aSLeo (Hanghong) Ma 	if (!is_hdmi_tmds && !is_dp)
672d99f1387SBhawanpreet Lakha 		return;
673d99f1387SBhawanpreet Lakha 
674d99f1387SBhawanpreet Lakha 	if (is_hdmi_tmds)
675d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
676d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.stream_enc,
677d99f1387SBhawanpreet Lakha 			&pipe_ctx->stream_res.encoder_info_frame);
678d99f1387SBhawanpreet Lakha 	else
679d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
680d99f1387SBhawanpreet Lakha 			pipe_ctx->stream_res.stream_enc,
681d99f1387SBhawanpreet Lakha 			&pipe_ctx->stream_res.encoder_info_frame);
682d99f1387SBhawanpreet Lakha }
683d99f1387SBhawanpreet Lakha 
684d99f1387SBhawanpreet Lakha void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
685d99f1387SBhawanpreet Lakha {
686d99f1387SBhawanpreet Lakha 	struct dc_stream_state    *stream     = pipe_ctx->stream;
687d99f1387SBhawanpreet Lakha 	struct hubp               *hubp       = pipe_ctx->plane_res.hubp;
688d99f1387SBhawanpreet Lakha 	bool                       enable     = false;
689d99f1387SBhawanpreet Lakha 	struct stream_encoder     *stream_enc = pipe_ctx->stream_res.stream_enc;
690d99f1387SBhawanpreet Lakha 	enum dynamic_metadata_mode mode       = dc_is_dp_signal(stream->signal)
691d99f1387SBhawanpreet Lakha 							? dmdata_dp
692d99f1387SBhawanpreet Lakha 							: dmdata_hdmi;
693d99f1387SBhawanpreet Lakha 
694d99f1387SBhawanpreet Lakha 	/* if using dynamic meta, don't set up generic infopackets */
695d99f1387SBhawanpreet Lakha 	if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
696d99f1387SBhawanpreet Lakha 		pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
697d99f1387SBhawanpreet Lakha 		enable = true;
698d99f1387SBhawanpreet Lakha 	}
699d99f1387SBhawanpreet Lakha 
700d99f1387SBhawanpreet Lakha 	if (!hubp)
701d99f1387SBhawanpreet Lakha 		return;
702d99f1387SBhawanpreet Lakha 
703d99f1387SBhawanpreet Lakha 	if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
704d99f1387SBhawanpreet Lakha 		return;
705d99f1387SBhawanpreet Lakha 
706d99f1387SBhawanpreet Lakha 	stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
707d99f1387SBhawanpreet Lakha 							hubp->inst, mode);
708d99f1387SBhawanpreet Lakha }
709d99f1387SBhawanpreet Lakha 
710d99f1387SBhawanpreet Lakha bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
711d99f1387SBhawanpreet Lakha {
71252f2e83eSBhawanpreet Lakha 	union dmub_rb_cmd cmd;
71352f2e83eSBhawanpreet Lakha 	unsigned int surface_size, refresh_hz, denom;
71452f2e83eSBhawanpreet Lakha 	uint32_t tmr_delay = 0, tmr_scale = 0;
71552f2e83eSBhawanpreet Lakha 
716d99f1387SBhawanpreet Lakha 	if (!dc->ctx->dmub_srv)
717d99f1387SBhawanpreet Lakha 		return false;
718d99f1387SBhawanpreet Lakha 
719d99f1387SBhawanpreet Lakha 	if (enable) {
72048e48e59SZhan Liu 		if (dc->current_state) {
72148e48e59SZhan Liu 			int i;
722d99f1387SBhawanpreet Lakha 
72348e48e59SZhan Liu 			/* First, check no-memory-requests case */
72448e48e59SZhan Liu 			for (i = 0; i < dc->current_state->stream_count; i++) {
72548e48e59SZhan Liu 				if (dc->current_state->stream_status[i]
72648e48e59SZhan Liu 					    .plane_count)
72748e48e59SZhan Liu 					/* Fail eligibility on a visible stream */
72848e48e59SZhan Liu 					break;
72948e48e59SZhan Liu 			}
73052f2e83eSBhawanpreet Lakha 
731a87a9a73SAlex Deucher 			if (dc->current_state->stream_count == 1 // single display only
732a87a9a73SAlex Deucher 			    && dc->current_state->stream_status[0].plane_count == 1 // single surface only
733a87a9a73SAlex Deucher 			    && dc->current_state->stream_status[0].plane_states[0]->address.page_table_base.quad_part == 0 // no VM
734a87a9a73SAlex Deucher 			    // Only 8 and 16 bit formats
735a87a9a73SAlex Deucher 			    && dc->current_state->stream_status[0].plane_states[0]->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
736a87a9a73SAlex Deucher 			    && dc->current_state->stream_status[0].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) {
737a87a9a73SAlex Deucher 				surface_size = dc->current_state->stream_status[0].plane_states[0]->plane_size.surface_pitch *
738a87a9a73SAlex Deucher 					dc->current_state->stream_status[0].plane_states[0]->plane_size.surface_size.height *
739a87a9a73SAlex Deucher 					(dc->current_state->stream_status[0].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ?
740a87a9a73SAlex Deucher 					 8 : 4);
741a87a9a73SAlex Deucher 			} else {
742a87a9a73SAlex Deucher 				// TODO: remove hard code size
743a87a9a73SAlex Deucher 				surface_size = 128 * 1024 * 1024;
744a87a9a73SAlex Deucher 			}
745a87a9a73SAlex Deucher 
74652f2e83eSBhawanpreet Lakha 			// TODO: remove hard code size
74752f2e83eSBhawanpreet Lakha 			if (surface_size < 128 * 1024 * 1024) {
74852f2e83eSBhawanpreet Lakha 				refresh_hz = div_u64((unsigned long long) dc->current_state->streams[0]->timing.pix_clk_100hz *
74952f2e83eSBhawanpreet Lakha 						     100LL,
75052f2e83eSBhawanpreet Lakha 						     (dc->current_state->streams[0]->timing.v_total *
75152f2e83eSBhawanpreet Lakha 						      dc->current_state->streams[0]->timing.h_total));
75252f2e83eSBhawanpreet Lakha 
75352f2e83eSBhawanpreet Lakha 				/*
75452f2e83eSBhawanpreet Lakha 				 * Delay_Us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
75552f2e83eSBhawanpreet Lakha 				 * Delay_Us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
75652f2e83eSBhawanpreet Lakha 				 * (Delay_Us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly
75752f2e83eSBhawanpreet Lakha 				 * MallFrameCacheTmrDly = ((Delay_Us / 65.28) / 2^MallFrameCacheTmrScale) - 64
75852f2e83eSBhawanpreet Lakha 				 *                      = (1000000 / refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64
75952f2e83eSBhawanpreet Lakha 				 *                      = 1000000 / (refresh * 65.28 * 2^MallFrameCacheTmrScale) - 64
76052f2e83eSBhawanpreet Lakha 				 *                      = (1000000 * 100) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64
76152f2e83eSBhawanpreet Lakha 				 *
76252f2e83eSBhawanpreet Lakha 				 * need to round up the result of the division before the subtraction
76352f2e83eSBhawanpreet Lakha 				 */
76452f2e83eSBhawanpreet Lakha 				denom = refresh_hz * 6528;
76552f2e83eSBhawanpreet Lakha 				tmr_delay = div_u64((100000000LL + denom - 1), denom) - 64LL;
76652f2e83eSBhawanpreet Lakha 
76752f2e83eSBhawanpreet Lakha 				/* scale should be increased until it fits into 6 bits */
76852f2e83eSBhawanpreet Lakha 				while (tmr_delay & ~0x3F) {
76952f2e83eSBhawanpreet Lakha 					tmr_scale++;
77052f2e83eSBhawanpreet Lakha 
77152f2e83eSBhawanpreet Lakha 					if (tmr_scale > 3) {
77252f2e83eSBhawanpreet Lakha 						/* The delay exceeds the range of the hystersis timer */
77352f2e83eSBhawanpreet Lakha 						ASSERT(false);
77452f2e83eSBhawanpreet Lakha 						return false;
77552f2e83eSBhawanpreet Lakha 					}
77652f2e83eSBhawanpreet Lakha 
77752f2e83eSBhawanpreet Lakha 					denom *= 2;
77852f2e83eSBhawanpreet Lakha 					tmr_delay = div_u64((100000000LL + denom - 1), denom) - 64LL;
77952f2e83eSBhawanpreet Lakha 				}
78052f2e83eSBhawanpreet Lakha 
78152f2e83eSBhawanpreet Lakha 				/* Enable MALL */
78252f2e83eSBhawanpreet Lakha 				memset(&cmd, 0, sizeof(cmd));
78352f2e83eSBhawanpreet Lakha 				cmd.mall.header.type = DMUB_CMD__MALL;
78452f2e83eSBhawanpreet Lakha 				cmd.mall.header.sub_type =
78552f2e83eSBhawanpreet Lakha 					DMUB_CMD__MALL_ACTION_ALLOW;
78652f2e83eSBhawanpreet Lakha 				cmd.mall.header.payload_bytes =
78752f2e83eSBhawanpreet Lakha 					sizeof(cmd.mall) -
78852f2e83eSBhawanpreet Lakha 					sizeof(cmd.mall.header);
78952f2e83eSBhawanpreet Lakha 				cmd.mall.tmr_delay = tmr_delay;
79052f2e83eSBhawanpreet Lakha 				cmd.mall.tmr_scale = tmr_scale;
79152f2e83eSBhawanpreet Lakha 
79252f2e83eSBhawanpreet Lakha 				dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
79352f2e83eSBhawanpreet Lakha 				dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
79452f2e83eSBhawanpreet Lakha 
79552f2e83eSBhawanpreet Lakha 				return true;
79652f2e83eSBhawanpreet Lakha 			}
797d99f1387SBhawanpreet Lakha 		}
798d99f1387SBhawanpreet Lakha 
79948e48e59SZhan Liu 		/* No applicable optimizations */
800d99f1387SBhawanpreet Lakha 		return false;
801d99f1387SBhawanpreet Lakha 	}
802d99f1387SBhawanpreet Lakha 
80352f2e83eSBhawanpreet Lakha 	/* Disable MALL */
80452f2e83eSBhawanpreet Lakha 	memset(&cmd, 0, sizeof(cmd));
80552f2e83eSBhawanpreet Lakha 	cmd.mall.header.type = DMUB_CMD__MALL;
80652f2e83eSBhawanpreet Lakha 	cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_DISALLOW;
80752f2e83eSBhawanpreet Lakha 	cmd.mall.header.payload_bytes =
80852f2e83eSBhawanpreet Lakha 		sizeof(cmd.mall) - sizeof(cmd.mall.header);
80952f2e83eSBhawanpreet Lakha 
81052f2e83eSBhawanpreet Lakha 	dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
81152f2e83eSBhawanpreet Lakha 	dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
81252f2e83eSBhawanpreet Lakha 	dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
81352f2e83eSBhawanpreet Lakha 
814d99f1387SBhawanpreet Lakha 	return true;
815d99f1387SBhawanpreet Lakha }
8163e190955SJoshua Aberback 
817e74c8a46SJoshua Aberback bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane)
818e74c8a46SJoshua Aberback {
819e74c8a46SJoshua Aberback 	// add meta size?
820e74c8a46SJoshua Aberback 	unsigned int surface_size = plane->plane_size.surface_pitch * plane->plane_size.surface_size.height *
821e74c8a46SJoshua Aberback 			(plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4);
822e74c8a46SJoshua Aberback 	unsigned int mall_size = dc->caps.mall_size_total;
823e74c8a46SJoshua Aberback 
824e74c8a46SJoshua Aberback 	if (dc->debug.mall_size_override)
825e74c8a46SJoshua Aberback 		mall_size = 1024 * 1024 * dc->debug.mall_size_override;
826e74c8a46SJoshua Aberback 
827e74c8a46SJoshua Aberback 	return (surface_size + dc->caps.cursor_cache_size) < mall_size;
828e74c8a46SJoshua Aberback }
829e74c8a46SJoshua Aberback 
8303e190955SJoshua Aberback void dcn30_hardware_release(struct dc *dc)
8313e190955SJoshua Aberback {
8323e190955SJoshua Aberback 	/* if pstate unsupported, force it supported */
8333e190955SJoshua Aberback 	if (!dc->clk_mgr->clks.p_state_change_support &&
8343e190955SJoshua Aberback 			dc->res_pool->hubbub->funcs->force_pstate_change_control)
8353e190955SJoshua Aberback 		dc->res_pool->hubbub->funcs->force_pstate_change_control(
8363e190955SJoshua Aberback 				dc->res_pool->hubbub, true, true);
8373e190955SJoshua Aberback }
83836f87850SJoshua Aberback 
839985faf2cSWesley Chalmers void dcn30_set_hubp_blank(const struct dc *dc,
840985faf2cSWesley Chalmers 		struct pipe_ctx *pipe_ctx,
841985faf2cSWesley Chalmers 		bool blank_enable)
842985faf2cSWesley Chalmers {
843985faf2cSWesley Chalmers 	struct pipe_ctx *mpcc_pipe;
844985faf2cSWesley Chalmers 	struct pipe_ctx *odm_pipe;
845985faf2cSWesley Chalmers 
846985faf2cSWesley Chalmers 	if (blank_enable) {
847985faf2cSWesley Chalmers 		struct plane_resource *plane_res = &pipe_ctx->plane_res;
848985faf2cSWesley Chalmers 		struct stream_resource *stream_res = &pipe_ctx->stream_res;
849985faf2cSWesley Chalmers 
850985faf2cSWesley Chalmers 		/* Wait for enter vblank */
851985faf2cSWesley Chalmers 		stream_res->tg->funcs->wait_for_state(stream_res->tg, CRTC_STATE_VBLANK);
852985faf2cSWesley Chalmers 
853985faf2cSWesley Chalmers 		/* Blank HUBP to allow p-state during blank on all timings */
854985faf2cSWesley Chalmers 		pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, true);
855985faf2cSWesley Chalmers 		/* Confirm hubp in blank */
856985faf2cSWesley Chalmers 		ASSERT(plane_res->hubp->funcs->hubp_in_blank(plane_res->hubp));
857985faf2cSWesley Chalmers 		/* Toggle HUBP_DISABLE */
858985faf2cSWesley Chalmers 		plane_res->hubp->funcs->hubp_soft_reset(plane_res->hubp, true);
859985faf2cSWesley Chalmers 		plane_res->hubp->funcs->hubp_soft_reset(plane_res->hubp, false);
860985faf2cSWesley Chalmers 		for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) {
861985faf2cSWesley Chalmers 			mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, true);
862985faf2cSWesley Chalmers 			/* Confirm hubp in blank */
863985faf2cSWesley Chalmers 			ASSERT(mpcc_pipe->plane_res.hubp->funcs->hubp_in_blank(mpcc_pipe->plane_res.hubp));
864985faf2cSWesley Chalmers 			/* Toggle HUBP_DISABLE */
865985faf2cSWesley Chalmers 			mpcc_pipe->plane_res.hubp->funcs->hubp_soft_reset(mpcc_pipe->plane_res.hubp, true);
866985faf2cSWesley Chalmers 			mpcc_pipe->plane_res.hubp->funcs->hubp_soft_reset(mpcc_pipe->plane_res.hubp, false);
867985faf2cSWesley Chalmers 
868985faf2cSWesley Chalmers 		}
869985faf2cSWesley Chalmers 		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
870985faf2cSWesley Chalmers 			odm_pipe->plane_res.hubp->funcs->set_blank(odm_pipe->plane_res.hubp, true);
871985faf2cSWesley Chalmers 			/* Confirm hubp in blank */
872985faf2cSWesley Chalmers 			ASSERT(odm_pipe->plane_res.hubp->funcs->hubp_in_blank(odm_pipe->plane_res.hubp));
873985faf2cSWesley Chalmers 			/* Toggle HUBP_DISABLE */
874985faf2cSWesley Chalmers 			odm_pipe->plane_res.hubp->funcs->hubp_soft_reset(odm_pipe->plane_res.hubp, true);
875985faf2cSWesley Chalmers 			odm_pipe->plane_res.hubp->funcs->hubp_soft_reset(odm_pipe->plane_res.hubp, false);
876985faf2cSWesley Chalmers 		}
877985faf2cSWesley Chalmers 	} else {
878985faf2cSWesley Chalmers 		pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, false);
879985faf2cSWesley Chalmers 		for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
880985faf2cSWesley Chalmers 			mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false);
881985faf2cSWesley Chalmers 		for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
882985faf2cSWesley Chalmers 			odm_pipe->plane_res.hubp->funcs->set_blank(odm_pipe->plane_res.hubp, false);
883985faf2cSWesley Chalmers 	}
884985faf2cSWesley Chalmers }
885985faf2cSWesley Chalmers 
886dbf5256bSJoshua Aberback void dcn30_set_disp_pattern_generator(const struct dc *dc,
887dbf5256bSJoshua Aberback 		struct pipe_ctx *pipe_ctx,
888dbf5256bSJoshua Aberback 		enum controller_dp_test_pattern test_pattern,
889dbf5256bSJoshua Aberback 		enum controller_dp_color_space color_space,
890dbf5256bSJoshua Aberback 		enum dc_color_depth color_depth,
891dbf5256bSJoshua Aberback 		const struct tg_color *solid_color,
892dbf5256bSJoshua Aberback 		int width, int height, int offset)
89336f87850SJoshua Aberback {
894*d209124dSBhawanpreet Lakha 	struct stream_resource *stream_res = &pipe_ctx->stream_res;
895*d209124dSBhawanpreet Lakha 
896*d209124dSBhawanpreet Lakha 	if (test_pattern != CONTROLLER_DP_TEST_PATTERN_VIDEOMODE) {
897*d209124dSBhawanpreet Lakha 		pipe_ctx->vtp_locked = false;
898*d209124dSBhawanpreet Lakha 		/* turning on DPG */
899*d209124dSBhawanpreet Lakha 		stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space,
900*d209124dSBhawanpreet Lakha 				color_depth, solid_color, width, height, offset);
901*d209124dSBhawanpreet Lakha 
902*d209124dSBhawanpreet Lakha 		/* Defer hubp blank if tg is locked */
903*d209124dSBhawanpreet Lakha 		if (stream_res->tg->funcs->is_tg_enabled(stream_res->tg)) {
904*d209124dSBhawanpreet Lakha 			if (stream_res->tg->funcs->is_locked(stream_res->tg))
905*d209124dSBhawanpreet Lakha 				pipe_ctx->vtp_locked = true;
906*d209124dSBhawanpreet Lakha 			else
907*d209124dSBhawanpreet Lakha 				dc->hwss.set_hubp_blank(dc, pipe_ctx, true);
908*d209124dSBhawanpreet Lakha 		}
909*d209124dSBhawanpreet Lakha 	} else {
910*d209124dSBhawanpreet Lakha 		dc->hwss.set_hubp_blank(dc, pipe_ctx, false);
911*d209124dSBhawanpreet Lakha 		/* turning off DPG */
912*d209124dSBhawanpreet Lakha 		stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space,
913*d209124dSBhawanpreet Lakha 				color_depth, solid_color, width, height, offset);
914*d209124dSBhawanpreet Lakha 	}
91536f87850SJoshua Aberback }
916