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

Commit ea70ee05 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'full-roland-support' of git://git.alsa-project.org/alsa-kprivate into for-next

For adding support for many Roland and Yamaha devices:
* 'full-roland-support' of git://git.alsa-project.org/alsa-kprivate:
  ALSA: usb-audio: add quirks for Roland QUAD/OCTO-CAPTURE
  ALSA: usb-audio: claim autodetected PCM interfaces all at once
  ALSA: usb-audio: remove superfluous Roland quirks
  ALSA: usb-audio: add MIDI port names for some Roland devices
  ALSA: usb-audio: add support for many Roland/Yamaha devices
  ALSA: usb-audio: detect implicit feedback on Roland devices
  ALSA: usb-audio: store protocol version in struct audioformat
parents ad60d502 b7f33917
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ struct audioformat {
	unsigned char endpoint;		/* endpoint */
	unsigned char ep_attr;		/* endpoint attributes */
	unsigned char datainterval;	/* log_2 of data packet interval */
	unsigned char protocol;		/* UAC_VERSION_1/2 */
	unsigned int maxpacksize;	/* max. packet size */
	unsigned int rates;		/* rate bitmasks */
	unsigned int rate_min, rate_max;	/* min/max rates */
+1 −3
Original line number Diff line number Diff line
@@ -407,9 +407,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
			     struct usb_host_interface *alts,
			     struct audioformat *fmt, int rate)
{
	struct usb_interface_descriptor *altsd = get_iface_desc(alts);

	switch (altsd->bInterfaceProtocol) {
	switch (fmt->protocol) {
	case UAC_VERSION_1:
	default:
		return set_sample_rate_v1(chip, iface, alts, fmt, rate);
+10 −24
Original line number Diff line number Diff line
@@ -43,13 +43,12 @@
 */
static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
				     struct audioformat *fp,
				     unsigned int format, void *_fmt,
				     int protocol)
				     unsigned int format, void *_fmt)
{
	int sample_width, sample_bytes;
	u64 pcm_formats = 0;

	switch (protocol) {
	switch (fp->protocol) {
	case UAC_VERSION_1:
	default: {
		struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
@@ -360,11 +359,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
 */
static int parse_audio_format_i(struct snd_usb_audio *chip,
				struct audioformat *fp, unsigned int format,
				struct uac_format_type_i_continuous_descriptor *fmt,
				struct usb_host_interface *iface)
				struct uac_format_type_i_continuous_descriptor *fmt)
{
	struct usb_interface_descriptor *altsd = get_iface_desc(iface);
	int protocol = altsd->bInterfaceProtocol;
	snd_pcm_format_t pcm_format;
	int ret;

@@ -387,8 +383,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
		}
		fp->formats = pcm_format_to_bits(pcm_format);
	} else {
		fp->formats = parse_audio_format_i_type(chip, fp, format,
							fmt, protocol);
		fp->formats = parse_audio_format_i_type(chip, fp, format, fmt);
		if (!fp->formats)
			return -EINVAL;
	}
@@ -398,11 +393,8 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
	 * proprietary class specific descriptor.
	 * audio class v2 uses class specific EP0 range requests for that.
	 */
	switch (protocol) {
	switch (fp->protocol) {
	default:
		snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n",
			   chip->dev->devnum, fp->iface, fp->altsetting, protocol);
		/* fall through */
	case UAC_VERSION_1:
		fp->channels = fmt->bNrChannels;
		ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7);
@@ -427,12 +419,9 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
 */
static int parse_audio_format_ii(struct snd_usb_audio *chip,
				 struct audioformat *fp,
				 int format, void *_fmt,
				 struct usb_host_interface *iface)
				 int format, void *_fmt)
{
	int brate, framesize, ret;
	struct usb_interface_descriptor *altsd = get_iface_desc(iface);
	int protocol = altsd->bInterfaceProtocol;

	switch (format) {
	case UAC_FORMAT_TYPE_II_AC3:
@@ -452,11 +441,8 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,

	fp->channels = 1;

	switch (protocol) {
	switch (fp->protocol) {
	default:
		snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n",
			   chip->dev->devnum, fp->iface, fp->altsetting, protocol);
		/* fall through */
	case UAC_VERSION_1: {
		struct uac_format_type_ii_discrete_descriptor *fmt = _fmt;
		brate = le16_to_cpu(fmt->wMaxBitRate);
@@ -483,17 +469,17 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
			       struct audioformat *fp, unsigned int format,
			       struct uac_format_type_i_continuous_descriptor *fmt,
			       int stream, struct usb_host_interface *iface)
			       int stream)
{
	int err;

	switch (fmt->bFormatType) {
	case UAC_FORMAT_TYPE_I:
	case UAC_FORMAT_TYPE_III:
		err = parse_audio_format_i(chip, fp, format, fmt, iface);
		err = parse_audio_format_i(chip, fp, format, fmt);
		break;
	case UAC_FORMAT_TYPE_II:
		err = parse_audio_format_ii(chip, fp, format, fmt, iface);
		err = parse_audio_format_ii(chip, fp, format, fmt);
		break;
	default:
		snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
+1 −1
Original line number Diff line number Diff line
@@ -4,6 +4,6 @@
int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
			       struct audioformat *fp, unsigned int format,
			       struct uac_format_type_i_continuous_descriptor *fmt,
			       int stream, struct usb_host_interface *iface);
			       int stream);

#endif /*  __USBAUDIO_FORMAT_H */
+74 −0
Original line number Diff line number Diff line
@@ -1575,8 +1575,41 @@ static struct port_info {
	EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"),
	EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"),
	EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"),
	/* BOSS GT-PRO */
	CONTROL_PORT(0x0582, 0x0089, 0, "%s Control"),
	/* Edirol UM-3EX */
	CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"),
	/* Roland VG-99 */
	CONTROL_PORT(0x0582, 0x00b2, 0, "%s Control"),
	EXTERNAL_PORT(0x0582, 0x00b2, 1, "%s MIDI"),
	/* Cakewalk Sonar V-Studio 100 */
	EXTERNAL_PORT(0x0582, 0x00eb, 0, "%s MIDI"),
	CONTROL_PORT(0x0582, 0x00eb, 1, "%s Control"),
	/* Roland VB-99 */
	CONTROL_PORT(0x0582, 0x0102, 0, "%s Control"),
	EXTERNAL_PORT(0x0582, 0x0102, 1, "%s MIDI"),
	/* Roland A-PRO */
	EXTERNAL_PORT(0x0582, 0x010f, 0, "%s MIDI"),
	CONTROL_PORT(0x0582, 0x010f, 1, "%s 1"),
	CONTROL_PORT(0x0582, 0x010f, 2, "%s 2"),
	/* Roland SD-50 */
	ROLAND_SYNTH_PORT(0x0582, 0x0114, 0, "%s Synth", 128),
	EXTERNAL_PORT(0x0582, 0x0114, 1, "%s MIDI"),
	CONTROL_PORT(0x0582, 0x0114, 2, "%s Control"),
	/* Roland OCTA-CAPTURE */
	EXTERNAL_PORT(0x0582, 0x0120, 0, "%s MIDI"),
	CONTROL_PORT(0x0582, 0x0120, 1, "%s Control"),
	EXTERNAL_PORT(0x0582, 0x0121, 0, "%s MIDI"),
	CONTROL_PORT(0x0582, 0x0121, 1, "%s Control"),
	/* Roland SPD-SX */
	CONTROL_PORT(0x0582, 0x0145, 0, "%s Control"),
	EXTERNAL_PORT(0x0582, 0x0145, 1, "%s MIDI"),
	/* Roland A-Series */
	CONTROL_PORT(0x0582, 0x0156, 0, "%s Keyboard"),
	EXTERNAL_PORT(0x0582, 0x0156, 1, "%s MIDI"),
	/* Roland INTEGRA-7 */
	ROLAND_SYNTH_PORT(0x0582, 0x015b, 0, "%s Synth", 128),
	CONTROL_PORT(0x0582, 0x015b, 1, "%s Control"),
	/* M-Audio MidiSport 8x8 */
	CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"),
	CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"),
@@ -1947,6 +1980,44 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
	return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
}

/*
 * Detects the endpoints and ports of Roland devices.
 */
static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi,
				     struct snd_usb_midi_endpoint_info* endpoint)
{
	struct usb_interface* intf;
	struct usb_host_interface *hostif;
	u8* cs_desc;

	intf = umidi->iface;
	if (!intf)
		return -ENOENT;
	hostif = intf->altsetting;
	/*
	 * Some devices have a descriptor <06 24 F1 02 <inputs> <outputs>>,
	 * some have standard class descriptors, or both kinds, or neither.
	 */
	for (cs_desc = hostif->extra;
	     cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
	     cs_desc += cs_desc[0]) {
		if (cs_desc[0] >= 6 &&
		    cs_desc[1] == USB_DT_CS_INTERFACE &&
		    cs_desc[2] == 0xf1 &&
		    cs_desc[3] == 0x02) {
			endpoint->in_cables  = (1 << cs_desc[4]) - 1;
			endpoint->out_cables = (1 << cs_desc[5]) - 1;
			return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
		} else if (cs_desc[0] >= 7 &&
			   cs_desc[1] == USB_DT_CS_INTERFACE &&
			   cs_desc[2] == UAC_HEADER) {
			return snd_usbmidi_get_ms_info(umidi, endpoint);
		}
	}

	return -ENODEV;
}

/*
 * Creates the endpoints and their ports for Midiman devices.
 */
@@ -2162,6 +2233,9 @@ int snd_usbmidi_create(struct snd_card *card,
	case QUIRK_MIDI_YAMAHA:
		err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
		break;
	case QUIRK_MIDI_ROLAND:
		err = snd_usbmidi_detect_roland(umidi, &endpoints[0]);
		break;
	case QUIRK_MIDI_MIDIMAN:
		umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
		memcpy(&endpoints[0], quirk->data,
Loading