@@ -112,3 +112,5 @@ config ATI_VGA
default y if PCI_DEVICES
depends on PCI
select VGA
+ select BITBANG_I2C
+ select DDC
@@ -24,6 +24,7 @@
#include "qapi/error.h"
#include "hw/hw.h"
#include "ui/console.h"
+#include "hw/i2c/i2c-ddc.h"
#include "trace.h"
#define ATI_DEBUG_HW_CURSOR 0
@@ -267,7 +268,12 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
case DAC_CNTL:
val = s->regs.dac_cntl;
break;
-/* case GPIO_MONID: FIXME hook up DDC I2C here */
+ case GPIO_DVI_DDC:
+ val = s->regs.gpio_dvi_ddc;
+ break;
+ case GPIO_MONID:
+ val = s->regs.gpio_monid;
+ break;
case PALETTE_INDEX:
/* FIXME unaligned access */
val = vga_ioport_read(&s->vga, VGA_PEL_IR) << 16;
@@ -501,7 +507,34 @@ static void ati_mm_write(void *opaque, hwaddr addr,
s->regs.dac_cntl = data & 0xffffe3ff;
s->vga.dac_8bit = !!(data & DAC_8BIT_EN);
break;
-/* case GPIO_MONID: FIXME hook up DDC I2C here */
+ case GPIO_DVI_DDC:
+ if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
+ break;
+ }
+ s->regs.gpio_dvi_ddc = data & 0xf000f;
+ if (data & BIT(17)) {
+ s->regs.gpio_dvi_ddc |= !!(data & BIT(1)) << 9;
+ bitbang_i2c_set(s->bbi2c, BITBANG_I2C_SCL, (data & BIT(1)) != 0);
+ }
+ if (data & BIT(16)) {
+ s->regs.gpio_dvi_ddc |= bitbang_i2c_set(s->bbi2c, BITBANG_I2C_SDA,
+ data & BIT(0)) << 8;
+ }
+ break;
+ case GPIO_MONID:
+ if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
+ break; /* FIXME What does Radeon have here? */
+ }
+ s->regs.gpio_monid = data & 0x0f0f000f;
+ if (data & BIT(2) << 24) {
+ s->regs.gpio_monid |= !!(data & BIT(2)) << 10;
+ bitbang_i2c_set(s->bbi2c, BITBANG_I2C_SCL, (data & BIT(2)) != 0);
+ }
+ if (data & BIT(1) << 24) {
+ s->regs.gpio_monid |= bitbang_i2c_set(s->bbi2c, BITBANG_I2C_SDA,
+ (data & BIT(1)) != 0) << 9;
+ }
+ break;
case PALETTE_INDEX ... PALETTE_INDEX + 3:
if (size == 4) {
vga_ioport_write(&s->vga, VGA_PEL_IR, (data >> 16) & 0xff);
@@ -792,6 +825,12 @@ static void ati_vga_realize(PCIDevice *dev, Error **errp)
vga->cursor_draw_line = ati_cursor_draw_line;
}
+ /* ddc, edid */
+ I2CBus *i2cbus = i2c_init_bus(DEVICE(s), "ati-vga.ddc");
+ s->bbi2c = bitbang_i2c_init(i2cbus);
+ I2CSlave *i2cddc = I2C_SLAVE(qdev_create(BUS(i2cbus), TYPE_I2CDDC));
+ i2c_set_slave_address(i2cddc, 0x50);
+
/* mmio register space */
memory_region_init_io(&s->mm, OBJECT(s), &ati_mm_ops, s,
"ati.mmregs", 0x4000);
@@ -817,6 +856,7 @@ static void ati_vga_exit(PCIDevice *dev)
ATIVGAState *s = ATI_VGA(dev);
graphic_console_close(s->vga.con);
+ g_free(s->bbi2c);
}
static Property ati_vga_properties[] = {
@@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "hw/pci/pci.h"
+#include "hw/i2c/bitbang_i2c.h"
#include "vga_int.h"
/*#define DEBUG_ATI*/
@@ -36,6 +37,8 @@ typedef struct ATIVGARegs {
uint32_t crtc_gen_cntl;
uint32_t crtc_ext_cntl;
uint32_t dac_cntl;
+ uint32_t gpio_dvi_ddc;
+ uint32_t gpio_monid;
uint32_t crtc_h_total_disp;
uint32_t crtc_h_sync_strt_wid;
uint32_t crtc_v_total_disp;
@@ -84,6 +87,7 @@ typedef struct ATIVGAState {
uint16_t cursor_size;
uint32_t cursor_offset;
QEMUCursor *cursor;
+ bitbang_i2c_interface *bbi2c;
MemoryRegion io;
MemoryRegion mm;
ATIVGARegs regs;
@@ -37,6 +37,7 @@
#define CRTC_GEN_CNTL 0x0050
#define CRTC_EXT_CNTL 0x0054
#define DAC_CNTL 0x0058
+#define GPIO_DVI_DDC 0x0064
#define GPIO_MONID 0x0068
#define I2C_CNTL_1 0x0094
#define PALETTE_INDEX 0x00b0
This adds DDC support to ati-vga and connects i2c-ddc to provide EDID info that is read by guests to find available screen modes. Not sure if this is 100% correct yet but at least MorphOS is happy with it and starts in a high resolution mode instead of 640x480 (although its splash screen is still not correct). Linux needs support from VESA vgabios, it seems to be missing INT10 0x4F15 function (see https://gitlab.freedesktop.org/xorg/xserver/blob/master/hw/xfree86/vbe/vbe.c) without which no DDC is available that also prevents loading the accelerated X driver. Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu> --- hw/display/Kconfig | 2 ++ hw/display/ati.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- hw/display/ati_int.h | 4 ++++ hw/display/ati_regs.h | 1 + 4 files changed, 49 insertions(+), 2 deletions(-)