graphics/edid: add support for the CTA extension block
Change-Id: I2799496faf2f9383c703384a419d8d9fcffc75ab Reviewed-on: https://review.haiku-os.org/c/haiku/+/5803 Reviewed-by: Jérôme Duval <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
@@ -127,6 +127,28 @@ typedef struct {
|
|||||||
} data;
|
} data;
|
||||||
} edid1_detailed_monitor;
|
} edid1_detailed_monitor;
|
||||||
|
|
||||||
|
// CTA data block
|
||||||
|
typedef struct cta_info {
|
||||||
|
uint8 tag;
|
||||||
|
uint8 revision;
|
||||||
|
uint8 num_native_detailed;
|
||||||
|
bool ycbcr422_supported;
|
||||||
|
bool ycbcr444_supported;
|
||||||
|
bool audio_supported;
|
||||||
|
bool underscan;
|
||||||
|
edid1_detailed_timing detailed_timing[6];
|
||||||
|
uint8 num_data_blocks;
|
||||||
|
cta_data_block data_blocks[8];
|
||||||
|
} cta_info;
|
||||||
|
|
||||||
|
|
||||||
|
// DisplayID data block
|
||||||
|
typedef struct displayid_info {
|
||||||
|
uint8 tag;
|
||||||
|
uint8 version;
|
||||||
|
uint8 extension_count;
|
||||||
|
} displayid_info;
|
||||||
|
|
||||||
// EDID data block
|
// EDID data block
|
||||||
typedef struct edid1_info {
|
typedef struct edid1_info {
|
||||||
edid1_vendor vendor;
|
edid1_vendor vendor;
|
||||||
@@ -139,8 +161,13 @@ typedef struct edid1_info {
|
|||||||
edid1_detailed_monitor detailed_monitor[EDID1_NUM_DETAILED_MONITOR_DESC];
|
edid1_detailed_monitor detailed_monitor[EDID1_NUM_DETAILED_MONITOR_DESC];
|
||||||
|
|
||||||
uint8 num_sections;
|
uint8 num_sections;
|
||||||
|
|
||||||
|
// optional
|
||||||
|
cta_info cta_block;
|
||||||
|
displayid_info displayid_block;
|
||||||
} edid1_info;
|
} edid1_info;
|
||||||
|
|
||||||
|
|
||||||
#define EDID_VERSION_1 1
|
#define EDID_VERSION_1 1
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ typedef struct _PACKED {
|
|||||||
BBITFIELD8_3 (
|
BBITFIELD8_3 (
|
||||||
input_type : 1, // 0 : analog, 1 : digital
|
input_type : 1, // 0 : analog, 1 : digital
|
||||||
bit_depth : 3, // 0=undefined, 1=6,2=8,3=10,4=12,5=14,6=16,7=reserved
|
bit_depth : 3, // 0=undefined, 1=6,2=8,3=10,4=12,5=14,6=16,7=reserved
|
||||||
interface : 4 // 0=undefined, 2=HDMIa, 3=HDMIb
|
interface : 4 // 0=undefined, 1=DVI, 2=HDMIa, 3=HDMIb
|
||||||
// 4=MDDI, 5=DisplayPort
|
// 4=MDDI, 5=DisplayPort
|
||||||
);
|
);
|
||||||
} edid1_digital_params_raw;
|
} edid1_digital_params_raw;
|
||||||
@@ -301,4 +301,262 @@ typedef struct _PACKED {
|
|||||||
uint8 check_sum; // 1 byte
|
uint8 check_sum; // 1 byte
|
||||||
} edid1_raw; // total: 128 bytes
|
} edid1_raw; // total: 128 bytes
|
||||||
|
|
||||||
|
typedef union _PACKED {
|
||||||
|
struct _PACKED {
|
||||||
|
BBITFIELD8_3 (
|
||||||
|
reserved : 1,
|
||||||
|
format_code : 4,
|
||||||
|
reserved2 : 3
|
||||||
|
);
|
||||||
|
} descr;
|
||||||
|
struct _PACKED {
|
||||||
|
BBITFIELD8_3 (
|
||||||
|
reserved : 1,
|
||||||
|
format_code : 4,
|
||||||
|
max_channels : 3
|
||||||
|
);
|
||||||
|
BBITFIELD8_8 (
|
||||||
|
reserved2 : 1,
|
||||||
|
can_192khz : 1,
|
||||||
|
can_176khz : 1,
|
||||||
|
can_96khz : 1,
|
||||||
|
can_88khz : 1,
|
||||||
|
can_48khz : 1,
|
||||||
|
can_44khz : 1,
|
||||||
|
can_32khz : 1
|
||||||
|
);
|
||||||
|
BBITFIELD8_4 (
|
||||||
|
reserved3 : 5,
|
||||||
|
can_24bit : 1,
|
||||||
|
can_20bit : 1,
|
||||||
|
can_16bit : 1
|
||||||
|
);
|
||||||
|
} descr_1;
|
||||||
|
struct _PACKED {
|
||||||
|
BBITFIELD8_3 (
|
||||||
|
reserved : 1,
|
||||||
|
format_code : 4,
|
||||||
|
max_channels : 3
|
||||||
|
);
|
||||||
|
BBITFIELD8_8 (
|
||||||
|
reserved2 : 1,
|
||||||
|
can_192khz : 1,
|
||||||
|
can_176khz : 1,
|
||||||
|
can_96khz : 1,
|
||||||
|
can_88khz : 1,
|
||||||
|
can_48khz : 1,
|
||||||
|
can_44khz : 1,
|
||||||
|
can_32khz : 1
|
||||||
|
);
|
||||||
|
uint8 maximum_bitrate;
|
||||||
|
} descr_2_8;
|
||||||
|
|
||||||
|
} audio_descr;
|
||||||
|
|
||||||
|
#if !defined(__GNUC__) || __GNUC__ < 3
|
||||||
|
#define FLEXIBLE_ARRAY_LENGTH 0
|
||||||
|
#else
|
||||||
|
#define FLEXIBLE_ARRAY_LENGTH
|
||||||
|
#endif
|
||||||
|
typedef struct _PACKED {
|
||||||
|
BBITFIELD8_2 (
|
||||||
|
tag_code : 3,
|
||||||
|
length : 5
|
||||||
|
);
|
||||||
|
union _PACKED {
|
||||||
|
uint8 extended_tag_code;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
uint8 vic0;
|
||||||
|
uint8 vic[FLEXIBLE_ARRAY_LENGTH];
|
||||||
|
} video;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
audio_descr desc0;
|
||||||
|
audio_descr desc[FLEXIBLE_ARRAY_LENGTH];
|
||||||
|
} audio;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
uint8 ouinum0;
|
||||||
|
uint8 ouinum1;
|
||||||
|
uint8 ouinum2;
|
||||||
|
union _PACKED {
|
||||||
|
struct _PACKED {
|
||||||
|
struct _PACKED {
|
||||||
|
BBITFIELD8_2 (
|
||||||
|
a : 4,
|
||||||
|
b : 4
|
||||||
|
);
|
||||||
|
BBITFIELD8_2 (
|
||||||
|
c : 4,
|
||||||
|
d : 4
|
||||||
|
);
|
||||||
|
} source_physical_address;
|
||||||
|
BBITFIELD8_7 (
|
||||||
|
supports_ai : 1,
|
||||||
|
dc_48bit : 1,
|
||||||
|
dc_36bit : 1,
|
||||||
|
dc_30bit : 1,
|
||||||
|
dc_y444 : 1,
|
||||||
|
reserved : 2,
|
||||||
|
dvi_dual : 1
|
||||||
|
);
|
||||||
|
uint8 max_tmds_clock;
|
||||||
|
uint8 reserved2[2];
|
||||||
|
BBITFIELD8_2 (
|
||||||
|
vic_length : 3,
|
||||||
|
length_3d : 5
|
||||||
|
);
|
||||||
|
uint8 vic[FLEXIBLE_ARRAY_LENGTH];
|
||||||
|
} hdmi;
|
||||||
|
struct _PACKED {
|
||||||
|
uint8 version;
|
||||||
|
uint8 max_tmds_rate;
|
||||||
|
BBITFIELD8_8 (
|
||||||
|
scdc_present : 1,
|
||||||
|
scdc_read_request_capable : 1,
|
||||||
|
supports_cable_status : 1,
|
||||||
|
supports_color_content_bits : 1,
|
||||||
|
supports_scrambling : 1,
|
||||||
|
supports_3d_independent : 1,
|
||||||
|
supports_3d_dual_view : 1,
|
||||||
|
supports_3d_osd_disparity : 1
|
||||||
|
);
|
||||||
|
BBITFIELD8_5 (
|
||||||
|
max_frl_rate : 4,
|
||||||
|
supports_uhd_vic : 1,
|
||||||
|
supports_16bit_deep_color_4_2_0 : 1,
|
||||||
|
supports_12bit_deep_color_4_2_0 : 1,
|
||||||
|
supports_10bit_deep_color_4_2_0 : 1
|
||||||
|
);
|
||||||
|
} hdmi_forum;
|
||||||
|
};
|
||||||
|
} vendor_specific;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
BBITFIELD8_8 (
|
||||||
|
FLW_FRW : 1,
|
||||||
|
RLC_RRC : 1,
|
||||||
|
FLC_FRC : 1,
|
||||||
|
BC : 1,
|
||||||
|
BL_BR : 1,
|
||||||
|
FC : 1,
|
||||||
|
LFE : 1,
|
||||||
|
FL_FR : 1
|
||||||
|
);
|
||||||
|
BBITFIELD8_8 (
|
||||||
|
TpSiL_TpSiR : 1,
|
||||||
|
SiL_SiR : 1,
|
||||||
|
TpBC : 1,
|
||||||
|
LFE2 : 1,
|
||||||
|
LS_RS : 1,
|
||||||
|
TpFC : 1,
|
||||||
|
TpC : 1,
|
||||||
|
TpFL_TpFH : 1
|
||||||
|
);
|
||||||
|
BBITFIELD8_6 (
|
||||||
|
reserved: 3,
|
||||||
|
LSd_RSd : 1,
|
||||||
|
TpLS_TpRS : 1,
|
||||||
|
BtFL_BtFR : 1,
|
||||||
|
BtFC : 1,
|
||||||
|
TpBL_TpBR : 1
|
||||||
|
);
|
||||||
|
} speaker_allocation_map;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
uint8 extended_tag_code;
|
||||||
|
BBITFIELD8_8 (
|
||||||
|
BT2020RGB : 1,
|
||||||
|
BT2020YCC : 1,
|
||||||
|
BT2020cYCC : 1,
|
||||||
|
opRGB : 1,
|
||||||
|
opYCC601 : 1,
|
||||||
|
sYCC601 : 1,
|
||||||
|
xvYCC709 : 1,
|
||||||
|
xvYCC601 : 1
|
||||||
|
);
|
||||||
|
BBITFIELD8_2 (
|
||||||
|
DCIP3 : 1,
|
||||||
|
reserved : 7
|
||||||
|
);
|
||||||
|
} colorimetry;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
uint8 extended_tag_code;
|
||||||
|
uint8 bitmap[FLEXIBLE_ARRAY_LENGTH];
|
||||||
|
} YCbCr_4_2_0_capability_map;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
uint8 extended_tag_code;
|
||||||
|
BBITFIELD8_5 (
|
||||||
|
QY : 1,
|
||||||
|
QS : 1,
|
||||||
|
S_PT : 2,
|
||||||
|
S_IT : 2,
|
||||||
|
S_CE : 2
|
||||||
|
);
|
||||||
|
} video_capability;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
uint8 extended_tag_code;
|
||||||
|
BBITFIELD8_7 (
|
||||||
|
reserved : 2,
|
||||||
|
ET_5 : 1,
|
||||||
|
ET_4 : 1,
|
||||||
|
ET_3 : 1,
|
||||||
|
ET_2 : 1,
|
||||||
|
ET_1 : 1,
|
||||||
|
ET_0 : 1
|
||||||
|
);
|
||||||
|
BBITFIELD8_8 (
|
||||||
|
SM_7 : 1,
|
||||||
|
SM_6 : 1,
|
||||||
|
SM_5 : 1,
|
||||||
|
SM_4 : 1,
|
||||||
|
SM_3 : 1,
|
||||||
|
SM_2 : 1,
|
||||||
|
SM_1 : 1,
|
||||||
|
SM_0 : 1
|
||||||
|
);
|
||||||
|
uint8 desired_content_max_luminance;
|
||||||
|
uint8 desired_content_max_frame_average_luminance;
|
||||||
|
uint8 desired_content_min_luminance;
|
||||||
|
} hdr_static_metadata;
|
||||||
|
|
||||||
|
struct _PACKED {
|
||||||
|
uint8 extended_tag_code;
|
||||||
|
// TODO extend
|
||||||
|
} hdr_dyn_metadata;
|
||||||
|
|
||||||
|
uint8 buffer[127];
|
||||||
|
};
|
||||||
|
} cta_data_block;
|
||||||
|
|
||||||
|
typedef struct _PACKED {
|
||||||
|
uint8 tag;
|
||||||
|
uint8 revision;
|
||||||
|
uint8 offset;
|
||||||
|
BBITFIELD8_5 (
|
||||||
|
underscan : 1,
|
||||||
|
audio : 1,
|
||||||
|
ycbcr444 : 1,
|
||||||
|
ycbcr422 : 1,
|
||||||
|
num_native_detailed : 4
|
||||||
|
);
|
||||||
|
cta_data_block data_blocks[0];
|
||||||
|
|
||||||
|
uint8 reserved[123];
|
||||||
|
uint8 check_sum; // 1 byte
|
||||||
|
} cta_raw; // total: 128 bytes
|
||||||
|
|
||||||
|
typedef struct _PACKED {
|
||||||
|
uint8 tag;
|
||||||
|
uint8 version;
|
||||||
|
uint8 length;
|
||||||
|
uint8 reserved;
|
||||||
|
uint8 extension_count;
|
||||||
|
uint8 reserved2[123];
|
||||||
|
} displayid_raw; // total: 128 bytes
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -171,7 +172,8 @@ copy_str(char *dest, const uint8 *src, size_t len)
|
|||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (*src == 0xa)
|
if (*src == 0xa)
|
||||||
break;
|
break;
|
||||||
|
if (!isgraph(*src) && *src != 0x20)
|
||||||
|
break;
|
||||||
*dest++ = *src++;
|
*dest++ = *src++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,6 +248,45 @@ decode_detailed_monitor(edid1_detailed_monitor *monitor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
decode_cta_block(edid1_info *edid, const cta_raw *raw)
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
edid->cta_block.tag = raw->tag;
|
||||||
|
edid->cta_block.revision = raw->revision;
|
||||||
|
edid->cta_block.num_native_detailed = raw->num_native_detailed;
|
||||||
|
edid->cta_block.ycbcr422_supported = raw->ycbcr422;
|
||||||
|
edid->cta_block.ycbcr444_supported = raw->ycbcr444;
|
||||||
|
edid->cta_block.audio_supported = raw->audio;
|
||||||
|
edid->cta_block.underscan = raw->underscan;
|
||||||
|
edid->cta_block.num_data_blocks = 0;
|
||||||
|
|
||||||
|
for (i = 4; i < raw->offset;) {
|
||||||
|
cta_data_block* block = (cta_data_block*)&((uint8*)raw)[i];
|
||||||
|
memcpy(&edid->cta_block.data_blocks[edid->cta_block.num_data_blocks++],
|
||||||
|
block, block->length + 1);
|
||||||
|
i += block->length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = raw->offset, j = 0; i + sizeof(edid1_detailed_timing_raw) - 1 < 128;
|
||||||
|
i += sizeof(edid1_detailed_timing_raw), j++) {
|
||||||
|
const edid1_detailed_timing_raw* timing =
|
||||||
|
(const edid1_detailed_timing_raw*)&((uint8*)raw)[i];
|
||||||
|
decode_detailed_timing(&edid->cta_block.detailed_timing[j], timing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
decode_displayid_block(edid1_info *edid, const displayid_raw *raw)
|
||||||
|
{
|
||||||
|
edid->displayid_block.tag = raw->tag;
|
||||||
|
edid->displayid_block.version = raw->version;
|
||||||
|
edid->displayid_block.extension_count = raw->extension_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -268,4 +309,21 @@ edid_decode(edid1_info *edid, const edid1_raw *raw)
|
|||||||
|
|
||||||
decode_detailed_monitor(edid->detailed_monitor, raw->detailed_monitor,
|
decode_detailed_monitor(edid->detailed_monitor, raw->detailed_monitor,
|
||||||
edid->version.version == 1 && edid->version.revision >= 1);
|
edid->version.version == 1 && edid->version.revision >= 1);
|
||||||
|
|
||||||
|
edid->num_sections = raw->num_sections;
|
||||||
|
|
||||||
|
for (i = 1; i < 1 + edid->num_sections; i++) {
|
||||||
|
cta_raw* cta = (cta_raw*)&raw[i];
|
||||||
|
switch (cta->tag) {
|
||||||
|
case 0x2:
|
||||||
|
decode_cta_block(edid, cta);
|
||||||
|
break;
|
||||||
|
case 0x70:
|
||||||
|
decode_displayid_block(edid, (displayid_raw*)&raw[i]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//printf("edid_decode unknown tag 0x%x\n", cta->tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,28 +12,554 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
|
||||||
|
const edid1_std_timing cta_mode1_timings[] = {
|
||||||
|
/* VIC 1 */
|
||||||
|
{ 640, 480, 0, 1, 60 },
|
||||||
|
{ 720, 480, 0, 1, 60 },
|
||||||
|
{ 720, 480, 0, 3, 60 },
|
||||||
|
{ 1280, 720, 0, 3, 60 },
|
||||||
|
{ 1920, 1080, 0, 3, 60 },
|
||||||
|
{ 1440, 480, 0, 1, 60 },
|
||||||
|
{ 1440, 480, 0, 3, 60 },
|
||||||
|
{ 1440, 240, 0, 1, 60 },
|
||||||
|
{ 1440, 240, 0, 3, 60 },
|
||||||
|
{ 2880, 480, 0, 1, 60 },
|
||||||
|
/* VIC 11 */
|
||||||
|
{ 2880, 480, 0, 3, 60 },
|
||||||
|
{ 2880, 240, 0, 1, 60 },
|
||||||
|
{ 2880, 240, 0, 3, 60 },
|
||||||
|
{ 1440, 480, 0, 1, 60 },
|
||||||
|
{ 1440, 480, 0, 3, 60 },
|
||||||
|
{ 1920, 1080, 0, 3, 60 },
|
||||||
|
{ 720, 576, 0, 1, 50 },
|
||||||
|
{ 720, 576, 0, 3, 50 },
|
||||||
|
{ 1280, 720, 0, 3, 50 },
|
||||||
|
{ 1920, 1080, 0, 3, 50 },
|
||||||
|
/* VIC 21 */
|
||||||
|
{ 1440, 576, 0, 1, 50 },
|
||||||
|
{ 1440, 576, 0, 3, 50 },
|
||||||
|
{ 1440, 288, 0, 1, 50 },
|
||||||
|
{ 1440, 288, 0, 3, 50 },
|
||||||
|
{ 2880, 576, 0, 1, 50 },
|
||||||
|
{ 2880, 576, 0, 3, 50 },
|
||||||
|
{ 2880, 288, 0, 1, 50 },
|
||||||
|
{ 2880, 288, 0, 3, 50 },
|
||||||
|
{ 1440, 576, 0, 1, 50 },
|
||||||
|
{ 1440, 576, 0, 3, 50 },
|
||||||
|
/* VIC 31 */
|
||||||
|
{ 1920, 1080, 0, 3, 50 },
|
||||||
|
{ 1920, 1080, 0, 3, 24 },
|
||||||
|
{ 1920, 1080, 0, 3, 25 },
|
||||||
|
{ 1920, 1080, 0, 3, 30 },
|
||||||
|
{ 2880, 480, 0, 1, 60 },
|
||||||
|
{ 2880, 480, 0, 3, 60 },
|
||||||
|
{ 2880, 576, 0, 1, 50 },
|
||||||
|
{ 2880, 576, 0, 3, 50 },
|
||||||
|
{ 1920, 1080, 0, 3, 50 },
|
||||||
|
{ 1920, 1080, 0, 3, 100 },
|
||||||
|
/* VIC 41 */
|
||||||
|
{ 1280, 720, 0, 3, 100 },
|
||||||
|
{ 720, 576, 0, 1, 100 },
|
||||||
|
{ 720, 576, 0, 3, 100 },
|
||||||
|
{ 1440, 576, 0, 1, 100 },
|
||||||
|
{ 1440, 576, 0, 3, 100 },
|
||||||
|
{ 1920, 1080, 0, 3, 120 },
|
||||||
|
{ 1280, 720, 0, 3, 120 },
|
||||||
|
{ 720, 480, 0, 1, 120 },
|
||||||
|
{ 720, 480, 0, 3, 120 },
|
||||||
|
{ 1440, 480, 0, 1, 120 },
|
||||||
|
/* VIC 51 */
|
||||||
|
{ 1440, 480, 0, 3, 120 },
|
||||||
|
{ 720, 576, 0, 1, 200 },
|
||||||
|
{ 720, 576, 0, 3, 200 },
|
||||||
|
{ 1440, 576, 0, 1, 200 },
|
||||||
|
{ 1440, 576, 0, 3, 200 },
|
||||||
|
{ 720, 480, 0, 1, 240 },
|
||||||
|
{ 720, 480, 0, 3, 240 },
|
||||||
|
{ 1440, 480, 0, 1, 240 },
|
||||||
|
{ 1440, 480, 0, 3, 240 },
|
||||||
|
{ 1280, 720, 0, 3, 24 },
|
||||||
|
/* VIC 61 */
|
||||||
|
{ 1280, 720, 0, 3, 25 },
|
||||||
|
{ 1280, 720, 0, 3, 30 },
|
||||||
|
{ 1920, 1080, 0, 3, 120 },
|
||||||
|
{ 1920, 1080, 0, 3, 100 },
|
||||||
|
{ 1280, 720, 0, 4, 24 },
|
||||||
|
{ 1280, 720, 0, 4, 25 },
|
||||||
|
{ 1280, 720, 0, 4, 30 },
|
||||||
|
{ 1280, 720, 0, 4, 50 },
|
||||||
|
{ 1280, 720, 0, 4, 60 },
|
||||||
|
{ 1280, 720, 0, 4, 100 },
|
||||||
|
/* VIC 71 */
|
||||||
|
{ 1280, 720, 0, 4, 120 },
|
||||||
|
{ 1920, 1080, 0, 4, 24 },
|
||||||
|
{ 1920, 1080, 0, 4, 25 },
|
||||||
|
{ 1920, 1080, 0, 4, 30 },
|
||||||
|
{ 1920, 1080, 0, 4, 50 },
|
||||||
|
{ 1920, 1080, 0, 4, 60 },
|
||||||
|
{ 1920, 1080, 0, 4, 100 },
|
||||||
|
{ 1920, 1080, 0, 4, 120 },
|
||||||
|
{ 1680, 720, 0, 4, 24 },
|
||||||
|
{ 1680, 720, 0, 4, 25 },
|
||||||
|
/* VIC 81 */
|
||||||
|
{ 1680, 720, 0, 4, 30 },
|
||||||
|
{ 1680, 720, 0, 4, 50 },
|
||||||
|
{ 1680, 720, 0, 4, 60 },
|
||||||
|
{ 1680, 720, 0, 4, 100 },
|
||||||
|
{ 1680, 720, 0, 4, 120 },
|
||||||
|
{ 2560, 1080, 0, 4, 24 },
|
||||||
|
{ 2560, 1080, 0, 4, 25 },
|
||||||
|
{ 2560, 1080, 0, 4, 30 },
|
||||||
|
{ 2560, 1080, 0, 4, 50 },
|
||||||
|
{ 2560, 1080, 0, 4, 60 },
|
||||||
|
/* VIC 91 */
|
||||||
|
{ 2560, 1080, 0, 4, 100 },
|
||||||
|
{ 2560, 1080, 0, 4, 120 },
|
||||||
|
{ 3840, 2160, 0, 3, 24 },
|
||||||
|
{ 3840, 2160, 0, 3, 25 },
|
||||||
|
{ 3840, 2160, 0, 3, 30 },
|
||||||
|
{ 3840, 2160, 0, 3, 50 },
|
||||||
|
{ 3840, 2160, 0, 3, 60 },
|
||||||
|
{ 4096, 2160, 0, 5, 24 },
|
||||||
|
{ 4096, 2160, 0, 5, 25 },
|
||||||
|
{ 4096, 2160, 0, 5, 30 },
|
||||||
|
/* VIC 101 */
|
||||||
|
{ 4096, 2160, 0, 5, 50 },
|
||||||
|
{ 4096, 2160, 0, 5, 60 },
|
||||||
|
{ 3840, 2160, 0, 4, 24 },
|
||||||
|
{ 3840, 2160, 0, 4, 25 },
|
||||||
|
{ 3840, 2160, 0, 4, 30 },
|
||||||
|
{ 3840, 2160, 0, 4, 50 },
|
||||||
|
{ 3840, 2160, 0, 4, 60 },
|
||||||
|
{ 1280, 720, 0, 3, 48 },
|
||||||
|
{ 1280, 720, 0, 4, 48 },
|
||||||
|
{ 1680, 720, 0, 4, 48 },
|
||||||
|
/* VIC 111 */
|
||||||
|
{ 1920, 1080, 0, 3, 48 },
|
||||||
|
{ 1920, 1080, 0, 4, 48 },
|
||||||
|
{ 2560, 1080, 0, 4, 48 },
|
||||||
|
{ 3840, 2160, 0, 3, 48 },
|
||||||
|
{ 4096, 2160, 0, 5, 48 },
|
||||||
|
{ 3840, 2160, 0, 4, 48 },
|
||||||
|
{ 3840, 2160, 0, 3, 100 },
|
||||||
|
{ 3840, 2160, 0, 3, 120 },
|
||||||
|
{ 3840, 2160, 0, 4, 100 },
|
||||||
|
{ 3840, 2160, 0, 4, 120 },
|
||||||
|
/* VIC 121 */
|
||||||
|
{ 5120, 2160, 0, 4, 24 },
|
||||||
|
{ 5120, 2160, 0, 4, 25 },
|
||||||
|
{ 5120, 2160, 0, 4, 30 },
|
||||||
|
{ 5120, 2160, 0, 4, 48 },
|
||||||
|
{ 5120, 2160, 0, 4, 50 },
|
||||||
|
{ 5120, 2160, 0, 4, 60 },
|
||||||
|
{ 5120, 2160, 0, 4, 100 },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const edid1_std_timing cta_mode2_timings[] = {
|
||||||
|
/* VIC 193 */
|
||||||
|
{ 5120, 2160, 0, 4, 120 },
|
||||||
|
{ 7680, 4320, 0, 3, 24 },
|
||||||
|
{ 7680, 4320, 0, 3, 25 },
|
||||||
|
{ 7680, 4320, 0, 3, 30 },
|
||||||
|
{ 7680, 4320, 0, 3, 48 },
|
||||||
|
{ 7680, 4320, 0, 3, 50 },
|
||||||
|
{ 7680, 4320, 0, 3, 60 },
|
||||||
|
{ 7680, 4320, 0, 3, 100 },
|
||||||
|
/* VIC 201 */
|
||||||
|
{ 7680, 4320, 0, 3, 120 },
|
||||||
|
{ 7680, 4320, 0, 4, 24 },
|
||||||
|
{ 7680, 4320, 0, 4, 25 },
|
||||||
|
{ 7680, 4320, 0, 4, 30 },
|
||||||
|
{ 7680, 4320, 0, 4, 48 },
|
||||||
|
{ 7680, 4320, 0, 4, 50 },
|
||||||
|
{ 7680, 4320, 0, 4, 60 },
|
||||||
|
{ 7680, 4320, 0, 4, 100 },
|
||||||
|
{ 7680, 4320, 0, 4, 120 },
|
||||||
|
{ 10240, 4320, 0, 4, 24 },
|
||||||
|
/* VIC 211 */
|
||||||
|
{ 10240, 4320, 0, 4, 25 },
|
||||||
|
{ 10240, 4320, 0, 4, 30 },
|
||||||
|
{ 10240, 4320, 0, 4, 48 },
|
||||||
|
{ 10240, 4320, 0, 4, 50 },
|
||||||
|
{ 10240, 4320, 0, 4, 60 },
|
||||||
|
{ 10240, 4320, 0, 4, 100 },
|
||||||
|
{ 10240, 4320, 0, 4, 120 },
|
||||||
|
{ 4096, 2160, 0, 5, 100 },
|
||||||
|
{ 4096, 2160, 0, 5, 120 },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
edid_timing_dump(edid1_detailed_timing *timing, bool warnInvalid)
|
||||||
|
{
|
||||||
|
if (timing->h_active + timing->h_blank == 0
|
||||||
|
|| timing->v_active + timing->v_blank == 0
|
||||||
|
|| timing->pixel_clock == 0) {
|
||||||
|
if (warnInvalid)
|
||||||
|
dprintf("Invalid video mode (%dx%d)\n", timing->h_active, timing->v_active);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("Additional Video Mode (%dx%d@%dHz):\n",
|
||||||
|
timing->h_active, timing->v_active,
|
||||||
|
(timing->pixel_clock * 10000
|
||||||
|
/ (timing->h_active + timing->h_blank)
|
||||||
|
/ (timing->v_active + timing->v_blank)));
|
||||||
|
// Refresh rate = pixel clock in MHz / Htotal / Vtotal
|
||||||
|
|
||||||
|
dprintf("clock=%.3f MHz\n", timing->pixel_clock / 100.0);
|
||||||
|
dprintf("h: (%d, %d, %d, %d)\n",
|
||||||
|
timing->h_active, timing->h_active + timing->h_sync_off,
|
||||||
|
timing->h_active + timing->h_sync_off
|
||||||
|
+ timing->h_sync_width,
|
||||||
|
timing->h_active + timing->h_blank);
|
||||||
|
dprintf("v: (%d, %d, %d, %d)\n",
|
||||||
|
timing->v_active, timing->v_active + timing->v_sync_off,
|
||||||
|
timing->v_active + timing->v_sync_off
|
||||||
|
+ timing->v_sync_width,
|
||||||
|
timing->v_active + timing->v_blank);
|
||||||
|
dprintf("size: %.1f cm x %.1f cm\n",
|
||||||
|
timing->h_size / 10.0, timing->v_size / 10.0);
|
||||||
|
dprintf("border: %.1f cm x %.1f cm\n",
|
||||||
|
timing->h_border / 10.0, timing->v_border / 10.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
edid_cta_datablock_dump(cta_data_block *dataBlock)
|
||||||
|
{
|
||||||
|
uint16 tagCode = dataBlock->tag_code;
|
||||||
|
uint8 i, j;
|
||||||
|
if (tagCode == 0x7)
|
||||||
|
tagCode = 0x700 | dataBlock->extended_tag_code;
|
||||||
|
switch (tagCode) {
|
||||||
|
case 0x1:
|
||||||
|
dprintf("Audio data block\n");
|
||||||
|
for (i = 0; i * 3 < dataBlock->length; i++) {
|
||||||
|
const char* formatName = NULL;
|
||||||
|
audio_descr* descr = &dataBlock->audio.desc0;
|
||||||
|
if (i > 0)
|
||||||
|
descr = &dataBlock->audio.desc[i - 1];
|
||||||
|
switch (descr->descr.format_code) {
|
||||||
|
case 0x1: formatName = "Linear-PCM"; break;
|
||||||
|
case 0x2: formatName = "AC-3"; break;
|
||||||
|
case 0x3: formatName = "MPEG 1 (Layers 1 & 2)"; break;
|
||||||
|
case 0x4: formatName = "MPEG 1 Layer 3 (MP3)"; break;
|
||||||
|
case 0x5: formatName = "MPEG2 (multichannel)"; break;
|
||||||
|
case 0x6: formatName = "AAC LC"; break;
|
||||||
|
case 0x7: formatName = "DTS"; break;
|
||||||
|
case 0x8: formatName = "ATRAC"; break;
|
||||||
|
case 0x9: formatName = "One Bit Audio"; break;
|
||||||
|
case 0xa: formatName = "Enhanced AC-3 (DD+)"; break;
|
||||||
|
case 0xb: formatName = "DTS-HD"; break;
|
||||||
|
case 0xc: formatName = "MAT (MLP)"; break;
|
||||||
|
case 0xd: formatName = "DST"; break;
|
||||||
|
case 0xe: formatName = "WMA Pro"; break;
|
||||||
|
case 0xf: formatName = "unknown"; break;
|
||||||
|
}
|
||||||
|
dprintf("\t%s, max channels %d\n", formatName,
|
||||||
|
descr->descr_2_8.max_channels + 1);
|
||||||
|
dprintf("\t\tSupported sample rates (kHz): %s%s%s%s%s%s%s\n",
|
||||||
|
descr->descr_2_8.can_192khz ? "192 " : "",
|
||||||
|
descr->descr_2_8.can_176khz ? "176.4 " : "",
|
||||||
|
descr->descr_2_8.can_96khz ? "96 " : "",
|
||||||
|
descr->descr_2_8.can_88khz ? "88.2 " : "",
|
||||||
|
descr->descr_2_8.can_48khz ? "48 " : "",
|
||||||
|
descr->descr_2_8.can_44khz ? "44.1 " : "",
|
||||||
|
descr->descr_2_8.can_32khz ? "32 " : ""
|
||||||
|
);
|
||||||
|
if (descr->descr.format_code >= 2 && descr->descr.format_code <= 0x8) {
|
||||||
|
dprintf("\t\tMaximum bit rate: %u kHz\n",
|
||||||
|
descr->descr_2_8.maximum_bitrate * 8);
|
||||||
|
} else if (descr->descr.format_code == 0x1) {
|
||||||
|
dprintf("\t\tSupported sample sizes (bits): %s%s%s\n",
|
||||||
|
descr->descr_1.can_24bit ? "24 " : "",
|
||||||
|
descr->descr_1.can_20bit ? "20 " : "",
|
||||||
|
descr->descr_1.can_16bit ? "16 " : ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x2:
|
||||||
|
dprintf("Video data block:\n");
|
||||||
|
for (i = 0; i < dataBlock->length; i++) {
|
||||||
|
uint8 vic = dataBlock->video.vic0;
|
||||||
|
bool native = false;
|
||||||
|
const edid1_std_timing *timing = NULL;
|
||||||
|
if (i > 0)
|
||||||
|
vic = dataBlock->video.vic[i - 1];
|
||||||
|
if (((vic - 1) & 0x40) == 0) {
|
||||||
|
native = (vic & 0x80) != 0;
|
||||||
|
vic = vic & 0x7f;
|
||||||
|
}
|
||||||
|
if (vic > 0 && vic < B_COUNT_OF(cta_mode1_timings)) {
|
||||||
|
timing = &cta_mode1_timings[vic - 1];
|
||||||
|
} else if (vic >= 193 && vic < B_COUNT_OF(cta_mode2_timings) + 193) {
|
||||||
|
timing = &cta_mode2_timings[vic - 193];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timing != NULL) {
|
||||||
|
const char* ratioString = NULL;
|
||||||
|
switch (timing->ratio) {
|
||||||
|
case 1: ratioString = "4:3";
|
||||||
|
break;
|
||||||
|
case 2: ratioString = "5:4";
|
||||||
|
break;
|
||||||
|
case 3: ratioString = "16:9";
|
||||||
|
break;
|
||||||
|
case 4: ratioString = "64:27";
|
||||||
|
break;
|
||||||
|
case 5: ratioString = "256:135";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dprintf("\tVIC %3u %dx%d@%dHz %s%s\n", vic,
|
||||||
|
timing->h_size, timing->v_size, timing->refresh, ratioString,
|
||||||
|
native ? " (native)" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3:
|
||||||
|
{
|
||||||
|
uint32 ouinum = (dataBlock->vendor_specific.ouinum2 << 16)
|
||||||
|
| (dataBlock->vendor_specific.ouinum1 << 8) | dataBlock->vendor_specific.ouinum0;
|
||||||
|
const char* ouinumString = "unknown";
|
||||||
|
if (ouinum == 0x000c03)
|
||||||
|
ouinumString = "HDMI";
|
||||||
|
if (ouinum == 0xc45dd8)
|
||||||
|
ouinumString = "HDMI Forum";
|
||||||
|
dprintf("Vendor specific data block, %06" B_PRIx32 " (%s)\n", ouinum, ouinumString);
|
||||||
|
if (ouinum == 0x000c03) {
|
||||||
|
dprintf("\tSource physical address: %u.%u.%u.%u\n",
|
||||||
|
dataBlock->vendor_specific.hdmi.source_physical_address.a,
|
||||||
|
dataBlock->vendor_specific.hdmi.source_physical_address.b,
|
||||||
|
dataBlock->vendor_specific.hdmi.source_physical_address.c,
|
||||||
|
dataBlock->vendor_specific.hdmi.source_physical_address.d);
|
||||||
|
#define PRINT_HDMI_FLAG(x, s) if (dataBlock->vendor_specific.hdmi. x ) dprintf("\t" s "\n");
|
||||||
|
PRINT_HDMI_FLAG(supports_ai, "Supports_AI");
|
||||||
|
PRINT_HDMI_FLAG(dc_48bit, "DC_48bit");
|
||||||
|
PRINT_HDMI_FLAG(dc_36bit, "DC_36bit");
|
||||||
|
PRINT_HDMI_FLAG(dc_30bit, "DC_30bit");
|
||||||
|
PRINT_HDMI_FLAG(dc_y444, "DC_Y444");
|
||||||
|
PRINT_HDMI_FLAG(dvi_dual, "DVI_DUAL");
|
||||||
|
#undef PRINT_HDMI_FLAG
|
||||||
|
dprintf("\tMaximum TMDS clock: %uMHz\n",
|
||||||
|
dataBlock->vendor_specific.hdmi.max_tmds_clock * 5);
|
||||||
|
if (dataBlock->vendor_specific.hdmi.vic_length > 0)
|
||||||
|
dprintf("\tExtended HDMI video details:\n");
|
||||||
|
for (i = 0; i < dataBlock->vendor_specific.hdmi.vic_length; i++) {
|
||||||
|
const edid1_std_timing *timing = NULL;
|
||||||
|
switch (dataBlock->vendor_specific.hdmi.vic[i]) {
|
||||||
|
case 1: timing = &cta_mode1_timings[94]; break;
|
||||||
|
case 2: timing = &cta_mode1_timings[93]; break;
|
||||||
|
case 3: timing = &cta_mode1_timings[92]; break;
|
||||||
|
case 4: timing = &cta_mode1_timings[97]; break;
|
||||||
|
}
|
||||||
|
if (timing != NULL) {
|
||||||
|
const char* ratioString = NULL;
|
||||||
|
switch (timing->ratio) {
|
||||||
|
case 1: ratioString = "4:3";
|
||||||
|
break;
|
||||||
|
case 2: ratioString = "5:4";
|
||||||
|
break;
|
||||||
|
case 3: ratioString = "16:9";
|
||||||
|
break;
|
||||||
|
case 4: ratioString = "64:27";
|
||||||
|
break;
|
||||||
|
case 5: ratioString = "256:135";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dprintf("\tHDMI VIC %u %dx%d@%dHz %s\n", dataBlock->vendor_specific.hdmi.vic[i],
|
||||||
|
timing->h_size, timing->v_size, timing->refresh, ratioString);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (ouinum == 0xc45dd8) {
|
||||||
|
dprintf("\tVersion: %u\n", dataBlock->vendor_specific.hdmi_forum.version);
|
||||||
|
dprintf("\tMaximum TMDS character rate: %uMHz\n",
|
||||||
|
dataBlock->vendor_specific.hdmi_forum.max_tmds_rate * 5);
|
||||||
|
#define PRINT_HDMIFORUM_FLAG(x, s) if (dataBlock->vendor_specific.hdmi_forum. x ) dprintf("\t" s "\n");
|
||||||
|
PRINT_HDMIFORUM_FLAG(scdc_present, "SCDC Present");
|
||||||
|
PRINT_HDMIFORUM_FLAG(scdc_read_request_capable, "SCDC Read Request Capable");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_cable_status, "Supports Cable Status");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_color_content_bits,
|
||||||
|
"Supports Color Content Bits Per Component Indication");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_scrambling, "Supports scrambling for <= 340 Mcsc");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_3d_independent, "Supports 3D Independent View signaling");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_3d_dual_view, "Supports 3D Dual View signaling");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_3d_osd_disparity, "Supports 3D OSD Disparity signaling");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_uhd_vic, "Supports UHD VIC");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_16bit_deep_color_4_2_0,
|
||||||
|
"Supports 16-bits/component Deep Color 4:2:0 Pixel Encoding");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_12bit_deep_color_4_2_0,
|
||||||
|
"Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding");
|
||||||
|
PRINT_HDMIFORUM_FLAG(supports_10bit_deep_color_4_2_0,
|
||||||
|
"Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding");
|
||||||
|
#undef PRINT_HDMIFORUM_FLAG
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x4:
|
||||||
|
dprintf("Speaker allocation data block\n");
|
||||||
|
#define PRINT_SPEAKER_FLAG(x, s) if (dataBlock->speaker_allocation_map. x ) dprintf("\t" s "\n");
|
||||||
|
PRINT_SPEAKER_FLAG(FL_FR, "FL/FR - Front Left/Right");
|
||||||
|
PRINT_SPEAKER_FLAG(LFE, "LFE1 - Low Frequency Effects 1");
|
||||||
|
PRINT_SPEAKER_FLAG(FC, "FC - Front Center");
|
||||||
|
PRINT_SPEAKER_FLAG(BL_BR, "BL/BR - Back Left/Right");
|
||||||
|
PRINT_SPEAKER_FLAG(BC, "BC - Back Center");
|
||||||
|
PRINT_SPEAKER_FLAG(FLC_FRC, "FLC/FRC - Front Left/Right of Center");
|
||||||
|
PRINT_SPEAKER_FLAG(RLC_RRC, "RLC/RRC - Rear Left/Right of Center - deprecated");
|
||||||
|
PRINT_SPEAKER_FLAG(FLW_FRW, "FLW/FRW - Front Left/Right Wide");
|
||||||
|
PRINT_SPEAKER_FLAG(TpFL_TpFH, "TpFL/TpFR - Top Front Left/Right");
|
||||||
|
PRINT_SPEAKER_FLAG(TpC, "TpC - Top Center");
|
||||||
|
PRINT_SPEAKER_FLAG(TpFC, "TpFC - Top Front Center");
|
||||||
|
PRINT_SPEAKER_FLAG(LS_RS, "LS/RS - Left/Right Surround");
|
||||||
|
PRINT_SPEAKER_FLAG(LFE2, "LFE2 - Low Frequency Effects 2");
|
||||||
|
PRINT_SPEAKER_FLAG(TpBC, "TpBC - Top Back Center");
|
||||||
|
PRINT_SPEAKER_FLAG(SiL_SiR, "SiL/SiR - Side Left/Right");
|
||||||
|
PRINT_SPEAKER_FLAG(TpSiL_TpSiR, "TpSiL/TpSiR - Top Side Left/Right");
|
||||||
|
PRINT_SPEAKER_FLAG(TpBL_TpBR, "TpBL/TpBR - Top Back Left/Right");
|
||||||
|
PRINT_SPEAKER_FLAG(BtFC, "BtFC - Bottom Front Center");
|
||||||
|
PRINT_SPEAKER_FLAG(BtFL_BtFR, "BtFL/BtFR - Bottom Front Left/Right");
|
||||||
|
PRINT_SPEAKER_FLAG(TpLS_TpRS, "TpLS/TpRS - Top Left/Right Surround");
|
||||||
|
PRINT_SPEAKER_FLAG(LSd_RSd, "LSd/RSd - Left/Right Surround Direct");
|
||||||
|
#undef PRINT_SPEAKER_FLAG
|
||||||
|
break;
|
||||||
|
case 0x705:
|
||||||
|
dprintf("Extended tag: Colorimetry data block\n");
|
||||||
|
#define PRINT_COLORIMETRY(x) if (dataBlock->colorimetry. x ) dprintf("\t" #x );
|
||||||
|
PRINT_COLORIMETRY(BT2020RGB);
|
||||||
|
PRINT_COLORIMETRY(BT2020YCC);
|
||||||
|
PRINT_COLORIMETRY(BT2020cYCC);
|
||||||
|
PRINT_COLORIMETRY(opRGB);
|
||||||
|
PRINT_COLORIMETRY(opYCC601);
|
||||||
|
PRINT_COLORIMETRY(sYCC601);
|
||||||
|
PRINT_COLORIMETRY(xvYCC709);
|
||||||
|
PRINT_COLORIMETRY(xvYCC601);
|
||||||
|
PRINT_COLORIMETRY(DCIP3);
|
||||||
|
#undef PRINT_COLORIMETRY
|
||||||
|
dprintf("\n");
|
||||||
|
break;
|
||||||
|
case 0x700:
|
||||||
|
dprintf("Extended tag: Video capability data block\n");
|
||||||
|
dprintf("\tYCbCr quantization: %s\n",
|
||||||
|
dataBlock->video_capability.QY ? "Selectable (via AVI YQ)" : "No Data");
|
||||||
|
dprintf("\tRGB quantization: %s\n",
|
||||||
|
dataBlock->video_capability.QS ? "Selectable (via AVI Q)" : "No Data");
|
||||||
|
dprintf("\tPT scan behaviour: ");
|
||||||
|
switch (dataBlock->video_capability.S_PT) {
|
||||||
|
case 0: dprintf("No Data\n"); break;
|
||||||
|
case 1: dprintf("Always Overscanned\n"); break;
|
||||||
|
case 2: dprintf("Always Underscanned\n"); break;
|
||||||
|
case 3: dprintf("Supports both over- and underscan\n"); break;
|
||||||
|
}
|
||||||
|
dprintf("\tIT scan behaviour: ");
|
||||||
|
switch (dataBlock->video_capability.S_IT) {
|
||||||
|
case 0: dprintf("IT Video Formats not supported\n"); break;
|
||||||
|
case 1: dprintf("Always Overscanned\n"); break;
|
||||||
|
case 2: dprintf("Always Underscanned\n"); break;
|
||||||
|
case 3: dprintf("Supports both over- and underscan\n"); break;
|
||||||
|
}
|
||||||
|
dprintf("\tCE scan behaviour: ");
|
||||||
|
switch (dataBlock->video_capability.S_CE) {
|
||||||
|
case 0: dprintf("CE Video Formats not supported\n"); break;
|
||||||
|
case 1: dprintf("Always Overscanned\n"); break;
|
||||||
|
case 2: dprintf("Always Underscanned\n"); break;
|
||||||
|
case 3: dprintf("Supports both over- and underscan\n"); break;
|
||||||
|
}
|
||||||
|
case 0x706:
|
||||||
|
dprintf("Extended tag: HDR static metadata data block\n");
|
||||||
|
#define PRINT_SMD_FLAG(x, s) if (dataBlock->hdr_static_metadata. x ) dprintf("\t\t" s "\n");
|
||||||
|
dprintf("\tSupported Electro-Optical Transfer Functions:\n");
|
||||||
|
PRINT_SMD_FLAG(ET_0, "Traditional gamma - SDR Luminance Range");
|
||||||
|
PRINT_SMD_FLAG(ET_1, "Traditional gamma - HDR Luminance Range");
|
||||||
|
PRINT_SMD_FLAG(ET_2, "SMPTE ST 2084");
|
||||||
|
PRINT_SMD_FLAG(ET_3, "Hybrid Log-Gamma");
|
||||||
|
dprintf("\tSupported Static Metadata Descriptors:\n");
|
||||||
|
PRINT_SMD_FLAG(SM_0, "Static Metadata Type 1");
|
||||||
|
#undef PRINT_SMD_FLAG
|
||||||
|
if (dataBlock->length >= 4) {
|
||||||
|
dprintf("\tDesired content max luminance: %u\n",
|
||||||
|
dataBlock->hdr_static_metadata.desired_content_max_luminance);
|
||||||
|
}
|
||||||
|
if (dataBlock->length >= 5) {
|
||||||
|
dprintf("\tDesired content max frame-average luminance: %u\n",
|
||||||
|
dataBlock->hdr_static_metadata.desired_content_max_frame_average_luminance);
|
||||||
|
}
|
||||||
|
if (dataBlock->length >= 6) {
|
||||||
|
dprintf("\tDesired content min luminance: %u\n",
|
||||||
|
dataBlock->hdr_static_metadata.desired_content_min_luminance);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x707:
|
||||||
|
dprintf("Extended tag: HDR dynamic metadata data block\n");
|
||||||
|
break;
|
||||||
|
case 0x708:
|
||||||
|
dprintf("Extended tag: Native Video Resolution data block\n");
|
||||||
|
break;
|
||||||
|
case 0x711:
|
||||||
|
dprintf("Vendor-Specific Audio Data Block\n");
|
||||||
|
case 0x70f:
|
||||||
|
dprintf("Extended tag: YCbCr 4:2:0 capability map data block\n");
|
||||||
|
for (i = 0; i < dataBlock->length - 1; i++) {
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
if ((dataBlock->YCbCr_4_2_0_capability_map.bitmap[i] & (1 << j)) != 0)
|
||||||
|
dprintf("\tVSD Index %u\n", i * 8 + j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintf("unknown tag 0x%x\n", tagCode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
edid_dump(edid1_info *edid)
|
edid_dump(edid1_info *edid)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
dprintf("EDID info:\n");
|
dprintf("EDID info:\n");
|
||||||
dprintf(" Vendor: %s\n", edid->vendor.manufacturer);
|
dprintf(" EDID version: %d.%d\n", edid->version.version, edid->version.revision);
|
||||||
dprintf(" Product ID: %d\n", (int)edid->vendor.prod_id);
|
dprintf(" Vendor: %s Product ID: 0x%x\n", edid->vendor.manufacturer, edid->vendor.prod_id);
|
||||||
dprintf(" Serial #: %d\n", (int)edid->vendor.serial);
|
dprintf(" Serial #: %" B_PRIu32 "\n", edid->vendor.serial);
|
||||||
dprintf(" Produced in week/year: %d/%d\n", edid->vendor.week,
|
dprintf(" Produced in week/year: %u/%u\n", edid->vendor.week, edid->vendor.year);
|
||||||
edid->vendor.year);
|
|
||||||
|
|
||||||
dprintf(" EDID version: %d.%d\n", edid->version.version,
|
|
||||||
edid->version.revision);
|
|
||||||
|
|
||||||
dprintf(" Type: %s\n", edid->display.input_type != 0 ? "Digital" : "Analog");
|
dprintf(" Type: %s\n", edid->display.input_type != 0 ? "Digital" : "Analog");
|
||||||
if (edid->display.input_type != 0)
|
if (edid->display.input_type != 0 && edid->version.revision >= 4) {
|
||||||
dprintf(" Digital Bit Depth: %d\n", edid->display.digital_params.bit_depth);
|
dprintf(" Digital Bit Depth: %d\n", edid->display.digital_params.bit_depth);
|
||||||
|
switch (edid->display.digital_params.interface) {
|
||||||
|
case 0x1: dprintf(" DVI interface\n"); break;
|
||||||
|
case 0x2: dprintf(" HDMIa interface\n"); break;
|
||||||
|
case 0x3: dprintf(" HDMIb interface\n"); break;
|
||||||
|
case 0x4: dprintf(" MDDI interface\n"); break;
|
||||||
|
case 0x5: dprintf(" DisplayPort interface\n"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
dprintf(" Size: %d cm x %d cm\n", edid->display.h_size,
|
dprintf(" Size: %d cm x %d cm\n", edid->display.h_size,
|
||||||
edid->display.v_size);
|
edid->display.v_size);
|
||||||
dprintf(" Gamma=%.3f\n", (edid->display.gamma + 100) / 100.0);
|
dprintf(" Gamma=%.2f\n", (edid->display.gamma + 100) / 100.0);
|
||||||
dprintf(" White (X,Y)=(%.3f,%.3f)\n", edid->display.white_x / 1024.0,
|
if (edid->display.gtf_supported) {
|
||||||
|
if (edid->version.revision >= 4)
|
||||||
|
dprintf(" Display supports continuous frequency\n");
|
||||||
|
else
|
||||||
|
dprintf(" GTF Timings supported\n");
|
||||||
|
}
|
||||||
|
dprintf(" Red (X,Y)=(%.4f,%.4f)\n", edid->display.red_x / 1024.0,
|
||||||
|
edid->display.red_y / 1024.0);
|
||||||
|
dprintf(" Green (X,Y)=(%.4f,%.4f)\n", edid->display.green_x / 1024.0,
|
||||||
|
edid->display.green_y / 1024.0);
|
||||||
|
dprintf(" Blue (X,Y)=(%.4f,%.4f)\n", edid->display.blue_x / 1024.0,
|
||||||
|
edid->display.blue_y / 1024.0);
|
||||||
|
dprintf(" White (X,Y)=(%.4f,%.4f)\n", edid->display.white_x / 1024.0,
|
||||||
edid->display.white_y / 1024.0);
|
edid->display.white_y / 1024.0);
|
||||||
|
|
||||||
dprintf("Supported Future Video Modes:\n");
|
dprintf("Supported Future Video Modes:\n");
|
||||||
@@ -147,36 +673,37 @@ edid_dump(edid1_info *edid)
|
|||||||
case EDID1_IS_DETAILED_TIMING:
|
case EDID1_IS_DETAILED_TIMING:
|
||||||
{
|
{
|
||||||
edid1_detailed_timing *timing = &monitor->data.detailed_timing;
|
edid1_detailed_timing *timing = &monitor->data.detailed_timing;
|
||||||
if (timing->h_active + timing->h_blank == 0
|
edid_timing_dump(timing, true);
|
||||||
|| timing->v_active + timing->v_blank == 0) {
|
|
||||||
dprintf("Invalid video mode (%dx%d)\n", timing->h_active,
|
|
||||||
timing->v_active);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
dprintf("Additional Video Mode (%dx%d@%dHz):\n",
|
|
||||||
timing->h_active, timing->v_active,
|
|
||||||
(timing->pixel_clock * 10000
|
|
||||||
/ (timing->h_active + timing->h_blank)
|
|
||||||
/ (timing->v_active + timing->v_blank)));
|
|
||||||
// Refresh rate = pixel clock in MHz / Htotal / Vtotal
|
|
||||||
|
|
||||||
dprintf("clock=%f MHz\n", timing->pixel_clock / 100.0);
|
|
||||||
dprintf("h: (%d, %d, %d, %d)\n",
|
|
||||||
timing->h_active, timing->h_active + timing->h_sync_off,
|
|
||||||
timing->h_active + timing->h_sync_off
|
|
||||||
+ timing->h_sync_width,
|
|
||||||
timing->h_active + timing->h_blank);
|
|
||||||
dprintf("v: (%d, %d, %d, %d)\n",
|
|
||||||
timing->v_active, timing->v_active + timing->v_sync_off,
|
|
||||||
timing->v_active + timing->v_sync_off
|
|
||||||
+ timing->v_sync_width,
|
|
||||||
timing->v_active + timing->v_blank);
|
|
||||||
dprintf("size: %.1f cm x %.1f cm\n",
|
|
||||||
timing->h_size / 10.0, timing->v_size / 10.0);
|
|
||||||
dprintf("border: %.1f cm x %.1f cm\n",
|
|
||||||
timing->h_border / 10.0, timing->v_border / 10.0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (edid->num_sections > 0)
|
||||||
|
dprintf("Extension blocks: %u\n", edid->num_sections);
|
||||||
|
if (edid->cta_block.tag == 0x2) {
|
||||||
|
dprintf("CTA extension block\n");
|
||||||
|
dprintf(" Extension version: %u\n", edid->cta_block.revision);
|
||||||
|
dprintf(" Number of native detailed modes: %u\n", edid->cta_block.num_native_detailed);
|
||||||
|
if (edid->cta_block.ycbcr422_supported)
|
||||||
|
dprintf(" Supports YCbCr 4:2:2\n");
|
||||||
|
if (edid->cta_block.ycbcr444_supported)
|
||||||
|
dprintf(" Supports YCbCr 4:4:4\n");
|
||||||
|
if (edid->cta_block.audio_supported)
|
||||||
|
dprintf(" Basic audio support\n");
|
||||||
|
if (edid->cta_block.underscan)
|
||||||
|
dprintf(" Underscans PC formats by default\n");
|
||||||
|
if (edid->cta_block.revision >= 3) {
|
||||||
|
for (i = 0; i < edid->cta_block.num_data_blocks; i++) {
|
||||||
|
edid_cta_datablock_dump(&edid->cta_block.data_blocks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
edid_timing_dump(&edid->cta_block.detailed_timing[i], false);
|
||||||
|
}
|
||||||
|
if (edid->displayid_block.tag == 0x70) {
|
||||||
|
dprintf("DisplayID extension block\n");
|
||||||
|
dprintf(" Extension version: %u\n", edid->displayid_block.version);
|
||||||
|
dprintf(" Extension count: %u\n", edid->displayid_block.extension_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user