Commit 4ed79308 authored by Alvin Lee's avatar Alvin Lee Committed by Alex Deucher
Browse files

drm/amd/display: Use per pipe P-State force for FPO



[Description]
*  Pass in pipe index for FPO cmd to DMCUB
- This change will pass in the pipe index for each stream
  that is using FPO
- This change is in preparation to enable FPO + VActive

*  Use per pipe P-State force for FPO
- For FPO, instead of using max watermarks value for P-State disallow,
  use per pipe p-state force instead
- This is in preparation to enable FPO + VActive

Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarQingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: default avatarAlvin Lee <Alvin.Lee2@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e8e5cc64
Loading
Loading
Loading
Loading
+27 −19
Original line number Diff line number Diff line
@@ -302,27 +302,31 @@ static uint8_t dc_dmub_srv_get_pipes_for_stream(struct dc *dc, struct dc_stream_
	return pipes;
}

static int dc_dmub_srv_get_timing_generator_offset(struct dc *dc, struct dc_stream_state *stream)
static void dc_dmub_srv_populate_fams_pipe_info(struct dc *dc, struct dc_state *context,
		struct pipe_ctx *head_pipe,
		struct dmub_cmd_fw_assisted_mclk_switch_pipe_data *fams_pipe_data)
{
	int  tg_inst = 0;
	int i = 0;
	int j;

	for (i = 0; i < MAX_PIPES; i++) {
		struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
	// TODO: Uncomment once FW headers are updated in driver
	//fams_pipe_data->pipe_index[pipe_idx++] = head_pipe->plane_res.hubp->inst;
	for (j = 0; j < dc->res_pool->pipe_count; j++) {
		struct pipe_ctx *split_pipe = &context->res_ctx.pipe_ctx[j];

		if (pipe->stream == stream && pipe->stream_res.tg) {
			tg_inst = pipe->stream_res.tg->inst;
			break;
		if (split_pipe->stream == head_pipe->stream && (split_pipe->top_pipe || split_pipe->prev_odm_pipe)) {
			// TODO: Uncomment once FW headers are updated in driver
			//fams_pipe_data->pipe_index[pipe_idx++] = split_pipe->plane_res.hubp->inst;
		}
	}
	return tg_inst;
	// TODO: Uncomment once FW headers are updated in driver
	//fams_pipe_data->pipe_count = pipe_idx;
}

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 i = 0, k = 0;
	int ramp_up_num_steps = 1; // TODO: Ramp is currently disabled. Reenable it.
	uint8_t visual_confirm_enabled;

@@ -337,17 +341,21 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru
	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);
	for (i = 0, k = 0; context && i < dc->res_pool->pipe_count; i++) {
		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];

		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);
	}
		if (!pipe->top_pipe && !pipe->prev_odm_pipe && pipe->stream && pipe->stream->fpo_in_use) {
			struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
			uint8_t min_refresh_in_hz = (pipe->stream->timing.min_refresh_in_uhz + 999999) / 1000000;

			config_data->pipe_data[k].pix_clk_100hz = pipe->stream->timing.pix_clk_100hz;
			config_data->pipe_data[k].min_refresh_in_hz = min_refresh_in_hz;
			config_data->pipe_data[k].max_ramp_step = ramp_up_num_steps;
			config_data->pipe_data[k].pipes = dc_dmub_srv_get_pipes_for_stream(dc, pipe->stream);
			dc_dmub_srv_populate_fams_pipe_info(dc, context, pipe, &config_data->pipe_data[k]);
			k++;
		}
	}
	cmd.fw_assisted_mclk_switch.header.payload_bytes =
		sizeof(cmd.fw_assisted_mclk_switch) - sizeof(cmd.fw_assisted_mclk_switch.header);

+1 −0
Original line number Diff line number Diff line
@@ -293,6 +293,7 @@ struct dc_stream_state {

	bool has_non_synchronizable_pclk;
	bool vblank_synchronized;
	bool fpo_in_use;
	struct mall_stream_config mall_stream_config;
};

+10 −0
Original line number Diff line number Diff line
@@ -1993,6 +1993,16 @@ void dcn20_post_unlock_program_front_end(
		}
	}

	/* P-State support transitions:
	 * Natural -> FPO: 		P-State disabled in prepare, force disallow anytime is safe
	 * FPO -> Natural: 		Unforce anytime after FW disable is safe (P-State will assert naturally)
	 * Unsupported -> FPO:	P-State enabled in optimize, force disallow anytime is safe
	 * FPO -> Unsupported:	P-State disabled in prepare, unforce disallow anytime is safe
	 * FPO <-> SubVP:		Force disallow is maintained on the FPO / SubVP pipes
	 */
	if (hwseq && hwseq->funcs.update_force_pstate)
		dc->hwseq->funcs.update_force_pstate(dc, context);

	/* Only program the MALL registers after all the main and phantom pipes
	 * are done programming.
	 */
+2 −0
Original line number Diff line number Diff line
@@ -2016,6 +2016,8 @@ bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc,
	if (context->streams[0]->vrr_active_variable)
		return false;

	context->streams[0]->fpo_in_use = true;

	return true;
}

+10 −0
Original line number Diff line number Diff line
@@ -47,6 +47,15 @@ void hubp32_update_force_pstate_disallow(struct hubp *hubp, bool pstate_disallow
			DATA_UCLK_PSTATE_FORCE_VALUE, 0);
}

void hubp32_update_force_cursor_pstate_disallow(struct hubp *hubp, bool pstate_disallow)
{
	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);

	REG_UPDATE_2(UCLK_PSTATE_FORCE,
			CURSOR_UCLK_PSTATE_FORCE_EN, pstate_disallow,
			CURSOR_UCLK_PSTATE_FORCE_VALUE, 0);
}

void hubp32_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor)
{
	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
@@ -188,6 +197,7 @@ static struct hubp_funcs dcn32_hubp_funcs = {
	.hubp_set_flip_int = hubp1_set_flip_int,
	.hubp_in_blank = hubp1_in_blank,
	.hubp_update_force_pstate_disallow = hubp32_update_force_pstate_disallow,
	.hubp_update_force_cursor_pstate_disallow = hubp32_update_force_cursor_pstate_disallow,
	.phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable,
	.hubp_update_mall_sel = hubp32_update_mall_sel,
	.hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering
Loading