Commit 00949083 authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 7d0e0240 263807f4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -130,3 +130,5 @@ config ATI_VGA
    default y if PCI_DEVICES
    depends on PCI
    select VGA
    select BITBANG_I2C
    select DDC
+86 −13
Original line number Diff line number Diff line
@@ -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;
}
+18 −8
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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},
+6 −0
Original line number Diff line number Diff line
@@ -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;
Loading