VIA AC97: Move some variables to SGD structure to ease future expansion
This commit is contained in:
@@ -39,7 +39,12 @@ typedef struct {
|
|||||||
int32_t sample_count;
|
int32_t sample_count;
|
||||||
uint8_t entry_flags, fifo[32], restart;
|
uint8_t entry_flags, fifo[32], restart;
|
||||||
|
|
||||||
pc_timer_t timer;
|
int16_t out_l, out_r;
|
||||||
|
int vol_l, vol_r, pos;
|
||||||
|
int32_t buffer[SOUNDBUFLEN * 2];
|
||||||
|
uint64_t timer_latch;
|
||||||
|
|
||||||
|
pc_timer_t dma_timer, poll_timer;
|
||||||
} ac97_via_sgd_t;
|
} ac97_via_sgd_t;
|
||||||
|
|
||||||
typedef struct _ac97_via_ {
|
typedef struct _ac97_via_ {
|
||||||
@@ -56,12 +61,7 @@ typedef struct _ac97_via_ {
|
|||||||
ac97_codec_t *codec[2][2];
|
ac97_codec_t *codec[2][2];
|
||||||
ac97_via_sgd_t sgd[6];
|
ac97_via_sgd_t sgd[6];
|
||||||
|
|
||||||
pc_timer_t timer_count, timer_count_fm;
|
int master_vol_l, master_vol_r, cd_vol_l, cd_vol_r;
|
||||||
uint64_t timer_latch, timer_latch_fm;
|
|
||||||
int16_t out_l, out_r, fm_out_l, fm_out_r;
|
|
||||||
int master_vol_l, master_vol_r, pcm_vol_l, pcm_vol_r, cd_vol_l, cd_vol_r;
|
|
||||||
int32_t buffer[SOUNDBUFLEN * 2], fm_buffer[SOUNDBUFLEN * 2];
|
|
||||||
int pos, fm_pos;
|
|
||||||
} ac97_via_t;
|
} ac97_via_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -142,13 +142,13 @@ ac97_via_write_control(void *priv, uint8_t modem, uint8_t val)
|
|||||||
/* Start or stop PCM playback. */
|
/* Start or stop PCM playback. */
|
||||||
i = (val & 0xf4) == 0xc4;
|
i = (val & 0xf4) == 0xc4;
|
||||||
if (i && !dev->pcm_enabled)
|
if (i && !dev->pcm_enabled)
|
||||||
timer_advance_u64(&dev->timer_count, dev->timer_latch);
|
timer_advance_u64(&dev->sgd[0].poll_timer, dev->sgd[0].timer_latch);
|
||||||
dev->pcm_enabled = i;
|
dev->pcm_enabled = i;
|
||||||
|
|
||||||
/* Start or stop FM playback. */
|
/* Start or stop FM playback. */
|
||||||
i = (val & 0xf2) == 0xc2;
|
i = (val & 0xf2) == 0xc2;
|
||||||
if (i && !dev->fm_enabled)
|
if (i && !dev->fm_enabled)
|
||||||
timer_advance_u64(&dev->timer_count_fm, dev->timer_latch);
|
timer_advance_u64(&dev->sgd[2].poll_timer, dev->sgd[2].timer_latch);
|
||||||
dev->fm_enabled = i;
|
dev->fm_enabled = i;
|
||||||
|
|
||||||
/* Update primary audio codec state. */
|
/* Update primary audio codec state. */
|
||||||
@@ -183,7 +183,7 @@ ac97_via_update_codec(ac97_via_t *dev)
|
|||||||
|
|
||||||
/* Update volumes according to codec registers. */
|
/* Update volumes according to codec registers. */
|
||||||
ac97_codec_getattn(codec, 0x02, &dev->master_vol_l, &dev->master_vol_r);
|
ac97_codec_getattn(codec, 0x02, &dev->master_vol_l, &dev->master_vol_r);
|
||||||
ac97_codec_getattn(codec, 0x18, &dev->pcm_vol_l, &dev->pcm_vol_r);
|
ac97_codec_getattn(codec, 0x18, &dev->sgd[0].vol_l, &dev->sgd[0].vol_r);
|
||||||
ac97_codec_getattn(codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r);
|
ac97_codec_getattn(codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r);
|
||||||
|
|
||||||
/* Update sample rate according to codec registers and the variable sample rate flag. */
|
/* Update sample rate according to codec registers and the variable sample rate flag. */
|
||||||
@@ -503,10 +503,10 @@ ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ac97_via_update(ac97_via_t *dev)
|
ac97_via_update_stereo(ac97_via_t *dev, ac97_via_sgd_t *sgd)
|
||||||
{
|
{
|
||||||
int32_t l = (((dev->out_l * dev->pcm_vol_l) >> 15) * dev->master_vol_l) >> 15,
|
int32_t l = (((sgd->out_l * sgd->vol_l) >> 15) * dev->master_vol_l) >> 15,
|
||||||
r = (((dev->out_r * dev->pcm_vol_r) >> 15) * dev->master_vol_r) >> 15;
|
r = (((sgd->out_r * sgd->vol_r) >> 15) * dev->master_vol_r) >> 15;
|
||||||
|
|
||||||
if (l < -32768)
|
if (l < -32768)
|
||||||
l = -32768;
|
l = -32768;
|
||||||
@@ -517,19 +517,9 @@ ac97_via_update(ac97_via_t *dev)
|
|||||||
else if (r > 32767)
|
else if (r > 32767)
|
||||||
r = 32767;
|
r = 32767;
|
||||||
|
|
||||||
for (; dev->pos < sound_pos_global; dev->pos++) {
|
for (; sgd->pos < sound_pos_global; sgd->pos++) {
|
||||||
dev->buffer[dev->pos*2] = l;
|
sgd->buffer[sgd->pos*2] = l;
|
||||||
dev->buffer[dev->pos*2 + 1] = r;
|
sgd->buffer[sgd->pos*2 + 1] = r;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ac97_via_update_fm(ac97_via_t *dev)
|
|
||||||
{
|
|
||||||
for (; dev->fm_pos < sound_pos_global; dev->fm_pos++) {
|
|
||||||
dev->fm_buffer[dev->fm_pos*2] = dev->fm_out_l;
|
|
||||||
dev->fm_buffer[dev->fm_pos*2 + 1] = dev->fm_out_r;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +536,7 @@ ac97_via_sgd_process(void *priv)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Schedule next run. */
|
/* Schedule next run. */
|
||||||
timer_on_auto(&sgd->timer, 10.0);
|
timer_on_auto(&sgd->dma_timer, 10.0);
|
||||||
|
|
||||||
/* Process SGD if it's active, and the FIFO has room or is disabled. */
|
/* Process SGD if it's active, and the FIFO has room or is disabled. */
|
||||||
if ((sgd_status == 0x80) && (sgd->always_run || ((sgd->fifo_end - sgd->fifo_pos) <= (sizeof(sgd->fifo) - 4)))) {
|
if ((sgd_status == 0x80) && (sgd->always_run || ((sgd->fifo_end - sgd->fifo_pos) <= (sizeof(sgd->fifo) - 4)))) {
|
||||||
@@ -652,38 +642,38 @@ ac97_via_sgd_process(void *priv)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ac97_via_poll(void *priv)
|
ac97_via_poll_stereo(void *priv)
|
||||||
{
|
{
|
||||||
ac97_via_t *dev = (ac97_via_t *) priv;
|
ac97_via_t *dev = (ac97_via_t *) priv;
|
||||||
ac97_via_sgd_t *sgd = &dev->sgd[0]; /* Audio Read */
|
ac97_via_sgd_t *sgd = &dev->sgd[0]; /* Audio Read */
|
||||||
|
|
||||||
/* Schedule next run if PCM playback is enabled. */
|
/* Schedule next run if PCM playback is enabled. */
|
||||||
if (dev->pcm_enabled)
|
if (dev->pcm_enabled)
|
||||||
timer_advance_u64(&dev->timer_count, dev->timer_latch);
|
timer_advance_u64(&sgd->poll_timer, sgd->timer_latch);
|
||||||
|
|
||||||
/* Update audio buffer. */
|
/* Update stereo audio buffer. */
|
||||||
ac97_via_update(dev);
|
ac97_via_update_stereo(dev, sgd);
|
||||||
|
|
||||||
/* Feed next sample from the FIFO. */
|
/* Feed next sample from the FIFO. */
|
||||||
switch (dev->sgd_regs[0x02] & 0x30) {
|
switch (dev->sgd_regs[sgd->id | 0x2] & 0x30) {
|
||||||
case 0x00: /* Mono, 8-bit PCM */
|
case 0x00: /* Mono, 8-bit PCM */
|
||||||
if ((sgd->fifo_end - sgd->fifo_pos) >= 1) {
|
if ((sgd->fifo_end - sgd->fifo_pos) >= 1) {
|
||||||
dev->out_l = dev->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8;
|
sgd->out_l = sgd->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10: /* Stereo, 8-bit PCM */
|
case 0x10: /* Stereo, 8-bit PCM */
|
||||||
if ((sgd->fifo_end - sgd->fifo_pos) >= 2) {
|
if ((sgd->fifo_end - sgd->fifo_pos) >= 2) {
|
||||||
dev->out_l = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8;
|
sgd->out_l = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8;
|
||||||
dev->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8;
|
sgd->out_r = (sgd->fifo[sgd->fifo_pos++ & (sizeof(sgd->fifo) - 1)] ^ 0x80) << 8;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20: /* Mono, 16-bit PCM */
|
case 0x20: /* Mono, 16-bit PCM */
|
||||||
if ((sgd->fifo_end - sgd->fifo_pos) >= 2) {
|
if ((sgd->fifo_end - sgd->fifo_pos) >= 2) {
|
||||||
dev->out_l = dev->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
sgd->out_l = sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
||||||
sgd->fifo_pos += 2;
|
sgd->fifo_pos += 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -691,9 +681,9 @@ ac97_via_poll(void *priv)
|
|||||||
|
|
||||||
case 0x30: /* Stereo, 16-bit PCM */
|
case 0x30: /* Stereo, 16-bit PCM */
|
||||||
if ((sgd->fifo_end - sgd->fifo_pos) >= 4) {
|
if ((sgd->fifo_end - sgd->fifo_pos) >= 4) {
|
||||||
dev->out_l = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
sgd->out_l = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
||||||
sgd->fifo_pos += 2;
|
sgd->fifo_pos += 2;
|
||||||
dev->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
||||||
sgd->fifo_pos += 2;
|
sgd->fifo_pos += 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -701,7 +691,7 @@ ac97_via_poll(void *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Feed silence if the FIFO is empty. */
|
/* Feed silence if the FIFO is empty. */
|
||||||
dev->out_l = dev->out_r = 0;
|
sgd->out_l = sgd->out_r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -713,23 +703,23 @@ ac97_via_poll_fm(void *priv)
|
|||||||
|
|
||||||
/* Schedule next run if FM playback is enabled. */
|
/* Schedule next run if FM playback is enabled. */
|
||||||
if (dev->fm_enabled)
|
if (dev->fm_enabled)
|
||||||
timer_advance_u64(&dev->timer_count_fm, dev->timer_latch_fm);
|
timer_advance_u64(&sgd->poll_timer, sgd->timer_latch);
|
||||||
|
|
||||||
/* Update FM audio buffer. */
|
/* Update FM audio buffer. */
|
||||||
ac97_via_update_fm(dev);
|
ac97_via_update_stereo(dev, sgd);
|
||||||
|
|
||||||
/* Feed next sample from the FIFO.
|
/* Feed next sample from the FIFO.
|
||||||
The data format is not documented, but it probes as 16-bit stereo at 24 KHz. */
|
The data format is not documented, but it probes as 16-bit stereo at 24 KHz. */
|
||||||
if ((sgd->fifo_end - sgd->fifo_pos) >= 4) {
|
if ((sgd->fifo_end - sgd->fifo_pos) >= 4) {
|
||||||
dev->out_l = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
sgd->out_l = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
||||||
sgd->fifo_pos += 2;
|
sgd->fifo_pos += 2;
|
||||||
dev->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
sgd->out_r = *((uint16_t *) &sgd->fifo[sgd->fifo_pos & (sizeof(sgd->fifo) - 1)]);
|
||||||
sgd->fifo_pos += 2;
|
sgd->fifo_pos += 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Feed silence if the FIFO is empty. */
|
/* Feed silence if the FIFO is empty. */
|
||||||
dev->fm_out_l = dev->fm_out_r = 0;
|
sgd->out_l = sgd->out_r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -738,15 +728,15 @@ ac97_via_get_buffer(int32_t *buffer, int len, void *priv)
|
|||||||
{
|
{
|
||||||
ac97_via_t *dev = (ac97_via_t *) priv;
|
ac97_via_t *dev = (ac97_via_t *) priv;
|
||||||
|
|
||||||
ac97_via_update(dev);
|
ac97_via_update_stereo(dev, &dev->sgd[0]);
|
||||||
ac97_via_update_fm(dev);
|
ac97_via_update_stereo(dev, &dev->sgd[2]);
|
||||||
|
|
||||||
for (int c = 0; c < len * 2; c++) {
|
for (int c = 0; c < len * 2; c++) {
|
||||||
buffer[c] += dev->buffer[c] / 2;
|
buffer[c] += dev->sgd[0].buffer[c] / 2;
|
||||||
buffer[c] += dev->fm_buffer[c] / 2;
|
buffer[c] += dev->sgd[2].buffer[c] / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->pos = dev->fm_pos = 0;
|
dev->sgd[0].pos = dev->sgd[2].pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -773,8 +763,8 @@ ac97_via_speed_changed(void *priv)
|
|||||||
else
|
else
|
||||||
freq = 48000.0;
|
freq = 48000.0;
|
||||||
|
|
||||||
dev->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / freq));
|
dev->sgd[0].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / freq));
|
||||||
dev->timer_latch_fm = (uint64_t) ((double) TIMER_USEC * (1000000.0 / 24000.0));
|
dev->sgd[2].timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / 24000.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -801,12 +791,16 @@ ac97_via_init(const device_t *info)
|
|||||||
if ((i != 0) && (i != 2))
|
if ((i != 0) && (i != 2))
|
||||||
dev->sgd[i].always_run = 1;
|
dev->sgd[i].always_run = 1;
|
||||||
|
|
||||||
timer_add(&dev->sgd[i].timer, ac97_via_sgd_process, &dev->sgd[i], 0);
|
/* No volume control on FM SGD that I know of. */
|
||||||
|
if (i == 2)
|
||||||
|
dev->sgd[i].vol_l = dev->sgd[i].vol_r = 32767;
|
||||||
|
|
||||||
|
timer_add(&dev->sgd[i].dma_timer, ac97_via_sgd_process, &dev->sgd[i], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up playback pollers. */
|
/* Set up playback pollers. */
|
||||||
timer_add(&dev->timer_count, ac97_via_poll, dev, 0);
|
timer_add(&dev->sgd[0].poll_timer, ac97_via_poll_stereo, dev, 0);
|
||||||
timer_add(&dev->timer_count_fm, ac97_via_poll_fm, dev, 0);
|
timer_add(&dev->sgd[2].poll_timer, ac97_via_poll_fm, dev, 0);
|
||||||
ac97_via_speed_changed(dev);
|
ac97_via_speed_changed(dev);
|
||||||
|
|
||||||
/* Set up playback handler. */
|
/* Set up playback handler. */
|
||||||
|
Reference in New Issue
Block a user