From af3f381a59c10f6bd49d86a5ff2325b6ebeb79e9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 27 Apr 2020 19:07:50 +0100 Subject: [PATCH] vc4_hdmi: BCM2835 requires a fixed hsm clock for CEC to work Signed-off-by: popcornmix --- drivers/gpu/drm/vc4/vc4_hdmi.c | 32 ++++++++++++++++++++++++++------ drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++ 2 files changed, 29 insertions(+), 6 deletions(-) --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -580,12 +580,7 @@ static void vc4_hdmi_encoder_enable(stru return; } - /* - * The HSM rate needs to be slightly greater than the pixel clock, with - * a minimum of 108MHz. - * Use 101% as this is what the firmware uses. - */ - hsm_rate = max_t(unsigned long, 108000000, (pixel_rate / 100) * 101); + hsm_rate = vc4_hdmi->variant->calc_hsm_clock(vc4_hdmi, pixel_rate); ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); @@ -753,6 +748,28 @@ static u32 vc5_hdmi_get_hsm_clock(struct return 108000000; } +static u32 vc4_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate) +{ + /* + * This is the rate that is set by the firmware. The number + * needs to be a bit higher than the pixel clock rate + * (generally 148.5Mhz). + */ + + return 163682864; +} + +static u32 vc5_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate) +{ + /* + * The HSM rate needs to be slightly greater than the pixel clock, with + * a minimum of 108MHz. + * Use 101% as this is what the firmware uses. + */ + + return max_t(unsigned long, 108000000, (pixel_rate / 100) * 101); +} + static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) { int i; @@ -1749,6 +1766,7 @@ static const struct vc4_hdmi_variant bcm .phy_rng_enable = vc4_hdmi_phy_rng_enable, .phy_rng_disable = vc4_hdmi_phy_rng_disable, .get_hsm_clock = vc4_hdmi_get_hsm_clock, + .calc_hsm_clock = vc4_hdmi_calc_hsm_clock, .channel_map = vc4_hdmi_channel_map, }; @@ -1773,6 +1791,7 @@ static const struct vc4_hdmi_variant bcm .phy_rng_enable = vc5_hdmi_phy_rng_enable, .phy_rng_disable = vc5_hdmi_phy_rng_disable, .get_hsm_clock = vc5_hdmi_get_hsm_clock, + .calc_hsm_clock = vc5_hdmi_calc_hsm_clock, .channel_map = vc5_hdmi_channel_map, }; @@ -1797,6 +1816,7 @@ static const struct vc4_hdmi_variant bcm .phy_rng_enable = vc5_hdmi_phy_rng_enable, .phy_rng_disable = vc5_hdmi_phy_rng_disable, .get_hsm_clock = vc5_hdmi_get_hsm_clock, + .calc_hsm_clock = vc5_hdmi_calc_hsm_clock, .channel_map = vc5_hdmi_channel_map, }; --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -92,6 +92,9 @@ struct vc4_hdmi_variant { /* Callback to get hsm clock */ u32 (*get_hsm_clock)(struct vc4_hdmi *vc4_hdmi); + /* Callback to get hsm clock */ + u32 (*calc_hsm_clock)(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate); + /* Callback to get channel map */ u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask); };