Merge tag 'sound-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "After a heavy storm by syzkaller in 4.5 cycle, we have relatively few changes in the core at this time while a lot of changes are found in the driver side, unsurprisingly. Below are some highlights: ALSA core: - A few more hardening in ALSA timer codes - An extension of sequencer API for advertising the card / pid - Small fixes in compress-offload and jack layers HD-audio: - Dynamic PCM assignment in HDMI/DP codec; preparation for upcoming DP-MST support - Lots of code refactoring for sharing with ASoC SKL driver - Regression fixes for Intel HDMI/DP - Fixups for CX20724 codec, Lenovo AiO USB-audio: - Add quirk_alias option to make quirk debugging easier - Fixes for possible Oops by malformed firmware Firewire: - Add support for FW-1804 in tascam driver - Improvements / changes in card registration, multi stream handling, etc for DICE - Lots of code refactoring ASoC: - Enhancements of still ongoing topology API - Lots of commits for Intel Skylake support including HDMI support - A few Intel Atom driver updates for recent devices - Lots of improvements to the Renesas drivers - Capture support for Qualcomm drivers - Support for TI DaVinci DRA7xxx devices - New machine drivers for Freescale systems with Cirrus CODECs, Mediatek systems with RT5650 CODECs - New CPU drivers for Allwinner S/PDIF controllers - New CODEC drivers for Maxim MAX9867 and MAX98926 and Realtek RT5514" * tag 'sound-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (291 commits) ALSA: hda - Fix mutex deadlock at HDMI/DP hotplug ALSA: ctl: change return value in compatibility layer so that it's the same value in core implementation ALSA: mixart: silence an uninitialized variable warning ALSA: usb-audio: Add sanity checks for endpoint accesses ALSA: usb-audio: Minor code cleanup in create_fixed_stream_quirk() ALSA: usb-audio: Fix NULL dereference in create_fixed_stream_quirk() ALSA: hda - Limit i915 HDMI binding only for HSW and later ALSA: hda - Fix unconditional GPIO toggle via automute ALSA: mixart: silence unitialized variable warnings ALSA: hda - Fixes double fault in nvhdmi_chmap_cea_alloc_validate_get_type ALSA: intel8x0: Add clock quirk entry for AD1981B on IBM ThinkPad X41. ALSA: hda - Add new GPU codec ID 0x10de0082 to snd-hda ASoC: rsnd: add simplified module explanation ASoC: hdac_hdmi: Add broxton device ID ASoC: Intel: Bxtn: Add Broxton PCI ID ASoC: Intel: Skylake: Move Skylake dsp ops & loader ops ASoC: Intel: add dmabuffer to common sst_dsp ASoC: Intel: Skylake: Unstatify skl_dsp_enable_core ASoC: Intel: Skylake: Fix whitepsace issues ASoC: Intel: Skylake: Move module id defines ...
This commit is contained in:
@@ -83,6 +83,7 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
|
||||
static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
|
||||
static bool ignore_ctl_error;
|
||||
static bool autoclock = true;
|
||||
static char *quirk_alias[SNDRV_CARDS];
|
||||
|
||||
module_param_array(index, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
|
||||
@@ -101,6 +102,8 @@ MODULE_PARM_DESC(ignore_ctl_error,
|
||||
"Ignore errors from USB controller for mixer interfaces.");
|
||||
module_param(autoclock, bool, 0444);
|
||||
MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");
|
||||
module_param_array(quirk_alias, charp, NULL, 0444);
|
||||
MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");
|
||||
|
||||
/*
|
||||
* we keep the snd_usb_audio_t instances by ourselves for merging
|
||||
@@ -172,8 +175,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",
|
||||
@@ -312,6 +316,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;
|
||||
}
|
||||
@@ -456,6 +461,48 @@ static int snd_usb_audio_create(struct usb_interface *intf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* look for a matching quirk alias id */
|
||||
static bool get_alias_id(struct usb_device *dev, unsigned int *id)
|
||||
{
|
||||
int i;
|
||||
unsigned int src, dst;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(quirk_alias); i++) {
|
||||
if (!quirk_alias[i] ||
|
||||
sscanf(quirk_alias[i], "%x:%x", &src, &dst) != 2 ||
|
||||
src != *id)
|
||||
continue;
|
||||
dev_info(&dev->dev,
|
||||
"device (%04x:%04x): applying quirk alias %04x:%04x\n",
|
||||
USB_ID_VENDOR(*id), USB_ID_PRODUCT(*id),
|
||||
USB_ID_VENDOR(dst), USB_ID_PRODUCT(dst));
|
||||
*id = dst;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct usb_device_id usb_audio_ids[]; /* defined below */
|
||||
|
||||
/* look for the corresponding quirk */
|
||||
static const struct snd_usb_audio_quirk *
|
||||
get_alias_quirk(struct usb_device *dev, unsigned int id)
|
||||
{
|
||||
const struct usb_device_id *p;
|
||||
|
||||
for (p = usb_audio_ids; p->match_flags; p++) {
|
||||
/* FIXME: this checks only vendor:product pair in the list */
|
||||
if ((p->match_flags & USB_DEVICE_ID_MATCH_DEVICE) ==
|
||||
USB_DEVICE_ID_MATCH_DEVICE &&
|
||||
p->idVendor == USB_ID_VENDOR(id) &&
|
||||
p->idProduct == USB_ID_PRODUCT(id))
|
||||
return (const struct snd_usb_audio_quirk *)p->driver_info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* probe the active usb device
|
||||
*
|
||||
@@ -482,10 +529,12 @@ static int usb_audio_probe(struct usb_interface *intf,
|
||||
ifnum = get_iface_desc(alts)->bInterfaceNumber;
|
||||
id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
|
||||
le16_to_cpu(dev->descriptor.idProduct));
|
||||
if (get_alias_id(dev, &id))
|
||||
quirk = get_alias_quirk(dev, id);
|
||||
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;
|
||||
|
||||
@@ -504,6 +553,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;
|
||||
}
|
||||
|
@@ -285,6 +285,8 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
|
||||
unsigned char data[3];
|
||||
int err, crate;
|
||||
|
||||
if (get_iface_desc(alts)->bNumEndpoints < 1)
|
||||
return -EINVAL;
|
||||
ep = get_endpoint(alts, 0)->bEndpointAddress;
|
||||
|
||||
/* if endpoint doesn't have sampling rate control, bail out */
|
||||
|
@@ -438,6 +438,9 @@ exit_clear:
|
||||
*
|
||||
* New endpoints will be added to chip->ep_list and must be freed by
|
||||
* calling snd_usb_endpoint_free().
|
||||
*
|
||||
* For SND_USB_ENDPOINT_TYPE_SYNC, the caller needs to guarantee that
|
||||
* bNumEndpoints > 1 beforehand.
|
||||
*/
|
||||
struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
|
||||
struct usb_host_interface *alts,
|
||||
|
@@ -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,
|
||||
struct usb_interface *iface,
|
||||
struct list_head *midi_list,
|
||||
const struct snd_usb_audio_quirk *quirk)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -2463,4 +2466,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);
|
||||
|
@@ -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,
|
||||
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);
|
||||
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);
|
||||
|
@@ -1519,7 +1519,11 @@ static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol,
|
||||
|
||||
/* use known values for that card: interface#1 altsetting#1 */
|
||||
iface = usb_ifnum_to_if(chip->dev, 1);
|
||||
if (!iface || iface->num_altsetting < 2)
|
||||
return -EINVAL;
|
||||
alts = &iface->altsetting[1];
|
||||
if (get_iface_desc(alts)->bNumEndpoints < 1)
|
||||
return -EINVAL;
|
||||
ep = get_endpoint(alts, 0)->bEndpointAddress;
|
||||
|
||||
err = snd_usb_ctl_msg(chip->dev,
|
||||
|
@@ -160,6 +160,8 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
|
||||
unsigned char data[1];
|
||||
int err;
|
||||
|
||||
if (get_iface_desc(alts)->bNumEndpoints < 1)
|
||||
return -EINVAL;
|
||||
ep = get_endpoint(alts, 0)->bEndpointAddress;
|
||||
|
||||
data[0] = 1;
|
||||
|
@@ -167,19 +167,20 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
|
||||
stream = (fp->endpoint & USB_DIR_IN)
|
||||
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
|
||||
err = snd_usb_add_audio_stream(chip, stream, fp);
|
||||
if (err < 0) {
|
||||
kfree(fp);
|
||||
kfree(rate_table);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
goto error;
|
||||
if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber ||
|
||||
fp->altset_idx >= iface->num_altsetting) {
|
||||
kfree(fp);
|
||||
kfree(rate_table);
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
alts = &iface->altsetting[fp->altset_idx];
|
||||
altsd = get_iface_desc(alts);
|
||||
if (altsd->bNumEndpoints < 1) {
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
fp->protocol = altsd->bInterfaceProtocol;
|
||||
|
||||
if (fp->datainterval == 0)
|
||||
@@ -190,6 +191,11 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
|
||||
snd_usb_init_pitch(chip, fp->iface, alts, fp);
|
||||
snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(fp);
|
||||
kfree(rate_table);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int create_auto_pcm_quirk(struct snd_usb_audio *chip,
|
||||
@@ -446,8 +452,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 +981,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 */
|
||||
@@ -1184,7 +1189,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;
|
||||
|
||||
@@ -1203,11 +1208,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);
|
||||
@@ -1215,15 +1224,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);
|
||||
|
||||
@@ -1231,23 +1245,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);
|
||||
}
|
||||
@@ -1264,7 +1276,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;
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user