mirror of https://github.com/xemu-project/xemu.git
vga: ati fixes, add ati vgabios.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJdFe5kAAoJEEy22O7T6HE45qQP/37tN/q9FAjfvwu26zbbhcYd V0wchXmnKcZ6mszPKtoYnXJV3poQj8aNQGVb3/vMB+3+ENVbrH1J6G7fxxGiZyNc owG4JmMy2OmLdPzSeEwnPafOg8m5UPPgXQwuuCNseUFigcx+3zjB8LPY2jW23DGl Jxhd8hvxaozZXbUzi7NA5dcoAq11cG6tz5D6DS5pCtbSj/puYF6Zz12o82E0Poaw /sxCAwfhVVWNHXrw10Az3TmZUV9JKyc3XkMIy74P/cD4UhJwXCbzdbSZiIwB3ASD psm2QPoEp4/kl2xpitycvHI9eWKojEGN/m093UZiPv6rMVzGDNr97ntRsAtXl0VS Gf/sU/5JR9yg8ZmxCKE//Z2r8KPWybqdMhfpxt5JGhd2MA3eHUXo4a3IezXxHkQB EJrJK+DV42tp6DMH4iMrnJZPET0DWUVdvbAZc+l8HFmMZBeOMXUFfGUNLQaEn3jC bUrPGgtt2G80Ltl4usMSGcAwAo9CrES3egh8InENsZi1VrbBVb+7VXN0g1v+1IIf IE12q730HWDwfWcbCAmM3s92ISujRQriCsW+NhW5xMc5a0bACXIoHy7zmw7X/ep7 N0uyv04c3PsPPH5Kou2IcdhVILT5u4ynT2KVCtYo6ip5/DZTpNhvrrVF93vNkbqe XrfF5WwTa8iuaDImdq/T =8o+H -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/vga-20190628-pull-request' into staging vga: ati fixes, add ati vgabios. # gpg: Signature made Fri 28 Jun 2019 11:39:32 BST # gpg: using RSA key 4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/vga-20190628-pull-request: ati-vga: switch to vgabios-ati.bin seabios: add ati vgabios binary seabios: add config for ati vgabios ati-vga: Fixes to offset and pitch registers ati-vga: Implement DDC and EDID info from monitor i2c: Move bitbang_i2c.h to include/hw/i2c/ Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0094908375
|
@ -130,3 +130,5 @@ config ATI_VGA
|
|||
default y if PCI_DEVICES
|
||||
depends on PCI
|
||||
select VGA
|
||||
select BITBANG_I2C
|
||||
select DDC
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "qapi/error.h"
|
||||
#include "hw/hw.h"
|
||||
#include "ui/console.h"
|
||||
#include "hw/display/i2c-ddc.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define ATI_DEBUG_HW_CURSOR 0
|
||||
|
@ -215,6 +216,24 @@ static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
|
|||
}
|
||||
}
|
||||
|
||||
static uint64_t ati_i2c(bitbang_i2c_interface *i2c, uint64_t data, int base)
|
||||
{
|
||||
bool c = (data & BIT(base + 17) ? !!(data & BIT(base + 1)) : 1);
|
||||
bool d = (data & BIT(base + 16) ? !!(data & BIT(base)) : 1);
|
||||
|
||||
bitbang_i2c_set(i2c, BITBANG_I2C_SCL, c);
|
||||
d = bitbang_i2c_set(i2c, BITBANG_I2C_SDA, d);
|
||||
|
||||
data &= ~0xf00ULL;
|
||||
if (c) {
|
||||
data |= BIT(base + 9);
|
||||
}
|
||||
if (d) {
|
||||
data |= BIT(base + 8);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
|
||||
unsigned int size)
|
||||
{
|
||||
|
@ -266,7 +285,16 @@ 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_VGA_DDC:
|
||||
val = s->regs.gpio_vga_ddc;
|
||||
break;
|
||||
case GPIO_DVI_DDC:
|
||||
val = s->regs.gpio_dvi_ddc;
|
||||
break;
|
||||
case GPIO_MONID ... GPIO_MONID + 3:
|
||||
val = ati_reg_read_offs(s->regs.gpio_monid,
|
||||
addr - GPIO_MONID, size);
|
||||
break;
|
||||
case PALETTE_INDEX:
|
||||
/* FIXME unaligned access */
|
||||
val = vga_ioport_read(&s->vga, VGA_PEL_IR) << 16;
|
||||
|
@ -391,9 +419,15 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
|
|||
break;
|
||||
case DEFAULT_OFFSET:
|
||||
val = s->regs.default_offset;
|
||||
if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
val >>= 10;
|
||||
val |= s->regs.default_pitch << 16;
|
||||
val |= s->regs.default_tile << 30;
|
||||
}
|
||||
break;
|
||||
case DEFAULT_PITCH:
|
||||
val = s->regs.default_pitch;
|
||||
val |= s->regs.default_tile << 16;
|
||||
break;
|
||||
case DEFAULT_SC_BOTTOM_RIGHT:
|
||||
val = s->regs.default_sc_bottom_right;
|
||||
|
@ -497,7 +531,33 @@ 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_VGA_DDC:
|
||||
if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
/* FIXME: Maybe add a property to select VGA or DVI port? */
|
||||
}
|
||||
break;
|
||||
case GPIO_DVI_DDC:
|
||||
if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
s->regs.gpio_dvi_ddc = ati_i2c(s->bbi2c, data, 0);
|
||||
}
|
||||
break;
|
||||
case GPIO_MONID ... GPIO_MONID + 3:
|
||||
/* FIXME What does Radeon have here? */
|
||||
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
ati_reg_write_offs(&s->regs.gpio_monid,
|
||||
addr - GPIO_MONID, data, size);
|
||||
/*
|
||||
* Rage128p accesses DDC used to get EDID via these bits.
|
||||
* Only touch i2c when write overlaps 3rd byte because some
|
||||
* drivers access this reg via multiple partial writes and
|
||||
* without this spurious bits would be sent.
|
||||
*/
|
||||
if ((s->regs.gpio_monid & BIT(25)) &&
|
||||
addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) {
|
||||
s->regs.gpio_monid = ati_i2c(s->bbi2c, s->regs.gpio_monid, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PALETTE_INDEX ... PALETTE_INDEX + 3:
|
||||
if (size == 4) {
|
||||
vga_ioport_write(&s->vga, VGA_PEL_IR, (data >> 16) & 0xff);
|
||||
|
@ -628,22 +688,22 @@ static void ati_mm_write(void *opaque, hwaddr addr,
|
|||
break;
|
||||
case SRC_PITCH_OFFSET:
|
||||
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
s->regs.src_offset = (data & 0x1fffff) << 5;
|
||||
s->regs.src_pitch = (data >> 21) & 0x3ff;
|
||||
s->regs.src_offset = (data & 0x1fffff) << 4;
|
||||
s->regs.src_pitch = (data & 0x7fe00000) >> 21;
|
||||
s->regs.src_tile = data >> 31;
|
||||
} else {
|
||||
s->regs.src_offset = (data & 0x3fffff) << 11;
|
||||
s->regs.src_offset = (data & 0x3fffff) << 10;
|
||||
s->regs.src_pitch = (data & 0x3fc00000) >> 16;
|
||||
s->regs.src_tile = (data >> 30) & 1;
|
||||
}
|
||||
break;
|
||||
case DST_PITCH_OFFSET:
|
||||
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
s->regs.dst_offset = (data & 0x1fffff) << 5;
|
||||
s->regs.dst_pitch = (data >> 21) & 0x3ff;
|
||||
s->regs.dst_offset = (data & 0x1fffff) << 4;
|
||||
s->regs.dst_pitch = (data & 0x7fe00000) >> 21;
|
||||
s->regs.dst_tile = data >> 31;
|
||||
} else {
|
||||
s->regs.dst_offset = (data & 0x3fffff) << 11;
|
||||
s->regs.dst_offset = (data & 0x3fffff) << 10;
|
||||
s->regs.dst_pitch = (data & 0x3fc00000) >> 16;
|
||||
s->regs.dst_tile = data >> 30;
|
||||
}
|
||||
|
@ -723,13 +783,19 @@ static void ati_mm_write(void *opaque, hwaddr addr,
|
|||
s->regs.dp_write_mask = data;
|
||||
break;
|
||||
case DEFAULT_OFFSET:
|
||||
data &= (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF ?
|
||||
0x03fffc00 : 0xfffffc00);
|
||||
s->regs.default_offset = data;
|
||||
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
s->regs.default_offset = data & 0xfffffff0;
|
||||
} else {
|
||||
/* Radeon has DEFAULT_PITCH_OFFSET here like DST_PITCH_OFFSET */
|
||||
s->regs.default_offset = (data & 0x3fffff) << 10;
|
||||
s->regs.default_pitch = (data & 0x3fc00000) >> 16;
|
||||
s->regs.default_tile = data >> 30;
|
||||
}
|
||||
break;
|
||||
case DEFAULT_PITCH:
|
||||
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
s->regs.default_pitch = data & 0x103ff;
|
||||
s->regs.default_pitch = data & 0x3fff;
|
||||
s->regs.default_tile = (data >> 16) & 1;
|
||||
}
|
||||
break;
|
||||
case DEFAULT_SC_BOTTOM_RIGHT:
|
||||
|
@ -788,6 +854,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);
|
||||
|
@ -813,6 +885,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[] = {
|
||||
|
@ -837,7 +910,7 @@ static void ati_vga_class_init(ObjectClass *klass, void *data)
|
|||
k->class_id = PCI_CLASS_DISPLAY_VGA;
|
||||
k->vendor_id = PCI_VENDOR_ID_ATI;
|
||||
k->device_id = PCI_DEVICE_ID_ATI_RAGE128_PF;
|
||||
k->romfile = "vgabios-stdvga.bin";
|
||||
k->romfile = "vgabios-ati.bin";
|
||||
k->realize = ati_vga_realize;
|
||||
k->exit = ati_vga_exit;
|
||||
}
|
||||
|
|
|
@ -51,8 +51,9 @@ void ati_2d_blt(ATIVGAState *s)
|
|||
s->vga.vbe_start_addr, surface_data(ds), surface_stride(ds),
|
||||
surface_bits_per_pixel(ds),
|
||||
(s->regs.dp_mix & GMC_ROP3_MASK) >> 16);
|
||||
DPRINTF("%d %d, %d %d, (%d,%d) -> (%d,%d) %dx%d\n", s->regs.src_offset,
|
||||
s->regs.dst_offset, s->regs.src_pitch, s->regs.dst_pitch,
|
||||
DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d\n",
|
||||
s->regs.src_offset, s->regs.dst_offset, s->regs.default_offset,
|
||||
s->regs.src_pitch, s->regs.dst_pitch, s->regs.default_pitch,
|
||||
s->regs.src_x, s->regs.src_y, s->regs.dst_x, s->regs.dst_y,
|
||||
s->regs.dst_width, s->regs.dst_height);
|
||||
switch (s->regs.dp_mix & GMC_ROP3_MASK) {
|
||||
|
@ -60,10 +61,16 @@ void ati_2d_blt(ATIVGAState *s)
|
|||
{
|
||||
uint8_t *src_bits, *dst_bits, *end;
|
||||
int src_stride, dst_stride, bpp = ati_bpp_from_datatype(s);
|
||||
src_bits = s->vga.vram_ptr + s->regs.src_offset;
|
||||
dst_bits = s->vga.vram_ptr + s->regs.dst_offset;
|
||||
src_stride = s->regs.src_pitch;
|
||||
dst_stride = s->regs.dst_pitch;
|
||||
src_bits = s->vga.vram_ptr +
|
||||
(s->regs.dp_gui_master_cntl & GMC_SRC_PITCH_OFFSET_CNTL ?
|
||||
s->regs.src_offset : s->regs.default_offset);
|
||||
dst_bits = s->vga.vram_ptr +
|
||||
(s->regs.dp_gui_master_cntl & GMC_DST_PITCH_OFFSET_CNTL ?
|
||||
s->regs.dst_offset : s->regs.default_offset);
|
||||
src_stride = (s->regs.dp_gui_master_cntl & GMC_SRC_PITCH_OFFSET_CNTL ?
|
||||
s->regs.src_pitch : s->regs.default_pitch);
|
||||
dst_stride = (s->regs.dp_gui_master_cntl & GMC_DST_PITCH_OFFSET_CNTL ?
|
||||
s->regs.dst_pitch : s->regs.default_pitch);
|
||||
|
||||
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
src_bits += s->regs.crtc_offset & 0x07ffffff;
|
||||
|
@ -111,8 +118,11 @@ void ati_2d_blt(ATIVGAState *s)
|
|||
uint8_t *dst_bits, *end;
|
||||
int dst_stride, bpp = ati_bpp_from_datatype(s);
|
||||
uint32_t filler = 0;
|
||||
dst_bits = s->vga.vram_ptr + s->regs.dst_offset;
|
||||
dst_stride = s->regs.dst_pitch;
|
||||
dst_bits = s->vga.vram_ptr +
|
||||
(s->regs.dp_gui_master_cntl & GMC_DST_PITCH_OFFSET_CNTL ?
|
||||
s->regs.dst_offset : s->regs.default_offset);
|
||||
dst_stride = (s->regs.dp_gui_master_cntl & GMC_DST_PITCH_OFFSET_CNTL ?
|
||||
s->regs.dst_pitch : s->regs.default_pitch);
|
||||
|
||||
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
|
||||
dst_bits += s->regs.crtc_offset & 0x07ffffff;
|
||||
|
|
|
@ -19,6 +19,8 @@ static struct ati_regdesc ati_reg_names[] = {
|
|||
{"CRTC_GEN_CNTL", 0x0050},
|
||||
{"CRTC_EXT_CNTL", 0x0054},
|
||||
{"DAC_CNTL", 0x0058},
|
||||
{"GPIO_VGA_DDC", 0x0060},
|
||||
{"GPIO_DVI_DDC", 0x0064},
|
||||
{"GPIO_MONID", 0x0068},
|
||||
{"I2C_CNTL_1", 0x0094},
|
||||
{"PALETTE_INDEX", 0x00b0},
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define ATI_INT_H
|
||||
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/i2c/bitbang_i2c.h"
|
||||
#include "vga_int.h"
|
||||
|
||||
/*#define DEBUG_ATI*/
|
||||
|
@ -35,6 +36,9 @@ typedef struct ATIVGARegs {
|
|||
uint32_t crtc_gen_cntl;
|
||||
uint32_t crtc_ext_cntl;
|
||||
uint32_t dac_cntl;
|
||||
uint32_t gpio_vga_ddc;
|
||||
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;
|
||||
|
@ -70,6 +74,7 @@ typedef struct ATIVGARegs {
|
|||
uint32_t dp_write_mask;
|
||||
uint32_t default_offset;
|
||||
uint32_t default_pitch;
|
||||
uint32_t default_tile;
|
||||
uint32_t default_sc_bottom_right;
|
||||
} ATIVGARegs;
|
||||
|
||||
|
@ -83,6 +88,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,8 @@
|
|||
#define CRTC_GEN_CNTL 0x0050
|
||||
#define CRTC_EXT_CNTL 0x0054
|
||||
#define DAC_CNTL 0x0058
|
||||
#define GPIO_VGA_DDC 0x0060
|
||||
#define GPIO_DVI_DDC 0x0064
|
||||
#define GPIO_MONID 0x0068
|
||||
#define I2C_CNTL_1 0x0094
|
||||
#define PALETTE_INDEX 0x00b0
|
||||
|
@ -368,8 +370,8 @@
|
|||
#define BRUSH_SOLIDCOLOR 0x00000d00
|
||||
|
||||
/* DP_GUI_MASTER_CNTL bit constants */
|
||||
#define GMC_SRC_PITCH_OFFSET_DEFAULT 0x00000000
|
||||
#define GMC_DST_PITCH_OFFSET_DEFAULT 0x00000000
|
||||
#define GMC_SRC_PITCH_OFFSET_CNTL 0x00000001
|
||||
#define GMC_DST_PITCH_OFFSET_CNTL 0x00000002
|
||||
#define GMC_SRC_CLIP_DEFAULT 0x00000000
|
||||
#define GMC_DST_CLIP_DEFAULT 0x00000000
|
||||
#define GMC_BRUSH_SOLIDCOLOR 0x000000d0
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "bitbang_i2c.h"
|
||||
#include "hw/i2c/bitbang_i2c.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "cpu.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/i2c/ppc4xx_i2c.h"
|
||||
#include "bitbang_i2c.h"
|
||||
|
||||
#define PPC4xx_I2C_MEM_SIZE 18
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "bitbang_i2c.h"
|
||||
#include "hw/i2c/bitbang_i2c.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "hw/i2c/i2c.h"
|
||||
|
||||
typedef struct bitbang_i2c_interface bitbang_i2c_interface;
|
||||
|
||||
#define BITBANG_I2C_SDA 0
|
||||
#define BITBANG_I2C_SCL 1
|
||||
|
|
@ -81,8 +81,6 @@ uint8_t i2c_recv(I2CBus *bus);
|
|||
|
||||
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
|
||||
|
||||
typedef struct bitbang_i2c_interface bitbang_i2c_interface;
|
||||
|
||||
/* lm832x.c */
|
||||
void lm832x_key_event(DeviceState *dev, int key, int state);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define PPC4XX_I2C_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/i2c/i2c.h"
|
||||
#include "hw/i2c/bitbang_i2c.h"
|
||||
|
||||
#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
|
||||
#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
CONFIG_QEMU=y
|
||||
CONFIG_BUILD_VGABIOS=y
|
||||
CONFIG_VGA_ATI=y
|
||||
CONFIG_VGA_PCI=y
|
Loading…
Reference in New Issue