Commit f623746f authored by Maxime Ripard's avatar Maxime Ripard

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: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20201215154243.540115-7-maxime@cerno.tech
parent fbe7271e
...@@ -198,6 +198,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) ...@@ -198,6 +198,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
if (!new_state) if (!new_state)
return NULL; return NULL;
new_state->pixel_rate = vc4_state->pixel_rate;
__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
return &new_state->base; return &new_state->base;
...@@ -618,9 +619,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) ...@@ -618,9 +619,29 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
"VC4_HDMI_FIFO_CTL_RECENTER_DONE"); "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, static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
struct drm_atomic_state *state) 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 drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
unsigned long pixel_rate, hsm_rate; unsigned long pixel_rate, hsm_rate;
...@@ -632,7 +653,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, ...@@ -632,7 +653,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
return; 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); ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
if (ret) { if (ret) {
DRM_ERROR("Failed to set pixel clock rate: %d\n", 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, ...@@ -804,6 +825,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state, struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_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 drm_display_mode *mode = &crtc_state->adjusted_mode;
struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
unsigned long long pixel_rate = mode->clock * 1000; unsigned long long pixel_rate = mode->clock * 1000;
...@@ -834,6 +856,8 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, ...@@ -834,6 +856,8 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
if (pixel_rate > vc4_hdmi->variant->max_pixel_clock) if (pixel_rate > vc4_hdmi->variant->max_pixel_clock)
return -EINVAL; return -EINVAL;
vc4_state->pixel_rate = pixel_rate;
return 0; return 0;
} }
......
...@@ -182,6 +182,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) ...@@ -182,6 +182,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
struct vc4_hdmi_connector_state { struct vc4_hdmi_connector_state {
struct drm_connector_state base; struct drm_connector_state base;
unsigned long long pixel_rate;
}; };
static inline struct vc4_hdmi_connector_state * static inline struct vc4_hdmi_connector_state *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment