diff options
-rw-r--r-- | sound/usb/usbaudio.c | 53 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 1 | ||||
-rw-r--r-- | sound/usb/usbquirks.h | 32 |
3 files changed, 85 insertions, 1 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8fd37596e3a1..4dfb91d4398a 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -3077,6 +3077,58 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip, | |||
3077 | return 0; | 3077 | return 0; |
3078 | } | 3078 | } |
3079 | 3079 | ||
3080 | /* | ||
3081 | * Create a stream for an Edirol UA-101 interface. | ||
3082 | * Copy, paste and modify from Edirol UA-1000 | ||
3083 | */ | ||
3084 | static int create_ua101_quirk(struct snd_usb_audio *chip, | ||
3085 | struct usb_interface *iface, | ||
3086 | const struct snd_usb_audio_quirk *quirk) | ||
3087 | { | ||
3088 | static const struct audioformat ua101_format = { | ||
3089 | .format = SNDRV_PCM_FORMAT_S32_LE, | ||
3090 | .fmt_type = USB_FORMAT_TYPE_I, | ||
3091 | .altsetting = 1, | ||
3092 | .altset_idx = 1, | ||
3093 | .attributes = 0, | ||
3094 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
3095 | }; | ||
3096 | struct usb_host_interface *alts; | ||
3097 | struct usb_interface_descriptor *altsd; | ||
3098 | struct audioformat *fp; | ||
3099 | int stream, err; | ||
3100 | |||
3101 | if (iface->num_altsetting != 2) | ||
3102 | return -ENXIO; | ||
3103 | alts = &iface->altsetting[1]; | ||
3104 | altsd = get_iface_desc(alts); | ||
3105 | if (alts->extralen != 18 || alts->extra[1] != USB_DT_CS_INTERFACE || | ||
3106 | altsd->bNumEndpoints != 1) | ||
3107 | return -ENXIO; | ||
3108 | |||
3109 | fp = kmemdup(&ua101_format, sizeof(*fp), GFP_KERNEL); | ||
3110 | if (!fp) | ||
3111 | return -ENOMEM; | ||
3112 | |||
3113 | fp->channels = alts->extra[11]; | ||
3114 | fp->iface = altsd->bInterfaceNumber; | ||
3115 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; | ||
3116 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | ||
3117 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | ||
3118 | fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]); | ||
3119 | |||
3120 | stream = (fp->endpoint & USB_DIR_IN) | ||
3121 | ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | ||
3122 | err = add_audio_endpoint(chip, stream, fp); | ||
3123 | if (err < 0) { | ||
3124 | kfree(fp); | ||
3125 | return err; | ||
3126 | } | ||
3127 | /* FIXME: playback must be synchronized to capture */ | ||
3128 | usb_set_interface(chip->dev, fp->iface, 0); | ||
3129 | return 0; | ||
3130 | } | ||
3131 | |||
3080 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, | 3132 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, |
3081 | struct usb_interface *iface, | 3133 | struct usb_interface *iface, |
3082 | const struct snd_usb_audio_quirk *quirk); | 3134 | const struct snd_usb_audio_quirk *quirk); |
@@ -3258,6 +3310,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, | |||
3258 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, | 3310 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, |
3259 | [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, | 3311 | [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, |
3260 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, | 3312 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, |
3313 | [QUIRK_AUDIO_EDIROL_UA101] = create_ua101_quirk, | ||
3261 | }; | 3314 | }; |
3262 | 3315 | ||
3263 | if (quirk->type < QUIRK_TYPE_COUNT) { | 3316 | if (quirk->type < QUIRK_TYPE_COUNT) { |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 0f4b2b8541d6..2272f45a1867 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -159,6 +159,7 @@ enum quirk_type { | |||
159 | QUIRK_AUDIO_FIXED_ENDPOINT, | 159 | QUIRK_AUDIO_FIXED_ENDPOINT, |
160 | QUIRK_AUDIO_EDIROL_UA700_UA25, | 160 | QUIRK_AUDIO_EDIROL_UA700_UA25, |
161 | QUIRK_AUDIO_EDIROL_UA1000, | 161 | QUIRK_AUDIO_EDIROL_UA1000, |
162 | QUIRK_AUDIO_EDIROL_UA101, | ||
162 | 163 | ||
163 | QUIRK_TYPE_COUNT | 164 | QUIRK_TYPE_COUNT |
164 | }; | 165 | }; |
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index a7e9563a01df..25b4ab4f61e7 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -1098,7 +1098,37 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1098 | } | 1098 | } |
1099 | } | 1099 | } |
1100 | }, | 1100 | }, |
1101 | /* TODO: add Edirol UA-101 support */ | 1101 | /* Roland UA-101 in High-Speed Mode only */ |
1102 | { | ||
1103 | USB_DEVICE(0x0582, 0x007d), | ||
1104 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1105 | .vendor_name = "Roland", | ||
1106 | .product_name = "UA-101", | ||
1107 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1108 | .type = QUIRK_COMPOSITE, | ||
1109 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1110 | { | ||
1111 | .ifnum = 0, | ||
1112 | .type = QUIRK_AUDIO_EDIROL_UA101 | ||
1113 | }, | ||
1114 | { | ||
1115 | .ifnum = 1, | ||
1116 | .type = QUIRK_AUDIO_EDIROL_UA101 | ||
1117 | }, | ||
1118 | { | ||
1119 | .ifnum = 2, | ||
1120 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1121 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1122 | .out_cables = 0x0001, | ||
1123 | .in_cables = 0x0001 | ||
1124 | } | ||
1125 | }, | ||
1126 | { | ||
1127 | .ifnum = -1 | ||
1128 | } | ||
1129 | } | ||
1130 | } | ||
1131 | }, | ||
1102 | { | 1132 | { |
1103 | /* has ID 0x0081 when not in "Advanced Driver" mode */ | 1133 | /* has ID 0x0081 when not in "Advanced Driver" mode */ |
1104 | USB_DEVICE(0x0582, 0x0080), | 1134 | USB_DEVICE(0x0582, 0x0080), |