Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,238 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright 2026 Advanced Micro Devices, Inc.
*/
#include "dm_services.h"
#include "core_types.h"
#include "resource.h"
#include "dce/dce_hwseq.h"
#include "dcn10/dcn10_hwseq.h"
#include "reg_helper.h"
#include "hubp.h"
#include "dchubbub.h"
#include "timing_generator.h"
#include "opp.h"
#include "mpc.h"
#include "dcn42b_hwseq.h"
#define CTX \
hws->ctx
#define REG(reg)\
hws->regs->reg
#define DC_LOGGER \
hws->ctx->logger
#undef FN
#define FN(reg_name, field_name) \
hws->shifts->field_name, hws->masks->field_name
/*
* dcn42b_init_pipes - Initialize pipes for dcn42b
*
* This function is modeled after dcn10_init_pipes but handles the case
* where num_timing_generator != num_pipes (e.g., 3 TGs but 4 pipes).
*
* For dcn42b:
* - num_timing_generator = 3
* - num_pipes (num_dpp) = 4
*
* The key difference is that we iterate over timing generators separately
* from pipes to avoid accessing timing_generators[i] when i >= num_timing_generator.
*/
void dcn42b_init_pipes(struct dc *dc, struct dc_state *context)
{
uint8_t i;
struct dce_hwseq *hws = dc->hwseq;
struct hubbub *hubbub = dc->res_pool->hubbub;
bool can_apply_seamless_boot = false;
bool tg_enabled[MAX_PIPES] = {false};
for (i = 0; i < context->stream_count; i++) {
if (context->streams[i]->apply_seamless_boot_optimization) {
can_apply_seamless_boot = true;
break;
}
}
for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
struct timing_generator *tg = dc->res_pool->timing_generators[i];
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
/* There is assumption that pipe_ctx is not mapping irregularly
* to non-preferred front end. If pipe_ctx->stream is not NULL,
* we will use the pipe, so don't disable
*/
if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
continue;
/* Blank controller using driver code instead of
* command table.
*/
if (tg->funcs->is_tg_enabled(tg)) {
if (hws->funcs.init_blank != NULL) {
hws->funcs.init_blank(dc, tg);
tg->funcs->lock(tg);
} else {
tg->funcs->lock(tg);
tg->funcs->set_blank(tg, true);
hwss_wait_for_blank_complete(tg);
}
}
}
/* Reset det size */
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct hubp *hubp = dc->res_pool->hubps[i];
/* Do not need to reset for seamless boot */
if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
continue;
if (hubbub && hubp) {
if (hubbub->funcs->program_det_size)
hubbub->funcs->program_det_size(hubbub, hubp->inst, 0);
if (hubbub->funcs->program_det_segments)
hubbub->funcs->program_det_segments(hubbub, hubp->inst, 0);
}
}
/* num_opp will be equal to number of mpcc */
for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
/* Cannot reset the MPC mux if seamless boot */
if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
continue;
dc->res_pool->mpc->funcs->mpc_init_single_inst(
dc->res_pool->mpc, i);
}
/* initialize DWB pointer to MCIF_WB */
for (i = 0; i < dc->res_pool->res_cap->num_dwb; i++)
dc->res_pool->dwbc[i]->mcif = dc->res_pool->mcif_wb[i];
for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
struct timing_generator *tg = dc->res_pool->timing_generators[i];
struct hubp *hubp = dc->res_pool->hubps[i];
struct dpp *dpp = dc->res_pool->dpps[i];
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
/* There is assumption that pipe_ctx is not mapping irregularly
* to non-preferred front end. If pipe_ctx->stream is not NULL,
* we will use the pipe, so don't disable
*/
if (can_apply_seamless_boot &&
pipe_ctx->stream != NULL &&
pipe_ctx->stream_res.tg->funcs->is_tg_enabled(
pipe_ctx->stream_res.tg)) {
// Enable double buffering for OTG_BLANK no matter if
// seamless boot is enabled or not to suppress global sync
// signals when OTG blanked. This is to prevent pipe from
// requesting data while in PSR.
tg->funcs->tg_init(tg);
hubp->power_gated = true;
tg_enabled[i] = true;
continue;
}
/* Disable on the current state so the new one isn't cleared. */
pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
hubp->funcs->hubp_reset(hubp);
dpp->funcs->dpp_reset(dpp);
pipe_ctx->stream_res.tg = tg;
pipe_ctx->pipe_idx = i;
pipe_ctx->plane_res.hubp = hubp;
pipe_ctx->plane_res.dpp = dpp;
pipe_ctx->plane_res.mpcc_inst = (uint8_t)dpp->inst;
hubp->mpcc_id = dpp->inst;
hubp->opp_id = OPP_ID_INVALID;
hubp->power_gated = false;
dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx);
if (tg->funcs->is_tg_enabled(tg))
tg->funcs->unlock(tg);
dc->hwss.disable_plane(dc, context, pipe_ctx);
pipe_ctx->stream_res.tg = NULL;
pipe_ctx->plane_res.hubp = NULL;
if (tg->funcs->is_tg_enabled(tg)) {
if (tg->funcs->init_odm)
tg->funcs->init_odm(tg);
}
tg->funcs->tg_init(tg);
}
/* Clean up MPC tree */
for (i = 0; i < dc->res_pool->pipe_count; i++) {
if (tg_enabled[i]) {
if (dc->res_pool->opps[i]->mpc_tree_params.opp_list) {
if (dc->res_pool->opps[i]->mpc_tree_params.opp_list->mpcc_bot) {
int bot_id = dc->res_pool->opps[i]->mpc_tree_params.opp_list->mpcc_bot->mpcc_id;
if ((bot_id < MAX_MPCC) && (bot_id < MAX_PIPES) && (!tg_enabled[bot_id]))
dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
}
}
}
}
/* Power gate DSCs */
if (hws->funcs.dsc_pg_control != NULL) {
uint32_t num_opps = 0;
uint32_t opp_id_src0 = OPP_ID_INVALID;
uint32_t opp_id_src1 = OPP_ID_INVALID;
// Step 1: To find out which OPTC is running & OPTC DSC is ON
// We can't use res_pool->res_cap->num_timing_generator to check
// Because it records display pipes default setting built in driver,
// not display pipes of the current chip.
// Some ASICs would be fused display pipes less than the default setting.
// In dcnxx_resource_construct function, driver would obatin real information.
for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
uint32_t optc_dsc_state = 0;
struct timing_generator *tg = dc->res_pool->timing_generators[i];
if (tg->funcs->is_tg_enabled(tg)) {
if (tg->funcs->get_dsc_status)
tg->funcs->get_dsc_status(tg, &optc_dsc_state);
// Only one OPTC with DSC is ON, so if we got one result, we would exit this block.
// non-zero value is DSC enabled
if (optc_dsc_state != 0) {
tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
break;
}
}
}
// Step 2: To power down DSC but skip DSC of running OPTC
for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
struct dcn_dsc_state s = {0};
dc->res_pool->dscs[i]->funcs->dsc_read_state(dc->res_pool->dscs[i], &s);
if ((s.dsc_opp_source == opp_id_src0 || s.dsc_opp_source == opp_id_src1) &&
s.dsc_clock_en && s.dsc_fw_en)
continue;
hws->funcs.dsc_pg_control(hws, dc->res_pool->dscs[i]->inst, false);
}
}
}
@@ -0,0 +1,15 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright 2026 Advanced Micro Devices, Inc.
*/
#ifndef __DC_HWSS_DCN42B_H__
#define __DC_HWSS_DCN42B_H__
#include "dc.h"
#include "hw_sequencer_private.h"
void dcn42b_init_pipes(struct dc *dc, struct dc_state *context);
#endif /* __DC_HWSS_DCN42B_H__ */
@@ -0,0 +1,20 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright 2026 Advanced Micro Devices, Inc.
*/
#include "dcn20/dcn20_hwseq.h"
#include "dcn42/dcn42_init.h"
#include "dcn42b_hwseq.h"
#include "dcn42b_init.h"
void dcn42b_hw_sequencer_init_functions(struct dc *dc)
{
/* Initialize with dcn42 functions first */
dcn42_hw_sequencer_init_functions(dc);
/* Override only init_pipes with dcn42b version */
dc->hwseq->funcs.init_pipes = dcn42b_init_pipes;
}
@@ -0,0 +1,14 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright 2026 Advanced Micro Devices, Inc.
*/
#ifndef __DC_DCN42B_INIT_H__
#define __DC_DCN42B_INIT_H__
struct dc;
void dcn42b_hw_sequencer_init_functions(struct dc *dc);
#endif /* __DC_DCN42B_INIT_H__ */