1 From cbb71ade28d28e5fcb04171b6be283b150796e7a Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Wed, 13 Jan 2021 11:30:21 +0100
4 Subject: [PATCH] drm/vc4: hdmi: Define colorspace matrices
6 The current CSC setup code for the BCM2711 uses a sequence of register
7 writes to configure the CSC depending on whether we output using a full
10 However, with the upcoming introduction of the YUV output, we're going
11 to add new matrices to perform the conversions, so we should switch to
12 something a bit more flexible that takes the matrix as an argument and
13 programs the CSC accordingly.
15 Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
16 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
18 drivers/gpu/drm/vc4/vc4_hdmi.c | 79 +++++++++++++++++++++-------------
19 1 file changed, 50 insertions(+), 29 deletions(-)
21 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
22 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
23 @@ -782,6 +782,52 @@ static void vc4_hdmi_csc_setup(struct vc
24 spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
29 + * If we need to output Full Range RGB, then use the unity matrix
35 + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
37 +static const u16 vc5_hdmi_csc_full_rgb_unity[3][4] = {
38 + { 0x2000, 0x0000, 0x0000, 0x0000 },
39 + { 0x0000, 0x2000, 0x0000, 0x0000 },
40 + { 0x0000, 0x0000, 0x2000, 0x0000 },
44 + * CEA VICs other than #1 require limited range RGB output unless
45 + * overridden by an AVI infoframe. Apply a colorspace conversion to
46 + * squash 0-255 down to 16-235. The matrix here is:
52 + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
54 +static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = {
55 + { 0x1b80, 0x0000, 0x0000, 0x0400 },
56 + { 0x0000, 0x1b80, 0x0000, 0x0400 },
57 + { 0x0000, 0x0000, 0x1b80, 0x0400 },
60 +static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
61 + const u16 coeffs[3][4])
63 + lockdep_assert_held(&vc4_hdmi->hw_lock);
65 + HDMI_WRITE(HDMI_CSC_12_11, (coeffs[0][1] << 16) | coeffs[0][0]);
66 + HDMI_WRITE(HDMI_CSC_14_13, (coeffs[0][3] << 16) | coeffs[0][2]);
67 + HDMI_WRITE(HDMI_CSC_22_21, (coeffs[1][1] << 16) | coeffs[1][0]);
68 + HDMI_WRITE(HDMI_CSC_24_23, (coeffs[1][3] << 16) | coeffs[1][2]);
69 + HDMI_WRITE(HDMI_CSC_32_31, (coeffs[2][1] << 16) | coeffs[2][0]);
70 + HDMI_WRITE(HDMI_CSC_34_33, (coeffs[2][3] << 16) | coeffs[2][2]);
73 static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
74 const struct drm_display_mode *mode)
76 @@ -793,35 +839,10 @@ static void vc5_hdmi_csc_setup(struct vc
78 HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
80 - if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) {
81 - /* CEA VICs other than #1 requre limited range RGB
82 - * output unless overridden by an AVI infoframe.
83 - * Apply a colorspace conversion to squash 0-255 down
84 - * to 16-235. The matrix here is:
90 - * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
92 - HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
93 - HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
94 - HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
95 - HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
96 - HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
97 - HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
99 - /* Still use the matrix for full range, but make it unity.
100 - * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
102 - HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
103 - HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
104 - HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
105 - HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
106 - HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
107 - HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
109 + if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode))
110 + vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb);
112 + vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity);
114 HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);