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];
- clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active;
- dc_link_set_psr_allow_active(edp_link, false, false, false);
+ 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);
+ }
}
}
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];
- dc_link_set_psr_allow_active(edp_link,
- clk_mgr->psr_allow_active_cache, false, false);
+ 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)
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;
+ }
}
}
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)
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
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);
struct dmcu *dmcu;
struct dmub_psr *psr;
int i;
+ unsigned int panel_inst;
/* updateSinkPsrDpcdConfig*/
union dpcd_psr_configuration psr_configuration;
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));
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);
/*
* 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;
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
/*
* 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;
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);
/*
* 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;
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
*/
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)
/*
* 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;
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);
*/
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;
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
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);
/*
* 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;
};
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);
};
/* Trace buffer offset for entry */
#define TRACE_BUFFER_ENTRY_OFFSET 16
+/**
+ *
+ * PSR control version legacy
+ */
+#define DMUB_CMD_PSR_CONTROL_VERSION_UNKNOWN 0x0
+/**
+ * PSR control version with multi edp support
+ */
+#define DMUB_CMD_PSR_CONTROL_VERSION_1 0x1
+
+
/**
* ABM control version legacy
*/
*/
uint8_t fec_enable_delay_in100us;
/**
- * Explicit padding to 4 byte boundary.
+ * PSR control version.
+ */
+ uint8_t cmd_version;
+ /**
+ * Panel Instance.
+ * Panel isntance to identify which psr_state to use
+ * Currently the support is only for 0 or 1
*/
- uint8_t pad3[2];
+ uint8_t panel_inst;
};
/**
*/
uint16_t psr_level;
/**
- * Explicit padding to 4 byte boundary.
+ * PSR control version.
*/
- uint8_t pad[2];
+ uint8_t cmd_version;
+ /**
+ * Panel Instance.
+ * Panel isntance to identify which psr_state to use
+ * Currently the support is only for 0 or 1
+ */
+ uint8_t panel_inst;
};
/**
struct dmub_cmd_psr_set_level_data psr_set_level_data;
};
+struct dmub_rb_cmd_psr_enable_data {
+ /**
+ * PSR control version.
+ */
+ uint8_t cmd_version;
+ /**
+ * Panel Instance.
+ * Panel isntance to identify which psr_state to use
+ * Currently the support is only for 0 or 1
+ */
+ uint8_t panel_inst;
+ /**
+ * Explicit padding to 4 byte boundary.
+ */
+ uint8_t pad[2];
+};
+
/**
* Definition of a DMUB_CMD__PSR_ENABLE command.
* PSR enable/disable is controlled using the sub_type.
* Command header.
*/
struct dmub_cmd_header header;
+
+ struct dmub_rb_cmd_psr_enable_data data;
};
/**
* PSR version that FW should implement.
*/
enum psr_version version;
+ /**
+ * PSR control version.
+ */
+ uint8_t cmd_version;
+ /**
+ * Panel Instance.
+ * Panel isntance to identify which psr_state to use
+ * Currently the support is only for 0 or 1
+ */
+ uint8_t panel_inst;
+ /**
+ * Explicit padding to 4 byte boundary.
+ */
+ uint8_t pad[2];
};
/**
struct dmub_cmd_psr_set_version_data psr_set_version_data;
};
+struct dmub_cmd_psr_force_static_data {
+ /**
+ * PSR control version.
+ */
+ uint8_t cmd_version;
+ /**
+ * Panel Instance.
+ * Panel isntance to identify which psr_state to use
+ * Currently the support is only for 0 or 1
+ */
+ uint8_t panel_inst;
+ /**
+ * Explicit padding to 4 byte boundary.
+ */
+ uint8_t pad[2];
+};
+
/**
* Definition of a DMUB_CMD__PSR_FORCE_STATIC command.
*/
* Command header.
*/
struct dmub_cmd_header header;
+ /**
+ * Data passed from driver to FW in a DMUB_CMD__PSR_FORCE_STATIC command.
+ */
+ struct dmub_cmd_psr_force_static_data psr_force_static_data;
};
/**