@@ -599,6 +599,7 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
599
599
600
600
new_state -> base .max_bpc = 8 ;
601
601
new_state -> base .max_requested_bpc = 8 ;
602
+ new_state -> base .color_format = ilog2 (DRM_COLOR_FORMAT_RGB444 );
602
603
drm_atomic_helper_connector_tv_reset (connector );
603
604
}
604
605
@@ -663,6 +664,14 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
663
664
return ret ;
664
665
665
666
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
+
666
675
drm_connector_attach_tv_margin_properties (connector );
667
676
drm_connector_attach_max_bpc_property (connector , 8 , 12 );
668
677
@@ -778,6 +787,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
778
787
HDMI_QUANTIZATION_RANGE_LIMITED );
779
788
drm_hdmi_avi_infoframe_colorimetry (& frame .avi , cstate );
780
789
drm_hdmi_avi_infoframe_bars (& frame .avi , cstate );
790
+ drm_hdmi_avi_infoframe_colorspace (& frame .avi , cstate );
781
791
782
792
vc4_hdmi_write_infoframe (encoder , & frame );
783
793
}
@@ -1024,6 +1034,38 @@ static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = {
1024
1034
{ 0x0000 , 0x0000 , 0x1b80 , 0x0400 },
1025
1035
};
1026
1036
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
+
1027
1069
static void vc5_hdmi_set_csc_coeffs (struct vc4_hdmi * vc4_hdmi ,
1028
1070
const u16 coeffs [3 ][4 ])
1029
1071
{
@@ -1039,16 +1081,48 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
1039
1081
struct drm_connector_state * state ,
1040
1082
const struct drm_display_mode * mode )
1041
1083
{
1084
+ u32 if_cfg = 0 ;
1085
+ u32 if_xbar = 0x543210 ;
1086
+ u32 csc_chan_ctl = 0 ;
1042
1087
u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD (VC4_HD_CSC_CTL_MODE_CUSTOM ,
1043
1088
VC5_MT_CP_CSC_CTL_MODE );
1044
1089
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 ;
1046
1100
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 ;
1051
1112
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 );
1052
1126
HDMI_WRITE (HDMI_CSC_CTL , csc_ctl );
1053
1127
}
1054
1128
@@ -1435,12 +1509,15 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
1435
1509
pixel_rate = mode -> clock * 1000 ;
1436
1510
}
1437
1511
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
+ }
1444
1521
}
1445
1522
1446
1523
if (mode -> flags & DRM_MODE_FLAG_DBLCLK )
0 commit comments