drm/amd/display: PSR Refactor
- Refacotr PSR to follow correct module pattern - fix eDP only working on sink index 0. Signed-off-by: Sylvia Tsai <sylvia.tsai@amd.com> Acked-by: Harry Wentland <Harry.Wentland@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
d27383a2b5
commit
94267b3df7
@@ -199,6 +199,32 @@ static bool set_gamut_remap(struct dc *dc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void set_static_screen_events(struct dc *dc,
|
||||
const struct dc_stream **stream,
|
||||
int num_streams,
|
||||
const struct dc_static_screen_events *events)
|
||||
{
|
||||
struct core_dc *core_dc = DC_TO_CORE(dc);
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
struct pipe_ctx *pipes_affected[MAX_PIPES];
|
||||
int num_pipes_affected = 0;
|
||||
|
||||
for (i = 0; i < num_streams; i++) {
|
||||
struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[i]);
|
||||
|
||||
for (j = 0; j < MAX_PIPES; j++) {
|
||||
if (core_dc->current_context->res_ctx.pipe_ctx[j].stream
|
||||
== core_stream) {
|
||||
pipes_affected[num_pipes_affected++] =
|
||||
&core_dc->current_context->res_ctx.pipe_ctx[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events);
|
||||
}
|
||||
|
||||
/* This function is not expected to fail, proper implementation of
|
||||
* validation will prevent this from ever being called for unsupported
|
||||
* configurations.
|
||||
@@ -240,45 +266,6 @@ static void stream_update_scaling(
|
||||
}
|
||||
}
|
||||
|
||||
static bool set_psr_enable(struct dc *dc, bool enable)
|
||||
{
|
||||
struct core_dc *core_dc = DC_TO_CORE(dc);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < core_dc->link_count; i++)
|
||||
dc_link_set_psr_enable(&core_dc->links[i]->public,
|
||||
enable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool setup_psr(struct dc *dc, const struct dc_stream *stream)
|
||||
{
|
||||
struct core_dc *core_dc = DC_TO_CORE(dc);
|
||||
struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
|
||||
struct pipe_ctx *pipes;
|
||||
int i;
|
||||
unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index;
|
||||
|
||||
for (i = 0; i < core_dc->link_count; i++) {
|
||||
if (core_stream->sink->link == core_dc->links[i])
|
||||
dc_link_setup_psr(&core_dc->links[i]->public,
|
||||
stream);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
|
||||
== core_stream && i != underlay_idx) {
|
||||
pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
|
||||
core_dc->hwss.set_static_screen_control(&pipes, 1,
|
||||
0x182);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_drive_settings(struct dc *dc,
|
||||
struct link_training_settings *lt_settings,
|
||||
const struct dc_link *link)
|
||||
@@ -359,15 +346,12 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc)
|
||||
stream_adjust_vmin_vmax;
|
||||
}
|
||||
|
||||
core_dc->public.stream_funcs.set_static_screen_events =
|
||||
set_static_screen_events;
|
||||
|
||||
core_dc->public.stream_funcs.set_gamut_remap =
|
||||
set_gamut_remap;
|
||||
|
||||
core_dc->public.stream_funcs.set_psr_enable =
|
||||
set_psr_enable;
|
||||
|
||||
core_dc->public.stream_funcs.setup_psr =
|
||||
setup_psr;
|
||||
|
||||
core_dc->public.link_funcs.set_drive_settings =
|
||||
set_drive_settings;
|
||||
|
||||
|
||||
@@ -1430,14 +1430,14 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable)
|
||||
struct core_dc *core_dc = DC_TO_CORE(ctx->dc);
|
||||
struct dmcu *dmcu = core_dc->res_pool->dmcu;
|
||||
|
||||
if (dmcu != NULL && dc_link->psr_caps.psr_version > 0)
|
||||
if (dmcu != NULL && link->psr_enabled)
|
||||
dmcu->funcs->set_psr_enable(dmcu, enable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_link_setup_psr(const struct dc_link *dc_link,
|
||||
const struct dc_stream *stream)
|
||||
const struct dc_stream *stream, struct psr_config *psr_config)
|
||||
{
|
||||
struct core_link *link = DC_LINK_TO_CORE(dc_link);
|
||||
struct dc_context *ctx = link->ctx;
|
||||
@@ -1449,10 +1449,8 @@ bool dc_link_setup_psr(const struct dc_link *dc_link,
|
||||
|
||||
psr_context.controllerId = CONTROLLER_ID_UNDEFINED;
|
||||
|
||||
|
||||
if (dc_link != NULL &&
|
||||
dmcu != NULL &&
|
||||
dc_link->psr_caps.psr_version > 0) {
|
||||
dmcu != NULL) {
|
||||
/* updateSinkPsrDpcdConfig*/
|
||||
union dpcd_psr_configuration psr_configuration;
|
||||
|
||||
@@ -1461,10 +1459,10 @@ bool dc_link_setup_psr(const struct dc_link *dc_link,
|
||||
psr_configuration.bits.ENABLE = 1;
|
||||
psr_configuration.bits.CRC_VERIFICATION = 1;
|
||||
psr_configuration.bits.FRAME_CAPTURE_INDICATION =
|
||||
dc_link->psr_caps.psr_frame_capture_indication_req;
|
||||
psr_config->psr_frame_capture_indication_req;
|
||||
|
||||
/* Check for PSR v2*/
|
||||
if (dc_link->psr_caps.psr_version == 0x2) {
|
||||
if (psr_config->psr_version == 0x2) {
|
||||
/* For PSR v2 selective update.
|
||||
* Indicates whether sink should start capturing
|
||||
* immediately following active scan line,
|
||||
@@ -1512,14 +1510,13 @@ bool dc_link_setup_psr(const struct dc_link *dc_link,
|
||||
stream->timing.v_total),
|
||||
stream->timing.h_total);
|
||||
|
||||
psr_context.psrSupportedDisplayConfig =
|
||||
(dc_link->psr_caps.psr_version > 0) ? true : false;
|
||||
psr_context.psrSupportedDisplayConfig = true;
|
||||
psr_context.psrExitLinkTrainingRequired =
|
||||
dc_link->psr_caps.psr_exit_link_training_required;
|
||||
psr_config->psr_exit_link_training_required;
|
||||
psr_context.sdpTransmitLineNumDeadline =
|
||||
dc_link->psr_caps.psr_sdp_transmit_line_num_deadline;
|
||||
psr_config->psr_sdp_transmit_line_num_deadline;
|
||||
psr_context.psrFrameCaptureIndicationReq =
|
||||
dc_link->psr_caps.psr_frame_capture_indication_req;
|
||||
psr_config->psr_frame_capture_indication_req;
|
||||
|
||||
psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */
|
||||
|
||||
@@ -1550,6 +1547,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link,
|
||||
*/
|
||||
psr_context.frame_delay = 0;
|
||||
|
||||
link->psr_enabled = true;
|
||||
dmcu->funcs->setup_psr(dmcu, link, &psr_context);
|
||||
return true;
|
||||
} else
|
||||
|
||||
@@ -1478,7 +1478,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link)
|
||||
{
|
||||
union dpcd_psr_configuration psr_configuration;
|
||||
|
||||
if (link->public.psr_caps.psr_version == 0)
|
||||
if (!link->psr_enabled)
|
||||
return false;
|
||||
|
||||
dm_helpers_dp_read_dpcd(
|
||||
@@ -2060,36 +2060,6 @@ static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data,
|
||||
link->wa_flags.dp_keep_receiver_powered = false;
|
||||
}
|
||||
|
||||
static void retrieve_psr_link_cap(struct core_link *link,
|
||||
enum edp_revision edp_revision)
|
||||
{
|
||||
if (edp_revision >= EDP_REVISION_13) {
|
||||
core_link_read_dpcd(link,
|
||||
DP_PSR_SUPPORT,
|
||||
(uint8_t *)(&link->public.psr_caps),
|
||||
sizeof(link->public.psr_caps));
|
||||
if (link->public.psr_caps.psr_version != 0) {
|
||||
unsigned char psr_capability = 0;
|
||||
|
||||
core_link_read_dpcd(link,
|
||||
DP_PSR_CAPS,
|
||||
&psr_capability,
|
||||
sizeof(psr_capability));
|
||||
/* Bit 0 determines whether fast link training is
|
||||
* required on PSR exit. If set to 0, link training
|
||||
* is required. If set to 1, sink must lock within
|
||||
* five Idle Patterns after Main Link is turned on.
|
||||
*/
|
||||
link->public.psr_caps.psr_exit_link_training_required
|
||||
= !(psr_capability & 0x1);
|
||||
|
||||
psr_capability = (psr_capability >> 1) & 0x7;
|
||||
link->public.psr_caps.psr_rfb_setup_time =
|
||||
55 * (6 - psr_capability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void retrieve_link_cap(struct core_link *link)
|
||||
{
|
||||
uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1];
|
||||
@@ -2157,38 +2127,17 @@ static void retrieve_link_cap(struct core_link *link)
|
||||
link->dpcd_caps.panel_mode_edp =
|
||||
edp_config_cap.bits.ALT_SCRAMBLER_RESET;
|
||||
|
||||
link->edp_revision = EDP_REVISION_11;
|
||||
|
||||
link->public.test_pattern_enabled = false;
|
||||
link->public.compliance_test_state.raw = 0;
|
||||
|
||||
link->public.psr_caps.psr_exit_link_training_required = false;
|
||||
link->public.psr_caps.psr_frame_capture_indication_req = false;
|
||||
link->public.psr_caps.psr_rfb_setup_time = 0;
|
||||
link->public.psr_caps.psr_sdp_transmit_line_num_deadline = 0;
|
||||
link->public.psr_caps.psr_version = 0;
|
||||
|
||||
/* read sink count */
|
||||
core_link_read_dpcd(link,
|
||||
DP_SINK_COUNT,
|
||||
&link->dpcd_caps.sink_count.raw,
|
||||
sizeof(link->dpcd_caps.sink_count.raw));
|
||||
|
||||
/* Display control registers starting at DPCD 700h are only valid and
|
||||
* enabled if this eDP config cap bit is set. */
|
||||
if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) {
|
||||
/* Read the Panel's eDP revision at DPCD 700h. */
|
||||
core_link_read_dpcd(link,
|
||||
DP_EDP_DPCD_REV,
|
||||
(uint8_t *)(&link->edp_revision),
|
||||
sizeof(link->edp_revision));
|
||||
}
|
||||
|
||||
/* Connectivity log: detection */
|
||||
CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
|
||||
|
||||
/* TODO: Confirm if need retrieve_psr_link_cap */
|
||||
retrieve_psr_link_cap(link, link->edp_revision);
|
||||
}
|
||||
|
||||
void detect_dp_sink_caps(struct core_link *link)
|
||||
|
||||
@@ -2015,7 +2015,7 @@ static void set_vsc_info_packet(
|
||||
unsigned int vscPacketRevision = 0;
|
||||
unsigned int i;
|
||||
|
||||
if (stream->sink->link->public.psr_caps.psr_version != 0) {
|
||||
if (stream->sink->link->psr_enabled) {
|
||||
vscPacketRevision = 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,12 @@ struct dc_surface_dcc_cap {
|
||||
};
|
||||
};
|
||||
|
||||
struct dc_static_screen_events {
|
||||
bool cursor_update;
|
||||
bool surface_update;
|
||||
bool overlay_update;
|
||||
};
|
||||
|
||||
/* Forward declaration*/
|
||||
struct dc;
|
||||
struct dc_surface;
|
||||
@@ -102,10 +108,14 @@ struct dc_stream_funcs {
|
||||
const struct dc_stream *dc_stream,
|
||||
const struct rect *src,
|
||||
const struct rect *dst);
|
||||
|
||||
bool (*set_gamut_remap)(struct dc *dc,
|
||||
const struct dc_stream **stream, int num_streams);
|
||||
bool (*set_psr_enable)(struct dc *dc, bool enable);
|
||||
bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream);
|
||||
|
||||
void (*set_static_screen_events)(struct dc *dc,
|
||||
const struct dc_stream **stream,
|
||||
int num_streams,
|
||||
const struct dc_static_screen_events *events);
|
||||
};
|
||||
|
||||
struct link_training_settings;
|
||||
@@ -604,7 +614,6 @@ struct dc_link {
|
||||
uint8_t ddc_hw_inst;
|
||||
uint8_t link_enc_hw_inst;
|
||||
|
||||
struct psr_caps psr_caps;
|
||||
bool test_pattern_enabled;
|
||||
union compliance_test_state compliance_test_state;
|
||||
|
||||
@@ -657,7 +666,7 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level,
|
||||
bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable);
|
||||
|
||||
bool dc_link_setup_psr(const struct dc_link *dc_link,
|
||||
const struct dc_stream *stream);
|
||||
const struct dc_stream *stream, struct psr_config *psr_config);
|
||||
|
||||
/* Request DC to detect if there is a Panel connected.
|
||||
* boot - If this call is during initial boot.
|
||||
|
||||
@@ -484,6 +484,15 @@ struct freesync_context {
|
||||
unsigned int nominal_refresh_in_micro_hz;
|
||||
};
|
||||
|
||||
struct psr_config {
|
||||
unsigned char psr_version;
|
||||
unsigned int psr_rfb_setup_time;
|
||||
bool psr_exit_link_training_required;
|
||||
|
||||
bool psr_frame_capture_indication_req;
|
||||
unsigned int psr_sdp_transmit_line_num_deadline;
|
||||
};
|
||||
|
||||
struct colorspace_transform {
|
||||
struct fixed31_32 matrix[12];
|
||||
bool enable_remap;
|
||||
@@ -494,21 +503,6 @@ struct csc_transform {
|
||||
bool enable_adjustment;
|
||||
};
|
||||
|
||||
struct psr_caps {
|
||||
/* These parameters are from PSR capabilities reported by Sink DPCD */
|
||||
unsigned char psr_version;
|
||||
unsigned int psr_rfb_setup_time;
|
||||
bool psr_exit_link_training_required;
|
||||
|
||||
/* These parameters are calculated in Driver,
|
||||
* based on display timing and Sink capabilities.
|
||||
* If VBLANK region is too small and Sink takes a long time
|
||||
* to set up RFB, it may take an extra frame to enter PSR state.
|
||||
*/
|
||||
bool psr_frame_capture_indication_req;
|
||||
unsigned int psr_sdp_transmit_line_num_deadline;
|
||||
};
|
||||
|
||||
enum i2c_mot_mode {
|
||||
I2C_MOT_UNDEF,
|
||||
I2C_MOT_TRUE,
|
||||
|
||||
@@ -1005,6 +1005,10 @@ static enum dc_status dce110_prog_pixclk_crtc_otg(
|
||||
pipe_ctx->tg,
|
||||
&stream->public.timing,
|
||||
true);
|
||||
|
||||
pipe_ctx->tg->funcs->set_static_screen_control(
|
||||
pipe_ctx->tg,
|
||||
0x182);
|
||||
}
|
||||
|
||||
if (!pipe_ctx_old->stream) {
|
||||
@@ -1015,6 +1019,8 @@ static enum dc_status dce110_prog_pixclk_crtc_otg(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
@@ -1114,6 +1120,8 @@ static enum dc_status apply_single_controller_ctx_to_hw(
|
||||
stream->public.timing.pix_clk_khz,
|
||||
context->stream_count);
|
||||
|
||||
pipe_ctx->stream->sink->link->psr_enabled = false;
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
@@ -1355,9 +1363,17 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
|
||||
}
|
||||
|
||||
static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
|
||||
int num_pipes, int value)
|
||||
int num_pipes, const struct dc_static_screen_events *events)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int value = 0;
|
||||
|
||||
if (events->overlay_update)
|
||||
value |= 0x100;
|
||||
if (events->surface_update)
|
||||
value |= 0x80;
|
||||
if (events->cursor_update)
|
||||
value |= 0x2;
|
||||
|
||||
for (i = 0; i < num_pipes; i++)
|
||||
pipe_ctx[i]->tg->funcs->
|
||||
|
||||
@@ -371,7 +371,6 @@ void dce110_timing_generator_set_drr(
|
||||
uint32_t v_total_min = 0;
|
||||
uint32_t v_total_max = 0;
|
||||
uint32_t v_total_cntl = 0;
|
||||
uint32_t static_screen_cntl = 0;
|
||||
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
|
||||
|
||||
uint32_t addr = 0;
|
||||
@@ -385,9 +384,6 @@ void dce110_timing_generator_set_drr(
|
||||
addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
|
||||
v_total_cntl = dm_read_reg(tg->ctx, addr);
|
||||
|
||||
addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
|
||||
static_screen_cntl = dm_read_reg(tg->ctx, addr);
|
||||
|
||||
if (params != NULL &&
|
||||
params->vertical_total_max > 0 &&
|
||||
params->vertical_total_min > 0) {
|
||||
@@ -430,20 +426,11 @@ void dce110_timing_generator_set_drr(
|
||||
0,
|
||||
CRTC_V_TOTAL_CONTROL,
|
||||
CRTC_SET_V_TOTAL_MIN_MASK);
|
||||
|
||||
set_reg_field_value(static_screen_cntl,
|
||||
0x180,
|
||||
CRTC_STATIC_SCREEN_CONTROL,
|
||||
CRTC_STATIC_SCREEN_EVENT_MASK);
|
||||
} else {
|
||||
set_reg_field_value(v_total_cntl,
|
||||
0,
|
||||
CRTC_V_TOTAL_CONTROL,
|
||||
CRTC_SET_V_TOTAL_MIN_MASK);
|
||||
set_reg_field_value(static_screen_cntl,
|
||||
0,
|
||||
CRTC_STATIC_SCREEN_CONTROL,
|
||||
CRTC_STATIC_SCREEN_EVENT_MASK);
|
||||
set_reg_field_value(v_total_min,
|
||||
0,
|
||||
CRTC_V_TOTAL_MIN,
|
||||
@@ -478,9 +465,6 @@ void dce110_timing_generator_set_drr(
|
||||
|
||||
addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
|
||||
dm_write_reg(tg->ctx, addr, v_total_cntl);
|
||||
|
||||
addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
|
||||
dm_write_reg(tg->ctx, addr, static_screen_cntl);
|
||||
}
|
||||
|
||||
void dce110_timing_generator_set_static_screen_control(
|
||||
|
||||
@@ -156,6 +156,7 @@ struct core_link {
|
||||
unsigned int dpcd_sink_count;
|
||||
|
||||
enum edp_revision edp_revision;
|
||||
bool psr_enabled;
|
||||
|
||||
/* MST record stream using this link */
|
||||
struct link_flags {
|
||||
|
||||
@@ -132,7 +132,7 @@ struct hw_sequencer_funcs {
|
||||
int vmin, int vmax);
|
||||
|
||||
void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx,
|
||||
int num_pipes, int value);
|
||||
int num_pipes, const struct dc_static_screen_events *events);
|
||||
|
||||
enum dc_status (*prog_pixclk_crtc_otg)(
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
|
||||
@@ -264,10 +264,10 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync,
|
||||
enable_for_video = false;
|
||||
}
|
||||
|
||||
temp = core_stream->public.timing.pix_clk_khz;
|
||||
temp = stream->timing.pix_clk_khz;
|
||||
temp *= 1000ULL * 1000ULL * 1000ULL;
|
||||
temp = div_u64(temp, core_stream->public.timing.h_total);
|
||||
temp = div_u64(temp, core_stream->public.timing.v_total);
|
||||
temp = div_u64(temp, stream->timing.h_total);
|
||||
temp = div_u64(temp, stream->timing.v_total);
|
||||
|
||||
nom_refresh_rate_micro_hz = (unsigned int) temp;
|
||||
|
||||
@@ -657,6 +657,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
|
||||
unsigned int min_frame_duration_in_ns, vmax, vmin = 0;
|
||||
struct freesync_state *state;
|
||||
struct core_freesync *core_freesync = NULL;
|
||||
struct dc_static_screen_events triggers = {0};
|
||||
|
||||
if (mod_freesync == NULL)
|
||||
return;
|
||||
@@ -749,6 +750,13 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
|
||||
core_freesync->dc, streams,
|
||||
num_streams, v_total,
|
||||
v_total);
|
||||
|
||||
triggers.overlay_update = true;
|
||||
triggers.surface_update = true;
|
||||
|
||||
core_freesync->dc->stream_funcs.set_static_screen_events(
|
||||
core_freesync->dc, streams, num_streams,
|
||||
&triggers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user