On 5/10/22 16:45, David Zhang wrote: > [why & how] > We need to add the necessary DC codes to support PSR-SU rate > control (RC). We'll probably want to expand a bit on what rate control is and also note that this is just adding core functionality for RC but not enabling it. Harry > > Signed-off-by: David Zhang <dingchen.zhang@xxxxxxx> > --- > drivers/gpu/drm/amd/display/dc/core/dc_link.c | 14 +++++++++++ > drivers/gpu/drm/amd/display/dc/dc_link.h | 3 +++ > drivers/gpu/drm/amd/display/dc/dc_types.h | 2 ++ > drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 23 +++++++++++++++++++ > drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 2 ++ > .../drm/amd/display/dc/inc/hw/link_encoder.h | 8 +++++++ > 6 files changed, 52 insertions(+) > > 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 259745074ebb..08dedc16a9c5 100644 > --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c > +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c > @@ -1765,6 +1765,7 @@ static bool dc_link_construct_legacy(struct dc_link *link, > */ > program_hpd_filter(link); > > + link->psr_settings.psr_vtotal_control_support = false; > link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; > > DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__); > @@ -3377,6 +3378,19 @@ void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency) > *residency = 0; > } > > +bool dc_link_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su) > +{ > + struct dc *dc = link->ctx->dc; > + struct dmub_psr *psr = dc->res_pool->psr; > + > + if (psr == NULL || !link->psr_settings.psr_feature_enabled || !link->psr_settings.psr_vtotal_control_support) > + return false; > + > + psr->funcs->psr_set_sink_vtotal_in_psr_active(psr, psr_vtotal_idle, psr_vtotal_su); > + > + return true; > +} > + > const struct dc_link_status *dc_link_get_status(const struct dc_link *link) > { > return &link->link_status; > diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h > index 5e7f70840e1a..4e15e68375da 100644 > --- a/drivers/gpu/drm/amd/display/dc/dc_link.h > +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h > @@ -100,6 +100,7 @@ struct psr_settings { > bool psr_feature_enabled; // PSR is supported by sink > bool psr_allow_active; // PSR is currently active > enum dc_psr_version psr_version; // Internal PSR version, determined based on DPCD > + bool psr_vtotal_control_support; // Vtotal control is supported by sink > > /* These parameters are calculated in Driver, > * based on display timing and Sink capabilities. > @@ -326,6 +327,8 @@ void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency); > void dc_link_blank_all_dp_displays(struct dc *dc); > > void dc_link_blank_dp_stream(struct dc_link *link, bool hw_init); > +bool dc_link_set_sink_vtotal_in_psr_active(const struct dc_link *link, > + uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su); > > /* 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 26b62f50ac4e..fa735d5f730f 100644 > --- a/drivers/gpu/drm/amd/display/dc/dc_types.h > +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h > @@ -684,6 +684,7 @@ struct psr_config { > /* psr2 selective update y granularity capability */ > uint8_t su_y_granularity; > unsigned int line_time_in_us; > + uint8_t rate_control_caps; > }; > > union dmcu_psr_level { > @@ -794,6 +795,7 @@ struct psr_context { > /* psr2 selective update y granularity capability */ > uint8_t su_y_granularity; > unsigned int line_time_in_us; > + uint8_t rate_control_caps; > }; > > struct colorspace_transform { > diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c > index 9ca0cbb0af9b..0df06740ec39 100644 > --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c > +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c > @@ -250,6 +250,27 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_ > dc_dmub_srv_wait_idle(dc->dmub_srv); > } > > +/** > + * Set PSR vtotal requirement for FreeSync PSR. > + */ > +static void dmub_psr_set_sink_vtotal_in_psr_active(struct dmub_psr *dmub, > + uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su) > +{ > + union dmub_rb_cmd cmd; > + struct dc_context *dc = dmub->ctx; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.psr_set_vtotal.header.type = DMUB_CMD__PSR; > + cmd.psr_set_vtotal.header.sub_type = DMUB_CMD__SET_SINK_VTOTAL_IN_PSR_ACTIVE; > + cmd.psr_set_vtotal.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_vtotal_data); > + cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_idle = psr_vtotal_idle; > + cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_su = psr_vtotal_su; > + > + 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); > +} > + > /* > * Set PSR power optimization flags. > */ > @@ -358,6 +379,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, > > copy_settings_data->line_capture_indication = 0; > copy_settings_data->line_time_in_us = psr_context->line_time_in_us; > + copy_settings_data->rate_control_caps = psr_context->rate_control_caps; > 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 = DMUB_CMD_PSR_CONTROL_VERSION_1; > @@ -435,6 +457,7 @@ static const struct dmub_psr_funcs psr_funcs = { > .psr_set_level = dmub_psr_set_level, > .psr_force_static = dmub_psr_force_static, > .psr_get_residency = dmub_psr_get_residency, > + .psr_set_sink_vtotal_in_psr_active = dmub_psr_set_sink_vtotal_in_psr_active, > .psr_set_power_opt = dmub_psr_set_power_opt, > }; > > diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h > index 01acc01cc191..74005b9d352a 100644 > --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h > +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h > @@ -46,6 +46,8 @@ struct dmub_psr_funcs { > void (*psr_force_static)(struct dmub_psr *dmub, uint8_t panel_inst); > void (*psr_get_residency)(struct dmub_psr *dmub, uint32_t *residency, > uint8_t panel_inst); > + void (*psr_set_sink_vtotal_in_psr_active)(struct dmub_psr *dmub, > + uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su); > void (*psr_set_power_opt)(struct dmub_psr *dmub, unsigned int power_opt, uint8_t panel_inst); > }; > > diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h > index 66132f3cac42..c89643eaa0f4 100644 > --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h > +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h > @@ -101,6 +101,14 @@ union dpcd_alpm_configuration { > unsigned char raw; > }; > > +union dpcd_sink_active_vtotal_control_mode { > + struct { > + unsigned char ENABLE : 1; > + unsigned char RESERVED : 7; > + } bits; > + unsigned char raw; > +}; > + > union psr_error_status { > struct { > unsigned char LINK_CRC_ERROR :1;