summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/sound/pcm/datatypes.h6
-rw-r--r--sys/dev/sound/pcm/mixer.c75
-rw-r--r--sys/dev/sound/pcm/mixer.h1
-rw-r--r--sys/dev/sound/pcm/sound.c13
4 files changed, 86 insertions, 9 deletions
diff --git a/sys/dev/sound/pcm/datatypes.h b/sys/dev/sound/pcm/datatypes.h
index 55f4111..bf6d73d 100644
--- a/sys/dev/sound/pcm/datatypes.h
+++ b/sys/dev/sound/pcm/datatypes.h
@@ -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;
};
/*****************************************************************************/
diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
index b8bbef7..c9d4ae8 100644
--- a/sys/dev/sound/pcm/mixer.c
+++ b/sys/dev/sound/pcm/mixer.c
@@ -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;
+
+ 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;
-static int hwvol_mixer = SOUND_MIXER_VOLUME;
-SYSCTL_INT(_hw_snd, OID_AUTO, hwvol_mixer, CTLFLAG_RW, &hwvol_mixer, 0, "");
+ 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);
}
}
diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h
index b29cc14..f7ad35c 100644
--- a/sys/dev/sound/pcm/mixer.h
+++ b/sys/dev/sound/pcm/mixer.h
@@ -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);
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index 7e110772..6c8d468 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -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;
OpenPOWER on IntegriCloud