vid_mga: Implement DDC on the Millennium

This commit is contained in:
RichardG867
2023-12-16 18:26:39 -03:00
parent b57b87953d
commit 4b402c22cd
3 changed files with 60 additions and 0 deletions

View File

@@ -398,6 +398,7 @@ extern uint8_t tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, sv
extern void tvp3026_recalctimings(void *priv, svga_t *svga);
extern void tvp3026_hwcursor_draw(svga_t *svga, int displine);
extern float tvp3026_getclock(int clock, void *priv);
extern void tvp3026_gpio(uint8_t (*read)(uint8_t cntl, void *priv), void (*write)(uint8_t cntl, uint8_t data, void *priv), void *cb_priv, void *priv);
# ifdef EMU_DEVICE_H
extern const device_t ati68860_ramdac_device;

View File

@@ -5314,6 +5314,27 @@ mystique_hwcursor_draw(svga_t *svga, int displine)
svga->hwcursor_latch.addr += 16;
}
static uint8_t
mystique_tvp3026_gpio_read(uint8_t cntl, void *priv)
{
mystique_t *mystique = (mystique_t *) priv;
uint8_t ret = 0xff;
if (!i2c_gpio_get_scl(mystique->i2c_ddc))
ret &= ~0x10;
if (!i2c_gpio_get_sda(mystique->i2c_ddc))
ret &= ~0x04;
return ret;
}
static void
mystique_tvp3026_gpio_write(uint8_t cntl, uint8_t data, void *priv)
{
mystique_t *mystique = (mystique_t *) priv;
i2c_gpio_set(mystique->i2c_ddc, !(cntl & 0x10) || (data & 0x10), !(cntl & 0x04) || (data & 0x04));
}
static uint8_t
mystique_pci_read(UNUSED(int func), int addr, void *priv)
{
@@ -5625,6 +5646,7 @@ mystique_init(const device_t *info)
mystique->svga.ramdac = device_add(&tvp3026_ramdac_device);
mystique->svga.clock_gen = mystique->svga.ramdac;
mystique->svga.getclock = tvp3026_getclock;
tvp3026_gpio(mystique_tvp3026_gpio_read, mystique_tvp3026_gpio_write, mystique, mystique->svga.ramdac);
} else {
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique);
svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20,

View File

@@ -55,6 +55,11 @@ typedef struct tvp3026_ramdac_t {
uint8_t n;
uint8_t p;
} pix, mem, loop;
uint8_t gpio_cntl;
uint8_t gpio_data;
uint8_t (*gpio_read)(uint8_t cntl, void *priv);
void (*gpio_write)(uint8_t cntl, uint8_t val, void *priv);
void *gpio_priv;
} tvp3026_ramdac_t;
static void
@@ -211,6 +216,16 @@ tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svg
ramdac->misc = val;
svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT;
break;
case 0x2a: /* General-Purpose I/O Control */
ramdac->gpio_cntl = val;
if (ramdac->gpio_write)
ramdac->gpio_write(ramdac->gpio_cntl, ramdac->gpio_data, ramdac->gpio_priv);
break;
case 0x2b: /* General-Purpose I/O Data */
ramdac->gpio_data = val;
if (ramdac->gpio_write)
ramdac->gpio_write(ramdac->gpio_cntl, ramdac->gpio_data, ramdac->gpio_priv);
break;
case 0x2c: /* PLL Address */
ramdac->pll_addr = val;
break;
@@ -389,6 +404,16 @@ tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga)
case 0x1e: /* Miscellaneous Control */
temp = ramdac->misc;
break;
case 0x2a: /* General-Purpose I/O Control */
temp = ramdac->gpio_cntl;
break;
case 0x2b: /* General-Purpose I/O Data */
if (ramdac->gpio_read) {
temp = 0xe0 | (ramdac->gpio_cntl & 0x1f); /* keep upper bits untouched */
ramdac->gpio_data = (ramdac->gpio_data & temp) | (ramdac->gpio_read(ramdac->gpio_cntl, ramdac->gpio_priv) & ~temp);
}
temp = ramdac->gpio_data;
break;
case 0x2c: /* PLL Address */
temp = ramdac->pll_addr;
break;
@@ -630,6 +655,18 @@ tvp3026_getclock(int clock, void *priv)
return f_pll;
}
void
tvp3026_gpio(uint8_t (*read)(uint8_t cntl, void *priv),
void (*write)(uint8_t cntl, uint8_t val, void *priv),
void *cb_priv, void *priv)
{
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv;
ramdac->gpio_read = read;
ramdac->gpio_write = write;
ramdac->gpio_priv = cb_priv;
}
void *
tvp3026_ramdac_init(const device_t *info)
{