1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

o Add back support for DXS channels.

o Make DXS3 the primary playback channel.  It may be the only
universally supported channel with the assorted revisions of this
chipset.

o Add sysctl and handler for enabling s/pdif output from DXS3.
This commit is contained in:
Orion Hodson 2003-02-22 23:28:15 +00:00
parent e27c9f46ad
commit c7bbf97e00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=111269
2 changed files with 313 additions and 95 deletions

View File

@ -26,7 +26,8 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
/* Some Credits: /*
* Credits due to:
* *
* Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for * Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for
* comments, machine time, testing patches, and patience. VIA for * comments, machine time, testing patches, and patience. VIA for
@ -47,19 +48,25 @@ SND_DECLARE_FILE("$FreeBSD$");
#define VIA8233_PCI_ID 0x30591106 #define VIA8233_PCI_ID 0x30591106
#define VIA8233_REV_ID_8233PRE 0x10
#define VIA8233_REV_ID_8233C 0x20
#define VIA8233_REV_ID_8233 0x30
#define VIA8233_REV_ID_8233A 0x40
#define VIA8233_REV_ID_8235 0x50
#define SEGS_PER_CHAN 2 /* Segments per channel */ #define SEGS_PER_CHAN 2 /* Segments per channel */
#define NCHANS 2 /* Lines-in,out (mic later) */ #define NDXSCHANS 4 /* No of DXS channels */
#define NMSGDCHANS 1 /* No of multichannel SGD */
#define NWRCHANS 1 /* No of write channels */
#define NCHANS (NWRCHANS + NDXSCHANS + NMSGDCHANS)
#define NSEGS NCHANS * SEGS_PER_CHAN /* Segments in SGD table */ #define NSEGS NCHANS * SEGS_PER_CHAN /* Segments in SGD table */
#define VIA_DEFAULT_BUFSZ 0x1000 #define VIA_DEFAULT_BUFSZ 0x1000
#undef DEB
#define DEB(x) x
/* we rely on this struct being packed to 64 bits */ /* we rely on this struct being packed to 64 bits */
struct via_dma_op { struct via_dma_op {
u_int32_t ptr; volatile u_int32_t ptr;
u_int32_t flags; volatile u_int32_t flags;
#define VIA_DMAOP_EOL 0x80000000 #define VIA_DMAOP_EOL 0x80000000
#define VIA_DMAOP_FLAG 0x40000000 #define VIA_DMAOP_FLAG 0x40000000
#define VIA_DMAOP_STOP 0x20000000 #define VIA_DMAOP_STOP 0x20000000
@ -75,7 +82,7 @@ struct via_chinfo {
struct via_dma_op *sgd_table; struct via_dma_op *sgd_table;
bus_addr_t sgd_addr; bus_addr_t sgd_addr;
int dir, blksz; int dir, blksz;
int rbase; /* base register for channel */ int rbase;
}; };
struct via_info { struct via_info {
@ -93,9 +100,11 @@ struct via_info {
unsigned int bufsz; unsigned int bufsz;
struct via_chinfo pch, rch; struct via_chinfo pch[NDXSCHANS + NMSGDCHANS];
struct via_chinfo rch[NWRCHANS];
struct via_dma_op *sgd_table; struct via_dma_op *sgd_table;
u_int16_t codec_caps; u_int16_t codec_caps;
u_int16_t n_dxs_registered;
}; };
static u_int32_t via_fmt[] = { static u_int32_t via_fmt[] = {
@ -223,14 +232,7 @@ via_buildsgdt(struct via_chinfo *ch)
u_int32_t phys_addr, flag; u_int32_t phys_addr, flag;
int i, seg_size; int i, seg_size;
/*
* Build the scatter/gather DMA (SGD) table.
* There are four slots in the table: two for play, two for record.
* This creates two half-buffers, one of which is playing; the other
* is feeding.
*/
seg_size = sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN; seg_size = sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN;
phys_addr = sndbuf_getbufaddr(ch->buffer); phys_addr = sndbuf_getbufaddr(ch->buffer);
for (i = 0; i < SEGS_PER_CHAN; i++) { for (i = 0; i < SEGS_PER_CHAN; i++) {
@ -242,8 +244,47 @@ via_buildsgdt(struct via_chinfo *ch)
return 0; return 0;
} }
/* -------------------------------------------------------------------- */
/* Format setting functions */
static int static int
via8233pchan_setformat(kobj_t obj, void *data, u_int32_t format) via8233wr_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
u_int32_t f = WR_FORMAT_STOP_INDEX;
if (format & AFMT_STEREO)
f |= WR_FORMAT_STEREO;
if (format & AFMT_S16_LE)
f |= WR_FORMAT_16BIT;
via_wr(via, VIA_WR0_FORMAT, f, 4);
return 0;
}
static int
via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
u_int32_t r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
u_int32_t v = via_rd(via, r, 4);
v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT);
if (format & AFMT_STEREO)
v |= VIA8233_DXS_RATEFMT_STEREO;
if (format & AFMT_16BIT)
v |= VIA8233_DXS_RATEFMT_16BIT;
via_wr(via, r, v, 4);
return 0;
}
static int
via8233msgd_setformat(kobj_t obj, void *data, u_int32_t format)
{ {
struct via_chinfo *ch = data; struct via_chinfo *ch = data;
struct via_info *via = ch->parent; struct via_info *via = ch->parent;
@ -265,36 +306,11 @@ via8233pchan_setformat(kobj_t obj, void *data, u_int32_t format)
return 0; return 0;
} }
static int /* -------------------------------------------------------------------- */
via8233rchan_setformat(kobj_t obj, void *data, u_int32_t format) /* Speed setting functions */
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
u_int32_t f = WR_FORMAT_STOP_INDEX;
if (format & AFMT_STEREO)
f |= WR_FORMAT_STEREO;
if (format & AFMT_S16_LE)
f |= WR_FORMAT_16BIT;
via_wr(via, VIA_WR0_FORMAT, f, 4);
return 0;
}
static int static int
via8233pchan_setspeed(kobj_t obj, void *data, u_int32_t speed) via8233wr_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
if (via->codec_caps & AC97_EXTCAP_VRA)
return ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed);
return 48000;
}
static int
via8233rchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{ {
struct via_chinfo *ch = data; struct via_chinfo *ch = data;
struct via_info *via = ch->parent; struct via_info *via = ch->parent;
@ -306,11 +322,42 @@ via8233rchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
return spd; return spd;
} }
static int
via8233dxs_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
u_int32_t r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
u_int32_t v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K;
/* Careful to avoid overflow (divide by 48 per vt8233c docs) */
v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48);
via_wr(via, r, v, 4);
return speed;
}
static int
via8233msgd_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
if (via->codec_caps & AC97_EXTCAP_VRA)
return ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed);
return 48000;
}
/* -------------------------------------------------------------------- */
/* Common functions */
static int static int
via8233chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) via8233chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{ {
struct via_chinfo *ch = data; struct via_chinfo *ch = data;
sndbuf_resize(ch->buffer, SEGS_PER_CHAN, blocksize); sndbuf_resize(ch->buffer, SEGS_PER_CHAN, blocksize);
ch->blksz = sndbuf_getblksz(ch->buffer); ch->blksz = sndbuf_getblksz(ch->buffer);
return ch->blksz; return ch->blksz;
@ -350,39 +397,104 @@ via8233chan_reset(struct via_info *via, struct via_chinfo *ch)
SGD_STATUS_EOL | SGD_STATUS_FLAG, 1); SGD_STATUS_EOL | SGD_STATUS_FLAG, 1);
} }
/* -------------------------------------------------------------------- */
/* Channel initialization functions */
static void
via8233chan_sgdinit(struct via_info *via, struct via_chinfo *ch, int chnum)
{
ch->sgd_table = &via->sgd_table[chnum * SEGS_PER_CHAN];
ch->sgd_addr = via->sgd_addr + chnum * SEGS_PER_CHAN * sizeof(struct via_dma_op);
}
static void* static void*
via8233chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
struct pcm_channel *c, int dir) struct pcm_channel *c, int dir)
{ {
struct via_info *via = devinfo; struct via_info *via = devinfo;
struct via_chinfo *ch; struct via_chinfo *ch = &via->rch[c->num];
if (dir == PCMDIR_PLAY) {
ch = &via->pch;
ch->rbase = VIA_MC_SGD_STATUS;
ch->sgd_table = &via->sgd_table[0];
ch->sgd_addr = via->sgd_addr;
} else {
ch = &via->rch;
ch->rbase = VIA_WR0_SGD_STATUS;
ch->sgd_table = &via->sgd_table[SEGS_PER_CHAN];
ch->sgd_addr = via->sgd_addr + sizeof(struct via_dma_op) * SEGS_PER_CHAN;
via_wr(via, VIA_WR0_SGD_FORMAT, WR_FIFO_ENABLE, 1);
}
ch->parent = via; ch->parent = via;
ch->channel = c; ch->channel = c;
ch->buffer = b; ch->buffer = b;
ch->dir = dir; ch->dir = dir;
ch->rbase = VIA_WR_BASE(c->num);
via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1);
if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1) if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1)
return NULL; return NULL;
via8233chan_sgdinit(via, ch, c->num);
via8233chan_reset(via, ch); via8233chan_reset(via, ch);
return ch; return ch;
} }
static void*
via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
struct pcm_channel *c, int dir)
{
struct via_info *via = devinfo;
struct via_chinfo *ch = &via->pch[c->num];
ch->parent = via;
ch->channel = c;
ch->buffer = b;
ch->dir = dir;
/*
* All cards apparently support DXS3, but not other DXS
* channels. We therefore want to align first DXS channel to
* DXS3.
*/
ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered);
via->n_dxs_registered++;
if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1)
return NULL;
via8233chan_sgdinit(via, ch, NWRCHANS + c->num);
via8233chan_reset(via, ch);
return ch;
}
static void*
via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
struct pcm_channel *c, int dir)
{
struct via_info *via = devinfo;
struct via_chinfo *ch = &via->pch[c->num];
ch->parent = via;
ch->channel = c;
ch->buffer = b;
ch->dir = dir;
ch->rbase = VIA_MC_SGD_STATUS;
if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1)
return NULL;
via8233chan_sgdinit(via, ch, NWRCHANS + c->num);
via8233chan_reset(via, ch);
return ch;
}
static void
via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted)
{
if (BASE_IS_VIA_DXS_REG(ch->rbase)) {
int r;
muted = (muted) ? VIA8233_DXS_MUTE : 0;
via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1);
via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1);
r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) & VIA8233_DXS_MUTE;
if (r != muted) {
printf("via: failed to set dxs volume "
"(dxs base 0x%02x).\n", ch->rbase);
}
}
}
static int static int
via8233chan_trigger(kobj_t obj, void* data, int go) via8233chan_trigger(kobj_t obj, void* data, int go)
{ {
@ -392,6 +504,7 @@ via8233chan_trigger(kobj_t obj, void* data, int go)
switch(go) { switch(go) {
case PCMTRIG_START: case PCMTRIG_START:
via_buildsgdt(ch); via_buildsgdt(ch);
via8233chan_mute(via, ch, 0);
via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4); via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4);
via_wr(via, ch->rbase + VIA_RP_CONTROL, via_wr(via, ch->rbase + VIA_RP_CONTROL,
SGD_CONTROL_START | SGD_CONTROL_AUTOSTART | SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
@ -400,35 +513,48 @@ via8233chan_trigger(kobj_t obj, void* data, int go)
case PCMTRIG_STOP: case PCMTRIG_STOP:
case PCMTRIG_ABORT: case PCMTRIG_ABORT:
via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1); via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
via8233chan_mute(via, ch, 1);
via8233chan_reset(via, ch); via8233chan_reset(via, ch);
break; break;
} }
return 0; return 0;
} }
static kobj_method_t via8233pchan_methods[] = { static kobj_method_t via8233wr_methods[] = {
KOBJMETHOD(channel_init, via8233chan_init), KOBJMETHOD(channel_init, via8233wr_init),
KOBJMETHOD(channel_setformat, via8233pchan_setformat), KOBJMETHOD(channel_setformat, via8233wr_setformat),
KOBJMETHOD(channel_setspeed, via8233pchan_setspeed), KOBJMETHOD(channel_setspeed, via8233wr_setspeed),
KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
KOBJMETHOD(channel_trigger, via8233chan_trigger), KOBJMETHOD(channel_trigger, via8233chan_trigger),
KOBJMETHOD(channel_getptr, via8233chan_getptr), KOBJMETHOD(channel_getptr, via8233chan_getptr),
KOBJMETHOD(channel_getcaps, via8233chan_getcaps), KOBJMETHOD(channel_getcaps, via8233chan_getcaps),
{ 0, 0 } { 0, 0 }
}; };
CHANNEL_DECLARE(via8233pchan); CHANNEL_DECLARE(via8233wr);
static kobj_method_t via8233rchan_methods[] = { static kobj_method_t via8233dxs_methods[] = {
KOBJMETHOD(channel_init, via8233chan_init), KOBJMETHOD(channel_init, via8233dxs_init),
KOBJMETHOD(channel_setformat, via8233rchan_setformat), KOBJMETHOD(channel_setformat, via8233dxs_setformat),
KOBJMETHOD(channel_setspeed, via8233rchan_setspeed), KOBJMETHOD(channel_setspeed, via8233dxs_setspeed),
KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize), KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
KOBJMETHOD(channel_trigger, via8233chan_trigger), KOBJMETHOD(channel_trigger, via8233chan_trigger),
KOBJMETHOD(channel_getptr, via8233chan_getptr), KOBJMETHOD(channel_getptr, via8233chan_getptr),
KOBJMETHOD(channel_getcaps, via8233chan_getcaps), KOBJMETHOD(channel_getcaps, via8233chan_getcaps),
{ 0, 0 } { 0, 0 }
}; };
CHANNEL_DECLARE(via8233rchan); CHANNEL_DECLARE(via8233dxs);
static kobj_method_t via8233msgd_methods[] = {
KOBJMETHOD(channel_init, via8233msgd_init),
KOBJMETHOD(channel_setformat, via8233msgd_setformat),
KOBJMETHOD(channel_setspeed, via8233msgd_setspeed),
KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
KOBJMETHOD(channel_trigger, via8233chan_trigger),
KOBJMETHOD(channel_getptr, via8233chan_getptr),
KOBJMETHOD(channel_getcaps, via8233chan_getcaps),
{ 0, 0 }
};
CHANNEL_DECLARE(via8233msgd);
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -436,16 +562,28 @@ static void
via_intr(void *p) via_intr(void *p)
{ {
struct via_info *via = p; struct via_info *via = p;
int r = via_rd(via, VIA_MC_SGD_STATUS, 1); int i, stat;
if (r & SGD_STATUS_INTR) {
via_wr(via, VIA_MC_SGD_STATUS, SGD_STATUS_INTR, 1);
chn_intr(via->pch.channel);
}
r = via_rd(via, VIA_WR0_SGD_STATUS, 1); /* Poll playback channels */
if (r & SGD_STATUS_INTR) { for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
via_wr(via, VIA_WR0_SGD_STATUS, SGD_STATUS_INTR, 1); if (via->pch[i].rbase == 0)
chn_intr(via->rch.channel); continue;
stat = via->pch[i].rbase + VIA_RP_STATUS;
if (via_rd(via, stat, 1) & SGD_STATUS_INTR) {
via_wr(via, stat, SGD_STATUS_INTR, 1);
chn_intr(via->pch[i].channel);
}
}
/* Poll record channels */
for (i = 0; i < NWRCHANS; i++) {
if (via->rch[i].rbase == 0)
continue;
stat = via->rch[i].rbase + VIA_RP_STATUS;
if (via_rd(via, stat, 1) & SGD_STATUS_INTR) {
via_wr(via, stat, SGD_STATUS_INTR, 1);
chn_intr(via->rch[i].channel);
}
} }
} }
@ -458,19 +596,19 @@ via_probe(device_t dev)
switch(pci_get_devid(dev)) { switch(pci_get_devid(dev)) {
case VIA8233_PCI_ID: case VIA8233_PCI_ID:
switch(pci_get_revid(dev)) { switch(pci_get_revid(dev)) {
case 0x10: case VIA8233_REV_ID_8233PRE:
device_set_desc(dev, "VIA VT8233 (pre)"); device_set_desc(dev, "VIA VT8233 (pre)");
return 0; return 0;
case 0x20: case VIA8233_REV_ID_8233C:
device_set_desc(dev, "VIA VT8233C"); device_set_desc(dev, "VIA VT8233C");
return 0; return 0;
case 0x30: case VIA8233_REV_ID_8233:
device_set_desc(dev, "VIA VT8233"); device_set_desc(dev, "VIA VT8233");
return 0; return 0;
case 0x40: case VIA8233_REV_ID_8233A:
device_set_desc(dev, "VIA VT8233A"); device_set_desc(dev, "VIA VT8233A");
return 0; return 0;
case 0x50: case VIA8233_REV_ID_8235:
device_set_desc(dev, "VIA VT8235"); device_set_desc(dev, "VIA VT8235");
return 0; return 0;
default: default:
@ -521,6 +659,54 @@ via_chip_init(device_t dev)
return ENXIO; return ENXIO;
} }
#ifdef SND_DYNSYSCTL
static int via8233_spdif_en;
static int
sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS)
{
device_t dev;
int err, new_en, r;
dev = oidp->oid_arg1;
new_en = via8233_spdif_en;
err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req);
if (err || req->newptr == NULL)
return err;
if (new_en < 0 || new_en > 1)
return EINVAL;
via8233_spdif_en = new_en;
r = pci_read_config(dev, VIA_PCI_SPDIF, 1) & ~VIA_SPDIF_EN;
if (new_en)
r |= VIA_SPDIF_EN;
pci_write_config(dev, VIA_PCI_SPDIF, r, 1);
return 0;
}
#endif /* SND_DYNSYSCTL */
static void
via_init_sysctls(device_t dev)
{
#ifdef SND_DYNSYSCTL
int r;
r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
via8233_spdif_en = (r & VIA_SPDIF_EN) ? 1 : 0;
SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
OID_AUTO, "spdif_enabled",
CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
sysctl_via8233_spdif_enable, "I",
"Enable S/PDIF output on primary playback channel");
#endif
}
static int static int
via_attach(device_t dev) via_attach(device_t dev)
{ {
@ -616,12 +802,23 @@ via_attach(device_t dev)
rman_get_start(via->reg), rman_get_start(via->irq)); rman_get_start(via->reg), rman_get_start(via->irq));
/* Register */ /* Register */
if (pcm_register(dev, via, 1, 1)) goto bad; if (pci_get_revid(dev) == VIA8233_REV_ID_8233A) {
if (pcm_register(dev, via, NMSGDCHANS + 1, 1)) goto bad;
pcm_addchan(dev, PCMDIR_PLAY, &via8233pchan_class, via); pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via);
pcm_addchan(dev, PCMDIR_REC, &via8233rchan_class, via); pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via);
pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via);
} else {
int i;
if (pcm_register(dev, via, NMSGDCHANS + NDXSCHANS, NWRCHANS)) goto bad;
for (i = 0; i < NDXSCHANS; i++)
pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via);
pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via);
for (i = 0; i < NWRCHANS; i++)
pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via);
}
pcm_setstatus(dev, status); pcm_setstatus(dev, status);
via_init_sysctls(dev);
return 0; return 0;
bad: bad:

View File

@ -34,11 +34,30 @@
* *
* Documentation sources: * Documentation sources:
* *
* V8233C specs. from VIA, gratefully received under NDA. * o V8233C specs. from VIA, gratefully received under NDA.
* AC97 R2.2 specs. * o AC97 R2.2 specs.
* ALSA driver (very useful comments) * o ALSA driver (very useful comments)
*/ */
#define VIA_PCI_SPDIF 0x49
#define VIA_SPDIF_EN 0x08
#define VIA_DXS0_BASE 0x00
#define VIA_DXS1_BASE 0x10
#define VIA_DXS2_BASE 0x20
#define VIA_DXS3_BASE 0x30
#define VIA_DXS_BASE(n) (0x10 * (n))
#define BASE_IS_VIA_DXS_REG(x) ((x) <= VIA_DXS3_BASE)
#define VIA8233_RP_DXS_LVOL 0x02
#define VIA8233_RP_DXS_RVOL 0x03
#define VIA8233_DXS_MUTE 0x3f
#define VIA8233_RP_DXS_RATEFMT 0x08
#define VIA8233_DXS_STOP_INDEX 0xff000000
#define VIA8233_DXS_RATEFMT_48K 0x000fffff
#define VIA8233_DXS_RATEFMT_STEREO 0x00100000
#define VIA8233_DXS_RATEFMT_16BIT 0x00200000
#define VIA_PCI_ACLINK_STAT 0x40 #define VIA_PCI_ACLINK_STAT 0x40
# define VIA_PCI_ACLINK_C11_READY 0x20 # define VIA_PCI_ACLINK_C11_READY 0x20
# define VIA_PCI_ACLINK_C10_READY 0x10 # define VIA_PCI_ACLINK_C10_READY 0x10
@ -65,6 +84,8 @@
# define SGD_STATUS_FLAG 0x01 # define SGD_STATUS_FLAG 0x01
# define SGD_STATUS_INTR (SGD_STATUS_EOL | SGD_STATUS_FLAG) # define SGD_STATUS_INTR (SGD_STATUS_EOL | SGD_STATUS_FLAG)
#define VIA_WR_BASE(n) (0x60 + (n) * 0x10)
#define VIA_MC_SGD_CONTROL 0x41 #define VIA_MC_SGD_CONTROL 0x41
#define VIA_WR0_SGD_CONTROL 0x61 #define VIA_WR0_SGD_CONTROL 0x61
#define VIA_WR1_SGD_CONTROL 0x71 #define VIA_WR1_SGD_CONTROL 0x71
@ -83,6 +104,7 @@
#define VIA_WR0_SGD_FORMAT 0x62 #define VIA_WR0_SGD_FORMAT 0x62
#define VIA_WR1_SGD_FORMAT 0x72 #define VIA_WR1_SGD_FORMAT 0x72
#define VIA_WR_RP_SGD_FORMAT 0x02
# define WR_FIFO_ENABLE 0x40 # define WR_FIFO_ENABLE 0x40
#define VIA_WR0_SGD_INPUT 0x63 #define VIA_WR0_SGD_INPUT 0x63
@ -133,7 +155,6 @@
# define VIA_AC97_INDEX(x) ((x) << 16) # define VIA_AC97_INDEX(x) ((x) << 16)
# define VIA_AC97_DATA(x) ((x) & 0xffff) # define VIA_AC97_DATA(x) ((x) & 0xffff)
#define VIA_CODEC_BUSY 0x01000000 #define VIA_CODEC_BUSY 0x01000000
#define VIA_CODEC_PRIVALID 0x02000000 #define VIA_CODEC_PRIVALID 0x02000000
#define VIA_CODEC_INDEX(x) ((x)<<16) #define VIA_CODEC_INDEX(x) ((x)<<16)