diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.10/950-0575-drm-vc4-hdmi-Enable-the-scrambler.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.10/950-0575-drm-vc4-hdmi-Enable-the-scrambler.patch | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.10/950-0575-drm-vc4-hdmi-Enable-the-scrambler.patch b/target/linux/bcm27xx/patches-5.10/950-0575-drm-vc4-hdmi-Enable-the-scrambler.patch new file mode 100644 index 0000000000..0b00614ab8 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.10/950-0575-drm-vc4-hdmi-Enable-the-scrambler.patch @@ -0,0 +1,142 @@ +From b1388530046be8a912979594f9c43b47d6f242fe Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime@cerno.tech> +Date: Thu, 8 Oct 2020 16:06:58 +0200 +Subject: [PATCH] drm/vc4: hdmi: Enable the scrambler + +The HDMI controller on the BCM2711 includes a scrambler in order to +reach the HDMI 2.0 modes that require it. Let's add the support for it. + +Acked-by: Thomas Zimmermann <tzimmermann@suse.de> +Signed-off-by: Maxime Ripard <maxime@cerno.tech> +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 64 +++++++++++++++++++++++++++++ + drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 3 ++ + 2 files changed, 67 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -35,6 +35,7 @@ + #include <drm/drm_edid.h> + #include <drm/drm_probe_helper.h> + #include <drm/drm_simple_kms_helper.h> ++#include <drm/drm_scdc_helper.h> + #include <linux/clk.h> + #include <linux/component.h> + #include <linux/i2c.h> +@@ -77,6 +78,8 @@ + #define VC5_HDMI_VERTB_VSPO_SHIFT 16 + #define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16) + ++#define VC5_HDMI_SCRAMBLER_CTL_ENABLE BIT(0) ++ + #define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT 8 + #define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK VC4_MASK(10, 8) + +@@ -517,6 +520,64 @@ static void vc4_hdmi_set_infoframes(stru + vc4_hdmi_set_hdr_infoframe(encoder); + } + ++static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder, ++ struct drm_display_mode *mode) ++{ ++ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); ++ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ struct drm_display_info *display = &vc4_hdmi->connector.display_info; ++ ++ if (!vc4_encoder->hdmi_monitor) ++ return false; ++ ++ if (!display->hdmi.scdc.supported || ++ !display->hdmi.scdc.scrambling.supported) ++ return false; ++ ++ return true; ++} ++ ++static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) ++{ ++ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; ++ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ ++ if (!vc4_hdmi_supports_scrambling(encoder, mode)) ++ return; ++ ++ if (!vc4_hdmi_mode_needs_scrambling(mode)) ++ return; ++ ++ drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); ++ drm_scdc_set_scrambling(vc4_hdmi->ddc, true); ++ ++ HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) | ++ VC5_HDMI_SCRAMBLER_CTL_ENABLE); ++} ++ ++static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder) ++{ ++ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ struct drm_crtc *crtc = encoder->crtc; ++ ++ /* ++ * At boot, encoder->crtc will be NULL. Since we don't know the ++ * state of the scrambler and in order to avoid any ++ * inconsistency, let's disable it all the time. ++ */ ++ if (crtc && !vc4_hdmi_supports_scrambling(encoder, &crtc->mode)) ++ return; ++ ++ if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode)) ++ return; ++ ++ HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) & ++ ~VC5_HDMI_SCRAMBLER_CTL_ENABLE); ++ ++ drm_scdc_set_scrambling(vc4_hdmi->ddc, false); ++ drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false); ++} ++ + static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) + { +@@ -529,6 +590,8 @@ static void vc4_hdmi_encoder_post_crtc_d + + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); ++ ++ vc4_hdmi_disable_scrambling(encoder); + } + + static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, +@@ -979,6 +1042,7 @@ static void vc4_hdmi_encoder_post_crtc_e + } + + vc4_hdmi_recenter_fifo(vc4_hdmi); ++ vc4_hdmi_enable_scrambling(encoder); + } + + static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +@@ -100,6 +100,7 @@ enum vc4_hdmi_field { + HDMI_RM_FORMAT, + HDMI_RM_OFFSET, + HDMI_SCHEDULER_CONTROL, ++ HDMI_SCRAMBLER_CTL, + HDMI_SW_RESET_CONTROL, + HDMI_TX_PHY_CHANNEL_SWAP, + HDMI_TX_PHY_CLK_DIV, +@@ -238,6 +239,7 @@ static const struct vc4_hdmi_register vc + VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178), + VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c), + VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8), ++ VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4), + + VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), + VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), +@@ -317,6 +319,7 @@ static const struct vc4_hdmi_register vc + VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178), + VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c), + VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8), ++ VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4), + + VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), + VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), |