Skip to content

Commit 2b093bd

Browse files
committed
drm/vc4: hdmi: Support HDMI YUV output
The HDMI controllers in the BCM2711 support YUV444 and YUV420 outputs, let's add support for it. Signed-off-by: Maxime Ripard <[email protected]>
1 parent 28db031 commit 2b093bd

File tree

3 files changed

+110
-11
lines changed

3 files changed

+110
-11
lines changed

drivers/gpu/drm/vc4/vc4_hdmi.c

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
599599

600600
new_state->base.max_bpc = 8;
601601
new_state->base.max_requested_bpc = 8;
602+
new_state->base.color_format = ilog2(DRM_COLOR_FORMAT_RGB444);
602603
drm_atomic_helper_connector_tv_reset(connector);
603604
}
604605

@@ -663,6 +664,14 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
663664
return ret;
664665

665666
drm_connector_attach_colorspace_property(connector);
667+
668+
ret = drm_connector_create_hdmi_color_formats_properties(connector,
669+
DRM_COLOR_FORMAT_RGB444 |
670+
DRM_COLOR_FORMAT_YCRCB444 |
671+
DRM_COLOR_FORMAT_YCRCB422);
672+
if (ret)
673+
return ret;
674+
666675
drm_connector_attach_tv_margin_properties(connector);
667676
drm_connector_attach_max_bpc_property(connector, 8, 12);
668677

@@ -778,6 +787,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
778787
HDMI_QUANTIZATION_RANGE_LIMITED);
779788
drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate);
780789
drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);
790+
drm_hdmi_avi_infoframe_colorspace(&frame.avi, cstate);
781791

782792
vc4_hdmi_write_infoframe(encoder, &frame);
783793
}
@@ -1024,6 +1034,38 @@ static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = {
10241034
{ 0x0000, 0x0000, 0x1b80, 0x0400 },
10251035
};
10261036

1037+
/*
1038+
* Conversion between Full Range RGB and Full Range YUV422 using the
1039+
* BT.709 Colorspace
1040+
*
1041+
* [ 0.212639 0.715169 0.072192 0 ]
1042+
* [ -0.117208 -0.394207 0.511416 128 ]
1043+
* [ 0.511416 -0.464524 -0.046891 128 ]
1044+
*
1045+
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
1046+
*/
1047+
static const u16 vc5_hdmi_csc_full_rgb_to_full_yuv422_bt709[3][4] = {
1048+
{ 0x06ce, 0x16e3, 0x024f, 0x0000 },
1049+
{ 0xfc41, 0xf364, 0x105e, 0x2000 },
1050+
{ 0x105e, 0xf124, 0xfe81, 0x2000 },
1051+
};
1052+
1053+
/*
1054+
* Conversion between Full Range RGB and Full Range YUV444 using the
1055+
* BT.709 Colorspace
1056+
*
1057+
* [ -0.117208 -0.394207 0.511416 128 ]
1058+
* [ 0.511416 -0.464524 -0.046891 128 ]
1059+
* [ 0.212639 0.715169 0.072192 0 ]
1060+
*
1061+
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
1062+
*/
1063+
static const u16 vc5_hdmi_csc_full_rgb_to_full_yuv444_bt709[3][4] = {
1064+
{ 0xfc41, 0xf364, 0x105e, 0x2000 },
1065+
{ 0x105e, 0xf124, 0xfe81, 0x2000 },
1066+
{ 0x06ce, 0x16e3, 0x024f, 0x0000 },
1067+
};
1068+
10271069
static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
10281070
const u16 coeffs[3][4])
10291071
{
@@ -1039,16 +1081,48 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
10391081
struct drm_connector_state *state,
10401082
const struct drm_display_mode *mode)
10411083
{
1084+
u32 if_cfg = 0;
1085+
u32 if_xbar = 0x543210;
1086+
u32 csc_chan_ctl = 0;
10421087
u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
10431088
VC5_MT_CP_CSC_CTL_MODE);
10441089

1045-
HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
1090+
switch (BIT(state->color_format)) {
1091+
case DRM_COLOR_FORMAT_YCRCB444:
1092+
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_full_yuv444_bt709);
1093+
break;
1094+
1095+
case DRM_COLOR_FORMAT_YCRCB422:
1096+
csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD,
1097+
VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) |
1098+
VC5_MT_CP_CSC_CTL_USE_444_TO_422 |
1099+
VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION;
10461100

1047-
if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode))
1048-
vc5_hdmi_set_csc_coeffs(vc4_hdmi, &vc5_hdmi_csc_full_rgb_to_limited_rgb);
1049-
else
1050-
vc5_hdmi_set_csc_coeffs(vc4_hdmi, &vc5_hdmi_csc_full_rgb_unity);
1101+
csc_chan_ctl |= VC4_SET_FIELD(VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE,
1102+
VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP);
1103+
1104+
if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY,
1105+
VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422);
1106+
1107+
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_full_yuv422_bt709);
1108+
break;
1109+
1110+
case DRM_COLOR_FORMAT_RGB444:
1111+
if_xbar = 0x354021;
10511112

1113+
if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode))
1114+
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb);
1115+
else
1116+
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity);
1117+
break;
1118+
1119+
default:
1120+
break;
1121+
}
1122+
1123+
HDMI_WRITE(HDMI_VEC_INTERFACE_CFG, if_cfg);
1124+
HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, if_xbar);
1125+
HDMI_WRITE(HDMI_CSC_CHANNEL_CTL, csc_chan_ctl);
10521126
HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
10531127
}
10541128

@@ -1435,12 +1509,15 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
14351509
pixel_rate = mode->clock * 1000;
14361510
}
14371511

1438-
if (conn_state->max_bpc == 12) {
1439-
pixel_rate = pixel_rate * 150;
1440-
do_div(pixel_rate, 100);
1441-
} else if (conn_state->max_bpc == 10) {
1442-
pixel_rate = pixel_rate * 125;
1443-
do_div(pixel_rate, 100);
1512+
if (BIT(conn_state->color_format) == DRM_COLOR_FORMAT_RGB444 ||
1513+
BIT(conn_state->color_format) == DRM_COLOR_FORMAT_YCRCB444) {
1514+
if (conn_state->max_bpc == 12) {
1515+
pixel_rate = pixel_rate * 150;
1516+
do_div(pixel_rate, 100);
1517+
} else if (conn_state->max_bpc == 10) {
1518+
pixel_rate = pixel_rate * 125;
1519+
do_div(pixel_rate, 100);
1520+
}
14441521
}
14451522

14461523
if (mode->flags & DRM_MODE_FLAG_DBLCLK)

drivers/gpu/drm/vc4/vc4_hdmi_regs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ enum vc4_hdmi_field {
5252
HDMI_CSC_24_23,
5353
HDMI_CSC_32_31,
5454
HDMI_CSC_34_33,
55+
HDMI_CSC_CHANNEL_CTL,
5556
HDMI_CSC_CTL,
5657

5758
/*
@@ -117,6 +118,7 @@ enum vc4_hdmi_field {
117118
HDMI_TX_PHY_POWERDOWN_CTL,
118119
HDMI_TX_PHY_RESET_CTL,
119120
HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
121+
HDMI_VEC_INTERFACE_CFG,
120122
HDMI_VEC_INTERFACE_XBAR,
121123
HDMI_VERTA0,
122124
HDMI_VERTA1,
@@ -242,6 +244,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
242244
VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4),
243245

244246
VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
247+
VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec),
245248
VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
246249

247250
VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
@@ -287,6 +290,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
287290
VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
288291
VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
289292
VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
293+
VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c),
290294
};
291295

292296
static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
@@ -322,6 +326,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
322326
VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4),
323327

324328
VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
329+
VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec),
325330
VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
326331

327332
VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
@@ -367,6 +372,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
367372
VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
368373
VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
369374
VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
375+
VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c),
370376
};
371377

372378
static inline

drivers/gpu/drm/vc4/vc4_regs.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,11 +774,27 @@ enum {
774774
# define VC4_HD_CSC_CTL_RGB2YCC BIT(1)
775775
# define VC4_HD_CSC_CTL_ENABLE BIT(0)
776776

777+
# define VC5_MT_CP_CSC_CTL_USE_444_TO_422 BIT(6)
778+
# define VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_MASK \
779+
VC4_MASK(5, 4)
780+
# define VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD \
781+
3
782+
# define VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION BIT(3)
777783
# define VC5_MT_CP_CSC_CTL_ENABLE BIT(2)
778784
# define VC5_MT_CP_CSC_CTL_MODE_MASK VC4_MASK(1, 0)
779785

786+
# define VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_MASK \
787+
VC4_MASK(7, 6)
788+
# define VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE \
789+
2
790+
780791
# define VC4_DVP_HT_CLOCK_STOP_PIXEL BIT(1)
781792

793+
# define VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_MASK \
794+
VC4_MASK(3, 2)
795+
# define VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY \
796+
2
797+
782798
/* HVS display list information. */
783799
#define HVS_BOOTLOADER_DLIST_END 32
784800

0 commit comments

Comments
 (0)