Commit f56c837a authored by Mikita Lipski's avatar Mikita Lipski Committed by Alex Deucher
Browse files

drm/amd/display: Enabling PSR support for multiple panels



[why]
Updating PSR interfaces to allow PSR enablement
per eDP panel.
[how]
- Copying PSR command structures to DC
- Changing function interfaces to pass panel instance
- Communicating with DMUB per link instead of assuming
to use a single one
-Iterating through all PSR capable panels when enabling/disabling
all

Signed-off-by: default avatarMikita Lipski <mikita.lipski@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: default avatarStylon Wang <stylon.wang@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 6c475bdb
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -93,16 +93,21 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
	struct dc_link *edp_links[MAX_NUM_EDP];
	struct dc_link *edp_link = NULL;
	int edp_num;
	unsigned int panel_inst;

	get_edp_links(dc, edp_links, &edp_num);
	if (dc->hwss.exit_optimized_pwr_state)
		dc->hwss.exit_optimized_pwr_state(dc, dc->current_state);

	if (edp_num) {
		edp_link = edp_links[0];
		for (panel_inst = 0; panel_inst < edp_num; panel_inst++) {
			edp_link = edp_links[panel_inst];
			if (!edp_link->psr_settings.psr_feature_enabled)
				continue;
			clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active;
			dc_link_set_psr_allow_active(edp_link, false, false, false);
		}
	}

}

@@ -111,13 +116,18 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
	struct dc_link *edp_links[MAX_NUM_EDP];
	struct dc_link *edp_link = NULL;
	int edp_num;
	unsigned int panel_inst;

	get_edp_links(dc, edp_links, &edp_num);
	if (edp_num) {
		edp_link = edp_links[0];
		for (panel_inst = 0; panel_inst < edp_num; panel_inst++) {
			edp_link = edp_links[panel_inst];
			if (!edp_link->psr_settings.psr_feature_enabled)
				continue;
			dc_link_set_psr_allow_active(edp_link,
					clk_mgr->psr_allow_active_cache, false, false);
		}
	}

	if (dc->hwss.optimize_pwr_state)
		dc->hwss.optimize_pwr_state(dc, dc->current_state);
+7 −4
Original line number Diff line number Diff line
@@ -3278,10 +3278,13 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable)
			continue;

		if (link->psr_settings.psr_feature_enabled) {
			if (enable && !link->psr_settings.psr_allow_active)
				return dc_link_set_psr_allow_active(link, true, false, false);
			else if (!enable && link->psr_settings.psr_allow_active)
				return dc_link_set_psr_allow_active(link, false, true, false);
			if (enable && !link->psr_settings.psr_allow_active) {
				if (!dc_link_set_psr_allow_active(link, true, false, false))
					return false;
			} else if (!enable && link->psr_settings.psr_allow_active) {
				if (!dc_link_set_psr_allow_active(link, false, true, false))
					return false;
			}
		}
	}

+17 −4
Original line number Diff line number Diff line
@@ -2701,10 +2701,14 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active,
	struct dc  *dc = link->ctx->dc;
	struct dmcu *dmcu = dc->res_pool->dmcu;
	struct dmub_psr *psr = dc->res_pool->psr;
	unsigned int panel_inst;

	if (psr == NULL && force_static)
		return false;

	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
		return false;

	link->psr_settings.psr_allow_active = allow_active;
#if defined(CONFIG_DRM_AMD_DC_DCN3_1)
	if (!allow_active)
@@ -2713,8 +2717,8 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active,

	if (psr != NULL && link->psr_settings.psr_feature_enabled) {
		if (force_static && psr->funcs->psr_force_static)
			psr->funcs->psr_force_static(psr);
		psr->funcs->psr_enable(psr, allow_active, wait);
			psr->funcs->psr_force_static(psr, panel_inst);
		psr->funcs->psr_enable(psr, allow_active, wait, panel_inst);
	} else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled)
		dmcu->funcs->set_psr_enable(dmcu, allow_active, wait);
	else
@@ -2728,9 +2732,13 @@ bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
	struct dc  *dc = link->ctx->dc;
	struct dmcu *dmcu = dc->res_pool->dmcu;
	struct dmub_psr *psr = dc->res_pool->psr;
	unsigned int panel_inst;

	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
		return false;

	if (psr != NULL && link->psr_settings.psr_feature_enabled)
		psr->funcs->psr_get_state(psr, state);
		psr->funcs->psr_get_state(psr, state, panel_inst);
	else if (dmcu != NULL && link->psr_settings.psr_feature_enabled)
		dmcu->funcs->get_psr_state(dmcu, state);

@@ -2780,6 +2788,7 @@ bool dc_link_setup_psr(struct dc_link *link,
	struct dmcu *dmcu;
	struct dmub_psr *psr;
	int i;
	unsigned int panel_inst;
	/* updateSinkPsrDpcdConfig*/
	union dpcd_psr_configuration psr_configuration;

@@ -2795,6 +2804,9 @@ bool dc_link_setup_psr(struct dc_link *link,
	if (!dmcu && !psr)
		return false;

	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
		return false;


	memset(&psr_configuration, 0, sizeof(psr_configuration));

@@ -2909,7 +2921,8 @@ bool dc_link_setup_psr(struct dc_link *link,
	psr_context->frame_delay = 0;

	if (psr)
		link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr, link, psr_context);
		link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr,
			link, psr_context, panel_inst);
	else
		link->psr_settings.psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context);

+23 −11
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state)
/*
 * Get PSR state from firmware.
 */
static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state)
static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst)
{
	struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
	uint32_t raw_state = 0;
@@ -86,7 +86,7 @@ static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state)

	do {
		// Send gpint command and wait for ack
		status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30);
		status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, panel_inst, 30);

		if (status == DMUB_STATUS_OK) {
			// GPINT was executed, get response
@@ -105,7 +105,7 @@ static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state)
/*
 * Set PSR version.
 */
static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream)
static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream, uint8_t panel_inst)
{
	union dmub_rb_cmd cmd;
	struct dc_context *dc = dmub->ctx;
@@ -125,6 +125,8 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *
		cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED;
		break;
	}
	cmd.psr_set_version.psr_set_version_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
	cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst;
	cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data);

	dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
@@ -137,7 +139,7 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *
/*
 * Enable/Disable PSR.
 */
static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8_t panel_inst)
{
	union dmub_rb_cmd cmd;
	struct dc_context *dc = dmub->ctx;
@@ -147,6 +149,9 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
	memset(&cmd, 0, sizeof(cmd));
	cmd.psr_enable.header.type = DMUB_CMD__PSR;

	cmd.psr_enable.data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
	cmd.psr_enable.data.panel_inst = panel_inst;

	if (enable)
		cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_ENABLE;
	else
@@ -164,7 +169,7 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
	 */
	if (wait) {
		for (retry_count = 0; retry_count <= 1000; retry_count++) {
			dmub_psr_get_state(dmub, &state);
			dmub_psr_get_state(dmub, &state, panel_inst);

			if (enable) {
				if (state != PSR_STATE0)
@@ -186,13 +191,13 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait)
/*
 * Set PSR level.
 */
static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level)
static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_t panel_inst)
{
	union dmub_rb_cmd cmd;
	enum dc_psr_state state = PSR_STATE0;
	struct dc_context *dc = dmub->ctx;

	dmub_psr_get_state(dmub, &state);
	dmub_psr_get_state(dmub, &state, panel_inst);

	if (state == PSR_STATE0)
		return;
@@ -202,7 +207,8 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level)
	cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL;
	cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data);
	cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;

	cmd.psr_set_level.psr_set_level_data.cmd_version = PSR_VERSION_1;
	cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst;
	dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
	dc_dmub_srv_cmd_execute(dc->dmub_srv);
	dc_dmub_srv_wait_idle(dc->dmub_srv);
@@ -213,7 +219,8 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level)
 */
static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
		struct dc_link *link,
		struct psr_context *psr_context)
		struct psr_context *psr_context,
		uint8_t panel_inst)
{
	union dmub_rb_cmd cmd;
	struct dc_context *dc = dmub->ctx;
@@ -237,7 +244,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
		return false;

	// First, set the psr version
	if (!dmub_psr_set_version(dmub, pipe_ctx->stream))
	if (!dmub_psr_set_version(dmub, pipe_ctx->stream, panel_inst))
		return false;

	// Program DP DPHY fast training registers
@@ -286,6 +293,8 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
	copy_settings_data->debug.bitfields.use_hw_lock_mgr		= 1;
	copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled);
	copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us;
	copy_settings_data->cmd_version =  PSR_VERSION_1;
	copy_settings_data->panel_inst = panel_inst;

	dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
	dc_dmub_srv_cmd_execute(dc->dmub_srv);
@@ -297,12 +306,15 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
/*
 * Send command to PSR to force static ENTER and ignore all state changes until exit
 */
static void dmub_psr_force_static(struct dmub_psr *dmub)
static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst)
{
	union dmub_rb_cmd cmd;
	struct dc_context *dc = dmub->ctx;

	memset(&cmd, 0, sizeof(cmd));

	cmd.psr_force_static.psr_force_static_data.panel_inst = panel_inst;
	cmd.psr_force_static.psr_force_static_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
	cmd.psr_force_static.header.type = DMUB_CMD__PSR;
	cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
	cmd.psr_enable.header.payload_bytes = 0;
+9 −5
Original line number Diff line number Diff line
@@ -35,11 +35,15 @@ struct dmub_psr {
};

struct dmub_psr_funcs {
	bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context);
	void (*psr_enable)(struct dmub_psr *dmub, bool enable, bool wait);
	void (*psr_get_state)(struct dmub_psr *dmub, enum dc_psr_state *dc_psr_state);
	void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level);
	void (*psr_force_static)(struct dmub_psr *dmub);
	bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link,
	struct psr_context *psr_context, uint8_t panel_inst);
	void (*psr_enable)(struct dmub_psr *dmub, bool enable, bool wait,
	uint8_t panel_inst);
	void (*psr_get_state)(struct dmub_psr *dmub, enum dc_psr_state *dc_psr_state,
	uint8_t panel_inst);
	void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level,
	uint8_t panel_inst);
	void (*psr_force_static)(struct dmub_psr *dmub, uint8_t panel_inst);
	void (*psr_get_residency)(struct dmub_psr *dmub, uint32_t *residency);
};

Loading