drm/amd/display: refactor init_hw to isolate pipe related init
[Why] Pipe related init is possible to optimized if we know what we intend to program, and if we can determine it matches what is already programmed for the pipe. [How] First step is to isolate the pipe related init code Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
9c0fb8d45b
commit
fb55546ea4
|
@ -2275,6 +2275,11 @@ static void dce110_enable_per_frame_crtc_position_reset(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_pipes(struct dc *dc, struct dc_state *context)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
static void init_hw(struct dc *dc)
|
static void init_hw(struct dc *dc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -2642,6 +2647,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
|
||||||
.program_gamut_remap = program_gamut_remap,
|
.program_gamut_remap = program_gamut_remap,
|
||||||
.program_output_csc = program_output_csc,
|
.program_output_csc = program_output_csc,
|
||||||
.init_hw = init_hw,
|
.init_hw = init_hw,
|
||||||
|
.init_pipes = init_pipes,
|
||||||
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
||||||
.apply_ctx_for_surface = dce110_apply_ctx_for_surface,
|
.apply_ctx_for_surface = dce110_apply_ctx_for_surface,
|
||||||
.update_plane_addr = update_plane_addr,
|
.update_plane_addr = update_plane_addr,
|
||||||
|
|
|
@ -956,97 +956,34 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||||
pipe_ctx->pipe_idx);
|
pipe_ctx->pipe_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dcn10_init_hw(struct dc *dc)
|
static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct abm *abm = dc->res_pool->abm;
|
|
||||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
|
||||||
struct dce_hwseq *hws = dc->hwseq;
|
|
||||||
struct dc_bios *dcb = dc->ctx->dc_bios;
|
|
||||||
struct dc_state *context = dc->current_state;
|
|
||||||
|
|
||||||
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
|
|
||||||
REG_WRITE(REFCLK_CNTL, 0);
|
|
||||||
REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
|
|
||||||
REG_WRITE(DIO_MEM_PWR_CTRL, 0);
|
|
||||||
|
|
||||||
if (!dc->debug.disable_clock_gate) {
|
|
||||||
/* enable all DCN clock gating */
|
|
||||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
|
|
||||||
|
|
||||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
|
|
||||||
|
|
||||||
REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
enable_power_gating_plane(dc->hwseq, true);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (!dcb->funcs->is_accelerated_mode(dcb)) {
|
|
||||||
bool allow_self_fresh_force_enable =
|
|
||||||
hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub);
|
|
||||||
|
|
||||||
bios_golden_init(dc);
|
|
||||||
|
|
||||||
/* WA for making DF sleep when idle after resume from S0i3.
|
|
||||||
* DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by
|
|
||||||
* command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0
|
|
||||||
* before calling command table and it changed to 1 after,
|
|
||||||
* it should be set back to 0.
|
|
||||||
*/
|
|
||||||
if (allow_self_fresh_force_enable == false &&
|
|
||||||
hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub))
|
|
||||||
hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, true);
|
|
||||||
|
|
||||||
disable_vga(dc->hwseq);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < dc->link_count; i++) {
|
|
||||||
/* Power up AND update implementation according to the
|
|
||||||
* required signal (which may be different from the
|
|
||||||
* default signal on connector).
|
|
||||||
*/
|
|
||||||
struct dc_link *link = dc->links[i];
|
|
||||||
|
|
||||||
if (link->link_enc->connector.id == CONNECTOR_ID_EDP)
|
|
||||||
dc->hwss.edp_power_control(link, true);
|
|
||||||
|
|
||||||
link->link_enc->funcs->hw_init(link->link_enc);
|
|
||||||
|
|
||||||
/* Check for enabled DIG to identify enabled display */
|
|
||||||
if (link->link_enc->funcs->is_dig_enabled &&
|
|
||||||
link->link_enc->funcs->is_dig_enabled(link->link_enc))
|
|
||||||
link->link_status.link_active = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||||
struct timing_generator *tg = dc->res_pool->timing_generators[i];
|
struct timing_generator *tg = dc->res_pool->timing_generators[i];
|
||||||
|
|
||||||
if (tg->funcs->is_tg_enabled(tg))
|
if (tg->funcs->is_tg_enabled(tg))
|
||||||
tg->funcs->lock(tg);
|
tg->funcs->lock(tg);
|
||||||
}
|
|
||||||
|
|
||||||
/* Blank controller using driver code instead of
|
|
||||||
* command table.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
|
||||||
struct timing_generator *tg = dc->res_pool->timing_generators[i];
|
|
||||||
|
|
||||||
|
/* Blank controller using driver code instead of
|
||||||
|
* command table.
|
||||||
|
*/
|
||||||
if (tg->funcs->is_tg_enabled(tg)) {
|
if (tg->funcs->is_tg_enabled(tg)) {
|
||||||
tg->funcs->set_blank(tg, true);
|
tg->funcs->set_blank(tg, true);
|
||||||
hwss_wait_for_blank_complete(tg);
|
hwss_wait_for_blank_complete(tg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset all MPCC muxes */
|
|
||||||
dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc);
|
dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc);
|
||||||
|
|
||||||
for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
|
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||||
struct timing_generator *tg = dc->res_pool->timing_generators[i];
|
struct timing_generator *tg = dc->res_pool->timing_generators[i];
|
||||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
|
||||||
struct hubp *hubp = dc->res_pool->hubps[i];
|
struct hubp *hubp = dc->res_pool->hubps[i];
|
||||||
struct dpp *dpp = dc->res_pool->dpps[i];
|
struct dpp *dpp = dc->res_pool->dpps[i];
|
||||||
|
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||||
|
|
||||||
|
dpp->funcs->dpp_reset(dpp);
|
||||||
|
|
||||||
pipe_ctx->stream_res.tg = tg;
|
pipe_ctx->stream_res.tg = tg;
|
||||||
pipe_ctx->pipe_idx = i;
|
pipe_ctx->pipe_idx = i;
|
||||||
|
@ -1064,18 +1001,9 @@ static void dcn10_init_hw(struct dc *dc)
|
||||||
pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
|
pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
|
||||||
|
|
||||||
hwss1_plane_atomic_disconnect(dc, pipe_ctx);
|
hwss1_plane_atomic_disconnect(dc, pipe_ctx);
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
|
||||||
struct timing_generator *tg = dc->res_pool->timing_generators[i];
|
|
||||||
|
|
||||||
if (tg->funcs->is_tg_enabled(tg))
|
if (tg->funcs->is_tg_enabled(tg))
|
||||||
tg->funcs->unlock(tg);
|
tg->funcs->unlock(tg);
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
|
||||||
struct timing_generator *tg = dc->res_pool->timing_generators[i];
|
|
||||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
|
||||||
|
|
||||||
dcn10_disable_plane(dc, pipe_ctx);
|
dcn10_disable_plane(dc, pipe_ctx);
|
||||||
|
|
||||||
|
@ -1084,10 +1012,73 @@ static void dcn10_init_hw(struct dc *dc)
|
||||||
|
|
||||||
tg->funcs->tg_init(tg);
|
tg->funcs->tg_init(tg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* end of FPGA. Below if real ASIC */
|
static void dcn10_init_hw(struct dc *dc)
|
||||||
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
|
{
|
||||||
|
int i;
|
||||||
|
struct abm *abm = dc->res_pool->abm;
|
||||||
|
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||||
|
struct dce_hwseq *hws = dc->hwseq;
|
||||||
|
struct dc_bios *dcb = dc->ctx->dc_bios;
|
||||||
|
|
||||||
|
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
|
||||||
|
REG_WRITE(REFCLK_CNTL, 0);
|
||||||
|
REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
|
||||||
|
REG_WRITE(DIO_MEM_PWR_CTRL, 0);
|
||||||
|
|
||||||
|
if (!dc->debug.disable_clock_gate) {
|
||||||
|
/* enable all DCN clock gating */
|
||||||
|
REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
|
||||||
|
|
||||||
|
REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
|
||||||
|
|
||||||
|
REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_power_gating_plane(dc->hwseq, true);
|
||||||
|
|
||||||
|
/* end of FPGA. Below if real ASIC */
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dcb->funcs->is_accelerated_mode(dcb)) {
|
||||||
|
bool allow_self_fresh_force_enable =
|
||||||
|
hububu1_is_allow_self_refresh_enabled(
|
||||||
|
dc->res_pool->hubbub);
|
||||||
|
|
||||||
|
bios_golden_init(dc);
|
||||||
|
|
||||||
|
/* WA for making DF sleep when idle after resume from S0i3.
|
||||||
|
* DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by
|
||||||
|
* command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0
|
||||||
|
* before calling command table and it changed to 1 after,
|
||||||
|
* it should be set back to 0.
|
||||||
|
*/
|
||||||
|
if (allow_self_fresh_force_enable == false &&
|
||||||
|
hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub))
|
||||||
|
hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, true);
|
||||||
|
|
||||||
|
disable_vga(dc->hwseq);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < dc->link_count; i++) {
|
||||||
|
/* Power up AND update implementation according to the
|
||||||
|
* required signal (which may be different from the
|
||||||
|
* default signal on connector).
|
||||||
|
*/
|
||||||
|
struct dc_link *link = dc->links[i];
|
||||||
|
|
||||||
|
if (link->link_enc->connector.id == CONNECTOR_ID_EDP)
|
||||||
|
dc->hwss.edp_power_control(link, true);
|
||||||
|
|
||||||
|
link->link_enc->funcs->hw_init(link->link_enc);
|
||||||
|
|
||||||
|
/* Check for enabled DIG to identify enabled display */
|
||||||
|
if (link->link_enc->funcs->is_dig_enabled &&
|
||||||
|
link->link_enc->funcs->is_dig_enabled(link->link_enc))
|
||||||
|
link->link_status.link_active = true;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < dc->res_pool->audio_count; i++) {
|
for (i = 0; i < dc->res_pool->audio_count; i++) {
|
||||||
struct audio *audio = dc->res_pool->audios[i];
|
struct audio *audio = dc->res_pool->audios[i];
|
||||||
|
@ -1118,6 +1109,9 @@ static void dcn10_init_hw(struct dc *dc)
|
||||||
enable_power_gating_plane(dc->hwseq, true);
|
enable_power_gating_plane(dc->hwseq, true);
|
||||||
|
|
||||||
memset(&dc->res_pool->clk_mgr->clks, 0, sizeof(dc->res_pool->clk_mgr->clks));
|
memset(&dc->res_pool->clk_mgr->clks, 0, sizeof(dc->res_pool->clk_mgr->clks));
|
||||||
|
|
||||||
|
if (dc->hwss.init_pipes)
|
||||||
|
dc->hwss.init_pipes(dc, dc->current_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reset_hw_ctx_wrap(
|
static void reset_hw_ctx_wrap(
|
||||||
|
@ -2718,6 +2712,7 @@ static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)
|
||||||
static const struct hw_sequencer_funcs dcn10_funcs = {
|
static const struct hw_sequencer_funcs dcn10_funcs = {
|
||||||
.program_gamut_remap = program_gamut_remap,
|
.program_gamut_remap = program_gamut_remap,
|
||||||
.init_hw = dcn10_init_hw,
|
.init_hw = dcn10_init_hw,
|
||||||
|
.init_pipes = dcn10_init_pipes,
|
||||||
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
||||||
.apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
|
.apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
|
||||||
.update_plane_addr = dcn10_update_plane_addr,
|
.update_plane_addr = dcn10_update_plane_addr,
|
||||||
|
|
|
@ -70,6 +70,8 @@ struct hw_sequencer_funcs {
|
||||||
|
|
||||||
void (*init_hw)(struct dc *dc);
|
void (*init_hw)(struct dc *dc);
|
||||||
|
|
||||||
|
void (*init_pipes)(struct dc *dc, struct dc_state *context);
|
||||||
|
|
||||||
enum dc_status (*apply_ctx_to_hw)(
|
enum dc_status (*apply_ctx_to_hw)(
|
||||||
struct dc *dc, struct dc_state *context);
|
struct dc *dc, struct dc_state *context);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue