aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBALATON Zoltan <balaton@eik.bme.hu>2023-11-01 21:45:37 +0100
committerMarc-André Lureau <marcandre.lureau@redhat.com>2023-11-06 15:58:40 +0400
commite876b3400a01c5f3947de34d6c10388f43192dc9 (patch)
treef2989dc20200dc87f679b8ff5fac1dca4260a74e
parentf7ecde051dd73fad8265e83c26ea69ae0a86e1d4 (diff)
downloadqemu-e876b3400a01c5f3947de34d6c10388f43192dc9.zip
qemu-e876b3400a01c5f3947de34d6c10388f43192dc9.tar.gz
qemu-e876b3400a01c5f3947de34d6c10388f43192dc9.tar.bz2
ati-vga: Support unaligned access to GPIO DDC registers
The GPIO_VGA_DDC and GPIO_DVI_DDC registers are used on Radeon for DDC access. Some drivers like the PPC Mac FCode ROM uses unaligned writes to these registers so implement this the same way as already done for GPIO_MONID which is used the same way for the Rage 128 Pro. Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu> Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <dff6ce16ccabdfd54ffda348bf57c6d8b810cd98.1698871239.git.balaton@eik.bme.hu>
-rw-r--r--hw/display/ati.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/hw/display/ati.c b/hw/display/ati.c
index 9a9ea75..538651c 100644
--- a/hw/display/ati.c
+++ b/hw/display/ati.c
@@ -319,11 +319,13 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
case DAC_CNTL:
val = s->regs.dac_cntl;
break;
- case GPIO_VGA_DDC:
- val = s->regs.gpio_vga_ddc;
+ case GPIO_VGA_DDC ... GPIO_VGA_DDC + 3:
+ val = ati_reg_read_offs(s->regs.gpio_vga_ddc,
+ addr - GPIO_VGA_DDC, size);
break;
- case GPIO_DVI_DDC:
- val = s->regs.gpio_dvi_ddc;
+ case GPIO_DVI_DDC ... GPIO_DVI_DDC + 3:
+ val = ati_reg_read_offs(s->regs.gpio_dvi_ddc,
+ addr - GPIO_DVI_DDC, size);
break;
case GPIO_MONID ... GPIO_MONID + 3:
val = ati_reg_read_offs(s->regs.gpio_monid,
@@ -615,29 +617,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_VGA_DDC:
+ /*
+ * GPIO regs for DDC access. Because some drivers access these via
+ * multiple byte writes we have to be careful when we send bits to
+ * avoid spurious changes in bitbang_i2c state. Only do it when either
+ * the enable bits are changed or output bits changed while enabled.
+ */
+ case GPIO_VGA_DDC ... GPIO_VGA_DDC + 3:
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:
+ case GPIO_DVI_DDC ... GPIO_DVI_DDC + 3:
if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
- s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c, data, 0);
+ ati_reg_write_offs(&s->regs.gpio_dvi_ddc,
+ addr - GPIO_DVI_DDC, data, size);
+ if ((addr <= GPIO_DVI_DDC + 2 && addr + size > GPIO_DVI_DDC + 2) ||
+ (addr == GPIO_DVI_DDC && (s->regs.gpio_dvi_ddc & 0x30000))) {
+ s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c,
+ s->regs.gpio_dvi_ddc, 0);
+ }
}
break;
case GPIO_MONID ... GPIO_MONID + 3:
/* FIXME What does Radeon have here? */
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
+ /* Rage128p accesses DDC via MONID(1-2) with additional mask bit */
ati_reg_write_offs(&s->regs.gpio_monid,
addr - GPIO_MONID, data, size);
- /*
- * Rage128p accesses DDC used to get EDID via these bits.
- * Because some drivers access this via multiple byte writes
- * we have to be careful when we send bits to avoid spurious
- * changes in bitbang_i2c state. So only do it when mask is set
- * and either the enable bits are changed or output bits changed
- * while enabled.
- */
if ((s->regs.gpio_monid & BIT(25)) &&
((addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) ||
(addr == GPIO_MONID && (s->regs.gpio_monid & 0x60000)))) {