Skip to content

Commit c5c7717

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 1f7093b commit c5c7717

File tree

3 files changed

+93
-5
lines changed

3 files changed

+93
-5
lines changed

drivers/gpu/drm/vc4/vc4_hdmi.c

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,10 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
652652
if (ret)
653653
return ret;
654654

655+
ret = drm_mode_create_hdmi_color_formats_property(connector);
656+
if (ret)
657+
return ret;
658+
655659
drm_connector_attach_tv_margin_properties(connector);
656660
drm_connector_attach_max_bpc_property(connector, 8, 12);
657661

@@ -769,6 +773,13 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
769773

770774
drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);
771775

776+
if (cstate->hdmi_color_format == DRM_COLOR_FORMAT_YCRCB422)
777+
frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
778+
else if (cstate->hdmi_color_format == DRM_COLOR_FORMAT_YCRCB444)
779+
frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
780+
else
781+
frame.avi.colorspace = HDMI_COLORSPACE_RGB;
782+
772783
vc4_hdmi_write_infoframe(encoder, &frame);
773784
}
774785

@@ -951,6 +962,38 @@ static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = {
951962
{ 0x0000, 0x0000, 0x1b80, 0x0400 },
952963
};
953964

965+
/*
966+
* Conversion between Full Range RGB and Full Range YUV422 using the
967+
* BT.709 Colorspace
968+
*
969+
* [ 0.212639 0.715169 0.072192 0 ]
970+
* [ -0.117208 -0.394207 0.511416 128 ]
971+
* [ 0.511416 -0.464524 -0.046891 128 ]
972+
*
973+
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
974+
*/
975+
static const u16 vc5_hdmi_csc_full_rgb_to_full_yuv422_bt709[3][4] = {
976+
{ 0x06ce, 0x16e3, 0x024f, 0x0000 },
977+
{ 0xfc41, 0xf364, 0x105e, 0x2000 },
978+
{ 0x105e, 0xf124, 0xfe81, 0x2000 },
979+
};
980+
981+
/*
982+
* Conversion between Full Range RGB and Full Range YUV444 using the
983+
* BT.709 Colorspace
984+
*
985+
* [ -0.117208 -0.394207 0.511416 128 ]
986+
* [ 0.511416 -0.464524 -0.046891 128 ]
987+
* [ 0.212639 0.715169 0.072192 0 ]
988+
*
989+
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
990+
*/
991+
static const u16 vc5_hdmi_csc_full_rgb_to_full_yuv444_bt709[3][4] = {
992+
{ 0xfc41, 0xf364, 0x105e, 0x2000 },
993+
{ 0x105e, 0xf124, 0xfe81, 0x2000 },
994+
{ 0x06ce, 0x16e3, 0x024f, 0x0000 },
995+
};
996+
954997
static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
955998
const u16 coeffs[3][4])
956999
{
@@ -966,16 +1009,39 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
9661009
struct drm_connector_state *state,
9671010
const struct drm_display_mode *mode)
9681011
{
1012+
u32 if_cfg = 0;
1013+
u32 if_xbar = 0x543210;
1014+
u32 csc_chan_ctl = 0;
9691015
u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
9701016
VC5_MT_CP_CSC_CTL_MODE);
9711017

972-
HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
1018+
if (state->hdmi_color_format == DRM_COLOR_FORMAT_YCRCB422) {
1019+
csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD,
1020+
VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) |
1021+
VC5_MT_CP_CSC_CTL_USE_444_TO_422 |
1022+
VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION;
9731023

974-
if (vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode))
975-
vc5_hdmi_set_csc_coeffs(vc4_hdmi, &vc5_hdmi_csc_full_rgb_unity);
976-
else
977-
vc5_hdmi_set_csc_coeffs(vc4_hdmi, &vc5_hdmi_csc_full_rgb_to_limited_rgb);
1024+
csc_chan_ctl |= VC4_SET_FIELD(VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE,
1025+
VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP);
1026+
1027+
if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY,
1028+
VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422);
1029+
1030+
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_full_yuv422_bt709);
1031+
} else if (state->hdmi_color_format == DRM_COLOR_FORMAT_YCRCB444) {
1032+
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_full_yuv444_bt709);
1033+
} else if (state->hdmi_color_format == DRM_COLOR_FORMAT_RGB444) {
1034+
if_xbar = 0x354021;
1035+
1036+
if (vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode))
1037+
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity);
1038+
else
1039+
vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb);
1040+
}
9781041

1042+
HDMI_WRITE(HDMI_VEC_INTERFACE_CFG, if_cfg);
1043+
HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, if_xbar);
1044+
HDMI_WRITE(HDMI_CSC_CHANNEL_CTL, csc_chan_ctl);
9791045
HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
9801046
}
9811047

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
/*
@@ -116,6 +117,7 @@ enum vc4_hdmi_field {
116117
HDMI_TX_PHY_POWERDOWN_CTL,
117118
HDMI_TX_PHY_RESET_CTL,
118119
HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
120+
HDMI_VEC_INTERFACE_CFG,
119121
HDMI_VEC_INTERFACE_XBAR,
120122
HDMI_VERTA0,
121123
HDMI_VERTA1,
@@ -240,6 +242,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
240242
VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
241243

242244
VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
245+
VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec),
243246
VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
244247

245248
VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
@@ -285,6 +288,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
285288
VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
286289
VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
287290
VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
291+
VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c),
288292
};
289293

290294
static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
@@ -319,6 +323,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
319323
VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
320324

321325
VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
326+
VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec),
322327
VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
323328

324329
VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
@@ -364,6 +369,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
364369
VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
365370
VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
366371
VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
372+
VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c),
367373
};
368374

369375
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)