Implemented basic DDC support.

- Basic I2C implementation for DDC2B support.
- Added VESA EDID structure (values from a patch for the LGPL'd VGABIOS).
- Windows now detecting plug&play monitor "Bochs Screen" if an original VGABIOS
  image is used (Cirrus PCI / Voodoo Banshee).
- TODO: Add this feature in the Cirrus version of the LGPL'd VGABIOS.
This commit is contained in:
Volker Ruppert 2018-01-14 18:44:28 +00:00
parent 1f2d9ca668
commit e647f7b120
3 changed files with 243 additions and 16 deletions

View File

@ -26,6 +26,9 @@ Changes after 2.6.9 release:
- Voodoo2 model now working after some fixes and implementation of the
CMDFIFO (using FIFO thread) and one of the bitBLT functions.
- Added Voodoo Banshee emulation support (still under construction).
- Display
- Added basic DDC support for Cirrus and Voodoo Banshee adapters (plug&play
monitor "Bochs Screen").
- USB
- Now creating separate plugins for each USB device implementation.
- Networking

View File

@ -31,14 +31,136 @@
#define LOG_THIS
enum {
DDC_STAGE_START,
DDC_STAGE_ADDRESS,
DDC_STAGE_RW,
DDC_STAGE_DATA_IN,
DDC_STAGE_DATA_OUT,
DDC_STAGE_ACK_IN,
DDC_STAGE_ACK_OUT,
DDC_STAGE_STOP
};
const Bit8u vesa_EDID[128] = {
0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
/* 0x0000 8-byte header */
0x04,0x21, /* 0x0008 Vendor ID ("AAA") */
0xAB,0xCD, /* 0x000A Product ID */
0x00,0x00,0x00,0x00, /* 0x000C Serial number (none) */
12, 11, /* 0x0010 Week of manufacture (12) and year of manufacture (2001) */
0x01, 0x03, /* 0x0012 EDID version number (1.3) */
0x0F, /* 0x0014 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) */
0x21,0x19, /* 0x0015 Scren size (330 mm * 250 mm) */
0x78, /* 0x0017 Display gamma (2.2) */
0x0D, /* 0x0018 Feature flags (no DMPS states, RGB, display is continuous frequency) */
0x78,0xF5, /* 0x0019 Least significant bits for chromaticity and default white point */
0xA6,0x55,0x48,0x9B,0x26,0x12,0x50,0x54,
/* 0x001B Most significant bits for chromaticity and default white point */
0xFF, /* 0x0023 Established timings 1 (720 x 400 @ 70Hz, 720 x 400 @ 88Hz,
640 x 480 @ 60Hz, 640 x 480 @ 67Hz, 640 x 480 @ 72Hz, 640 x 480 @ 75Hz,
800 x 600 @ 56Hz, 800 x 600 @ 60Hz) - historical resolutions */
0xEF, /* 0x0024 Established timings 2 (800 x 600 @ 72Hz, 800 x 600 @ 75Hz, 832 x 624 @ 75Hz
not 1024 x 768 @ 87Hz(I), 1024 x 768 @ 60Hz, 1024 x 768 @ 70Hz,
1024 x 768 @ 75Hz, 1280 x 1024 @ 75Hz) - historical resolutions */
0x80, /* 0x0025 Established timings 2 (1152 x 870 @ 75Hz and no manufacturer timings) */
/* Standard timing */
/* First byte: X resolution, divided by 8, less 31 (2562288 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 (60123 Hz), nop 01 01 */
0x31, 0x59, /* 0x0026 Standard timing #1 (640 x 480 @ 85 Hz) */
0x45, 0x59, /* 0x0028 Standard timing #2 (800 x 600 @ 85 Hz) */
0x61, 0x59, /* 0x002A Standard timing #3 (1024 x 768 @ 85 Hz) */
0x81, 0xCA, /* 0x002C Standard timing #4 (1280 x 720 @ 70 Hz) */
0x81, 0x0A, /* 0x002E Standard timing #5 (1280 x 800 @ 70 Hz) */
0xA9, 0xC0, /* 0x0030 Standard timing #6 (1600 x 900 @ 60 Hz) */
0xA9, 0x40, /* 0x0034 Standard timing #7 (1600 x 1200 @ 60 Hz) */
0xD1, 0x00, /* 0x0032 Standard timing #8 (1920 x 1080 @ 60 Hz) */
/* 0x0036 First 18-byte descriptor (1920 x 1200) */
0x3C, 0x28, /* Pixel clock = 154000000 Hz */
0x80, /* 0x0038 Horizontal addressable pixels low byte (0x0780 & 0xFF) */
0xA0, /* 0x0039 Horizontal blanking low byte (0x00A0 & 0xFF) */
0x70, /* 0x003A Horizontal addressable pixels high 4 bits ((0x0780 & 0x0F00) >> 4), and */
/* Horizontal blanking high 4 bits ((0x00A0 & 0x0F00 ) >> 8) as low bits */
0xB0, /* 0x003B Vertical addressable pixels low byte (0x04B0 & 0xFF) */
0x23, /* 0x003C Vertical blanking low byte (0x0023 & 0xFF) */
0x40, /* 0x003D Vertical addressable pixels high 4 bits ((0x04B0 & 0x0F00) >> 4), and */
/* Vertical blanking high 4 bits ((0x0024 & x0F00) >> 8) */
0x30, /* 0x003E Horizontal front porch in pixels low byte (0x0030 & 0xFF) */
0x20, /* 0x003F Horizontal sync pulse width in pixels low byte (0x0020 & 0xFF) */
0x36, /* 0x0040 Vertical front porch in lines low 4 bits ((0x0003 & 0x0F) << 4), and */
/* Vertical sync pulse width in lines low 4 bits (0x0006 & 0x0F) */
0x00, /* 0x0041 Horizontal front porch pixels high 2 bits (0x0030 >> 8), and */
/* Horizontal sync pulse width in pixels high 2 bits (0x0020 >> 8), and */
/* Vertical front porch in lines high 2 bits (0x0003 >> 4), and */
/* Vertical sync pulse width in lines high 2 bits (0x0006 >> 4) */
0x06, /* 0x0042 Horizontal addressable video image size in mm low 8 bits (0x0206 & 0xFF) */
0x44, /* 0x0043 Vertical addressable video image size in mm low 8 bits (0x0144 & 0xFF) */
0x21, /* 0x0044 Horizontal addressable video image size in mm high 8 bits (0x0206 >> 8), and */
/* Vertical addressable video image size in mm high 8 bits (0x0144 >> 8) */
0x00, /* 0x0045 Left and right border size in pixels (0x00) */
0x00, /* 0x0046 Top and bottom border size in lines (0x00) */
0x1E, /* 0x0047 Flags (non-interlaced, no stereo, analog composite sync, sync on */
/* all three (RGB) video signals) */
/* 0x0048 Second 18-byte descriptor (1280 x 1024) */
0x30, 0x2a, /* Pixel clock = 108000000 Hz */
0x00, /* 0x004A Horizontal addressable pixels low byte (0x0500 & 0xFF) */
0x98, /* 0x004B Horizontal blanking low byte (0x0198 & 0xFF) */
0x51, /* 0x004C Horizontal addressable pixels high 4 bits (0x0500 >> 8), and */
/* Horizontal blanking high 4 bits (0x0198 >> 8) */
0x00, /* 0x004D Vertical addressable pixels low byte (0x0400 & 0xFF) */
0x2A, /* 0x004E Vertical blanking low byte (0x002A & 0xFF) */
0x40, /* 0x004F Vertical addressable pixels high 4 bits (0x0400 >> 8), and */
/* Vertical blanking high 4 bits (0x002A >> 8) */
0x30, /* 0x0050 Horizontal front porch in pixels low byte (0x0030 & 0xFF) */
0x70, /* 0x0051 Horizontal sync pulse width in pixels low byte (0x0070 & 0xFF) */
0x13, /* 0x0052 Vertical front porch in lines low 4 bits (0x0001 & 0x0F), and */
/* Vertical sync pulse width in lines low 4 bits (0x0003 & 0x0F) */
0x00, /* 0x0053 Horizontal front porch pixels high 2 bits (0x0030 >> 8), and */
/* Horizontal sync pulse width in pixels high 2 bits (0x0070 >> 8), and */
/* Vertical front porch in lines high 2 bits (0x0001 >> 4), and */
/* Vertical sync pulse width in lines high 2 bits (0x0003 >> 4) */
0x2C, /* 0x0054 Horizontal addressable video image size in mm low 8 bits (0x012C & 0xFF) */
0xE1, /* 0x0055 Vertical addressable video image size in mm low 8 bits (0x00E1 & 0xFF) */
0x10, /* 0x0056 Horizontal addressable video image size in mm high 8 bits (0x012C >> 8), and */
/* Vertical addressable video image size in mm high 8 bits (0x00E1 >> 8) */
0x00, /* 0x0057 Left and right border size in pixels (0x00) */
0x00, /* 0x0058 Top and bottom border size in lines (0x00) */
0x1E, /* 0x0059 Flags (non-interlaced, no stereo, analog composite sync, sync on */
/* all three (RGB) video signals) */
0x00,0x00,0x00,0xFF,0x00, /* 0x005A Third 18-byte descriptor - display product serial number */
'0','1','2','3','4','5','6','7','8','9',
0x0A,0x20,0x20,
0x00,0x00,0x00,0xFC,0x00, /* 0x006C Fourth 18-byte descriptor - display product name */
'B','o','c','h','s',' ','S','c','r','e','e','n',
0x0A,
0x00, /* 0x007E Extension block count (none) */
0x94, /* 0x007F Checksum */
};
bx_ddc_c::bx_ddc_c(void)
{
put("DDC");
s.DCKhost = 1;
s.DDAhost = 1;
s.DCKmon = 1;
s.DDAmon = 1;
s.retval = 0x0f;
s.ddc_stage = DDC_STAGE_STOP;
s.ddc_ack = 1;
s.ddc_rw = 1;
s.edid_index = 0;
}
bx_ddc_c::~bx_ddc_c(void)
@ -47,25 +169,123 @@ bx_ddc_c::~bx_ddc_c(void)
Bit8u bx_ddc_c::read()
{
return s.retval;
Bit8u retval = (((s.DDAmon & s.DDAhost) << 3) | (s.DCKhost << 2) |
(s.DDAhost << 1) | s.DCKhost);
return retval;
}
void bx_ddc_c::write(bx_bool dck, bx_bool dda)
{
if (dck != s.DCKhost) {
BX_INFO(("DCK now %s", dck ? "inactive":"active low"));
bx_bool dck_change = 0;
bx_bool dda_change = 0;
if ((dck != s.DCKhost) || (dda != s.DDAhost)) {
dck_change = (dck != s.DCKhost);
dda_change = (dda != s.DDAhost);
if (dck_change && dda_change) {
BX_ERROR(("DDC unknown: DCK=%d DDA=%d", dck, dda));
} else if (dck_change) {
if (!dck) {
switch (s.ddc_stage) {
case DDC_STAGE_START:
s.ddc_stage = DDC_STAGE_ADDRESS;
s.ddc_bitshift = 6;
s.ddc_byte = 0;
break;
case DDC_STAGE_ADDRESS:
if (s.ddc_bitshift > 0) {
s.ddc_bitshift--;
} else {
s.ddc_ack = !(s.ddc_byte == 0x50);
BX_DEBUG(("Address = 0x%02x", s.ddc_byte));
s.ddc_stage = DDC_STAGE_RW;
}
break;
case DDC_STAGE_RW:
BX_DEBUG(("R/W mode = %d", s.ddc_rw));
s.ddc_stage = DDC_STAGE_ACK_OUT;
s.DDAmon = s.ddc_ack;
break;
case DDC_STAGE_DATA_IN:
if (s.ddc_bitshift > 0) {
s.ddc_bitshift--;
} else {
s.ddc_ack = 0;
BX_DEBUG(("Data = 0x%02x", s.ddc_byte));
s.edid_index = s.ddc_byte;
s.DDAmon = s.ddc_ack;
s.ddc_stage = DDC_STAGE_ACK_OUT;
}
break;
case DDC_STAGE_DATA_OUT:
if (s.ddc_bitshift > 0) {
s.ddc_bitshift--;
s.DDAmon = ((s.ddc_byte >> s.ddc_bitshift) & 1);
} else {
s.ddc_stage = DDC_STAGE_ACK_IN;
s.DDAmon = 1;
}
break;
case DDC_STAGE_ACK_IN:
BX_DEBUG(("Received status %s", s.ddc_ack ? "NAK":"ACK"));
if (s.ddc_ack == 0) {
s.ddc_bitshift = 7;
s.ddc_stage = DDC_STAGE_DATA_OUT;
s.ddc_byte = get_edid_byte();
s.DDAmon = ((s.ddc_byte >> s.ddc_bitshift) & 1);
} else {
s.ddc_stage = DDC_STAGE_STOP;
}
break;
case DDC_STAGE_ACK_OUT:
BX_DEBUG(("Sent status %s", s.ddc_ack ? "NAK":"ACK"));
s.ddc_bitshift = 7;
if (s.ddc_rw) {
s.ddc_stage = DDC_STAGE_DATA_OUT;
s.ddc_byte = get_edid_byte();
s.DDAmon = ((s.ddc_byte >> s.ddc_bitshift) & 1);
} else {
s.ddc_stage = DDC_STAGE_DATA_IN;
s.DDAmon = 1;
s.ddc_byte = 0;
}
break;
}
} else {
switch (s.ddc_stage) {
case DDC_STAGE_ADDRESS:
case DDC_STAGE_DATA_IN:
s.ddc_byte |= (s.DDAhost << s.ddc_bitshift);
break;
case DDC_STAGE_RW:
s.ddc_rw = s.DDAhost;
break;
case DDC_STAGE_ACK_IN:
s.ddc_ack = s.DDAhost;
break;
}
}
} else {
if (s.DCKhost) {
if (!dda) {
s.ddc_stage = DDC_STAGE_START;
BX_DEBUG(("Start detected"));
} else {
s.ddc_stage = DDC_STAGE_STOP;
BX_DEBUG(("Stop detected"));
}
}
}
s.DCKhost = dck;
}
if (dda != s.DDAhost) {
BX_INFO(("DDA now %s", dda ? "inactive":"active low"));
s.DDAhost = dda;
}
combine_signals();
}
void bx_ddc_c::combine_signals()
Bit8u bx_ddc_c::get_edid_byte()
{
s.retval = (s.DCKhost & s.DCKmon) << 2;
s.retval |= ((s.DDAhost & s.DDAmon) << 3);
s.retval |= ((s.DDAhost << 1) | s.DCKhost);
Bit8u value = vesa_EDID[s.edid_index++];
BX_DEBUG(("Sending EDID byte %d (value = 0x%02x)", s.edid_index - 1, value));
s.edid_index &= 0x7f;
return value;
}

View File

@ -32,14 +32,18 @@ public:
private:
void combine_signals(void);
Bit8u get_edid_byte(void);
struct {
bx_bool DCKhost;
bx_bool DDAhost;
bx_bool DCKmon;
bx_bool DDAmon;
Bit8u retval;
Bit8u ddc_stage;
Bit8u ddc_bitshift;
bx_bool ddc_ack;
bx_bool ddc_rw;
Bit8u ddc_byte;
Bit8u edid_index;
} s; // state information
};