The Bochs VGA ROM now return an information
about a recent WIDE monitor.
It is constructed from defitions at run time.
Returning an EDID with decent timings may be necessary
in case we want to use a resolution
superior to 1024x768 with Xorg.
Signed-off-by: Hiroshi Miura <[email protected]>
---
vgasrc/bochsvga.c | 202
++++++++++++++++++++++++++++++++---------------------
vgasrc/vbe_edid.h | 134 +++++++++++++++++++++++++++++++++++
2 files changed, 255 insertions(+), 81 deletions(-)
create mode 100644 vgasrc/vbe_edid.h
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c
index 93e6818..c12a859 100644
--- a/vgasrc/bochsvga.c
+++ b/vgasrc/bochsvga.c
@@ -15,7 +15,7 @@
#include "stdvga.h" // VGAREG_SEQU_ADDRESS
#include "pci.h" // pci_config_readl
#include "pci_regs.h" // PCI_BASE_ADDRESS_0
-
+#include "vbe_edid.h"
/****************************************************************
* Mode tables
@@ -83,12 +83,15 @@ static struct bochsvga_mode
{ 0x184, { MM_DIRECT, 1680, 1050, 16, 8, 16, SEG_GRAPH } },
{ 0x185, { MM_DIRECT, 1680, 1050, 24, 8, 16, SEG_GRAPH } },
{ 0x186, { MM_DIRECT, 1680, 1050, 32, 8, 16, SEG_GRAPH } },
- { 0x187, { MM_DIRECT, 1920, 1200, 16, 8, 16, SEG_GRAPH } },
- { 0x188, { MM_DIRECT, 1920, 1200, 24, 8, 16, SEG_GRAPH } },
- { 0x189, { MM_DIRECT, 1920, 1200, 32, 8, 16, SEG_GRAPH } },
- { 0x18a, { MM_DIRECT, 2560, 1600, 16, 8, 16, SEG_GRAPH } },
- { 0x18b, { MM_DIRECT, 2560, 1600, 24, 8, 16, SEG_GRAPH } },
- { 0x18c, { MM_DIRECT, 2560, 1600, 32, 8, 16, SEG_GRAPH } },
+ { 0x187, { MM_DIRECT, 1920, 1080, 16, 8, 16, SEG_GRAPH } },
+ { 0x188, { MM_DIRECT, 1920, 1080, 24, 8, 16, SEG_GRAPH } },
+ { 0x189, { MM_DIRECT, 1920, 1080, 32, 8, 16, SEG_GRAPH } },
+ { 0x18a, { MM_DIRECT, 1920, 1200, 16, 8, 16, SEG_GRAPH } },
+ { 0x18b, { MM_DIRECT, 1920, 1200, 24, 8, 16, SEG_GRAPH } },
+ { 0x18c, { MM_DIRECT, 1920, 1200, 32, 8, 16, SEG_GRAPH } },
+ { 0x18d, { MM_DIRECT, 2560, 1600, 16, 8, 16, SEG_GRAPH } },
+ { 0x18e, { MM_DIRECT, 2560, 1600, 24, 8, 16, SEG_GRAPH } },
+ { 0x18f, { MM_DIRECT, 2560, 1600, 32, 8, 16, SEG_GRAPH } },
};
static int is_bochsvga_mode(struct vgamode_s *vmode_g)
@@ -323,70 +326,6 @@ bochsvga_set_mode(struct vgamode_s *vmode_g, int flags)
return 0;
}
-/****************************************************************
- * EDID
- ****************************************************************/
-
-u8 bochsvga_edid[128] VAR16 = {
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* 8-byte header */
- 0x04, 0x21, /* Vendor ID ("AAA") */
- 0xAB, 0xCD, /* Product ID */
- 0x00, 0x00, 0x00, 0x00, /* Serial number */
- 54, /* Week of manufacture (54) */
- 10, /* Year of manufacture (2000) */
- 0x01, 0x01, /* EDID version number (1.1) */
- 0x0F, /* Video signal interface */
- 0x21, 0x19, /* Scren size (330 mm * 250 mm) */
- 0x78, /* Display gamma (2.2) */
- 0x0D, /* Feature flags */
- 0x78, 0xF5, /* Chromaticity LSB */
- 0xA6, 0x55, 0x48, 0x9B, 0x26, 0x12, 0x50, 0x54, /* Chromaticity MSB */
- 0xFF, 0xEF, 0x80, /* Established timings */
- 0x31, 0x59, /* Standard timing #1 (640 x 480 @ 85 Hz) */
- 0x45, 0x59, /* Standard timing #2 (800 x 600 @ 85 Hz) */
- 0x61, 0x59, /* Standard timing #3 (1024 x 768 @ 85 Hz) */
- 0x31, 0x4A, /* Standard timing #4 (640 x 480 @ 70 Hz) */
- 0x81, 0x4A, /* Standard timing #5 (1280 x 960 @ 70 Hz) */
- 0xA9, 0x40, /* Standard timing #6 (1600 x 1200 @ 60 Hz) */
- 0x01, 0x01, /* Standard timing #7 (unused) */
- 0x01, 0x01, /* Standard timing #8 (unused) */
-
- /* First timing descriptor (1024 x 768) */
- 0x30, 0x2a, /* Pixel clock */
- 0x80, /* hactive low */
- 0xC0, /* hblank low */
- 0x41, /* hactive high, hblank high */
- 0x60, /* vactive low */
- 0x24, /* vblank low */
- 0x30, /* vactive high, vblank high */
- 0x40, /* hsync offset low */
- 0x80, /* hsync width low */
- 0x13, /* vsync offset low, vsync width low */
- 0x00, /* hsync offset high, hsync width high , vsync offset high, vsync width high */
- 0x2C, /* hsize low */
- 0xE1, /* vsize low */
- 0x10, /* hsize high, vsize high */
- 0x00, /* hborder */
- 0x00, /* vborder */
- 0x1E, /* Features */
-
- /* Second descriptor */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
-
- /* Third descriptor - Serial number */
- 0x00, 0x00, 0x00, 0xFF, 0x00,
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '\n', ' ', ' ',
-
- /* Fourth descriptor - Monitor name */
- 0x00,0x00,0x00,0xFC,0x00,
- 'B', 'o', 'c', 'h', 's', ' ', 'S', 'c', 'r', 'e', 'e', 'n', '\n',
-
- 0x00, /* Extensions */
- 0x00, /* Checksum */
-};
-
int bochsvga_get_ddc_capabilities(u16 unit)
{
if (unit != 0)
@@ -395,17 +334,123 @@ int bochsvga_get_ddc_capabilities(u16 unit)
return (1 << 8) | VBE_DDC1_PROTOCOL_SUPPORTED;
}
-int bochsvga_read_edid(u16 unit, u16 block, u16 seg, void *data)
+u8 most_chromaticity[8] VAR16 = {0xA6,0x55,0x48,0x9B,0x26,0x12,0x50,0x54};
+unsigned char vgabios_name[] VAR16 = "Sea VGABIOS";
+struct edid_detailed_timing vbe_edid_dtd_1920x1080 VAR16 = {
+ WORDBE(0x3a02), 0x80, 0x90, 0x72, 0x38, 0x26,
+ 0x40, 0x78, 0xD0, 0x13, 0x00, 0x14, 0x2B, 0x21,
+ 0x00, 0x00, 0x1E};
+struct edid_detailed_timing vbe_edid_dtd_1280x1024 VAR16 = {
+ WORDBE(0x2a30), 0x00, 0x98, 0x51, 0x00, 0x2A,
+ 0x40, 0x30, 0x70, 0x13, 0x00, 0x2C, 0xE1, 0x10,
+ 0x00, 0x00, 0x1E};
+struct edid_detailed_timing vbe_edid_dtd_1152x864 VAR16 = {
+ WORDBE(0x2a30), 0x80, 0xC0, 0x41, 0x60, 0x24,
+ 0x30, 0x40, 0x80, 0x13, 0x00, 0x2C, 0xE1, 0x10,
+ 0x00, 0x00, 0x1E};
+struct edid_detailed_timing vbe_edid_dtd_1600x1200 VAR16 = {
+ WORDBE(0x3c8c), 0x40, 0x30, 0x62, 0xB0, 0x32,
+ 0x40, 0x40, 0xC0, 0x13, 0x00, 0x2C, 0xE1, 0x10,
+ 0x00, 0x00, 0x1E};
+
+int bochsvga_read_edid_block0(u16 unit, u16 block, u16 seg, void *data)
{
- if (unit != 0 || block != 0)
- return -1;
+ struct vbe_edid_info *info = data;
+ int i;
+
+ memset_far(seg, info, 0, sizeof(*info));
+ /* header */
+ SET_FARVAR(seg, info->header[0], 0);
+ for (i = 1; i < 7; i++) {
+ SET_FARVAR(seg, info->header[i], 0xFF);
+ }
+ SET_FARVAR(seg, info->header[7], 0);
+ /* Vendor/Product/Serial/Date */
+ SET_FARVAR(seg, info->vendor, WORDBE(0x0421));
+ SET_FARVAR(seg, info->product,WORDBE(0xABCD));
+ SET_FARVAR(seg, info->serial, DWORDBE(0));
+ /* date/version */
+ SET_FARVAR(seg, info->week,54);
+ SET_FARVAR(seg, info->year,10); /* 2000 */
+ SET_FARVAR(seg, info->major_version,1);
+ SET_FARVAR(seg, info->minor_version,3); /* 1.3 */
+ /* video prameters */
+ SET_FARVAR(seg, info->video_setup,0x0F);
+ /* Video signal interface (analogue, 0.700 : 0.300 : 1.000 V p-p,
+ Video Setup: Blank Level = Black Level, Separate Sync H & V Signals are
+ supported, Composite Sync Signal on Horizontal is supported, Composite
+ Sync Signal on Green Video is supported, Serration on the Vertical Sync
+ is supported) */
+ SET_FARVAR(seg, info->screen_width,0x21);
+ SET_FARVAR(seg, info->screen_height,0x19); /* 330 mm * 250 mm */
+ SET_FARVAR(seg, info->gamma,0x78); /* 2.2 */
+ SET_FARVAR(seg, info->feature_flag,0x0D); /* no DMPS states, RGB, display is continuous frequency */
+ SET_FARVAR(seg, info->least_chromaticity[0],0x78);
+ SET_FARVAR(seg, info->least_chromaticity[1],0xF5);
+ memcpy_far(seg, info->most_chromaticity, get_global_seg(), most_chromaticity,
+ sizeof (most_chromaticity));
+
+ SET_FARVAR(seg, info->established_timing[0], 0xFF);
+ SET_FARVAR(seg, info->established_timing[1], 0xEF);
+ SET_FARVAR(seg, info->established_timing[2], 0x80);
+ /* 720x400@70Hz, 720x400@88Hz, 640x480@60Hz, 640x480@67Hz, 640x480@72Hz, 640x480@75Hz,
+ 800x600@56Hz, 800x600@60Hz, 800x600@72Hz, 800x600@75Hz, 832x624@75Hz, 1152x870@75Hz,
+ not 1024x768@87Hz(I), 1024x768@60Hz, 1024x768@70Hz, 1024x768@75Hz, 1280x1024@75Hz */
+ /* standard timings */
+ SET_FARVAR(seg, info->standard_timing[0], VBE_EDID_STD_640x480_85Hz);
+ SET_FARVAR(seg, info->standard_timing[1], VBE_EDID_STD_800x600_85Hz);
+ SET_FARVAR(seg, info->standard_timing[2], VBE_EDID_STD_1024x768_85Hz);
+ SET_FARVAR(seg, info->standard_timing[3], VBE_EDID_STD_1280x720_70Hz);
+ SET_FARVAR(seg, info->standard_timing[4], VBE_EDID_STD_1280x960_60Hz);
+ SET_FARVAR(seg, info->standard_timing[5], VBE_EDID_STD_1440x900_60Hz);
+ SET_FARVAR(seg, info->standard_timing[6], VBE_EDID_STD_1600x1200_60Hz);
+ SET_FARVAR(seg, info->standard_timing[7], VBE_EDID_STD_1680x1050_60Hz);
+ /* detailed timing blocks */
+ memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &vbe_edid_dtd_1152x864,
+ sizeof (vbe_edid_dtd_1152x864));
+ memcpy_far(seg, &(info->desc[1].dtd), get_global_seg(), &vbe_edid_dtd_1280x1024,
+ sizeof (vbe_edid_dtd_1280x1024));
+ /* serial */
+ for (i = 0; i < 5; i++) {
+ SET_FARVAR(seg, info->desc[2].mtxtd.header[i], 0);
+ }
+ SET_FARVAR(seg, info->desc[2].mtxtd.header[3], 0xFF);
+ for (i = 0; i < 10; i++) {
+ SET_FARVAR(seg, info->desc[2].mtxtd.text[i], i+0x30);
+ }
+ SET_FARVAR(seg, info->desc[2].mtxtd.text[10], 0x0A);
+ SET_FARVAR(seg, info->desc[2].mtxtd.text[11], 0x20);
+ SET_FARVAR(seg, info->desc[2].mtxtd.text[12], 0x20);
+ /* monitor name */
+ for (i = 0; i < 5; i++) {
+ SET_FARVAR(seg, info->desc[3].mtxtd.header[i], 0);
+ }
+ SET_FARVAR(seg, info->desc[3].mtxtd.header[3], 0xFC);
+ memcpy_far(seg, info->desc[3].mtxtd.text, get_global_seg(), vgabios_name, 12);
+ SET_FARVAR(seg, info->desc[3].mtxtd.text[12], 0x0A);
+ /* ext */
+ SET_FARVAR(seg, info->extensions, 0);
- memcpy_far(seg, data, get_global_seg(), bochsvga_edid,
- sizeof (bochsvga_edid));
+ /* checksum */
+ u8 sum = -checksum_far(get_global_seg(), info, sizeof(info));
+ SET_FARVAR(seg, info->checksum, sum);
return 0;
}
+int bochsvga_read_edid(u16 unit, u16 block, u16 seg, void *data)
+{
+ if (unit != 0)
+ return -1;
+
+ switch (block) {
+ case 0:
+ return bochsvga_read_edid_block0(unit, block, seg, data);
+ default:
+ return -1;
+ }
+}
+
/****************************************************************
* Init
****************************************************************/
@@ -471,11 +516,6 @@ bochsvga_init(void)
}
}
- // Fixup EDID checksum
- u8 sum = -checksum_far(get_global_seg(), bochsvga_edid,
- sizeof(bochsvga_edid));
- SET_VGA(bochsvga_edid[sizeof (bochsvga_edid) - 1], sum);
-
return 0;
}
diff --git a/vgasrc/vbe_edid.h b/vgasrc/vbe_edid.h
new file mode 100644
index 0000000..f15a2af
--- /dev/null
+++ b/vgasrc/vbe_edid.h
@@ -0,0 +1,134 @@
+#ifndef __VBE_EDID_H
+#define __VBE_EDID_H
+
+#define WORDBE(x) ((((x) & 0xff) << 8 ) | (((x) >> 8) & 0xff))
+#define DWORDBE(x) (((x) & 0xff) << 24) | ((((x) >> 8) & 0xff) << 16 ) | ((((x) >> 16) & 0xff) << 8 ) | ((((x) >> 24) & 0xff))
+
+/* EDID infomation definitions */
+/* Detailed Timing Descriptor */
+struct edid_detailed_timing {
+ u16 pixel_clock;
+ u8 horizontal_addressable_low;
+ u8 horizontal_blanking_low;
+ u8 horizontal_high;
+ u8 vertical_addressable_low;
+ u8 vertical_blanking_low;
+ u8 vertical_high;
+ u8 horizontal_front_porch_low;
+ u8 horizontal_sync_pulse_low;
+ u8 vertical_low4;
+ u8 horizontal_vertical_sync_hi;
+ u8 horizontal_video_image_low;
+ u8 vertical_video_image_low;
+ u8 video_image_high;
+ u8 horizontal_border;
+ u8 vertical_border;
+ u8 features;
+} PACKED;
+
+/* Other Monitor Descriptors */
+/*
+ 0xFF: Monitor serial number (text)
+ 0xFE: Unspecified text (text)
+ 0xFC: Monitor name (text)
+ */
+struct edid_monitor_text {
+ u8 header[5];
+ u8 text[13];
+} PACKED;
+
+/* Monitor Range Limits Descriptor */
+/*
+ 0xFD: Monitor range limits. 6- or 13-byte binary descriptor.
+ */
+struct edid_monitor_range_limit {
+ u8 header[5];
+ u8 vertical_rate_min;
+ u8 vertical_rate_max;
+ u8 horizontal_rate_min;
+ u8 horizontal_rate_max;
+ u8 pixel_clock_max;
+ u8 extended_timing_type;
+ u8 reserved;
+ u8 start_frequency;
+ u8 gtf_c_val;
+ u16 gtf_m_val;
+ u8 gtf_k_val;
+ u8 gtf_j_val;
+} PACKED;
+
+/* White point Descriptor */
+/*
+ 0xFB: Additional white point data. 2Ã 5-byte descriptors, padded with 0A 20 20.
+ 0xFA: Additional standard timing identifiers. 6Ã 2-byte descriptors, padded with 0A
+ */
+struct edid_wp_desc {
+ u8 index;
+ u8 least;
+ u8 x;
+ u8 y;
+ u8 gamma;
+} PACKED;
+
+struct edid_white_point {
+ u8 header[5];
+ struct edid_wp_desc desc[2];
+ u8 padding[3];
+} PACKED;
+
+struct edid_additional_timing {
+ u8 header[5];
+ u16 standard_timing[6];
+ u8 padding;
+} PACKED;
+
+union edid_descriptors {
+ struct edid_detailed_timing dtd;
+ struct edid_monitor_range_limit mrld;
+ struct edid_monitor_text mtxtd;
+ struct edid_white_point wpd;
+ struct edid_additional_timing astd;
+} PACKED;
+
+struct vbe_edid_info {
+ u8 header[8];
+ u16 vendor;
+ u16 product;
+ u32 serial;
+ u8 week;
+ u8 year;
+ u8 major_version;
+ u8 minor_version;
+ u8 video_setup;
+ u8 screen_width;
+ u8 screen_height;
+ u8 gamma;
+ u8 feature_flag;
+ u8 least_chromaticity[2];
+ u8 most_chromaticity[8];
+ u8 established_timing[3];
+ u16 standard_timing[8];
+ union edid_descriptors desc[4];
+ u8 extensions;
+ u8 checksum;
+} PACKED;
+
+/* EDID Standard Timing Description */
+
+/* First byte: X resolution, divided by 8, less 31 (256â2288 pixels) */
+/* bit 7-6, X:Y pixel ratio: 00=16:10; 01=4:3; 10=5:4; 11=16:9 */
+/* bit 5-0, Vertical frequency, less 60 (60â123 Hz), nop 01 01 in Big Endian*/
+#define VBE_EDID_STD_640x480_85Hz 0x5931
+#define VBE_EDID_STD_800x600_85Hz 0x5945
+#define VBE_EDID_STD_1024x768_85Hz 0x5961
+#define VBE_EDID_STD_1152x864_70Hz 0x4A71
+#define VBE_EDID_STD_1280x720_70Hz 0xCA81
+#define VBE_EDID_STD_1280x800_70Hz 0x0A81
+#define VBE_EDID_STD_1280x960_60Hz 0x4081
+#define VBE_EDID_STD_1280x1024_60Hz 0x8081
+#define VBE_EDID_STD_1440x900_60Hz 0x0095
+#define VBE_EDID_STD_1600x1200_60Hz 0x40A9
+#define VBE_EDID_STD_1680x1050_60Hz 0x00B3
+#define VBE_EDID_STD_NOP 0x0101
+
+#endif /* vbe_edid.h */
_______________________________________________
SeaBIOS mailing list
[email protected]
http://www.seabios.org/mailman/listinfo/seabios