- Make the 'hwvol_mixer' and 'hwvol_step' variables be specific to a
specific snd_mixer device rather than global across all mixers. - Add per-mixer mute status and saved mute_level so that the mixer_hwmute() function can now toggle the mute state when the mute button is pressed. - Create a dynamic sysctl tree hw.snd.pcmX when a pcm device is registered. - Move the hw.snd.hwvol_* sysctl's to hw.snd.pcmX.hwvol_* so that they are now properly device-specific. Eventually when the mixers become their own devices these sysctl's will move to live under a mixerX tree. - Change the interface of the hwvol_mixer sysctl so that it reports the name of the current mixer device instead of the number and is settable with the name instead of the number. - Add a new function mixer_hwinit() used to setup the dynamic sysctl's needed for the hwvol support that can be called by drivers that support hwvol. Reviewed by: cg
This commit is contained in:
parent
37f73f2c0d
commit
3c2f715fb6
@ -40,6 +40,10 @@ struct _snd_mixer {
|
||||
const char *name;
|
||||
void *devinfo;
|
||||
int busy;
|
||||
int muted;
|
||||
int hwvol_mixer;
|
||||
int hwvol_step;
|
||||
u_int32_t mute_level;
|
||||
u_int32_t devs;
|
||||
u_int32_t recdevs;
|
||||
u_int32_t recsrc;
|
||||
@ -133,6 +137,8 @@ struct _snddev_info {
|
||||
void *devinfo;
|
||||
device_t dev;
|
||||
char status[SND_STATUSLEN];
|
||||
struct sysctl_ctx_list sysctl_tree;
|
||||
struct sysctl_oid *sysctl_tree_top;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -48,6 +48,20 @@ static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = {
|
||||
[SOUND_MIXER_OGAIN] = 50,
|
||||
};
|
||||
|
||||
static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
|
||||
|
||||
static int
|
||||
mixer_lookup(char *devname)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
|
||||
if (strncmp(devname, snd_mixernames[i],
|
||||
strlen(snd_mixernames[i])) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
mixer_set(snd_mixer *mixer, unsigned dev, unsigned lev)
|
||||
{
|
||||
@ -254,39 +268,82 @@ mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg)
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
static int hwvol_step = 5;
|
||||
SYSCTL_INT(_hw_snd, OID_AUTO, hwvol_step, CTLFLAG_RW, &hwvol_step, 0, "");
|
||||
static int
|
||||
sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
char devname[32];
|
||||
int error, dev;
|
||||
snd_mixer *m;
|
||||
|
||||
static int hwvol_mixer = SOUND_MIXER_VOLUME;
|
||||
SYSCTL_INT(_hw_snd, OID_AUTO, hwvol_mixer, CTLFLAG_RW, &hwvol_mixer, 0, "");
|
||||
m = oidp->oid_arg1;
|
||||
strncpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname));
|
||||
error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req);
|
||||
if (error == 0 && req->newptr != NULL) {
|
||||
dev = mixer_lookup(devname);
|
||||
if (dev == -1)
|
||||
return EINVAL;
|
||||
else
|
||||
m->hwvol_mixer = dev;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
mixer_hwinit(device_t dev)
|
||||
{
|
||||
snddev_info *d;
|
||||
snd_mixer *m;
|
||||
|
||||
d = device_get_softc(dev);
|
||||
m = d->mixer;
|
||||
m->hwvol_mixer = SOUND_MIXER_VOLUME;
|
||||
m->hwvol_step = 5;
|
||||
SYSCTL_ADD_INT(&d->sysctl_tree, SYSCTL_CHILDREN(d->sysctl_tree_top),
|
||||
OID_AUTO, "hwvol_step", CTLFLAG_RW, &m->hwvol_step, 0, "");
|
||||
SYSCTL_ADD_PROC(&d->sysctl_tree, SYSCTL_CHILDREN(d->sysctl_tree_top),
|
||||
OID_AUTO, "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RW, m, 0,
|
||||
sysctl_hw_snd_hwvol_mixer, "A", "")
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mixer_hwmute(device_t dev)
|
||||
{
|
||||
snddev_info *d;
|
||||
snd_mixer *m;
|
||||
|
||||
d = device_get_softc(dev);
|
||||
mixer_set(d->mixer, hwvol_mixer, 0);
|
||||
m = d->mixer;
|
||||
if (m->muted) {
|
||||
m->muted = 0;
|
||||
mixer_set(m, m->hwvol_mixer, m->mute_level);
|
||||
} else {
|
||||
m->muted++;
|
||||
m->mute_level = mixer_get(m, m->hwvol_mixer);
|
||||
mixer_set(m, m->hwvol_mixer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mixer_hwstep(device_t dev, int left_step, int right_step)
|
||||
{
|
||||
snddev_info *d;
|
||||
snd_mixer *m;
|
||||
int level, left, right;
|
||||
|
||||
d = device_get_softc(dev);
|
||||
level = mixer_get(d->mixer, hwvol_mixer);
|
||||
m = d->mixer;
|
||||
level = mixer_get(m, m->hwvol_mixer);
|
||||
if (level != -1) {
|
||||
left = level & 0xff;
|
||||
right = level >> 8;
|
||||
left += left_step * hwvol_step;
|
||||
left += left_step * m->hwvol_step;
|
||||
if (left < 0)
|
||||
left = 0;
|
||||
right += right_step * hwvol_step;
|
||||
right += right_step * m->hwvol_step;
|
||||
if (right < 0)
|
||||
right = 0;
|
||||
mixer_set(d->mixer, hwvol_mixer, left | right << 8);
|
||||
mixer_set(m, m->hwvol_mixer, left | right << 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ extern int mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg);
|
||||
extern int mixer_busy(snd_mixer *m, int busy);
|
||||
extern int mixer_isbusy(snd_mixer *m);
|
||||
|
||||
int mixer_hwinit(device_t dev);
|
||||
void mixer_hwmute(device_t dev);
|
||||
void mixer_hwstep(device_t dev, int left_step, int right_step);
|
||||
|
||||
|
@ -302,6 +302,15 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
|
||||
} else
|
||||
d->rec = NULL;
|
||||
|
||||
sysctl_ctx_init(&d->sysctl_tree);
|
||||
d->sysctl_tree_top = SYSCTL_ADD_NODE(&d->sysctl_tree,
|
||||
&sysctl__hw_snd_children, OID_AUTO,
|
||||
device_get_nameunit(dev), CTLFLAG_RD, 0, "");
|
||||
if (!d->sysctl_tree_top) {
|
||||
sysctl_ctx_free(&d->sysctl_tree);
|
||||
goto no;
|
||||
}
|
||||
|
||||
if (numplay == 0 || numrec == 0)
|
||||
d->flags |= SD_F_SIMPLEX;
|
||||
|
||||
@ -326,6 +335,10 @@ pcm_unregister(device_t dev)
|
||||
snddev_info *d = device_get_softc(dev);
|
||||
dev_t pdev;
|
||||
|
||||
sysctl_remove_oid(d->sysctl_tree_top, 1, 1);
|
||||
d->sysctl_tree_top = NULL;
|
||||
sysctl_ctx_free(&d->sysctl_tree);
|
||||
|
||||
r = 0;
|
||||
for (i = 0; i < d->chancount; i++)
|
||||
if (d->ref[i]) r = EBUSY;
|
||||
|
Loading…
Reference in New Issue
Block a user