sound: Import latest code from FreeBSD
[dragonfly.git] / sys / dev / sound / pcm / mixer.c
1 /*-
2  * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
3  * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
4  * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #ifdef HAVE_KERNEL_OPTION_HEADERS
30 #include "opt_snd.h"
31 #endif
32
33 #include <dev/sound/pcm/sound.h>
34
35 #include "feeder_if.h"
36 #include "mixer_if.h"
37
38 SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/mixer.c 274035 2014-11-03 11:11:45Z bapt $");
39
40 static MALLOC_DEFINE(M_MIXER, "mixer", "mixer");
41
42 static int mixer_bypass = 1;
43 SYSCTL_INT(_hw_snd, OID_AUTO, vpc_mixer_bypass, CTLFLAG_RWTUN,
44     &mixer_bypass, 0,
45     "control channel pcm/rec volume, bypassing real mixer device");
46
47 #define MIXER_NAMELEN   16
48 struct snd_mixer {
49         KOBJ_FIELDS;
50         void *devinfo;
51         int busy;
52         int hwvol_muted;
53         int hwvol_mixer;
54         int hwvol_step;
55         int type;
56         device_t dev;
57         u_int32_t hwvol_mute_level;
58         u_int32_t devs;
59         u_int32_t recdevs;
60         u_int32_t recsrc;
61         u_int16_t level[32];
62         u_int8_t parent[32];
63         u_int32_t child[32];
64         u_int8_t realdev[32];
65         char name[MIXER_NAMELEN];
66         struct mtx *lock;
67         oss_mixer_enuminfo enuminfo;
68         /** 
69          * Counter is incremented when applications change any of this
70          * mixer's controls.  A change in value indicates that persistent
71          * mixer applications should update their displays.
72          */
73         int modify_counter;
74 };
75
76 static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = {
77         [SOUND_MIXER_VOLUME]    = 75,
78         [SOUND_MIXER_BASS]      = 50,
79         [SOUND_MIXER_TREBLE]    = 50,
80         [SOUND_MIXER_SYNTH]     = 75,
81         [SOUND_MIXER_PCM]       = 75,
82         [SOUND_MIXER_SPEAKER]   = 75,
83         [SOUND_MIXER_LINE]      = 75,
84         [SOUND_MIXER_MIC]       = 0,
85         [SOUND_MIXER_CD]        = 75,
86         [SOUND_MIXER_IGAIN]     = 0,
87         [SOUND_MIXER_LINE1]     = 75,
88         [SOUND_MIXER_VIDEO]     = 75,
89         [SOUND_MIXER_RECLEV]    = 75,
90         [SOUND_MIXER_OGAIN]     = 50,
91         [SOUND_MIXER_MONITOR]   = 75,
92 };
93
94 static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
95
96 static d_open_t mixer_open;
97 static d_close_t mixer_close;
98 static d_ioctl_t mixer_ioctl;
99
100 static struct cdevsw mixer_cdevsw = {
101         .d_version =    D_VERSION,
102         .d_open =       mixer_open,
103         .d_close =      mixer_close,
104         .d_ioctl =      mixer_ioctl,
105         .d_name =       "mixer",
106 };
107
108 /**
109  * Keeps a count of mixer devices; used only by OSSv4 SNDCTL_SYSINFO ioctl.
110  */
111 int mixer_count = 0;
112
113 static eventhandler_tag mixer_ehtag = NULL;
114
115 static struct cdev *
116 mixer_get_devt(device_t dev)
117 {
118         struct snddev_info *snddev;
119
120         snddev = device_get_softc(dev);
121
122         return snddev->mixer_dev;
123 }
124
125 static int
126 mixer_lookup(char *devname)
127 {
128         int i;
129
130         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
131                 if (strncmp(devname, snd_mixernames[i],
132                     strlen(snd_mixernames[i])) == 0)
133                         return i;
134         return -1;
135 }
136
137 #define MIXER_SET_UNLOCK(x, y)          do {                            \
138         if ((y) != 0)                                                   \
139                 snd_mtxunlock((x)->lock);                               \
140 } while (0)
141
142 #define MIXER_SET_LOCK(x, y)            do {                            \
143         if ((y) != 0)                                                   \
144                 snd_mtxlock((x)->lock);                                 \
145 } while (0)
146
147 static int
148 mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d,
149     u_int left, u_int right)
150 {
151         struct pcm_channel *c;
152         int dropmtx, acquiremtx;
153
154         if (!PCM_REGISTERED(d))
155                 return (EINVAL);
156
157         if (mtx_owned(m->lock))
158                 dropmtx = 1;
159         else
160                 dropmtx = 0;
161         
162         if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0)
163                 acquiremtx = 0;
164         else
165                 acquiremtx = 1;
166
167         /*
168          * Be careful here. If we're coming from cdev ioctl, it is OK to
169          * not doing locking AT ALL (except on individual channel) since
170          * we've been heavily guarded by pcm cv, or if we're still
171          * under Giant influence. Since we also have mix_* calls, we cannot
172          * assume such protection and just do the lock as usuall.
173          */
174         MIXER_SET_UNLOCK(m, dropmtx);
175         MIXER_SET_LOCK(d, acquiremtx);
176
177         CHN_FOREACH(c, d, channels.pcm.busy) {
178                 CHN_LOCK(c);
179                 if (c->direction == PCMDIR_PLAY &&
180                     (c->feederflags & (1 << FEEDER_VOLUME)))
181                         chn_setvolume_multi(c, SND_VOL_C_MASTER, left, right,
182                             (left + right) >> 1);
183                 CHN_UNLOCK(c);
184         }
185
186         MIXER_SET_UNLOCK(d, acquiremtx);
187         MIXER_SET_LOCK(m, dropmtx);
188
189         return (0);
190 }
191
192 static int
193 mixer_set_eq(struct snd_mixer *m, struct snddev_info *d,
194     u_int dev, u_int level)
195 {
196         struct pcm_channel *c;
197         struct pcm_feeder *f;
198         int tone, dropmtx, acquiremtx;
199
200         if (dev == SOUND_MIXER_TREBLE)
201                 tone = FEEDEQ_TREBLE;
202         else if (dev == SOUND_MIXER_BASS)
203                 tone = FEEDEQ_BASS;
204         else
205                 return (EINVAL);
206
207         if (!PCM_REGISTERED(d))
208                 return (EINVAL);
209
210         if (mtx_owned(m->lock))
211                 dropmtx = 1;
212         else
213                 dropmtx = 0;
214         
215         if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0)
216                 acquiremtx = 0;
217         else
218                 acquiremtx = 1;
219
220         /*
221          * Be careful here. If we're coming from cdev ioctl, it is OK to
222          * not doing locking AT ALL (except on individual channel) since
223          * we've been heavily guarded by pcm cv, or if we're still
224          * under Giant influence. Since we also have mix_* calls, we cannot
225          * assume such protection and just do the lock as usuall.
226          */
227         MIXER_SET_UNLOCK(m, dropmtx);
228         MIXER_SET_LOCK(d, acquiremtx);
229
230         CHN_FOREACH(c, d, channels.pcm.busy) {
231                 CHN_LOCK(c);
232                 f = chn_findfeeder(c, FEEDER_EQ);
233                 if (f != NULL)
234                         (void)FEEDER_SET(f, tone, level);
235                 CHN_UNLOCK(c);
236         }
237
238         MIXER_SET_UNLOCK(d, acquiremtx);
239         MIXER_SET_LOCK(m, dropmtx);
240
241         return (0);
242 }
243
244 static int
245 mixer_set(struct snd_mixer *m, u_int dev, u_int lev)
246 {
247         struct snddev_info *d;
248         u_int l, r, tl, tr;
249         u_int32_t parent = SOUND_MIXER_NONE, child = 0;
250         u_int32_t realdev;
251         int i, dropmtx;
252
253         if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
254             (0 == (m->devs & (1 << dev))))
255                 return -1;
256
257         l = min((lev & 0x00ff), 100);
258         r = min(((lev & 0xff00) >> 8), 100);
259         realdev = m->realdev[dev];
260
261         d = device_get_softc(m->dev);
262         if (d == NULL)
263                 return -1;
264
265         /* It is safe to drop this mutex due to Giant. */
266         if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0)
267                 dropmtx = 1;
268         else
269                 dropmtx = 0;
270
271         MIXER_SET_UNLOCK(m, dropmtx);
272
273         /* TODO: recursive handling */
274         parent = m->parent[dev];
275         if (parent >= SOUND_MIXER_NRDEVICES)
276                 parent = SOUND_MIXER_NONE;
277         if (parent == SOUND_MIXER_NONE)
278                 child = m->child[dev];
279
280         if (parent != SOUND_MIXER_NONE) {
281                 tl = (l * (m->level[parent] & 0x00ff)) / 100;
282                 tr = (r * ((m->level[parent] & 0xff00) >> 8)) / 100;
283                 if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
284                         (void)mixer_set_softpcmvol(m, d, tl, tr);
285                 else if (realdev != SOUND_MIXER_NONE &&
286                     MIXER_SET(m, realdev, tl, tr) < 0) {
287                         MIXER_SET_LOCK(m, dropmtx);
288                         return -1;
289                 }
290         } else if (child != 0) {
291                 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
292                         if (!(child & (1 << i)) || m->parent[i] != dev)
293                                 continue;
294                         realdev = m->realdev[i];
295                         tl = (l * (m->level[i] & 0x00ff)) / 100;
296                         tr = (r * ((m->level[i] & 0xff00) >> 8)) / 100;
297                         if (i == SOUND_MIXER_PCM &&
298                             (d->flags & SD_F_SOFTPCMVOL))
299                                 (void)mixer_set_softpcmvol(m, d, tl, tr);
300                         else if (realdev != SOUND_MIXER_NONE)
301                                 MIXER_SET(m, realdev, tl, tr);
302                 }
303                 realdev = m->realdev[dev];
304                 if (realdev != SOUND_MIXER_NONE &&
305                     MIXER_SET(m, realdev, l, r) < 0) {
306                                 MIXER_SET_LOCK(m, dropmtx);
307                                 return -1;
308                 }
309         } else {
310                 if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
311                         (void)mixer_set_softpcmvol(m, d, l, r);
312                 else if ((dev == SOUND_MIXER_TREBLE ||
313                     dev == SOUND_MIXER_BASS) && (d->flags & SD_F_EQ))
314                         (void)mixer_set_eq(m, d, dev, (l + r) >> 1);
315                 else if (realdev != SOUND_MIXER_NONE &&
316                     MIXER_SET(m, realdev, l, r) < 0) {
317                         MIXER_SET_LOCK(m, dropmtx);
318                         return -1;
319                 }
320         }
321
322         MIXER_SET_LOCK(m, dropmtx);
323
324         m->level[dev] = l | (r << 8);
325
326         return 0;
327 }
328
329 static int
330 mixer_get(struct snd_mixer *mixer, int dev)
331 {
332         if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev)))
333                 return mixer->level[dev];
334         else
335                 return -1;
336 }
337
338 static int
339 mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
340 {
341         struct snddev_info *d;
342         u_int32_t recsrc;
343         int dropmtx;
344
345         d = device_get_softc(mixer->dev);
346         if (d == NULL)
347                 return -1;
348         if (!(d->flags & SD_F_MPSAFE) && mtx_owned(mixer->lock) != 0)
349                 dropmtx = 1;
350         else
351                 dropmtx = 0;
352         src &= mixer->recdevs;
353         if (src == 0)
354                 src = mixer->recdevs & SOUND_MASK_MIC;
355         if (src == 0)
356                 src = mixer->recdevs & SOUND_MASK_MONITOR;
357         if (src == 0)
358                 src = mixer->recdevs & SOUND_MASK_LINE;
359         if (src == 0 && mixer->recdevs != 0)
360                 src = (1 << (ffs(mixer->recdevs) - 1));
361         /* It is safe to drop this mutex due to Giant. */
362         MIXER_SET_UNLOCK(mixer, dropmtx);
363         recsrc = MIXER_SETRECSRC(mixer, src);
364         MIXER_SET_LOCK(mixer, dropmtx);
365
366         mixer->recsrc = recsrc;
367
368         return 0;
369 }
370
371 static int
372 mixer_getrecsrc(struct snd_mixer *mixer)
373 {
374         return mixer->recsrc;
375 }
376
377 /**
378  * @brief Retrieve the route number of the current recording device
379  *
380  * OSSv4 assigns routing numbers to recording devices, unlike the previous
381  * API which relied on a fixed table of device numbers and names.  This
382  * function returns the routing number of the device currently selected
383  * for recording.
384  *
385  * For now, this function is kind of a goofy compatibility stub atop the
386  * existing sound system.  (For example, in theory, the old sound system
387  * allows multiple recording devices to be specified via a bitmask.)
388  *
389  * @param m     mixer context container thing
390  *
391  * @retval 0            success
392  * @retval EIDRM        no recording device found (generally not possible)
393  * @todo Ask about error code
394  */
395 static int
396 mixer_get_recroute(struct snd_mixer *m, int *route)
397 {
398         int i, cnt;
399
400         cnt = 0;
401
402         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
403                 /** @todo can user set a multi-device mask? (== or &?) */
404                 if ((1 << i) == m->recsrc)
405                         break;
406                 if ((1 << i) & m->recdevs)
407                         ++cnt;
408         }
409
410         if (i == SOUND_MIXER_NRDEVICES)
411                 return EIDRM;
412
413         *route = cnt;
414         return 0;
415 }
416
417 /**
418  * @brief Select a device for recording
419  *
420  * This function sets a recording source based on a recording device's
421  * routing number.  Said number is translated to an old school recdev
422  * mask and passed over mixer_setrecsrc. 
423  *
424  * @param m     mixer context container thing
425  *
426  * @retval 0            success(?)
427  * @retval EINVAL       User specified an invalid device number
428  * @retval otherwise    error from mixer_setrecsrc
429  */
430 static int
431 mixer_set_recroute(struct snd_mixer *m, int route)
432 {
433         int i, cnt, ret;
434
435         ret = 0;
436         cnt = 0;
437
438         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
439                 if ((1 << i) & m->recdevs) {
440                         if (route == cnt)
441                                 break;
442                         ++cnt;
443                 }
444         }
445
446         if (i == SOUND_MIXER_NRDEVICES)
447                 ret = EINVAL;
448         else
449                 ret = mixer_setrecsrc(m, (1 << i));
450
451         return ret;
452 }
453
454 void
455 mix_setdevs(struct snd_mixer *m, u_int32_t v)
456 {
457         struct snddev_info *d;
458         int i;
459
460         if (m == NULL)
461                 return;
462
463         d = device_get_softc(m->dev);
464         if (d != NULL && (d->flags & SD_F_SOFTPCMVOL))
465                 v |= SOUND_MASK_PCM;
466         if (d != NULL && (d->flags & SD_F_EQ))
467                 v |= SOUND_MASK_TREBLE | SOUND_MASK_BASS;
468         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
469                 if (m->parent[i] < SOUND_MIXER_NRDEVICES)
470                         v |= 1 << m->parent[i];
471                 v |= m->child[i];
472         }
473         m->devs = v;
474 }
475
476 /**
477  * @brief Record mask of available recording devices
478  *
479  * Calling functions are responsible for defining the mask of available
480  * recording devices.  This function records that value in a structure
481  * used by the rest of the mixer code.
482  *
483  * This function also populates a structure used by the SNDCTL_DSP_*RECSRC*
484  * family of ioctls that are part of OSSV4.  All recording device labels
485  * are concatenated in ascending order corresponding to their routing
486  * numbers.  (Ex:  a system might have 0 => 'vol', 1 => 'cd', 2 => 'line',
487  * etc.)  For now, these labels are just the standard recording device
488  * names (cd, line1, etc.), but will eventually be fully dynamic and user
489  * controlled.
490  *
491  * @param m     mixer device context container thing
492  * @param v     mask of recording devices
493  */
494 void
495 mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
496 {
497         oss_mixer_enuminfo *ei;
498         char *loc;
499         int i, nvalues, nwrote, nleft, ncopied;
500
501         ei = &m->enuminfo;
502
503         nvalues = 0;
504         nwrote = 0;
505         nleft = sizeof(ei->strings);
506         loc = ei->strings;
507
508         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
509                 if ((1 << i) & v) {
510                         ei->strindex[nvalues] = nwrote;
511                         ncopied = strlcpy(loc, snd_mixernames[i], nleft) + 1;
512                             /* strlcpy retval doesn't include terminator */
513
514                         nwrote += ncopied;
515                         nleft -= ncopied;
516                         nvalues++;
517
518                         /*
519                          * XXX I don't think this should ever be possible.
520                          * Even with a move to dynamic device/channel names,
521                          * each label is limited to ~16 characters, so that'd
522                          * take a LOT to fill this buffer.
523                          */
524                         if ((nleft <= 0) || (nvalues >= OSS_ENUM_MAXVALUE)) {
525                                 device_printf(m->dev,
526                                     "mix_setrecdevs:  Not enough room to store device names--please file a bug report.\n");
527                                 device_printf(m->dev, 
528                                     "mix_setrecdevs:  Please include details about your sound hardware, OS version, etc.\n");
529                                 break;
530                         }
531
532                         loc = &ei->strings[nwrote];
533                 }
534         }
535
536         /*
537          * NB:  The SNDCTL_DSP_GET_RECSRC_NAMES ioctl ignores the dev
538          *      and ctrl fields.
539          */
540         ei->nvalues = nvalues;
541         m->recdevs = v;
542 }
543
544 void
545 mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs)
546 {
547         u_int32_t mask = 0;
548         int i;
549
550         if (m == NULL || parent >= SOUND_MIXER_NRDEVICES)
551                 return;
552         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
553                 if (i == parent)
554                         continue;
555                 if (childs & (1 << i)) {
556                         mask |= 1 << i;
557                         if (m->parent[i] < SOUND_MIXER_NRDEVICES)
558                                 m->child[m->parent[i]] &= ~(1 << i);
559                         m->parent[i] = parent;
560                         m->child[i] = 0;
561                 }
562         }
563         mask &= ~(1 << parent);
564         m->child[parent] = mask;
565 }
566
567 void
568 mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev)
569 {
570         if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
571             !(realdev == SOUND_MIXER_NONE || realdev < SOUND_MIXER_NRDEVICES))
572                 return;
573         m->realdev[dev] = realdev;
574 }
575
576 u_int32_t
577 mix_getparent(struct snd_mixer *m, u_int32_t dev)
578 {
579         if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
580                 return SOUND_MIXER_NONE;
581         return m->parent[dev];
582 }
583
584 u_int32_t
585 mix_getchild(struct snd_mixer *m, u_int32_t dev)
586 {
587         if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
588                 return 0;
589         return m->child[dev];
590 }
591
592 u_int32_t
593 mix_getdevs(struct snd_mixer *m)
594 {
595         return m->devs;
596 }
597
598 u_int32_t
599 mix_getrecdevs(struct snd_mixer *m)
600 {
601         return m->recdevs;
602 }
603
604 void *
605 mix_getdevinfo(struct snd_mixer *m)
606 {
607         return m->devinfo;
608 }
609
610 static struct snd_mixer *
611 mixer_obj_create(device_t dev, kobj_class_t cls, void *devinfo,
612     int type, const char *desc)
613 {
614         struct snd_mixer *m;
615         int i;
616
617         KASSERT(dev != NULL && cls != NULL && devinfo != NULL,
618             ("%s(): NULL data dev=%p cls=%p devinfo=%p",
619             __func__, dev, cls, devinfo));
620         KASSERT(type == MIXER_TYPE_PRIMARY || type == MIXER_TYPE_SECONDARY,
621             ("invalid mixer type=%d", type));
622
623         m = (struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO);
624         snprintf(m->name, sizeof(m->name), "%s:mixer",
625             device_get_nameunit(dev));
626         if (desc != NULL) {
627                 strlcat(m->name, ":", sizeof(m->name));
628                 strlcat(m->name, desc, sizeof(m->name));
629         }
630         m->lock = snd_mtxcreate(m->name, (type == MIXER_TYPE_PRIMARY) ?
631             "primary pcm mixer" : "secondary pcm mixer");
632         m->type = type;
633         m->devinfo = devinfo;
634         m->busy = 0;
635         m->dev = dev;
636         for (i = 0; i < (sizeof(m->parent) / sizeof(m->parent[0])); i++) {
637                 m->parent[i] = SOUND_MIXER_NONE;
638                 m->child[i] = 0;
639                 m->realdev[i] = i;
640         }
641
642         if (MIXER_INIT(m)) {
643                 snd_mtxlock(m->lock);
644                 snd_mtxfree(m->lock);
645                 kobj_delete((kobj_t)m, M_MIXER);
646                 return (NULL);
647         }
648
649         return (m);
650 }
651
652 int
653 mixer_delete(struct snd_mixer *m)
654 {
655         KASSERT(m != NULL, ("NULL snd_mixer"));
656         KASSERT(m->type == MIXER_TYPE_SECONDARY,
657             ("%s(): illegal mixer type=%d", __func__, m->type));
658
659         /* mixer uninit can sleep --hps */
660
661         MIXER_UNINIT(m);
662
663         snd_mtxfree(m->lock);
664         kobj_delete((kobj_t)m, M_MIXER);
665
666         --mixer_count;
667
668         return (0);
669 }
670
671 struct snd_mixer *
672 mixer_create(device_t dev, kobj_class_t cls, void *devinfo, const char *desc)
673 {
674         struct snd_mixer *m;
675
676         m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_SECONDARY, desc);
677
678         if (m != NULL)
679                 ++mixer_count;
680
681         return (m);
682 }
683
684 int
685 mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
686 {
687         struct snddev_info *snddev;
688         struct snd_mixer *m;
689         u_int16_t v;
690         struct cdev *pdev;
691         int i, unit, devunit, val;
692
693         snddev = device_get_softc(dev);
694         if (snddev == NULL)
695                 return (-1);
696
697         if (resource_int_value(device_get_name(dev),
698             device_get_unit(dev), "eq", &val) == 0 && val != 0) {
699                 snddev->flags |= SD_F_EQ;
700                 if ((val & SD_F_EQ_MASK) == val)
701                         snddev->flags |= val;
702                 else
703                         snddev->flags |= SD_F_EQ_DEFAULT;
704                 snddev->eqpreamp = 0;
705         }
706
707         m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_PRIMARY, NULL);
708         if (m == NULL)
709                 return (-1);
710
711         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
712                 v = snd_mixerdefaults[i];
713
714                 if (resource_int_value(device_get_name(dev),
715                     device_get_unit(dev), snd_mixernames[i], &val) == 0) {
716                         if (val >= 0 && val <= 100) {
717                                 v = (u_int16_t) val;
718                         }
719                 }
720
721                 mixer_set(m, i, v | (v << 8));
722         }
723
724         mixer_setrecsrc(m, 0); /* Set default input. */
725
726         unit = device_get_unit(dev);
727         devunit = snd_mkunit(unit, SND_DEV_CTL, 0);
728         pdev = make_dev(&mixer_cdevsw, PCMMINOR(devunit),
729                  UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit);
730         pdev->si_drv1 = m;
731         snddev->mixer_dev = pdev;
732
733         ++mixer_count;
734
735         if (bootverbose) {
736                 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
737                         if (!(m->devs & (1 << i)))
738                                 continue;
739                         if (m->realdev[i] != i) {
740                                 device_printf(dev, "Mixer \"%s\" -> \"%s\":",
741                                     snd_mixernames[i],
742                                     (m->realdev[i] < SOUND_MIXER_NRDEVICES) ?
743                                     snd_mixernames[m->realdev[i]] : "none");
744                         } else {
745                                 device_printf(dev, "Mixer \"%s\":",
746                                     snd_mixernames[i]);
747                         }
748                         if (m->parent[i] < SOUND_MIXER_NRDEVICES)
749                                 printf(" parent=\"%s\"",
750                                     snd_mixernames[m->parent[i]]);
751                         if (m->child[i] != 0)
752                                 printf(" child=0x%08x", m->child[i]);
753                         printf("\n");
754                 }
755                 if (snddev->flags & SD_F_SOFTPCMVOL)
756                         device_printf(dev, "Soft PCM mixer ENABLED\n");
757                 if (snddev->flags & SD_F_EQ)
758                         device_printf(dev, "EQ Treble/Bass ENABLED\n");
759         }
760
761         return (0);
762 }
763
764 int
765 mixer_uninit(device_t dev)
766 {
767         int i;
768         struct snddev_info *d;
769         struct snd_mixer *m;
770         struct cdev *pdev;
771
772         d = device_get_softc(dev);
773         pdev = mixer_get_devt(dev);
774         if (d == NULL || pdev == NULL || pdev->si_drv1 == NULL)
775                 return EBADF;
776
777         m = pdev->si_drv1;
778         KASSERT(m != NULL, ("NULL snd_mixer"));
779         KASSERT(m->type == MIXER_TYPE_PRIMARY,
780             ("%s(): illegal mixer type=%d", __func__, m->type));
781
782         snd_mtxlock(m->lock);
783
784         if (m->busy) {
785                 snd_mtxunlock(m->lock);
786                 return EBUSY;
787         }
788
789         /* destroy dev can sleep --hps */
790
791         snd_mtxunlock(m->lock);
792
793         pdev->si_drv1 = NULL;
794         destroy_dev(pdev);
795
796         snd_mtxlock(m->lock);
797
798         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
799                 mixer_set(m, i, 0);
800
801         mixer_setrecsrc(m, SOUND_MASK_MIC);
802
803         snd_mtxunlock(m->lock);
804
805         /* mixer uninit can sleep --hps */
806
807         MIXER_UNINIT(m);
808
809         snd_mtxfree(m->lock);
810         kobj_delete((kobj_t)m, M_MIXER);
811
812         d->mixer_dev = NULL;
813
814         --mixer_count;
815
816         return 0;
817 }
818
819 int
820 mixer_reinit(device_t dev)
821 {
822         struct snd_mixer *m;
823         struct cdev *pdev;
824         int i;
825
826         pdev = mixer_get_devt(dev);
827         m = pdev->si_drv1;
828         snd_mtxlock(m->lock);
829
830         i = MIXER_REINIT(m);
831         if (i) {
832                 snd_mtxunlock(m->lock);
833                 return i;
834         }
835
836         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
837                 mixer_set(m, i, m->level[i]);
838
839         mixer_setrecsrc(m, m->recsrc);
840         snd_mtxunlock(m->lock);
841
842         return 0;
843 }
844
845 static int
846 sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS)
847 {
848         char devname[32];
849         int error, dev;
850         struct snd_mixer *m;
851
852         m = oidp->oid_arg1;
853         snd_mtxlock(m->lock);
854         strlcpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname));
855         snd_mtxunlock(m->lock);
856         error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req);
857         snd_mtxlock(m->lock);
858         if (error == 0 && req->newptr != NULL) {
859                 dev = mixer_lookup(devname);
860                 if (dev == -1) {
861                         snd_mtxunlock(m->lock);
862                         return EINVAL;
863                 }
864                 else if (dev != m->hwvol_mixer) {
865                         m->hwvol_mixer = dev;
866                         m->hwvol_muted = 0;
867                 }
868         }
869         snd_mtxunlock(m->lock);
870         return error;
871 }
872
873 int
874 mixer_hwvol_init(device_t dev)
875 {
876         struct snd_mixer *m;
877         struct cdev *pdev;
878
879         pdev = mixer_get_devt(dev);
880         m = pdev->si_drv1;
881
882         m->hwvol_mixer = SOUND_MIXER_VOLUME;
883         m->hwvol_step = 5;
884         SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
885             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
886             OID_AUTO, "hwvol_step", CTLFLAG_RW, &m->hwvol_step, 0, "");
887         SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
888             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
889             OID_AUTO, "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RW, m, 0,
890             sysctl_hw_snd_hwvol_mixer, "A", "");
891         return 0;
892 }
893
894 void
895 mixer_hwvol_mute_locked(struct snd_mixer *m)
896 {
897         if (m->hwvol_muted) {
898                 m->hwvol_muted = 0;
899                 mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level);
900         } else {
901                 m->hwvol_muted++;
902                 m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer);
903                 mixer_set(m, m->hwvol_mixer, 0);
904         }
905 }
906
907 void
908 mixer_hwvol_mute(device_t dev)
909 {
910         struct snd_mixer *m;
911         struct cdev *pdev;
912
913         pdev = mixer_get_devt(dev);
914         m = pdev->si_drv1;
915         snd_mtxlock(m->lock);
916         mixer_hwvol_mute_locked(m);
917         snd_mtxunlock(m->lock);
918 }
919
920 void
921 mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step)
922 {
923         int level, left, right;
924
925         if (m->hwvol_muted) {
926                 m->hwvol_muted = 0;
927                 level = m->hwvol_mute_level;
928         } else
929                 level = mixer_get(m, m->hwvol_mixer);
930         if (level != -1) {
931                 left = level & 0xff;
932                 right = (level >> 8) & 0xff;
933                 left += left_step * m->hwvol_step;
934                 if (left < 0)
935                         left = 0;
936                 else if (left > 100)
937                         left = 100;
938                 right += right_step * m->hwvol_step;
939                 if (right < 0)
940                         right = 0;
941                 else if (right > 100)
942                         right = 100;
943                 mixer_set(m, m->hwvol_mixer, left | right << 8);
944         }
945 }
946
947 void
948 mixer_hwvol_step(device_t dev, int left_step, int right_step)
949 {
950         struct snd_mixer *m;
951         struct cdev *pdev;
952
953         pdev = mixer_get_devt(dev);
954         m = pdev->si_drv1;
955         snd_mtxlock(m->lock);
956         mixer_hwvol_step_locked(m, left_step, right_step);
957         snd_mtxunlock(m->lock);
958 }
959
960 int
961 mixer_busy(struct snd_mixer *m)
962 {
963         KASSERT(m != NULL, ("NULL snd_mixer"));
964
965         return (m->busy);
966 }
967
968 int
969 mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right)
970 {
971         int ret;
972
973         KASSERT(m != NULL, ("NULL snd_mixer"));
974
975         snd_mtxlock(m->lock);
976         ret = mixer_set(m, dev, left | (right << 8));
977         snd_mtxunlock(m->lock);
978
979         return ((ret != 0) ? ENXIO : 0);
980 }
981
982 int
983 mix_get(struct snd_mixer *m, u_int dev)
984 {
985         int ret;
986
987         KASSERT(m != NULL, ("NULL snd_mixer"));
988
989         snd_mtxlock(m->lock);
990         ret = mixer_get(m, dev);
991         snd_mtxunlock(m->lock);
992
993         return (ret);
994 }
995
996 int
997 mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
998 {
999         int ret;
1000
1001         KASSERT(m != NULL, ("NULL snd_mixer"));
1002
1003         snd_mtxlock(m->lock);
1004         ret = mixer_setrecsrc(m, src);
1005         snd_mtxunlock(m->lock);
1006
1007         return ((ret != 0) ? ENXIO : 0);
1008 }
1009
1010 u_int32_t
1011 mix_getrecsrc(struct snd_mixer *m)
1012 {
1013         u_int32_t ret;
1014
1015         KASSERT(m != NULL, ("NULL snd_mixer"));
1016
1017         snd_mtxlock(m->lock);
1018         ret = mixer_getrecsrc(m);
1019         snd_mtxunlock(m->lock);
1020
1021         return (ret);
1022 }
1023
1024 int
1025 mix_get_type(struct snd_mixer *m)
1026 {
1027         KASSERT(m != NULL, ("NULL snd_mixer"));
1028
1029         return (m->type);
1030 }
1031
1032 /* ----------------------------------------------------------------------- */
1033
1034 static int
1035 mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
1036 {
1037         struct snddev_info *d;
1038         struct snd_mixer *m;
1039
1040
1041         if (i_dev == NULL || i_dev->si_drv1 == NULL)
1042                 return (EBADF);
1043
1044         m = i_dev->si_drv1;
1045         d = device_get_softc(m->dev);
1046         if (!PCM_REGISTERED(d))
1047                 return (EBADF);
1048
1049         /* XXX Need Giant magic entry ??? */
1050
1051         snd_mtxlock(m->lock);
1052         m->busy = 1;
1053         snd_mtxunlock(m->lock);
1054
1055         return (0);
1056 }
1057
1058 static int
1059 mixer_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
1060 {
1061         struct snddev_info *d;
1062         struct snd_mixer *m;
1063         int ret;
1064
1065         if (i_dev == NULL || i_dev->si_drv1 == NULL)
1066                 return (EBADF);
1067
1068         m = i_dev->si_drv1;
1069         d = device_get_softc(m->dev);
1070         if (!PCM_REGISTERED(d))
1071                 return (EBADF);
1072
1073         /* XXX Need Giant magic entry ??? */
1074
1075         snd_mtxlock(m->lock);
1076         ret = (m->busy == 0) ? EBADF : 0;
1077         m->busy = 0;
1078         snd_mtxunlock(m->lock);
1079
1080         return (ret);
1081 }
1082
1083 static int
1084 mixer_ioctl_channel(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
1085     struct thread *td, int from)
1086 {
1087         struct snddev_info *d;
1088         struct snd_mixer *m;
1089         struct pcm_channel *c, *rdch, *wrch;
1090         pid_t pid;
1091         int j, ret;
1092
1093         if (td == NULL || td->td_proc == NULL)
1094                 return (-1);
1095
1096         m = dev->si_drv1;
1097         d = device_get_softc(m->dev);
1098         j = cmd & 0xff;
1099
1100         switch (j) {
1101         case SOUND_MIXER_PCM:
1102         case SOUND_MIXER_RECLEV:
1103         case SOUND_MIXER_DEVMASK:
1104         case SOUND_MIXER_CAPS:
1105         case SOUND_MIXER_STEREODEVS:
1106                 break;
1107         default:
1108                 return (-1);
1109                 break;
1110         }
1111
1112         pid = td->td_proc->p_pid;
1113         rdch = NULL;
1114         wrch = NULL;
1115         c = NULL;
1116         ret = -1;
1117
1118         /*
1119          * This is unfair. Imagine single proc opening multiple
1120          * instances of same direction. What we do right now
1121          * is looking for the first matching proc/pid, and just
1122          * that. Nothing more. Consider it done.
1123          *
1124          * The better approach of controlling specific channel
1125          * pcm or rec volume is by doing mixer ioctl
1126          * (SNDCTL_DSP_[SET|GET][PLAY|REC]VOL / SOUND_MIXER_[PCM|RECLEV]
1127          * on its open fd, rather than cracky mixer bypassing here.
1128          */
1129         CHN_FOREACH(c, d, channels.pcm.opened) {
1130                 CHN_LOCK(c);
1131                 if (c->pid != pid ||
1132                     !(c->feederflags & (1 << FEEDER_VOLUME))) {
1133                         CHN_UNLOCK(c);
1134                         continue;
1135                 }
1136                 if (rdch == NULL && c->direction == PCMDIR_REC) {
1137                         rdch = c;
1138                         if (j == SOUND_MIXER_RECLEV)
1139                                 goto mixer_ioctl_channel_proc;
1140                 } else if (wrch == NULL && c->direction == PCMDIR_PLAY) {
1141                         wrch = c;
1142                         if (j == SOUND_MIXER_PCM)
1143                                 goto mixer_ioctl_channel_proc;
1144                 }
1145                 CHN_UNLOCK(c);
1146                 if (rdch != NULL && wrch != NULL)
1147                         break;
1148         }
1149
1150         if (rdch == NULL && wrch == NULL)
1151                 return (-1);
1152
1153         if ((j == SOUND_MIXER_DEVMASK || j == SOUND_MIXER_CAPS ||
1154             j == SOUND_MIXER_STEREODEVS) &&
1155             (cmd & ~0xff) == MIXER_READ(0)) {
1156                 snd_mtxlock(m->lock);
1157                 *(int *)arg = mix_getdevs(m);
1158                 snd_mtxunlock(m->lock);
1159                 if (rdch != NULL)
1160                         *(int *)arg |= SOUND_MASK_RECLEV;
1161                 if (wrch != NULL)
1162                         *(int *)arg |= SOUND_MASK_PCM;
1163                 ret = 0;
1164         }
1165
1166         return (ret);
1167
1168 mixer_ioctl_channel_proc:
1169
1170         KASSERT(c != NULL, ("%s(): NULL channel", __func__));
1171         CHN_LOCKASSERT(c);
1172
1173         if ((cmd & ~0xff) == MIXER_WRITE(0)) {
1174                 int left, right, center;
1175
1176                 left = *(int *)arg & 0x7f;
1177                 right = (*(int *)arg >> 8) & 0x7f;
1178                 center = (left + right) >> 1;
1179                 chn_setvolume_multi(c, SND_VOL_C_PCM, left, right, center);
1180         } else if ((cmd & ~0xff) == MIXER_READ(0)) {
1181                 *(int *)arg = CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FL);
1182                 *(int *)arg |=
1183                     CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FR) << 8;
1184         }
1185
1186         CHN_UNLOCK(c);
1187
1188         return (0);
1189 }
1190
1191 static int
1192 mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
1193     struct thread *td)
1194 {
1195         struct snddev_info *d;
1196         int ret;
1197
1198         if (i_dev == NULL || i_dev->si_drv1 == NULL)
1199                 return (EBADF);
1200
1201         d = device_get_softc(((struct snd_mixer *)i_dev->si_drv1)->dev);
1202         if (!PCM_REGISTERED(d))
1203                 return (EBADF);
1204
1205         PCM_GIANT_ENTER(d);
1206         PCM_ACQUIRE_QUICK(d);
1207
1208         ret = -1;
1209
1210         if (mixer_bypass != 0 && (d->flags & SD_F_VPC))
1211                 ret = mixer_ioctl_channel(i_dev, cmd, arg, mode, td,
1212                     MIXER_CMD_CDEV);
1213
1214         if (ret == -1)
1215                 ret = mixer_ioctl_cmd(i_dev, cmd, arg, mode, td,
1216                     MIXER_CMD_CDEV);
1217
1218         PCM_RELEASE_QUICK(d);
1219         PCM_GIANT_LEAVE(d);
1220
1221         return (ret);
1222 }
1223
1224 static void
1225 mixer_mixerinfo(struct snd_mixer *m, mixer_info *mi)
1226 {
1227         bzero((void *)mi, sizeof(*mi));
1228         strlcpy(mi->id, m->name, sizeof(mi->id));
1229         strlcpy(mi->name, device_get_desc(m->dev), sizeof(mi->name));
1230         mi->modify_counter = m->modify_counter;
1231 }
1232
1233 /*
1234  * XXX Make sure you can guarantee concurrency safety before calling this
1235  *     function, be it through Giant, PCM_*, etc !
1236  */
1237 int
1238 mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
1239     struct thread *td, int from)
1240 {
1241         struct snd_mixer *m;
1242         int ret = EINVAL, *arg_i = (int *)arg;
1243         int v = -1, j = cmd & 0xff;
1244
1245         /*
1246          * Certain ioctls may be made on any type of device (audio, mixer,
1247          * and MIDI).  Handle those special cases here.
1248          */
1249         if (IOCGROUP(cmd) == 'X') {
1250                 switch (cmd) {
1251                 case SNDCTL_SYSINFO:
1252                         sound_oss_sysinfo((oss_sysinfo *)arg);
1253                         return (0);
1254                 case SNDCTL_CARDINFO:
1255                         return (sound_oss_card_info((oss_card_info *)arg));
1256                 case SNDCTL_AUDIOINFO:
1257                 case SNDCTL_AUDIOINFO_EX:
1258                 case SNDCTL_ENGINEINFO:
1259                         return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg));
1260                 case SNDCTL_MIXERINFO:
1261                         return (mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg));
1262                 }
1263                 return (EINVAL);
1264         }
1265
1266         m = i_dev->si_drv1;
1267
1268         if (m == NULL)
1269                 return (EBADF);
1270
1271         snd_mtxlock(m->lock);
1272         if (from == MIXER_CMD_CDEV && !m->busy) {
1273                 snd_mtxunlock(m->lock);
1274                 return (EBADF);
1275         }
1276         switch (cmd) {
1277         case SNDCTL_DSP_GET_RECSRC_NAMES:
1278                 bcopy((void *)&m->enuminfo, arg, sizeof(oss_mixer_enuminfo));
1279                 ret = 0;
1280                 goto done;
1281         case SNDCTL_DSP_GET_RECSRC:
1282                 ret = mixer_get_recroute(m, arg_i);
1283                 goto done;
1284         case SNDCTL_DSP_SET_RECSRC:
1285                 ret = mixer_set_recroute(m, *arg_i);
1286                 goto done;
1287         case OSS_GETVERSION:
1288                 *arg_i = SOUND_VERSION;
1289                 ret = 0;
1290                 goto done;
1291         case SOUND_MIXER_INFO:
1292                 mixer_mixerinfo(m, (mixer_info *)arg);
1293                 ret = 0;
1294                 goto done;
1295         }
1296         if ((cmd & ~0xff) == MIXER_WRITE(0)) {
1297                 if (j == SOUND_MIXER_RECSRC)
1298                         ret = mixer_setrecsrc(m, *arg_i);
1299                 else
1300                         ret = mixer_set(m, j, *arg_i);
1301                 snd_mtxunlock(m->lock);
1302                 return ((ret == 0) ? 0 : ENXIO);
1303         }
1304         if ((cmd & ~0xff) == MIXER_READ(0)) {
1305                 switch (j) {
1306                 case SOUND_MIXER_DEVMASK:
1307                 case SOUND_MIXER_CAPS:
1308                 case SOUND_MIXER_STEREODEVS:
1309                         v = mix_getdevs(m);
1310                         break;
1311                 case SOUND_MIXER_RECMASK:
1312                         v = mix_getrecdevs(m);
1313                         break;
1314                 case SOUND_MIXER_RECSRC:
1315                         v = mixer_getrecsrc(m);
1316                         break;
1317                 default:
1318                         v = mixer_get(m, j);
1319                 }
1320                 *arg_i = v;
1321                 snd_mtxunlock(m->lock);
1322                 return ((v != -1) ? 0 : ENXIO);
1323         }
1324 done:
1325         snd_mtxunlock(m->lock);
1326         return (ret);
1327 }
1328
1329 static void
1330 mixer_clone(void *arg,
1331     struct ucred *cred,
1332     char *name, int namelen, struct cdev **dev)
1333 {
1334         struct snddev_info *d;
1335
1336         if (*dev != NULL)
1337                 return;
1338         if (strcmp(name, "mixer") == 0) {
1339                 d = devclass_get_softc(pcm_devclass, snd_unit);
1340                 if (PCM_REGISTERED(d) && d->mixer_dev != NULL) {
1341                         *dev = d->mixer_dev;
1342                         dev_ref(*dev);
1343                 }
1344         }
1345 }
1346
1347 static void
1348 mixer_sysinit(void *p)
1349 {
1350         if (mixer_ehtag != NULL)
1351                 return;
1352         mixer_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_clone, 0, 1000);
1353 }
1354
1355 static void
1356 mixer_sysuninit(void *p)
1357 {
1358         if (mixer_ehtag == NULL)
1359                 return;
1360         EVENTHANDLER_DEREGISTER(dev_clone, mixer_ehtag);
1361         mixer_ehtag = NULL;
1362 }
1363
1364 SYSINIT(mixer_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysinit, NULL);
1365 SYSUNINIT(mixer_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysuninit, NULL);
1366
1367 /**
1368  * @brief Handler for SNDCTL_MIXERINFO
1369  *
1370  * This function searches for a mixer based on the numeric ID stored
1371  * in oss_miserinfo::dev.  If set to -1, then information about the
1372  * current mixer handling the request is provided.  Note, however, that
1373  * this ioctl may be made with any sound device (audio, mixer, midi).
1374  *
1375  * @note Caller must not hold any PCM device, channel, or mixer locks.
1376  *
1377  * See http://manuals.opensound.com/developer/SNDCTL_MIXERINFO.html for
1378  * more information.
1379  *
1380  * @param i_dev character device on which the ioctl arrived
1381  * @param arg   user argument (oss_mixerinfo *)
1382  *
1383  * @retval EINVAL       oss_mixerinfo::dev specified a bad value
1384  * @retval 0            success
1385  */
1386 int
1387 mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi)
1388 {
1389         struct snddev_info *d;
1390         struct snd_mixer *m;
1391         int nmix, i;
1392
1393         /*
1394          * If probing the device handling the ioctl, make sure it's a mixer
1395          * device.  (This ioctl is valid on audio, mixer, and midi devices.)
1396          */
1397         if (mi->dev == -1 && i_dev->si_devsw != &mixer_cdevsw)
1398                 return (EINVAL);
1399
1400         d = NULL;
1401         m = NULL;
1402         nmix = 0;
1403
1404         /*
1405          * There's a 1:1 relationship between mixers and PCM devices, so
1406          * begin by iterating over PCM devices and search for our mixer.
1407          */
1408         for (i = 0; pcm_devclass != NULL &&
1409             i < devclass_get_maxunit(pcm_devclass); i++) {
1410                 d = devclass_get_softc(pcm_devclass, i);
1411                 if (!PCM_REGISTERED(d))
1412                         continue;
1413
1414                 /* XXX Need Giant magic entry */
1415
1416                 /* See the note in function docblock. */
1417                 PCM_UNLOCKASSERT(d);
1418                 PCM_LOCK(d);
1419
1420                 if (d->mixer_dev != NULL && d->mixer_dev->si_drv1 != NULL &&
1421                     ((mi->dev == -1 && d->mixer_dev == i_dev) ||
1422                     mi->dev == nmix)) {
1423                         m = d->mixer_dev->si_drv1;
1424                         mtx_lock(m->lock);
1425
1426                         /*
1427                          * At this point, the following synchronization stuff
1428                          * has happened:
1429                          * - a specific PCM device is locked.
1430                          * - a specific mixer device has been locked, so be
1431                          *   sure to unlock when existing.
1432                          */
1433                         bzero((void *)mi, sizeof(*mi));
1434                         mi->dev = nmix;
1435                         snprintf(mi->id, sizeof(mi->id), "mixer%d", i);
1436                         strlcpy(mi->name, m->name, sizeof(mi->name));
1437                         mi->modify_counter = m->modify_counter;
1438                         mi->card_number = i;
1439                         /*
1440                          * Currently, FreeBSD assumes 1:1 relationship between
1441                          * a pcm and mixer devices, so this is hardcoded to 0.
1442                          */
1443                         mi->port_number = 0;
1444
1445                         /**
1446                          * @todo Fill in @sa oss_mixerinfo::mixerhandle.
1447                          * @note From 4Front:  "mixerhandle is an arbitrary
1448                          *       string that identifies the mixer better than
1449                          *       the device number (mixerinfo.dev).  Device
1450                          *       numbers may change depending on the order the
1451                          *       drivers are loaded. However the handle should
1452                          *       remain the same provided that the sound card
1453                          *       is not moved to another PCI slot."
1454                          */
1455
1456                         /**
1457                          * @note
1458                          * @sa oss_mixerinfo::magic is a reserved field.
1459                          * 
1460                          * @par
1461                          * From 4Front:  "magic is usually 0. However some
1462                          * devices may have dedicated setup utilities and the
1463                          * magic field may contain an unique driver specific
1464                          * value (managed by [4Front])."
1465                          */
1466
1467                         mi->enabled = device_is_attached(m->dev) ? 1 : 0;
1468                         /**
1469                          * The only flag for @sa oss_mixerinfo::caps is
1470                          * currently MIXER_CAP_VIRTUAL, which I'm not sure we
1471                          * really worry about.
1472                          */
1473                         /**
1474                          * Mixer extensions currently aren't supported, so
1475                          * leave @sa oss_mixerinfo::nrext blank for now.
1476                          */
1477                         /**
1478                          * @todo Fill in @sa oss_mixerinfo::priority (requires
1479                          *       touching drivers?)
1480                          * @note The priority field is for mixer applets to
1481                          * determine which mixer should be the default, with 0
1482                          * being least preferred and 10 being most preferred.
1483                          * From 4Front:  "OSS drivers like ICH use higher
1484                          * values (10) because such chips are known to be used
1485                          * only on motherboards.  Drivers for high end pro
1486                          * devices use 0 because they will never be the
1487                          * default mixer. Other devices use values 1 to 9
1488                          * depending on the estimated probability of being the
1489                          * default device.
1490                          *
1491                          * XXX Described by Hannu@4Front, but not found in
1492                          *     soundcard.h.
1493                         strlcpy(mi->devnode, devtoname(d->mixer_dev),
1494                         sizeof(mi->devnode));
1495                         mi->legacy_device = i;
1496                          */
1497                         mtx_unlock(m->lock);
1498                 } else
1499                         ++nmix;
1500
1501                 PCM_UNLOCK(d);
1502
1503                 if (m != NULL)
1504                         return (0);
1505         }
1506
1507         return (EINVAL);
1508 }
1509
1510 /*
1511  * Allow the sound driver to use the mixer lock to protect its mixer
1512  * data:
1513  */
1514 struct mtx *
1515 mixer_get_lock(struct snd_mixer *m)
1516 {
1517         if (m->lock == NULL) {
1518                 return (&Giant);
1519         }
1520         return (m->lock);
1521 }
1522
1523 int
1524 mix_get_locked(struct snd_mixer *m, u_int dev, int *pleft, int *pright)
1525 {
1526         int level;
1527
1528         level = mixer_get(m, dev);
1529         if (level < 0) {
1530                 *pright = *pleft = -1;
1531                 return (-1);
1532         }
1533
1534         *pleft = level & 0xFF;
1535         *pright = (level >> 8) & 0xFF;
1536
1537         return (0);
1538 }
1539
1540 int
1541 mix_set_locked(struct snd_mixer *m, u_int dev, int left, int right)
1542 {
1543         int level;
1544
1545         level = (left & 0xFF) | ((right & 0xFF) << 8);
1546
1547         return (mixer_set(m, dev, level));
1548 }