ES1371 improvements, including codec select

This commit is contained in:
RichardG867
2021-11-20 23:24:11 -03:00
parent 1e98d531f2
commit 2bc486612b
3 changed files with 132 additions and 27 deletions

View File

@@ -93,6 +93,18 @@
#define AC97_PRL (1 << 14) #define AC97_PRL (1 << 14)
/* New codecs should be added to the end of this enum to avoid breaking configs. */
enum {
AC97_CODEC_AD1881 = 0,
AC97_CODEC_ALC100,
AC97_CODEC_CS4297,
AC97_CODEC_CS4297A,
AC97_CODEC_WM9701A,
AC97_CODEC_STAC9708,
AC97_CODEC_STAC9721
};
typedef struct { typedef struct {
const uint16_t index, value, write_mask; const uint16_t index, value, write_mask;
} ac97_vendor_reg_t; } ac97_vendor_reg_t;
@@ -112,6 +124,7 @@ extern void ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val);
extern void ac97_codec_reset(void *priv); extern void ac97_codec_reset(void *priv);
extern void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r); extern void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r);
extern uint32_t ac97_codec_getrate(void *priv, uint8_t reg); extern uint32_t ac97_codec_getrate(void *priv, uint8_t reg);
extern const device_t *ac97_codec_get(int model);
extern void ac97_via_set_slot(void *priv, int slot, int irq_pin); extern void ac97_via_set_slot(void *priv, int slot, int irq_pin);
extern uint8_t ac97_via_read_status(void *priv, uint8_t modem); extern uint8_t ac97_via_read_status(void *priv, uint8_t modem);
@@ -122,15 +135,17 @@ extern void ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t
extern void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable); extern void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable);
#ifdef EMU_DEVICE_H
extern ac97_codec_t **ac97_codec, **ac97_modem_codec; extern ac97_codec_t **ac97_codec, **ac97_modem_codec;
extern int ac97_codec_count, ac97_modem_codec_count, extern int ac97_codec_count, ac97_modem_codec_count,
ac97_codec_id, ac97_modem_codec_id; ac97_codec_id, ac97_modem_codec_id;
#ifdef EMU_DEVICE_H
extern const device_t ad1881_device; extern const device_t ad1881_device;
extern const device_t alc100_device; extern const device_t alc100_device;
extern const device_t cs4297_device; extern const device_t cs4297_device;
extern const device_t cs4297a_device; extern const device_t cs4297a_device;
extern const device_t stac9708_device;
extern const device_t stac9721_device;
extern const device_t wm9701a_device; extern const device_t wm9701a_device;
extern const device_t ac97_via_device; extern const device_t ac97_via_device;

View File

@@ -26,19 +26,12 @@
#include <86box/snd_ac97.h> #include <86box/snd_ac97.h>
enum {
AC97_CODEC_AD1881,
AC97_CODEC_ALC100,
AC97_CODEC_CS4297,
AC97_CODEC_CS4297A,
AC97_CODEC_WM9701A
};
static const struct { static const struct {
const uint32_t vendor_id, max_rate, misc_flags; /* definitions for misc_flags in snd_ac97.h */ const uint32_t vendor_id, max_rate, misc_flags; /* definitions for misc_flags in snd_ac97.h */
const uint16_t reset_flags, extid_flags, /* definitions in snd_ac97.h */ const uint16_t reset_flags, extid_flags, /* definitions in snd_ac97.h */
powerdown_mask; /* bits [7:0] => register 26 bits [15:8]; bits [11:8] => register 2A bits [14:11] */ powerdown_mask; /* bits [7:0] => register 26 bits [15:8]; bits [11:8] => register 2A bits [14:11] */
const ac97_vendor_reg_t *vendor_regs; /* bits [11:8] of index are the page number if applicable (registers [60:6F]) */ const ac97_vendor_reg_t *vendor_regs; /* bits [11:8] of index are the page number if applicable (registers [60:6F]) */
const device_t *device;
} ac97_codecs[] = { } ac97_codecs[] = {
[AC97_CODEC_AD1881] = { [AC97_CODEC_AD1881] = {
.vendor_id = AC97_VENDOR_ID('A', 'D', 'S', 0x40), .vendor_id = AC97_VENDOR_ID('A', 'D', 'S', 0x40),
@@ -46,7 +39,8 @@ static const struct {
.misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_POP | AC97_MS | AC97_LPBK, .misc_flags = AC97_MASTER_6B | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_POP | AC97_MS | AC97_LPBK,
.reset_flags = (1 << AC97_3D_SHIFT), /* datasheet contradicts itself on AC97_HPOUT */ .reset_flags = (1 << AC97_3D_SHIFT), /* datasheet contradicts itself on AC97_HPOUT */
.extid_flags = AC97_VRA, .extid_flags = AC97_VRA,
.powerdown_mask = 0x0bf .powerdown_mask = 0x0bf,
.device = &ad1881_device
}, },
[AC97_CODEC_ALC100] = { [AC97_CODEC_ALC100] = {
.vendor_id = AC97_VENDOR_ID('A', 'L', 'C', 0x20), .vendor_id = AC97_VENDOR_ID('A', 'L', 'C', 0x20),
@@ -54,7 +48,8 @@ static const struct {
.misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_POP | AC97_MS | AC97_LPBK, .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_POP | AC97_MS | AC97_LPBK,
.reset_flags = (22 << AC97_3D_SHIFT), .reset_flags = (22 << AC97_3D_SHIFT),
.extid_flags = AC97_AMAP, .extid_flags = AC97_AMAP,
.powerdown_mask = 0x0bf .powerdown_mask = 0x0bf,
.device = &alc100_device
}, },
[AC97_CODEC_CS4297] = { [AC97_CODEC_CS4297] = {
.vendor_id = AC97_VENDOR_ID('C', 'R', 'Y', 0x03), .vendor_id = AC97_VENDOR_ID('C', 'R', 'Y', 0x03),
@@ -63,7 +58,8 @@ static const struct {
.reset_flags = AC97_HPOUT | AC97_DAC_18B | AC97_ADC_18B, .reset_flags = AC97_HPOUT | AC97_DAC_18B | AC97_ADC_18B,
.extid_flags = 0, .extid_flags = 0,
.powerdown_mask = 0x07f, .powerdown_mask = 0x07f,
.vendor_regs = (const ac97_vendor_reg_t[]) {{0x05a, 0x0301, 0x0000}, {0}} .vendor_regs = (const ac97_vendor_reg_t[]) {{0x5a, 0x0301, 0x0000}, {0}},
.device = &cs4297_device
}, },
[AC97_CODEC_CS4297A] = { [AC97_CODEC_CS4297A] = {
.vendor_id = AC97_VENDOR_ID('C', 'R', 'Y', 0x11), .vendor_id = AC97_VENDOR_ID('C', 'R', 'Y', 0x11),
@@ -72,7 +68,28 @@ static const struct {
.reset_flags = AC97_HPOUT | AC97_DAC_20B | AC97_ADC_18B | (6 << AC97_3D_SHIFT), .reset_flags = AC97_HPOUT | AC97_DAC_20B | AC97_ADC_18B | (6 << AC97_3D_SHIFT),
.extid_flags = AC97_AMAP, .extid_flags = AC97_AMAP,
.powerdown_mask = 0x0ff, .powerdown_mask = 0x0ff,
.vendor_regs = (const ac97_vendor_reg_t[]) {{0x05e, 0x0000, 0x01b0}, {0x060, 0x0023, 0x0001}, {0x068, 0x0000, 0xdfff}, {0}} .vendor_regs = (const ac97_vendor_reg_t[]) {{0x5e, 0x0000, 0x01b0}, {0x60, 0x0023, 0x0001}, {0x68, 0x0000, 0xdfff}, {0}},
.device = &cs4297a_device
},
[AC97_CODEC_STAC9708] = {
.vendor_id = AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x08),
.max_rate = 48000,
.misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK,
.reset_flags = (26 << AC97_3D_SHIFT) | AC97_DAC_18B | AC97_ADC_18B,
.extid_flags = AC97_SDAC,
.powerdown_mask = 0x2ff,
.vendor_regs = (const ac97_vendor_reg_t []) {{0x6c, 0x0000, 0x0003}, {0x74, 0x0000, 0x0003}, {0}},
.device = &stac9708_device
},
[AC97_CODEC_STAC9721] = {
.vendor_id = AC97_VENDOR_ID(0x83, 0x84, 0x76, 0x09),
.max_rate = 48000,
.misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK,
.reset_flags = (26 << AC97_3D_SHIFT) | AC97_DAC_18B | AC97_ADC_18B,
.extid_flags = AC97_AMAP,
.powerdown_mask = 0x0ff,
.vendor_regs = (const ac97_vendor_reg_t []) {{0x6c, 0x0000, 0x0000}, {0x6e, 0x0000, 0x0003}, {0x70, 0x0000, 0xffff}, {0x72, 0x0000, 0x0006}, {0x74, 0x0000, 0x0003}, {0x76, 0x0000, 0xffff}, {0x78, 0x0000, 0x3802}, {0}},
.device = &stac9721_device
}, },
[AC97_CODEC_WM9701A] = { [AC97_CODEC_WM9701A] = {
.vendor_id = AC97_VENDOR_ID('W', 'M', 'L', 0x00), .vendor_id = AC97_VENDOR_ID('W', 'M', 'L', 0x00),
@@ -80,7 +97,8 @@ static const struct {
.misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK, .misc_flags = AC97_AUXOUT | AC97_MONOOUT | AC97_PCBEEP | AC97_PHONE | AC97_VIDEO | AC97_AUXIN | AC97_MS | AC97_LPBK,
.reset_flags = AC97_DAC_18B | AC97_ADC_18B, .reset_flags = AC97_DAC_18B | AC97_ADC_18B,
.extid_flags = 0, .extid_flags = 0,
.powerdown_mask = 0x03f .powerdown_mask = 0x03f,
.device = &wm9701a_device
} }
}; };
@@ -257,6 +275,13 @@ line_gain: val &= 0x9f1f;
val &= 0x0003; val &= 0x0003;
break; break;
case 26: /* SigmaTel */
i = 0x0003;
if (dev->extid_flags & AC97_SDAC)
i |= 0x000c;
val &= i;
break;
default: default:
return; return;
} }
@@ -433,6 +458,9 @@ ac97_codec_reset(void *priv)
dev->regs[0x14 >> 1] = AC97_MUTE | 0x0808; dev->regs[0x14 >> 1] = AC97_MUTE | 0x0808;
if (dev->misc_flags & AC97_AUXIN) if (dev->misc_flags & AC97_AUXIN)
dev->regs[0x14 >> 1] = AC97_MUTE | 0x0808; dev->regs[0x14 >> 1] = AC97_MUTE | 0x0808;
dev->regs[0x1c] = AC97_MUTE; /* record gain */
if (dev->reset_flags & AC97_MICPCM)
dev->regs[0x1e] = AC97_MUTE; /* mic record gain */
if (dev->misc_flags & AC97_LDAC) if (dev->misc_flags & AC97_LDAC)
dev->regs[0x36 >> 1] = AC97_MUTE_L; dev->regs[0x36 >> 1] = AC97_MUTE_L;
if (dev->misc_flags & AC97_CDAC) if (dev->misc_flags & AC97_CDAC)
@@ -594,6 +622,16 @@ ac97_codec_close(void *priv)
} }
const device_t *
ac97_codec_get(int model)
{
if ((model >= 0) && (model < (sizeof(ac97_codecs) / sizeof(ac97_codecs[0]))))
return ac97_codecs[model].device;
else
return &cs4297a_device; /* fallback */
}
const device_t ad1881_device = const device_t ad1881_device =
{ {
"Analog Devices AD1881", "Analog Devices AD1881",
@@ -642,6 +680,30 @@ const device_t cs4297a_device =
NULL NULL
}; };
const device_t stac9708_device =
{
"SigmaTel STAC9708",
DEVICE_AC97,
AC97_CODEC_STAC9708,
ac97_codec_init, ac97_codec_close, ac97_codec_reset,
{ NULL },
NULL,
NULL,
NULL
};
const device_t stac9721_device =
{
"SigmaTel STAC9721",
DEVICE_AC97,
AC97_CODEC_STAC9721,
ac97_codec_init, ac97_codec_close, ac97_codec_reset,
{ NULL },
NULL,
NULL,
NULL
};
const device_t wm9701a_device = const device_t wm9701a_device =
{ {
"Wolfson WM9701A", "Wolfson WM9701A",

View File

@@ -99,6 +99,7 @@ typedef struct {
int64_t dac_latch, dac_time; int64_t dac_latch, dac_time;
int master_vol_l, master_vol_r, int master_vol_l, master_vol_r,
pcm_vol_l, pcm_vol_r,
cd_vol_l, cd_vol_r; cd_vol_l, cd_vol_r;
int card; int card;
@@ -1019,6 +1020,7 @@ es1371_outl(uint16_t port, uint32_t val, void *p)
ac97_codec_writew(dev->codec, val >> 16, val); ac97_codec_writew(dev->codec, val >> 16, val);
ac97_codec_getattn(dev->codec, 0x02, &dev->master_vol_l, &dev->master_vol_r); ac97_codec_getattn(dev->codec, 0x02, &dev->master_vol_l, &dev->master_vol_r);
ac97_codec_getattn(dev->codec, 0x18, &dev->pcm_vol_l, &dev->pcm_vol_r);
ac97_codec_getattn(dev->codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r); ac97_codec_getattn(dev->codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r);
} }
break; break;
@@ -1407,7 +1409,7 @@ es1371_pci_read(int func, int addr, void *p)
case 0x06: return 0x10; /* Supports ACPI */ case 0x06: return 0x10; /* Supports ACPI */
case 0x07: return 0x00; case 0x07: return 0x00;
case 0x08: return 0x02; /* Revision ID */ case 0x08: return 0x08; /* Revision ID - 0x02 (datasheet, VMware) has issues with the 2001 Creative WDM driver */
case 0x09: return 0x00; /* Multimedia audio device */ case 0x09: return 0x00; /* Multimedia audio device */
case 0x0a: return 0x01; case 0x0a: return 0x01;
case 0x0b: return 0x04; case 0x0b: return 0x04;
@@ -1664,8 +1666,8 @@ es1371_update(es1371_t *dev)
l >>= 1; l >>= 1;
r >>= 1; r >>= 1;
l = (l * dev->master_vol_l) >> 15; l = (((l * dev->pcm_vol_l) >> 15) * dev->master_vol_l) >> 15;
r = (r * dev->master_vol_r) >> 15; r = (((r * dev->pcm_vol_r) >> 15) * dev->master_vol_r) >> 15;
if (l < -32768) if (l < -32768)
l = -32768; l = -32768;
@@ -1694,7 +1696,7 @@ es1371_poll(void *p)
es1371_update(dev); es1371_update(dev);
if (dev->int_ctrl & INT_UART_EN) { if (dev->int_ctrl & INT_UART_EN) {
audiopci_log("UART INT Enabled\n"); //audiopci_log("UART INT Enabled\n");
if (dev->uart_ctrl & UART_CTRL_RXINTEN) { if (dev->uart_ctrl & UART_CTRL_RXINTEN) {
/* We currently don't implement MIDI Input. /* We currently don't implement MIDI Input.
But if anything sets MIDI Input and Output together we'd have to take account But if anything sets MIDI Input and Output together we'd have to take account
@@ -1710,7 +1712,7 @@ es1371_poll(void *p)
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
} }
audiopci_log("UART control = %02x\n", dev->uart_ctrl & (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN)); //audiopci_log("UART control = %02x\n", dev->uart_ctrl & (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN));
es1371_update_irqs(dev); es1371_update_irqs(dev);
} }
@@ -1785,14 +1787,12 @@ static void
es1371_filter_cd_audio(int channel, double *buffer, void *p) es1371_filter_cd_audio(int channel, double *buffer, void *p)
{ {
es1371_t *dev = (es1371_t *)p; es1371_t *dev = (es1371_t *)p;
int32_t c; double c;
int cd = channel ? dev->cd_vol_r : dev->cd_vol_l; int cd = channel ? dev->cd_vol_r : dev->cd_vol_l;
int master = channel ? dev->master_vol_r : dev->master_vol_l; int master = channel ? dev->master_vol_r : dev->master_vol_l;
c = (((int32_t) *buffer) * cd) >> 15; c = ((((*buffer) * cd) / 65536.0) * master) / 65536.0;
c = (c * master) >> 15; *buffer = c;
*buffer = (double) c;
} }
@@ -1858,7 +1858,7 @@ es1371_init(const device_t *info)
ac97_codec_id = 0; ac97_codec_id = 0;
/* Let the machine decide the codec on onboard implementations. */ /* Let the machine decide the codec on onboard implementations. */
if (!info->local) if (!info->local)
device_add(&cs4297a_device); device_add(ac97_codec_get(device_get_config_int("codec")));
es1371_reset(dev); es1371_reset(dev);
@@ -1884,6 +1884,34 @@ es1371_speed_changed(void *p)
} }
static const device_config_t es1371_config[] =
{
{
.name = "codec",
.description = "CODEC",
.type = CONFIG_SELECTION,
.selection = {
{
.description = "Crystal CS4297",
.value = AC97_CODEC_CS4297
}, {
.description = "Crystal CS4297A",
.value = AC97_CODEC_CS4297A
}, {
.description = "SigmaTel STAC9708",
.value = AC97_CODEC_STAC9708
}, {
.description = "SigmaTel STAC9721",
.value = AC97_CODEC_STAC9721
}
},
.default_int = AC97_CODEC_CS4297A
}, {
"", "", -1
}
};
const device_t es1371_device = const device_t es1371_device =
{ {
"Ensoniq AudioPCI (ES1371)", "Ensoniq AudioPCI (ES1371)",
@@ -1891,11 +1919,11 @@ const device_t es1371_device =
0, 0,
es1371_init, es1371_init,
es1371_close, es1371_close,
NULL, es1371_reset,
{ NULL }, { NULL },
es1371_speed_changed, es1371_speed_changed,
NULL, NULL,
NULL es1371_config
}; };
const device_t es1371_onboard_device = const device_t es1371_onboard_device =