mirror of
https://github.com/torvalds/linux.git
synced 2026-11-08 21:24:02 +01:00
drm/amd/display: eDP panel polarity control and test support
eDP panels can require explicit polarity control during power transitions to ensure correct signal behavior. Without this, panels that depend on polarity state may behave incorrectly when combined with refresh rate drop logic, since the two features previously had no coordination point. To address this, a set/reset/query API is introduced and integrated into the resource layer so polarity is managed as a first-class concern within the existing power optimization flow. RamlessPowerOptimization is updated to coordinate polarity state alongside refresh rate drop decisions, preventing the two paths from conflicting during transitions. Reviewed-by: Sreeja Golui <sreeja.golui@amd.com> Signed-off-by: Harry VanZyllDeJong <hvanzyll@amd.com> Signed-off-by: Tom Chung <chiahsuan.chung@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
8f27dbc82e
commit
7dcd85c224
|
|
@ -601,3 +601,25 @@ void dc_link_get_alpm_support(struct dc_link *link,
|
|||
{
|
||||
link->dc->link_srv->edp_get_alpm_support(link, auxless_support, auxwake_support);
|
||||
}
|
||||
|
||||
void dc_link_set_panel_polarity_enable(struct dc_link *link, bool enable)
|
||||
{
|
||||
if (link->dc->link_srv->edp_set_panel_polarity_enabled)
|
||||
link->dc->link_srv->edp_set_panel_polarity_enabled(link, enable);
|
||||
}
|
||||
|
||||
void dc_link_panel_polarity_reset(struct dc_link *link)
|
||||
{
|
||||
if (link->dc->link_srv->edp_panel_polarity_reset)
|
||||
link->dc->link_srv->edp_panel_polarity_reset(link);
|
||||
}
|
||||
|
||||
bool dc_link_get_panel_polarity(struct dc_link *link, int32_t *polarity)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (link->dc->link_srv->edp_get_panel_polarity)
|
||||
ret = link->dc->link_srv->edp_get_panel_polarity(link, polarity);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3897,4 +3897,11 @@ unsigned int dc_override_memory_bandwidth_request(
|
|||
struct dc *dc,
|
||||
unsigned int bw_mbps);
|
||||
|
||||
/**
|
||||
* Panel Polarity Control
|
||||
*/
|
||||
void dc_link_set_panel_polarity_enable(struct dc_link *link, bool enable);
|
||||
void dc_link_panel_polarity_reset(struct dc_link *link);
|
||||
bool dc_link_get_panel_polarity(struct dc_link *link, int32_t *polarity);
|
||||
|
||||
#endif /* DC_INTERFACE_H_ */
|
||||
|
|
|
|||
|
|
@ -2475,3 +2475,55 @@ void dc_dmub_srv_get_fams2_debug_meta(struct dc_dmub_srv *dc_dmub_srv)
|
|||
dm_execute_dmub_cmd_list(dc_dmub_srv->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
}
|
||||
|
||||
void dc_dmub_srv_panel_polarity_set_enable(struct dc_dmub_srv *dc_dmub_srv, uint8_t panel_inst, bool enable)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dc_context *ctx = dc_dmub_srv->ctx;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.panel_polarity_enable.header.type = DMUB_CMD__PANEL_POLARITY;
|
||||
cmd.panel_polarity_enable.header.sub_type = DMUB_CMD__PANEL_POLARITY_ENABLE;
|
||||
cmd.panel_polarity_enable.header.payload_bytes = sizeof(cmd.panel_polarity_enable.data);
|
||||
cmd.panel_polarity_enable.data.enable = enable ? 1 : 0;
|
||||
cmd.panel_polarity_enable.data.otg_inst = panel_inst;
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
}
|
||||
|
||||
void dc_dmub_srv_panel_polarity_reset(struct dc_dmub_srv *dc_dmub_srv, uint8_t panel_inst)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dc_context *ctx = dc_dmub_srv->ctx;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.panel_polarity_enable.header.type = DMUB_CMD__PANEL_POLARITY;
|
||||
cmd.panel_polarity_enable.header.sub_type = DMUB_CMD__PANEL_POLARITY_RESET;
|
||||
cmd.panel_polarity_enable.header.payload_bytes = sizeof(cmd.panel_polarity_enable.data);
|
||||
cmd.panel_polarity_enable.data.otg_inst = panel_inst;
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
}
|
||||
|
||||
bool dc_dmub_srv_panel_polarity_get_polarity(struct dc_dmub_srv *dc_dmub_srv, uint8_t panel_inst, int32_t *polarity)
|
||||
{
|
||||
bool ret = false;
|
||||
uint32_t raw_polarity = 0;
|
||||
uint32_t retry_count = 0;
|
||||
struct dc_context *ctx = dc_dmub_srv->ctx;
|
||||
|
||||
*polarity = 0;
|
||||
|
||||
do {
|
||||
/* Send gpint command and wait for ack */
|
||||
if (dc_wake_and_execute_gpint(ctx, DMUB_GPINT__PANEL_POLARITY_GET_BIAS, panel_inst, &raw_polarity,
|
||||
DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
|
||||
*polarity = (int32_t)raw_polarity;
|
||||
ret = true;
|
||||
}
|
||||
} while (++retry_count <= 1000 && ret == false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -424,4 +424,31 @@ bool dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest(
|
|||
* @dc_dmub_srv - pointer to DMUB service object
|
||||
*/
|
||||
void dc_dmub_srv_get_fams2_debug_meta(struct dc_dmub_srv *dc_dmub_srv);
|
||||
|
||||
/**
|
||||
* dc_dmub_srv_panel_polarity_set_enable() - Enables or disables panel polarity.
|
||||
*
|
||||
* @dc_dmub_srv: DMUB service handle
|
||||
* @panel_inst: Panel instance
|
||||
* @enable: true to enable, false to disable
|
||||
*/
|
||||
void dc_dmub_srv_panel_polarity_set_enable(struct dc_dmub_srv *dc_dmub_srv, uint8_t panel_inst, bool enable);
|
||||
|
||||
/**
|
||||
* dc_dmub_srv_panel_polarity_reset() - Resets panel polarity.
|
||||
*
|
||||
* @dc_dmub_srv: DMUB service handle
|
||||
* @panel_inst: Panel instance
|
||||
*/
|
||||
void dc_dmub_srv_panel_polarity_reset(struct dc_dmub_srv *dc_dmub_srv, uint8_t panel_inst);
|
||||
|
||||
/**
|
||||
* dc_dmub_srv_panel_polarity_get_polarity() - Gets the current panel polarity.
|
||||
*
|
||||
* @dc_dmub_srv: DMUB service handle
|
||||
* @panel_inst: Panel instance
|
||||
* @polarity: Pointer to store the current polarity
|
||||
*/
|
||||
bool dc_dmub_srv_panel_polarity_get_polarity(struct dc_dmub_srv *dc_dmub_srv, uint8_t panel_inst, int32_t *polarity);
|
||||
|
||||
#endif /* _DMUB_DC_SRV_H_ */
|
||||
|
|
|
|||
|
|
@ -315,7 +315,9 @@ struct link_service {
|
|||
bool (*dp_pr_set_general_cmd)(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data);
|
||||
bool (*dp_pr_get_state)(const struct dc_link *link, uint64_t *state);
|
||||
void (*edp_set_panel_power)(struct dc_link *link, bool powerOn);
|
||||
|
||||
void (*edp_set_panel_polarity_enabled)(const struct dc_link *link, bool enable);
|
||||
void (*edp_panel_polarity_reset)(struct dc_link *link);
|
||||
bool (*edp_get_panel_polarity)(struct dc_link *link, int32_t *polarity);
|
||||
|
||||
/*************************** HDMI FRL *********************************/
|
||||
bool (*hdmi_frl_poll_status_flag)(struct dc_link *link);
|
||||
|
|
@ -363,5 +365,6 @@ struct link_service {
|
|||
uint64_t (*dp_trace_get_edp_poweroff_timestamp)(struct dc_link *link);
|
||||
void (*dp_trace_source_sequence)(
|
||||
struct dc_link *link, uint8_t dp_test_mode);
|
||||
|
||||
};
|
||||
#endif /* __DC_LINK_HPD_H__ */
|
||||
|
|
|
|||
|
|
@ -234,6 +234,10 @@ static void construct_link_service_edp_panel_control(struct link_service *link_s
|
|||
link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7;
|
||||
link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable;
|
||||
link_srv->edp_set_panel_power = edp_set_panel_power;
|
||||
|
||||
link_srv->edp_set_panel_polarity_enabled = edp_set_panel_polarity_enabled;
|
||||
link_srv->edp_panel_polarity_reset = edp_panel_polarity_reset;
|
||||
link_srv->edp_get_panel_polarity = edp_get_panel_polarity;
|
||||
}
|
||||
|
||||
/* link dp panel replay implements DP panel replay functionality.
|
||||
|
|
|
|||
|
|
@ -1301,3 +1301,33 @@ void edp_set_panel_assr(struct dc_link *link, struct pipe_ctx *pipe_ctx,
|
|||
*panel_mode = DP_PANEL_MODE_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
void edp_set_panel_polarity_enabled(const struct dc_link *link, bool enable)
|
||||
{
|
||||
struct dc *dc = link->ctx->dc;
|
||||
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
|
||||
if (dc_dmub_srv)
|
||||
dc_dmub_srv_panel_polarity_set_enable(dc_dmub_srv, 0, enable);
|
||||
}
|
||||
|
||||
void edp_panel_polarity_reset(struct dc_link *link)
|
||||
{
|
||||
struct dc *dc = link->ctx->dc;
|
||||
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
|
||||
if (dc_dmub_srv)
|
||||
dc_dmub_srv_panel_polarity_reset(dc_dmub_srv, 0);
|
||||
}
|
||||
|
||||
bool edp_get_panel_polarity(struct dc_link *link, int32_t *polarity)
|
||||
{
|
||||
struct dc *dc = link->ctx->dc;
|
||||
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
bool ret = false;
|
||||
|
||||
if (dc_dmub_srv)
|
||||
ret = dc_dmub_srv_panel_polarity_get_polarity(dc_dmub_srv, 0, polarity);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,4 +77,8 @@ bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_stat
|
|||
void edp_set_panel_power(struct dc_link *link, bool powerOn);
|
||||
void edp_set_panel_assr(struct dc_link *link, struct pipe_ctx *pipe_ctx,
|
||||
enum dp_panel_mode *panel_mode, bool enable);
|
||||
|
||||
void edp_set_panel_polarity_enabled(const struct dc_link *link, bool enable);
|
||||
void edp_panel_polarity_reset(struct dc_link *link);
|
||||
bool edp_get_panel_polarity(struct dc_link *link, int32_t *polarity);
|
||||
#endif /* __DC_LINK_EDP_POWER_CONTROL_H__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user