From: Sylvia Tsai Date: Fri, 21 Apr 2017 19:29:55 +0000 (-0400) Subject: drm/amd/display: PSR Refactor X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=94267b3df7ee00f21fa0ff7d618ca7e0574db5ed;p=openwrt%2Fstaging%2Fblogic.git 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 Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1dd9c736aedc..93c936d92f5a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -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; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 426f7f8187a6..6f78403e2d64 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -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 diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 17286465e850..f883fdb820c8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -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) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2e12a0ba5ddf..cdb98d5f7caa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -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; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a2a9e4ed393c..d12aa726164e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -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. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 2ba02b50bc18..d2f3b9fd7a30 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -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, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6b249f5bf1da..6a93c96b9b26 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -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-> diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 7070aaf9e433..23760727f000 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -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( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 405608318ccc..2b43e18c65f5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -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 { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 9bfaaad09bea..b42e4a0ef18a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -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, diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 5c6de723da5d..78b4f28d862c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -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); } }