All the drivers that implement the HDMI scrambling setup (dw-hdmi, i915,
tegra, vc4) duplicate the same logic to see if the TMDS ratio or the
scrambling state needs to be modified depending on the current connector
state and CRTC mode.

Since it's basically the same logic everywhere, let's put these two
informations in the connector state, and filled by a atomic_check helper
so that drivers can just use it.

Signed-off-by: Maxime Ripard <max...@cerno.tech>
---
 drivers/gpu/drm/drm_atomic_state_helper.c | 58 +++++++++++++++++++++++
 include/drm/drm_atomic_state_helper.h     |  3 ++
 include/drm/drm_connector.h               | 25 ++++++++++
 3 files changed, 86 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index ddcf5c2c8e6a..93f40f2975c3 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -454,6 +454,64 @@ void drm_atomic_helper_connector_tv_reset(struct 
drm_connector *connector)
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
 
+/**
+ * drm_atomic_helper_connector_hdmi_check - Checks the state of an HDMI 
connector
+ * @connector: DRM connector
+ * @state: DRM atomic state to check
+ *
+ * Checks that an HDMI connector state is sane, and sets the various
+ * HDMI-specific flags in drm_connector_state related to HDMI support.
+ *
+ * Returns:
+ * 0 on success, a negative error code otherwise.
+ */
+int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
+                                          struct drm_atomic_state *state)
+{
+       struct drm_connector_state *conn_state = 
drm_atomic_get_new_connector_state(state,
+                                                                               
    connector);
+       struct drm_display_info *info = &connector->display_info;
+       const struct drm_display_mode *mode;
+       struct drm_crtc_state *crtc_state;
+       struct drm_crtc *crtc;
+       bool required;
+
+       if (!conn_state)
+               return -EINVAL;
+
+       crtc = conn_state->crtc;
+       if (!crtc)
+               return -EINVAL;
+
+       crtc_state = drm_atomic_get_crtc_state(state, crtc);
+       if (IS_ERR(crtc_state))
+               return PTR_ERR(crtc_state);
+
+       mode = &crtc_state->mode;
+       crtc_state->connectors_changed = true;
+       conn_state->hdmi_needs_scrambling = false;
+       conn_state->hdmi_needs_high_tmds_ratio = false;
+
+       if (!info->is_hdmi)
+               return 0;
+
+       if (!info->hdmi.scdc.supported)
+               return 0;
+
+       required = drm_mode_hdmi_requires_scrambling(mode);
+       if (required && !info->hdmi.scdc.scrambling.supported)
+               return -EINVAL;
+
+       if (info->hdmi.scdc.scrambling.low_rates || required)
+               conn_state->hdmi_needs_scrambling = true;
+
+       if (required)
+               conn_state->hdmi_needs_high_tmds_ratio = true;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_hdmi_check);
+
 /**
  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
  * @connector: connector object
diff --git a/include/drm/drm_atomic_state_helper.h 
b/include/drm/drm_atomic_state_helper.h
index 3f8f1d627f7c..3d3d1ff355f4 100644
--- a/include/drm/drm_atomic_state_helper.h
+++ b/include/drm/drm_atomic_state_helper.h
@@ -26,6 +26,7 @@
 
 #include <linux/types.h>
 
+struct drm_atomic_state;
 struct drm_bridge;
 struct drm_bridge_state;
 struct drm_crtc;
@@ -71,6 +72,8 @@ void __drm_atomic_helper_connector_reset(struct drm_connector 
*connector,
                                         struct drm_connector_state 
*conn_state);
 void drm_atomic_helper_connector_reset(struct drm_connector *connector);
 void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
+int drm_atomic_helper_connector_hdmi_check(struct drm_connector *connector,
+                                          struct drm_atomic_state *state);
 void
 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
                                           struct drm_connector_state *state);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 030636635af1..78d3d6c78fcb 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -832,6 +832,31 @@ struct drm_connector_state {
         * DRM blob property for HDR output metadata
         */
        struct drm_property_blob *hdr_output_metadata;
+
+       /**
+        * @hdmi_needs_scrambling:
+        *
+        * Only relevant for HDMI sink. Tracks whether the scrambling
+        * should be turned on for the current sink and mode.
+        *
+        * Drivers needing this should use
+        * drm_atomic_helper_connector_hdmi_check() and use the value
+        * set here to enable or disable their scrambler.
+        */
+       bool hdmi_needs_scrambling;
+
+       /**
+        * @hdmi_needs_high_tmds_ratio:
+        *
+        * Only relevant for HDMI sink. Tracks whether the TMDS clock
+        * ratio should be 1/10 of the pixel clock (false), or 1/40
+        * (true).
+        *
+        * Drivers needing this should use
+        * drm_atomic_helper_connector_hdmi_check() and use the value
+        * set here to enable or disable their scrambler.
+        */
+       bool hdmi_needs_high_tmds_ratio;
 };
 
 /**
-- 
2.32.0

Reply via email to