Add high refresh rate and 1366x768 modes to DDC

This commit is contained in:
RichardG867
2020-11-25 19:10:15 -03:00
parent 0fbb94df2a
commit 6a097f78b4

View File

@@ -25,10 +25,29 @@
#include <86box/i2c.h>
#define STD_TIMING(idx, width, aspect_ratio) do { \
edid->standard_timings[idx].horiz_pixels = ((width) >> 3) - 31; \
edid->standard_timings[idx].aspect_ratio_refresh_rate = (aspect_ratio) << 6; /* 60 Hz */ \
} while (0)
#define PIXEL_MM(px) ((uint16_t) (((px) * 25.4) / 96))
#define STANDARD_TIMING(slot, width, aspect_ratio, refresh) do { \
edid->slot.horiz_pixels = ((width) >> 3) - 31; \
edid->slot.aspect_ratio_refresh_rate = ((aspect_ratio) << 6) | ((refresh) - 60); \
} while (0)
#define DETAILED_TIMING(slot, clk, width, height, hblank, vblank, hfp, hsp, vfp, vsp) do { \
edid->slot.pixel_clock_lsb = ((clk) / 10) & 0xff; \
edid->slot.pixel_clock_msb = ((clk) / 10) >> 8; \
edid->slot.h_active_lsb = (width) & 0xff; \
edid->slot.h_blank_lsb = (hblank) & 0xff; \
edid->slot.h_active_blank_msb = (((width) >> 4) & 0xf0) | (((hblank) >> 8) & 0x0f); \
edid->slot.v_active_lsb = (height) & 0xff; \
edid->slot.v_blank_lsb = (vblank) & 0xff; \
edid->slot.v_active_blank_msb = (((height) >> 4) & 0xf0) | (((vblank) >> 8) & 0x0f); \
edid->slot.h_front_porch_lsb = (hfp) & 0xff; \
edid->slot.h_sync_pulse_lsb = (hsp) & 0xff; \
edid->slot.v_front_porch_sync_pulse_lsb = (((vfp) & 0x0f) << 4) | ((vsp) & 0x0f); \
edid->slot.hv_front_porch_sync_pulse_msb = (((hfp) >> 2) & 0x03) | (((hsp) >> 4) & 0x03) | (((vfp) >> 6) & 0x03) | (((vsp) >> 8) & 0x03); \
edid->slot.h_size_lsb = PIXEL_MM(width) & 0xff; \
edid->slot.v_size_lsb = PIXEL_MM(height) & 0xff; \
edid->slot.hv_size_msb = ((PIXEL_MM(width) >> 4) & 0xf0) | ((PIXEL_MM(height) >> 8) & 0x0f); \
} while (0)
enum {
STD_ASPECT_16_10 = 0x0,
@@ -112,6 +131,7 @@ void *
ddc_init(void *i2c)
{
edid_t *edid = malloc(sizeof(edid_t));
uint8_t *edid_bytes = (uint8_t *) edid;
memset(edid, 0, sizeof(edid_t));
memset(&edid->magic[1], 0xff, sizeof(edid->magic) - 2);
@@ -140,34 +160,23 @@ ddc_init(void *i2c)
memset(&edid->established_timings, 0xff, sizeof(edid->established_timings)); /* all enabled */
#if 0
memset(&edid->standard_timings, 0x01, sizeof(edid->standard_timings)); /* pad unused entries */
#endif
STD_TIMING(0, 1280, STD_ASPECT_16_9); /* 1280x720 */
STD_TIMING(1, 1280, STD_ASPECT_16_10); /* 1280x800 */
STD_TIMING(2, 1366, STD_ASPECT_16_9); /* 1360x768 (closest to 1366x768) */
STD_TIMING(3, 1440, STD_ASPECT_16_10); /* 1440x900 */
STD_TIMING(4, 1600, STD_ASPECT_16_9); /* 1600x900 */
STD_TIMING(5, 1680, STD_ASPECT_16_10); /* 1680x1050 */
STD_TIMING(6, 1920, STD_ASPECT_16_9); /* 1920x1080 */
STD_TIMING(7, 2048, STD_ASPECT_4_3); /* 2048x1536 */
/* 60 Hz timings */
STANDARD_TIMING(standard_timings[0], 1280, STD_ASPECT_16_9, 60); /* 1280x720 */
STANDARD_TIMING(standard_timings[1], 1280, STD_ASPECT_16_10, 60); /* 1280x800 */
STANDARD_TIMING(standard_timings[2], 1366, STD_ASPECT_16_9, 60); /* 1360x768 (closest to 1366x768) */
STANDARD_TIMING(standard_timings[3], 1440, STD_ASPECT_16_10, 60); /* 1440x900 */
STANDARD_TIMING(standard_timings[4], 1600, STD_ASPECT_16_9, 60); /* 1600x900 */
STANDARD_TIMING(standard_timings[5], 1680, STD_ASPECT_16_10, 60); /* 1680x1050 */
STANDARD_TIMING(standard_timings[6], 1920, STD_ASPECT_16_9, 60); /* 1920x1080 */
STANDARD_TIMING(standard_timings[7], 2048, STD_ASPECT_4_3, 60); /* 2048x1536 */
/* Detailed timings for the preferred mode of 800x600 @ 60 Hz */
edid->detailed_timings[0].pixel_clock_lsb = 4000 & 0xff; /* 40.000 MHz */
edid->detailed_timings[0].pixel_clock_msb = 4000 >> 8;
edid->detailed_timings[0].h_active_lsb = 800 & 0xff;
edid->detailed_timings[0].h_blank_lsb = 256 & 0xff;
edid->detailed_timings[0].h_active_blank_msb = ((800 >> 4) & 0xf0) | ((256 >> 8) & 0x0f);
edid->detailed_timings[0].v_active_lsb = 600 & 0xff;
edid->detailed_timings[0].v_blank_lsb = 28;
edid->detailed_timings[0].v_active_blank_msb = (600 >> 4) & 0xf0;
edid->detailed_timings[0].h_front_porch_lsb = 40;
edid->detailed_timings[0].h_sync_pulse_lsb = 128;
edid->detailed_timings[0].v_front_porch_sync_pulse_lsb = (1 << 4) | 4;
/* Detailed timing for the preferred mode of 800x600 @ 60 Hz */
DETAILED_TIMING(detailed_timings[0], 40000, 800, 600, 256, 28, 40, 128, 1, 4);
edid->descriptors[1].tag = 0xf7; /* established timings 3 */
edid->descriptors[1].established_timings3.version = 0x0a;
memset(&edid->descriptors[1].established_timings3.timings, 0xff, sizeof(edid->descriptors[1].established_timings3.timings)); /* all enabled */
edid->descriptors[1].established_timings3.timings[5] &= 0xf0; /* reserved bits */
edid->descriptors[2].tag = 0xfc; /* display name */
memcpy(&edid->descriptors[2].ascii, "86Box Monitor", 13); /* exactly 13 characters (would otherwise require LF termination and space padding) */
@@ -182,14 +191,37 @@ ddc_init(void *i2c)
edid->descriptors[3].range_limits.padding[0] = 0x0a;
memset(&edid->descriptors[3].range_limits.padding[1], 0x20, sizeof(edid->descriptors[3].range_limits.padding) - 1);
uint8_t *edid_bytes = (uint8_t *) edid;
edid->extensions = 1;
for (uint8_t c = 0; c < 127; c++)
edid->checksum += edid_bytes[c];
edid->checksum = 256 - edid->checksum;
edid->ext_tag = 0x02;
edid->ext_rev = 0x03;
edid->ext_dtd_offset = 0x04;
/* Detailed timing for 1366x768 */
DETAILED_TIMING(ext_detailed_timings[0], 85500, 1366, 768, 426, 30, 70, 143, 3, 3);
/* High refresh rate timings (VGA is limited to 85 Hz) */
edid->ext_descriptors[1].tag = 0xfa; /* standard timing identifiers */
#define ext_standard_timings0 ext_descriptors[1].ext_standard_timings.timings
STANDARD_TIMING(ext_standard_timings0[0], 640, STD_ASPECT_4_3, 90); /* 640x480 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[1], 640, STD_ASPECT_4_3, 120); /* 640x480 @ 120 Hz */
STANDARD_TIMING(ext_standard_timings0[2], 800, STD_ASPECT_4_3, 90); /* 800x600 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[3], 800, STD_ASPECT_4_3, 120); /* 800x600 @ 120 Hz */
STANDARD_TIMING(ext_standard_timings0[4], 1024, STD_ASPECT_4_3, 90); /* 1024x768 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[5], 1280, STD_ASPECT_5_4, 90); /* 1280x1024 @ 90 Hz */
edid->ext_descriptors[1].ext_standard_timings.padding = 0x0a;
for (uint8_t c = 128; c < 255; c++)
edid->checksum2 += edid_bytes[c];
edid->checksum2 = 256 - edid->checksum2;
FILE *f = fopen("C:\\Users\\Richard\\Desktop\\86boxedid.bin", "wb");
fwrite(edid_bytes, 1, sizeof(edid_t), f);
fclose(f);
return i2c_eeprom_init(i2c, 0x50, edid_bytes, sizeof(edid_t), 0);
}