diff options
author | Álvaro Fernández Rojas <noltari@gmail.com> | 2022-05-16 23:40:32 +0200 |
---|---|---|
committer | Álvaro Fernández Rojas <noltari@gmail.com> | 2022-05-17 15:11:22 +0200 |
commit | 20ea6adbf199097c4f5f591ffee088340630dae4 (patch) | |
tree | d6719d95e136611a1c25bbf7789652d6d402779d /target/linux/bcm27xx/patches-5.15/950-0786-drm-vc4-hdmi-Add-CSC-for-BT601-709-2020-limited-and-.patch | |
parent | bca05bd072180dc38ef740b37ded9572a6db1981 (diff) | |
download | upstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.gz upstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.bz2 upstream-20ea6adbf199097c4f5f591ffee088340630dae4.zip |
bcm27xx: add support for linux v5.15
Build system: x86_64
Build-tested: bcm2708, bcm2709, bcm2710, bcm2711
Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B
Signed-off-by: Marty Jones <mj8263788@gmail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0786-drm-vc4-hdmi-Add-CSC-for-BT601-709-2020-limited-and-.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.15/950-0786-drm-vc4-hdmi-Add-CSC-for-BT601-709-2020-limited-and-.patch | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0786-drm-vc4-hdmi-Add-CSC-for-BT601-709-2020-limited-and-.patch b/target/linux/bcm27xx/patches-5.15/950-0786-drm-vc4-hdmi-Add-CSC-for-BT601-709-2020-limited-and-.patch new file mode 100644 index 0000000000..dbfc1520c1 --- /dev/null +++ b/target/linux/bcm27xx/patches-5.15/950-0786-drm-vc4-hdmi-Add-CSC-for-BT601-709-2020-limited-and-.patch @@ -0,0 +1,308 @@ +From a2e09555e32742320fdaa511e1ccf6aafbf29485 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson <dave.stevenson@raspberrypi.com> +Date: Mon, 7 Mar 2022 15:19:38 +0000 +Subject: [PATCH] drm/vc4: hdmi: Add CSC for BT601/709/2020 limited and + full range output + +The HVS always composes in the RGB domain, but there is a colourspace +conversion block on the output to allow for sending YCbCr over the +HDMI interface. +The colourspace on that link is configurable via the "Colorspace" +property on the connector, and that updates the infoframes. There +is also selection of limited or full range based on the mode selected +or an override. + +Add code to update the CSC as well so that the metadata matches the +image data. + +Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 198 ++++++++++++++++++++++++--------- + 1 file changed, 146 insertions(+), 52 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -138,8 +138,8 @@ static bool vc4_hdmi_mode_needs_scrambli + return clock > HDMI_14_MAX_TMDS_CLK; + } + +-static bool vc4_hdmi_is_full_range_rgb(struct vc4_hdmi *vc4_hdmi, +- const struct drm_display_mode *mode) ++static bool vc4_hdmi_is_full_range(struct vc4_hdmi *vc4_hdmi, ++ const struct drm_display_mode *mode) + { + struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder; + +@@ -679,7 +679,7 @@ static void vc4_hdmi_set_avi_infoframe(s + + drm_hdmi_avi_infoframe_quant_range(&frame.avi, + connector, mode, +- vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode) ? ++ vc4_hdmi_is_full_range(vc4_hdmi, mode) ? + HDMI_QUANTIZATION_RANGE_FULL : + HDMI_QUANTIZATION_RANGE_LIMITED); + drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate); +@@ -913,7 +913,7 @@ static void vc4_hdmi_csc_setup(struct vc + csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, + VC4_HD_CSC_CTL_ORDER); + +- if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) { ++ if (!vc4_hdmi_is_full_range(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 +@@ -943,7 +943,6 @@ 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 + * +@@ -951,15 +950,6 @@ static void vc4_hdmi_csc_setup(struct vc + * [ 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: +@@ -970,42 +960,105 @@ static const u16 vc5_hdmi_csc_full_rgb_u + * + * 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 const u16 vc5_hdmi_csc_full_rgb_to_rgb[2][3][4] = { ++ { ++ /* Full range - unity */ ++ { 0x2000, 0x0000, 0x0000, 0x0000 }, ++ { 0x0000, 0x2000, 0x0000, 0x0000 }, ++ { 0x0000, 0x0000, 0x2000, 0x0000 }, ++ }, { ++ /* Limited range */ ++ { 0x1b80, 0x0000, 0x0000, 0x0400 }, ++ { 0x0000, 0x1b80, 0x0000, 0x0400 }, ++ { 0x0000, 0x0000, 0x1b80, 0x0400 }, ++ } ++}; ++ ++/* ++ * Conversion between Full Range RGB and YUV using the BT.601 Colorspace ++ * ++ * Full range ++ * [ 0.299000 0.587000 0.114000 0.000000 ] ++ * [ -0.168736 -0.331264 0.500000 128.000000 ] ++ * [ 0.500000 -0.418688 -0.081312 128.000000 ] ++ * ++ * Limited range ++ * [ 0.255785 0.502160 0.097523 16.000000 ] ++ * [ -0.147644 -0.289856 0.437500 128.000000 ] ++ * [ 0.437500 -0.366352 -0.071148 128.000000 ] ++ * ++ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets ++ */ ++static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt601[2][3][4] = { ++ { ++ /* Full range */ ++ { 0x0991, 0x12c9, 0x03a6, 0x0000 }, ++ { 0xfa9b, 0xf567, 0x1000, 0x2000 }, ++ { 0x1000, 0xf29b, 0xfd67, 0x2000 }, ++ }, { ++ /* Limited range */ ++ { 0x082f, 0x1012, 0x031f, 0x0400 }, ++ { 0xfb48, 0xf6ba, 0x0e00, 0x2000 }, ++ { 0x0e00, 0xf448, 0xfdba, 0x2000 }, ++ } + }; + + /* +- * Conversion between Full Range RGB and Full Range YUV422 using the +- * BT.709 Colorspace ++ * Conversion between Full Range RGB and YUV using the BT.709 Colorspace ++ * ++ * Full range ++ * [ 0.212600 0.715200 0.072200 0.000000 ] ++ * [ -0.114572 -0.385428 0.500000 128.000000 ] ++ * [ 0.500000 -0.454153 -0.045847 128.000000 ] + * +- * [ 0.212639 0.715169 0.072192 0 ] +- * [ -0.117208 -0.394207 0.511416 128 ] +- * [ 0.511416 -0.464524 -0.046891 128 ] ++ * Limited range ++ * [ 0.181873 0.611831 0.061765 16.000000 ] ++ * [ -0.100251 -0.337249 0.437500 128.000000 ] ++ * [ 0.437500 -0.397384 -0.040116 128.000000 ] + * + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets + */ +-static const u16 vc5_hdmi_csc_full_rgb_to_full_yuv422_bt709[3][4] = { +- { 0x06ce, 0x16e3, 0x024f, 0x0000 }, +- { 0xfc41, 0xf364, 0x105e, 0x2000 }, +- { 0x105e, 0xf124, 0xfe81, 0x2000 }, ++static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt709[2][3][4] = { ++ { ++ /* Full range */ ++ { 0x06ce, 0x16e3, 0x024f, 0x0000 }, ++ { 0xfc56, 0xf3ac, 0x1000, 0x2000 }, ++ { 0x1000, 0xf179, 0xfe89, 0x2000 }, ++ }, { ++ /* Limited range */ ++ { 0x05d2, 0x1394, 0x01fa, 0x0400 }, ++ { 0xfccc, 0xf536, 0x0e00, 0x2000 }, ++ { 0x0e00, 0xf34a, 0xfeb8, 0x2000 }, ++ } + }; + + /* +- * Conversion between Full Range RGB and Full Range YUV444 using the +- * BT.709 Colorspace ++ * Conversion between Full Range RGB and YUV using the BT.2020 Colorspace ++ * ++ * Full range ++ * [ 0.262700 0.678000 0.059300 0.000000 ] ++ * [ -0.139630 -0.360370 0.500000 128.000000 ] ++ * [ 0.500000 -0.459786 -0.040214 128.000000 ] + * +- * [ -0.117208 -0.394207 0.511416 128 ] +- * [ 0.511416 -0.464524 -0.046891 128 ] +- * [ 0.212639 0.715169 0.072192 0 ] ++ * Limited range ++ * [ 0.224732 0.580008 0.050729 16.000000 ] ++ * [ -0.122176 -0.315324 0.437500 128.000000 ] ++ * [ 0.437500 -0.402312 -0.035188 128.000000 ] + * + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets + */ +-static const u16 vc5_hdmi_csc_full_rgb_to_full_yuv444_bt709[3][4] = { +- { 0xfc41, 0xf364, 0x105e, 0x2000 }, +- { 0x105e, 0xf124, 0xfe81, 0x2000 }, +- { 0x06ce, 0x16e3, 0x024f, 0x0000 }, ++static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt2020[2][3][4] = { ++ { ++ /* Full range */ ++ { 0x0868, 0x15b2, 0x01e6, 0x0000 }, ++ { 0xfb89, 0xf479, 0x1000, 0x2000 }, ++ { 0x1000, 0xf14a, 0xfeb8, 0x2000 }, ++ }, { ++ /* Limited range */ ++ { 0x0731, 0x128f, 0x01a0, 0x0400 }, ++ { 0xfc18, 0xf5ea, 0x0e00, 0x2000 }, ++ { 0x0e00, 0xf321, 0xfee1, 0x2000 }, ++ } + }; + + static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi, +@@ -1021,12 +1074,28 @@ static void vc5_hdmi_set_csc_coeffs(stru + HDMI_WRITE(HDMI_CSC_34_33, (coeffs[2][3] << 16) | coeffs[2][2]); + } + ++static void vc5_hdmi_set_csc_coeffs_swap(struct vc4_hdmi *vc4_hdmi, ++ const u16 coeffs[3][4]) ++{ ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ ++ /* YUV444 needs the CSC matrices using the channels in a different order */ ++ HDMI_WRITE(HDMI_CSC_12_11, (coeffs[2][1] << 16) | coeffs[2][0]); ++ HDMI_WRITE(HDMI_CSC_14_13, (coeffs[2][3] << 16) | coeffs[2][2]); ++ HDMI_WRITE(HDMI_CSC_22_21, (coeffs[0][1] << 16) | coeffs[0][0]); ++ HDMI_WRITE(HDMI_CSC_24_23, (coeffs[0][3] << 16) | coeffs[0][2]); ++ HDMI_WRITE(HDMI_CSC_32_31, (coeffs[1][1] << 16) | coeffs[1][0]); ++ HDMI_WRITE(HDMI_CSC_34_33, (coeffs[1][3] << 16) | coeffs[1][2]); ++} ++ + static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, + struct drm_connector_state *state, + const struct drm_display_mode *mode) + { + struct vc4_hdmi_connector_state *vc4_state = + conn_state_to_vc4_hdmi_conn_state(state); ++ unsigned int lim_range = vc4_hdmi_is_full_range(vc4_hdmi, mode) ? 0 : 1; ++ const u16 (*csc)[4]; + unsigned long flags; + u32 if_cfg = 0; + u32 if_xbar = 0x543210; +@@ -1038,31 +1107,56 @@ static void vc5_hdmi_csc_setup(struct vc + + switch (vc4_state->output_format) { + case VC4_HDMI_OUTPUT_YUV444: +- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_full_yuv444_bt709); +- break; +- + case VC4_HDMI_OUTPUT_YUV422: +- csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD, +- VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) | +- VC5_MT_CP_CSC_CTL_USE_444_TO_422 | +- VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION; +- +- csc_chan_ctl |= VC4_SET_FIELD(VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE, +- VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP); ++ switch (state->colorspace) { ++ default: ++ case DRM_MODE_COLORIMETRY_NO_DATA: ++ case DRM_MODE_COLORIMETRY_BT709_YCC: ++ case DRM_MODE_COLORIMETRY_XVYCC_709: ++ case DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED: ++ case DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT: ++ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt709[lim_range]; ++ break; ++ case DRM_MODE_COLORIMETRY_SMPTE_170M_YCC: ++ case DRM_MODE_COLORIMETRY_XVYCC_601: ++ case DRM_MODE_COLORIMETRY_SYCC_601: ++ case DRM_MODE_COLORIMETRY_OPYCC_601: ++ case DRM_MODE_COLORIMETRY_BT601_YCC: ++ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt601[lim_range]; ++ break; ++ case DRM_MODE_COLORIMETRY_BT2020_CYCC: ++ case DRM_MODE_COLORIMETRY_BT2020_YCC: ++ case DRM_MODE_COLORIMETRY_BT2020_RGB: ++ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65: ++ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER: ++ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt2020[lim_range]; ++ break; ++ } + +- if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY, +- VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422); ++ if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { ++ csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD, ++ VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) | ++ VC5_MT_CP_CSC_CTL_USE_444_TO_422 | ++ VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION; ++ ++ csc_chan_ctl |= VC4_SET_FIELD(VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE, ++ VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP); ++ ++ if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY, ++ VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422); ++ ++ vc5_hdmi_set_csc_coeffs(vc4_hdmi, csc); ++ } else { ++ vc5_hdmi_set_csc_coeffs_swap(vc4_hdmi, csc); ++ } + +- vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_full_yuv422_bt709); + break; + + case VC4_HDMI_OUTPUT_RGB: + if_xbar = 0x354021; + +- 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); ++ vc5_hdmi_set_csc_coeffs(vc4_hdmi, ++ vc5_hdmi_csc_full_rgb_to_rgb[lim_range]); + break; + + default: |