@@ -138,8 +138,8 @@ static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode,
138
138
return clock > HDMI_14_MAX_TMDS_CLK ;
139
139
}
140
140
141
- static bool vc4_hdmi_is_full_range_rgb (struct vc4_hdmi * vc4_hdmi ,
142
- const struct drm_display_mode * mode )
141
+ static bool vc4_hdmi_is_full_range (struct vc4_hdmi * vc4_hdmi ,
142
+ const struct drm_display_mode * mode )
143
143
{
144
144
struct vc4_hdmi_encoder * vc4_encoder = & vc4_hdmi -> encoder ;
145
145
@@ -679,7 +679,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
679
679
680
680
drm_hdmi_avi_infoframe_quant_range (& frame .avi ,
681
681
connector , mode ,
682
- vc4_hdmi_is_full_range_rgb (vc4_hdmi , mode ) ?
682
+ vc4_hdmi_is_full_range (vc4_hdmi , mode ) ?
683
683
HDMI_QUANTIZATION_RANGE_FULL :
684
684
HDMI_QUANTIZATION_RANGE_LIMITED );
685
685
drm_hdmi_avi_infoframe_colorimetry (& frame .avi , cstate );
@@ -913,7 +913,7 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
913
913
csc_ctl = VC4_SET_FIELD (VC4_HD_CSC_CTL_ORDER_BGR ,
914
914
VC4_HD_CSC_CTL_ORDER );
915
915
916
- if (!vc4_hdmi_is_full_range_rgb (vc4_hdmi , mode )) {
916
+ if (!vc4_hdmi_is_full_range (vc4_hdmi , mode )) {
917
917
/* CEA VICs other than #1 requre limited range RGB
918
918
* output unless overridden by an AVI infoframe.
919
919
* Apply a colorspace conversion to squash 0-255 down
@@ -943,23 +943,13 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
943
943
spin_unlock_irqrestore (& vc4_hdmi -> hw_lock , flags );
944
944
}
945
945
946
-
947
946
/*
948
947
* If we need to output Full Range RGB, then use the unity matrix
949
948
*
950
949
* [ 1 0 0 0]
951
950
* [ 0 1 0 0]
952
951
* [ 0 0 1 0]
953
952
*
954
- * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
955
- */
956
- static const u16 vc5_hdmi_csc_full_rgb_unity [3 ][4 ] = {
957
- { 0x2000 , 0x0000 , 0x0000 , 0x0000 },
958
- { 0x0000 , 0x2000 , 0x0000 , 0x0000 },
959
- { 0x0000 , 0x0000 , 0x2000 , 0x0000 },
960
- };
961
-
962
- /*
963
953
* CEA VICs other than #1 require limited range RGB output unless
964
954
* overridden by an AVI infoframe. Apply a colorspace conversion to
965
955
* squash 0-255 down to 16-235. The matrix here is:
@@ -970,42 +960,105 @@ static const u16 vc5_hdmi_csc_full_rgb_unity[3][4] = {
970
960
*
971
961
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
972
962
*/
973
- static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb [3 ][4 ] = {
974
- { 0x1b80 , 0x0000 , 0x0000 , 0x0400 },
975
- { 0x0000 , 0x1b80 , 0x0000 , 0x0400 },
976
- { 0x0000 , 0x0000 , 0x1b80 , 0x0400 },
963
+ static const u16 vc5_hdmi_csc_full_rgb_to_rgb [2 ][3 ][4 ] = {
964
+ {
965
+ /* Full range - unity */
966
+ { 0x2000 , 0x0000 , 0x0000 , 0x0000 },
967
+ { 0x0000 , 0x2000 , 0x0000 , 0x0000 },
968
+ { 0x0000 , 0x0000 , 0x2000 , 0x0000 },
969
+ }, {
970
+ /* Limited range */
971
+ { 0x1b80 , 0x0000 , 0x0000 , 0x0400 },
972
+ { 0x0000 , 0x1b80 , 0x0000 , 0x0400 },
973
+ { 0x0000 , 0x0000 , 0x1b80 , 0x0400 },
974
+ }
977
975
};
978
976
979
977
/*
980
- * Conversion between Full Range RGB and Full Range YUV422 using the
981
- * BT.709 Colorspace
978
+ * Conversion between Full Range RGB and YUV using the BT.601 Colorspace
979
+ *
980
+ * Full range
981
+ * [ 0.299000 0.587000 0.114000 0.000000 ]
982
+ * [ -0.168736 -0.331264 0.500000 128.000000 ]
983
+ * [ 0.500000 -0.418688 -0.081312 128.000000 ]
982
984
*
983
- * [ 0.212639 0.715169 0.072192 0 ]
984
- * [ -0.117208 -0.394207 0.511416 128 ]
985
- * [ 0.511416 -0.464524 -0.046891 128 ]
985
+ * Limited range
986
+ * [ 0.255785 0.502160 0.097523 16.000000 ]
987
+ * [ -0.147644 -0.289856 0.437500 128.000000 ]
988
+ * [ 0.437500 -0.366352 -0.071148 128.000000 ]
986
989
*
987
990
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
988
991
*/
989
- static const u16 vc5_hdmi_csc_full_rgb_to_full_yuv422_bt709 [3 ][4 ] = {
990
- { 0x06ce , 0x16e3 , 0x024f , 0x0000 },
991
- { 0xfc41 , 0xf364 , 0x105e , 0x2000 },
992
- { 0x105e , 0xf124 , 0xfe81 , 0x2000 },
992
+ static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt601 [2 ][3 ][4 ] = {
993
+ {
994
+ /* Full range */
995
+ { 0x0991 , 0x12c9 , 0x03a6 , 0x0000 },
996
+ { 0xfa9b , 0xf567 , 0x1000 , 0x2000 },
997
+ { 0x1000 , 0xf29b , 0xfd67 , 0x2000 },
998
+ }, {
999
+ /* Limited range */
1000
+ { 0x082f , 0x1012 , 0x031f , 0x0400 },
1001
+ { 0xfb48 , 0xf6ba , 0x0e00 , 0x2000 },
1002
+ { 0x0e00 , 0xf448 , 0xfdba , 0x2000 },
1003
+ }
993
1004
};
994
1005
995
1006
/*
996
- * Conversion between Full Range RGB and Full Range YUV444 using the
997
- * BT.709 Colorspace
1007
+ * Conversion between Full Range RGB and YUV using the BT.709 Colorspace
1008
+ *
1009
+ * Full range
1010
+ * [ 0.212600 0.715200 0.072200 0.000000 ]
1011
+ * [ -0.114572 -0.385428 0.500000 128.000000 ]
1012
+ * [ 0.500000 -0.454153 -0.045847 128.000000 ]
998
1013
*
999
- * [ -0.117208 -0.394207 0.511416 128 ]
1000
- * [ 0.511416 -0.464524 -0.046891 128 ]
1001
- * [ 0.212639 0.715169 0.072192 0 ]
1014
+ * Limited range
1015
+ * [ 0.181873 0.611831 0.061765 16.000000 ]
1016
+ * [ -0.100251 -0.337249 0.437500 128.000000 ]
1017
+ * [ 0.437500 -0.397384 -0.040116 128.000000 ]
1002
1018
*
1003
1019
* Matrix is signed 2p13 fixed point, with signed 9p6 offsets
1004
1020
*/
1005
- static const u16 vc5_hdmi_csc_full_rgb_to_full_yuv444_bt709 [3 ][4 ] = {
1006
- { 0xfc41 , 0xf364 , 0x105e , 0x2000 },
1007
- { 0x105e , 0xf124 , 0xfe81 , 0x2000 },
1008
- { 0x06ce , 0x16e3 , 0x024f , 0x0000 },
1021
+ static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt709 [2 ][3 ][4 ] = {
1022
+ {
1023
+ /* Full range */
1024
+ { 0x06ce , 0x16e3 , 0x024f , 0x0000 },
1025
+ { 0xfc56 , 0xf3ac , 0x1000 , 0x2000 },
1026
+ { 0x1000 , 0xf179 , 0xfe89 , 0x2000 },
1027
+ }, {
1028
+ /* Limited range */
1029
+ { 0x05d2 , 0x1394 , 0x01fa , 0x0400 },
1030
+ { 0xfccc , 0xf536 , 0x0e00 , 0x2000 },
1031
+ { 0x0e00 , 0xf34a , 0xfeb8 , 0x2000 },
1032
+ }
1033
+ };
1034
+
1035
+ /*
1036
+ * Conversion between Full Range RGB and YUV using the BT.2020 Colorspace
1037
+ *
1038
+ * Full range
1039
+ * [ 0.262700 0.678000 0.059300 0.000000 ]
1040
+ * [ -0.139630 -0.360370 0.500000 128.000000 ]
1041
+ * [ 0.500000 -0.459786 -0.040214 128.000000 ]
1042
+ *
1043
+ * Limited range
1044
+ * [ 0.224732 0.580008 0.050729 16.000000 ]
1045
+ * [ -0.122176 -0.315324 0.437500 128.000000 ]
1046
+ * [ 0.437500 -0.402312 -0.035188 128.000000 ]
1047
+ *
1048
+ * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
1049
+ */
1050
+ static const u16 vc5_hdmi_csc_full_rgb_to_yuv_bt2020 [2 ][3 ][4 ] = {
1051
+ {
1052
+ /* Full range */
1053
+ { 0x0868 , 0x15b2 , 0x01e6 , 0x0000 },
1054
+ { 0xfb89 , 0xf479 , 0x1000 , 0x2000 },
1055
+ { 0x1000 , 0xf14a , 0xfeb8 , 0x2000 },
1056
+ }, {
1057
+ /* Limited range */
1058
+ { 0x0731 , 0x128f , 0x01a0 , 0x0400 },
1059
+ { 0xfc18 , 0xf5ea , 0x0e00 , 0x2000 },
1060
+ { 0x0e00 , 0xf321 , 0xfee1 , 0x2000 },
1061
+ }
1009
1062
};
1010
1063
1011
1064
static void vc5_hdmi_set_csc_coeffs (struct vc4_hdmi * vc4_hdmi ,
@@ -1021,12 +1074,28 @@ static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi,
1021
1074
HDMI_WRITE (HDMI_CSC_34_33 , (coeffs [2 ][3 ] << 16 ) | coeffs [2 ][2 ]);
1022
1075
}
1023
1076
1077
+ static void vc5_hdmi_set_csc_coeffs_swap (struct vc4_hdmi * vc4_hdmi ,
1078
+ const u16 coeffs [3 ][4 ])
1079
+ {
1080
+ lockdep_assert_held (& vc4_hdmi -> hw_lock );
1081
+
1082
+ /* YUV444 needs the CSC matrices using the channels in a different order */
1083
+ HDMI_WRITE (HDMI_CSC_12_11 , (coeffs [2 ][1 ] << 16 ) | coeffs [2 ][0 ]);
1084
+ HDMI_WRITE (HDMI_CSC_14_13 , (coeffs [2 ][3 ] << 16 ) | coeffs [2 ][2 ]);
1085
+ HDMI_WRITE (HDMI_CSC_22_21 , (coeffs [0 ][1 ] << 16 ) | coeffs [0 ][0 ]);
1086
+ HDMI_WRITE (HDMI_CSC_24_23 , (coeffs [0 ][3 ] << 16 ) | coeffs [0 ][2 ]);
1087
+ HDMI_WRITE (HDMI_CSC_32_31 , (coeffs [1 ][1 ] << 16 ) | coeffs [1 ][0 ]);
1088
+ HDMI_WRITE (HDMI_CSC_34_33 , (coeffs [1 ][3 ] << 16 ) | coeffs [1 ][2 ]);
1089
+ }
1090
+
1024
1091
static void vc5_hdmi_csc_setup (struct vc4_hdmi * vc4_hdmi ,
1025
1092
struct drm_connector_state * state ,
1026
1093
const struct drm_display_mode * mode )
1027
1094
{
1028
1095
struct vc4_hdmi_connector_state * vc4_state =
1029
1096
conn_state_to_vc4_hdmi_conn_state (state );
1097
+ unsigned int lim_range = vc4_hdmi_is_full_range (vc4_hdmi , mode ) ? 0 : 1 ;
1098
+ const u16 (* csc )[4 ];
1030
1099
unsigned long flags ;
1031
1100
u32 if_cfg = 0 ;
1032
1101
u32 if_xbar = 0x543210 ;
@@ -1038,31 +1107,56 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
1038
1107
1039
1108
switch (vc4_state -> output_format ) {
1040
1109
case VC4_HDMI_OUTPUT_YUV444 :
1041
- vc5_hdmi_set_csc_coeffs (vc4_hdmi , vc5_hdmi_csc_full_rgb_to_full_yuv444_bt709 );
1042
- break ;
1043
-
1044
1110
case VC4_HDMI_OUTPUT_YUV422 :
1045
- csc_ctl |= VC4_SET_FIELD (VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD ,
1046
- VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422 ) |
1047
- VC5_MT_CP_CSC_CTL_USE_444_TO_422 |
1048
- VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION ;
1111
+ switch (state -> colorspace ) {
1112
+ default :
1113
+ case DRM_MODE_COLORIMETRY_NO_DATA :
1114
+ case DRM_MODE_COLORIMETRY_BT709_YCC :
1115
+ case DRM_MODE_COLORIMETRY_XVYCC_709 :
1116
+ case DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED :
1117
+ case DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT :
1118
+ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt709 [lim_range ];
1119
+ break ;
1120
+ case DRM_MODE_COLORIMETRY_SMPTE_170M_YCC :
1121
+ case DRM_MODE_COLORIMETRY_XVYCC_601 :
1122
+ case DRM_MODE_COLORIMETRY_SYCC_601 :
1123
+ case DRM_MODE_COLORIMETRY_OPYCC_601 :
1124
+ case DRM_MODE_COLORIMETRY_BT601_YCC :
1125
+ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt601 [lim_range ];
1126
+ break ;
1127
+ case DRM_MODE_COLORIMETRY_BT2020_CYCC :
1128
+ case DRM_MODE_COLORIMETRY_BT2020_YCC :
1129
+ case DRM_MODE_COLORIMETRY_BT2020_RGB :
1130
+ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65 :
1131
+ case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER :
1132
+ csc = vc5_hdmi_csc_full_rgb_to_yuv_bt2020 [lim_range ];
1133
+ break ;
1134
+ }
1049
1135
1050
- csc_chan_ctl |= VC4_SET_FIELD (VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE ,
1051
- VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP );
1136
+ if (vc4_state -> output_format == VC4_HDMI_OUTPUT_YUV422 ) {
1137
+ csc_ctl |= VC4_SET_FIELD (VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD ,
1138
+ VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422 ) |
1139
+ VC5_MT_CP_CSC_CTL_USE_444_TO_422 |
1140
+ VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION ;
1052
1141
1053
- if_cfg |= VC4_SET_FIELD (VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY ,
1054
- VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422 );
1142
+ csc_chan_ctl |= VC4_SET_FIELD (VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE ,
1143
+ VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP );
1144
+
1145
+ if_cfg |= VC4_SET_FIELD (VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY ,
1146
+ VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422 );
1147
+
1148
+ vc5_hdmi_set_csc_coeffs (vc4_hdmi , csc );
1149
+ } else {
1150
+ vc5_hdmi_set_csc_coeffs_swap (vc4_hdmi , csc );
1151
+ }
1055
1152
1056
- vc5_hdmi_set_csc_coeffs (vc4_hdmi , vc5_hdmi_csc_full_rgb_to_full_yuv422_bt709 );
1057
1153
break ;
1058
1154
1059
1155
case VC4_HDMI_OUTPUT_RGB :
1060
1156
if_xbar = 0x354021 ;
1061
1157
1062
- if (!vc4_hdmi_is_full_range_rgb (vc4_hdmi , mode ))
1063
- vc5_hdmi_set_csc_coeffs (vc4_hdmi , vc5_hdmi_csc_full_rgb_to_limited_rgb );
1064
- else
1065
- vc5_hdmi_set_csc_coeffs (vc4_hdmi , vc5_hdmi_csc_full_rgb_unity );
1158
+ vc5_hdmi_set_csc_coeffs (vc4_hdmi ,
1159
+ vc5_hdmi_csc_full_rgb_to_rgb [lim_range ]);
1066
1160
break ;
1067
1161
1068
1162
default :
0 commit comments