xref: /linux/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c (revision 40288c9206c17eb66a603262e06a58d300d0f279)
1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4 
5 #include "dm_services.h"
6 #include "dm_helpers.h"
7 #include "core_types.h"
8 #include "resource.h"
9 #include "dccg.h"
10 #include "dce/dce_hwseq.h"
11 #include "reg_helper.h"
12 #include "abm.h"
13 #include "hubp.h"
14 #include "dchubbub.h"
15 #include "timing_generator.h"
16 #include "opp.h"
17 #include "ipp.h"
18 #include "mpc.h"
19 #include "mcif_wb.h"
20 #include "dc_dmub_srv.h"
21 #include "link_hwss.h"
22 #include "dpcd_defs.h"
23 #include "clk_mgr.h"
24 #include "dsc.h"
25 #include "link_service.h"
26 
27 #include "dce/dmub_hw_lock_mgr.h"
28 #include "dcn10/dcn10_cm_common.h"
29 #include "dcn20/dcn20_optc.h"
30 #include "dcn30/dcn30_cm_common.h"
31 #include "dcn32/dcn32_hwseq.h"
32 #include "dcn50_hwseq.h"
33 #include "dcn60/dcn60_resource.h"
34 #include "dcn401/dcn401_hwseq.h"
35 #include "dcn401/dcn401_resource.h"
36 #include "dc_state_priv.h"
37 #include "link_enc_cfg.h"
38 #include "dio/dcn10/dcn10_dio.h"
39 
40 #define DC_LOGGER_INIT(logger)
41 
42 #define CTX \
43 	hws->ctx
44 #define REG(reg)\
45 	hws->regs->reg
46 #define DC_LOGGER \
47 	dc->ctx->logger
48 
49 #undef FN
50 #define FN(reg_name, field_name) \
51 	hws->shifts->field_name, hws->masks->field_name
52 
dcn50_initialize_min_clocks(struct dc * dc)53 static void dcn50_initialize_min_clocks(struct dc *dc)
54 {
55 	struct dc_clocks *clocks = &dc->current_state->bw_ctx.bw.dcn.clk;
56 
57 	clocks->dcfclk_deep_sleep_khz = DCN3_2_DCFCLK_DS_INIT_KHZ;
58 	clocks->dcfclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz * 1000;
59 	clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000;
60 	clocks->dramclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 1000;
61 	clocks->dppclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dppclk_mhz * 1000;
62 	if (dc->debug.disable_boot_optimizations) {
63 		clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000;
64 	} else {
65 		/* Even though DPG_EN = 1 for the connected display, it still requires the
66 		 * correct timing so we cannot set DISPCLK to min freq or it could cause
67 		 * audio corruption. Read current DISPCLK from DENTIST and request the same
68 		 * freq to ensure that the timing is valid and unchanged.
69 		 */
70 		if (dc->clk_mgr->funcs->get_dispclk_from_dentist)
71 			clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
72 	}
73 	clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
74 	clocks->fclk_p_state_change_support = true;
75 	clocks->p_state_change_support = true;
76 
77 	dc->clk_mgr->funcs->update_clocks(
78 			dc->clk_mgr,
79 			dc->current_state,
80 			true);
81 }
82 
dcn50_update_dchubp_dpp(struct dc * dc,struct pipe_ctx * pipe_ctx,struct dc_state * context)83 void dcn50_update_dchubp_dpp(
84 	struct dc *dc,
85 	struct pipe_ctx *pipe_ctx,
86 	struct dc_state *context)
87 {
88 	struct dce_hwseq *hws = dc->hwseq;
89 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
90 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
91 	struct dc_plane_state *plane_state = pipe_ctx->plane_state;
92 	struct dccg *dccg = dc->res_pool->dccg;
93 	bool viewport_changed = false;
94 	enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe_ctx);
95 
96 	if (pipe_ctx->update_flags.bits.dppclk)
97 		dpp->funcs->dpp_dppclk_control(dpp, false, true);
98 
99 	if (pipe_ctx->update_flags.bits.enable)
100 		dccg->funcs->update_dpp_dto(dccg, dpp->inst, pipe_ctx->plane_res.bw.dppclk_khz);
101 
102 	/* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
103 	 * VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
104 	 * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
105 	 */
106 
107 	if (pipe_ctx->update_flags.bits.hubp_rq_dlg_ttu) {
108 		hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
109 
110 		if (hubp->funcs->hubp_setup2) {
111 			hubp->funcs->hubp_setup2(
112 				hubp,
113 				&pipe_ctx->hubp_regs,
114 				&pipe_ctx->global_sync,
115 				&pipe_ctx->stream->timing);
116 		} else {
117 			hubp->funcs->hubp_setup(
118 				hubp,
119 				&pipe_ctx->dlg_regs,
120 				&pipe_ctx->ttu_regs,
121 				&pipe_ctx->rq_regs,
122 				&pipe_ctx->pipe_dlg_param);
123 		}
124 	}
125 
126 	if (pipe_ctx->update_flags.bits.unbounded_req && hubp->funcs->set_unbounded_requesting)
127 		hubp->funcs->set_unbounded_requesting(hubp, pipe_ctx->unbounded_req);
128 
129 	if (pipe_ctx->update_flags.bits.hubp_interdependent) {
130 		if (hubp->funcs->hubp_setup_interdependent2) {
131 			hubp->funcs->hubp_setup_interdependent2(
132 				hubp,
133 				&pipe_ctx->hubp_regs);
134 		} else {
135 			hubp->funcs->hubp_setup_interdependent(
136 				hubp,
137 				&pipe_ctx->dlg_regs,
138 				&pipe_ctx->ttu_regs);
139 		}
140 	}
141 
142 	if (pipe_ctx->update_flags.bits.enable ||
143 		pipe_ctx->update_flags.bits.plane_changed ||
144 		plane_state->update_bits.bpp_change ||
145 		plane_state->update_bits.input_csc_change ||
146 		plane_state->update_bits.color_space_change ||
147 		plane_state->update_bits.coeff_reduction_change) {
148 		struct dc_bias_and_scale bns_params = plane_state->bias_and_scale;
149 
150 		// program the input csc
151 		dpp->funcs->dpp_setup(dpp,
152 			plane_state->format,
153 			EXPANSION_MODE_ZERO,
154 			plane_state->input_csc_color_matrix,
155 			plane_state->color_space,
156 			NULL);
157 
158 		if (dpp->funcs->set_cursor_matrix) {
159 			dpp->funcs->set_cursor_matrix(dpp,
160 				plane_state->color_space,
161 				plane_state->cursor_csc_color_matrix);
162 		}
163 		if (dpp->funcs->dpp_program_bias_and_scale) {
164 			//TODO :for CNVC set scale and bias registers if necessary
165 			dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
166 		}
167 	}
168 
169 	if (pipe_ctx->update_flags.bits.mpcc
170 		|| pipe_ctx->update_flags.bits.plane_changed
171 		|| plane_state->update_bits.global_alpha_change
172 		|| plane_state->update_bits.per_pixel_alpha_change) {
173 		// MPCC inst is equal to pipe index in practice
174 		hws->funcs.update_mpcc(dc, pipe_ctx);
175 	}
176 
177 	if (pipe_ctx->update_flags.bits.scaler ||
178 		plane_state->update_bits.scaling_change ||
179 		plane_state->update_bits.position_change ||
180 		plane_state->update_bits.per_pixel_alpha_change ||
181 		pipe_ctx->stream->update_flags.bits.scaling) {
182 		pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha;
183 		ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_36BPP);
184 		/* scaler configuration */
185 		pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
186 			pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
187 	}
188 
189 	if (pipe_ctx->update_flags.bits.viewport ||
190 		(context == dc->current_state && plane_state->update_bits.position_change) ||
191 		(context == dc->current_state && plane_state->update_bits.scaling_change) ||
192 		(context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) {
193 
194 		hubp->funcs->mem_program_viewport(
195 			hubp,
196 			&pipe_ctx->plane_res.scl_data.viewport,
197 			&pipe_ctx->plane_res.scl_data.viewport_c);
198 		viewport_changed = true;
199 	}
200 
201 	/* Any updates are handled in dc interface, just need to apply existing for plane enable */
202 	if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
203 		pipe_ctx->update_flags.bits.scaler || viewport_changed == true) &&
204 		pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
205 		if (dc->hwss.abort_cursor_offload_update)
206 			dc->hwss.abort_cursor_offload_update(dc, pipe_ctx);
207 
208 		dc->hwss.set_cursor_attribute(pipe_ctx);
209 		dc->hwss.set_cursor_position(pipe_ctx);
210 
211 		if (dc->hwss.set_cursor_sdr_white_level)
212 			dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
213 	}
214 
215 	/* Any updates are handled in dc interface, just need
216 	 * to apply existing for plane enable / opp change */
217 	if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed
218 		|| pipe_ctx->update_flags.bits.plane_changed
219 		|| pipe_ctx->stream->update_flags.bits.gamut_remap
220 		|| plane_state->update_bits.gamut_remap_change
221 		|| pipe_ctx->stream->update_flags.bits.out_csc) {
222 		/* dpp/cm gamut remap*/
223 		hwss_program_gamut_remap(pipe_ctx);
224 
225 		/*call the dcn2 method which uses mpc csc*/
226 		dc->hwss.program_output_csc(dc,
227 			pipe_ctx,
228 			pipe_ctx->stream->output_color_space,
229 			pipe_ctx->stream->csc_color_matrix.matrix,
230 			hubp->opp_id);
231 	}
232 
233 	if (pipe_ctx->update_flags.bits.enable ||
234 		pipe_ctx->update_flags.bits.plane_changed ||
235 		plane_state->update_bits.addr_update) {
236 		if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) &&
237 			pipe_mall_type == SUBVP_MAIN) {
238 			union block_sequence_params params;
239 
240 			params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv;
241 			params.subvp_save_surf_addr.addr = &pipe_ctx->plane_state->address;
242 			params.subvp_save_surf_addr.subvp_index = pipe_ctx->subvp_index;
243 			hwss_subvp_save_surf_addr(&params);
244 		}
245 		dc->hwss.update_plane_addr(dc, pipe_ctx);
246 	}
247 
248 	if (pipe_ctx->update_flags.bits.enable)
249 		hubp->funcs->set_blank(hubp, false);
250 	/* If the stream paired with this plane is phantom, the plane is also phantom */
251 	if (pipe_mall_type == SUBVP_PHANTOM && hubp->funcs->phantom_hubp_post_enable)
252 		hubp->funcs->phantom_hubp_post_enable(hubp);
253 }
254 
dcn50_update_dchubp_dpp_sequence(struct dc * dc,struct pipe_ctx * pipe_ctx,struct dc_state * context,struct block_sequence_state * seq_state)255 void dcn50_update_dchubp_dpp_sequence(struct dc *dc,
256 				       struct pipe_ctx *pipe_ctx,
257 				       struct dc_state *context,
258 				       struct block_sequence_state *seq_state)
259 {
260 	struct dce_hwseq *hws = dc->hwseq;
261 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
262 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
263 	struct dc_plane_state *plane_state = pipe_ctx->plane_state;
264 	struct dccg *dccg = dc->res_pool->dccg;
265 	bool viewport_changed = false;
266 	enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe_ctx);
267 
268 	if (!hubp || !dpp || !plane_state)
269 		return;
270 
271 	/* Step 1: DPP DPPCLK control */
272 	if (pipe_ctx->update_flags.bits.dppclk)
273 		hwss_add_dpp_dppclk_control(seq_state, dpp, false, true);
274 
275 	/* Step 2: DCCG update DPP DTO */
276 	if (pipe_ctx->update_flags.bits.enable)
277 		hwss_add_dccg_update_dpp_dto(seq_state, dccg, dpp->inst, pipe_ctx->plane_res.bw.dppclk_khz);
278 
279 	/* Step 3: HUBP VTG selection */
280 	if (pipe_ctx->update_flags.bits.hubp_rq_dlg_ttu) {
281 		hwss_add_hubp_vtg_sel(seq_state, hubp, pipe_ctx->stream_res.tg->inst);
282 
283 		/* Step 4: HUBP setup (choose setup2 or setup) */
284 		if (hubp->funcs->hubp_setup2) {
285 			hwss_add_hubp_setup2(seq_state, hubp, &pipe_ctx->hubp_regs,
286 				&pipe_ctx->global_sync, &pipe_ctx->stream->timing);
287 		} else if (hubp->funcs->hubp_setup) {
288 			hwss_add_hubp_setup(seq_state, hubp, &pipe_ctx->dlg_regs,
289 				&pipe_ctx->ttu_regs, &pipe_ctx->rq_regs, &pipe_ctx->pipe_dlg_param);
290 		}
291 	}
292 
293 	/* Step 5: Set unbounded requesting */
294 	if (pipe_ctx->update_flags.bits.unbounded_req && hubp->funcs->set_unbounded_requesting)
295 		hwss_add_hubp_set_unbounded_requesting(seq_state, hubp, pipe_ctx->unbounded_req);
296 
297 	/* Step 6: HUBP interdependent setup */
298 	if (pipe_ctx->update_flags.bits.hubp_interdependent) {
299 		if (hubp->funcs->hubp_setup_interdependent2)
300 			hwss_add_hubp_setup_interdependent2(seq_state, hubp, &pipe_ctx->hubp_regs);
301 		else if (hubp->funcs->hubp_setup_interdependent)
302 			hwss_add_hubp_setup_interdependent(seq_state, hubp, &pipe_ctx->dlg_regs, &pipe_ctx->ttu_regs);
303 	}
304 
305 	/* Step 7: DPP setup - input CSC and format setup */
306 	if (pipe_ctx->update_flags.bits.enable ||
307 			pipe_ctx->update_flags.bits.plane_changed ||
308 			plane_state->update_bits.bpp_change ||
309 			plane_state->update_bits.input_csc_change ||
310 			plane_state->update_bits.color_space_change ||
311 			plane_state->update_bits.coeff_reduction_change) {
312 		hwss_add_dpp_setup_dpp(seq_state, pipe_ctx);
313 
314 		/* Step 8: DPP cursor matrix setup */
315 		if (dpp->funcs->set_cursor_matrix) {
316 			hwss_add_dpp_set_cursor_matrix(seq_state, dpp, plane_state->color_space,
317 				&plane_state->cursor_csc_color_matrix);
318 		}
319 
320 		/* Step 9: DPP program bias and scale */
321 		if (dpp->funcs->dpp_program_bias_and_scale)
322 			hwss_add_dpp_program_bias_and_scale(seq_state, pipe_ctx);
323 	}
324 
325 	/* Step 10: MPCC updates */
326 	if (pipe_ctx->update_flags.bits.mpcc ||
327 	     pipe_ctx->update_flags.bits.plane_changed ||
328 	     plane_state->update_bits.global_alpha_change ||
329 	     plane_state->update_bits.per_pixel_alpha_change) {
330 
331 		/* Check if update_mpcc_sequence is implemented and prefer it over single MPC_UPDATE_MPCC step */
332 		if (hws->funcs.update_mpcc_sequence)
333 			hws->funcs.update_mpcc_sequence(dc, pipe_ctx, seq_state);
334 	}
335 
336 	/* Step 11: DPP scaler setup */
337 	if (pipe_ctx->update_flags.bits.scaler ||
338 			plane_state->update_bits.scaling_change ||
339 			plane_state->update_bits.position_change ||
340 			plane_state->update_bits.per_pixel_alpha_change ||
341 			pipe_ctx->stream->update_flags.bits.scaling) {
342 		pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha;
343 		ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_36BPP);
344 		hwss_add_dpp_set_scaler(seq_state, pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
345 	}
346 
347 	/* Step 12: HUBP viewport programming */
348 	if (pipe_ctx->update_flags.bits.viewport ||
349 	     (context == dc->current_state && plane_state->update_bits.position_change) ||
350 	     (context == dc->current_state && plane_state->update_bits.scaling_change) ||
351 	     (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) {
352 		hwss_add_hubp_mem_program_viewport(seq_state, hubp,
353 			&pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c);
354 		viewport_changed = true;
355 	}
356 
357 	/* Step 13: Cursor attribute setup */
358 	if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
359 	     pipe_ctx->update_flags.bits.scaler || viewport_changed == true) &&
360 	    pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
361 
362 		hwss_add_abort_cursor_offload_update(seq_state, dc, pipe_ctx);
363 
364 		hwss_add_set_cursor_attribute(seq_state, dc, pipe_ctx);
365 
366 		/* Step 14: Cursor position setup */
367 		hwss_add_set_cursor_position(seq_state, dc, pipe_ctx);
368 
369 		/* Step 15: Cursor SDR white level */
370 		if (dc->hwss.set_cursor_sdr_white_level)
371 			hwss_add_set_cursor_sdr_white_level(seq_state, dc, pipe_ctx);
372 	}
373 
374 	/* Step 16: Gamut remap and output CSC */
375 	if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
376 			pipe_ctx->update_flags.bits.plane_changed ||
377 			pipe_ctx->stream->update_flags.bits.gamut_remap ||
378 			plane_state->update_bits.gamut_remap_change ||
379 			pipe_ctx->stream->update_flags.bits.out_csc) {
380 
381 		/* Gamut remap */
382 		hwss_add_dpp_program_gamut_remap(seq_state, pipe_ctx);
383 
384 		/* Output CSC */
385 		hwss_add_program_output_csc(seq_state, dc, pipe_ctx, pipe_ctx->stream->output_color_space,
386 			pipe_ctx->stream->csc_color_matrix.matrix, hubp->opp_id);
387 	}
388 
389 	/* Step 17: Update plane address (with SubVP support) */
390 	if (pipe_ctx->update_flags.bits.enable ||
391 	     pipe_ctx->update_flags.bits.plane_changed ||
392 	     plane_state->update_bits.addr_update) {
393 
394 		/* SubVP save surface address if needed */
395 		if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && pipe_mall_type == SUBVP_MAIN) {
396 			hwss_add_dmub_subvp_save_surf_addr(seq_state, dc->ctx->dmub_srv,
397 				&pipe_ctx->plane_state->address, pipe_ctx->subvp_index);
398 		}
399 
400 		/* Update plane address */
401 		hwss_add_hubp_update_plane_addr(seq_state, dc, pipe_ctx);
402 	}
403 
404 	/* Step 18: HUBP set blank - enable plane */
405 	if (pipe_ctx->update_flags.bits.enable)
406 		hwss_add_hubp_set_blank(seq_state, hubp, false);
407 
408 	/* Step 19: Phantom HUBP post enable */
409 	if (pipe_mall_type == SUBVP_PHANTOM && hubp->funcs->phantom_hubp_post_enable)
410 		hwss_add_phantom_hubp_post_enable(seq_state, hubp);
411 }
412 
dcn50_update_mpcc_sequence(struct dc * dc,struct pipe_ctx * pipe_ctx,struct block_sequence_state * seq_state)413 void dcn50_update_mpcc_sequence(struct dc *dc,
414 				struct pipe_ctx *pipe_ctx,
415 				struct block_sequence_state *seq_state)
416 {
417 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
418 	struct mpcc_blnd_cfg blnd_cfg = {0};
419 	bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha;
420 	int mpcc_id;
421 	struct mpcc *new_mpcc;
422 	struct mpc *mpc = dc->res_pool->mpc;
423 	struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
424 
425 	if (!hubp || !pipe_ctx->plane_state)
426 		return;
427 
428 	/* Initialize blend configuration */
429 	blnd_cfg.overlap_only = false;
430 	blnd_cfg.global_gain = 0xfff;
431 
432 	if (per_pixel_alpha) {
433 		blnd_cfg.pre_multiplied_alpha = pipe_ctx->plane_state->pre_multiplied_alpha;
434 		if (pipe_ctx->plane_state->global_alpha) {
435 			blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
436 			blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
437 		} else {
438 			blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
439 		}
440 	} else {
441 		blnd_cfg.pre_multiplied_alpha = false;
442 		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
443 	}
444 
445 	if (pipe_ctx->plane_state->global_alpha)
446 		blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
447 	else
448 		blnd_cfg.global_alpha = 0xfff;
449 
450 	blnd_cfg.background_color_bpc = 4;
451 	blnd_cfg.bottom_gain_mode = 0;
452 	blnd_cfg.top_gain = 0x1f000;
453 	blnd_cfg.bottom_inside_gain = 0x1f000;
454 	blnd_cfg.bottom_outside_gain = 0x1f000;
455 
456 	if (pipe_ctx->plane_state->format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA)
457 		blnd_cfg.pre_multiplied_alpha = false;
458 
459 	/* MPCC instance is equal to HUBP instance */
460 	mpcc_id = hubp->inst;
461 
462 	/* Step 1: Update blending if no full update needed */
463 	if (!pipe_ctx->plane_state->update_bits.full_update &&
464 	    !pipe_ctx->update_flags.bits.mpcc) {
465 
466 		/* Update blending configuration */
467 		hwss_add_mpc_update_blending(seq_state, mpc, blnd_cfg, mpcc_id);
468 
469 		/* Update visual confirm color */
470 		hwss_add_mpc_update_visual_confirm(seq_state, dc, pipe_ctx, mpcc_id);
471 		return;
472 	}
473 
474 	/* Step 2: Get existing MPCC for DPP */
475 	new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
476 
477 	/* Step 3: Remove MPCC if being used */
478 	if (new_mpcc != NULL) {
479 		hwss_add_mpc_remove_mpcc(seq_state, mpc, mpc_tree_params, new_mpcc);
480 	} else {
481 		/* Step 4: Assert MPCC idle (debug only) */
482 		if (dc->debug.sanity_checks)
483 			hwss_add_mpc_assert_idle_mpcc(seq_state, mpc, mpcc_id);
484 	}
485 
486 	/* Step 5: Insert new plane into MPC tree */
487 	hwss_add_mpc_insert_plane(seq_state, mpc, mpc_tree_params, blnd_cfg, NULL, NULL, hubp->inst, mpcc_id);
488 
489 	/* Step 6: Update visual confirm color */
490 	hwss_add_mpc_update_visual_confirm(seq_state, dc, pipe_ctx, mpcc_id);
491 
492 	/* Step 7: Set HUBP OPP and MPCC IDs */
493 	hubp->opp_id = pipe_ctx->stream_res.opp->inst;
494 	hubp->mpcc_id = mpcc_id;
495 }
496 
dcn50_setup_hpo_hw_control(const struct dce_hwseq * hws,bool enable)497 static void dcn50_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable)
498 {
499 	REG_UPDATE(HPO_TOP_HW_CONTROL, HPO_IO_EN, enable);
500 }
501 
dcn50_program_front_end_for_ctx(struct dc * dc,struct dc_state * context)502 void dcn50_program_front_end_for_ctx(
503 	struct dc *dc,
504 	struct dc_state *context)
505 {
506 	if (resource_is_pipe_topology_changed(dc->current_state, context))
507 		resource_log_pipe_topology_update(dc, context);
508 
509 	hwss_build_full_sequence(dc,
510 		context->block_sequence,
511 		&(context->block_sequence_steps),
512 		context, false);
513 	hwss_execute_sequence(dc,
514 		context->block_sequence,
515 		context->block_sequence_steps);
516 }
517 
dcn50_post_unlock_program_front_end(struct dc * dc,struct dc_state * context)518 void dcn50_post_unlock_program_front_end(
519 	struct dc *dc,
520 	struct dc_state *context)
521 {
522 	hwss_build_post_unlock_full_sequence(dc,
523 		context->block_sequence,
524 		&(context->block_sequence_steps),
525 		context);
526 	hwss_execute_sequence(dc,
527 		context->block_sequence,
528 		context->block_sequence_steps);
529 }
530 
dcn50_init_hw(struct dc * dc)531 void dcn50_init_hw(struct dc *dc)
532 {
533 	struct abm **abms = dc->res_pool->multiple_abms;
534 	struct dce_hwseq *hws = dc->hwseq;
535 	struct dc_bios *dcb = dc->ctx->dc_bios;
536 	struct resource_pool *res_pool = dc->res_pool;
537 	unsigned int i;
538 	unsigned int edp_num;
539 	uint32_t backlight = MAX_BACKLIGHT_LEVEL;
540 	uint32_t user_level = MAX_BACKLIGHT_LEVEL;
541 	int current_dchub_ref_freq = 0;
542 
543 	if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
544 		dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
545 
546 		// mark dcmode limits present if any clock has distinct AC and DC values from SMU
547 		dc->caps.dcmode_power_limits_present = dc->clk_mgr->funcs->is_dc_mode_present &&
548 				dc->clk_mgr->funcs->is_dc_mode_present(dc->clk_mgr);
549 	}
550 
551 	// Initialize the dccg
552 	if (res_pool->dccg->funcs->dccg_init)
553 		res_pool->dccg->funcs->dccg_init(res_pool->dccg);
554 
555 	// Disable DMUB Initialization until IPS state programming is finalized
556 	//if (!dcb->funcs->is_accelerated_mode(dcb)) {
557 	//	hws->funcs.bios_golden_init(dc);
558 	//}
559 
560 	// Set default OPTC memory power states
561 	if (dc->debug.enable_mem_low_power.bits.optc) {
562 		// Shutdown when unassigned and light sleep in VBLANK
563 		REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
564 	}
565 
566 	if (dc->debug.enable_mem_low_power.bits.vga) {
567 		// Power down VGA memory
568 		REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
569 	}
570 
571 	if (dc->ctx->dc_bios->fw_info_valid) {
572 		res_pool->ref_clocks.xtalin_clock_inKhz =
573 				dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
574 
575 		if (res_pool->hubbub) {
576 			(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
577 					dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
578 					&res_pool->ref_clocks.dccg_ref_clock_inKhz);
579 
580 			current_dchub_ref_freq = res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
581 
582 			(res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
583 					res_pool->ref_clocks.dccg_ref_clock_inKhz,
584 					&res_pool->ref_clocks.dchub_ref_clock_inKhz);
585 		} else {
586 			// Not all ASICs have DCCG sw component
587 			res_pool->ref_clocks.dccg_ref_clock_inKhz =
588 					res_pool->ref_clocks.xtalin_clock_inKhz;
589 			res_pool->ref_clocks.dchub_ref_clock_inKhz =
590 					res_pool->ref_clocks.xtalin_clock_inKhz;
591 		}
592 	} else
593 		ASSERT_CRITICAL(false);
594 
595 	for (i = 0; i < dc->link_count; i++) {
596 		/* Power up AND update implementation according to the
597 		 * required signal (which may be different from the
598 		 * default signal on connector).
599 		 */
600 		struct dc_link *link = dc->links[i];
601 
602 		link->link_enc->funcs->hw_init(link->link_enc);
603 
604 		/* Check for enabled DIG to identify enabled display */
605 		if (link->link_enc->funcs->is_dig_enabled &&
606 			link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
607 			link->link_status.link_active = true;
608 			link->phy_state.symclk_state = SYMCLK_ON_TX_ON;
609 			if (link->link_enc->funcs->fec_is_active &&
610 					link->link_enc->funcs->fec_is_active(link->link_enc))
611 				link->fec_state = dc_link_fec_enabled;
612 		}
613 	}
614 
615 	/* enable_power_gating_plane before dsc_pg_control because
616 	 * FORCEON = 1 with hw default value on bootup, resume from s3
617 	 */
618 	if (hws->funcs.enable_power_gating_plane)
619 		hws->funcs.enable_power_gating_plane(dc->hwseq, true);
620 
621 	/* we want to turn off all dp displays before doing detection */
622 	dc->link_srv->blank_all_dp_displays(dc);
623 
624 	/* If taking control over from VBIOS, we may want to optimize our first
625 	 * mode set, so we need to skip powering down pipes until we know which
626 	 * pipes we want to use.
627 	 * Otherwise, if taking control is not possible, we need to power
628 	 * everything down.
629 	 */
630 	if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
631 		/* Disable boot optimizations means power down everything including PHY, DIG,
632 		 * and OTG (i.e. the boot is not optimized because we do a full power down).
633 		 */
634 		if (dc->hwss.enable_accelerated_mode && dc->debug.disable_boot_optimizations)
635 			dc->hwss.enable_accelerated_mode(dc, dc->current_state);
636 		else
637 			hws->funcs.init_pipes(dc, dc->current_state);
638 
639 		if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
640 			dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
641 					!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
642 
643 		if (dc->clk_mgr && dc->clk_mgr->funcs)
644 			dcn50_initialize_min_clocks(dc);
645 
646 		/* On HW init, allow idle optimizations after pipes have been turned off.
647 		 *
648 		 * In certain D3 cases (i.e. BOCO / BOMACO) it's possible that hardware state
649 		 * is reset (i.e. not in idle at the time hw init is called), but software state
650 		 * still has idle_optimizations = true, so we must disable idle optimizations first
651 		 * (i.e. set false), then re-enable (set true).
652 		 */
653 		dc_allow_idle_optimizations(dc, false);
654 		dc_allow_idle_optimizations(dc, true);
655 	}
656 
657 	/* In headless boot cases, DIG may be turned
658 	 * on which causes HW/SW discrepancies.
659 	 * To avoid this, power down hardware on boot
660 	 * if DIG is turned on and seamless boot not enabled
661 	 */
662 	if (!dc->config.seamless_boot_edp_requested) {
663 		struct dc_link *edp_links[MAX_NUM_EDP];
664 		struct dc_link *edp_link;
665 
666 		dc_get_edp_links(dc, edp_links, &edp_num);
667 		if (edp_num) {
668 			for (i = 0; i < edp_num; i++) {
669 				edp_link = edp_links[i];
670 				if (edp_link->link_enc->funcs->is_dig_enabled &&
671 						edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
672 						dc->hwss.edp_backlight_control &&
673 						hws->funcs.power_down &&
674 						dc->hwss.edp_power_control) {
675 					dc->hwss.edp_backlight_control(edp_link, false);
676 					hws->funcs.power_down(dc);
677 					dc->hwss.edp_power_control(edp_link, false);
678 				}
679 			}
680 		} else {
681 			for (i = 0; i < dc->link_count; i++) {
682 				struct dc_link *link = dc->links[i];
683 
684 				if (link->link_enc->funcs->is_dig_enabled &&
685 						link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
686 						hws->funcs.power_down) {
687 					hws->funcs.power_down(dc);
688 					break;
689 				}
690 
691 			}
692 		}
693 	}
694 
695 	for (i = 0; i < res_pool->audio_count; i++) {
696 		struct audio *audio = res_pool->audios[i];
697 
698 		audio->funcs->hw_init(audio);
699 	}
700 
701 	for (i = 0; i < dc->link_count; i++) {
702 		struct dc_link *link = dc->links[i];
703 
704 		if (link->panel_cntl) {
705 			backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
706 			user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
707 		}
708 	}
709 
710 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
711 		if (abms[i] != NULL && abms[i]->funcs != NULL)
712 			abms[i]->funcs->abm_init(abms[i], backlight, user_level);
713 	}
714 
715 	/* power AFMT HDMI memory TODO: may move to dis/en output save power*/
716 	if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl)
717 		dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, false);
718 
719 	if (!dc->debug.disable_clock_gate) {
720 		/* enable all DCN clock gating */
721 		if (dc->res_pool->dccg && dc->res_pool->dccg->funcs && dc->res_pool->dccg->funcs->allow_clock_gating)
722 			dc->res_pool->dccg->funcs->allow_clock_gating(dc->res_pool->dccg, true);
723 
724 		REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
725 	}
726 
727 	dcn50_setup_hpo_hw_control(hws, true);
728 
729 	if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
730 		dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
731 
732 	if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
733 		dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
734 
735 	if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
736 		dc->res_pool->hubbub->funcs->force_pstate_change_control(
737 				dc->res_pool->hubbub, false, false);
738 
739 	if (dc->res_pool->hubbub->funcs->init_crb)
740 		dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
741 
742 	if (dc->res_pool->hubbub->funcs->set_request_limit && dc->config.sdpif_request_limit_words_per_umc > 0)
743 		dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub,
744 			dc->ctx->dc_bios->vram_info.num_chans, dc->config.sdpif_request_limit_words_per_umc);
745 
746 	// Get DMCUB capabilities
747 	if (dc->ctx->dmub_srv) {
748 		dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
749 		dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
750 		dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
751 		dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
752 		dc->debug.fams2_config.bits.enable &=
753 				dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver; // sw & fw fams versions must match for support
754 		if ((!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box)
755 			|| res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq) {
756 			/* update bounding box if FAMS2 disabled, or if dchub clk has changed */
757 			if (dc->clk_mgr)
758 				dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
759 		}
760 	}
761 }
762