Skip to content

Commit e876b34

Browse files
zbalatonelmarco
authored andcommitted
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 <[email protected]> Acked-by: Marc-André Lureau <[email protected]> Message-ID: <dff6ce16ccabdfd54ffda348bf57c6d8b810cd98.1698871239.git.balaton@eik.bme.hu>
1 parent f7ecde0 commit e876b34

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

hw/display/ati.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,13 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
319319
case DAC_CNTL:
320320
val = s->regs.dac_cntl;
321321
break;
322-
case GPIO_VGA_DDC:
323-
val = s->regs.gpio_vga_ddc;
322+
case GPIO_VGA_DDC ... GPIO_VGA_DDC + 3:
323+
val = ati_reg_read_offs(s->regs.gpio_vga_ddc,
324+
addr - GPIO_VGA_DDC, size);
324325
break;
325-
case GPIO_DVI_DDC:
326-
val = s->regs.gpio_dvi_ddc;
326+
case GPIO_DVI_DDC ... GPIO_DVI_DDC + 3:
327+
val = ati_reg_read_offs(s->regs.gpio_dvi_ddc,
328+
addr - GPIO_DVI_DDC, size);
327329
break;
328330
case GPIO_MONID ... GPIO_MONID + 3:
329331
val = ati_reg_read_offs(s->regs.gpio_monid,
@@ -615,29 +617,34 @@ static void ati_mm_write(void *opaque, hwaddr addr,
615617
s->regs.dac_cntl = data & 0xffffe3ff;
616618
s->vga.dac_8bit = !!(data & DAC_8BIT_EN);
617619
break;
618-
case GPIO_VGA_DDC:
620+
/*
621+
* GPIO regs for DDC access. Because some drivers access these via
622+
* multiple byte writes we have to be careful when we send bits to
623+
* avoid spurious changes in bitbang_i2c state. Only do it when either
624+
* the enable bits are changed or output bits changed while enabled.
625+
*/
626+
case GPIO_VGA_DDC ... GPIO_VGA_DDC + 3:
619627
if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
620628
/* FIXME: Maybe add a property to select VGA or DVI port? */
621629
}
622630
break;
623-
case GPIO_DVI_DDC:
631+
case GPIO_DVI_DDC ... GPIO_DVI_DDC + 3:
624632
if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
625-
s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c, data, 0);
633+
ati_reg_write_offs(&s->regs.gpio_dvi_ddc,
634+
addr - GPIO_DVI_DDC, data, size);
635+
if ((addr <= GPIO_DVI_DDC + 2 && addr + size > GPIO_DVI_DDC + 2) ||
636+
(addr == GPIO_DVI_DDC && (s->regs.gpio_dvi_ddc & 0x30000))) {
637+
s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c,
638+
s->regs.gpio_dvi_ddc, 0);
639+
}
626640
}
627641
break;
628642
case GPIO_MONID ... GPIO_MONID + 3:
629643
/* FIXME What does Radeon have here? */
630644
if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
645+
/* Rage128p accesses DDC via MONID(1-2) with additional mask bit */
631646
ati_reg_write_offs(&s->regs.gpio_monid,
632647
addr - GPIO_MONID, data, size);
633-
/*
634-
* Rage128p accesses DDC used to get EDID via these bits.
635-
* Because some drivers access this via multiple byte writes
636-
* we have to be careful when we send bits to avoid spurious
637-
* changes in bitbang_i2c state. So only do it when mask is set
638-
* and either the enable bits are changed or output bits changed
639-
* while enabled.
640-
*/
641648
if ((s->regs.gpio_monid & BIT(25)) &&
642649
((addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) ||
643650
(addr == GPIO_MONID && (s->regs.gpio_monid & 0x60000)))) {

0 commit comments

Comments
 (0)