mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
sys/dev/sound/pcm/ac97.c:
* Added codec id for CMI9761. * feeder_volume *whitelist* through ac97_fix_volume() sys/dev/sound/pcm/ac97.h: * Added AC97_F_SOFTVOL definition. sys/dev/sound/pcm/channel.c: * Slight changes for chn_setvolume() to conform with OSS. * FEEDER_VOLUME is now part of feeder building process. sys/dev/sound/pcm/mixer.c: * General spl* cleanup. It doesn't serve any purpose anymore. * Main hook for feeder_volume. Submitted by: Ariff Abdullah <skywizard@MyBSD.org.my> Tested by: multimedia@
This commit is contained in:
parent
4406886f5e
commit
cb44f623ec
4 changed files with 112 additions and 19 deletions
|
|
@ -161,8 +161,11 @@ static struct ac97_codecid ac97codecid[] = {
|
|||
{ 0x43525940, 0x07, 0, "CS4201", 0 },
|
||||
{ 0x43525958, 0x07, 0, "CS4205", 0 },
|
||||
{ 0x43525960, 0x07, 0, "CS4291A", 0 },
|
||||
{ 0x434d4961, 0x00, 0, "CMI9739", 0 },
|
||||
{ 0x434d4961, 0x00, 0, "CMI9739", cmi9739_patch },
|
||||
{ 0x434d4941, 0x00, 0, "CMI9738", 0 },
|
||||
{ 0x434d4978, 0x00, 0, "CMI9761", 0 },
|
||||
{ 0x434d4982, 0x00, 0, "CMI9761", 0 },
|
||||
{ 0x434d4983, 0x00, 0, "CMI9761", 0 },
|
||||
{ 0x43585421, 0x00, 0, "HSD11246", 0 },
|
||||
{ 0x43585428, 0x07, 0, "CX20468", 0 },
|
||||
{ 0x44543000, 0x00, 0, "DT0398", 0 },
|
||||
|
|
@ -197,6 +200,7 @@ static struct ac97_codecid ac97codecid[] = {
|
|||
{ 0x83847658, 0x00, 0, "STAC9758/59", 0 },
|
||||
{ 0x83847660, 0x00, 0, "STAC9760/61", 0 }, /* Extrapolated */
|
||||
{ 0x83847662, 0x00, 0, "STAC9762/63", 0 }, /* Extrapolated */
|
||||
{ 0x83847666, 0x00, 0, "STAC9766/67", 0 },
|
||||
{ 0x53494c22, 0x00, 0, "Si3036", 0 },
|
||||
{ 0x53494c23, 0x00, 0, "Si3038", 0 },
|
||||
{ 0x54524103, 0x00, 0, "TR28023", 0 }, /* Extrapolated */
|
||||
|
|
@ -538,6 +542,40 @@ ac97_fix_tone(struct ac97_info *codec)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ac97_fix_volume(struct ac97_info *codec)
|
||||
{
|
||||
struct snddev_info *d = device_get_softc(codec->dev);
|
||||
|
||||
#if 0
|
||||
/* XXX For the sake of debugging purposes */
|
||||
ac97_wrcd(codec, AC97_MIX_PCM, 0);
|
||||
bzero(&codec->mix[SOUND_MIXER_PCM],
|
||||
sizeof(codec->mix[SOUND_MIXER_PCM]));
|
||||
codec->flags |= AC97_F_SOFTVOL;
|
||||
if (d)
|
||||
d->flags |= SD_F_SOFTVOL;
|
||||
return;
|
||||
#endif
|
||||
switch (codec->id) {
|
||||
case 0x434d4941: /* CMI9738 */
|
||||
case 0x434d4961: /* CMI9739 */
|
||||
case 0x434d4978: /* CMI9761 */
|
||||
case 0x434d4982: /* CMI9761 */
|
||||
case 0x434d4983: /* CMI9761 */
|
||||
ac97_wrcd(codec, AC97_MIX_PCM, 0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
bzero(&codec->mix[SOUND_MIXER_PCM],
|
||||
sizeof(codec->mix[SOUND_MIXER_PCM]));
|
||||
codec->flags |= AC97_F_SOFTVOL;
|
||||
if (d)
|
||||
d->flags |= SD_F_SOFTVOL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf)
|
||||
{
|
||||
|
|
@ -643,6 +681,7 @@ ac97_initmixer(struct ac97_info *codec)
|
|||
}
|
||||
ac97_fix_auxout(codec);
|
||||
ac97_fix_tone(codec);
|
||||
ac97_fix_volume(codec);
|
||||
if (codec_patch)
|
||||
codec_patch(codec);
|
||||
|
||||
|
|
@ -709,6 +748,8 @@ ac97_initmixer(struct ac97_info *codec)
|
|||
if (bootverbose) {
|
||||
if (codec->flags & AC97_F_RDCD_BUG)
|
||||
device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n");
|
||||
if (codec->flags & AC97_F_SOFTVOL)
|
||||
device_printf(codec->dev, "Soft PCM volume\n");
|
||||
device_printf(codec->dev, "Codec features ");
|
||||
for (i = j = 0; i < 10; i++)
|
||||
if (codec->caps & (1 << i))
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@
|
|||
|
||||
#define AC97_F_EAPD_INV 0x00000001
|
||||
#define AC97_F_RDCD_BUG 0x00000002
|
||||
#define AC97_F_SOFTVOL 0x00000004
|
||||
|
||||
#define AC97_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))
|
||||
#define AC97_CREATE(dev, devinfo, cls) ac97_create(dev, devinfo, &cls ## _class)
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ chn_sleep(struct pcm_channel *c, char *str, int timeout)
|
|||
|
||||
/*
|
||||
* chn_dmaupdate() tracks the status of a dma transfer,
|
||||
* updating pointers. It must be called at spltty().
|
||||
* updating pointers.
|
||||
*/
|
||||
|
||||
static unsigned int
|
||||
|
|
@ -394,7 +394,6 @@ chn_rddump(struct pcm_channel *c, unsigned int cnt)
|
|||
|
||||
/*
|
||||
* Feed new data from the read buffer. Can be called in the bottom half.
|
||||
* Hence must be called at spltty.
|
||||
*/
|
||||
int
|
||||
chn_rdfeed(struct pcm_channel *c)
|
||||
|
|
@ -785,8 +784,10 @@ chn_reset(struct pcm_channel *c, u_int32_t fmt)
|
|||
r = chn_setformat(c, fmt);
|
||||
if (r == 0)
|
||||
r = chn_setspeed(c, hwspd);
|
||||
#if 0
|
||||
if (r == 0)
|
||||
r = chn_setvolume(c, 100, 100);
|
||||
#endif
|
||||
}
|
||||
if (r == 0)
|
||||
r = chn_setblocksize(c, 0, 0);
|
||||
|
|
@ -926,7 +927,15 @@ chn_setvolume(struct pcm_channel *c, int left, int right)
|
|||
{
|
||||
CHN_LOCKASSERT(c);
|
||||
/* should add a feeder for volume changing if channel returns -1 */
|
||||
c->volume = (left << 8) | right;
|
||||
if (left > 100)
|
||||
left = 100;
|
||||
if (left < 0)
|
||||
left = 0;
|
||||
if (right > 100)
|
||||
right = 100;
|
||||
if (right < 0)
|
||||
right = 0;
|
||||
c->volume = left | (right << 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1303,6 +1312,12 @@ chn_buildfeeder(struct pcm_channel *c)
|
|||
return err;
|
||||
}
|
||||
}
|
||||
c->feederflags &= ~(1 << FEEDER_VOLUME);
|
||||
if (c->direction == PCMDIR_PLAY &&
|
||||
!(c->flags & CHN_F_VIRTUAL) &&
|
||||
c->parentsnddev && (c->parentsnddev->flags & SD_F_SOFTVOL) &&
|
||||
c->parentsnddev->mixer_dev)
|
||||
c->feederflags |= 1 << FEEDER_VOLUME;
|
||||
flags = c->feederflags;
|
||||
fmtlist = chn_getcaps(c)->fmtlist;
|
||||
|
||||
|
|
@ -1367,6 +1382,22 @@ chn_buildfeeder(struct pcm_channel *c)
|
|||
|
||||
sndbuf_setfmt(c->bufhard, hwfmt);
|
||||
|
||||
if ((flags & (1 << FEEDER_VOLUME))) {
|
||||
int vol = 100 | (100 << 8);
|
||||
|
||||
CHN_UNLOCK(c);
|
||||
/*
|
||||
* XXX This is ugly! The way mixer subs being so secretive
|
||||
* about its own internals force us to use this silly
|
||||
* monkey trick.
|
||||
*/
|
||||
if (mixer_ioctl(c->parentsnddev->mixer_dev,
|
||||
MIXER_READ(SOUND_MIXER_PCM), (caddr_t)&vol, -1, NULL) != 0)
|
||||
device_printf(c->dev, "Soft Volume: Failed to read default value\n");
|
||||
CHN_LOCK(c);
|
||||
chn_setvolume(c, vol & 0x7f, (vol >> 8) & 0x7f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ struct snd_mixer {
|
|||
int hwvol_muted;
|
||||
int hwvol_mixer;
|
||||
int hwvol_step;
|
||||
device_t dev;
|
||||
u_int32_t hwvol_mute_level;
|
||||
u_int32_t devs;
|
||||
u_int32_t recdevs;
|
||||
|
|
@ -112,6 +113,7 @@ mixer_lookup(char *devname)
|
|||
static int
|
||||
mixer_set(struct snd_mixer *mixer, unsigned dev, unsigned lev)
|
||||
{
|
||||
struct snddev_info *d;
|
||||
unsigned l, r;
|
||||
int v;
|
||||
|
||||
|
|
@ -121,9 +123,34 @@ mixer_set(struct snd_mixer *mixer, unsigned dev, unsigned lev)
|
|||
l = min((lev & 0x00ff), 100);
|
||||
r = min(((lev & 0xff00) >> 8), 100);
|
||||
|
||||
v = MIXER_SET(mixer, dev, l, r);
|
||||
if (v < 0)
|
||||
return -1;
|
||||
d = device_get_softc(mixer->dev);
|
||||
if (dev == SOUND_MIXER_PCM && d &&
|
||||
(d->flags & SD_F_SOFTVOL)) {
|
||||
struct snddev_channel *sce;
|
||||
struct pcm_channel *ch;
|
||||
#ifdef USING_MUTEX
|
||||
int locked = (mixer->lock && mtx_owned((struct mtx *)(mixer->lock))) ? 1 : 0;
|
||||
|
||||
if (locked)
|
||||
snd_mtxunlock(mixer->lock);
|
||||
#endif
|
||||
SLIST_FOREACH(sce, &d->channels, link) {
|
||||
ch = sce->channel;
|
||||
CHN_LOCK(ch);
|
||||
if (ch->direction == PCMDIR_PLAY &&
|
||||
(ch->feederflags & (1 << FEEDER_VOLUME)))
|
||||
chn_setvolume(ch, l, r);
|
||||
CHN_UNLOCK(ch);
|
||||
}
|
||||
#ifdef USING_MUTEX
|
||||
if (locked)
|
||||
snd_mtxlock(mixer->lock);
|
||||
#endif
|
||||
} else {
|
||||
v = MIXER_SET(mixer, dev, l, r);
|
||||
if (v < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
mixer->level[dev] = l | (r << 8);
|
||||
return 0;
|
||||
|
|
@ -156,6 +183,9 @@ mixer_getrecsrc(struct snd_mixer *mixer)
|
|||
void
|
||||
mix_setdevs(struct snd_mixer *m, u_int32_t v)
|
||||
{
|
||||
struct snddev_info *d = device_get_softc(m->dev);
|
||||
if (d && (d->flags & SD_F_SOFTVOL))
|
||||
v |= SOUND_MASK_PCM;
|
||||
m->devs = v;
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +228,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
|
|||
m->type = cls->name;
|
||||
m->devinfo = devinfo;
|
||||
m->busy = 0;
|
||||
m->dev = dev;
|
||||
|
||||
if (MIXER_INIT(m))
|
||||
goto bad;
|
||||
|
|
@ -397,16 +428,13 @@ static int
|
|||
mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
||||
{
|
||||
struct snd_mixer *m;
|
||||
intrmask_t s;
|
||||
|
||||
m = i_dev->si_drv1;
|
||||
s = spltty();
|
||||
snd_mtxlock(m->lock);
|
||||
|
||||
m->busy++;
|
||||
|
||||
snd_mtxunlock(m->lock);
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -414,21 +442,17 @@ static int
|
|||
mixer_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
||||
{
|
||||
struct snd_mixer *m;
|
||||
intrmask_t s;
|
||||
|
||||
m = i_dev->si_drv1;
|
||||
s = spltty();
|
||||
snd_mtxlock(m->lock);
|
||||
|
||||
if (!m->busy) {
|
||||
snd_mtxunlock(m->lock);
|
||||
splx(s);
|
||||
return EBADF;
|
||||
}
|
||||
m->busy--;
|
||||
|
||||
snd_mtxunlock(m->lock);
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -436,15 +460,13 @@ int
|
|||
mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
|
||||
{
|
||||
struct snd_mixer *m;
|
||||
intrmask_t s;
|
||||
int ret, *arg_i = (int *)arg;
|
||||
int v = -1, j = cmd & 0xff;
|
||||
|
||||
m = i_dev->si_drv1;
|
||||
if (!m->busy)
|
||||
if (mode != -1 && !m->busy)
|
||||
return EBADF;
|
||||
|
||||
s = spltty();
|
||||
snd_mtxlock(m->lock);
|
||||
if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) {
|
||||
if (j == SOUND_MIXER_RECSRC)
|
||||
|
|
@ -452,7 +474,6 @@ mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread
|
|||
else
|
||||
ret = mixer_set(m, j, *arg_i);
|
||||
snd_mtxunlock(m->lock);
|
||||
splx(s);
|
||||
return (ret == 0)? 0 : ENXIO;
|
||||
}
|
||||
|
||||
|
|
@ -480,7 +501,6 @@ mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread
|
|||
return (v != -1)? 0 : ENXIO;
|
||||
}
|
||||
snd_mtxunlock(m->lock);
|
||||
splx(s);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue