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.
}
}
-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)
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;
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;
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;
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,
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 */
*/
psr_context.frame_delay = 0;
+ link->psr_enabled = true;
dmcu->funcs->setup_psr(dmcu, link, &psr_context);
return true;
} else
{
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(
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];
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)
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;
}
};
};
+struct dc_static_screen_events {
+ bool cursor_update;
+ bool surface_update;
+ bool overlay_update;
+};
+
/* Forward declaration*/
struct dc;
struct dc_surface;
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;
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;
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.
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;
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,
pipe_ctx->tg,
&stream->public.timing,
true);
+
+ pipe_ctx->tg->funcs->set_static_screen_control(
+ pipe_ctx->tg,
+ 0x182);
}
if (!pipe_ctx_old->stream) {
}
}
+
+
return DC_OK;
}
stream->public.timing.pix_clk_khz,
context->stream_count);
+ pipe_ctx->stream->sink->link->psr_enabled = false;
+
return DC_OK;
}
}
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->
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;
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) {
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,
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(
unsigned int dpcd_sink_count;
enum edp_revision edp_revision;
+ bool psr_enabled;
/* MST record stream using this link */
struct link_flags {
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,
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;
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;
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);
}
}