forked from mirrors/linux
		
	drm/amd/display: Make init_hw and init_pipes generic for seamless boot
[Why] For seamless boot the init_hw sequence must be split into actual hardware vs pipes, in order to defer pipe initialization to set mode and skip of pipe-destructive sequences [How] made dcn10_init_hw and dcn10_init_pipes generic for future dcns to inherit deleted dcn20 specific versions. This is part 1 of a 2 partimplementation of seamless boot Signed-off-by: Martin Leung <martin.leung@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Leo Li <sunpeng.li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
		
							parent
							
								
									61e29b21cb
								
							
						
					
					
						commit
						8a31820b12
					
				
					 9 changed files with 309 additions and 310 deletions
				
			
		| 
						 | 
				
			
			@ -731,7 +731,7 @@ static enum bp_result link_transmitter_control(
 | 
			
		|||
 * @brief
 | 
			
		||||
 * eDP only.
 | 
			
		||||
 */
 | 
			
		||||
void hwss_edp_wait_for_hpd_ready(
 | 
			
		||||
void dce110_edp_wait_for_hpd_ready(
 | 
			
		||||
		struct dc_link *link,
 | 
			
		||||
		bool power_up)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -799,7 +799,7 @@ void hwss_edp_wait_for_hpd_ready(
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hwss_edp_power_control(
 | 
			
		||||
void dce110_edp_power_control(
 | 
			
		||||
		struct dc_link *link,
 | 
			
		||||
		bool power_up)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -881,7 +881,7 @@ void hwss_edp_power_control(
 | 
			
		|||
 * @brief
 | 
			
		||||
 * eDP only. Control the backlight of the eDP panel
 | 
			
		||||
 */
 | 
			
		||||
void hwss_edp_backlight_control(
 | 
			
		||||
void dce110_edp_backlight_control(
 | 
			
		||||
		struct dc_link *link,
 | 
			
		||||
		bool enable)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -2758,9 +2758,9 @@ static const struct hw_sequencer_funcs dce110_funcs = {
 | 
			
		|||
	.setup_stereo = NULL,
 | 
			
		||||
	.set_avmute = dce110_set_avmute,
 | 
			
		||||
	.wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
 | 
			
		||||
	.edp_backlight_control = hwss_edp_backlight_control,
 | 
			
		||||
	.edp_power_control = hwss_edp_power_control,
 | 
			
		||||
	.edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
 | 
			
		||||
	.edp_backlight_control = dce110_edp_backlight_control,
 | 
			
		||||
	.edp_power_control = dce110_edp_power_control,
 | 
			
		||||
	.edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
 | 
			
		||||
	.set_cursor_position = dce110_set_cursor_position,
 | 
			
		||||
	.set_cursor_attribute = dce110_set_cursor_attribute
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,15 +73,15 @@ void dce110_optimize_bandwidth(
 | 
			
		|||
 | 
			
		||||
void dp_receiver_power_ctrl(struct dc_link *link, bool on);
 | 
			
		||||
 | 
			
		||||
void hwss_edp_power_control(
 | 
			
		||||
void dce110_edp_power_control(
 | 
			
		||||
		struct dc_link *link,
 | 
			
		||||
		bool power_up);
 | 
			
		||||
 | 
			
		||||
void hwss_edp_backlight_control(
 | 
			
		||||
void dce110_edp_backlight_control(
 | 
			
		||||
	struct dc_link *link,
 | 
			
		||||
	bool enable);
 | 
			
		||||
 | 
			
		||||
void hwss_edp_wait_for_hpd_ready(
 | 
			
		||||
void dce110_edp_wait_for_hpd_ready(
 | 
			
		||||
		struct dc_link *link,
 | 
			
		||||
		bool power_up);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow)
 | 
			
		|||
			DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
 | 
			
		||||
bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
 | 
			
		||||
{
 | 
			
		||||
	struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
 | 
			
		||||
	uint32_t enable = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -945,6 +945,8 @@ static const struct hubbub_funcs hubbub1_funcs = {
 | 
			
		|||
	.get_dcc_compression_cap = hubbub1_get_dcc_compression_cap,
 | 
			
		||||
	.wm_read_state = hubbub1_wm_read_state,
 | 
			
		||||
	.program_watermarks = hubbub1_program_watermarks,
 | 
			
		||||
	.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
 | 
			
		||||
	.allow_self_refresh_control = hubbub1_allow_self_refresh_control,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void hubbub1_construct(struct hubbub *hubbub,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -247,7 +247,7 @@ void hubbub1_program_watermarks(
 | 
			
		|||
 | 
			
		||||
void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow);
 | 
			
		||||
 | 
			
		||||
bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubub);
 | 
			
		||||
bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubub);
 | 
			
		||||
 | 
			
		||||
void hubbub1_toggle_watermark_change_req(
 | 
			
		||||
		struct hubbub *hubbub);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -438,7 +438,7 @@ bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		|||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void enable_power_gating_plane(
 | 
			
		||||
static void dcn10_enable_power_gating_plane(
 | 
			
		||||
	struct dce_hwseq *hws,
 | 
			
		||||
	bool enable)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -460,7 +460,7 @@ static void enable_power_gating_plane(
 | 
			
		|||
	REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void disable_vga(
 | 
			
		||||
static void dcn10_disable_vga(
 | 
			
		||||
	struct dce_hwseq *hws)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int in_vga1_mode = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -493,7 +493,7 @@ static void disable_vga(
 | 
			
		|||
	REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dpp_pg_control(
 | 
			
		||||
static void dcn10_dpp_pg_control(
 | 
			
		||||
		struct dce_hwseq *hws,
 | 
			
		||||
		unsigned int dpp_inst,
 | 
			
		||||
		bool power_on)
 | 
			
		||||
| 
						 | 
				
			
			@ -545,7 +545,7 @@ static void dpp_pg_control(
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hubp_pg_control(
 | 
			
		||||
static void dcn10_hubp_pg_control(
 | 
			
		||||
		struct dce_hwseq *hws,
 | 
			
		||||
		unsigned int hubp_inst,
 | 
			
		||||
		bool power_on)
 | 
			
		||||
| 
						 | 
				
			
			@ -605,8 +605,8 @@ static void power_on_plane(
 | 
			
		|||
	if (REG(DC_IP_REQUEST_CNTL)) {
 | 
			
		||||
		REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
				IP_REQUEST_EN, 1);
 | 
			
		||||
		dpp_pg_control(hws, plane_id, true);
 | 
			
		||||
		hubp_pg_control(hws, plane_id, true);
 | 
			
		||||
		hws->ctx->dc->hwss.dpp_pg_control(hws, plane_id, true);
 | 
			
		||||
		hws->ctx->dc->hwss.hubp_pg_control(hws, plane_id, true);
 | 
			
		||||
		REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
				IP_REQUEST_EN, 0);
 | 
			
		||||
		DC_LOG_DEBUG(
 | 
			
		||||
| 
						 | 
				
			
			@ -627,7 +627,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc)
 | 
			
		|||
	REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
			IP_REQUEST_EN, 1);
 | 
			
		||||
 | 
			
		||||
	hubp_pg_control(hws, 0, false);
 | 
			
		||||
	dc->hwss.hubp_pg_control(hws, 0, false);
 | 
			
		||||
	REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
			IP_REQUEST_EN, 0);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -656,7 +656,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc)
 | 
			
		|||
	REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
			IP_REQUEST_EN, 1);
 | 
			
		||||
 | 
			
		||||
	hubp_pg_control(hws, 0, true);
 | 
			
		||||
	dc->hwss.hubp_pg_control(hws, 0, true);
 | 
			
		||||
	REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
			IP_REQUEST_EN, 0);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -664,10 +664,23 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc)
 | 
			
		|||
	hws->wa_state.DEGVIDCN10_253_applied = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bios_golden_init(struct dc *dc)
 | 
			
		||||
static void dcn10_bios_golden_init(struct dc *dc)
 | 
			
		||||
{
 | 
			
		||||
	struct dc_bios *bp = dc->ctx->dc_bios;
 | 
			
		||||
	int i;
 | 
			
		||||
	bool allow_self_fresh_force_enable = true;
 | 
			
		||||
 | 
			
		||||
	if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
 | 
			
		||||
		allow_self_fresh_force_enable =
 | 
			
		||||
				dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* 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.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	/* initialize dcn global */
 | 
			
		||||
	bp->funcs->enable_disp_power_gating(bp,
 | 
			
		||||
| 
						 | 
				
			
			@ -678,6 +691,12 @@ static void bios_golden_init(struct dc *dc)
 | 
			
		|||
		bp->funcs->enable_disp_power_gating(bp,
 | 
			
		||||
				CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
 | 
			
		||||
		if (allow_self_fresh_force_enable == false &&
 | 
			
		||||
				dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub))
 | 
			
		||||
			dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, true);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void false_optc_underflow_wa(
 | 
			
		||||
| 
						 | 
				
			
			@ -971,7 +990,7 @@ void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		|||
		dcn10_verify_allow_pstate_change_high(dc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void plane_atomic_power_down(struct dc *dc,
 | 
			
		||||
static void dcn10_plane_atomic_power_down(struct dc *dc,
 | 
			
		||||
		struct dpp *dpp,
 | 
			
		||||
		struct hubp *hubp)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -981,8 +1000,8 @@ static void plane_atomic_power_down(struct dc *dc,
 | 
			
		|||
	if (REG(DC_IP_REQUEST_CNTL)) {
 | 
			
		||||
		REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
				IP_REQUEST_EN, 1);
 | 
			
		||||
		dpp_pg_control(hws, dpp->inst, false);
 | 
			
		||||
		hubp_pg_control(hws, hubp->inst, false);
 | 
			
		||||
		dc->hwss.dpp_pg_control(hws, dpp->inst, false);
 | 
			
		||||
		dc->hwss.hubp_pg_control(hws, hubp->inst, false);
 | 
			
		||||
		dpp->funcs->dpp_reset(dpp);
 | 
			
		||||
		REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
				IP_REQUEST_EN, 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -994,7 +1013,7 @@ static void plane_atomic_power_down(struct dc *dc,
 | 
			
		|||
/* disable HW used by plane.
 | 
			
		||||
 * note:  cannot disable until disconnect is complete
 | 
			
		||||
 */
 | 
			
		||||
static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		||||
static void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct hubp *hubp = pipe_ctx->plane_res.hubp;
 | 
			
		||||
	struct dpp *dpp = pipe_ctx->plane_res.dpp;
 | 
			
		||||
| 
						 | 
				
			
			@ -1014,7 +1033,7 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		|||
	hubp->power_gated = true;
 | 
			
		||||
	dc->optimized_required = false; /* We're powering off, no need to optimize */
 | 
			
		||||
 | 
			
		||||
	plane_atomic_power_down(dc,
 | 
			
		||||
	dc->hwss.plane_atomic_power_down(dc,
 | 
			
		||||
			pipe_ctx->plane_res.dpp,
 | 
			
		||||
			pipe_ctx->plane_res.hubp);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1033,7 +1052,7 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		|||
	if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	plane_atomic_disable(dc, pipe_ctx);
 | 
			
		||||
	dc->hwss.plane_atomic_disable(dc, pipe_ctx);
 | 
			
		||||
 | 
			
		||||
	apply_DEGVIDCN10_253_wa(dc);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1068,9 +1087,14 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
 | 
			
		|||
		 * command table.
 | 
			
		||||
		 */
 | 
			
		||||
		if (tg->funcs->is_tg_enabled(tg)) {
 | 
			
		||||
			tg->funcs->lock(tg);
 | 
			
		||||
			tg->funcs->set_blank(tg, true);
 | 
			
		||||
			hwss_wait_for_blank_complete(tg);
 | 
			
		||||
			if (dc->hwss.init_blank != NULL) {
 | 
			
		||||
				dc->hwss.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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1114,12 +1138,12 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
 | 
			
		|||
		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];
 | 
			
		||||
 | 
			
		||||
		hwss1_plane_atomic_disconnect(dc, pipe_ctx);
 | 
			
		||||
		dc->hwss.plane_atomic_disconnect(dc, pipe_ctx);
 | 
			
		||||
 | 
			
		||||
		if (tg->funcs->is_tg_enabled(tg))
 | 
			
		||||
			tg->funcs->unlock(tg);
 | 
			
		||||
 | 
			
		||||
		dcn10_disable_plane(dc, pipe_ctx);
 | 
			
		||||
		dc->hwss.disable_plane(dc, pipe_ctx);
 | 
			
		||||
 | 
			
		||||
		pipe_ctx->stream_res.tg = NULL;
 | 
			
		||||
		pipe_ctx->plane_res.hubp = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -1135,8 +1159,17 @@ static void dcn10_init_hw(struct dc *dc)
 | 
			
		|||
	struct dmcu *dmcu = dc->res_pool->dmcu;
 | 
			
		||||
	struct dce_hwseq *hws = dc->hwseq;
 | 
			
		||||
	struct dc_bios *dcb = dc->ctx->dc_bios;
 | 
			
		||||
	struct resource_pool *res_pool = dc->res_pool;
 | 
			
		||||
 | 
			
		||||
	if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
 | 
			
		||||
		dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
 | 
			
		||||
 | 
			
		||||
	// Initialize the dccg
 | 
			
		||||
	if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init)
 | 
			
		||||
		dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
| 
						 | 
				
			
			@ -1150,30 +1183,39 @@ static void dcn10_init_hw(struct dc *dc)
 | 
			
		|||
			REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		enable_power_gating_plane(dc->hwseq, true);
 | 
			
		||||
		//Enable ability to power gate / don't force power on permanently
 | 
			
		||||
		dc->hwss.enable_power_gating_plane(hws, 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);
 | 
			
		||||
		dc->hwss.bios_golden_init(dc);
 | 
			
		||||
		if (dc->ctx->dc_bios->fw_info_valid) {
 | 
			
		||||
			res_pool->ref_clocks.xtalin_clock_inKhz =
 | 
			
		||||
					dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
 | 
			
		||||
 | 
			
		||||
		bios_golden_init(dc);
 | 
			
		||||
			if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
 | 
			
		||||
				if (res_pool->dccg && res_pool->hubbub) {
 | 
			
		||||
 | 
			
		||||
		/* 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);
 | 
			
		||||
					(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
 | 
			
		||||
							dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
 | 
			
		||||
							&res_pool->ref_clocks.dccg_ref_clock_inKhz);
 | 
			
		||||
 | 
			
		||||
		disable_vga(dc->hwseq);
 | 
			
		||||
					(res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
 | 
			
		||||
							res_pool->ref_clocks.dccg_ref_clock_inKhz,
 | 
			
		||||
							&res_pool->ref_clocks.dchub_ref_clock_inKhz);
 | 
			
		||||
				} else {
 | 
			
		||||
					// Not all ASICs have DCCG sw component
 | 
			
		||||
					res_pool->ref_clocks.dccg_ref_clock_inKhz =
 | 
			
		||||
							res_pool->ref_clocks.xtalin_clock_inKhz;
 | 
			
		||||
					res_pool->ref_clocks.dchub_ref_clock_inKhz =
 | 
			
		||||
							res_pool->ref_clocks.xtalin_clock_inKhz;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else
 | 
			
		||||
			ASSERT_CRITICAL(false);
 | 
			
		||||
		dc->hwss.disable_vga(dc->hwseq);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->link_count; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1191,6 +1233,13 @@ static void dcn10_init_hw(struct dc *dc)
 | 
			
		|||
			link->link_status.link_active = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Power gate DSCs */
 | 
			
		||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 | 
			
		||||
	for (i = 0; i < res_pool->res_cap->num_dsc; i++)
 | 
			
		||||
		if (dc->hwss.dsc_pg_control != NULL)
 | 
			
		||||
			dc->hwss.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* If taking control over from VBIOS, we may want to optimize our first
 | 
			
		||||
	 * mode set, so we need to skip powering down pipes until we know which
 | 
			
		||||
	 * pipes we want to use.
 | 
			
		||||
| 
						 | 
				
			
			@ -1199,10 +1248,21 @@ static void dcn10_init_hw(struct dc *dc)
 | 
			
		|||
	 */
 | 
			
		||||
	if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
 | 
			
		||||
		dc->hwss.init_pipes(dc, dc->current_state);
 | 
			
		||||
		for (i = 0; i < res_pool->pipe_count; i++) {
 | 
			
		||||
			struct hubp *hubp = res_pool->hubps[i];
 | 
			
		||||
			struct dpp *dpp = res_pool->dpps[i];
 | 
			
		||||
 | 
			
		||||
			hubp->funcs->hubp_init(hubp);
 | 
			
		||||
			res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
 | 
			
		||||
			dc->hwss.plane_atomic_power_down(dc, dpp, hubp);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		apply_DEGVIDCN10_253_wa(dc);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->audio_count; i++) {
 | 
			
		||||
		struct audio *audio = dc->res_pool->audios[i];
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < res_pool->audio_count; i++) {
 | 
			
		||||
		struct audio *audio = res_pool->audios[i];
 | 
			
		||||
 | 
			
		||||
		audio->funcs->hw_init(audio);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1230,7 +1290,7 @@ static void dcn10_init_hw(struct dc *dc)
 | 
			
		|||
		REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	enable_power_gating_plane(dc->hwseq, true);
 | 
			
		||||
	dc->hwss.enable_power_gating_plane(dc->hwseq, true);
 | 
			
		||||
 | 
			
		||||
	memset(&dc->clk_mgr->clks, 0, sizeof(dc->clk_mgr->clks));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1789,7 +1849,7 @@ static void dcn10_enable_plane(
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
 | 
			
		||||
static void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	struct dpp_grph_csc_adjustment adjust;
 | 
			
		||||
| 
						 | 
				
			
			@ -2220,7 +2280,7 @@ void update_dchubp_dpp(
 | 
			
		|||
 | 
			
		||||
	if (plane_state->update_flags.bits.full_update) {
 | 
			
		||||
		/*gamut remap*/
 | 
			
		||||
		program_gamut_remap(pipe_ctx);
 | 
			
		||||
		dc->hwss.program_gamut_remap(pipe_ctx);
 | 
			
		||||
 | 
			
		||||
		dc->hwss.program_output_csc(dc,
 | 
			
		||||
				pipe_ctx,
 | 
			
		||||
| 
						 | 
				
			
			@ -2457,7 +2517,7 @@ static void dcn10_apply_ctx_for_surface(
 | 
			
		|||
			if (old_pipe_ctx->stream_res.tg == tg &&
 | 
			
		||||
			    old_pipe_ctx->plane_res.hubp &&
 | 
			
		||||
			    old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
 | 
			
		||||
				dcn10_disable_plane(dc, old_pipe_ctx);
 | 
			
		||||
				dc->hwss.disable_plane(dc, old_pipe_ctx);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((!pipe_ctx->plane_state ||
 | 
			
		||||
| 
						 | 
				
			
			@ -2505,7 +2565,7 @@ static void dcn10_apply_ctx_for_surface(
 | 
			
		|||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->pipe_count; i++)
 | 
			
		||||
		if (removed_pipe[i])
 | 
			
		||||
			dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
 | 
			
		||||
			dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->pipe_count; i++)
 | 
			
		||||
		if (removed_pipe[i]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2597,7 +2657,7 @@ static void dcn10_optimize_bandwidth(
 | 
			
		|||
		dcn10_verify_allow_pstate_change_high(dc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_drr(struct pipe_ctx **pipe_ctx,
 | 
			
		||||
static void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
 | 
			
		||||
		int num_pipes, int vmin, int vmax)
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -2622,7 +2682,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void get_position(struct pipe_ctx **pipe_ctx,
 | 
			
		||||
static void dcn10_get_position(struct pipe_ctx **pipe_ctx,
 | 
			
		||||
		int num_pipes,
 | 
			
		||||
		struct crtc_position *position)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -2634,7 +2694,7 @@ static void get_position(struct pipe_ctx **pipe_ctx,
 | 
			
		|||
		pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
 | 
			
		||||
static void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
 | 
			
		||||
		int num_pipes, const struct dc_static_screen_events *events)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
| 
						 | 
				
			
			@ -3125,7 +3185,7 @@ static void dcn10_get_clock(struct dc *dc,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static const struct hw_sequencer_funcs dcn10_funcs = {
 | 
			
		||||
	.program_gamut_remap = program_gamut_remap,
 | 
			
		||||
	.program_gamut_remap = dcn10_program_gamut_remap,
 | 
			
		||||
	.init_hw = dcn10_init_hw,
 | 
			
		||||
	.init_pipes = dcn10_init_pipes,
 | 
			
		||||
	.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
 | 
			
		||||
| 
						 | 
				
			
			@ -3158,18 +3218,18 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
 | 
			
		|||
	.optimize_bandwidth = dcn10_optimize_bandwidth,
 | 
			
		||||
	.reset_hw_ctx_wrap = dcn10_reset_hw_ctx_wrap,
 | 
			
		||||
	.enable_stream_timing = dcn10_enable_stream_timing,
 | 
			
		||||
	.set_drr = set_drr,
 | 
			
		||||
	.get_position = get_position,
 | 
			
		||||
	.set_static_screen_control = set_static_screen_control,
 | 
			
		||||
	.set_drr = dcn10_set_drr,
 | 
			
		||||
	.get_position = dcn10_get_position,
 | 
			
		||||
	.set_static_screen_control = dcn10_set_static_screen_control,
 | 
			
		||||
	.setup_stereo = dcn10_setup_stereo,
 | 
			
		||||
	.set_avmute = dce110_set_avmute,
 | 
			
		||||
	.log_hw_state = dcn10_log_hw_state,
 | 
			
		||||
	.get_hw_state = dcn10_get_hw_state,
 | 
			
		||||
	.clear_status_bits = dcn10_clear_status_bits,
 | 
			
		||||
	.wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
 | 
			
		||||
	.edp_backlight_control = hwss_edp_backlight_control,
 | 
			
		||||
	.edp_power_control = hwss_edp_power_control,
 | 
			
		||||
	.edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
 | 
			
		||||
	.edp_backlight_control = dce110_edp_backlight_control,
 | 
			
		||||
	.edp_power_control = dce110_edp_power_control,
 | 
			
		||||
	.edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
 | 
			
		||||
	.set_cursor_position = dcn10_set_cursor_position,
 | 
			
		||||
	.set_cursor_attribute = dcn10_set_cursor_attribute,
 | 
			
		||||
	.set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level,
 | 
			
		||||
| 
						 | 
				
			
			@ -3179,6 +3239,16 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
 | 
			
		|||
	.setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt,
 | 
			
		||||
	.set_clock = dcn10_set_clock,
 | 
			
		||||
	.get_clock = dcn10_get_clock,
 | 
			
		||||
	.did_underflow_occur = dcn10_did_underflow_occur,
 | 
			
		||||
	.init_blank = NULL,
 | 
			
		||||
	.disable_vga = dcn10_disable_vga,
 | 
			
		||||
	.bios_golden_init = dcn10_bios_golden_init,
 | 
			
		||||
	.plane_atomic_disable = dcn10_plane_atomic_disable,
 | 
			
		||||
	.plane_atomic_power_down = dcn10_plane_atomic_power_down,
 | 
			
		||||
	.enable_power_gating_plane = dcn10_enable_power_gating_plane,
 | 
			
		||||
	.dpp_pg_control = dcn10_dpp_pg_control,
 | 
			
		||||
	.hubp_pg_control = dcn10_hubp_pg_control,
 | 
			
		||||
	.dsc_pg_control = NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -582,7 +582,7 @@ static const struct hubbub_funcs hubbub2_funcs = {
 | 
			
		|||
	.get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
 | 
			
		||||
	.wm_read_state = hubbub2_wm_read_state,
 | 
			
		||||
	.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
 | 
			
		||||
	.program_watermarks = hubbub2_program_watermarks,
 | 
			
		||||
	.program_watermarks = hubbub2_program_watermarks
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void hubbub2_construct(struct dcn20_hubbub *hubbub,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,23 +64,7 @@
 | 
			
		|||
#define FN(reg_name, field_name) \
 | 
			
		||||
	hws->shifts->field_name, hws->masks->field_name
 | 
			
		||||
 | 
			
		||||
static void bios_golden_init(struct dc *dc)
 | 
			
		||||
{
 | 
			
		||||
	struct dc_bios *bp = dc->ctx->dc_bios;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	/* initialize dcn global */
 | 
			
		||||
	bp->funcs->enable_disp_power_gating(bp,
 | 
			
		||||
			CONTROLLER_ID_D0, ASIC_PIPE_INIT);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 | 
			
		||||
		/* initialize dcn per pipe */
 | 
			
		||||
		bp->funcs->enable_disp_power_gating(bp,
 | 
			
		||||
				CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void enable_power_gating_plane(
 | 
			
		||||
static void dcn20_enable_power_gating_plane(
 | 
			
		||||
	struct dce_hwseq *hws,
 | 
			
		||||
	bool enable)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -184,7 +168,7 @@ void dcn20_display_init(struct dc *dc)
 | 
			
		|||
	REG_WRITE(AZALIA_CONTROLLER_CLOCK_GATING, 0x1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void disable_vga(
 | 
			
		||||
void dcn20_disable_vga(
 | 
			
		||||
	struct dce_hwseq *hws)
 | 
			
		||||
{
 | 
			
		||||
	REG_WRITE(D1VGA_CONTROL, 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -487,29 +471,6 @@ static void dcn20_hubp_pg_control(
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void dcn20_plane_atomic_power_down(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct dce_hwseq *hws = dc->hwseq;
 | 
			
		||||
	struct dpp *dpp = pipe_ctx->plane_res.dpp;
 | 
			
		||||
 | 
			
		||||
	DC_LOGGER_INIT(dc->ctx->logger);
 | 
			
		||||
 | 
			
		||||
	if (REG(DC_IP_REQUEST_CNTL)) {
 | 
			
		||||
		REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
				IP_REQUEST_EN, 1);
 | 
			
		||||
		dcn20_dpp_pg_control(hws, dpp->inst, false);
 | 
			
		||||
		dcn20_hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, false);
 | 
			
		||||
		dpp->funcs->dpp_reset(dpp);
 | 
			
		||||
		REG_SET(DC_IP_REQUEST_CNTL, 0,
 | 
			
		||||
				IP_REQUEST_EN, 0);
 | 
			
		||||
		DC_LOG_DEBUG(
 | 
			
		||||
				"Power gated front end %d\n", pipe_ctx->pipe_idx);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* disable HW used by plane.
 | 
			
		||||
 * note:  cannot disable until disconnect is complete
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -535,7 +496,9 @@ static void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		|||
	hubp->power_gated = true;
 | 
			
		||||
	dc->optimized_required = false; /* We're powering off, no need to optimize */
 | 
			
		||||
 | 
			
		||||
	dcn20_plane_atomic_power_down(dc, pipe_ctx);
 | 
			
		||||
	dc->hwss.plane_atomic_power_down(dc,
 | 
			
		||||
			pipe_ctx->plane_res.dpp,
 | 
			
		||||
			pipe_ctx->plane_res.hubp);
 | 
			
		||||
 | 
			
		||||
	pipe_ctx->stream = NULL;
 | 
			
		||||
	memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
 | 
			
		||||
| 
						 | 
				
			
			@ -559,204 +522,6 @@ void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
 | 
			
		|||
					pipe_ctx->pipe_idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dcn20_init_hw(struct dc *dc)
 | 
			
		||||
{
 | 
			
		||||
	int i, j;
 | 
			
		||||
	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 resource_pool *res_pool = dc->res_pool;
 | 
			
		||||
	struct dc_state  *context = dc->current_state;
 | 
			
		||||
 | 
			
		||||
	if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
 | 
			
		||||
		dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
 | 
			
		||||
 | 
			
		||||
	// Initialize the dccg
 | 
			
		||||
	if (res_pool->dccg->funcs->dccg_init)
 | 
			
		||||
		res_pool->dccg->funcs->dccg_init(res_pool->dccg);
 | 
			
		||||
 | 
			
		||||
	//Enable ability to power gate / don't force power on permanently
 | 
			
		||||
	enable_power_gating_plane(dc->hwseq, true);
 | 
			
		||||
 | 
			
		||||
	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
 | 
			
		||||
		REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
 | 
			
		||||
		REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
 | 
			
		||||
 | 
			
		||||
		dcn20_dccg_init(hws);
 | 
			
		||||
 | 
			
		||||
		REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
 | 
			
		||||
		REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
 | 
			
		||||
		REG_WRITE(REFCLK_CNTL, 0);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (!dcb->funcs->is_accelerated_mode(dcb)) {
 | 
			
		||||
			bios_golden_init(dc);
 | 
			
		||||
			if (dc->ctx->dc_bios->fw_info_valid) {
 | 
			
		||||
				res_pool->ref_clocks.xtalin_clock_inKhz =
 | 
			
		||||
						dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
 | 
			
		||||
 | 
			
		||||
				if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
 | 
			
		||||
					if (res_pool->dccg && res_pool->hubbub) {
 | 
			
		||||
 | 
			
		||||
						(res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
 | 
			
		||||
								dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
 | 
			
		||||
								&res_pool->ref_clocks.dccg_ref_clock_inKhz);
 | 
			
		||||
 | 
			
		||||
						(res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
 | 
			
		||||
								res_pool->ref_clocks.dccg_ref_clock_inKhz,
 | 
			
		||||
								&res_pool->ref_clocks.dchub_ref_clock_inKhz);
 | 
			
		||||
					} else {
 | 
			
		||||
						// Not all ASICs have DCCG sw component
 | 
			
		||||
						res_pool->ref_clocks.dccg_ref_clock_inKhz =
 | 
			
		||||
								res_pool->ref_clocks.xtalin_clock_inKhz;
 | 
			
		||||
						res_pool->ref_clocks.dchub_ref_clock_inKhz =
 | 
			
		||||
								res_pool->ref_clocks.xtalin_clock_inKhz;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else
 | 
			
		||||
				ASSERT_CRITICAL(false);
 | 
			
		||||
			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];
 | 
			
		||||
 | 
			
		||||
			link->link_enc->funcs->hw_init(link->link_enc);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 | 
			
		||||
	/* Power gate DSCs */
 | 
			
		||||
	for (i = 0; i < res_pool->res_cap->num_dsc; i++)
 | 
			
		||||
		dcn20_dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Blank pixel data with OPP DPG */
 | 
			
		||||
	for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
 | 
			
		||||
		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 | 
			
		||||
 | 
			
		||||
		if (tg->funcs->is_tg_enabled(tg)) {
 | 
			
		||||
			dcn20_init_blank(dc, tg);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < res_pool->timing_generator_count; i++) {
 | 
			
		||||
		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 | 
			
		||||
 | 
			
		||||
		if (tg->funcs->is_tg_enabled(tg))
 | 
			
		||||
			tg->funcs->lock(tg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 | 
			
		||||
		struct dpp *dpp = res_pool->dpps[i];
 | 
			
		||||
 | 
			
		||||
		dpp->funcs->dpp_reset(dpp);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Reset all MPCC muxes */
 | 
			
		||||
	res_pool->mpc->funcs->mpc_init(res_pool->mpc);
 | 
			
		||||
 | 
			
		||||
	/* initialize OPP mpc_tree parameter */
 | 
			
		||||
	for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
 | 
			
		||||
		res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
 | 
			
		||||
		res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
 | 
			
		||||
		for (j = 0; j < MAX_PIPES; j++)
 | 
			
		||||
			res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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];
 | 
			
		||||
 | 
			
		||||
		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 = dpp->inst;
 | 
			
		||||
		hubp->mpcc_id = dpp->inst;
 | 
			
		||||
		hubp->opp_id = OPP_ID_INVALID;
 | 
			
		||||
		hubp->power_gated = false;
 | 
			
		||||
		pipe_ctx->stream_res.opp = NULL;
 | 
			
		||||
 | 
			
		||||
		hubp->funcs->hubp_init(hubp);
 | 
			
		||||
 | 
			
		||||
		//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];
 | 
			
		||||
		/*to do*/
 | 
			
		||||
		hwss1_plane_atomic_disconnect(dc, pipe_ctx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* initialize DWB pointer to MCIF_WB */
 | 
			
		||||
	for (i = 0; i < res_pool->res_cap->num_dwb; i++)
 | 
			
		||||
		res_pool->dwbc[i]->mcif = 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];
 | 
			
		||||
 | 
			
		||||
		if (tg->funcs->is_tg_enabled(tg))
 | 
			
		||||
			tg->funcs->unlock(tg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 | 
			
		||||
		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 | 
			
		||||
 | 
			
		||||
		dc->hwss.disable_plane(dc, pipe_ctx);
 | 
			
		||||
 | 
			
		||||
		pipe_ctx->stream_res.tg = NULL;
 | 
			
		||||
		pipe_ctx->plane_res.hubp = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
 | 
			
		||||
		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 | 
			
		||||
 | 
			
		||||
		tg->funcs->tg_init(tg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* end of FPGA. Below if real ASIC */
 | 
			
		||||
	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < res_pool->audio_count; i++) {
 | 
			
		||||
		struct audio *audio = res_pool->audios[i];
 | 
			
		||||
 | 
			
		||||
		audio->funcs->hw_init(audio);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (abm != NULL) {
 | 
			
		||||
		abm->funcs->init_backlight(abm);
 | 
			
		||||
		abm->funcs->abm_init(abm);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dmcu != NULL)
 | 
			
		||||
		dmcu->funcs->dmcu_init(dmcu);
 | 
			
		||||
 | 
			
		||||
	if (abm != NULL && dmcu != NULL)
 | 
			
		||||
		abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
 | 
			
		||||
 | 
			
		||||
	/* power AFMT HDMI memory TODO: may move to dis/en output save power*/
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum dc_status dcn20_enable_stream_timing(
 | 
			
		||||
		struct pipe_ctx *pipe_ctx,
 | 
			
		||||
		struct dc_state *context,
 | 
			
		||||
| 
						 | 
				
			
			@ -1409,7 +1174,7 @@ static void dcn20_apply_ctx_for_surface(
 | 
			
		|||
			if (old_pipe_ctx->stream_res.tg == tg &&
 | 
			
		||||
			    old_pipe_ctx->plane_res.hubp &&
 | 
			
		||||
			    old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
 | 
			
		||||
				dcn20_disable_plane(dc, old_pipe_ctx);
 | 
			
		||||
				dc->hwss.disable_plane(dc, old_pipe_ctx);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ((!pipe_ctx->plane_state ||
 | 
			
		||||
| 
						 | 
				
			
			@ -2169,14 +1934,126 @@ static void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
 | 
			
		|||
						hubp->inst, mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dcn20_fpga_init_hw(struct dc *dc)
 | 
			
		||||
{
 | 
			
		||||
	int i, j;
 | 
			
		||||
	struct dce_hwseq *hws = dc->hwseq;
 | 
			
		||||
	struct resource_pool *res_pool = dc->res_pool;
 | 
			
		||||
	struct dc_state  *context = dc->current_state;
 | 
			
		||||
 | 
			
		||||
	if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
 | 
			
		||||
		dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
 | 
			
		||||
 | 
			
		||||
	// Initialize the dccg
 | 
			
		||||
	if (res_pool->dccg->funcs->dccg_init)
 | 
			
		||||
		res_pool->dccg->funcs->dccg_init(res_pool->dccg);
 | 
			
		||||
 | 
			
		||||
	//Enable ability to power gate / don't force power on permanently
 | 
			
		||||
	dc->hwss.enable_power_gating_plane(hws, true);
 | 
			
		||||
 | 
			
		||||
	// Specific to FPGA dccg and registers
 | 
			
		||||
	REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
 | 
			
		||||
	REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
 | 
			
		||||
 | 
			
		||||
	dcn20_dccg_init(hws);
 | 
			
		||||
 | 
			
		||||
	REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
 | 
			
		||||
	REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
 | 
			
		||||
	REG_WRITE(REFCLK_CNTL, 0);
 | 
			
		||||
	//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* Blank pixel data with OPP DPG */
 | 
			
		||||
	for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
 | 
			
		||||
		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 | 
			
		||||
 | 
			
		||||
		if (tg->funcs->is_tg_enabled(tg))
 | 
			
		||||
			dcn20_init_blank(dc, tg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < res_pool->timing_generator_count; i++) {
 | 
			
		||||
		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 | 
			
		||||
 | 
			
		||||
		if (tg->funcs->is_tg_enabled(tg))
 | 
			
		||||
			tg->funcs->lock(tg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 | 
			
		||||
		struct dpp *dpp = res_pool->dpps[i];
 | 
			
		||||
 | 
			
		||||
		dpp->funcs->dpp_reset(dpp);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Reset all MPCC muxes */
 | 
			
		||||
	res_pool->mpc->funcs->mpc_init(res_pool->mpc);
 | 
			
		||||
 | 
			
		||||
	/* initialize OPP mpc_tree parameter */
 | 
			
		||||
	for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
 | 
			
		||||
		res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
 | 
			
		||||
		res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
 | 
			
		||||
		for (j = 0; j < MAX_PIPES; j++)
 | 
			
		||||
			res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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];
 | 
			
		||||
 | 
			
		||||
		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 = dpp->inst;
 | 
			
		||||
		hubp->mpcc_id = dpp->inst;
 | 
			
		||||
		hubp->opp_id = OPP_ID_INVALID;
 | 
			
		||||
		hubp->power_gated = false;
 | 
			
		||||
		pipe_ctx->stream_res.opp = NULL;
 | 
			
		||||
 | 
			
		||||
		hubp->funcs->hubp_init(hubp);
 | 
			
		||||
 | 
			
		||||
		//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];
 | 
			
		||||
		/*to do*/
 | 
			
		||||
		hwss1_plane_atomic_disconnect(dc, pipe_ctx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* initialize DWB pointer to MCIF_WB */
 | 
			
		||||
	for (i = 0; i < res_pool->res_cap->num_dwb; i++)
 | 
			
		||||
		res_pool->dwbc[i]->mcif = 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];
 | 
			
		||||
 | 
			
		||||
		if (tg->funcs->is_tg_enabled(tg))
 | 
			
		||||
			tg->funcs->unlock(tg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->pipe_count; i++) {
 | 
			
		||||
		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 | 
			
		||||
 | 
			
		||||
		dc->hwss.disable_plane(dc, pipe_ctx);
 | 
			
		||||
 | 
			
		||||
		pipe_ctx->stream_res.tg = NULL;
 | 
			
		||||
		pipe_ctx->plane_res.hubp = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
 | 
			
		||||
		struct timing_generator *tg = dc->res_pool->timing_generators[i];
 | 
			
		||||
 | 
			
		||||
		tg->funcs->tg_init(tg);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dcn20_hw_sequencer_construct(struct dc *dc)
 | 
			
		||||
{
 | 
			
		||||
	dcn10_hw_sequencer_construct(dc);
 | 
			
		||||
	dc->hwss.init_hw = dcn20_init_hw;
 | 
			
		||||
	dc->hwss.init_pipes = NULL;
 | 
			
		||||
	dc->hwss.unblank_stream = dcn20_unblank_stream;
 | 
			
		||||
	dc->hwss.update_plane_addr = dcn20_update_plane_addr;
 | 
			
		||||
	dc->hwss.disable_plane = dcn20_disable_plane,
 | 
			
		||||
	dc->hwss.enable_stream_timing = dcn20_enable_stream_timing;
 | 
			
		||||
	dc->hwss.program_triplebuffer = dcn20_program_tripleBuffer;
 | 
			
		||||
	dc->hwss.set_input_transfer_func = dcn20_set_input_transfer_func;
 | 
			
		||||
| 
						 | 
				
			
			@ -2204,5 +2081,19 @@ void dcn20_hw_sequencer_construct(struct dc *dc)
 | 
			
		|||
	dc->hwss.reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap;
 | 
			
		||||
	dc->hwss.update_mpcc = dcn20_update_mpcc;
 | 
			
		||||
	dc->hwss.set_flip_control_gsl = dcn20_set_flip_control_gsl;
 | 
			
		||||
	dc->hwss.did_underflow_occur = dcn10_did_underflow_occur;
 | 
			
		||||
	dc->hwss.init_blank = dcn20_init_blank;
 | 
			
		||||
	dc->hwss.disable_plane = dcn20_disable_plane;
 | 
			
		||||
	dc->hwss.plane_atomic_disable = dcn20_plane_atomic_disable;
 | 
			
		||||
	dc->hwss.enable_power_gating_plane = dcn20_enable_power_gating_plane;
 | 
			
		||||
	dc->hwss.dpp_pg_control = dcn20_dpp_pg_control;
 | 
			
		||||
	dc->hwss.hubp_pg_control = dcn20_hubp_pg_control;
 | 
			
		||||
	dc->hwss.dsc_pg_control = dcn20_dsc_pg_control;
 | 
			
		||||
	dc->hwss.disable_vga = dcn20_disable_vga;
 | 
			
		||||
 | 
			
		||||
	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
 | 
			
		||||
		dc->hwss.init_hw = dcn20_fpga_init_hw;
 | 
			
		||||
		dc->hwss.init_pipes = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,6 +141,10 @@ struct hubbub_funcs {
 | 
			
		|||
			struct dcn_watermark_set *watermarks,
 | 
			
		||||
			unsigned int refclk_mhz,
 | 
			
		||||
			bool safe_to_lower);
 | 
			
		||||
 | 
			
		||||
	bool (*is_allow_self_refresh_enabled)(struct hubbub *hubbub);
 | 
			
		||||
	void (*allow_self_refresh_control)(struct hubbub *hubbub, bool allow);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct hubbub {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,8 @@ struct stream_resource;
 | 
			
		|||
struct dc_phy_addr_space_config;
 | 
			
		||||
struct dc_virtual_addr_space_config;
 | 
			
		||||
#endif
 | 
			
		||||
struct hubp;
 | 
			
		||||
struct dpp;
 | 
			
		||||
 | 
			
		||||
struct hw_sequencer_funcs {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -280,6 +282,36 @@ struct hw_sequencer_funcs {
 | 
			
		|||
	void (*setup_vupdate_interrupt)(struct pipe_ctx *pipe_ctx);
 | 
			
		||||
	bool (*did_underflow_occur)(struct dc *dc, struct pipe_ctx *pipe_ctx);
 | 
			
		||||
 | 
			
		||||
	void (*init_blank)(struct dc *dc, struct timing_generator *tg);
 | 
			
		||||
	void (*disable_vga)(struct dce_hwseq *hws);
 | 
			
		||||
	void (*bios_golden_init)(struct dc *dc);
 | 
			
		||||
	void (*plane_atomic_power_down)(struct dc *dc,
 | 
			
		||||
			struct dpp *dpp,
 | 
			
		||||
			struct hubp *hubp);
 | 
			
		||||
 | 
			
		||||
	void (*plane_atomic_disable)(
 | 
			
		||||
			struct dc *dc, struct pipe_ctx *pipe_ctx);
 | 
			
		||||
 | 
			
		||||
	void (*enable_power_gating_plane)(
 | 
			
		||||
		struct dce_hwseq *hws,
 | 
			
		||||
		bool enable);
 | 
			
		||||
 | 
			
		||||
	void (*dpp_pg_control)(
 | 
			
		||||
			struct dce_hwseq *hws,
 | 
			
		||||
			unsigned int dpp_inst,
 | 
			
		||||
			bool power_on);
 | 
			
		||||
 | 
			
		||||
	void (*hubp_pg_control)(
 | 
			
		||||
			struct dce_hwseq *hws,
 | 
			
		||||
			unsigned int hubp_inst,
 | 
			
		||||
			bool power_on);
 | 
			
		||||
 | 
			
		||||
	void (*dsc_pg_control)(
 | 
			
		||||
			struct dce_hwseq *hws,
 | 
			
		||||
			unsigned int dsc_inst,
 | 
			
		||||
			bool power_on);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
 | 
			
		||||
	void (*update_odm)(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx);
 | 
			
		||||
	void (*program_all_writeback_pipes_in_tree)(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue