diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/sound/usb/uaudio.c | 202 |
1 files changed, 188 insertions, 14 deletions
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c index 6bef4a7..ccc5d83 100644 --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -167,6 +167,7 @@ struct uaudio_mixer_node { #define MAX_SELECTOR_INPUT_PIN 256 uint8_t slctrtype[MAX_SELECTOR_INPUT_PIN]; uint8_t class; + uint8_t val_default; uint8_t desc[64]; @@ -282,7 +283,6 @@ struct uaudio_softc { struct uaudio_chan sc_play_chan; struct umidi_chan sc_midi_chan; struct uaudio_search_result sc_mixer_clocks; - struct sysctl_ctx_list sc_sysctl_ctx; struct mtx *sc_mixer_lock; struct usb_device *sc_udev; @@ -412,6 +412,7 @@ static int uaudio_mixer_sysctl_handler(SYSCTL_HANDLER_ARGS); static void uaudio_mixer_ctl_free(struct uaudio_softc *); static void uaudio_mixer_register_sysctl(struct uaudio_softc *, device_t); static void uaudio_mixer_reload_all(struct uaudio_softc *); +static void uaudio_mixer_controls_create_ftu(struct uaudio_softc *); /* ==== USB audio v1.0 ==== */ @@ -714,8 +715,6 @@ uaudio_attach(device_t dev) if (usb_test_quirk(uaa, UQ_AU_VENDOR_CLASS)) sc->sc_uq_au_vendor_class = 1; - sysctl_ctx_init(&sc->sc_sysctl_ctx); - umidi_init(dev); device_set_usb_desc(dev); @@ -732,6 +731,15 @@ uaudio_attach(device_t dev) sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff); + if (sc->sc_mixer_count == 0) { + if (uaa->info.idVendor == USB_VENDOR_MAUDIO && + (uaa->info.idProduct == USB_PRODUCT_MAUDIO_FASTTRACKULTRA || + uaa->info.idProduct == USB_PRODUCT_MAUDIO_FASTTRACKULTRA8R)) { + DPRINTF("Generating mixer descriptors\n"); + uaudio_mixer_controls_create_ftu(sc); + } + } + DPRINTF("%d mixer controls\n", sc->sc_mixer_count); @@ -896,10 +904,6 @@ uaudio_detach(device_t dev) { struct uaudio_softc *sc = device_get_softc(dev); - /* free all sysctls */ - - sysctl_ctx_free(&sc->sc_sysctl_ctx); - /* * Stop USB transfers early so that any audio applications * will time out and close opened /dev/dspX.Y device(s), if @@ -2147,7 +2151,7 @@ uaudio_mixer_register_sysctl(struct uaudio_softc *sc, device_t dev) int chan; int n; - mixer_tree = SYSCTL_ADD_NODE(&sc->sc_sysctl_ctx, + mixer_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "mixer", CTLFLAG_RD, NULL, ""); @@ -2167,30 +2171,30 @@ uaudio_mixer_register_sysctl(struct uaudio_softc *sc, device_t dev) pmc->name, n); } - control_tree = SYSCTL_ADD_NODE(&sc->sc_sysctl_ctx, + control_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(mixer_tree), OID_AUTO, buf, - CTLFLAG_RD, NULL, ""); + CTLFLAG_RD, NULL, "Mixer control nodes"); if (control_tree == NULL) continue; - SYSCTL_ADD_PROC(&sc->sc_sysctl_ctx, + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(control_tree), OID_AUTO, "val", CTLTYPE_INT | CTLFLAG_RW, sc, pmc->wValue[chan], uaudio_mixer_sysctl_handler, "I", "Current value"); - SYSCTL_ADD_INT(&sc->sc_sysctl_ctx, + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(control_tree), OID_AUTO, "min", CTLFLAG_RD, 0, pmc->minval, "Minimum value"); - SYSCTL_ADD_INT(&sc->sc_sysctl_ctx, + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(control_tree), OID_AUTO, "max", CTLFLAG_RD, 0, pmc->maxval, "Maximum value"); - SYSCTL_ADD_STRING(&sc->sc_sysctl_ctx, + SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(control_tree), OID_AUTO, "desc", CTLFLAG_RD, pmc->desc, 0, "Description"); @@ -2198,6 +2202,157 @@ uaudio_mixer_register_sysctl(struct uaudio_softc *sc, device_t dev) } } +/* M-Audio FastTrack Ultra Mixer Description */ +/* Origin: Linux USB Audio driver */ +static void +uaudio_mixer_controls_create_ftu(struct uaudio_softc *sc) +{ + struct uaudio_mixer_node mix; + int chx; + int chy; + + memset(&mix, 0, sizeof(mix)); + mix.wIndex = MAKE_WORD(6, sc->sc_mixer_iface_no); + mix.wValue[0] = MAKE_WORD(8, 0); + mix.class = UAC_OUTPUT; + mix.type = MIX_UNSIGNED_16; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "effect"; + mix.minval = 0; + mix.maxval = 7; + mix.mul = 7; + mix.nchan = 1; + mix.update[0] = 1; + strlcpy(mix.desc, "Room1,2,3,Hall1,2,Plate,Delay,Echo", sizeof(mix.desc)); + uaudio_mixer_add_ctl_sub(sc, &mix); + + memset(&mix, 0, sizeof(mix)); + mix.wIndex = MAKE_WORD(5, sc->sc_mixer_iface_no); + + for (chx = 0; chx != 8; chx++) { + for (chy = 0; chy != 8; chy++) { + + mix.wValue[0] = MAKE_WORD(chx + 1, chy + 1); + mix.type = MIX_SIGNED_16; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "mix_rec"; + mix.nchan = 1; + mix.update[0] = 1; + mix.val_default = 0; + snprintf(mix.desc, sizeof(mix.desc), + "AIn%d - Out%d Record Volume", chy + 1, chx + 1); + + uaudio_mixer_add_ctl(sc, &mix); + + mix.wValue[0] = MAKE_WORD(chx + 1, chy + 1 + 8); + mix.type = MIX_SIGNED_16; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "mix_play"; + mix.nchan = 1; + mix.update[0] = 1; + mix.val_default = (chx == chy) ? 1 : 0; + snprintf(mix.desc, sizeof(mix.desc), + "DIn%d - Out%d Playback Volume", chy + 1, chx + 1); + + uaudio_mixer_add_ctl(sc, &mix); + } + } + + memset(&mix, 0, sizeof(mix)); + mix.wIndex = MAKE_WORD(6, sc->sc_mixer_iface_no); + mix.wValue[0] = MAKE_WORD(2, 0); + mix.class = UAC_OUTPUT; + mix.type = MIX_SIGNED_8; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "effect_vol"; + mix.nchan = 1; + mix.update[0] = 1; + mix.minval = 0; + mix.maxval = 0x7f; + mix.mul = 0x7f; + mix.nchan = 1; + mix.update[0] = 1; + strlcpy(mix.desc, "Effect Volume", sizeof(mix.desc)); + uaudio_mixer_add_ctl_sub(sc, &mix); + + memset(&mix, 0, sizeof(mix)); + mix.wIndex = MAKE_WORD(6, sc->sc_mixer_iface_no); + mix.wValue[0] = MAKE_WORD(3, 0); + mix.class = UAC_OUTPUT; + mix.type = MIX_SIGNED_16; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "effect_dur"; + mix.nchan = 1; + mix.update[0] = 1; + mix.minval = 0; + mix.maxval = 0x7f00; + mix.mul = 0x7f00; + mix.nchan = 1; + mix.update[0] = 1; + strlcpy(mix.desc, "Effect Duration", sizeof(mix.desc)); + uaudio_mixer_add_ctl_sub(sc, &mix); + + memset(&mix, 0, sizeof(mix)); + mix.wIndex = MAKE_WORD(6, sc->sc_mixer_iface_no); + mix.wValue[0] = MAKE_WORD(4, 0); + mix.class = UAC_OUTPUT; + mix.type = MIX_SIGNED_8; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "effect_fb"; + mix.nchan = 1; + mix.update[0] = 1; + mix.minval = 0; + mix.maxval = 0x7f; + mix.mul = 0x7f; + mix.nchan = 1; + mix.update[0] = 1; + strlcpy(mix.desc, "Effect Feedback Volume", sizeof(mix.desc)); + uaudio_mixer_add_ctl_sub(sc, &mix); + + memset(&mix, 0, sizeof(mix)); + mix.wIndex = MAKE_WORD(7, sc->sc_mixer_iface_no); + for (chy = 0; chy != 4; chy++) { + + mix.wValue[0] = MAKE_WORD(7, chy + 1); + mix.type = MIX_SIGNED_16; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "effect_ret"; + mix.nchan = 1; + mix.update[0] = 1; + snprintf(mix.desc, sizeof(mix.desc), + "Effect Return %d Volume", chy + 1); + + uaudio_mixer_add_ctl(sc, &mix); + } + + memset(&mix, 0, sizeof(mix)); + mix.wIndex = MAKE_WORD(5, sc->sc_mixer_iface_no); + + for (chy = 0; chy != 8; chy++) { + mix.wValue[0] = MAKE_WORD(9, chy + 1); + mix.type = MIX_SIGNED_16; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "effect_send"; + mix.nchan = 1; + mix.update[0] = 1; + snprintf(mix.desc, sizeof(mix.desc), + "Effect Send AIn%d Volume", chy + 1); + + uaudio_mixer_add_ctl(sc, &mix); + + mix.wValue[0] = MAKE_WORD(9, chy + 1); + mix.type = MIX_SIGNED_16; + mix.ctl = SOUND_MIXER_NRDEVICES; + mix.name = "effect_send"; + mix.nchan = 1; + mix.update[0] = 1; + snprintf(mix.desc, sizeof(mix.desc), + "Effect Send DIn%d Volume", chy + 1 + 8); + + uaudio_mixer_add_ctl(sc, &mix); + } +} + static void uaudio_mixer_reload_all(struct uaudio_softc *sc) { @@ -2209,6 +2364,9 @@ uaudio_mixer_reload_all(struct uaudio_softc *sc) mtx_lock(sc->sc_mixer_lock); for (pmc = sc->sc_mixer_root; pmc != NULL; pmc = pmc->next) { + /* use reset defaults for non-oss controlled settings */ + if (pmc->ctl == SOUND_MIXER_NRDEVICES) + continue; for (chan = 0; chan < pmc->nchan; chan++) pmc->update[chan / 8] |= (1 << (chan % 8)); } @@ -2221,12 +2379,28 @@ uaudio_mixer_add_ctl_sub(struct uaudio_softc *sc, struct uaudio_mixer_node *mc) { struct uaudio_mixer_node *p_mc_new = malloc(sizeof(*p_mc_new), M_USBDEV, M_WAITOK); + int ch; if (p_mc_new != NULL) { memcpy(p_mc_new, mc, sizeof(*p_mc_new)); p_mc_new->next = sc->sc_mixer_root; sc->sc_mixer_root = p_mc_new; sc->sc_mixer_count++; + + /* set default value for all channels */ + for (ch = 0; ch < p_mc_new->nchan; ch++) { + switch (p_mc_new->val_default) { + case 1: + p_mc_new->wData[ch] = (p_mc_new->maxval + p_mc_new->minval) / 2; + break; + case 2: + p_mc_new->wData[ch] = p_mc_new->maxval; + break; + default: + p_mc_new->wData[ch] = p_mc_new->minval; + break; + } + } } else { DPRINTF("out of memory\n"); } |