vid_mga: Implement DDC on the Millennium
This commit is contained in:
@@ -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_recalctimings(void *priv, svga_t *svga);
|
||||||
extern void tvp3026_hwcursor_draw(svga_t *svga, int displine);
|
extern void tvp3026_hwcursor_draw(svga_t *svga, int displine);
|
||||||
extern float tvp3026_getclock(int clock, void *priv);
|
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
|
# ifdef EMU_DEVICE_H
|
||||||
extern const device_t ati68860_ramdac_device;
|
extern const device_t ati68860_ramdac_device;
|
||||||
|
@@ -5314,6 +5314,27 @@ mystique_hwcursor_draw(svga_t *svga, int displine)
|
|||||||
svga->hwcursor_latch.addr += 16;
|
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
|
static uint8_t
|
||||||
mystique_pci_read(UNUSED(int func), int addr, void *priv)
|
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.ramdac = device_add(&tvp3026_ramdac_device);
|
||||||
mystique->svga.clock_gen = mystique->svga.ramdac;
|
mystique->svga.clock_gen = mystique->svga.ramdac;
|
||||||
mystique->svga.getclock = tvp3026_getclock;
|
mystique->svga.getclock = tvp3026_getclock;
|
||||||
|
tvp3026_gpio(mystique_tvp3026_gpio_read, mystique_tvp3026_gpio_write, mystique, mystique->svga.ramdac);
|
||||||
} else {
|
} else {
|
||||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique);
|
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique);
|
||||||
svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20,
|
svga_init(info, &mystique->svga, mystique, mystique->vram_size << 20,
|
||||||
|
@@ -55,6 +55,11 @@ typedef struct tvp3026_ramdac_t {
|
|||||||
uint8_t n;
|
uint8_t n;
|
||||||
uint8_t p;
|
uint8_t p;
|
||||||
} pix, mem, loop;
|
} 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;
|
} tvp3026_ramdac_t;
|
||||||
|
|
||||||
static void
|
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;
|
ramdac->misc = val;
|
||||||
svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT;
|
svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT;
|
||||||
break;
|
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 */
|
case 0x2c: /* PLL Address */
|
||||||
ramdac->pll_addr = val;
|
ramdac->pll_addr = val;
|
||||||
break;
|
break;
|
||||||
@@ -389,6 +404,16 @@ tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga)
|
|||||||
case 0x1e: /* Miscellaneous Control */
|
case 0x1e: /* Miscellaneous Control */
|
||||||
temp = ramdac->misc;
|
temp = ramdac->misc;
|
||||||
break;
|
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 */
|
case 0x2c: /* PLL Address */
|
||||||
temp = ramdac->pll_addr;
|
temp = ramdac->pll_addr;
|
||||||
break;
|
break;
|
||||||
@@ -630,6 +655,18 @@ tvp3026_getclock(int clock, void *priv)
|
|||||||
return f_pll;
|
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 *
|
void *
|
||||||
tvp3026_ramdac_init(const device_t *info)
|
tvp3026_ramdac_init(const device_t *info)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user