31#ifdef HAVE_KERNEL_OPTION_HEADERS
45SYSCTL_INT(_hw_snd, OID_AUTO, vpc_mixer_bypass, CTLFLAG_RWTUN,
47 "control channel pcm/rec volume, bypassing real mixer device");
49#define MIXER_NAMELEN 16
79 [SOUND_MIXER_VOLUME] = 75,
80 [SOUND_MIXER_BASS] = 50,
81 [SOUND_MIXER_TREBLE] = 50,
82 [SOUND_MIXER_SYNTH] = 75,
83 [SOUND_MIXER_PCM] = 75,
84 [SOUND_MIXER_SPEAKER] = 75,
85 [SOUND_MIXER_LINE] = 75,
86 [SOUND_MIXER_MIC] = 25,
87 [SOUND_MIXER_CD] = 75,
88 [SOUND_MIXER_IGAIN] = 0,
89 [SOUND_MIXER_LINE1] = 75,
90 [SOUND_MIXER_VIDEO] = 75,
91 [SOUND_MIXER_RECLEV] = 75,
92 [SOUND_MIXER_OGAIN] = 50,
93 [SOUND_MIXER_MONITOR] = 75,
103 .d_version = D_VERSION,
122 snddev = device_get_softc(
dev);
132 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
139#define MIXER_SET_UNLOCK(x, y) do { \
141 snd_mtxunlock((x)->lock); \
144#define MIXER_SET_LOCK(x, y) do { \
146 snd_mtxlock((x)->lock); \
154 int dropmtx, acquiremtx;
159 if (mtx_owned(
m->lock))
196 u_int
dev, u_int level)
200 int tone, dropmtx, acquiremtx;
202 if (
dev == SOUND_MIXER_TREBLE)
204 else if (
dev == SOUND_MIXER_BASS)
212 if (mtx_owned(
m->lock))
236 (void)FEEDER_SET(f, tone, level);
251 u_int32_t parent = SOUND_MIXER_NONE,
child = 0;
255 if (
m == NULL ||
dev >= SOUND_MIXER_NRDEVICES ||
256 (0 == (
m->devs & (1 <<
dev))))
259 l = min((lev & 0x00ff), 100);
260 r = min(((lev & 0xff00) >> 8), 100);
261 realdev =
m->realdev[
dev];
263 d = device_get_softc(
m->dev);
274 if (muted & (1 <<
dev)) {
275 m->level_muted[
dev] = l | (
r << 8);
281 parent =
m->parent[
dev];
282 if (parent >= SOUND_MIXER_NRDEVICES)
283 parent = SOUND_MIXER_NONE;
284 if (parent == SOUND_MIXER_NONE)
287 if (parent != SOUND_MIXER_NONE) {
288 tl = (l * (
m->level[parent] & 0x00ff)) / 100;
289 tr = (
r * ((
m->level[parent] & 0xff00) >> 8)) / 100;
292 else if (realdev != SOUND_MIXER_NONE &&
293 MIXER_SET(
m, realdev, tl, tr) < 0) {
297 }
else if (
child != 0) {
298 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
299 if (!(
child & (1 << i)) ||
m->parent[i] !=
dev)
301 realdev =
m->realdev[i];
302 tl = (l * (
m->level[i] & 0x00ff)) / 100;
303 tr = (
r * ((
m->level[i] & 0xff00) >> 8)) / 100;
304 if (i == SOUND_MIXER_PCM &&
307 else if (realdev != SOUND_MIXER_NONE)
308 MIXER_SET(
m, realdev, tl, tr);
310 realdev =
m->realdev[
dev];
311 if (realdev != SOUND_MIXER_NONE &&
312 MIXER_SET(
m, realdev, l,
r) < 0) {
319 else if ((
dev == SOUND_MIXER_TREBLE ||
322 else if (realdev != SOUND_MIXER_NONE &&
323 MIXER_SET(
m, realdev, l,
r) < 0) {
331 m->level[
dev] = l | (
r << 8);
340 if ((
dev < SOUND_MIXER_NRDEVICES) && (
mixer->devs & (1 <<
dev))) {
356 mutedevs &=
mixer->devs;
357 delta = (
mixer->mutedevs ^ mutedevs) &
mixer->devs;
358 mixer->mutedevs = mutedevs;
360 for (
int i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
361 if (!(delta & (1 << i)))
363 if (mutedevs & (1 << i)) {
379 d = device_get_softc(
mixer->dev);
388 src =
mixer->recdevs & SOUND_MASK_MIC;
390 src =
mixer->recdevs & SOUND_MASK_MONITOR;
392 src =
mixer->recdevs & SOUND_MASK_LINE;
393 if (
src == 0 &&
mixer->recdevs != 0)
394 src = (1 << (ffs(
mixer->recdevs) - 1));
397 recsrc = MIXER_SETRECSRC(
mixer,
src);
400 mixer->recsrc = recsrc;
408 return mixer->recsrc;
436 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
438 if ((1 << i) ==
m->recsrc)
440 if ((1 << i) &
m->recdevs)
444 if (i == SOUND_MIXER_NRDEVICES)
472 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
473 if ((1 << i) &
m->recdevs) {
480 if (i == SOUND_MIXER_NRDEVICES)
497 d = device_get_softc(
m->dev);
501 v |= SOUND_MASK_TREBLE | SOUND_MASK_BASS;
502 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
503 if (
m->parent[i] < SOUND_MIXER_NRDEVICES)
504 v |= 1 <<
m->parent[i];
531 oss_mixer_enuminfo *ei;
533 int i, nvalues, nwrote, nleft, ncopied;
539 nleft =
sizeof(ei->strings);
542 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
544 ei->strindex[nvalues] = nwrote;
558 if ((nleft <= 0) || (nvalues >= OSS_ENUM_MAXVALUE)) {
559 device_printf(
m->dev,
560 "mix_setrecdevs: Not enough room to store device names--please file a bug report.\n");
561 device_printf(
m->dev,
562 "mix_setrecdevs: Please include details about your sound hardware, OS version, etc.\n");
566 loc = &ei->strings[nwrote];
574 ei->nvalues = nvalues;
584 if (
m == NULL || parent >= SOUND_MIXER_NRDEVICES)
586 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
589 if (childs & (1 << i)) {
591 if (
m->parent[i] < SOUND_MIXER_NRDEVICES)
592 m->child[
m->parent[i]] &= ~(1 << i);
593 m->parent[i] = parent;
597 mask &= ~(1 << parent);
598 m->child[parent] =
mask;
604 if (
m == NULL ||
dev >= SOUND_MIXER_NRDEVICES ||
605 !(realdev == SOUND_MIXER_NONE || realdev < SOUND_MIXER_NRDEVICES))
607 m->realdev[
dev] = realdev;
613 if (
m == NULL ||
dev >= SOUND_MIXER_NRDEVICES)
614 return SOUND_MIXER_NONE;
615 return m->parent[
dev];
621 if (
m == NULL ||
dev >= SOUND_MIXER_NRDEVICES)
623 return m->child[
dev];
657 KASSERT(
dev != NULL && cls != NULL &&
devinfo != NULL,
658 (
"%s(): NULL data dev=%p cls=%p devinfo=%p",
661 (
"invalid mixer type=%d",
type));
663 m = (
struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO);
664 snprintf(
m->name,
sizeof(
m->name),
"%s:mixer",
665 device_get_nameunit(
dev));
667 strlcat(
m->name,
":",
sizeof(
m->name));
668 strlcat(
m->name,
desc,
sizeof(
m->name));
671 "primary pcm mixer" :
"secondary pcm mixer");
676 for (i = 0; i < (
sizeof(
m->parent) /
sizeof(
m->parent[0])); i++) {
677 m->parent[i] = SOUND_MIXER_NONE;
685 kobj_delete((kobj_t)
m, M_MIXER);
695 KASSERT(
m != NULL, (
"NULL snd_mixer"));
697 (
"%s(): illegal mixer type=%d", __func__,
m->
type));
704 kobj_delete((kobj_t)
m, M_MIXER);
731 int i, unit, devunit,
val;
733 snddev = device_get_softc(
dev);
737 if (resource_int_value(device_get_name(
dev),
738 device_get_unit(
dev),
"eq", &
val) == 0 &&
val != 0) {
751 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
754 if (resource_int_value(device_get_name(
dev),
756 if (
val >= 0 &&
val <= 100) {
766 unit = device_get_unit(
dev);
769 UID_ROOT, GID_WHEEL, 0666,
"mixer%d", unit);
776 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
777 if (!(
m->devs & (1 << i)))
779 if (
m->realdev[i] != i) {
780 device_printf(
dev,
"Mixer \"%s\" -> \"%s\":",
782 (
m->realdev[i] < SOUND_MIXER_NRDEVICES) ?
785 device_printf(
dev,
"Mixer \"%s\":",
788 if (
m->parent[i] < SOUND_MIXER_NRDEVICES)
789 printf(
" parent=\"%s\"",
791 if (
m->child[i] != 0)
792 printf(
" child=0x%08x",
m->child[i]);
796 device_printf(
dev,
"Soft PCM mixer ENABLED\n");
798 device_printf(
dev,
"EQ Treble/Bass ENABLED\n");
812 d = device_get_softc(
dev);
814 if (d == NULL || pdev == NULL || pdev->si_drv1 == NULL)
818 KASSERT(
m != NULL, (
"NULL snd_mixer"));
820 (
"%s(): illegal mixer type=%d", __func__,
m->
type));
833 pdev->si_drv1 = NULL;
838 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
850 kobj_delete((kobj_t)
m, M_MIXER);
876 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
877 if (
m->mutedevs & (1 << i))
900 error = sysctl_handle_string(oidp, &devname[0],
sizeof(devname),
req);
902 if (
error == 0 &&
req->newptr != NULL) {
908 m->hwvol_mixer =
dev;
924 m->hwvol_mixer = SOUND_MIXER_VOLUME;
926 SYSCTL_ADD_INT(device_get_sysctl_ctx(
dev),
927 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)),
928 OID_AUTO,
"hwvol_step", CTLFLAG_RWTUN, &
m->hwvol_step, 0,
"");
929 SYSCTL_ADD_PROC(device_get_sysctl_ctx(
dev),
930 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
931 "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
964 right = (level >> 8) & 0xff;
965 left += left_step *
m->hwvol_step;
970 right += right_step *
m->hwvol_step;
973 else if (
right > 100)
996 KASSERT(
m != NULL, (
"NULL snd_mixer"));
1006 KASSERT(
m != NULL, (
"NULL snd_mixer"));
1012 return ((ret != 0) ? ENXIO : 0);
1020 KASSERT(
m != NULL, (
"NULL snd_mixer"));
1034 KASSERT(
m != NULL, (
"NULL snd_mixer"));
1040 return ((ret != 0) ? ENXIO : 0);
1048 KASSERT(
m != NULL, (
"NULL snd_mixer"));
1060 KASSERT(
m != NULL, (
"NULL snd_mixer"));
1068 KASSERT(
m != NULL, (
"NULL snd_mixer"));
1076mixer_open(
struct cdev *i_dev,
int flags,
int mode,
struct thread *td)
1081 if (i_dev == NULL || i_dev->si_drv1 == NULL)
1085 d = device_get_softc(
m->dev);
1099mixer_close(
struct cdev *i_dev,
int flags,
int mode,
struct thread *td)
1105 if (i_dev == NULL || i_dev->si_drv1 == NULL)
1109 d = device_get_softc(
m->dev);
1116 ret = (
m->busy == 0) ? EBADF : 0;
1125 struct thread *td,
int from)
1133 if (td == NULL || td->td_proc == NULL)
1137 d = device_get_softc(
m->dev);
1141 case SOUND_MIXER_PCM:
1142 case SOUND_MIXER_RECLEV:
1143 case SOUND_MIXER_DEVMASK:
1144 case SOUND_MIXER_CAPS:
1145 case SOUND_MIXER_STEREODEVS:
1152 pid = td->td_proc->p_pid;
1178 if (j == SOUND_MIXER_RECLEV)
1179 goto mixer_ioctl_channel_proc;
1182 if (j == SOUND_MIXER_PCM)
1183 goto mixer_ioctl_channel_proc;
1186 if (rdch != NULL && wrch != NULL)
1190 if (rdch == NULL && wrch == NULL)
1193 if ((j == SOUND_MIXER_DEVMASK || j == SOUND_MIXER_CAPS ||
1194 j == SOUND_MIXER_STEREODEVS) &&
1195 (cmd & ~0xff) == MIXER_READ(0)) {
1200 *(
int *)arg |= SOUND_MASK_RECLEV;
1202 *(
int *)arg |= SOUND_MASK_PCM;
1208mixer_ioctl_channel_proc:
1210 KASSERT(
c != NULL, (
"%s(): NULL channel", __func__));
1213 if ((cmd & ~0xff) == MIXER_WRITE(0)) {
1216 left = *(
int *)arg & 0x7f;
1217 right = (*(
int *)arg >> 8) & 0x7f;
1220 }
else if ((cmd & ~0xff) == MIXER_READ(0)) {
1238 if (i_dev == NULL || i_dev->si_drv1 == NULL)
1241 d = device_get_softc(((
struct snd_mixer *)i_dev->si_drv1)->dev);
1267 bzero((
void *)mi,
sizeof(*mi));
1268 strlcpy(mi->id,
m->name,
sizeof(mi->id));
1269 strlcpy(mi->name, device_get_desc(
m->dev),
sizeof(mi->name));
1270 mi->modify_counter =
m->modify_counter;
1279 struct thread *td,
int from)
1282 int ret = EINVAL, *arg_i = (
int *)arg;
1283 int v = -1, j = cmd & 0xff;
1289 if (IOCGROUP(cmd) ==
'X') {
1291 case SNDCTL_SYSINFO:
1294 case SNDCTL_CARDINFO:
1296 case SNDCTL_AUDIOINFO:
1297 case SNDCTL_AUDIOINFO_EX:
1298 case SNDCTL_ENGINEINFO:
1300 case SNDCTL_MIXERINFO:
1317 case SNDCTL_DSP_GET_RECSRC_NAMES:
1318 bcopy((
void *)&
m->enuminfo, arg,
sizeof(oss_mixer_enuminfo));
1321 case SNDCTL_DSP_GET_RECSRC:
1324 case SNDCTL_DSP_SET_RECSRC:
1327 case OSS_GETVERSION:
1328 *arg_i = SOUND_VERSION;
1331 case SOUND_MIXER_INFO:
1336 if ((cmd & ~0xff) == MIXER_WRITE(0)) {
1338 case SOUND_MIXER_RECSRC:
1341 case SOUND_MIXER_MUTE:
1350 return ((ret == 0) ? 0 : ENXIO);
1352 if ((cmd & ~0xff) == MIXER_READ(0)) {
1354 case SOUND_MIXER_DEVMASK:
1355 case SOUND_MIXER_CAPS:
1356 case SOUND_MIXER_STEREODEVS:
1359 case SOUND_MIXER_MUTE:
1362 case SOUND_MIXER_RECMASK:
1365 case SOUND_MIXER_RECSRC:
1374 return ((v != -1) ? 0 : ENXIO);
1384 char *
name,
int namelen,
struct cdev **
dev)
1390 if (strcmp(
name,
"mixer") == 0) {
1473 ((mi->dev == -1 && d->
mixer_dev == i_dev) ||
1485 bzero((
void *)mi,
sizeof(*mi));
1487 snprintf(mi->id,
sizeof(mi->id),
"mixer%d", i);
1488 strlcpy(mi->name,
m->name,
sizeof(mi->name));
1489 mi->modify_counter =
m->modify_counter;
1490 mi->card_number = i;
1495 mi->port_number = 0;
1519 mi->enabled = device_is_attached(
m->dev) ? 1 : 0;
1549 mtx_unlock(
m->lock);
1569 if (
m->lock == NULL) {
1582 *pright = *pleft = -1;
1586 *pleft = level & 0xFF;
1587 *pright = (level >> 8) & 0xFF;
1597 level = (
left & 0xFF) | ((
right & 0xFF) << 8);
int chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right, int center)
#define CHN_GETVOLUME(x, y, z)
#define CHN_FOREACH(x, y, z)
#define CHN_LOCKASSERT(c)
struct pcmchan_matrix * m
int dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai)
Handler for SNDCTL_AUDIOINFO.
struct pcm_feeder * chn_findfeeder(struct pcm_channel *c, u_int32_t type)
u_int32_t mix_getparent(struct snd_mixer *m, u_int32_t dev)
int mix_set_locked(struct snd_mixer *m, u_int dev, int left, int right)
int mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td, int from)
static int mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
static int mixer_get(struct snd_mixer *mixer, int dev)
SYSCTL_INT(_hw_snd, OID_AUTO, vpc_mixer_bypass, CTLFLAG_RWTUN, &mixer_bypass, 0, "control channel pcm/rec volume, bypassing real mixer device")
u_int32_t mix_getmutedevs(struct snd_mixer *m)
void mix_setmutedevs(struct snd_mixer *mixer, u_int32_t mutedevs)
static struct snd_mixer * mixer_obj_create(device_t dev, kobj_class_t cls, void *devinfo, int type, const char *desc)
static int mixer_set_eq(struct snd_mixer *m, struct snddev_info *d, u_int dev, u_int level)
void mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs)
void mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev)
static d_close_t mixer_close
static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES]
device_t mix_get_dev(struct snd_mixer *m)
int mixer_busy(struct snd_mixer *m)
static d_ioctl_t mixer_ioctl
u_int32_t mix_getrecsrc(struct snd_mixer *m)
static int mixer_ioctl_channel(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *td, int from)
u_int32_t mix_getchild(struct snd_mixer *m, u_int32_t dev)
struct mtx * mixer_get_lock(struct snd_mixer *m)
SYSUNINIT(mixer_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysuninit, NULL)
void mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step)
int mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
static struct cdevsw mixer_cdevsw
int mixer_delete(struct snd_mixer *m)
static d_open_t mixer_open
static int sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS)
#define MIXER_SET_UNLOCK(x, y)
static int mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev)
u_int32_t mix_getdevs(struct snd_mixer *m)
int mixer_uninit(device_t dev)
void mixer_hwvol_step(device_t dev, int left_step, int right_step)
int mixer_hwvol_init(device_t dev)
static eventhandler_tag mixer_ehtag
static int mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d, u_int left, u_int right)
static struct cdev * mixer_get_devt(device_t dev)
void mix_setdevs(struct snd_mixer *m, u_int32_t v)
struct snd_mixer * mixer_create(device_t dev, kobj_class_t cls, void *devinfo, const char *desc)
SND_DECLARE_FILE("$FreeBSD$")
int mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi)
Handler for SNDCTL_MIXERINFO.
static void mixer_mixerinfo(struct snd_mixer *m, mixer_info *mi)
static char * snd_mixernames[SOUND_MIXER_NRDEVICES]
static int mixer_set_recroute(struct snd_mixer *m, int route)
Select a device for recording.
#define MIXER_SET_LOCK(x, y)
static void mixer_sysinit(void *p)
int mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
static int mixer_getrecsrc(struct snd_mixer *mixer)
int mixer_reinit(device_t dev)
void mixer_hwvol_mute_locked(struct snd_mixer *m)
u_int32_t mix_getrecdevs(struct snd_mixer *m)
int mix_get_locked(struct snd_mixer *m, u_int dev, int *pleft, int *pright)
static int mixer_get_recroute(struct snd_mixer *m, int *route)
Retrieve the route number of the current recording device.
static MALLOC_DEFINE(M_MIXER, "mixer", "mixer")
static int mixer_lookup(char *devname)
int mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right)
void * mix_getdevinfo(struct snd_mixer *m)
static void mixer_clone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev)
void mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
Record mask of available recording devices.
void mixer_hwvol_mute(device_t dev)
SYSINIT(mixer_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysinit, NULL)
static void mixer_sysuninit(void *p)
int mix_get_type(struct snd_mixer *m)
int mix_get(struct snd_mixer *m, u_int dev)
#define MIXER_TYPE_SECONDARY
#define MIXER_TYPE_PRIMARY
void * snd_mtxcreate(const char *desc, const char *type)
int sound_oss_card_info(oss_card_info *si)
void snd_mtxfree(void *m)
void sound_oss_sysinfo(oss_sysinfo *si)
Handle OSSv4 SNDCTL_SYSINFO ioctl.
#define PCM_GIANT_LEAVE(x)
#define PCM_RELEASE_QUICK(x)
#define PCM_ACQUIRE_QUICK(x)
#define PCM_UNLOCKASSERT(d)
#define PCM_GIANT_ENTER(x)
#define PCM_REGISTERED(x)
struct pcm_channel::@28 channels
oss_mixer_enuminfo enuminfo
u_int16_t level_muted[32]
struct snddev_info::@49::@50::@51 busy
struct snddev_info::@49::@50 pcm
int snd_mkunit(int u, int d, int c)