- Locking improvements.
- Don't keep the SPDIF state in the driver private struct since it can be overriden by hand with pciconf(8), query it when needed instead. Regarding the locking I let Ariff explain it himself: ---snip--- About the locking, that is what I'm intended to do since the beginning. The reason I'm not putting that along since my first patchset was because several people especially from amd46 camp reported that it cause lots of LORs, which is weird considering that I've never encounter such in a pretty much strict locking environment (i386). However, since our previous discussion with Pyun YongHyeon about strict locking, I've decided to bring it back for all the affected drivers, not just for es137x. It turns out that the root of the problem was within dsp.c during device open, which has been fixed since dsp.c revision 1.84. ---snip--- Submitted by: Ariff Abdullah <skywizard@MyBSD.org.my>
This commit is contained in:
parent
dcbde45390
commit
e7d2d131f1
@ -271,9 +271,12 @@ static int
|
||||
alschan_getptr(kobj_t obj, void *data)
|
||||
{
|
||||
struct sc_chinfo *ch = data;
|
||||
struct sc_info *sc = ch->parent;
|
||||
int32_t pos, sz;
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
pos = als_gcr_rd(ch->parent, ch->gcr_fifo_status) & 0xffff;
|
||||
snd_mtxunlock(sc->lock);
|
||||
sz = sndbuf_getsize(ch->buffer);
|
||||
return (2 * sz - pos - 1) % sz;
|
||||
}
|
||||
@ -386,7 +389,9 @@ static int
|
||||
alspchan_trigger(kobj_t obj, void *data, int go)
|
||||
{
|
||||
struct sc_chinfo *ch = data;
|
||||
struct sc_info *sc = ch->parent;
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
switch(go) {
|
||||
case PCMTRIG_START:
|
||||
als_playback_start(ch);
|
||||
@ -395,6 +400,7 @@ alspchan_trigger(kobj_t obj, void *data, int go)
|
||||
als_playback_stop(ch);
|
||||
break;
|
||||
}
|
||||
snd_mtxunlock(sc->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -476,7 +482,9 @@ static int
|
||||
alsrchan_trigger(kobj_t obj, void *data, int go)
|
||||
{
|
||||
struct sc_chinfo *ch = data;
|
||||
struct sc_info *sc = ch->parent;
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
switch(go) {
|
||||
case PCMTRIG_START:
|
||||
als_capture_start(ch);
|
||||
@ -485,6 +493,7 @@ alsrchan_trigger(kobj_t obj, void *data, int go)
|
||||
als_capture_stop(ch);
|
||||
break;
|
||||
}
|
||||
snd_mtxunlock(sc->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -889,9 +898,11 @@ als_pci_suspend(device_t dev)
|
||||
{
|
||||
struct sc_info *sc = pcm_getdevinfo(dev);
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
sc->pch.dma_was_active = als_playback_stop(&sc->pch);
|
||||
sc->rch.dma_was_active = als_capture_stop(&sc->rch);
|
||||
als_uninit(sc);
|
||||
snd_mtxunlock(sc->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -901,13 +912,16 @@ als_pci_resume(device_t dev)
|
||||
struct sc_info *sc = pcm_getdevinfo(dev);
|
||||
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
if (als_init(sc) != 0) {
|
||||
device_printf(dev, "unable to reinitialize the card\n");
|
||||
snd_mtxunlock(sc->lock);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
if (mixer_reinit(dev) != 0) {
|
||||
device_printf(dev, "unable to reinitialize the mixer\n");
|
||||
snd_mtxunlock(sc->lock);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
@ -918,6 +932,7 @@ als_pci_resume(device_t dev)
|
||||
if (sc->rch.dma_was_active) {
|
||||
als_capture_start(&sc->rch);
|
||||
}
|
||||
snd_mtxunlock(sc->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ struct via_info {
|
||||
struct ac97_info *codec;
|
||||
|
||||
unsigned int bufsz;
|
||||
int spdif_en, dxs_src;
|
||||
int dxs_src;
|
||||
|
||||
struct via_chinfo pch[NDXSCHANS + NMSGDCHANS];
|
||||
struct via_chinfo rch[NWRCHANS];
|
||||
@ -127,13 +127,15 @@ sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct via_info *via;
|
||||
device_t dev;
|
||||
int err, new_en, r;
|
||||
uint32_t r;
|
||||
int err, new_en;
|
||||
|
||||
dev = oidp->oid_arg1;
|
||||
via = pcm_getdevinfo(dev);
|
||||
snd_mtxlock(via->lock);
|
||||
new_en = via->spdif_en;
|
||||
r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
|
||||
snd_mtxunlock(via->lock);
|
||||
new_en = (r & VIA_SPDIF_EN) ? 1 : 0;
|
||||
err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req);
|
||||
|
||||
if (err || req->newptr == NULL)
|
||||
@ -141,12 +143,11 @@ sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS)
|
||||
if (new_en < 0 || new_en > 1)
|
||||
return EINVAL;
|
||||
|
||||
snd_mtxlock(via->lock);
|
||||
via->spdif_en = new_en;
|
||||
|
||||
r = pci_read_config(dev, VIA_PCI_SPDIF, 1) & ~VIA_SPDIF_EN;
|
||||
if (new_en)
|
||||
r |= VIA_SPDIF_EN;
|
||||
else
|
||||
r &= ~VIA_SPDIF_EN;
|
||||
snd_mtxlock(via->lock);
|
||||
pci_write_config(dev, VIA_PCI_SPDIF, r, 1);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
@ -184,13 +185,6 @@ static void
|
||||
via_init_sysctls(device_t dev)
|
||||
{
|
||||
#ifdef SND_DYNSYSCTL
|
||||
struct via_info *via;
|
||||
int r;
|
||||
|
||||
via = pcm_getdevinfo(dev);
|
||||
r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
|
||||
via->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",
|
||||
@ -206,7 +200,7 @@ via_init_sysctls(device_t dev)
|
||||
#endif
|
||||
}
|
||||
|
||||
static u_int32_t
|
||||
static __inline u_int32_t
|
||||
via_rd(struct via_info *via, int regno, int size)
|
||||
{
|
||||
switch (size) {
|
||||
@ -221,7 +215,7 @@ via_rd(struct via_info *via, int regno, int size)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static __inline void
|
||||
via_wr(struct via_info *via, int regno, u_int32_t data, int size)
|
||||
{
|
||||
|
||||
@ -347,7 +341,9 @@ via8233wr_setformat(kobj_t obj, void *data, u_int32_t format)
|
||||
f |= WR_FORMAT_STEREO;
|
||||
if (format & AFMT_S16_LE)
|
||||
f |= WR_FORMAT_16BIT;
|
||||
snd_mtxlock(via->lock);
|
||||
via_wr(via, VIA_WR0_FORMAT, f, 4);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -360,6 +356,7 @@ via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format)
|
||||
u_int32_t r, v;
|
||||
|
||||
r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
|
||||
snd_mtxlock(via->lock);
|
||||
v = via_rd(via, r, 4);
|
||||
|
||||
v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT);
|
||||
@ -368,6 +365,7 @@ via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format)
|
||||
if (format & AFMT_16BIT)
|
||||
v |= VIA8233_DXS_RATEFMT_16BIT;
|
||||
via_wr(via, r, v, 4);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -389,8 +387,10 @@ via8233msgd_setformat(kobj_t obj, void *data, u_int32_t format)
|
||||
s |= SLOT3(1) | SLOT4(1);
|
||||
}
|
||||
|
||||
snd_mtxlock(via->lock);
|
||||
via_wr(via, VIA_MC_SLOT_SELECT, s, 4);
|
||||
via_wr(via, VIA_MC_SGD_FORMAT, v, 1);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -418,12 +418,14 @@ via8233dxs_setspeed(kobj_t obj, void *data, u_int32_t speed)
|
||||
u_int32_t r, v;
|
||||
|
||||
r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
|
||||
snd_mtxlock(via->lock);
|
||||
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);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
return speed;
|
||||
}
|
||||
@ -505,7 +507,9 @@ via8233chan_getptr(kobj_t obj, void *data)
|
||||
u_int32_t v, index, count;
|
||||
int ptr;
|
||||
|
||||
snd_mtxlock(via->lock);
|
||||
v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4);
|
||||
snd_mtxunlock(via->lock);
|
||||
index = v >> 24; /* Last completed buffer */
|
||||
count = v & 0x00ffffff; /* Bytes remaining */
|
||||
ptr = (index + 1) * ch->blksz - count;
|
||||
@ -540,13 +544,13 @@ via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
|
||||
struct via_info *via = devinfo;
|
||||
struct via_chinfo *ch = &via->rch[c->num];
|
||||
|
||||
snd_mtxlock(via->lock);
|
||||
ch->parent = via;
|
||||
ch->channel = c;
|
||||
ch->buffer = b;
|
||||
ch->dir = dir;
|
||||
|
||||
ch->rbase = VIA_WR_BASE(c->num);
|
||||
snd_mtxlock(via->lock);
|
||||
via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
@ -568,7 +572,6 @@ via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
|
||||
struct via_info *via = devinfo;
|
||||
struct via_chinfo *ch = &via->pch[c->num];
|
||||
|
||||
snd_mtxlock(via->lock);
|
||||
ch->parent = via;
|
||||
ch->channel = c;
|
||||
ch->buffer = b;
|
||||
@ -579,6 +582,7 @@ via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
|
||||
* channels. We therefore want to align first DXS channel to
|
||||
* DXS3.
|
||||
*/
|
||||
snd_mtxlock(via->lock);
|
||||
ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered);
|
||||
via->n_dxs_registered++;
|
||||
snd_mtxunlock(via->lock);
|
||||
@ -601,13 +605,11 @@ via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
|
||||
struct via_info *via = devinfo;
|
||||
struct via_chinfo *ch = &via->pch[c->num];
|
||||
|
||||
snd_mtxlock(via->lock);
|
||||
ch->parent = via;
|
||||
ch->channel = c;
|
||||
ch->buffer = b;
|
||||
ch->dir = dir;
|
||||
ch->rbase = VIA_MC_SGD_STATUS;
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
|
||||
return NULL;
|
||||
@ -642,6 +644,7 @@ via8233chan_trigger(kobj_t obj, void* data, int go)
|
||||
struct via_chinfo *ch = data;
|
||||
struct via_info *via = ch->parent;
|
||||
|
||||
snd_mtxlock(via->lock);
|
||||
switch(go) {
|
||||
case PCMTRIG_START:
|
||||
via_buildsgdt(ch);
|
||||
@ -658,6 +661,7 @@ via8233chan_trigger(kobj_t obj, void* data, int go)
|
||||
via8233chan_reset(via, ch);
|
||||
break;
|
||||
}
|
||||
snd_mtxunlock(via->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ static u_int32_t via_fmt[] = {
|
||||
static struct pcmchan_caps via_vracaps = {4000, 48000, via_fmt, 0};
|
||||
static struct pcmchan_caps via_caps = {48000, 48000, via_fmt, 0};
|
||||
|
||||
static u_int32_t
|
||||
static __inline u_int32_t
|
||||
via_rd(struct via_info *via, int regno, int size)
|
||||
{
|
||||
|
||||
@ -116,7 +116,7 @@ via_rd(struct via_info *via, int regno, int size)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static __inline void
|
||||
via_wr(struct via_info *via, int regno, u_int32_t data, int size)
|
||||
{
|
||||
|
||||
@ -290,10 +290,12 @@ viachan_setformat(kobj_t obj, void *data, u_int32_t format)
|
||||
mode_set |= VIA_RPMODE_16BIT;
|
||||
|
||||
DEB(printf("set format: dir = %d, format=%x\n", ch->dir, format));
|
||||
snd_mtxlock(via->lock);
|
||||
mode = via_rd(via, ch->mode, 1);
|
||||
mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO);
|
||||
mode |= mode_set;
|
||||
via_wr(via, ch->mode, mode, 1);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -346,12 +348,14 @@ viachan_trigger(kobj_t obj, void *data, int go)
|
||||
ado = ch->sgd_table;
|
||||
DEB(printf("ado located at va=%p pa=%x\n", ado, sgd_addr));
|
||||
|
||||
snd_mtxlock(via->lock);
|
||||
if (go == PCMTRIG_START) {
|
||||
via_buildsgdt(ch);
|
||||
via_wr(via, ch->base, sgd_addr, 4);
|
||||
via_wr(via, ch->ctrl, VIA_RPCTRL_START, 1);
|
||||
} else
|
||||
via_wr(via, ch->ctrl, VIA_RPCTRL_TERMINATE, 1);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
DEB(printf("viachan_trigger: go=%d\n", go));
|
||||
return 0;
|
||||
@ -367,11 +371,13 @@ viachan_getptr(kobj_t obj, void *data)
|
||||
int ptr, base, base1, len, seg;
|
||||
|
||||
ado = ch->sgd_table;
|
||||
snd_mtxlock(via->lock);
|
||||
base1 = via_rd(via, ch->base, 4);
|
||||
len = via_rd(via, ch->count, 4);
|
||||
base = via_rd(via, ch->base, 4);
|
||||
if (base != base1) /* Avoid race hazard */
|
||||
len = via_rd(via, ch->count, 4);
|
||||
snd_mtxunlock(via->lock);
|
||||
|
||||
DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user