diff options
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.c | 37 |
1 files changed, 20 insertions, 17 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index cea18dc15f77..625bfcf52dc4 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -34,6 +34,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_simple_kms_helper.h> #include <linux/clk.h> #include <linux/component.h> #include <linux/i2c.h> @@ -306,15 +307,6 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, return connector; } -static void vc4_hdmi_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); -} - -static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = { - .destroy = vc4_hdmi_encoder_destroy, -}; - static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, enum hdmi_infoframe_type type) { @@ -681,11 +673,23 @@ static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc, const struct drm_display_mode *mode) { - /* HSM clock must be 108% of the pixel clock. Additionally, - * the AXI clock needs to be at least 25% of pixel clock, but - * HSM ends up being the limiting factor. + /* + * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must + * be faster than pixel clock, infinitesimally faster, tested in + * simulation. Otherwise, exact value is unimportant for HDMI + * operation." This conflicts with bcm2835's vc4 documentation, which + * states HSM's clock has to be at least 108% of the pixel clock. + * + * Real life tests reveal that vc4's firmware statement holds up, and + * users are able to use pixel clocks closer to HSM's, namely for + * 1920x1200@60Hz. So it was decided to have leave a 1% margin between + * both clocks. Which, for RPi0-3 implies a maximum pixel clock of + * 162MHz. + * + * Additionally, the AXI clock needs to be at least 25% of + * pixel clock, but HSM ends up being the limiting factor. */ - if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100)) + if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100)) return MODE_CLOCK_HIGH; return MODE_OK; @@ -1394,8 +1398,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) } pm_runtime_enable(dev); - drm_encoder_init(drm, hdmi->encoder, &vc4_hdmi_encoder_funcs, - DRM_MODE_ENCODER_TMDS, NULL); + drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS); drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs); hdmi->connector = @@ -1453,7 +1456,7 @@ err_destroy_conn: vc4_hdmi_connector_destroy(hdmi->connector); #endif err_destroy_encoder: - vc4_hdmi_encoder_destroy(hdmi->encoder); + drm_encoder_cleanup(hdmi->encoder); err_unprepare_hsm: clk_disable_unprepare(hdmi->hsm_clock); pm_runtime_disable(dev); @@ -1472,7 +1475,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, cec_unregister_adapter(hdmi->cec_adap); vc4_hdmi_connector_destroy(hdmi->connector); - vc4_hdmi_encoder_destroy(hdmi->encoder); + drm_encoder_cleanup(hdmi->encoder); clk_disable_unprepare(hdmi->hsm_clock); pm_runtime_disable(dev); |