mirror of https://github.com/xqemu/xqemu.git
ac97: More complete S/PDIF output handling
This commit is contained in:
parent
9464bad500
commit
1e7d8e43c0
|
@ -176,6 +176,7 @@ enum {
|
|||
|
||||
#define GET_BM(index) (((index) >> 4) & 7)
|
||||
|
||||
static void so_callback (void *opaque, int free);
|
||||
static void po_callback (void *opaque, int free);
|
||||
static void pi_callback (void *opaque, int avail);
|
||||
static void mc_callback (void *opaque, int avail);
|
||||
|
@ -272,6 +273,10 @@ static void voice_set_active (AC97LinkState *s, int bm_index, int on)
|
|||
AUD_set_active_in (s->voice_mc, on);
|
||||
break;
|
||||
|
||||
case SO_INDEX:
|
||||
AUD_set_active_out (s->voice_so, on);
|
||||
break;
|
||||
|
||||
default:
|
||||
AUD_log ("ac97", "invalid bm_index(%d) in voice_set_active\n", bm_index);
|
||||
break;
|
||||
|
@ -366,6 +371,18 @@ static void open_voice (AC97LinkState *s, int index, int freq)
|
|||
&as
|
||||
);
|
||||
break;
|
||||
|
||||
case SO_INDEX:
|
||||
s->voice_so = AUD_open_out (
|
||||
&s->card,
|
||||
s->voice_so,
|
||||
"ac97.so",
|
||||
s,
|
||||
so_callback,
|
||||
&as
|
||||
);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -385,6 +402,11 @@ static void open_voice (AC97LinkState *s, int index, int freq)
|
|||
AUD_close_in (&s->card, s->voice_mc);
|
||||
s->voice_mc = NULL;
|
||||
break;
|
||||
|
||||
case SO_INDEX:
|
||||
AUD_close_out (&s->card, s->voice_so);
|
||||
s->voice_so = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -400,6 +422,8 @@ static void reset_voices (AC97LinkState *s, uint8_t active[LAST_INDEX])
|
|||
freq = mixer_load (s, AC97_PCM_Front_DAC_Rate);
|
||||
open_voice (s, PO_INDEX, freq);
|
||||
AUD_set_active_out (s->voice_po, active[PO_INDEX]);
|
||||
open_voice (s, SO_INDEX, freq);
|
||||
AUD_set_active_out (s->voice_so, active[SO_INDEX]);
|
||||
|
||||
freq = mixer_load (s, AC97_MIC_ADC_Rate);
|
||||
open_voice (s, MC_INDEX, freq);
|
||||
|
@ -434,6 +458,12 @@ static void update_combined_volume_out (AC97LinkState *s)
|
|||
rvol = (rvol * prvol) / 255;
|
||||
|
||||
AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
|
||||
|
||||
mute = 1;
|
||||
lvol = 0;
|
||||
rvol = 0;
|
||||
|
||||
AUD_set_volume_out (s->voice_so, mute, lvol, rvol);
|
||||
}
|
||||
|
||||
static void update_volume_in (AC97LinkState *s)
|
||||
|
@ -596,6 +626,7 @@ static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
|
|||
mixer_store (s, AC97_PCM_LR_ADC_Rate, 0xbb80);
|
||||
open_voice (s, PI_INDEX, 48000);
|
||||
open_voice (s, PO_INDEX, 48000);
|
||||
open_voice (s, SO_INDEX, 48000);
|
||||
}
|
||||
if (!(val & EACS_VRM)) {
|
||||
mixer_store (s, AC97_MIC_ADC_Rate, 0xbb80);
|
||||
|
@ -609,6 +640,7 @@ static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
|
|||
mixer_store (s, index, val);
|
||||
dolog ("Set front DAC rate to %d\n", val);
|
||||
open_voice (s, PO_INDEX, val);
|
||||
open_voice (s, SO_INDEX, val);
|
||||
}
|
||||
else {
|
||||
dolog ("Attempt to set front DAC rate to %d, "
|
||||
|
@ -933,7 +965,7 @@ static void nabm_writel (void *opaque, uint32_t addr, uint32_t val)
|
|||
}
|
||||
}
|
||||
|
||||
static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
|
||||
static int write_audio (AC97LinkState *s, int index, AC97BusMasterRegs *r,
|
||||
int max, int *stop)
|
||||
{
|
||||
uint8_t tmpbuf[4096];
|
||||
|
@ -952,7 +984,14 @@ static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
|
|||
int copied;
|
||||
to_copy = audio_MIN (temp, sizeof (tmpbuf));
|
||||
dma_memory_read (s->as, addr, tmpbuf, to_copy);
|
||||
copied = AUD_write (s->voice_po, tmpbuf, to_copy);
|
||||
switch (index) {
|
||||
case PO_INDEX:
|
||||
copied = AUD_write (s->voice_po, tmpbuf, to_copy);
|
||||
break;
|
||||
case SO_INDEX:
|
||||
copied = AUD_write (s->voice_so, tmpbuf, to_copy);
|
||||
break;
|
||||
}
|
||||
dolog ("write_audio max=%x to_copy=%x copied=%x\n",
|
||||
max, to_copy, copied);
|
||||
if (!copied) {
|
||||
|
@ -978,7 +1017,7 @@ static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
|
|||
return written;
|
||||
}
|
||||
|
||||
static void write_bup (AC97LinkState *s, int elapsed)
|
||||
static void write_bup (AC97LinkState *s, int index, int elapsed)
|
||||
{
|
||||
dolog ("write_bup\n");
|
||||
if (!(s->bup_flag & BUP_SET)) {
|
||||
|
@ -998,7 +1037,15 @@ static void write_bup (AC97LinkState *s, int elapsed)
|
|||
while (elapsed) {
|
||||
int temp = audio_MIN (elapsed, sizeof (s->silence));
|
||||
while (temp) {
|
||||
int copied = AUD_write (s->voice_po, s->silence, temp);
|
||||
int copied;
|
||||
switch (index) {
|
||||
case PO_INDEX:
|
||||
copied = AUD_write (s->voice_po, s->silence, temp);
|
||||
break;
|
||||
case SO_INDEX:
|
||||
copied = AUD_write (s->voice_so, s->silence, temp);
|
||||
break;
|
||||
}
|
||||
if (!copied)
|
||||
return;
|
||||
temp -= copied;
|
||||
|
@ -1057,7 +1104,8 @@ static void transfer_audio (AC97LinkState *s, int index, int elapsed)
|
|||
if (r->cr & CR_RPBM) {
|
||||
switch (index) {
|
||||
case PO_INDEX:
|
||||
write_bup (s, elapsed);
|
||||
case SO_INDEX:
|
||||
write_bup (s, index, elapsed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1089,7 +1137,8 @@ static void transfer_audio (AC97LinkState *s, int index, int elapsed)
|
|||
|
||||
switch (index) {
|
||||
case PO_INDEX:
|
||||
temp = write_audio (s, r, elapsed, &stop);
|
||||
case SO_INDEX:
|
||||
temp = write_audio (s, index, r, elapsed, &stop);
|
||||
elapsed -= temp;
|
||||
r->picb -= (temp >> 1);
|
||||
break;
|
||||
|
@ -1142,6 +1191,11 @@ static void po_callback (void *opaque, int free)
|
|||
transfer_audio (opaque, PO_INDEX, free);
|
||||
}
|
||||
|
||||
static void so_callback (void *opaque, int free)
|
||||
{
|
||||
transfer_audio (opaque, SO_INDEX, free);
|
||||
}
|
||||
|
||||
static int ac97_post_load (void *opaque, int version_id)
|
||||
{
|
||||
uint8_t active[LAST_INDEX];
|
||||
|
@ -1158,6 +1212,7 @@ static int ac97_post_load (void *opaque, int version_id)
|
|||
active[PI_INDEX] = !!(s->bm_regs[PI_INDEX].cr & CR_RPBM);
|
||||
active[PO_INDEX] = !!(s->bm_regs[PO_INDEX].cr & CR_RPBM);
|
||||
active[MC_INDEX] = !!(s->bm_regs[MC_INDEX].cr & CR_RPBM);
|
||||
active[SO_INDEX] = !!(s->bm_regs[SO_INDEX].cr & CR_RPBM);
|
||||
reset_voices (s, active);
|
||||
|
||||
s->bup_flag = 0;
|
||||
|
@ -1274,9 +1329,10 @@ static void ac97_on_reset (void *opaque)
|
|||
{
|
||||
AC97LinkState *s = opaque;
|
||||
|
||||
reset_bm_regs (s, &s->bm_regs[0]);
|
||||
reset_bm_regs (s, &s->bm_regs[1]);
|
||||
reset_bm_regs (s, &s->bm_regs[2]);
|
||||
reset_bm_regs (s, &s->bm_regs[PI_INDEX]);
|
||||
reset_bm_regs (s, &s->bm_regs[PO_INDEX]);
|
||||
reset_bm_regs (s, &s->bm_regs[MC_INDEX]);
|
||||
reset_bm_regs (s, &s->bm_regs[SO_INDEX]);
|
||||
|
||||
/*
|
||||
* Reset the mixer too. The Windows XP driver seems to rely on
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef struct AC97LinkState {
|
|||
SWVoiceIn *voice_pi;
|
||||
SWVoiceOut *voice_po;
|
||||
SWVoiceIn *voice_mc;
|
||||
SWVoiceOut *voice_so;
|
||||
int invalid_freq[LAST_INDEX];
|
||||
uint8_t silence[128];
|
||||
int bup_flag;
|
||||
|
|
Loading…
Reference in New Issue