Lines Matching +full:num +full:- +full:channels
1 // SPDX-License-Identifier: GPL-2.0-or-later
21 * Auto-detection via UAC2 is not feasible to properly discover the vast
38 * - change Impedance of inputs (Line-in, Mic / Instrument, Hi-Z)
39 * - select clock source
40 * - dynamic input to mixer-matrix assignment
41 * - 18 x 6 mixer-matrix gain stages
42 * - bus routing & volume control
43 * - automatic re-initialization on connect if device was power-cycled
49 * pad (-10dB) switch, wValue=0x0b01 + channel, data=Off/On (2bytes)
54 * 0x29 Set Sample-rate, wValue=0x0100, data=sample-rate(4bytes)
55 * 0x32 Mixer mux, wValue=0x0600 + mixer-channel, data=input-to-connect(2bytes)
56 * 0x33 Output mux, wValue=bus, data=input-to-connect(2bytes)
57 * 0x34 Capture mux, wValue=0...18, data=input-to-connect(2bytes)
58 * 0x3c Matrix Mixer gains, wValue=mixer-node data=gain(2bytes)
63 * 0x29 wValue=0x0100 sample-rate(4bytes)
65 * 0x2a wValue=0x0100 ?? 4bytes, sample-rate2 ??
78 * /--------------\ 18chn 6chn /--------------\
79 * | Hardware in +--+-------\ /------+--+ ALSA PCM out |
80 * \--------------/ | | | | \--------------/
83 * | +---------------+ |
85 * | +-----+-----+ |
89 * | +-----------+ |
95 * | +-----+-----+ |
101 * +---------------+ +--—------------+
103 * +-----+-----+ +-----+-----+
107 * +-------------+ |
109 * +------+------+ |
113 * /--------------\ | | /--------------\
114 * | Hardware out |<--/ \-->| ALSA PCM in |
115 * \--------------/ \--------------/
122 #include <linux/usb/audio-v2.h>
164 unsigned char num; member
192 "0dB", "-10dB"
210 "Line", "Hi-Z"
235 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_switch_info()
237 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; in scarlett_ctl_switch_info()
238 uinfo->count = elem->channels; in scarlett_ctl_switch_info()
239 uinfo->value.integer.min = 0; in scarlett_ctl_switch_info()
240 uinfo->value.integer.max = 1; in scarlett_ctl_switch_info()
247 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_switch_get()
250 for (i = 0; i < elem->channels; i++) { in scarlett_ctl_switch_get()
256 ucontrol->value.integer.value[i] = val; in scarlett_ctl_switch_get()
265 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_switch_put()
269 for (i = 0; i < elem->channels; i++) { in scarlett_ctl_switch_put()
274 val = ucontrol->value.integer.value[i]; in scarlett_ctl_switch_put()
293 for (i = 0; i < elem->channels; i++) in scarlett_ctl_resume()
294 if (elem->cached & (1 << i)) in scarlett_ctl_resume()
296 elem->cache_val[i]); in scarlett_ctl_resume()
303 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_info()
305 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in scarlett_ctl_info()
306 uinfo->count = elem->channels; in scarlett_ctl_info()
307 uinfo->value.integer.min = 0; in scarlett_ctl_info()
308 uinfo->value.integer.max = (int)kctl->private_value + in scarlett_ctl_info()
310 uinfo->value.integer.step = 1; in scarlett_ctl_info()
317 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_get()
320 for (i = 0; i < elem->channels; i++) { in scarlett_ctl_get()
325 val = clamp(val / 256, -128, (int)kctl->private_value) + in scarlett_ctl_get()
327 ucontrol->value.integer.value[i] = val; in scarlett_ctl_get()
336 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_put()
340 for (i = 0; i < elem->channels; i++) { in scarlett_ctl_put()
345 val = ucontrol->value.integer.value[i] - in scarlett_ctl_put()
364 'A'+(i - offsets[SCARLETT_OFFSET_MIX] - 1)); in scarlett_generate_name()
366 sprintf(dst, "ADAT %d", i - offsets[SCARLETT_OFFSET_ADAT]); in scarlett_generate_name()
368 sprintf(dst, "SPDIF %d", i - offsets[SCARLETT_OFFSET_SPDIF]); in scarlett_generate_name()
370 sprintf(dst, "Analog %d", i - offsets[SCARLETT_OFFSET_ANALOG]); in scarlett_generate_name()
372 sprintf(dst, "PCM %d", i - offsets[SCARLETT_OFFSET_PCM]); in scarlett_generate_name()
380 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_enum_dynamic_info()
381 struct scarlett_mixer_elem_enum_info *opt = elem->private_data; in scarlett_ctl_enum_dynamic_info()
382 unsigned int items = opt->len; in scarlett_ctl_enum_dynamic_info()
384 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; in scarlett_ctl_enum_dynamic_info()
385 uinfo->count = elem->channels; in scarlett_ctl_enum_dynamic_info()
386 uinfo->value.enumerated.items = items; in scarlett_ctl_enum_dynamic_info()
388 if (uinfo->value.enumerated.item >= items) in scarlett_ctl_enum_dynamic_info()
389 uinfo->value.enumerated.item = items - 1; in scarlett_ctl_enum_dynamic_info()
392 scarlett_generate_name(uinfo->value.enumerated.item, in scarlett_ctl_enum_dynamic_info()
393 uinfo->value.enumerated.name, in scarlett_ctl_enum_dynamic_info()
394 opt->offsets); in scarlett_ctl_enum_dynamic_info()
402 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_enum_info()
403 struct scarlett_mixer_elem_enum_info *opt = elem->private_data; in scarlett_ctl_enum_info()
405 return snd_ctl_enum_info(uinfo, elem->channels, opt->len, in scarlett_ctl_enum_info()
406 (const char * const *)opt->names); in scarlett_ctl_enum_info()
412 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_enum_get()
413 struct scarlett_mixer_elem_enum_info *opt = elem->private_data; in scarlett_ctl_enum_get()
420 val = clamp(val - opt->start, 0, opt->len-1); in scarlett_ctl_enum_get()
422 ucontrol->value.enumerated.item[0] = val; in scarlett_ctl_enum_get()
430 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_enum_put()
431 struct scarlett_mixer_elem_enum_info *opt = elem->private_data; in scarlett_ctl_enum_put()
438 val = ucontrol->value.integer.value[0]; in scarlett_ctl_enum_put()
439 val = val + opt->start; in scarlett_ctl_enum_put()
451 if (elem->cached) in scarlett_ctl_enum_resume()
452 snd_usb_set_cur_mix_value(elem, 0, 0, *elem->cache_val); in scarlett_ctl_enum_resume()
459 struct usb_mixer_elem_info *elem = kctl->private_data; in scarlett_ctl_meter_get()
460 struct snd_usb_audio *chip = elem->head.mixer->chip; in scarlett_ctl_meter_get()
462 int wValue = (elem->control << 8) | elem->idx_off; in scarlett_ctl_meter_get()
463 int idx = snd_usb_ctrl_intf(elem->head.mixer->hostif) | (elem->head.id << 8); in scarlett_ctl_meter_get()
466 err = snd_usb_ctl_msg(chip->dev, in scarlett_ctl_meter_get()
467 usb_rcvctrlpipe(chip->dev, 0), in scarlett_ctl_meter_get()
470 USB_DIR_IN, wValue, idx, buf, elem->channels); in scarlett_ctl_meter_get()
474 ucontrol->value.enumerated.item[0] = clamp((int)buf[0], 0, 1); in scarlett_ctl_meter_get()
486 static const DECLARE_TLV_DB_SCALE(db_scale_scarlett_gain, -12800, 100, 0);
539 int index, int offset, int num, in add_new_ctl() argument
540 int val_type, int channels, const char *name, in add_new_ctl() argument
551 return -ENOMEM; in add_new_ctl()
553 elem->head.mixer = mixer; in add_new_ctl()
554 elem->head.resume = resume; in add_new_ctl()
555 elem->control = offset; in add_new_ctl()
556 elem->idx_off = num; in add_new_ctl()
557 elem->head.id = index; in add_new_ctl()
558 elem->val_type = val_type; in add_new_ctl()
560 elem->channels = channels; in add_new_ctl()
563 elem->private_data = (void *)opt; in add_new_ctl()
568 return -ENOMEM; in add_new_ctl()
570 kctl->private_free = snd_usb_mixer_elem_free; in add_new_ctl()
572 strscpy(kctl->id.name, name, sizeof(kctl->id.name)); in add_new_ctl()
574 err = snd_usb_mixer_add_control(&elem->head, kctl); in add_new_ctl()
615 2*index, USB_MIXER_S16, 1, mx, &info->opt_master, in add_output_ctls()
625 2*index+1, USB_MIXER_S16, 1, mx, &info->opt_master, in add_output_ctls()
633 /********************** device-specific config *************************/
643 .start = -1,
650 .start = -1,
658 { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },
659 { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" },
660 { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },
661 { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
662 { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL},
663 { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
664 { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL},
665 { .num = 3, .type = SCARLETT_SWITCH_GAIN, .name = NULL},
666 { .num = 4, .type = SCARLETT_SWITCH_GAIN, .name = NULL},
670 12, 13, 14, 15, /* Analog -> 1..4 */
671 16, 17, /* SPDIF -> 5,6 */
672 0, 1, 2, 3, 4, 5, 6, 7, /* PCM[1..12] -> 7..18 */
685 .start = -1,
692 .start = -1,
700 { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },
701 { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" },
702 { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },
703 { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
704 { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
705 { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL},
706 { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL},
710 12, 13, 14, 15, /* Analog -> 1..4 */
711 16, 17, /* SPDIF -> 5,6 */
712 0, 1, 2, 3, 4, 5, 6, 7, /* PCM[1..12] -> 7..18 */
724 .start = -1,
731 .start = -1,
739 { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },
740 { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" },
741 { .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },
742 { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
743 { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
747 6, 7, 8, 9, 10, 11, 12, 13, /* Analog -> 1..8 */
748 16, 17, 18, 19, 20, 21, /* ADAT[1..6] -> 9..14 */
749 14, 15, /* SPDIF -> 15,16 */
750 0, 1 /* PCM[1,2] -> 17,18 */
761 .start = -1,
768 .start = -1,
776 { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },
777 { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone 1" },
778 { .num = 2, .type = SCARLETT_OUTPUTS, .name = "Headphone 2" },
779 { .num = 3, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },
780 { .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
781 { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL},
782 { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
783 { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL},
784 { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL},
785 { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL},
789 8, 9, 10, 11, 12, 13, 14, 15, /* Analog -> 1..8 */
790 18, 19, 20, 21, 22, 23, /* ADAT[1..6] -> 9..14 */
791 16, 17, /* SPDIF -> 15,16 */
792 0, 1 /* PCM[1,2] -> 17,18 */
803 .start = -1,
810 .start = -1,
818 { .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },
819 { .num = 1, .type = SCARLETT_OUTPUTS, .name = "Line 3/4" },
820 { .num = 2, .type = SCARLETT_OUTPUTS, .name = "Line 5/6" },
821 { .num = 3, .type = SCARLETT_OUTPUTS, .name = "Line 7/8" },
822 { .num = 4, .type = SCARLETT_OUTPUTS, .name = "Line 9/10" },
823 { .num = 5, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },
824 { .num = 6, .type = SCARLETT_OUTPUTS, .name = "ADAT 1/2" },
825 { .num = 7, .type = SCARLETT_OUTPUTS, .name = "ADAT 3/4" },
826 { .num = 8, .type = SCARLETT_OUTPUTS, .name = "ADAT 5/6" },
827 { .num = 9, .type = SCARLETT_OUTPUTS, .name = "ADAT 7/8" },
828 /*{ .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
829 { .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL},
830 { .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},
831 { .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL},
832 { .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL},
833 { .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL},*/
837 20, 21, 22, 23, 24, 25, 26, 27, /* Analog -> 1..8 */
838 30, 31, 32, 33, 34, 35, /* ADAT[1..6] -> 9..14 */
839 28, 29, /* SPDIF -> 15,16 */
840 0, 1 /* PCM[1,2] -> 17,18 */
869 for (i = 0; i < info->num_controls; i++) { in scarlett_controls_create_generic()
870 ctl = &info->controls[i]; in scarlett_controls_create_generic()
872 switch (ctl->type) { in scarlett_controls_create_generic()
874 err = add_output_ctls(mixer, ctl->num, ctl->name, info); in scarlett_controls_create_generic()
879 sprintf(mx, "Input %d Impedance Switch", ctl->num); in scarlett_controls_create_generic()
882 0x09, ctl->num, USB_MIXER_S16, 1, mx, in scarlett_controls_create_generic()
888 sprintf(mx, "Input %d Pad Switch", ctl->num); in scarlett_controls_create_generic()
891 0x0b, ctl->num, USB_MIXER_S16, 1, mx, in scarlett_controls_create_generic()
897 sprintf(mx, "Input %d Gain Switch", ctl->num); in scarlett_controls_create_generic()
900 0x08, ctl->num, USB_MIXER_S16, 1, mx, in scarlett_controls_create_generic()
923 if (!mixer->protocol) in snd_scarlett_controls_create()
926 switch (mixer->chip->usb_id) { in snd_scarlett_controls_create()
943 return -EINVAL; in snd_scarlett_controls_create()
952 for (i = 0; i < info->matrix_in; i++) { in snd_scarlett_controls_create()
958 &info->opt_matrix, &elem); in snd_scarlett_controls_create()
962 for (o = 0; o < info->matrix_out; o++) { in snd_scarlett_controls_create()
975 for (i = 0; i < info->input_len; i++) { in snd_scarlett_controls_create()
981 &info->opt_master, &elem); in snd_scarlett_controls_create()
1002 err = snd_usb_ctl_msg(mixer->chip->dev, in snd_scarlett_controls_create()
1003 usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR, in snd_scarlett_controls_create()
1005 USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->hostif) | in snd_scarlett_controls_create()