cta: add support for video capability data block

Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
Simon Ser 2022-09-01 13:43:22 +02:00
parent edb952756d
commit 407b309904
5 changed files with 140 additions and 13 deletions

51
cta.c
View file

@ -84,6 +84,45 @@ parse_video_block(struct di_edid_cta *cta, struct di_cta_video_block *video,
return true;
}
static bool
parse_video_cap_block(struct di_edid_cta *cta,
struct di_cta_video_cap_block *video_cap,
const uint8_t *data, size_t size)
{
if (size < 1) {
add_failure(cta,
"Video Capability Data Block: Empty Data Block with length %u.",
size);
return false;
}
video_cap->selectable_ycc_quantization_range = has_bit(data[0], 7);
video_cap->selectable_rgb_quantization_range = has_bit(data[0], 6);
video_cap->pt_over_underscan = get_bit_range(data[0], 5, 4);
video_cap->it_over_underscan = get_bit_range(data[0], 3, 2);
video_cap->ce_over_underscan = get_bit_range(data[0], 1, 0);
if (!video_cap->selectable_rgb_quantization_range && cta->revision >= 3)
add_failure(cta,
"Video Capability Data Block: Set Selectable RGB Quantization to avoid interop issues.");
/* TODO: add failure if selectable_ycc_quantization_range is unset,
* the sink supports YCbCr formats and the revision is 3+ */
switch (video_cap->it_over_underscan) {
case DI_CTA_VIDEO_CAP_ALWAYS_OVERSCAN:
if (cta->flags.it_underscan)
add_failure(cta, "Video Capability Data Block: IT video formats are always overscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to underscanned.");
break;
case DI_CTA_VIDEO_CAP_ALWAYS_UNDERSCAN:
if (!cta->flags.it_underscan)
add_failure(cta, "Video Capability Data Block: IT video formats are always underscanned, but bit 7 of Byte 3 of the CTA-861 Extension header is set to overscanned.");
default:
break;
}
return true;
}
static bool
parse_colorimetry_block(struct di_edid_cta *cta,
struct di_cta_colorimetry_block *colorimetry,
@ -237,6 +276,9 @@ parse_data_block(struct di_edid_cta *cta, uint8_t raw_tag, const uint8_t *data,
switch (extended_tag) {
case 0:
tag = DI_CTA_DATA_BLOCK_VIDEO_CAP;
if (!parse_video_cap_block(cta, &data_block->video_cap,
data, size))
goto skip;
break;
case 2:
tag = DI_CTA_DATA_BLOCK_VESA_DISPLAY_DEVICE;
@ -477,6 +519,15 @@ di_cta_data_block_get_hdr_static_metadata(const struct di_cta_data_block *block)
return &block->hdr_static_metadata.base;
}
const struct di_cta_video_cap_block *
di_cta_data_block_get_video_cap(const struct di_cta_data_block *block)
{
if (block->tag != DI_CTA_DATA_BLOCK_VIDEO_CAP) {
return NULL;
}
return &block->video_cap;
}
const struct di_edid_detailed_timing_def *const *
di_edid_cta_get_detailed_timing_defs(const struct di_edid_cta *cta)
{

View file

@ -594,6 +594,23 @@ cta_data_block_tag_name(enum di_cta_data_block_tag tag)
return "Unknown CTA-861 Data Block";
}
static const char *
video_cap_over_underscan_name(enum di_cta_video_cap_over_underscan over_underscan,
const char *unknown)
{
switch (over_underscan) {
case DI_CTA_VIDEO_CAP_UNKNOWN_OVER_UNDERSCAN:
return unknown;
case DI_CTA_VIDEO_CAP_ALWAYS_OVERSCAN:
return "Always Overscanned";
case DI_CTA_VIDEO_CAP_ALWAYS_UNDERSCAN:
return "Always Underscanned";
case DI_CTA_VIDEO_CAP_BOTH_OVER_UNDERSCAN:
return "Supports both over- and underscan";
}
abort();
}
static void
print_cta(const struct di_edid_cta *cta)
{
@ -602,6 +619,7 @@ print_cta(const struct di_edid_cta *cta)
const struct di_cta_data_block *data_block;
enum di_cta_data_block_tag data_block_tag;
const struct di_cta_svd *const *svds;
const struct di_cta_video_cap_block *video_cap;
const struct di_cta_colorimetry_block *colorimetry;
const struct di_cta_hdr_static_metadata_block *hdr_static_metadata;
size_t i;
@ -636,6 +654,24 @@ print_cta(const struct di_edid_cta *cta)
svds = di_cta_data_block_get_svds(data_block);
printf_cta_svds(svds);
break;
case DI_CTA_DATA_BLOCK_VIDEO_CAP:
video_cap = di_cta_data_block_get_video_cap(data_block);
printf(" YCbCr quantization: %s\n",
video_cap->selectable_ycc_quantization_range ?
"Selectable (via AVI YQ)" : "No Data");
printf(" RGB quantization: %s\n",
video_cap->selectable_ycc_quantization_range ?
"Selectable (via AVI Q)" : "No Data");
printf(" PT scan behavior: %s\n",
video_cap_over_underscan_name(video_cap->pt_over_underscan,
"No Data"));
printf(" IT scan behavior: %s\n",
video_cap_over_underscan_name(video_cap->it_over_underscan,
"IT video formats not supported"));
printf(" CE scan behavior: %s\n",
video_cap_over_underscan_name(video_cap->ce_over_underscan,
"CE video formats not supported"));
break;
case DI_CTA_DATA_BLOCK_COLORIMETRY:
colorimetry = di_cta_data_block_get_colorimetry(data_block);
if (colorimetry->xvycc_601)

View file

@ -59,6 +59,8 @@ struct di_cta_data_block {
/* Used for DI_CTA_DATA_BLOCK_VIDEO */
struct di_cta_video_block video;
/* Used for DI_CTA_DATA_BLOCK_VIDEO_CAP */
struct di_cta_video_cap_block video_cap;
/* Used for DI_CTA_DATA_BLOCK_COLORIMETRY */
struct di_cta_colorimetry_block colorimetry;
/* Used for DI_CTA_DATA_BLOCK_HDR_STATIC_METADATA */

View file

@ -117,6 +117,45 @@ enum di_cta_data_block_tag {
enum di_cta_data_block_tag
di_cta_data_block_get_tag(const struct di_cta_data_block *block);
/**
* Over- and underscan capability.
*/
enum di_cta_video_cap_over_underscan {
/* No data */
DI_CTA_VIDEO_CAP_UNKNOWN_OVER_UNDERSCAN = 0x00,
/* Always overscanned */
DI_CTA_VIDEO_CAP_ALWAYS_OVERSCAN = 0x01,
/* Always underscanned */
DI_CTA_VIDEO_CAP_ALWAYS_UNDERSCAN = 0x02,
/* Supports both over- and underscan */
DI_CTA_VIDEO_CAP_BOTH_OVER_UNDERSCAN = 0x03,
};
/**
* Video capability data block (VCDB), defined in section 7.5.6.
*/
struct di_cta_video_cap_block {
/* If set to true, YCC quantization range is selectable (via AVI YQ). */
bool selectable_ycc_quantization_range;
/* If set to true, RGB quantization range is selectable (via AVI Q). */
bool selectable_rgb_quantization_range;
/* Overscan/underscan behavior for PT video formats (if set to unknown,
* use the IT/CE behavior) */
enum di_cta_video_cap_over_underscan pt_over_underscan;
/* Overscan/underscan behavior for IT video formats */
enum di_cta_video_cap_over_underscan it_over_underscan;
/* Overscan/underscan behavior for CE video formats */
enum di_cta_video_cap_over_underscan ce_over_underscan;
};
/**
* Get the video capabilities from a CTA data block.
*
* Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_VIDEO_CAP.
*/
const struct di_cta_video_cap_block *
di_cta_data_block_get_video_cap(const struct di_cta_data_block *block);
/**
* CTA colorimetry data block, defined in section 7.5.5.
*/

View file

@ -23,7 +23,7 @@
Detailed Timing Descriptors:
DTD 1: 2560x1440 59.950550 Hz 16:9 88.787 kHz 241.500000 MHz (597 mm x 339 mm)
Hfront 48 Hsync 32 Hback 80 Hpol P
@@ -51,32 +51,16 @@
@@ -51,32 +51,21 @@
Supports YCbCr 4:2:2
Native detailed modes: 1
Video Data Block:
@ -52,11 +52,11 @@
+ VIC 17
+ VIC 1
Video Capability Data Block:
- YCbCr quantization: No Data
- RGB quantization: No Data
- PT scan behavior: Always Underscanned
- IT scan behavior: Always Underscanned
- CE scan behavior: Supports both over- and underscan
YCbCr quantization: No Data
RGB quantization: No Data
PT scan behavior: Always Underscanned
IT scan behavior: Always Underscanned
CE scan behavior: Supports both over- and underscan
- Vendor-Specific Data Block (AMD), OUI 00-00-1A:
- Version: 1.1
- Minimum Refresh Rate: 46 Hz
@ -65,7 +65,7 @@
Colorimetry Data Block:
BT2020cYCC
BT2020YCC
@@ -104,20 +88,8 @@
@@ -104,20 +93,12 @@
DTD 5: 1920x1080 74.972503 Hz 16:9 83.894 kHz 174.500000 MHz (597 mm x 339 mm)
Hfront 48 Hsync 32 Hback 80 Hpol P
Vfront 3 Vsync 5 Vback 31 Vpol N
@ -81,10 +81,9 @@
- Colorimetry Data Block: Set the sRGB colorimetry bit to avoid interop issues.
- Display Product Serial Number is set, so the Serial Number in the Base EDID should be 0.
-
-Failures:
Failures:
Block 1, CTA-861 Extension Block:
Video Capability Data Block: Set Selectable RGB Quantization to avoid interop issues.
-
-Block 1, CTA-861 Extension Block:
- Video Capability Data Block: Set Selectable RGB Quantization to avoid interop issues.
-
-EDID conformity: FAIL
+EDID conformity: PASS
EDID conformity: FAIL