diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-03-01 10:20:37 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2010-03-01 11:02:38 -0500 |
commit | e584bc3cf6865e005bbb4dbabae0bf4b3df59500 (patch) | |
tree | 0ca057d2bee756f70064185ab4aa834cb6418eba /sound | |
parent | 291186e049d7f8178ad31d43c38a53889f25d79e (diff) |
ALSA: ua101: add Edirol UA-1000 support
Add support for the Edirol UA-1000 to the UA-101 driver.
Both devices behave the same, so we just have to shuffle around some
interface numbers and name strings.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/usb/Kconfig | 6 | ||||
-rw-r--r-- | sound/usb/ua101.c | 45 | ||||
-rw-r--r-- | sound/usb/usbaudio.c | 53 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 3 | ||||
-rw-r--r-- | sound/usb/usbquirks.h | 30 |
5 files changed, 37 insertions, 100 deletions
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 8c2925814ce4..c570ae3e6d55 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -22,13 +22,13 @@ config SND_USB_AUDIO | |||
22 | will be called snd-usb-audio. | 22 | will be called snd-usb-audio. |
23 | 23 | ||
24 | config SND_USB_UA101 | 24 | config SND_USB_UA101 |
25 | tristate "Edirol UA-101 driver (EXPERIMENTAL)" | 25 | tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)" |
26 | depends on EXPERIMENTAL | 26 | depends on EXPERIMENTAL |
27 | select SND_PCM | 27 | select SND_PCM |
28 | select SND_RAWMIDI | 28 | select SND_RAWMIDI |
29 | help | 29 | help |
30 | Say Y here to include support for the Edirol UA-101 audio/MIDI | 30 | Say Y here to include support for the Edirol UA-101 and UA-1000 |
31 | interface. | 31 | audio/MIDI interfaces. |
32 | 32 | ||
33 | To compile this driver as a module, choose M here: the module | 33 | To compile this driver as a module, choose M here: the module |
34 | will be called snd-ua101. | 34 | will be called snd-ua101. |
diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c index 4f4ccdf70dd0..047dc1ca84d0 100644 --- a/sound/usb/ua101.c +++ b/sound/usb/ua101.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Edirol UA-101 driver | 2 | * Edirol UA-101/UA-1000 driver |
3 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | 3 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
4 | * | 4 | * |
5 | * This driver is free software: you can redistribute it and/or modify | 5 | * This driver is free software: you can redistribute it and/or modify |
@@ -25,10 +25,10 @@ | |||
25 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
26 | #include "usbaudio.h" | 26 | #include "usbaudio.h" |
27 | 27 | ||
28 | MODULE_DESCRIPTION("Edirol UA-101 driver"); | 28 | MODULE_DESCRIPTION("Edirol UA-101/1000 driver"); |
29 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 29 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
30 | MODULE_LICENSE("GPL v2"); | 30 | MODULE_LICENSE("GPL v2"); |
31 | MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}"); | 31 | MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); |
32 | 32 | ||
33 | /* I use my UA-1A for testing because I don't have a UA-101 ... */ | 33 | /* I use my UA-1A for testing because I don't have a UA-101 ... */ |
34 | #define UA1A_HACK | 34 | #define UA1A_HACK |
@@ -1200,13 +1200,30 @@ static int ua101_probe(struct usb_interface *interface, | |||
1200 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 1200 | .type = QUIRK_MIDI_FIXED_ENDPOINT, |
1201 | .data = &midi_ep | 1201 | .data = &midi_ep |
1202 | }; | 1202 | }; |
1203 | static const int intf_numbers[2][3] = { | ||
1204 | { /* UA-101 */ | ||
1205 | [INTF_PLAYBACK] = 0, | ||
1206 | [INTF_CAPTURE] = 1, | ||
1207 | [INTF_MIDI] = 2, | ||
1208 | }, | ||
1209 | { /* UA-1000 */ | ||
1210 | [INTF_CAPTURE] = 1, | ||
1211 | [INTF_PLAYBACK] = 2, | ||
1212 | [INTF_MIDI] = 3, | ||
1213 | }, | ||
1214 | }; | ||
1203 | struct snd_card *card; | 1215 | struct snd_card *card; |
1204 | struct ua101 *ua; | 1216 | struct ua101 *ua; |
1205 | unsigned int card_index, i; | 1217 | unsigned int card_index, i; |
1218 | int is_ua1000; | ||
1219 | const char *name; | ||
1206 | char usb_path[32]; | 1220 | char usb_path[32]; |
1207 | int err; | 1221 | int err; |
1208 | 1222 | ||
1209 | if (interface->altsetting->desc.bInterfaceNumber != 0) | 1223 | is_ua1000 = usb_id->idProduct == 0x0044; |
1224 | |||
1225 | if (interface->altsetting->desc.bInterfaceNumber != | ||
1226 | intf_numbers[is_ua1000][0]) | ||
1210 | return -ENODEV; | 1227 | return -ENODEV; |
1211 | 1228 | ||
1212 | mutex_lock(&devices_mutex); | 1229 | mutex_lock(&devices_mutex); |
@@ -1250,9 +1267,11 @@ static int ua101_probe(struct usb_interface *interface, | |||
1250 | #endif | 1267 | #endif |
1251 | ua->intf[0] = interface; | 1268 | ua->intf[0] = interface; |
1252 | for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { | 1269 | for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { |
1253 | ua->intf[i] = usb_ifnum_to_if(ua->dev, i); | 1270 | ua->intf[i] = usb_ifnum_to_if(ua->dev, |
1271 | intf_numbers[is_ua1000][i]); | ||
1254 | if (!ua->intf[i]) { | 1272 | if (!ua->intf[i]) { |
1255 | dev_err(&ua->dev->dev, "interface %u not found\n", i); | 1273 | dev_err(&ua->dev->dev, "interface %u not found\n", |
1274 | intf_numbers[is_ua1000][i]); | ||
1256 | err = -ENXIO; | 1275 | err = -ENXIO; |
1257 | goto probe_error; | 1276 | goto probe_error; |
1258 | } | 1277 | } |
@@ -1292,11 +1311,12 @@ static int ua101_probe(struct usb_interface *interface, | |||
1292 | } | 1311 | } |
1293 | #endif | 1312 | #endif |
1294 | 1313 | ||
1314 | name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101"; | ||
1295 | strcpy(card->driver, "UA-101"); | 1315 | strcpy(card->driver, "UA-101"); |
1296 | strcpy(card->shortname, "UA-101"); | 1316 | strcpy(card->shortname, name); |
1297 | usb_make_path(ua->dev, usb_path, sizeof(usb_path)); | 1317 | usb_make_path(ua->dev, usb_path, sizeof(usb_path)); |
1298 | snprintf(ua->card->longname, sizeof(ua->card->longname), | 1318 | snprintf(ua->card->longname, sizeof(ua->card->longname), |
1299 | "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed", | 1319 | "EDIROL %s (serial %s), %u Hz at %s, %s speed", name, |
1300 | ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path, | 1320 | ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path, |
1301 | ua->dev->speed == USB_SPEED_HIGH ? "high" : "full"); | 1321 | ua->dev->speed == USB_SPEED_HIGH ? "high" : "full"); |
1302 | 1322 | ||
@@ -1314,11 +1334,11 @@ static int ua101_probe(struct usb_interface *interface, | |||
1314 | if (err < 0) | 1334 | if (err < 0) |
1315 | goto probe_error; | 1335 | goto probe_error; |
1316 | 1336 | ||
1317 | err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm); | 1337 | err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm); |
1318 | if (err < 0) | 1338 | if (err < 0) |
1319 | goto probe_error; | 1339 | goto probe_error; |
1320 | ua->pcm->private_data = ua; | 1340 | ua->pcm->private_data = ua; |
1321 | strcpy(ua->pcm->name, "UA-101"); | 1341 | strcpy(ua->pcm->name, name); |
1322 | snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); | 1342 | snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); |
1323 | snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); | 1343 | snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); |
1324 | 1344 | ||
@@ -1389,8 +1409,9 @@ static struct usb_device_id ua101_ids[] = { | |||
1389 | #ifdef UA1A_HACK | 1409 | #ifdef UA1A_HACK |
1390 | { USB_DEVICE(0x0582, 0x0018) }, | 1410 | { USB_DEVICE(0x0582, 0x0018) }, |
1391 | #endif | 1411 | #endif |
1392 | { USB_DEVICE(0x0582, 0x007d) }, | 1412 | { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */ |
1393 | { USB_DEVICE(0x0582, 0x008d) }, | 1413 | { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */ |
1414 | { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */ | ||
1394 | { } | 1415 | { } |
1395 | }; | 1416 | }; |
1396 | MODULE_DEVICE_TABLE(usb, ua101_ids); | 1417 | MODULE_DEVICE_TABLE(usb, ua101_ids); |
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8a8f62515b80..7ad8089b233e 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -3116,58 +3116,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, | |||
3116 | return 0; | 3116 | return 0; |
3117 | } | 3117 | } |
3118 | 3118 | ||
3119 | /* | ||
3120 | * Create a stream for an Edirol UA-1000 interface. | ||
3121 | */ | ||
3122 | static int create_ua1000_quirk(struct snd_usb_audio *chip, | ||
3123 | struct usb_interface *iface, | ||
3124 | const struct snd_usb_audio_quirk *quirk) | ||
3125 | { | ||
3126 | static const struct audioformat ua1000_format = { | ||
3127 | .format = SNDRV_PCM_FORMAT_S32_LE, | ||
3128 | .fmt_type = USB_FORMAT_TYPE_I, | ||
3129 | .altsetting = 1, | ||
3130 | .altset_idx = 1, | ||
3131 | .attributes = 0, | ||
3132 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
3133 | }; | ||
3134 | struct usb_host_interface *alts; | ||
3135 | struct usb_interface_descriptor *altsd; | ||
3136 | struct audioformat *fp; | ||
3137 | int stream, err; | ||
3138 | |||
3139 | if (iface->num_altsetting != 2) | ||
3140 | return -ENXIO; | ||
3141 | alts = &iface->altsetting[1]; | ||
3142 | altsd = get_iface_desc(alts); | ||
3143 | if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE || | ||
3144 | altsd->bNumEndpoints != 1) | ||
3145 | return -ENXIO; | ||
3146 | |||
3147 | fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL); | ||
3148 | if (!fp) | ||
3149 | return -ENOMEM; | ||
3150 | |||
3151 | fp->channels = alts->extra[4]; | ||
3152 | fp->iface = altsd->bInterfaceNumber; | ||
3153 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; | ||
3154 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | ||
3155 | fp->datainterval = parse_datainterval(chip, alts); | ||
3156 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | ||
3157 | fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); | ||
3158 | |||
3159 | stream = (fp->endpoint & USB_DIR_IN) | ||
3160 | ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | ||
3161 | err = add_audio_endpoint(chip, stream, fp); | ||
3162 | if (err < 0) { | ||
3163 | kfree(fp); | ||
3164 | return err; | ||
3165 | } | ||
3166 | /* FIXME: playback must be synchronized to capture */ | ||
3167 | usb_set_interface(chip->dev, fp->iface, 0); | ||
3168 | return 0; | ||
3169 | } | ||
3170 | |||
3171 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, | 3119 | static int snd_usb_create_quirk(struct snd_usb_audio *chip, |
3172 | struct usb_interface *iface, | 3120 | struct usb_interface *iface, |
3173 | const struct snd_usb_audio_quirk *quirk); | 3121 | const struct snd_usb_audio_quirk *quirk); |
@@ -3416,7 +3364,6 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, | |||
3416 | [QUIRK_MIDI_CME] = create_any_midi_quirk, | 3364 | [QUIRK_MIDI_CME] = create_any_midi_quirk, |
3417 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, | 3365 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, |
3418 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, | 3366 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, |
3419 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, | ||
3420 | [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, | 3367 | [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, |
3421 | [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk | 3368 | [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk |
3422 | }; | 3369 | }; |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 9d8cea48fc5f..96c558a76ba6 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -159,7 +159,6 @@ enum quirk_type { | |||
159 | QUIRK_MIDI_US122L, | 159 | QUIRK_MIDI_US122L, |
160 | QUIRK_AUDIO_STANDARD_INTERFACE, | 160 | QUIRK_AUDIO_STANDARD_INTERFACE, |
161 | QUIRK_AUDIO_FIXED_ENDPOINT, | 161 | QUIRK_AUDIO_FIXED_ENDPOINT, |
162 | QUIRK_AUDIO_EDIROL_UA1000, | ||
163 | QUIRK_AUDIO_EDIROL_UAXX, | 162 | QUIRK_AUDIO_EDIROL_UAXX, |
164 | QUIRK_AUDIO_ALIGN_TRANSFER, | 163 | QUIRK_AUDIO_ALIGN_TRANSFER, |
165 | 164 | ||
@@ -196,7 +195,7 @@ struct snd_usb_midi_endpoint_info { | |||
196 | 195 | ||
197 | /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ | 196 | /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ |
198 | 197 | ||
199 | /* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */ | 198 | /* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */ |
200 | 199 | ||
201 | /* for QUIRK_IGNORE_INTERFACE, data is NULL */ | 200 | /* for QUIRK_IGNORE_INTERFACE, data is NULL */ |
202 | 201 | ||
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index e691eba6a83e..977d980fb117 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -1016,36 +1016,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1016 | } | 1016 | } |
1017 | }, | 1017 | }, |
1018 | { | 1018 | { |
1019 | USB_DEVICE(0x0582, 0x0044), | ||
1020 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1021 | .vendor_name = "Roland", | ||
1022 | .product_name = "UA-1000", | ||
1023 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1024 | .type = QUIRK_COMPOSITE, | ||
1025 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1026 | { | ||
1027 | .ifnum = 1, | ||
1028 | .type = QUIRK_AUDIO_EDIROL_UA1000 | ||
1029 | }, | ||
1030 | { | ||
1031 | .ifnum = 2, | ||
1032 | .type = QUIRK_AUDIO_EDIROL_UA1000 | ||
1033 | }, | ||
1034 | { | ||
1035 | .ifnum = 3, | ||
1036 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1037 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1038 | .out_cables = 0x0003, | ||
1039 | .in_cables = 0x0003 | ||
1040 | } | ||
1041 | }, | ||
1042 | { | ||
1043 | .ifnum = -1 | ||
1044 | } | ||
1045 | } | ||
1046 | } | ||
1047 | }, | ||
1048 | { | ||
1049 | /* has ID 0x0049 when not in "Advanced Driver" mode */ | 1019 | /* has ID 0x0049 when not in "Advanced Driver" mode */ |
1050 | USB_DEVICE(0x0582, 0x0047), | 1020 | USB_DEVICE(0x0582, 0x0047), |
1051 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1021 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |