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

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
...@@ -171,8 +171,9 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int ...@@ -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 || if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) && altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) { altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) {
int err = snd_usbmidi_create(chip->card, iface, int err = __snd_usbmidi_create(chip->card, iface,
&chip->midi_list, NULL); &chip->midi_list, NULL,
chip->usb_id);
if (err < 0) { if (err < 0) {
dev_err(&dev->dev, dev_err(&dev->dev,
"%u:%d: cannot create sequencer device\n", "%u:%d: cannot create sequencer device\n",
...@@ -311,6 +312,7 @@ static int snd_usb_audio_free(struct snd_usb_audio *chip) ...@@ -311,6 +312,7 @@ static int snd_usb_audio_free(struct snd_usb_audio *chip)
snd_usb_endpoint_free(ep); snd_usb_endpoint_free(ep);
mutex_destroy(&chip->mutex); mutex_destroy(&chip->mutex);
dev_set_drvdata(&chip->dev->dev, NULL);
kfree(chip); kfree(chip);
return 0; return 0;
} }
...@@ -484,7 +486,7 @@ static int usb_audio_probe(struct usb_interface *intf, ...@@ -484,7 +486,7 @@ static int usb_audio_probe(struct usb_interface *intf,
if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
return -ENXIO; return -ENXIO;
err = snd_usb_apply_boot_quirk(dev, intf, quirk); err = snd_usb_apply_boot_quirk(dev, intf, quirk, id);
if (err < 0) if (err < 0)
return err; return err;
...@@ -503,6 +505,7 @@ static int usb_audio_probe(struct usb_interface *intf, ...@@ -503,6 +505,7 @@ static int usb_audio_probe(struct usb_interface *intf,
goto __error; goto __error;
} }
chip = usb_chip[i]; chip = usb_chip[i];
dev_set_drvdata(&dev->dev, chip);
atomic_inc(&chip->active); /* avoid autopm */ atomic_inc(&chip->active); /* avoid autopm */
break; break;
} }
......
...@@ -2320,10 +2320,11 @@ EXPORT_SYMBOL(snd_usbmidi_resume); ...@@ -2320,10 +2320,11 @@ EXPORT_SYMBOL(snd_usbmidi_resume);
/* /*
* Creates and registers everything needed for a MIDI streaming interface. * 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 usb_interface *iface,
struct list_head *midi_list, 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 *umidi;
struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS]; struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS];
...@@ -2341,8 +2342,10 @@ int snd_usbmidi_create(struct snd_card *card, ...@@ -2341,8 +2342,10 @@ int snd_usbmidi_create(struct snd_card *card,
spin_lock_init(&umidi->disc_lock); spin_lock_init(&umidi->disc_lock);
init_rwsem(&umidi->disc_rwsem); init_rwsem(&umidi->disc_rwsem);
mutex_init(&umidi->mutex); 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)); le16_to_cpu(umidi->dev->descriptor.idProduct));
umidi->usb_id = usb_id;
setup_timer(&umidi->error_timer, snd_usbmidi_error_timer, setup_timer(&umidi->error_timer, snd_usbmidi_error_timer,
(unsigned long)umidi); (unsigned long)umidi);
...@@ -2464,4 +2467,4 @@ int snd_usbmidi_create(struct snd_card *card, ...@@ -2464,4 +2467,4 @@ int snd_usbmidi_create(struct snd_card *card,
list_add_tail(&umidi->list, midi_list); list_add_tail(&umidi->list, midi_list);
return 0; return 0;
} }
EXPORT_SYMBOL(snd_usbmidi_create); EXPORT_SYMBOL(__snd_usbmidi_create);
...@@ -39,10 +39,20 @@ struct snd_usb_midi_endpoint_info { ...@@ -39,10 +39,20 @@ struct snd_usb_midi_endpoint_info {
/* for QUIRK_MIDI_AKAI, data is NULL */ /* 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,
unsigned int usb_id);
static inline int snd_usbmidi_create(struct snd_card *card,
struct usb_interface *iface, struct usb_interface *iface,
struct list_head *midi_list, struct list_head *midi_list,
const struct snd_usb_audio_quirk *quirk); 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_stop(struct list_head *p);
void snd_usbmidi_input_start(struct list_head *p); void snd_usbmidi_input_start(struct list_head *p);
void snd_usbmidi_disconnect(struct list_head *p); void snd_usbmidi_disconnect(struct list_head *p);
......
...@@ -446,8 +446,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, ...@@ -446,8 +446,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
const struct snd_usb_audio_quirk *quirk = const struct snd_usb_audio_quirk *quirk =
chip->usb_id == USB_ID(0x0582, 0x002b) chip->usb_id == USB_ID(0x0582, 0x002b)
? &ua700_quirk : &uaxx_quirk; ? &ua700_quirk : &uaxx_quirk;
return snd_usbmidi_create(chip->card, iface, return __snd_usbmidi_create(chip->card, iface,
&chip->midi_list, quirk); &chip->midi_list, quirk,
chip->usb_id);
} }
if (altsd->bNumEndpoints != 1) if (altsd->bNumEndpoints != 1)
...@@ -974,11 +975,9 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, ...@@ -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, int snd_usb_apply_boot_quirk(struct usb_device *dev,
struct usb_interface *intf, 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) { switch (id) {
case USB_ID(0x041e, 0x3000): case USB_ID(0x041e, 0x3000):
/* SB Extigy needs special boot-up sequence */ /* SB Extigy needs special boot-up sequence */
...@@ -1182,7 +1181,7 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) ...@@ -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 * "Playback Design" products send bogus feedback data at the start
* of the stream. Ignore them. * 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->type == SND_USB_ENDPOINT_TYPE_SYNC)
ep->skip_packets = 4; ep->skip_packets = 4;
...@@ -1201,11 +1200,15 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) ...@@ -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) 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 * "Playback Design" products need a 50ms delay after setting the
* USB interface. * USB interface.
*/ */
switch (le16_to_cpu(dev->descriptor.idVendor)) { switch (USB_ID_VENDOR(chip->usb_id)) {
case 0x23ba: /* Playback Design */ case 0x23ba: /* Playback Design */
case 0x0644: /* TEAC Corp. */ case 0x0644: /* TEAC Corp. */
mdelay(50); mdelay(50);
...@@ -1213,15 +1216,20 @@ void snd_usb_set_interface_quirk(struct usb_device *dev) ...@@ -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, void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
__u8 request, __u8 requesttype, __u16 value, __u8 request, __u8 requesttype, __u16 value,
__u16 index, void *data, __u16 size) __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 * "Playback Design" products need a 20ms delay after each
* class compliant request * 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) (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
mdelay(20); mdelay(20);
...@@ -1229,23 +1237,21 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, ...@@ -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 * "TEAC Corp." products need a 20ms delay after each
* class compliant request * 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) (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
mdelay(20); mdelay(20);
/* Marantz/Denon devices with USB DAC functionality need a delay /* Marantz/Denon devices with USB DAC functionality need a delay
* after each class compliant request * after each class compliant request
*/ */
if (is_marantz_denon_dac(USB_ID(le16_to_cpu(dev->descriptor.idVendor), if (is_marantz_denon_dac(chip->usb_id)
le16_to_cpu(dev->descriptor.idProduct)))
&& (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
mdelay(20); mdelay(20);
/* Zoom R16/24 needs a tiny delay here, otherwise requests like /* Zoom R16/24 needs a tiny delay here, otherwise requests like
* get/set frequency return as failed despite actually succeeding. * get/set frequency return as failed despite actually succeeding.
*/ */
if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1686) && if (chip->usb_id == USB_ID(0x1686, 0x00dd) &&
(le16_to_cpu(dev->descriptor.idProduct) == 0x00dd) &&
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
mdelay(1); mdelay(1);
} }
...@@ -1262,7 +1268,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, ...@@ -1262,7 +1268,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
unsigned int sample_bytes) unsigned int sample_bytes)
{ {
/* Playback Designs */ /* Playback Designs */
if (le16_to_cpu(chip->dev->descriptor.idVendor) == 0x23ba) { if (USB_ID_VENDOR(chip->usb_id) == 0x23ba) {
switch (fp->altsetting) { switch (fp->altsetting) {
case 1: case 1:
fp->dsd_dop = true; fp->dsd_dop = true;
......
...@@ -16,7 +16,8 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, ...@@ -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, int snd_usb_apply_boot_quirk(struct usb_device *dev,
struct usb_interface *intf, 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, void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
struct audioformat *fmt); struct audioformat *fmt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment