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-0635-drm-vc4-hdmi-Support-HDMI-YUV-output.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-0635-drm-vc4-hdmi-Support-HDMI-YUV-output.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.15/950-0635-drm-vc4-hdmi-Support-HDMI-YUV-output.patch | 578 |
1 files changed, 578 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0635-drm-vc4-hdmi-Support-HDMI-YUV-output.patch b/target/linux/bcm27xx/patches-5.15/950-0635-drm-vc4-hdmi-Support-HDMI-YUV-output.patch new file mode 100644 index 0000000000..72c79c3eed --- /dev/null +++ b/target/linux/bcm27xx/patches-5.15/950-0635-drm-vc4-hdmi-Support-HDMI-YUV-output.patch @@ -0,0 +1,578 @@ +From ef94081204ede8c11a28b3c3713c54fee6bc6fea Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime@cerno.tech> +Date: Fri, 4 Dec 2020 17:12:06 +0100 +Subject: [PATCH] drm/vc4: hdmi: Support HDMI YUV output + +In addition to the RGB444 output, the BCM2711 HDMI controller supports +the YUV444 and YUV422 output formats. + +Let's add support for them in the driver, but still use RGB as the +preferred format. + +Signed-off-by: Maxime Ripard <maxime@cerno.tech> +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 289 ++++++++++++++++++++++++++-- + drivers/gpu/drm/vc4/vc4_hdmi.h | 14 ++ + drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 6 + + drivers/gpu/drm/vc4/vc4_regs.h | 16 ++ + 4 files changed, 309 insertions(+), 16 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -102,15 +102,30 @@ + + #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) + ++static const char * const output_format_str[] = { ++ [VC4_HDMI_OUTPUT_RGB] = "RGB", ++ [VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0", ++ [VC4_HDMI_OUTPUT_YUV422] = "YUV 4:2:2", ++ [VC4_HDMI_OUTPUT_YUV444] = "YUV 4:4:4", ++}; ++ ++static const char *vc4_hdmi_output_fmt_str(enum vc4_hdmi_output_format fmt) ++{ ++ if (fmt >= ARRAY_SIZE(output_format_str)) ++ return "invalid"; ++ ++ return output_format_str[fmt]; ++} + + static unsigned long long + vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, +- unsigned int bpc); ++ unsigned int bpc, enum vc4_hdmi_output_format fmt); + + static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, +- unsigned int bpc) ++ unsigned int bpc, ++ enum vc4_hdmi_output_format fmt) + { +- unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc); ++ unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); + + return clock > HDMI_14_MAX_TMDS_CLK; + } +@@ -284,7 +299,7 @@ static int vc4_hdmi_connector_get_modes( + struct drm_display_mode *mode; + + list_for_each_entry(mode, &connector->probed_modes, head) { +- if (vc4_hdmi_mode_needs_scrambling(mode, 8)) { ++ if (vc4_hdmi_mode_needs_scrambling(mode, 8, VC4_HDMI_OUTPUT_RGB)) { + drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz."); + drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60."); + } +@@ -341,6 +356,7 @@ static void vc4_hdmi_connector_reset(str + + new_state->base.max_bpc = 8; + new_state->base.max_requested_bpc = 8; ++ new_state->output_format = VC4_HDMI_OUTPUT_RGB; + drm_atomic_helper_connector_tv_reset(connector); + } + +@@ -357,6 +373,7 @@ vc4_hdmi_connector_duplicate_state(struc + + new_state->pixel_rate = vc4_state->pixel_rate; + new_state->output_bpc = vc4_state->output_bpc; ++ new_state->output_format = vc4_state->output_format; + __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); + + return &new_state->base; +@@ -510,11 +527,38 @@ static void vc4_hdmi_write_infoframe(str + DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret); + } + ++static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, ++ enum vc4_hdmi_output_format fmt) ++{ ++ switch (fmt) { ++ case VC4_HDMI_OUTPUT_RGB: ++ frame->colorspace = HDMI_COLORSPACE_RGB; ++ break; ++ ++ case VC4_HDMI_OUTPUT_YUV420: ++ frame->colorspace = HDMI_COLORSPACE_YUV420; ++ break; ++ ++ case VC4_HDMI_OUTPUT_YUV422: ++ frame->colorspace = HDMI_COLORSPACE_YUV422; ++ break; ++ ++ case VC4_HDMI_OUTPUT_YUV444: ++ frame->colorspace = HDMI_COLORSPACE_YUV444; ++ break; ++ ++ default: ++ break; ++ } ++} ++ + static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) + { + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_connector *connector = &vc4_hdmi->connector; + struct drm_connector_state *cstate = connector->state; ++ struct vc4_hdmi_connector_state *vc4_state = ++ conn_state_to_vc4_hdmi_conn_state(cstate); + const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; + union hdmi_infoframe frame; + int ret; +@@ -534,6 +578,7 @@ static void vc4_hdmi_set_avi_infoframe(s + HDMI_QUANTIZATION_RANGE_FULL : + HDMI_QUANTIZATION_RANGE_LIMITED); + drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate); ++ vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format); + drm_hdmi_avi_infoframe_bars(&frame.avi, cstate); + + vc4_hdmi_write_infoframe(encoder, &frame); +@@ -636,7 +681,9 @@ static void vc4_hdmi_enable_scrambling(s + if (!vc4_hdmi_supports_scrambling(encoder, mode)) + return; + +- if (!vc4_hdmi_mode_needs_scrambling(mode, vc4_hdmi->output_bpc)) ++ if (!vc4_hdmi_mode_needs_scrambling(mode, ++ vc4_hdmi->output_bpc, ++ vc4_hdmi->output_format)) + return; + + drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); +@@ -824,6 +871,38 @@ static const u16 vc5_hdmi_csc_full_rgb_t + { 0x0000, 0x0000, 0x1b80, 0x0400 }, + }; + ++/* ++ * Conversion between Full Range RGB and Full Range YUV422 using the ++ * BT.709 Colorspace ++ * ++ * [ 0.212639 0.715169 0.072192 0 ] ++ * [ -0.117208 -0.394207 0.511416 128 ] ++ * [ 0.511416 -0.464524 -0.046891 128 ] ++ * ++ * 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 }, ++}; ++ ++/* ++ * Conversion between Full Range RGB and Full Range YUV444 using the ++ * BT.709 Colorspace ++ * ++ * [ -0.117208 -0.394207 0.511416 128 ] ++ * [ 0.511416 -0.464524 -0.046891 128 ] ++ * [ 0.212639 0.715169 0.072192 0 ] ++ * ++ * 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 void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi, + const u16 coeffs[3][4]) + { +@@ -841,19 +920,53 @@ static void vc5_hdmi_csc_setup(struct vc + 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 long flags; ++ u32 if_cfg = 0; ++ u32 if_xbar = 0x543210; ++ u32 csc_chan_ctl = 0; + u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, + VC5_MT_CP_CSC_CTL_MODE); + + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + +- HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); ++ 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; + +- 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); ++ 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, 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); ++ break; ++ ++ default: ++ break; ++ } ++ ++ HDMI_WRITE(HDMI_VEC_INTERFACE_CFG, if_cfg); ++ HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, if_xbar); ++ HDMI_WRITE(HDMI_CSC_CHANNEL_CTL, csc_chan_ctl); + HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); + + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); +@@ -979,6 +1092,15 @@ static void vc5_hdmi_set_timings(struct + break; + } + ++ /* ++ * YCC422 is always 36-bit and not considered deep colour so ++ * doesn't signal in GCP ++ */ ++ if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { ++ gcp = 4; ++ gcp_en = false; ++ } ++ + reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1); + reg &= ~(VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK | + VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK); +@@ -1258,12 +1380,97 @@ static void vc4_hdmi_encoder_atomic_mode + + mutex_lock(&vc4_hdmi->mutex); + vc4_hdmi->output_bpc = vc4_state->output_bpc; ++ vc4_hdmi->output_format = vc4_state->output_format; + memcpy(&vc4_hdmi->saved_adjusted_mode, + &crtc_state->adjusted_mode, + sizeof(vc4_hdmi->saved_adjusted_mode)); + mutex_unlock(&vc4_hdmi->mutex); + } + ++static bool ++vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode, ++ unsigned int format, unsigned int bpc) ++{ ++ struct drm_device *dev = vc4_hdmi->connector.dev; ++ u8 vic = drm_match_cea_mode(mode); ++ ++ if (vic == 1 && bpc != 8) { ++ drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); ++ return false; ++ } ++ ++ if (!info->is_hdmi && ++ (format != VC4_HDMI_OUTPUT_RGB || bpc != 8)) { ++ drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n"); ++ return false; ++ } ++ ++ switch (format) { ++ case VC4_HDMI_OUTPUT_RGB: ++ drm_dbg(dev, "RGB Format, checking the constraints.\n"); ++ ++ if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) ++ return false; ++ ++ if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { ++ drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); ++ return false; ++ } ++ ++ if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { ++ drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); ++ return false; ++ } ++ ++ drm_dbg(dev, "RGB format supported in that configuration.\n"); ++ ++ return true; ++ ++ case VC4_HDMI_OUTPUT_YUV422: ++ drm_dbg(dev, "YUV422 format, checking the constraints.\n"); ++ ++ if (!(info->color_formats & DRM_COLOR_FORMAT_YCRCB422)) { ++ drm_dbg(dev, "Sink doesn't support YUV422.\n"); ++ return false; ++ } ++ ++ if (bpc != 12) { ++ drm_dbg(dev, "YUV422 only supports 12 bpc.\n"); ++ return false; ++ } ++ ++ drm_dbg(dev, "YUV422 format supported in that configuration.\n"); ++ ++ return true; ++ ++ case VC4_HDMI_OUTPUT_YUV444: ++ drm_dbg(dev, "YUV444 format, checking the constraints.\n"); ++ ++ if (!(info->color_formats & DRM_COLOR_FORMAT_YCRCB444)) { ++ drm_dbg(dev, "Sink doesn't support YUV444.\n"); ++ return false; ++ } ++ ++ if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { ++ drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); ++ return false; ++ } ++ ++ if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { ++ drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); ++ return false; ++ } ++ ++ drm_dbg(dev, "YUV444 format supported in that configuration.\n"); ++ ++ return true; ++ } ++ ++ return false; ++} ++ + static enum drm_mode_status + vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, + unsigned long long clock) +@@ -1285,13 +1492,17 @@ vc4_hdmi_encoder_clock_valid(const struc + + static unsigned long long + vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, +- unsigned int bpc) ++ unsigned int bpc, ++ enum vc4_hdmi_output_format fmt) + { + unsigned long long clock = mode->crtc_clock * 1000; + + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + clock = clock * 2; + ++ if (fmt == VC4_HDMI_OUTPUT_YUV422) ++ bpc = 8; ++ + return clock * bpc / 8; + } + +@@ -1299,11 +1510,11 @@ static int + vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi, + struct vc4_hdmi_connector_state *vc4_state, + const struct drm_display_mode *mode, +- unsigned int bpc) ++ unsigned int bpc, unsigned int fmt) + { + unsigned long long clock; + +- clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc); ++ clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); + if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, clock) != MODE_OK) + return -EINVAL; + +@@ -1313,10 +1524,55 @@ vc4_hdmi_encoder_compute_clock(const str + } + + static int ++vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi, ++ struct vc4_hdmi_connector_state *vc4_state, ++ const struct drm_display_mode *mode, ++ unsigned int bpc) ++{ ++ struct drm_device *dev = vc4_hdmi->connector.dev; ++ const struct drm_connector *connector = &vc4_hdmi->connector; ++ const struct drm_display_info *info = &connector->display_info; ++ unsigned int format; ++ ++ drm_dbg(dev, "Trying with an RGB output\n"); ++ ++ format = VC4_HDMI_OUTPUT_RGB; ++ if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { ++ int ret; ++ ++ ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, ++ mode, bpc, format); ++ if (!ret) { ++ vc4_state->output_format = format; ++ return 0; ++ } ++ } ++ ++ drm_dbg(dev, "Failed, Trying with an YUV422 output\n"); ++ ++ format = VC4_HDMI_OUTPUT_YUV422; ++ if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { ++ int ret; ++ ++ ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, ++ mode, bpc, format); ++ if (!ret) { ++ vc4_state->output_format = format; ++ return 0; ++ } ++ } ++ ++ drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n"); ++ ++ return -EINVAL; ++} ++ ++static int + vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi, + struct vc4_hdmi_connector_state *vc4_state, + const struct drm_display_mode *mode) + { ++ struct drm_device *dev = vc4_hdmi->connector.dev; + struct drm_connector_state *conn_state = &vc4_state->base; + unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12); + unsigned int bpc; +@@ -1325,17 +1581,18 @@ vc4_hdmi_encoder_compute_config(const st + for (bpc = max_bpc; bpc >= 8; bpc -= 2) { + drm_dbg(dev, "Trying with a %d bpc output\n", bpc); + +- ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, +- mode, bpc); ++ ret = vc4_hdmi_encoder_compute_format(vc4_hdmi, vc4_state, ++ mode, bpc); + if (ret) + continue; + + vc4_state->output_bpc = bpc; + + drm_dbg(dev, +- "Mode %ux%u @ %uHz: Found configuration: bpc: %u, clock: %llu\n", ++ "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", + mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), + vc4_state->output_bpc, ++ vc4_hdmi_output_fmt_str(vc4_state->output_format), + vc4_state->pixel_rate); + + break; +--- a/drivers/gpu/drm/vc4/vc4_hdmi.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.h +@@ -121,6 +121,13 @@ struct vc4_hdmi_audio { + bool streaming; + }; + ++enum vc4_hdmi_output_format { ++ VC4_HDMI_OUTPUT_RGB, ++ VC4_HDMI_OUTPUT_YUV422, ++ VC4_HDMI_OUTPUT_YUV444, ++ VC4_HDMI_OUTPUT_YUV420, ++}; ++ + /* General HDMI hardware state. */ + struct vc4_hdmi { + struct vc4_hdmi_audio audio; +@@ -227,6 +234,12 @@ struct vc4_hdmi { + */ + unsigned int output_bpc; + ++ /** ++ * @output_format: Copy of @vc4_connector_state.output_format ++ * for use outside of KMS hooks. Protected by @mutex. ++ */ ++ enum vc4_hdmi_output_format output_format; ++ + /* VC5 debugfs regset */ + struct debugfs_regset32 cec_regset; + struct debugfs_regset32 csc_regset; +@@ -254,6 +267,7 @@ struct vc4_hdmi_connector_state { + struct drm_connector_state base; + unsigned long long pixel_rate; + unsigned int output_bpc; ++ enum vc4_hdmi_output_format output_format; + }; + + static inline struct vc4_hdmi_connector_state * +--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +@@ -54,6 +54,7 @@ enum vc4_hdmi_field { + HDMI_CSC_24_23, + HDMI_CSC_32_31, + HDMI_CSC_34_33, ++ HDMI_CSC_CHANNEL_CTL, + HDMI_CSC_CTL, + + /* +@@ -119,6 +120,7 @@ enum vc4_hdmi_field { + HDMI_TX_PHY_POWERDOWN_CTL, + HDMI_TX_PHY_RESET_CTL, + HDMI_TX_PHY_TMDS_CLK_WORD_SEL, ++ HDMI_VEC_INTERFACE_CFG, + HDMI_VEC_INTERFACE_XBAR, + HDMI_VERTA0, + HDMI_VERTA1, +@@ -246,6 +248,7 @@ static const struct vc4_hdmi_register __ + VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4), + + VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec), + VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), + + VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), +@@ -291,6 +294,7 @@ static const struct vc4_hdmi_register __ + VC5_CSC_REG(HDMI_CSC_24_23, 0x010), + VC5_CSC_REG(HDMI_CSC_32_31, 0x014), + VC5_CSC_REG(HDMI_CSC_34_33, 0x018), ++ VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), + }; + + static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi1_fields[] = { +@@ -327,6 +331,7 @@ static const struct vc4_hdmi_register __ + VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4), + + VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec), + VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), + + VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), +@@ -372,6 +377,7 @@ static const struct vc4_hdmi_register __ + VC5_CSC_REG(HDMI_CSC_24_23, 0x010), + VC5_CSC_REG(HDMI_CSC_32_31, 0x014), + VC5_CSC_REG(HDMI_CSC_34_33, 0x018), ++ VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), + }; + + static inline +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -796,11 +796,27 @@ enum { + # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) + # define VC4_HD_CSC_CTL_ENABLE BIT(0) + ++# define VC5_MT_CP_CSC_CTL_USE_444_TO_422 BIT(6) ++# define VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_MASK \ ++ VC4_MASK(5, 4) ++# define VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD \ ++ 3 ++# define VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION BIT(3) + # define VC5_MT_CP_CSC_CTL_ENABLE BIT(2) + # define VC5_MT_CP_CSC_CTL_MODE_MASK VC4_MASK(1, 0) + ++# define VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_MASK \ ++ VC4_MASK(7, 6) ++# define VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE \ ++ 2 ++ + # define VC4_DVP_HT_CLOCK_STOP_PIXEL BIT(1) + ++# define VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_MASK \ ++ VC4_MASK(3, 2) ++# define VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY \ ++ 2 ++ + /* HVS display list information. */ + #define HVS_BOOTLOADER_DLIST_END 32 + |