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
This commit is contained in:
Maxime Ripard 2020-12-15 16:42:40 +01:00
parent fbe7271e47
commit f623746f74
No known key found for this signature in database
GPG Key ID: E3EF0D6F671851C5
2 changed files with 26 additions and 1 deletions

View File

@ -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)
"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,
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,
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,
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;
} }

View File

@ -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 *