Initial implementation of the Crystal CS4232 audio controller

This commit is contained in:
win2kgamer
2025-10-25 22:20:25 -05:00
parent 3b43627f38
commit 080632bd4a
2 changed files with 54 additions and 5 deletions

View File

@@ -177,6 +177,7 @@ extern const device_t sb_awe64_ide_device;
extern const device_t sb_awe64_gold_device;
/* Crystal CS423x */
extern const device_t cs4232_onboard_device;
extern const device_t cs4235_device;
extern const device_t cs4235_onboard_device;
extern const device_t cs4236_onboard_device;

View File

@@ -88,6 +88,20 @@ static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0
0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2,
0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13,
0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A };
static const uint8_t cs4232_default[] = {
// clang-format off
/* Chip configuration */
0x00, /* external decode length */
0x48, /* reserved */
0x75, 0xb9, 0xfc, /* IRQ routing */
0x10, 0x03, /* DMA routing */
/* Default PnP data */
0x0e, 0x63, 0x42, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00 /* hinted by documentation to be just the header */
// clang-format on
};
static const uint8_t cs4236_default[] = {
// clang-format off
/* Chip configuration */
@@ -388,9 +402,17 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv)
case 6: /* RAM Access End */
/* TriGem Delhi-III BIOS writes undocumented value 0x40 instead of 0x00. */
if ((val == 0x00) || (val == 0x40)) {
/* Intel Atlantis, Holly, Monaco, Morrison and Thor BIOSes use several undocumented values */
/* 0x25, 0x60, 0x69, 0x86, 0xE2, 0xFE and 0xFF were observed on these BIOSes */
/* CS4232 likely accepts any written value to end RAM writes */
if ((val == 0x00) || (val == 0x40) || (dev->type == CRYSTAL_CS4232)) {
cs423x_log("CS423x: RAM end\n");
dev->ram_dl = CRYSTAL_RAM_CMD;
/* CS4232 resource data at 0x2090/2091 is written backwards */
if (dev->type == CRYSTAL_CS4232) {
dev->ram_data[0x2090] = 0x00;
dev->ram_data[0x2091] = 0x48;
}
/* Update PnP state and resource data. */
dev->pnp_size = (dev->type >= CRYSTAL_CS4236) ? 384 : 256; /* we don't know the length */
@@ -808,6 +830,10 @@ static void
cs423x_load_defaults(cs423x_t *dev, uint8_t *dest)
{
switch (dev->type) {
case CRYSTAL_CS4232:
memcpy(dest, cs4232_default, sizeof(cs4232_default));
dev->pnp_size = 9; /* header-only PnP ROM size */
break;
case CRYSTAL_CS4236:
case CRYSTAL_CS4236B:
case CRYSTAL_CS4237B:
@@ -841,7 +867,11 @@ cs423x_reset(void *priv)
memset(dev->ram_data, 0, sizeof(dev->ram_data));
/* Load default configuration data to RAM. */
cs423x_load_defaults(dev, &dev->ram_data[0x4000]);
/* CS4232 uses 0x2090 as the initial RAM location instead of 0x4000 */
if (dev->type == CRYSTAL_CS4232)
cs423x_load_defaults(dev, &dev->ram_data[0x2090]);
else
cs423x_load_defaults(dev, &dev->ram_data[0x4000]);
if (dev->eeprom) {
/* Load EEPROM data to RAM if the magic bytes are present. */
@@ -890,6 +920,7 @@ cs423x_init(const device_t *info)
dev->type = info->local & 0xff;
cs423x_log("CS423x: init(%02X)\n", dev->type);
switch (dev->type) {
case CRYSTAL_CS4232:
case CRYSTAL_CS4236:
case CRYSTAL_CS4236B:
case CRYSTAL_CS4237B:
@@ -897,13 +928,16 @@ cs423x_init(const device_t *info)
case CRYSTAL_CS4235:
case CRYSTAL_CS4239:
/* Different WSS codec families. */
dev->ad1848_type = (dev->type >= CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : ((dev->type >= CRYSTAL_CS4236B) ? AD1848_TYPE_CS4236B : AD1848_TYPE_CS4236);
dev->ad1848_type = (dev->type >= CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : ((dev->type >= CRYSTAL_CS4236B) ? AD1848_TYPE_CS4236B : (dev->type >= CRYSTAL_CS4236) ? AD1848_TYPE_CS4236 : AD1848_TYPE_CS4232);
/* Different Chip Version and ID values (N/A on CS4236), which shouldn't be reset by ad1848_init. */
dev->ad1848.xregs[25] = dev->type;
/* Same EEPROM structure. */
dev->pnp_offset = 0x4013;
/* Same EEPROM structure on CS4236+. CS4232 is different. */
if (dev->type == CRYSTAL_CS4232)
dev->pnp_offset = 0x2097;
else
dev->pnp_offset = 0x4013;
if (!(info->local & CRYSTAL_NOEEPROM)) {
/* Start a new EEPROM with the default configuration data. */
@@ -1056,6 +1090,20 @@ cs423x_speed_changed(void *priv)
ad1848_speed_changed(&dev->ad1848);
}
const device_t cs4232_onboard_device = {
.name = "Crystal CS4232 (On-Board)",
.internal_name = "cs4232_onboard",
.flags = DEVICE_ISA16,
.local = CRYSTAL_CS4232 | CRYSTAL_NOEEPROM,
.init = cs423x_init,
.close = cs423x_close,
.reset = cs423x_reset,
.available = cs423x_available,
.speed_changed = cs423x_speed_changed,
.force_redraw = NULL,
.config = NULL
};
const device_t cs4235_device = {
.name = "Crystal CS4235",
.internal_name = "cs4235",