Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 156366d3 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge remote branch 'alsa/devel' into topic/misc

Conflicts:
	sound/usb/usbaudio.c
parents 7f9320d4 0a566ec2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1812,7 +1812,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
  Module snd-ua101
  ----------------

    Module for the Edirol UA-101 audio/MIDI interface.
    Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces.

    This module supports multiple devices, autoprobe and hotplugging.

+3 −3
Original line number Diff line number Diff line
@@ -22,13 +22,13 @@ config SND_USB_AUDIO
	  will be called snd-usb-audio.

config SND_USB_UA101
	tristate "Edirol UA-101 driver (EXPERIMENTAL)"
	tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)"
	depends on EXPERIMENTAL
	select SND_PCM
	select SND_RAWMIDI
	help
	  Say Y here to include support for the Edirol UA-101 audio/MIDI
	  interface.
	  Say Y here to include support for the Edirol UA-101 and UA-1000
	  audio/MIDI interfaces.

	  To compile this driver as a module, choose M here: the module
	  will be called snd-ua101.
+33 −67
Original line number Diff line number Diff line
/*
 * Edirol UA-101 driver
 * Edirol UA-101/UA-1000 driver
 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
 *
 * This driver is free software: you can redistribute it and/or modify
@@ -25,13 +25,10 @@
#include <sound/pcm_params.h>
#include "usbaudio.h"

MODULE_DESCRIPTION("Edirol UA-101 driver");
MODULE_DESCRIPTION("Edirol UA-101/1000 driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}");

/* I use my UA-1A for testing because I don't have a UA-101 ... */
#define UA1A_HACK
MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}");

/*
 * Should not be lower than the minimum scheduling delay of the host
@@ -132,9 +129,6 @@ struct ua101 {
			dma_addr_t dma;
		} buffers[MAX_MEMORY_BUFFERS];
	} capture, playback;

	unsigned int fps[10];
	unsigned int frame_counter;
};

static DEFINE_MUTEX(devices_mutex);
@@ -424,16 +418,6 @@ static void capture_urb_complete(struct urb *urb)
	if (do_period_elapsed)
		snd_pcm_period_elapsed(stream->substream);

	/* for debugging: measure the sample rate relative to the USB clock */
	ua->fps[ua->frame_counter++ / ua->packets_per_second] += frames;
	if (ua->frame_counter >= ARRAY_SIZE(ua->fps) * ua->packets_per_second) {
		printk(KERN_DEBUG "capture rate:");
		for (frames = 0; frames < ARRAY_SIZE(ua->fps); ++frames)
			printk(KERN_CONT " %u", ua->fps[frames]);
		printk(KERN_CONT "\n");
		memset(ua->fps, 0, sizeof(ua->fps));
		ua->frame_counter = 0;
	}
	return;

stream_stopped:
@@ -1200,13 +1184,30 @@ static int ua101_probe(struct usb_interface *interface,
		.type = QUIRK_MIDI_FIXED_ENDPOINT,
		.data = &midi_ep
	};
	static const int intf_numbers[2][3] = {
		{	/* UA-101 */
			[INTF_PLAYBACK] = 0,
			[INTF_CAPTURE] = 1,
			[INTF_MIDI] = 2,
		},
		{	/* UA-1000 */
			[INTF_CAPTURE] = 1,
			[INTF_PLAYBACK] = 2,
			[INTF_MIDI] = 3,
		},
	};
	struct snd_card *card;
	struct ua101 *ua;
	unsigned int card_index, i;
	int is_ua1000;
	const char *name;
	char usb_path[32];
	int err;

	if (interface->altsetting->desc.bInterfaceNumber != 0)
	is_ua1000 = usb_id->idProduct == 0x0044;

	if (interface->altsetting->desc.bInterfaceNumber !=
	    intf_numbers[is_ua1000][0])
		return -ENODEV;

	mutex_lock(&devices_mutex);
@@ -1239,20 +1240,13 @@ static int ua101_probe(struct usb_interface *interface,
	init_waitqueue_head(&ua->rate_feedback_wait);
	init_waitqueue_head(&ua->alsa_playback_wait);

#ifdef UA1A_HACK
	if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) {
		ua->intf[2] = interface;
		ua->intf[0] = usb_ifnum_to_if(ua->dev, 1);
		ua->intf[1] = usb_ifnum_to_if(ua->dev, 2);
		usb_driver_claim_interface(&ua101_driver, ua->intf[0], ua);
		usb_driver_claim_interface(&ua101_driver, ua->intf[1], ua);
	} else {
#endif
	ua->intf[0] = interface;
	for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) {
		ua->intf[i] = usb_ifnum_to_if(ua->dev, i);
		ua->intf[i] = usb_ifnum_to_if(ua->dev,
					      intf_numbers[is_ua1000][i]);
		if (!ua->intf[i]) {
			dev_err(&ua->dev->dev, "interface %u not found\n", i);
			dev_err(&ua->dev->dev, "interface %u not found\n",
				intf_numbers[is_ua1000][i]);
			err = -ENXIO;
			goto probe_error;
		}
@@ -1264,39 +1258,19 @@ static int ua101_probe(struct usb_interface *interface,
			goto probe_error;
		}
	}
#ifdef UA1A_HACK
	}
#endif

	snd_card_set_dev(card, &interface->dev);

#ifdef UA1A_HACK
	if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) {
		ua->format_bit = SNDRV_PCM_FMTBIT_S16_LE;
		ua->rate = 44100;
		ua->packets_per_second = 1000;
		ua->capture.channels = 2;
		ua->playback.channels = 2;
		ua->capture.frame_bytes = 4;
		ua->playback.frame_bytes = 4;
		ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, 2);
		ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, 1);
		ua->capture.max_packet_bytes = 192;
		ua->playback.max_packet_bytes = 192;
	} else {
#endif
	err = detect_usb_format(ua);
	if (err < 0)
		goto probe_error;
#ifdef UA1A_HACK
	}
#endif

	name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101";
	strcpy(card->driver, "UA-101");
	strcpy(card->shortname, "UA-101");
	strcpy(card->shortname, name);
	usb_make_path(ua->dev, usb_path, sizeof(usb_path));
	snprintf(ua->card->longname, sizeof(ua->card->longname),
		 "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed",
		 "EDIROL %s (serial %s), %u Hz at %s, %s speed", name,
		 ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path,
		 ua->dev->speed == USB_SPEED_HIGH ? "high" : "full");

@@ -1314,24 +1288,18 @@ static int ua101_probe(struct usb_interface *interface,
	if (err < 0)
		goto probe_error;

	err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm);
	err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm);
	if (err < 0)
		goto probe_error;
	ua->pcm->private_data = ua;
	strcpy(ua->pcm->name, "UA-101");
	strcpy(ua->pcm->name, name);
	snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops);
	snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops);

#ifdef UA1A_HACK
	if (ua->dev->descriptor.idProduct != cpu_to_le16(0x0018)) {
#endif
	err = snd_usbmidi_create(card, ua->intf[INTF_MIDI],
				 &ua->midi_list, &midi_quirk);
	if (err < 0)
		goto probe_error;
#ifdef UA1A_HACK
	}
#endif

	err = snd_card_register(card);
	if (err < 0)
@@ -1386,11 +1354,9 @@ static void ua101_disconnect(struct usb_interface *interface)
}

static struct usb_device_id ua101_ids[] = {
#ifdef UA1A_HACK
	{ USB_DEVICE(0x0582, 0x0018) },
#endif
	{ USB_DEVICE(0x0582, 0x007d) },
	{ USB_DEVICE(0x0582, 0x008d) },
	{ USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */
	{ USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */
	{ USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */
	{ }
};
MODULE_DEVICE_TABLE(usb, ua101_ids);
+0 −53
Original line number Diff line number Diff line
@@ -3386,58 +3386,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
	return 0;
}

/*
 * Create a stream for an Edirol UA-1000 interface.
 */
static int create_ua1000_quirk(struct snd_usb_audio *chip,
			       struct usb_interface *iface,
			       const struct snd_usb_audio_quirk *quirk)
{
	static const struct audioformat ua1000_format = {
		.format = SNDRV_PCM_FORMAT_S32_LE,
		.fmt_type = UAC_FORMAT_TYPE_I,
		.altsetting = 1,
		.altset_idx = 1,
		.attributes = 0,
		.rates = SNDRV_PCM_RATE_CONTINUOUS,
	};
	struct usb_host_interface *alts;
	struct usb_interface_descriptor *altsd;
	struct audioformat *fp;
	int stream, err;

	if (iface->num_altsetting != 2)
		return -ENXIO;
	alts = &iface->altsetting[1];
	altsd = get_iface_desc(alts);
	if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE ||
	    altsd->bNumEndpoints != 1)
		return -ENXIO;

	fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL);
	if (!fp)
		return -ENOMEM;

	fp->channels = alts->extra[4];
	fp->iface = altsd->bInterfaceNumber;
	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
	fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
	fp->datainterval = parse_datainterval(chip, alts);
	fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
	fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);

	stream = (fp->endpoint & USB_DIR_IN)
		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
	err = add_audio_endpoint(chip, stream, fp);
	if (err < 0) {
		kfree(fp);
		return err;
	}
	/* FIXME: playback must be synchronized to capture */
	usb_set_interface(chip->dev, fp->iface, 0);
	return 0;
}

static int snd_usb_create_quirk(struct snd_usb_audio *chip,
				struct usb_interface *iface,
				const struct snd_usb_audio_quirk *quirk);
@@ -3686,7 +3634,6 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
		[QUIRK_MIDI_CME] = create_any_midi_quirk,
		[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
		[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
		[QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
		[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
		[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk
	};
+1 −2
Original line number Diff line number Diff line
@@ -75,7 +75,6 @@ enum quirk_type {
	QUIRK_MIDI_US122L,
	QUIRK_AUDIO_STANDARD_INTERFACE,
	QUIRK_AUDIO_FIXED_ENDPOINT,
	QUIRK_AUDIO_EDIROL_UA1000,
	QUIRK_AUDIO_EDIROL_UAXX,
	QUIRK_AUDIO_ALIGN_TRANSFER,

@@ -112,7 +111,7 @@ struct snd_usb_midi_endpoint_info {

/* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */

/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */

/* for QUIRK_IGNORE_INTERFACE, data is NULL */

Loading