e647f7b120
- 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.
292 lines
14 KiB
C++
292 lines
14 KiB
C++
/////////////////////////////////////////////////////////////////////////
|
||
// $Id$
|
||
/////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// Copyright (C) 2018 The Bochs Project
|
||
//
|
||
// This library is free software; you can redistribute it and/or
|
||
// modify it under the terms of the GNU Lesser General Public
|
||
// License as published by the Free Software Foundation; either
|
||
// version 2 of the License, or (at your option) any later version.
|
||
//
|
||
// This library is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
// Lesser General Public License for more details.
|
||
//
|
||
// You should have received a copy of the GNU Lesser General Public
|
||
// License along with this library; if not, write to the Free Software
|
||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
||
// DDC stub (when ready, this code should return the VESA EDID for the
|
||
// Bochs plug&play monitor)
|
||
|
||
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
|
||
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
|
||
// is used to know when we are exporting symbols and when we are importing.
|
||
#define BX_PLUGGABLE
|
||
|
||
#include "bochs.h"
|
||
#include "ddc.h"
|
||
|
||
#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 (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 */
|
||
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.DDAmon = 1;
|
||
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)
|
||
{
|
||
}
|
||
|
||
Bit8u bx_ddc_c::read()
|
||
{
|
||
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)
|
||
{
|
||
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;
|
||
s.DDAhost = dda;
|
||
}
|
||
}
|
||
|
||
Bit8u bx_ddc_c::get_edid_byte()
|
||
{
|
||
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;
|
||
|
||
}
|