diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0628-drm-vc4-hdmi-Define-colorspace-matrices.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.15/950-0628-drm-vc4-hdmi-Define-colorspace-matrices.patch | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0628-drm-vc4-hdmi-Define-colorspace-matrices.patch b/target/linux/bcm27xx/patches-5.15/950-0628-drm-vc4-hdmi-Define-colorspace-matrices.patch new file mode 100644 index 0000000000..ae2faca5f1 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.15/950-0628-drm-vc4-hdmi-Define-colorspace-matrices.patch @@ -0,0 +1,115 @@ +From cbb71ade28d28e5fcb04171b6be283b150796e7a Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime@cerno.tech> +Date: Wed, 13 Jan 2021 11:30:21 +0100 +Subject: [PATCH] drm/vc4: hdmi: Define colorspace matrices + +The current CSC setup code for the BCM2711 uses a sequence of register +writes to configure the CSC depending on whether we output using a full +or limited range. + +However, with the upcoming introduction of the YUV output, we're going +to add new matrices to perform the conversions, so we should switch to +something a bit more flexible that takes the matrix as an argument and +programs the CSC accordingly. + +Acked-by: Thomas Zimmermann <tzimmermann@suse.de> +Signed-off-by: Maxime Ripard <maxime@cerno.tech> +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 79 +++++++++++++++++++++------------- + 1 file changed, 50 insertions(+), 29 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -781,6 +781,52 @@ static void vc4_hdmi_csc_setup(struct vc + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } + ++ ++/* ++ * If we need to output Full Range RGB, then use the unity matrix ++ * ++ * [ 1 0 0 0] ++ * [ 0 1 0 0] ++ * [ 0 0 1 0] ++ * ++ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets ++ */ ++static const u16 vc5_hdmi_csc_full_rgb_unity[3][4] = { ++ { 0x2000, 0x0000, 0x0000, 0x0000 }, ++ { 0x0000, 0x2000, 0x0000, 0x0000 }, ++ { 0x0000, 0x0000, 0x2000, 0x0000 }, ++}; ++ ++/* ++ * CEA VICs other than #1 require limited range RGB output unless ++ * overridden by an AVI infoframe. Apply a colorspace conversion to ++ * squash 0-255 down to 16-235. The matrix here is: ++ * ++ * [ 0.8594 0 0 16] ++ * [ 0 0.8594 0 16] ++ * [ 0 0 0.8594 16] ++ * ++ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets ++ */ ++static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = { ++ { 0x1b80, 0x0000, 0x0000, 0x0400 }, ++ { 0x0000, 0x1b80, 0x0000, 0x0400 }, ++ { 0x0000, 0x0000, 0x1b80, 0x0400 }, ++}; ++ ++static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi, ++ const u16 coeffs[3][4]) ++{ ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ ++ HDMI_WRITE(HDMI_CSC_12_11, (coeffs[0][1] << 16) | coeffs[0][0]); ++ HDMI_WRITE(HDMI_CSC_14_13, (coeffs[0][3] << 16) | coeffs[0][2]); ++ HDMI_WRITE(HDMI_CSC_22_21, (coeffs[1][1] << 16) | coeffs[1][0]); ++ HDMI_WRITE(HDMI_CSC_24_23, (coeffs[1][3] << 16) | coeffs[1][2]); ++ HDMI_WRITE(HDMI_CSC_32_31, (coeffs[2][1] << 16) | coeffs[2][0]); ++ HDMI_WRITE(HDMI_CSC_34_33, (coeffs[2][3] << 16) | coeffs[2][2]); ++} ++ + static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, + const struct drm_display_mode *mode) + { +@@ -792,35 +838,10 @@ static void vc5_hdmi_csc_setup(struct vc + + HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); + +- if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) { +- /* CEA VICs other than #1 requre limited range RGB +- * output unless overridden by an AVI infoframe. +- * Apply a colorspace conversion to squash 0-255 down +- * to 16-235. The matrix here is: +- * +- * [ 0.8594 0 0 16] +- * [ 0 0.8594 0 16] +- * [ 0 0 0.8594 16] +- * [ 0 0 0 1] +- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets +- */ +- HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80); +- HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80); +- } else { +- /* Still use the matrix for full range, but make it unity. +- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets +- */ +- HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000); +- HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); +- HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000); +- } ++ if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) ++ vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb); ++ else ++ vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity); + + HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); + |