drm/vc4: hdmi: Store pixel frequency in the connector state
authorMaxime Ripard <maxime@cerno.tech>
Tue, 15 Dec 2020 15:42:40 +0000 (16:42 +0100)
committerMaxime Ripard <maxime@cerno.tech>
Wed, 16 Dec 2020 09:11:43 +0000 (10:11 +0100)
The pixel rate is for now quite simple to compute, but with more features
(30 and 36 bits output, YUV output, etc.) will depend on a bunch of
connectors properties.

Let's store the rate we have to run the pixel clock at in our custom
connector state, and compute it in atomic_check.

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20201215154243.540115-7-maxime@cerno.tech
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_hdmi.h

index d22a0db..a6422d7 100644 (file)
@@ -198,6 +198,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
        if (!new_state)
                return NULL;
 
+       new_state->pixel_rate = vc4_state->pixel_rate;
        __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
 
        return &new_state->base;
@@ -618,9 +619,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
                  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 }
 
+static struct drm_connector_state *
+vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder,
+                                    struct drm_atomic_state *state)
+{
+       struct drm_connector_state *conn_state;
+       struct drm_connector *connector;
+       unsigned int i;
+
+       for_each_new_connector_in_state(state, connector, conn_state, i) {
+               if (conn_state->best_encoder == encoder)
+                       return conn_state;
+       }
+
+       return NULL;
+}
+
 static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
                                                struct drm_atomic_state *state)
 {
+       struct drm_connector_state *conn_state =
+               vc4_hdmi_encoder_get_connector_state(encoder, state);
+       struct vc4_hdmi_connector_state *vc4_conn_state =
+               conn_state_to_vc4_hdmi_conn_state(conn_state);
        struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
        unsigned long pixel_rate, hsm_rate;
@@ -632,7 +653,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
                return;
        }
 
-       pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
+       pixel_rate = vc4_conn_state->pixel_rate;
        ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
        if (ret) {
                DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
@@ -804,6 +825,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
                                         struct drm_crtc_state *crtc_state,
                                         struct drm_connector_state *conn_state)
 {
+       struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state);
        struct drm_display_mode *mode = &crtc_state->adjusted_mode;
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
        unsigned long long pixel_rate = mode->clock * 1000;
@@ -834,6 +856,8 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
        if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
                return -EINVAL;
 
+       vc4_state->pixel_rate = pixel_rate;
+
        return 0;
 }
 
index 2cf5362..bca6943 100644 (file)
@@ -182,6 +182,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 
 struct vc4_hdmi_connector_state {
        struct drm_connector_state      base;
+       unsigned long long              pixel_rate;
 };
 
 static inline struct vc4_hdmi_connector_state *