I2C overhaul part 7: S3 Trio and Cirrus Logic
This commit is contained in:
@@ -33,6 +33,8 @@
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/vid_ddc.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_svga_render.h>
|
||||
|
||||
@@ -208,6 +210,8 @@ typedef struct gd54xx_t
|
||||
|
||||
uint32_t extpallook[256];
|
||||
PALETTE extpal;
|
||||
|
||||
void *i2c, *ddc;
|
||||
} gd54xx_t;
|
||||
|
||||
|
||||
@@ -355,6 +359,10 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
|
||||
if (svga->crtc[0x27] < CIRRUS_ID_CLGD5429)
|
||||
gd54xx->unlocked = (svga->seqregs[6] == 0x12);
|
||||
break;
|
||||
case 0x08:
|
||||
if (gd54xx->i2c)
|
||||
i2c_gpio_set(gd54xx->i2c, !!(val & 0x01), !!(val & 0x02));
|
||||
break;
|
||||
case 0x0b: case 0x0c: case 0x0d: case 0x0e: /* VCLK stuff */
|
||||
gd54xx->vclk_n[svga->seqaddr-0x0b] = val;
|
||||
break;
|
||||
@@ -697,6 +705,15 @@ gd54xx_in(uint16_t addr, void *p)
|
||||
case 6:
|
||||
ret = svga->seqregs[6];
|
||||
break;
|
||||
case 0x08:
|
||||
if (gd54xx->i2c) {
|
||||
ret &= 0x7b;
|
||||
if (i2c_gpio_get_scl(gd54xx->i2c))
|
||||
ret |= 0x04;
|
||||
if (i2c_gpio_get_sda(gd54xx->i2c))
|
||||
ret |= 0x80;
|
||||
}
|
||||
break;
|
||||
case 0x0b: case 0x0c: case 0x0d: case 0x0e:
|
||||
ret = gd54xx->vclk_n[svga->seqaddr-0x0b];
|
||||
break;
|
||||
@@ -3252,6 +3269,11 @@ static void
|
||||
mca_add(gd5428_mca_read, gd5428_mca_write, gd5428_mca_feedb, NULL, gd54xx);
|
||||
}
|
||||
|
||||
if (gd54xx_is_5434(svga)) {
|
||||
gd54xx->i2c = i2c_gpio_init("ddc_cl54xx");
|
||||
gd54xx->ddc = ddc_init(i2c_gpio_get_bus(gd54xx->i2c));
|
||||
}
|
||||
|
||||
return gd54xx;
|
||||
}
|
||||
|
||||
@@ -3359,6 +3381,11 @@ gd54xx_close(void *p)
|
||||
gd54xx_t *gd54xx = (gd54xx_t *)p;
|
||||
|
||||
svga_close(&gd54xx->svga);
|
||||
|
||||
if (gd54xx->i2c) {
|
||||
ddc_close(gd54xx->ddc);
|
||||
i2c_gpio_close(gd54xx->i2c);
|
||||
}
|
||||
|
||||
free(gd54xx);
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
|
||||
#define STD_TIMING(idx, width, aspect_ratio) do { \
|
||||
edid.std_timings[idx].horiz_pixels = ((width) / 8) - 31; \
|
||||
edid.std_timings[idx].aspect_ratio_refresh_rate = (aspect_ratio) << 6; /* 60 Hz */ \
|
||||
edid->standard_timings[idx].horiz_pixels = ((width) / 8) - 31; \
|
||||
edid->standard_timings[idx].aspect_ratio_refresh_rate = (aspect_ratio) << 6; /* 60 Hz */ \
|
||||
} while (0)
|
||||
|
||||
enum {
|
||||
@@ -39,7 +39,7 @@ enum {
|
||||
|
||||
typedef struct {
|
||||
uint8_t horiz_pixels, aspect_ratio_refresh_rate;
|
||||
} edid_std_timing_t;
|
||||
} edid_standard_timing_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t pixel_clock_lsb, pixel_clock_msb, h_active_lsb, h_blank_lsb,
|
||||
@@ -78,7 +78,7 @@ typedef struct {
|
||||
} edid_cvt_timings_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t magic[2], reserved, type, range_limit_offsets;
|
||||
uint8_t magic[2], reserved, tag, range_limit_offsets;
|
||||
union {
|
||||
char ascii[13];
|
||||
edid_range_limits_t range_limits;
|
||||
@@ -91,99 +91,111 @@ typedef struct {
|
||||
uint8_t magic[8], mfg[2], mfg_product[2], serial[4], mfg_week, mfg_year,
|
||||
edid_version, edid_rev;
|
||||
uint8_t input_params, horiz_size, vert_size, gamma, features;
|
||||
uint8_t chromaticity[10], established_timings[3];
|
||||
edid_std_timing_t std_timings[8];
|
||||
uint8_t red_green_lsb, blue_white_lsb, red_x_msb, red_y_msb, green_x_msb,
|
||||
green_y_msb, blue_x_msb, blue_y_msb, white_x_msb, white_y_msb;
|
||||
uint8_t established_timings[3];
|
||||
edid_standard_timing_t standard_timings[8];
|
||||
union {
|
||||
edid_detailed_timing_t detailed_timings[4];
|
||||
edid_descriptor_t descriptors[4];
|
||||
};
|
||||
uint8_t extensions, checksum;
|
||||
|
||||
uint8_t ext_tag, ext_rev, ext_dtd_offset, ext_native_dtds;
|
||||
union {
|
||||
edid_detailed_timing_t ext_detailed_timings[6];
|
||||
edid_descriptor_t ext_descriptors[6];
|
||||
};
|
||||
uint8_t padding[15], checksum2;
|
||||
} edid_t;
|
||||
|
||||
|
||||
static edid_t edid;
|
||||
|
||||
|
||||
void *
|
||||
ddc_init(void *i2c)
|
||||
{
|
||||
memset(&edid.magic[1], 0xff, sizeof(edid.magic) - 2);
|
||||
edid.magic[0] = edid.magic[7] = 0x00;
|
||||
edid_t *edid = malloc(sizeof(edid_t));
|
||||
memset(edid, 0, sizeof(edid_t));
|
||||
|
||||
edid.mfg[0] = 0x09; /* manufacturer "BOX" (apparently unassigned by UEFI) */
|
||||
edid.mfg[1] = 0xf8;
|
||||
edid.mfg_week = 48;
|
||||
edid.mfg_year = 2020 - 1990;
|
||||
edid.edid_version = 0x01;
|
||||
edid.edid_rev = 0x03; /* EDID 1.3 */
|
||||
memset(&edid->magic[1], 0xff, sizeof(edid->magic) - 2);
|
||||
|
||||
edid.input_params = 0x0e; /* analog input; separate sync; composite sync; sync on green */
|
||||
edid.horiz_size = ((4.0 / 3.0) * 100) - 99; /* landscape 4:3 */
|
||||
edid.features = 0x09; /* RGB color; CVT */
|
||||
edid->mfg[0] = 0x09; /* manufacturer "BOX" (apparently unassigned by UEFI) */
|
||||
edid->mfg[1] = 0xf8;
|
||||
edid->mfg_week = 48;
|
||||
edid->mfg_year = 2020 - 1990;
|
||||
edid->edid_version = 0x01;
|
||||
edid->edid_rev = 0x04; /* EDID 1.4 */
|
||||
|
||||
edid.chromaticity[0] = 0x81;
|
||||
edid.chromaticity[1] = 0xf1;
|
||||
edid.chromaticity[2] = 0xa3;
|
||||
edid.chromaticity[3] = 0x57;
|
||||
edid.chromaticity[4] = 0x53;
|
||||
edid.chromaticity[5] = 0x9f;
|
||||
edid.chromaticity[6] = 0x27;
|
||||
edid.chromaticity[7] = 0x0a;
|
||||
edid.chromaticity[8] = 0x50;
|
||||
edid.chromaticity[9] = 0x00;
|
||||
edid->input_params = 0x0e; /* analog input; separate sync; composite sync; sync on green */
|
||||
edid->horiz_size = ((4.0 / 3.0) * 100) - 99; /* landscape 4:3 */
|
||||
edid->features = 0x09; /* RGB color; GTF/CVT */
|
||||
|
||||
memset(&edid.established_timings, 0xff, sizeof(edid.established_timings)); /* all enabled */
|
||||
edid->red_green_lsb = 0x81;
|
||||
edid->blue_white_lsb = 0xf1;
|
||||
edid->red_x_msb = 0xa3;
|
||||
edid->red_y_msb = 0x57;
|
||||
edid->green_x_msb = 0x53;
|
||||
edid->green_y_msb = 0x9f;
|
||||
edid->blue_x_msb = 0x27;
|
||||
edid->blue_y_msb = 0x0a;
|
||||
edid->white_x_msb = 0x50;
|
||||
edid->white_y_msb = 0x00;
|
||||
|
||||
memset(&edid.std_timings, 0x01, sizeof(edid.std_timings)); /* pad unused entries with 0x01 */
|
||||
STD_TIMING(0, 800, STD_ASPECT_4_3); /* 800x600 (preferred) */
|
||||
STD_TIMING(1, 1280, STD_ASPECT_16_9); /* 1280x720 */
|
||||
memset(&edid->established_timings, 0xff, sizeof(edid->established_timings)); /* all enabled */
|
||||
|
||||
memset(&edid->standard_timings, 0x01, sizeof(edid->standard_timings)); /* pad unused entries */
|
||||
STD_TIMING(0, 1280, STD_ASPECT_16_9); /* 1280x720 */
|
||||
STD_TIMING(1, 1280, STD_ASPECT_16_10); /* 1280x800 */
|
||||
STD_TIMING(2, 1366, STD_ASPECT_16_9); /* 1360x768 (closest to 1366x768) */
|
||||
STD_TIMING(3, 1600, STD_ASPECT_16_9); /* 1600x900 */
|
||||
STD_TIMING(4, 1920, STD_ASPECT_16_9); /* 1920x1080 */
|
||||
STD_TIMING(5, 2048, STD_ASPECT_4_3); /* 2048x1536 */
|
||||
STD_TIMING(3, 1440, STD_ASPECT_16_10); /* 1440x900 */
|
||||
STD_TIMING(4, 1600, STD_ASPECT_16_9); /* 1600x900 */
|
||||
STD_TIMING(5, 1680, STD_ASPECT_16_10); /* 1680x1050 */
|
||||
STD_TIMING(6, 1920, STD_ASPECT_16_9); /* 1920x1080 */
|
||||
STD_TIMING(7, 2048, STD_ASPECT_4_3); /* 2048x1536 */
|
||||
|
||||
/* Detailed timings for the preferred resolution of 800x600 */
|
||||
edid.detailed_timings[0].pixel_clock_lsb = 0xa0; /* 40000 KHz */
|
||||
edid.detailed_timings[0].pixel_clock_msb = 0x0f;
|
||||
edid.detailed_timings[0].h_active_lsb = 800 & 0xff;
|
||||
edid.detailed_timings[0].h_blank_lsb = 256 & 0xff;
|
||||
edid.detailed_timings[0].h_active_blank_msb = ((800 >> 4) & 0xf0) | ((256 >> 8) & 0x0f);
|
||||
edid.detailed_timings[0].v_active_lsb = 600 & 0xff;
|
||||
edid.detailed_timings[0].v_blank_lsb = 28;
|
||||
edid.detailed_timings[0].v_active_blank_msb = (600 >> 4) & 0xf0;
|
||||
edid.detailed_timings[0].h_front_porch_lsb = 40;
|
||||
edid.detailed_timings[0].h_sync_pulse_lsb = 128;
|
||||
edid.detailed_timings[0].v_front_porch_sync_pulse_lsb = (1 << 4) | 4;
|
||||
/* Detailed timings for the preferred mode of 800x600 */
|
||||
edid->detailed_timings[0].pixel_clock_lsb = 0xa0; /* 40000 KHz */
|
||||
edid->detailed_timings[0].pixel_clock_msb = 0x0f;
|
||||
edid->detailed_timings[0].h_active_lsb = 800 & 0xff;
|
||||
edid->detailed_timings[0].h_blank_lsb = 256 & 0xff;
|
||||
edid->detailed_timings[0].h_active_blank_msb = ((800 >> 4) & 0xf0) | ((256 >> 8) & 0x0f);
|
||||
edid->detailed_timings[0].v_active_lsb = 600 & 0xff;
|
||||
edid->detailed_timings[0].v_blank_lsb = 28;
|
||||
edid->detailed_timings[0].v_active_blank_msb = (600 >> 4) & 0xf0;
|
||||
edid->detailed_timings[0].h_front_porch_lsb = 40;
|
||||
edid->detailed_timings[0].h_sync_pulse_lsb = 128;
|
||||
edid->detailed_timings[0].v_front_porch_sync_pulse_lsb = (1 << 4) | 4;
|
||||
|
||||
edid.descriptors[1].type = 0xf7; /* established timings 3 */
|
||||
edid.descriptors[1].established_timings3.version = 0x10;
|
||||
memset(&edid.descriptors[1].established_timings3.timings, 0xff, sizeof(edid.descriptors[1].established_timings3.timings)); /* all enabled */
|
||||
edid->descriptors[1].tag = 0xf7; /* established timings 3 */
|
||||
edid->descriptors[1].established_timings3.version = 0x0a;
|
||||
memset(&edid->descriptors[1].established_timings3.timings, 0xff, sizeof(edid->descriptors[1].established_timings3.timings)); /* all enabled */
|
||||
|
||||
edid.descriptors[2].type = 0xfc; /* display name */
|
||||
memcpy(&edid.descriptors[2].ascii, "86Box Monitor", 13); /* exactly 13 characters (would otherwise require LF termination and space padding) */
|
||||
edid->descriptors[2].tag = 0xfc; /* display name */
|
||||
memcpy(&edid->descriptors[2].ascii, "86Box Monitor", 13); /* exactly 13 characters (would otherwise require LF termination and space padding) */
|
||||
|
||||
edid.descriptors[3].type = 0xfd; /* range limits */
|
||||
edid.descriptors[3].range_limits.min_v_field = 1;
|
||||
edid.descriptors[3].range_limits.max_v_field = -1;
|
||||
edid.descriptors[3].range_limits.min_h_line = 1;
|
||||
edid.descriptors[3].range_limits.max_h_line = -1;
|
||||
edid.descriptors[3].range_limits.max_pixel_clock = -1;
|
||||
edid.descriptors[3].range_limits.timing_type = 0x00; /* default GTF */
|
||||
edid.descriptors[3].range_limits.padding[0] = 0x0a;
|
||||
memset(&edid.descriptors[3].range_limits.padding[1], 0x20, sizeof(edid.descriptors[3].range_limits.padding) - 1);
|
||||
edid->descriptors[3].tag = 0xfd; /* range limits */
|
||||
edid->descriptors[3].range_limits.min_v_field = 1;
|
||||
edid->descriptors[3].range_limits.max_v_field = -1;
|
||||
edid->descriptors[3].range_limits.min_h_line = 1;
|
||||
edid->descriptors[3].range_limits.max_h_line = -1;
|
||||
edid->descriptors[3].range_limits.max_pixel_clock = -1;
|
||||
edid->descriptors[3].range_limits.timing_type = 0x00; /* default GTF */
|
||||
edid->descriptors[3].range_limits.padding[0] = 0x0a;
|
||||
memset(&edid->descriptors[3].range_limits.padding[1], 0x20, sizeof(edid->descriptors[3].range_limits.padding) - 1);
|
||||
|
||||
uint8_t *edid_data = (uint8_t *) &edid;
|
||||
uint8_t *edid_bytes = (uint8_t *) edid;
|
||||
for (uint8_t c = 0; c < 127; c++)
|
||||
edid.checksum += edid_data[c];
|
||||
edid.checksum = 256 - edid.checksum;
|
||||
edid->checksum += edid_bytes[c];
|
||||
edid->checksum = 256 - edid->checksum;
|
||||
for (uint8_t c = 128; c < 255; c++)
|
||||
edid->checksum2 += edid_bytes[c];
|
||||
edid->checksum2 = 256 - edid->checksum2;
|
||||
|
||||
return i2c_eeprom_init(i2c, 0x50, edid_data, sizeof(edid), 0);
|
||||
return i2c_eeprom_init(i2c, 0x50, edid_bytes, sizeof(edid_t), 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ddc_close(void *dev_handle)
|
||||
ddc_close(void *eeprom)
|
||||
{
|
||||
i2c_eeprom_close(dev_handle);
|
||||
i2c_eeprom_close(eeprom);
|
||||
}
|
||||
|
||||
@@ -502,7 +502,7 @@ typedef struct mystique_t
|
||||
mutex_t *lock;
|
||||
} dma;
|
||||
|
||||
void *i2c, *ddc;
|
||||
void *i2c, *i2c_ddc, *ddc;
|
||||
} mystique_t;
|
||||
|
||||
|
||||
@@ -1023,18 +1023,15 @@ mystique_read_xreg(mystique_t *mystique, int reg)
|
||||
ret = mystique->xgenioctrl;
|
||||
break;
|
||||
case XREG_XGENIODATA:
|
||||
ret = mystique->xgeniodata;
|
||||
|
||||
if (!(mystique->xgenioctrl & 0x08)) {
|
||||
ret &= 0xf7;
|
||||
if (i2c_gpio_get_scl(mystique->i2c))
|
||||
ret |= 0x08;
|
||||
}
|
||||
if (!(mystique->xgenioctrl & 0x02)) {
|
||||
ret &= 0xfd;
|
||||
if (i2c_gpio_get_sda(mystique->i2c))
|
||||
ret |= 0x02;
|
||||
}
|
||||
ret = mystique->xgeniodata & 0xf0;
|
||||
if (i2c_gpio_get_scl(mystique->i2c_ddc))
|
||||
ret |= 0x08;
|
||||
if (i2c_gpio_get_scl(mystique->i2c))
|
||||
ret |= 0x04;
|
||||
if (i2c_gpio_get_sda(mystique->i2c_ddc))
|
||||
ret |= 0x02;
|
||||
if (i2c_gpio_get_sda(mystique->i2c))
|
||||
ret |= 0x01;
|
||||
break;
|
||||
|
||||
case XREG_XSYSPLLM:
|
||||
@@ -1169,7 +1166,8 @@ mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val)
|
||||
|
||||
case XREG_XGENIOCTRL:
|
||||
mystique->xgenioctrl = val;
|
||||
i2c_gpio_set(mystique->i2c, !(mystique->xgenioctrl & 0x08) || (mystique->xgeniodata & 0x08), !(mystique->xgenioctrl & 0x02) || (mystique->xgeniodata & 0x02));
|
||||
i2c_gpio_set(mystique->i2c_ddc, !(mystique->xgenioctrl & 0x08) || (mystique->xgeniodata & 0x08), !(mystique->xgenioctrl & 0x02) || (mystique->xgeniodata & 0x02));
|
||||
i2c_gpio_set(mystique->i2c, !(mystique->xgenioctrl & 0x04) || (mystique->xgeniodata & 0x04), !(mystique->xgenioctrl & 0x01) || (mystique->xgeniodata & 0x01));
|
||||
break;
|
||||
case XREG_XGENIODATA:
|
||||
mystique->xgeniodata = val;
|
||||
@@ -5025,8 +5023,9 @@ mystique_init(const device_t *info)
|
||||
|
||||
mystique->svga.vsync_callback = mystique_vsync_callback;
|
||||
|
||||
mystique->i2c = i2c_gpio_init("ddc_mga");
|
||||
mystique->ddc = ddc_init(i2c_gpio_get_bus(mystique->i2c));
|
||||
mystique->i2c = i2c_gpio_init("i2c_mga");
|
||||
mystique->i2c_ddc = i2c_gpio_init("ddc_mga");
|
||||
mystique->ddc = ddc_init(i2c_gpio_get_bus(mystique->i2c_ddc));
|
||||
|
||||
return mystique;
|
||||
}
|
||||
@@ -5045,6 +5044,7 @@ mystique_close(void *p)
|
||||
svga_close(&mystique->svga);
|
||||
|
||||
ddc_close(mystique->ddc);
|
||||
i2c_gpio_close(mystique->i2c_ddc);
|
||||
i2c_gpio_close(mystique->i2c);
|
||||
|
||||
free(mystique);
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <86box/rom.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/vid_ddc.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_svga_render.h>
|
||||
#include "cpu.h"
|
||||
@@ -266,6 +268,9 @@ typedef struct s3_t
|
||||
int translate;
|
||||
int enable_8514;
|
||||
volatile int busy, force_busy;
|
||||
|
||||
uint8_t serialport;
|
||||
void *i2c, *ddc;
|
||||
} s3_t;
|
||||
|
||||
#define INT_VSY (1 << 0)
|
||||
@@ -274,6 +279,11 @@ typedef struct s3_t
|
||||
#define INT_FIFO_EMP (1 << 3)
|
||||
#define INT_MASK 0xf
|
||||
|
||||
#define SERIAL_PORT_SCW (1 << 0)
|
||||
#define SERIAL_PORT_SDW (1 << 1)
|
||||
#define SERIAL_PORT_SCR (1 << 2)
|
||||
#define SERIAL_PORT_SDR (1 << 3)
|
||||
|
||||
static void s3_updatemapping(s3_t *s3);
|
||||
|
||||
static void s3_accel_write(uint32_t addr, uint8_t val, void *p);
|
||||
@@ -1051,6 +1061,10 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
|
||||
s3->accel.advfunc_cntl = val;
|
||||
s3_updatemapping(s3);
|
||||
break;
|
||||
case 0xff20:
|
||||
s3->serialport = val;
|
||||
i2c_gpio_set(s3->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW));
|
||||
break;
|
||||
default:
|
||||
s3_accel_out_fifo(s3, addr & 0xffff, val);
|
||||
break;
|
||||
@@ -1084,7 +1098,10 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val)
|
||||
default:
|
||||
s3_accel_write_fifo(s3, addr, val);
|
||||
s3_accel_write_fifo(s3, addr + 1, val >> 8);
|
||||
break;
|
||||
break;
|
||||
case 0xff20:
|
||||
s3_accel_write_fifo(s3, addr, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1233,6 +1250,10 @@ s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val)
|
||||
s3_updatemapping(s3);
|
||||
break;
|
||||
|
||||
case 0xff20:
|
||||
s3_accel_write_fifo(s3, addr, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
s3_accel_write_fifo(s3, addr, val);
|
||||
s3_accel_write_fifo(s3, addr + 1, val >> 8);
|
||||
@@ -2900,6 +2921,14 @@ s3_accel_in(uint16_t port, void *p)
|
||||
else if ((s3->accel.cmd & 0x600) == 0x000 && (s3->accel.cmd & 0x100))
|
||||
s3_accel_start(1, 1, 0xffffffff, 0xff, s3);
|
||||
return temp;
|
||||
|
||||
case 0xff20: case 0xff21:
|
||||
temp = s3->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR);
|
||||
if ((s3->serialport & SERIAL_PORT_SCW) && i2c_gpio_get_scl(s3->i2c))
|
||||
temp |= SERIAL_PORT_SCR;
|
||||
if ((s3->serialport & SERIAL_PORT_SDW) && i2c_gpio_get_sda(s3->i2c))
|
||||
temp |= SERIAL_PORT_SDR;
|
||||
return temp;
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
@@ -2976,7 +3005,7 @@ s3_accel_read(uint32_t addr, void *p)
|
||||
case 0x8504:
|
||||
return s3->subsys_stat;
|
||||
case 0x8505:
|
||||
return s3->subsys_cntl;;
|
||||
return s3->subsys_cntl;
|
||||
default:
|
||||
return s3_accel_in(addr & 0xffff, p);
|
||||
}
|
||||
@@ -4662,6 +4691,9 @@ static void *s3_init(const device_t *info)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s3->i2c = i2c_gpio_init("ddc_s3");
|
||||
s3->ddc = ddc_init(i2c_gpio_get_bus(s3->i2c));
|
||||
|
||||
return s3;
|
||||
}
|
||||
|
||||
@@ -4755,6 +4787,9 @@ static void s3_close(void *p)
|
||||
thread_destroy_event(s3->wake_fifo_thread);
|
||||
thread_destroy_event(s3->fifo_not_full_event);
|
||||
|
||||
ddc_close(s3->ddc);
|
||||
i2c_gpio_close(s3->i2c);
|
||||
|
||||
free(s3);
|
||||
}
|
||||
|
||||
|
||||
@@ -447,7 +447,11 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
|
||||
return;
|
||||
if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5))
|
||||
return;
|
||||
if (svga->crtcreg >= 0x80)
|
||||
if ((svga->crtcreg >= 0x80)
|
||||
#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X)
|
||||
&& !((virge->chip == S3_TRIO3D2X) && (svga->crtcreg == 0xaa))
|
||||
#endif
|
||||
)
|
||||
return;
|
||||
old = svga->crtc[svga->crtcreg];
|
||||
svga->crtc[svga->crtcreg] = val;
|
||||
@@ -550,6 +554,12 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
|
||||
default: svga->bpp = 8; break;
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X)
|
||||
case 0xaa:
|
||||
i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (old != val)
|
||||
{
|
||||
@@ -607,6 +617,18 @@ static uint8_t s3_virge_in(uint16_t addr, void *p)
|
||||
case 0x51: ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); break;
|
||||
case 0x69: ret = virge->ma_ext; break;
|
||||
case 0x6a: ret = virge->bank; break;
|
||||
#if defined(DEV_BRANCH) && defined(USE_S3TRIO3D2X)
|
||||
case 0xaa: /* Trio3D DDC */
|
||||
if (virge->chip == S3_TRIO3D2X) {
|
||||
ret = svga->crtc[0xaa] & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR);
|
||||
if ((svga->crtc[0xaa] & SERIAL_PORT_SCW) && i2c_gpio_get_scl(virge->i2c))
|
||||
ret |= SERIAL_PORT_SCR;
|
||||
if ((svga->crtc[0xaa] & SERIAL_PORT_SDW) && i2c_gpio_get_sda(virge->i2c))
|
||||
ret |= SERIAL_PORT_SDR;
|
||||
break;
|
||||
}
|
||||
/* fall-through */
|
||||
#endif
|
||||
default: ret = svga->crtc[svga->crtcreg]; break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2702,7 +2702,7 @@ static void banshee_force_redraw(void *p)
|
||||
|
||||
const device_t voodoo_banshee_device =
|
||||
{
|
||||
"Voodoo Banshee PCI (reference)",
|
||||
"3dfx Voodoo Banshee",
|
||||
DEVICE_PCI,
|
||||
0,
|
||||
banshee_init,
|
||||
@@ -2716,7 +2716,7 @@ const device_t voodoo_banshee_device =
|
||||
|
||||
const device_t creative_voodoo_banshee_device =
|
||||
{
|
||||
"Creative Labs 3D Blaster Banshee PCI",
|
||||
"Creative 3D Blaster Banshee",
|
||||
DEVICE_PCI,
|
||||
0,
|
||||
creative_banshee_init,
|
||||
@@ -2730,7 +2730,7 @@ const device_t creative_voodoo_banshee_device =
|
||||
|
||||
const device_t voodoo_3_2000_device =
|
||||
{
|
||||
"Voodoo 3 2000 PCI",
|
||||
"3dfx Voodoo3 2000",
|
||||
DEVICE_PCI,
|
||||
0,
|
||||
v3_2000_init,
|
||||
@@ -2744,7 +2744,7 @@ const device_t voodoo_3_2000_device =
|
||||
|
||||
const device_t voodoo_3_3000_device =
|
||||
{
|
||||
"Voodoo 3 3000 PCI",
|
||||
"3dfx Voodoo3 3000",
|
||||
DEVICE_PCI,
|
||||
0,
|
||||
v3_3000_init,
|
||||
|
||||
Reference in New Issue
Block a user