Commit 00fa7f03 authored by Rodrigo Siqueira's avatar Rodrigo Siqueira Committed by Alex Deucher
Browse files

drm/amd/display: Add basic infrastructure for enabling FAMS



We want to enable Firmware Assisted Memory (FAMS) Switching, but first,
we need to add the required code infrastructure in DC before allowing it
in amdgpu_dm.

Signed-off-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent bbb6e5ae
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -3842,10 +3842,18 @@ bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_
/* cleanup on driver unload */
void dc_hardware_release(struct dc *dc)
{
	dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(dc);

	if (dc->hwss.hardware_release)
		dc->hwss.hardware_release(dc);
}

void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc)
{
	if (dc->current_state)
		dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down = true;
}

/*
 *****************************************************************************
 * Function: dc_is_dmub_outbox_supported -
+9 −1
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ struct dc_color_caps {

struct dc_dmub_caps {
	bool psr;
	bool mclk_sw;
};

struct dc_caps {
@@ -359,6 +360,8 @@ enum visual_confirm {
	VISUAL_CONFIRM_HDR = 2,
	VISUAL_CONFIRM_MPCTREE = 4,
	VISUAL_CONFIRM_PSR = 5,
	VISUAL_CONFIRM_SWAPCHAIN = 6,
	VISUAL_CONFIRM_FAMS = 7,
	VISUAL_CONFIRM_SWIZZLE = 9,
};

@@ -441,6 +444,7 @@ struct dc_clocks {
	bool fclk_prev_p_state_change_support;
	int num_ways;
	bool fw_based_mclk_switching;
	bool fw_based_mclk_switching_shut_down;
	int prev_num_ways;
	enum dtm_pstate dtm_level;
	int max_supported_dppclk_khz;
@@ -726,6 +730,7 @@ struct dc_debug_options {

	/* Enable dmub aux for legacy ddc */
	bool enable_dmub_aux_for_legacy_ddc;
	bool disable_fams;
	bool optimize_edp_link_rate; /* eDP ILR */
	/* FEC/PSR1 sequence enable delay in 100us */
	uint8_t fec_enable_delay_in100us;
@@ -1452,6 +1457,9 @@ void dc_enable_dcmode_clk_limit(struct dc *dc, bool enable);
/* cleanup on driver unload */
void dc_hardware_release(struct dc *dc);

/* disables fw based mclk switch */
void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc);

bool dc_set_psr_allow_active(struct dc *dc, bool enable);
void dc_z10_restore(const struct dc *dc);
void dc_z10_save_init(struct dc *dc);
+87 −0
Original line number Diff line number Diff line
@@ -252,6 +252,93 @@ void dc_dmub_trace_event_control(struct dc *dc, bool enable)
	dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable);
}

void dc_dmub_srv_drr_update_cmd(struct dc *dc, uint32_t tg_inst, uint32_t vtotal_min, uint32_t vtotal_max)
{
	union dmub_rb_cmd cmd = { 0 };

	cmd.drr_update.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
	cmd.drr_update.header.sub_type = DMUB_CMD__FAMS_DRR_UPDATE;
	cmd.drr_update.dmub_optc_state_req.v_total_max = vtotal_max;
	cmd.drr_update.dmub_optc_state_req.v_total_min = vtotal_min;
	cmd.drr_update.dmub_optc_state_req.tg_inst = tg_inst;

	cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header);

	// Send the command to the DMCUB.
	dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
	dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
	dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
}

uint8_t dc_dmub_srv_get_pipes_for_stream(struct dc *dc, struct dc_stream_state *stream)
{
	uint8_t pipes = 0;
	int i = 0;

	for (i = 0; i < MAX_PIPES; i++) {
		struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];

		if (pipe->stream == stream && pipe->stream_res.tg)
			pipes = i;
	}
	return pipes;
}

int dc_dmub_srv_get_timing_generator_offset(struct dc *dc, struct dc_stream_state *stream)
{
	int  tg_inst = 0;
	int i = 0;

	for (i = 0; i < MAX_PIPES; i++) {
		struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];

		if (pipe->stream == stream && pipe->stream_res.tg) {
			tg_inst = pipe->stream_res.tg->inst;
			break;
		}
	}
	return tg_inst;
}

bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, struct dc_state *context)
{
	union dmub_rb_cmd cmd = { 0 };
	struct dmub_cmd_fw_assisted_mclk_switch_config *config_data = &cmd.fw_assisted_mclk_switch.config_data;
	int i = 0;
	int ramp_up_num_steps = 1; // TODO: Ramp is currently disabled. Reenable it.
	uint8_t visual_confirm_enabled = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS;

	if (dc == NULL)
		return false;

	// Format command.
	cmd.fw_assisted_mclk_switch.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
	cmd.fw_assisted_mclk_switch.header.sub_type = DMUB_CMD__FAMS_SETUP_FW_CTRL;
	cmd.fw_assisted_mclk_switch.config_data.fams_enabled = should_manage_pstate;
	cmd.fw_assisted_mclk_switch.config_data.visual_confirm_enabled = visual_confirm_enabled;

	for (i = 0; context && i < context->stream_count; i++) {
		struct dc_stream_state *stream = context->streams[i];
		uint8_t min_refresh_in_hz = (stream->timing.min_refresh_in_uhz + 999999) / 1000000;
		int  tg_inst = dc_dmub_srv_get_timing_generator_offset(dc, stream);

		config_data->pipe_data[tg_inst].pix_clk_100hz = stream->timing.pix_clk_100hz;
		config_data->pipe_data[tg_inst].min_refresh_in_hz = min_refresh_in_hz;
		config_data->pipe_data[tg_inst].max_ramp_step = ramp_up_num_steps;
		config_data->pipe_data[tg_inst].pipes = dc_dmub_srv_get_pipes_for_stream(dc, stream);
	}

	cmd.fw_assisted_mclk_switch.header.payload_bytes =
		sizeof(cmd.fw_assisted_mclk_switch) - sizeof(cmd.fw_assisted_mclk_switch.header);

	// Send the command to the DMCUB.
	dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
	dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
	dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);

	return true;
}

void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub)
{
	union dmub_rb_cmd cmd = { 0 };
+4 −0
Original line number Diff line number Diff line
@@ -72,6 +72,10 @@ bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_bu

void dc_dmub_trace_event_control(struct dc *dc, bool enable);

void dc_dmub_srv_drr_update_cmd(struct dc *dc, uint32_t tg_inst, uint32_t vtotal_min, uint32_t vtotal_max);

bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool enable_pstate, struct dc_state *context);

void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub);
void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv);
void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv);
+2 −0
Original line number Diff line number Diff line
@@ -196,6 +196,8 @@ struct dc_panel_patch {
	unsigned int disable_fec;
	unsigned int extra_t3_ms;
	unsigned int max_dsc_target_bpp_limit;
	unsigned int embedded_tiled_slave;
	unsigned int disable_fams;
	unsigned int skip_avmute;
};

Loading