Submit #2682 » uaudio.patch
| sys/bus/u4b/audio/Makefile | ||
|---|---|---|
|
KMOD= uaudio
|
||
|
SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \
|
||
|
mixer_if.h feeder_if.h channel_if.h uaudio.c
|
||
|
mixer_if.h feeder_if.h channel_if.h uaudio.c uaudio_pcm.c
|
||
|
.include <bsd.kmod.mk>
|
||
| sys/bus/u4b/audio/uaudio.c | ||
|---|---|---|
|
};
|
||
|
struct uaudio_softc {
|
||
|
struct lock sc_lock;
|
||
|
struct sbuf sc_sndstat;
|
||
|
struct sndcard_func sc_sndcard_func;
|
||
|
struct uaudio_chan sc_rec_chan;
|
||
| ... | ... | |
|
struct usb_xfer *sc_mixer_xfer[1];
|
||
|
struct uaudio_mixer_node *sc_mixer_root;
|
||
|
struct uaudio_mixer_node *sc_mixer_curr;
|
||
|
sndlock_t sc_mixer_lock;
|
||
|
uint32_t sc_mix_info;
|
||
|
uint32_t sc_recsrc_info;
|
||
| ... | ... | |
|
struct usb_interface_descriptor *id;
|
||
|
device_t child;
|
||
|
lockinit(&sc->sc_lock, "uaudio", 0, 0);
|
||
|
sc->sc_play_chan.priv_sc = sc;
|
||
|
sc->sc_rec_chan.priv_sc = sc;
|
||
|
sc->sc_udev = uaa->device;
|
||
| ... | ... | |
|
sc->sc_sndstat_valid = 0;
|
||
|
umidi_detach(dev);
|
||
|
lockuninit(&sc->sc_lock);
|
||
|
return (0);
|
||
|
}
|
||
| ... | ... | |
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
/*
|
||
|
* KLUDGE:
|
||
|
* Add support at least for 2 channels
|
||
|
*/
|
||
|
if (ch->p_asf1d->bNrChannels == 2) format |= AFMT_STEREO;
|
||
|
ch->pcm_cap.fmtlist[0] = format;
|
||
|
ch->pcm_cap.fmtlist[1] = 0;
|
||
| ... | ... | |
|
uaudio_mixer_init_sub(struct uaudio_softc *sc, struct snd_mixer *m)
|
||
|
{
|
||
|
DPRINTF("\n");
|
||
|
sc->sc_mixer_lock = mixer_get_lock(m);
|
||
|
if (usbd_transfer_setup(sc->sc_udev, &sc->sc_mixer_iface_index,
|
||
|
sc->sc_mixer_xfer, uaudio_mixer_config, 1, sc,
|
||
|
&sc->sc_lock)) {
|
||
|
sc->sc_mixer_lock)) {
|
||
|
DPRINTFN(0, "could not allocate USB "
|
||
|
"transfer for audio mixer!\n");
|
||
|
return (ENOMEM);
|
||
| ... | ... | |
|
DPRINTF("\n");
|
||
|
usbd_transfer_unsetup(sc->sc_mixer_xfer, 1);
|
||
|
sc->sc_mixer_lock = NULL;
|
||
|
return (0);
|
||
|
}
|
||
| ... | ... | |
|
unsigned left, unsigned right)
|
||
|
{
|
||
|
struct uaudio_mixer_node *mc;
|
||
|
int chan;
|
||
|
for (mc = sc->sc_mixer_root; mc;
|
||
|
mc = mc->next) {
|
||
|
if (mc->ctl == type) {
|
||
|
if (mc->nchan == 2) {
|
||
|
/* set Right */
|
||
|
uaudio_mixer_ctl_set(sc, mc, 1, (int)(right * 255) / 100);
|
||
|
for (chan = 0; chan < mc->nchan; chan++) {
|
||
|
uaudio_mixer_ctl_set(sc, mc, chan,
|
||
|
(int)((chan == 0 ? left : right) * 255) / 100);
|
||
|
}
|
||
|
/* set Left or Mono */
|
||
|
uaudio_mixer_ctl_set(sc, mc, 0, (int)(left * 255) / 100);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
| sys/bus/u4b/audio/uaudio_pcm.c | ||
|---|---|---|
|
return (uaudio_chan_set_param_blocksize(data, blocksize));
|
||
|
}
|
||
|
#if 0
|
||
|
static int
|
||
|
ua_chan_setfragments(kobj_t obj, void *data, uint32_t blocksize, uint32_t blockcount)
|
||
|
{
|
||
|
return (uaudio_chan_set_param_fragments(data, blocksize, blockcount));
|
||
|
}
|
||
|
#endif
|
||
|
static int
|
||
|
ua_chan_trigger(kobj_t obj, void *data, int go)
|
||
| ... | ... | |
|
return (uaudio_chan_getcaps(data));
|
||
|
}
|
||
|
#if 0
|
||
|
static struct pcmchan_matrix *
|
||
|
ua_chan_getmatrix(kobj_t obj, void *data, uint32_t format)
|
||
|
{
|
||
|
return (uaudio_chan_getmatrix(data, format));
|
||
|
}
|
||
|
#endif
|
||
|
static kobj_method_t ua_chan_methods[] = {
|
||
|
KOBJMETHOD(channel_init, ua_chan_init),
|
||
| ... | ... | |
|
static int
|
||
|
ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right)
|
||
|
{
|
||
|
struct lock *lock = mixer_get_lock(m);
|
||
|
uint8_t do_unlock;
|
||
|
if (lockstatus(lock, curthread)) {
|
||
|
do_unlock = 0;
|
||
|
} else {
|
||
|
do_unlock = 1;
|
||
|
lockmgr(lock, LK_EXCLUSIVE);
|
||
|
}
|
||
|
sndlock_t lock = mixer_get_lock(m);
|
||
|
snd_mtxlock(lock);
|
||
|
uaudio_mixer_set(mix_getdevinfo(m), type, left, right);
|
||
|
if (do_unlock) {
|
||
|
lockmgr(lock, LK_RELEASE);
|
||
|
}
|
||
|
snd_mtxunlock(lock);
|
||
|
return (left | (right << 8));
|
||
|
}
|
||
|
static uint32_t
|
||
|
ua_mixer_setrecsrc(struct snd_mixer *m, uint32_t src)
|
||
|
{
|
||
|
struct lock *lock = mixer_get_lock(m);
|
||
|
int retval;
|
||
|
uint8_t do_unlock;
|
||
|
if (lockstatus(lock, curthread)) {
|
||
|
do_unlock = 0;
|
||
|
} else {
|
||
|
do_unlock = 1;
|
||
|
lockmgr(lock, LK_EXCLUSIVE);
|
||
|
}
|
||
|
sndlock_t lock = mixer_get_lock(m);
|
||
|
snd_mtxlock(lock);
|
||
|
retval = uaudio_mixer_setrecsrc(mix_getdevinfo(m), src);
|
||
|
if (do_unlock) {
|
||
|
lockmgr(lock, LK_RELEASE);
|
||
|
}
|
||
|
snd_mtxunlock(lock);
|
||
|
return (retval);
|
||
|
}
|
||
| sys/dev/sound/pcm/channel.c | ||
|---|---|---|
|
return r;
|
||
|
}
|
||
|
/*
|
||
|
* given a bufsz value, round it to a power of 2 in the min-max range
|
||
|
* XXX only works if min and max are powers of 2
|
||
|
*/
|
||
|
static int
|
||
|
round_bufsz(int bufsz, int min, int max)
|
||
|
static unsigned int
|
||
|
round_bufsz (unsigned int bufsz, unsigned int min, unsigned int max)
|
||
|
{
|
||
|
int tmp = min * 2;
|
||
|
KASSERT((min & (min-1)) == 0, ("min %d must be power of 2", min));
|
||
|
KASSERT((max & (max-1)) == 0, ("max %d must be power of 2", max));
|
||
|
while (tmp <= bufsz)
|
||
|
tmp <<= 1;
|
||
|
tmp >>= 1;
|
||
|
if (tmp > max)
|
||
|
tmp = max;
|
||
|
return tmp;
|
||
|
int pow=1, res;
|
||
|
if (bufsz < min) bufsz = min;
|
||
|
else if (bufsz > max) bufsz = max;
|
||
|
if (bufsz & (bufsz-1)) {
|
||
|
while (bufsz >> pow) pow++;
|
||
|
res = 1<<pow;
|
||
|
}
|
||
|
else res = bufsz;
|
||
|
if (res > max) return res>>1;
|
||
|
else return res;
|
||
|
}
|
||
|
/*
|
||
| sys/dev/sound/pcm/mixer.c | ||
|---|---|---|
|
return m->devinfo;
|
||
|
}
|
||
|
sndlock_t
|
||
|
mixer_get_lock (struct snd_mixer *m)
|
||
|
{
|
||
|
if (m->lock == NULL) {
|
||
|
panic ("mixer_get_lock: mixer %p has not lock", m);
|
||
|
}
|
||
|
return m->lock;
|
||
|
}
|
||
|
int
|
||
|
mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
|
||
|
{
|
||
| ... | ... | |
|
mixer_set(m, i, 0);
|
||
|
mixer_setrecsrc(m, SOUND_MASK_MIC);
|
||
|
snd_mtxunlock (m->lock);
|
||
|
MIXER_UNINIT(m);
|
||
|
snd_mtxunlock(m->lock);
|
||
|
snd_mtxfree(m->lock);
|
||
|
kobj_delete((kobj_t)m, M_MIXER);
|
||
| sys/dev/sound/pcm/mixer.h | ||
|---|---|---|
|
u_int32_t mix_getparent(struct snd_mixer *m, u_int32_t dev);
|
||
|
u_int32_t mix_getchild(struct snd_mixer *m, u_int32_t dev);
|
||
|
void *mix_getdevinfo(struct snd_mixer *m);
|
||
|
sndlock_t mixer_get_lock(struct snd_mixer *m);
|
||
|
/*
|
||
|
* this is a kludge to allow hiding of the struct snd_mixer definition
|
||