diff options
| author | Anthony Koo <Anthony.Koo@amd.com> | 2019-01-20 09:23:07 +0300 | 
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2019-02-06 21:31:22 +0300 | 
| commit | fb55546ea4b50f04ef41c196b8ac1824e26bc48c (patch) | |
| tree | ff85e381a2d761983efc63759830ca99d50779bc | |
| parent | 9c0fb8d45bfcf2e8f080489913db443c1fd241ed (diff) | |
| download | linux-fb55546ea4b50f04ef41c196b8ac1824e26bc48c.tar.xz | |
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>
3 files changed, 85 insertions, 82 deletions
| diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a4386348a981..4df8a43b5018 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -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)  {  	int i; @@ -2642,6 +2647,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {  	.program_gamut_remap = program_gamut_remap,  	.program_output_csc = program_output_csc,  	.init_hw = init_hw, +	.init_pipes = init_pipes,  	.apply_ctx_to_hw = dce110_apply_ctx_to_hw,  	.apply_ctx_for_surface = dce110_apply_ctx_for_surface,  	.update_plane_addr = update_plane_addr, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a03bbbf94d5d..117d9d8227f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -956,97 +956,34 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)  					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; -	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++) {  		struct timing_generator *tg = dc->res_pool->timing_generators[i];  		if (tg->funcs->is_tg_enabled(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)) {  			tg->funcs->set_blank(tg, true);  			hwss_wait_for_blank_complete(tg);  		}  	} -	/* Reset all MPCC muxes */  	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 pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[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]; + +		dpp->funcs->dpp_reset(dpp);  		pipe_ctx->stream_res.tg = tg;  		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];  		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))  			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); @@ -1084,10 +1012,73 @@ static void dcn10_init_hw(struct dc *dc)  		tg->funcs->tg_init(tg);  	} +} + +static void dcn10_init_hw(struct dc *dc) +{ +	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); -	/* end of FPGA. Below if real ASIC */ -	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) +		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; +	} + +	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++) {  		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);  	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( @@ -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 = {  	.program_gamut_remap = program_gamut_remap,  	.init_hw = dcn10_init_hw, +	.init_pipes = dcn10_init_pipes,  	.apply_ctx_to_hw = dce110_apply_ctx_to_hw,  	.apply_ctx_for_surface = dcn10_apply_ctx_for_surface,  	.update_plane_addr = dcn10_update_plane_addr, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index d6a85f48b6d1..341b4810288c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -70,6 +70,8 @@ struct hw_sequencer_funcs {  	void (*init_hw)(struct dc *dc); +	void (*init_pipes)(struct dc *dc, struct dc_state *context); +  	enum dc_status (*apply_ctx_to_hw)(  			struct dc *dc, struct dc_state *context); | 
