Max' EDID generation implementation in C.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
7.1 KiB

#ifndef INCLUDED_MAX_EDID
#define INCLUDED_MAX_EDID
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "frozen/frozen.h"
#define EDID_LEN 128
#define EDID_DISPLAY_DESCRIPTOR_DATA_LEN 13
// EDID data structure
typedef struct __attribute__ (( packed )) {
uint8_t x_resolution;
uint8_t vertical_frequency:6;
uint8_t aspect_ratio :2;
} standard_timing_information_t;
typedef struct __attribute__ (( packed )) {
uint16_t pixel_clock; // 0-1
uint8_t horizontal_active_pixels_lsbs; // 2
uint8_t horizontal_blanking_pixels_lsbs; // 3
uint8_t horizontal_blanking_pixels_msbs :4; // 4
uint8_t horizontal_active_pixels_msbs :4;
uint8_t vertical_active_lines_lsbs; // 5
uint8_t vertical_blanking_lines_lsbs; // 6
uint8_t vertical_blanking_lines_msbs :4; // 7
uint8_t vertical_active_lines_msbs :4;
uint8_t horizontal_front_porch_pixels_lsbs; // 8
uint8_t horizontal_sync_pulse_pixels_lsbs; // 9
uint8_t vertical_sync_pulse_lines_lsbs :4; // 10
uint8_t vertical_front_porch_lines_lsbs :4;
uint8_t vertical_sync_pulse_lines_msbs :2; // 11
uint8_t vertical_front_porch_lines_msbs :2;
uint8_t horizontal_sync_pulse_pixels_msbs :2;
uint8_t horizontal_front_porch_pixels_msbs :2;
uint8_t horizontal_image_size_lsbs; // 12
uint8_t vertical_image_size_lsbs;
uint8_t vertical_image_size_msbs :4;
uint8_t horizontal_image_size_msbs :4;
uint8_t horizontal_border_pixels;
uint8_t vertical_border_lines;
// Feature bitmap
union __attribute__ (( packed )) {
struct __attribute__ (( packed )) {
uint8_t stereo_mode_lsb :1;
uint8_t sync_on_red_blue :1;
uint8_t vertical_sync_serration :1;
uint8_t sync_type :1;
uint8_t analog_sync :1;
uint8_t stereo_mode_msbs :2;
uint8_t interlaced :1;
} analog;
struct __attribute__ (( packed )) {
uint8_t stereo_mode_lsb :1;
uint8_t reserved :1;
uint8_t vertical_sync_polarity :1;
uint8_t digital_composite_sync :2;
uint8_t stereo_mode_msbs :2;
uint8_t interlaced :1;
} digital_composite;
struct __attribute__ (( packed )) {
uint8_t stereo_mode_lsb :1;
uint8_t horizontal_sync_polarity :1;
uint8_t vertical_sync_serration :1;
uint8_t digital_seperate_sync :2;
uint8_t stereo_mode_msbs :2;
uint8_t interlaced :1;
} digital_seperate;
} features;
} detailed_timing_descriptor_t;
typedef struct __attribute__ (( packed )) {
uint16_t display_descriptor;
uint8_t reserved;
uint8_t display_range_limits_descriptor;
struct __attribute__ (( packed )) {
uint8_t vertical :2;
uint8_t horizontal :2;
uint8_t reserved :4;
} rate_offsets;
struct __attribute__ (( packed )) {
uint8_t minimum;
uint8_t maximum;
} vertical_field_rate;
struct __attribute__ (( packed )) {
uint8_t minimum;
uint8_t maximum;
} horizontal_line_rate;
uint8_t maximum_pixel_clock_mhz; // In 10 MHz units
uint8_t extended_timing_information_type;
uint8_t video_timing_params[7];
} range_limits_descriptor_t;
typedef struct __attribute__ (( packed )) {
uint16_t display_descriptor;
uint8_t reserved0;
uint8_t descriptor_type;
uint8_t reserved1;
uint8_t descriptor_data[EDID_DISPLAY_DESCRIPTOR_DATA_LEN];
} display_descriptor_t;
typedef struct __attribute__ (( packed )) {
/*! Header information, 20 bytes */
struct __attribute__ (( packed )) {
uint64_t preamble;
uint8_t manufacturer_id[2];
uint16_t product_code;
uint32_t serial_number;
uint8_t week_of_manufacture;
uint8_t year_of_manufacture;
uint8_t edid_version;
uint8_t edid_revision;
} header;
/*! Basic display parameters, 5 bytes */
struct __attribute__ (( packed )) {
union __attribute__ (( packed )) {
struct __attribute__ (( packed )) {
uint8_t video_interface : 4;
uint8_t bit_depth : 3;
uint8_t input_type : 1; // 1 for digital
} digital;
struct __attribute__ (( packed )) {
uint8_t vsync_serrated: 1;
uint8_t sync_on_green : 1;
uint8_t composite_sync: 1;
uint8_t seperate_sync : 1;
uint8_t blank_to_black: 1;
uint8_t levels : 2;
uint8_t input_type : 1; // 0 for analog
} analog;
} video_input_parameters; // 1 byte
uint8_t horizontal_screen_size;
uint8_t vertical_screen_size;
uint8_t gamma;
struct __attribute__ (( packed )) {
uint8_t continuous_timings : 1;
uint8_t preferred_timing_mode : 1;
uint8_t standard_srgb : 1;
uint8_t display_type : 2;
uint8_t dpms_active_off_supported : 1;
uint8_t dpms_suspend_supported : 1;
uint8_t dpms_standby_supported : 1;
} features;
} basic_display_parameters;
/*! Chromaticity coordinates. 10-bit CIE 1931 xy coordinates for red, green,
* blue, and white point, 10 bytes */
struct __attribute__ (( packed )) {
struct __attribute__ (( packed )) {
uint8_t green_y : 2;
uint8_t green_x : 2;
uint8_t red_y : 2;
uint8_t red_x : 2;
} red_green_lsbs;
struct __attribute__ (( packed )) {
uint8_t white_y : 2;
uint8_t white_x : 2;
uint8_t blue_y : 2;
uint8_t blue_x : 2;
} blue_white_lsbs;
uint8_t red_x_msbs;
uint8_t red_y_msbs;
uint8_t green_x_msbs;
uint8_t green_y_msbs;
uint8_t blue_x_msbs;
uint8_t blue_y_msbs;
uint8_t white_x_msbs;
uint8_t white_y_msbs;
} chromaticity_coordinates;
/*! Established timing bitmap. Supported bitmap for (formerly) very common
timing modes. 3 bytes */
struct __attribute__ (( packed )) {
uint8_t m800_600_60 : 1;
uint8_t m800_600_56 : 1;
uint8_t m640_480_75 : 1;
uint8_t m640_480_72 : 1;
uint8_t m640_480_67 : 1;
uint8_t m640_480_60 : 1;
uint8_t m720_400_88 : 1;
uint8_t m720_400_70 : 1;
uint8_t m1280_1024_75: 1;
uint8_t m1024_768_75 : 1;
uint8_t m1024_768_70 : 1;
uint8_t m1024_768_60 : 1;
uint8_t m1024_768_87 : 1;
uint8_t m832_624_75 : 1;
uint8_t m800_600_75 : 1;
uint8_t m800_600_72 : 1;
uint8_t reserved : 7;
uint8_t m1152_870_75 : 1;
} common_timing_modes;
/*! Standard timing information. Up to 8 2-byte fields describing standard
display modes. Unused fields are filled with 01 01 hex. 16 bytes */
standard_timing_information_t timings[8];
detailed_timing_descriptor_t detailed_timing_descriptor;
range_limits_descriptor_t range_limits_descriptor;
display_descriptor_t display_name_descriptor;
display_descriptor_t display_serial_number_descriptor;
uint8_t number_extensions;
uint8_t checksum;
} edid_t;
// Interface
int generate_edid(edid_t* const edid, const char* const filename);
#endif