diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6a4dc90cb2801..3967bc19366b0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8205,6 +8205,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); new_state->freesync_capable = state->freesync_capable; + new_state->freesync_on_desktop_capable = state->freesync_on_desktop_capable; new_state->abm_level = state->abm_level; new_state->scaling = state->scaling; new_state->underscan_enable = state->underscan_enable; @@ -9418,8 +9419,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, connector_type == DRM_MODE_CONNECTOR_eDP) { drm_connector_attach_hdr_output_metadata_property(&aconnector->base); - if (!aconnector->mst_root) + if (!aconnector->mst_root) { drm_connector_attach_vrr_capable_property(&aconnector->base); + drm_connector_attach_passive_vrr_capable_property(&aconnector->base); + } if (adev->dm.hdcp_workqueue) drm_connector_attach_content_protection_property(&aconnector->base, true); @@ -11985,6 +11988,12 @@ static void get_freesync_config_for_crtc( config.vsif_supported = true; config.btr = true; + if (new_con_state->freesync_on_desktop_capable) + new_crtc_state->stream->freesync_on_desktop = + !new_crtc_state->base.passive_vrr_disabled; + else + new_crtc_state->stream->freesync_on_desktop = false; + if (fs_vid_mode) { config.state = VRR_STATE_ACTIVE_FIXED; config.fixed_refresh_in_uhz = new_crtc_state->freesync_config.fixed_refresh_in_uhz; @@ -11996,6 +12005,7 @@ static void get_freesync_config_for_crtc( } } else { config.state = VRR_STATE_UNSUPPORTED; + new_crtc_state->stream->freesync_on_desktop = false; } out: new_crtc_state->freesync_config = config; @@ -14116,7 +14126,8 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, if (do_mccs) { dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink); - if (sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported) + if (!connector->display_info.hdmi.vrr_cap.supported && + sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported) freesync_capable = false; if (sink->mccs_caps.freesync_supported && freesync_capable) @@ -14124,8 +14135,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, } update: - if (dm_con_state) + if (dm_con_state) { dm_con_state->freesync_capable = freesync_capable; + dm_con_state->freesync_on_desktop_capable = freesync_capable; + } drm_dbg_driver(adev_to_drm(adev), "VRR: caps result: freesync_capable=%d min_vfreq=%d max_vfreq=%d\n", @@ -14141,6 +14154,9 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, if (connector->vrr_capable_property) drm_connector_set_vrr_capable_property(connector, freesync_capable); + + if (connector->passive_vrr_capable_property) + drm_connector_set_passive_vrr_capable_property(connector, freesync_capable); } void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index dd199e0b79226..8acde054d7e90 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -1051,6 +1051,7 @@ struct dm_connector_state { uint8_t underscan_hborder; bool underscan_enable; bool freesync_capable; + bool freesync_on_desktop_capable; bool update_hdcp; bool abm_sysfs_forbidden; uint8_t abm_level; diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index e997917819e8e..c50c83360ba2f 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -420,6 +420,8 @@ static int drm_atomic_crtc_set_property(struct drm_crtc *crtc, return ret; } else if (property == config->prop_vrr_enabled) { state->vrr_enabled = val; + } else if (property == config->prop_passive_vrr_disabled) { + state->passive_vrr_disabled = val; } else if (property == config->degamma_lut_property) { const size_t elem_size = sizeof(struct drm_color_lut); u64 lut_size; @@ -505,6 +507,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, *val = (state->mode_blob) ? state->mode_blob->base.id : 0; else if (property == config->prop_vrr_enabled) *val = state->vrr_enabled; + else if (property == config->prop_passive_vrr_disabled) + *val = state->passive_vrr_disabled; else if (property == config->degamma_lut_property) *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; else if (property == config->ctm_property) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 11646453aaac9..f2f45674fa47f 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2367,6 +2367,16 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); * * Absence of the property should indicate absence of support. * + * "passive_vrr_capable": + * Optional &drm_connector boolean property that drivers should attach + * with drm_connector_attach_passive_vrr_capable_property() on + * connectors that could support keeping variable refresh rate signalling + * in fixed-refresh rate scenarios like desktop work. Drivers should update + * the property value by calling + * drm_connector_set_passive_vrr_capable_property(). + * + * Absence of the property should indicate absence of support. + * * "VRR_ENABLED": * Default &drm_crtc boolean property that notifies the driver that the * content on the CRTC is suitable for variable refresh rate presentation. @@ -2385,6 +2395,17 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); * * The driver may place further restrictions within these minimum * and maximum bounds. + * + * "PASSIVE_VRR_DISABLED": + * Default &drm_crtc boolean property that notifies the driver that the + * VRR singalling should be disabled in fixed refresh rate scenarios. + * Functionally, psssive vrr works the same as VRR_ENABLED == false + * but works around displays blanking (mainly HDMI) that do not support + * seamless VRR transitions. Also helps with brightness flickering during + * VRR transitions. + * + * Passive VRR mode is not that useful for DP/eDP sinks where seamless VRR + * transitions are enforced by the standard. */ /** @@ -2418,6 +2439,37 @@ int drm_connector_attach_vrr_capable_property( } EXPORT_SYMBOL(drm_connector_attach_vrr_capable_property); +/** + * drm_connector_attach_passive_vrr_capable_property - creates the + * passive_vrr_capable property + * @connector: connector to create the passive_vrr_capable property on. + * + * This is used by atomic drivers to add support for querying + * variable refresh rate on desktop capability for a connector. + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_attach_passive_vrr_capable_property( + struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_property *prop; + + if (!connector->passive_vrr_capable_property) { + prop = drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE, + "passive_vrr_capable"); + if (!prop) + return -ENOMEM; + + connector->passive_vrr_capable_property = prop; + drm_object_attach_property(&connector->base, prop, 0); + } + + return 0; +} +EXPORT_SYMBOL(drm_connector_attach_passive_vrr_capable_property); + /** * drm_connector_attach_scaling_mode_property - attach atomic scaling mode property * @connector: connector to attach scaling mode property on. @@ -2984,6 +3036,27 @@ void drm_connector_set_vrr_capable_property( } EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); +/** + * drm_connector_set_passive_vrr_capable_property - sets the variable refresh + * rate on desktop capable property for a connector + * @connector: drm connector + * @capable: True if the connector is variable refresh rate on desktop capable + * + * Should be used by atomic drivers to update the indicated support for + * variable refresh rate on desktop over a connector. + */ +void drm_connector_set_passive_vrr_capable_property( + struct drm_connector *connector, bool capable) +{ + if (!connector->passive_vrr_capable_property) + return; + + drm_object_property_set_value(&connector->base, + connector->passive_vrr_capable_property, + capable); +} +EXPORT_SYMBOL(drm_connector_set_passive_vrr_capable_property); + /** * drm_connector_set_panel_orientation - sets the connector's panel_orientation * @connector: connector for which to set the panel-orientation property. diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 63ead8ba67564..bd666dbc30f29 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -322,6 +322,8 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc * config->prop_out_fence_ptr, 0); drm_object_attach_property(&crtc->base, config->prop_vrr_enabled, 0); + drm_object_attach_property(&crtc->base, + config->prop_passive_vrr_disabled, 0); } return 0; diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 66f7dc37b5970..dc1ca08655ca6 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -345,6 +345,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.prop_vrr_enabled = prop; + prop = drm_property_create_bool(dev, 0, + "PASSIVE_VRR_DISABLED"); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_passive_vrr_disabled = prop; + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "DEGAMMA_LUT", 0); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 78d117d4de991..2a64297d97c53 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2206,6 +2206,17 @@ struct drm_connector { */ struct drm_property *vrr_capable_property; + /** + * @passive_vrr_capable_property: Optional property to help userspace + * query hardware support for passive variable refresh rate on a + * connector. Drivers can add the property to a connector by + * calling drm_connector_attach_passive_vrr_capable_property(). + * + * This should be updated only by calling + * drm_connector_set_passive_vrr_capable_property(). + */ + struct drm_property *passive_vrr_capable_property; + /** * @colorspace_property: Connector property to set the suitable * colorspace supported by the sink. @@ -2600,6 +2611,8 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, u32 scaling_mode_mask); int drm_connector_attach_vrr_capable_property( struct drm_connector *connector); +int drm_connector_attach_passive_vrr_capable_property( + struct drm_connector *connector); void drm_connector_attach_panel_type_property(struct drm_connector *connector); int drm_connector_attach_broadcast_rgb_property(struct drm_connector *connector); int drm_connector_attach_colorspace_property(struct drm_connector *connector); @@ -2623,6 +2636,8 @@ void drm_connector_set_link_status_property(struct drm_connector *connector, uint64_t link_status); void drm_connector_set_vrr_capable_property( struct drm_connector *connector, bool capable); +void drm_connector_set_passive_vrr_capable_property( + struct drm_connector *connector, bool capable); int drm_connector_set_panel_orientation( struct drm_connector *connector, enum drm_panel_orientation panel_orientation); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c6dbe8b7db9ee..642a374f403e6 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -311,6 +311,15 @@ struct drm_crtc_state { */ bool vrr_enabled; + /** + * @passive_vrr_disabled: + * + * Indicates if variable refresh rate on desktop should be enabled for + * the CRTC. Support for the requested state will depend on driver and + * hardware capabiltiy - lacking support is not treated as failure. + */ + bool passive_vrr_disabled; + /** * @self_refresh_active: * diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index e584652ddf676..e312e6ae4d7ee 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -701,6 +701,12 @@ struct drm_mode_config { * whether variable refresh rate should be enabled on the CRTC. */ struct drm_property *prop_vrr_enabled; + /** + * @prop_passive_vrr_disabled: Default atomic CRTC property to indicate + * whether passive variable refresh rate should be disabled + * on the CRTC. + */ + struct drm_property *prop_passive_vrr_disabled; /** * @dvi_i_subconnector_property: Optional DVI-I property to