From: Tomasz Pakuła <[email protected]>

Backport of upstream (Tomasz Pakula) amd-gfx v4 series patches 23/27 and
24/27, squashed into the drm-core change required for passive_vrr_capable.

Add the PASSIVE_VRR_DISABLED atomic CRTC property (drm_crtc_state.
passive_vrr_disabled) and the immutable passive_vrr_capable connector
property, together with drm_connector_attach_passive_vrr_capable_property()
and drm_connector_set_passive_vrr_capable_property() helpers.

Passive VRR keeps a sink in its variable-refresh state during fixed
refresh (desktop) use, avoiding blanking/flicker on VRR entry/exit for
HDMI sinks that lack seamless VRR transitions. The property is opt-out
(default enabled where the connector advertises passive_vrr_capable);
lacking hardware support is not treated as failure. Not useful for
DP/eDP where seamless VRR transitions are enforced by the standard.

Signed-off-by: Tomasz Pakuła <[email protected]>
Signed-off-by: Fangzhi Zuo <[email protected]>
---
 drivers/gpu/drm/drm_atomic_uapi.c |  4 ++
 drivers/gpu/drm/drm_connector.c   | 73 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_crtc.c        |  2 +
 drivers/gpu/drm/drm_mode_config.c |  6 +++
 include/drm/drm_connector.h       | 15 +++++++
 include/drm/drm_crtc.h            |  9 ++++
 include/drm/drm_mode_config.h     |  6 +++
 7 files changed, 115 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index e997917819e8..c50c83360ba2 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 9d820a2a87ce..c429105172b0 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -2368,6 +2368,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.
@@ -2386,6 +2396,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.
  */
 
 /**
@@ -2419,6 +2440,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.
@@ -2985,6 +3037,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 63ead8ba6756..bd666dbc30f2 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 66f7dc37b597..dc1ca08655ca 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 9f8f109c2dd1..fd370ecfc6a2 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -2212,6 +2212,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.
@@ -2606,6 +2617,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);
@@ -2629,6 +2642,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 c6dbe8b7db9e..642a374f403e 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 e584652ddf67..e312e6ae4d7e 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
-- 
2.53.0

Reply via email to