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

Commit 79289e24 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: usb-audio: Refer to chip->usb_id for quirks and MIDI creation



This is a preliminary patch for the later change to allow a better
quirk ID management.  In the current USB-audio code, there are a few
places looking at usb_device idVendor and idProduct fields directly
even though we have already a static member in snd_usb_audio.usb_id.
This patch modifies such codes to refer to the latter field.

For achieving this, two slightly intensive changes have been done:
- The snd_usb_audio object is set/reset via dev_getdrv() for the given
  USB device; it's needed for minimizing the changes for some existing
  quirks that take only usb_device object.

- __snd_usbmidi_create() is introduced to receive the pre-given usb_id
  argument.  The exported snd_usbmidi_create() is unchanged by calling
  this new function internally.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 3ec622f4
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -171,8 +171,9 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
	if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
	     altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
	    altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) {
		int err = snd_usbmidi_create(chip->card, iface,
					     &chip->midi_list, NULL);
		int err = __snd_usbmidi_create(chip->card, iface,
					     &chip->midi_list, NULL,
					     chip->usb_id);
		if (err < 0) {
			dev_err(&dev->dev,
				"%u:%d: cannot create sequencer device\n",
@@ -311,6 +312,7 @@ static int snd_usb_audio_free(struct snd_usb_audio *chip)
		snd_usb_endpoint_free(ep);

	mutex_destroy(&chip->mutex);
	dev_set_drvdata(&chip->dev->dev, NULL);
	kfree(chip);
	return 0;
}
@@ -484,7 +486,7 @@ static int usb_audio_probe(struct usb_interface *intf,
	if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
		return -ENXIO;

	err = snd_usb_apply_boot_quirk(dev, intf, quirk);
	err = snd_usb_apply_boot_quirk(dev, intf, quirk, id);
	if (err < 0)
		return err;

@@ -503,6 +505,7 @@ static int usb_audio_probe(struct usb_interface *intf,
				goto __error;
			}
			chip = usb_chip[i];
			dev_set_drvdata(&dev->dev, chip);
			atomic_inc(&chip->active); /* avoid autopm */
			break;
		}
+9 −6
Original line number Diff line number Diff line
@@ -2320,10 +2320,11 @@ EXPORT_SYMBOL(snd_usbmidi_resume);
/*
 * Creates and registers everything needed for a MIDI streaming interface.
 */
int snd_usbmidi_create(struct snd_card *card,
int __snd_usbmidi_create(struct snd_card *card,
			 struct usb_interface *iface,
			 struct list_head *midi_list,
		       const struct snd_usb_audio_quirk *quirk)
			 const struct snd_usb_audio_quirk *quirk,
			 unsigned int usb_id)
{
	struct snd_usb_midi *umidi;
	struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS];
@@ -2341,8 +2342,10 @@ int snd_usbmidi_create(struct snd_card *card,
	spin_lock_init(&umidi->disc_lock);
	init_rwsem(&umidi->disc_rwsem);
	mutex_init(&umidi->mutex);
	umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
	if (!usb_id)
		usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
			       le16_to_cpu(umidi->dev->descriptor.idProduct));
	umidi->usb_id = usb_id;
	setup_timer(&umidi->error_timer, snd_usbmidi_error_timer,
		    (unsigned long)umidi);

@@ -2464,4 +2467,4 @@ int snd_usbmidi_create(struct snd_card *card,
	list_add_tail(&umidi->list, midi_list);
	return 0;
}
EXPORT_SYMBOL(snd_usbmidi_create);
EXPORT_SYMBOL(__snd_usbmidi_create);
+12 −2
Original line number Diff line number Diff line
@@ -39,10 +39,20 @@ struct snd_usb_midi_endpoint_info {

/* for QUIRK_MIDI_AKAI, data is NULL */

int snd_usbmidi_create(struct snd_card *card,
int __snd_usbmidi_create(struct snd_card *card,
			 struct usb_interface *iface,
			 struct list_head *midi_list,
		       const struct snd_usb_audio_quirk *quirk);
			 const struct snd_usb_audio_quirk *quirk,
			 unsigned int usb_id);

static inline int snd_usbmidi_create(struct snd_card *card,
		       struct usb_interface *iface,
		       struct list_head *midi_list,
		       const struct snd_usb_audio_quirk *quirk)
{
	return __snd_usbmidi_create(card, iface, midi_list, quirk, 0);
}

void snd_usbmidi_input_stop(struct list_head *p);
void snd_usbmidi_input_start(struct list_head *p);
void snd_usbmidi_disconnect(struct list_head *p);
+21 −15
Original line number Diff line number Diff line
@@ -446,8 +446,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
		const struct snd_usb_audio_quirk *quirk =
			chip->usb_id == USB_ID(0x0582, 0x002b)
			? &ua700_quirk : &uaxx_quirk;
		return snd_usbmidi_create(chip->card, iface,
					  &chip->midi_list, quirk);
		return __snd_usbmidi_create(chip->card, iface,
					  &chip->midi_list, quirk,
					  chip->usb_id);
	}

	if (altsd->bNumEndpoints != 1)
@@ -974,11 +975,9 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,

int snd_usb_apply_boot_quirk(struct usb_device *dev,
			     struct usb_interface *intf,
			     const struct snd_usb_audio_quirk *quirk)
			     const struct snd_usb_audio_quirk *quirk,
			     unsigned int id)
{
	u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
			le16_to_cpu(dev->descriptor.idProduct));

	switch (id) {
	case USB_ID(0x041e, 0x3000):
		/* SB Extigy needs special boot-up sequence */
@@ -1182,7 +1181,7 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
	 * "Playback Design" products send bogus feedback data at the start
	 * of the stream. Ignore them.
	 */
	if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) &&
	if (USB_ID_VENDOR(ep->chip->usb_id) == 0x23ba &&
	    ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
		ep->skip_packets = 4;

@@ -1201,11 +1200,15 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)

void snd_usb_set_interface_quirk(struct usb_device *dev)
{
	struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev);

	if (!chip)
		return;
	/*
	 * "Playback Design" products need a 50ms delay after setting the
	 * USB interface.
	 */
	switch (le16_to_cpu(dev->descriptor.idVendor)) {
	switch (USB_ID_VENDOR(chip->usb_id)) {
	case 0x23ba: /* Playback Design */
	case 0x0644: /* TEAC Corp. */
		mdelay(50);
@@ -1213,15 +1216,20 @@ void snd_usb_set_interface_quirk(struct usb_device *dev)
	}
}

/* quirk applied after snd_usb_ctl_msg(); not applied during boot quirks */
void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
			   __u8 request, __u8 requesttype, __u16 value,
			   __u16 index, void *data, __u16 size)
{
	struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev);

	if (!chip)
		return;
	/*
	 * "Playback Design" products need a 20ms delay after each
	 * class compliant request
	 */
	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) &&
	if (USB_ID_VENDOR(chip->usb_id) == 0x23ba &&
	    (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
		mdelay(20);

@@ -1229,23 +1237,21 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
	 * "TEAC Corp." products need a 20ms delay after each
	 * class compliant request
	 */
	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0644) &&
	if (USB_ID_VENDOR(chip->usb_id) == 0x0644 &&
	    (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
		mdelay(20);

	/* Marantz/Denon devices with USB DAC functionality need a delay
	 * after each class compliant request
	 */
	if (is_marantz_denon_dac(USB_ID(le16_to_cpu(dev->descriptor.idVendor),
					le16_to_cpu(dev->descriptor.idProduct)))
	if (is_marantz_denon_dac(chip->usb_id)
	    && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
		mdelay(20);

	/* Zoom R16/24 needs a tiny delay here, otherwise requests like
	 * get/set frequency return as failed despite actually succeeding.
	 */
	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1686) &&
	    (le16_to_cpu(dev->descriptor.idProduct) == 0x00dd) &&
	if (chip->usb_id == USB_ID(0x1686, 0x00dd) &&
	    (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
		mdelay(1);
}
@@ -1262,7 +1268,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
					unsigned int sample_bytes)
{
	/* Playback Designs */
	if (le16_to_cpu(chip->dev->descriptor.idVendor) == 0x23ba) {
	if (USB_ID_VENDOR(chip->usb_id) == 0x23ba) {
		switch (fp->altsetting) {
		case 1:
			fp->dsd_dop = true;
+2 −1
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,

int snd_usb_apply_boot_quirk(struct usb_device *dev,
			     struct usb_interface *intf,
			     const struct snd_usb_audio_quirk *quirk);
			     const struct snd_usb_audio_quirk *quirk,
			     unsigned int usb_id);

void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
			      struct audioformat *fmt);