edid: Prepare types for wider exposure

The EDID code is copy from elsewhere, without adapting to conventions
regarding e.g. API and types. Clean this up a bit, as EDID information
will be kept around longer when possible, to be used e.g. by color
management.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2351>
This commit is contained in:
Jonas Ådahl 2021-11-08 14:56:35 +01:00
parent 1f03a20939
commit de2443bc3e
3 changed files with 98 additions and 71 deletions

View File

@ -46,7 +46,7 @@ get_bits (int in, int begin, int end)
} }
static int static int
decode_header (const uchar *edid) decode_header (const uint8_t *edid)
{ {
if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0) if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
return TRUE; return TRUE;
@ -54,7 +54,8 @@ decode_header (const uchar *edid)
} }
static int static int
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info) decode_vendor_and_product_identification (const uint8_t *edid,
MetaEdidInfo *info)
{ {
int is_model_year; int is_model_year;
@ -109,7 +110,8 @@ decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
} }
static int static int
decode_edid_version (const uchar *edid, MonitorInfo *info) decode_edid_version (const uint8_t *edid,
MetaEdidInfo *info)
{ {
info->major_version = edid[0x12]; info->major_version = edid[0x12];
info->minor_version = edid[0x13]; info->minor_version = edid[0x13];
@ -118,7 +120,8 @@ decode_edid_version (const uchar *edid, MonitorInfo *info)
} }
static int static int
decode_display_parameters (const uchar *edid, MonitorInfo *info) decode_display_parameters (const uint8_t *edid,
MetaEdidInfo *info)
{ {
/* Digital vs Analog */ /* Digital vs Analog */
info->is_digital = get_bit (edid[0x14], 7); info->is_digital = get_bit (edid[0x14], 7);
@ -132,9 +135,14 @@ decode_display_parameters (const uchar *edid, MonitorInfo *info)
-1, 6, 8, 10, 12, 14, 16, -1 -1, 6, 8, 10, 12, 14, 16, -1
}; };
static const Interface interfaces[6] = static const MetaEdidInterface interfaces[6] =
{ {
UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT META_EDID_INTERFACE_UNDEFINED,
META_EDID_INTERFACE_DVI,
META_EDID_INTERFACE_HDMI_A,
META_EDID_INTERFACE_HDMI_B,
META_EDID_INTERFACE_MDDI,
META_EDID_INTERFACE_DISPLAY_PORT
}; };
bits = get_bits (edid[0x14], 4, 6); bits = get_bits (edid[0x14], 4, 6);
@ -145,7 +153,7 @@ decode_display_parameters (const uchar *edid, MonitorInfo *info)
if (bits <= 5) if (bits <= 5)
info->connector.digital.interface = interfaces[bits]; info->connector.digital.interface = interfaces[bits];
else else
info->connector.digital.interface = UNDEFINED; info->connector.digital.interface = META_EDID_INTERFACE_UNDEFINED;
} }
else else
{ {
@ -220,9 +228,12 @@ decode_display_parameters (const uchar *edid, MonitorInfo *info)
else else
{ {
int bits = get_bits (edid[0x18], 3, 4); int bits = get_bits (edid[0x18], 3, 4);
ColorType color_type[4] = MetaEdidColorType color_type[4] =
{ {
MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR META_EDID_COLOR_TYPE_MONOCHROME,
META_EDID_COLOR_TYPE_RGB,
META_EDID_COLOR_TYPE_OTHER_COLOR,
META_EDID_COLOR_TYPE_UNDEFINED
}; };
info->connector.analog.color_type = color_type[bits]; info->connector.analog.color_type = color_type[bits];
@ -253,7 +264,8 @@ decode_fraction (int high, int low)
} }
static int static int
decode_color_characteristics (const uchar *edid, MonitorInfo *info) decode_color_characteristics (const uint8_t *edid,
MetaEdidInfo *info)
{ {
info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7)); info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4)); info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
@ -268,9 +280,10 @@ decode_color_characteristics (const uchar *edid, MonitorInfo *info)
} }
static int static int
decode_established_timings (const uchar *edid, MonitorInfo *info) decode_established_timings (const uint8_t *edid,
MetaEdidInfo *info)
{ {
static const Timing established[][8] = static const MetaEdidTiming established[][8] =
{ {
{ {
{ 800, 600, 60 }, { 800, 600, 60 },
@ -321,7 +334,8 @@ decode_established_timings (const uchar *edid, MonitorInfo *info)
} }
static int static int
decode_standard_timings (const uchar *edid, MonitorInfo *info) decode_standard_timings (const uint8_t *edid,
MetaEdidInfo *info)
{ {
int i; int i;
@ -353,7 +367,9 @@ decode_standard_timings (const uchar *edid, MonitorInfo *info)
} }
static void static void
decode_lf_string (const uchar *s, int n_chars, char *result) decode_lf_string (const uint8_t *s,
int n_chars,
char *result)
{ {
int i; int i;
for (i = 0; i < n_chars; ++i) for (i = 0; i < n_chars; ++i)
@ -376,8 +392,8 @@ decode_lf_string (const uchar *s, int n_chars, char *result)
} }
static void static void
decode_display_descriptor (const uchar *desc, decode_display_descriptor (const uint8_t *desc,
MonitorInfo *info) MetaEdidInfo *info)
{ {
switch (desc[0x03]) switch (desc[0x03])
{ {
@ -414,15 +430,22 @@ decode_display_descriptor (const uchar *desc,
} }
static void static void
decode_detailed_timing (const uchar *timing, decode_detailed_timing (const uint8_t *timing,
DetailedTiming *detailed) MetaEdidDetailedTiming *detailed)
{ {
int bits; int bits;
StereoType stereo[] = MetaEdidStereoType stereo[] =
{ {
NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT, META_EDID_STEREO_TYPE_NO_STEREO,
TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN, META_EDID_STEREO_TYPE_NO_STEREO,
FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE META_EDID_STEREO_TYPE_FIELD_RIGHT,
META_EDID_STEREO_TYPE_FIELD_LEFT,
META_EDID_STEREO_TYPE_TWO_WAY_RIGHT_ON_EVEN,
META_EDID_STEREO_TYPE_TWO_WAY_LEFT_ON_EVEN,
META_EDID_STEREO_TYPE_FOUR_WAY_INTERLEAVED,
META_EDID_STEREO_TYPE_SIDE_BY_SIDE
}; };
detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000; detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
@ -477,7 +500,8 @@ decode_detailed_timing (const uchar *timing,
} }
static int static int
decode_descriptors (const uchar *edid, MonitorInfo *info) decode_descriptors (const uint8_t *edid,
MetaEdidInfo *info)
{ {
int i; int i;
int timing_idx; int timing_idx;
@ -504,11 +528,11 @@ decode_descriptors (const uchar *edid, MonitorInfo *info)
} }
static void static void
decode_check_sum (const uchar *edid, decode_check_sum (const uint8_t *edid,
MonitorInfo *info) MetaEdidInfo *info)
{ {
int i; int i;
uchar check = 0; uint8_t check = 0;
for (i = 0; i < 128; ++i) for (i = 0; i < 128; ++i)
check += edid[i]; check += edid[i];
@ -516,10 +540,12 @@ decode_check_sum (const uchar *edid,
info->checksum = check; info->checksum = check;
} }
MonitorInfo * MetaEdidInfo *
decode_edid (const uchar *edid) meta_edid_info_new_parse (const uint8_t *edid)
{ {
MonitorInfo *info = g_new0 (MonitorInfo, 1); MetaEdidInfo *info;
info = g_new0 (MetaEdidInfo, 1);
decode_check_sum (edid, info); decode_check_sum (edid, info);

View File

@ -25,48 +25,49 @@
#ifndef EDID_H #ifndef EDID_H
#define EDID_H #define EDID_H
typedef unsigned char uchar; #include <stdint.h>
typedef struct MonitorInfo MonitorInfo;
typedef struct Timing Timing; typedef struct _MetaEdidInfo MetaEdidInfo;
typedef struct DetailedTiming DetailedTiming; typedef struct _MetaEdidTiming MetaEdidTiming;
typedef struct _MetaEdidDetailedTiming MetaEdidDetailedTiming;
typedef enum typedef enum
{ {
UNDEFINED, META_EDID_INTERFACE_UNDEFINED,
DVI, META_EDID_INTERFACE_DVI,
HDMI_A, META_EDID_INTERFACE_HDMI_A,
HDMI_B, META_EDID_INTERFACE_HDMI_B,
MDDI, META_EDID_INTERFACE_MDDI,
DISPLAY_PORT META_EDID_INTERFACE_DISPLAY_PORT
} Interface; } MetaEdidInterface;
typedef enum typedef enum
{ {
UNDEFINED_COLOR, META_EDID_COLOR_TYPE_UNDEFINED,
MONOCHROME, META_EDID_COLOR_TYPE_MONOCHROME,
RGB, META_EDID_COLOR_TYPE_RGB,
OTHER_COLOR META_EDID_COLOR_TYPE_OTHER_COLOR
} ColorType; } MetaEdidColorType;
typedef enum typedef enum
{ {
NO_STEREO, META_EDID_STEREO_TYPE_NO_STEREO,
FIELD_RIGHT, META_EDID_STEREO_TYPE_FIELD_RIGHT,
FIELD_LEFT, META_EDID_STEREO_TYPE_FIELD_LEFT,
TWO_WAY_RIGHT_ON_EVEN, META_EDID_STEREO_TYPE_TWO_WAY_RIGHT_ON_EVEN,
TWO_WAY_LEFT_ON_EVEN, META_EDID_STEREO_TYPE_TWO_WAY_LEFT_ON_EVEN,
FOUR_WAY_INTERLEAVED, META_EDID_STEREO_TYPE_FOUR_WAY_INTERLEAVED,
SIDE_BY_SIDE META_EDID_STEREO_TYPE_SIDE_BY_SIDE
} StereoType; } MetaEdidStereoType;
struct Timing struct _MetaEdidTiming
{ {
int width; int width;
int height; int height;
int frequency; int frequency;
}; };
struct DetailedTiming struct _MetaEdidDetailedTiming
{ {
int pixel_clock; int pixel_clock;
int h_addr; int h_addr;
@ -82,7 +83,7 @@ struct DetailedTiming
int right_border; int right_border;
int top_border; int top_border;
int interlaced; int interlaced;
StereoType stereo; MetaEdidStereoType stereo;
int digital_sync; int digital_sync;
union union
@ -104,7 +105,7 @@ struct DetailedTiming
} connector; } connector;
}; };
struct MonitorInfo struct _MetaEdidInfo
{ {
int checksum; int checksum;
char manufacturer_code[4]; char manufacturer_code[4];
@ -125,7 +126,7 @@ struct MonitorInfo
struct struct
{ {
int bits_per_primary; int bits_per_primary;
Interface interface; MetaEdidInterface interface;
int rgb444; int rgb444;
int ycrcb444; int ycrcb444;
int ycrcb422; int ycrcb422;
@ -143,7 +144,7 @@ struct MonitorInfo
int composite_sync_on_h; int composite_sync_on_h;
int composite_sync_on_green; int composite_sync_on_green;
int serration_on_vsync; int serration_on_vsync;
ColorType color_type; MetaEdidColorType color_type;
} analog; } analog;
} connector; } connector;
@ -170,11 +171,11 @@ struct MonitorInfo
double white_x; double white_x;
double white_y; double white_y;
Timing established[24]; /* Terminated by 0x0x0 */ MetaEdidTiming established[24]; /* Terminated by 0x0x0 */
Timing standard[8]; MetaEdidTiming standard[8];
int n_detailed_timings; int n_detailed_timings;
DetailedTiming detailed_timings[4]; /* If monitor has a preferred MetaEdidDetailedTiming detailed_timings[4]; /* If monitor has a preferred
* mode, it is the first one * mode, it is the first one
* (whether it has, is * (whether it has, is
* determined by the * determined by the
@ -188,6 +189,6 @@ struct MonitorInfo
char dsc_string[14]; /* Unspecified ASCII data */ char dsc_string[14]; /* Unspecified ASCII data */
}; };
MonitorInfo *decode_edid (const uchar *data); MetaEdidInfo *meta_edid_info_new_parse (const uint8_t *data);
#endif #endif

View File

@ -289,13 +289,13 @@ void
meta_output_info_parse_edid (MetaOutputInfo *output_info, meta_output_info_parse_edid (MetaOutputInfo *output_info,
GBytes *edid) GBytes *edid)
{ {
MonitorInfo *parsed_edid; MetaEdidInfo *parsed_edid;
size_t len; size_t len;
if (!edid) if (!edid)
goto out; goto out;
parsed_edid = decode_edid (g_bytes_get_data (edid, &len)); parsed_edid = meta_edid_info_new_parse (g_bytes_get_data (edid, &len));
if (parsed_edid) if (parsed_edid)
{ {