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(¶ms);
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