summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Ripard <maxime@cerno.tech>2020-12-15 16:42:40 +0100
committerMaxime Ripard <maxime@cerno.tech>2020-12-16 10:11:43 +0100
commitf623746f74721be7ac1cf10e0f5e731f30d191b0 (patch)
tree267fda23dfed02718db68cf32b79f0ca4727cbf6
parentdrm/vc4: hdmi: Create a custom connector state (diff)
downloadlinux-f623746f74721be7ac1cf10e0f5e731f30d191b0.tar.xz
linux-f623746f74721be7ac1cf10e0f5e731f30d191b0.zip
drm/vc4: hdmi: Store pixel frequency in the connector state
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
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c26
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.h1
2 files changed, 26 insertions, 1 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d22a0dbd0ce2..a6422d7af019 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -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;
}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 2cf5362052e2..bca6943de884 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -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 *