Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (26 commits) ALSA: snd-usb-caiaq: Bump version number to 1.3.21 ALSA: Revert "ALSA: snd-usb-caiaq: Set default input mode of A4DJ" ALSA: snd-usb-caiaq: Simplify single case to an 'if' ALSA: snd-usb-caiaq: Restore 'Control vinyl' input mode on A4DJ ALSA: hda: Use LPIB for a Shuttle device ALSA: hda: Add support for another Lenovo ThinkPad Edge in conexant codec ALSA: hda: Use LPIB for Sony VPCS11V9E ALSA: usb-audio: fix feature unit parser for UAC2 ALSA: asihpi - Minor code cleanup ALSA: asihpi - Add support for new ASI8800 family ALSA: asihpi - Fix bug preventing outstream_write preload from happening ALSA: asihpi - Fix imbalanced lock path in hw_message ALSA: asihpi - Remove support for old ASI8800 family ALSA: asihpi - Add hd radio blend functions ALSA: asihpi - Remove unused io map functions ALSA: usb-audio: add support for UAC2 pitch control ALSA: usb-audio: parse UAC2 endpoint descriptors correctly ALSA: usb-audio: fix return values ALSA: usb-audio: parse more format descriptors with structs sound: Add missing spin_unlock ...
Este commit está contenido en:
@@ -42,8 +42,9 @@ static int control_info(struct snd_kcontrol *kcontrol,
|
||||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
|
||||
if (pos == 0) {
|
||||
/* current input mode of A8DJ */
|
||||
/* current input mode of A8DJ and A4DJ */
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = 2;
|
||||
@@ -51,16 +52,6 @@ static int control_info(struct snd_kcontrol *kcontrol,
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
|
||||
if (pos == 0) {
|
||||
/* current input mode of A4DJ */
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = 1;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
maxval = 127;
|
||||
break;
|
||||
@@ -86,14 +77,6 @@ static int control_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
|
||||
int pos = kcontrol->private_value;
|
||||
|
||||
if (dev->chip.usb_id ==
|
||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) {
|
||||
/* A4DJ has only one control */
|
||||
/* do not expose hardware input mode 0 */
|
||||
ucontrol->value.integer.value[0] = dev->control_state[0] - 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos & CNT_INTVAL)
|
||||
ucontrol->value.integer.value[0]
|
||||
= dev->control_state[pos & ~CNT_INTVAL];
|
||||
@@ -112,20 +95,9 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
||||
int pos = kcontrol->private_value;
|
||||
unsigned char cmd = EP1_CMD_WRITE_IO;
|
||||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): {
|
||||
/* A4DJ has only one control */
|
||||
/* do not expose hardware input mode 0 */
|
||||
dev->control_state[0] = ucontrol->value.integer.value[0] + 1;
|
||||
snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
|
||||
dev->control_state, sizeof(dev->control_state));
|
||||
return 1;
|
||||
}
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
if (dev->chip.usb_id ==
|
||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1))
|
||||
cmd = EP1_CMD_DIMM_LEDS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pos & CNT_INTVAL) {
|
||||
dev->control_state[pos & ~CNT_INTVAL]
|
||||
|
@@ -36,7 +36,7 @@
|
||||
#include "input.h"
|
||||
|
||||
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
|
||||
MODULE_DESCRIPTION("caiaq USB audio, version 1.3.20");
|
||||
MODULE_DESCRIPTION("caiaq USB audio, version 1.3.21");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
|
||||
"{Native Instruments, RigKontrol3},"
|
||||
@@ -320,12 +320,6 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev)
|
||||
}
|
||||
|
||||
break;
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
|
||||
/* Audio 4 DJ - default input mode to phono */
|
||||
dev->control_state[0] = 2;
|
||||
snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
|
||||
dev->control_state, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->spec.num_analog_audio_out +
|
||||
|
@@ -149,6 +149,47 @@ int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct au
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
|
||||
struct usb_host_interface *alts,
|
||||
int protocol, int iface_no)
|
||||
{
|
||||
/* parsed with a v1 header here. that's ok as we only look at the
|
||||
* header first which is the same for both versions */
|
||||
struct uac_iso_endpoint_descriptor *csep;
|
||||
struct usb_interface_descriptor *altsd = get_iface_desc(alts);
|
||||
int attributes = 0;
|
||||
|
||||
csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
|
||||
|
||||
/* Creamware Noah has this descriptor after the 2nd endpoint */
|
||||
if (!csep && altsd->bNumEndpoints >= 2)
|
||||
csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
|
||||
|
||||
if (!csep || csep->bLength < 7 ||
|
||||
csep->bDescriptorSubtype != UAC_EP_GENERAL) {
|
||||
snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
|
||||
" class specific endpoint descriptor\n",
|
||||
chip->dev->devnum, iface_no,
|
||||
altsd->bAlternateSetting);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (protocol == UAC_VERSION_1) {
|
||||
attributes = csep->bmAttributes;
|
||||
} else {
|
||||
struct uac2_iso_endpoint_descriptor *csep2 =
|
||||
(struct uac2_iso_endpoint_descriptor *) csep;
|
||||
|
||||
attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
|
||||
|
||||
/* emulate the endpoint attributes of a v1 device */
|
||||
if (csep2->bmControls & UAC2_CONTROL_PITCH)
|
||||
attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
||||
{
|
||||
struct usb_device *dev;
|
||||
@@ -158,8 +199,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
||||
int i, altno, err, stream;
|
||||
int format = 0, num_channels = 0;
|
||||
struct audioformat *fp = NULL;
|
||||
unsigned char *fmt, *csep;
|
||||
int num, protocol;
|
||||
struct uac_format_type_i_continuous_descriptor *fmt;
|
||||
|
||||
dev = chip->dev;
|
||||
|
||||
@@ -256,8 +297,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
||||
dev->devnum, iface_no, altno);
|
||||
continue;
|
||||
}
|
||||
if (((protocol == UAC_VERSION_1) && (fmt[0] < 8)) ||
|
||||
((protocol == UAC_VERSION_2) && (fmt[0] != 6))) {
|
||||
if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
|
||||
((protocol == UAC_VERSION_2) && (fmt->bLength != 6))) {
|
||||
snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
|
||||
dev->devnum, iface_no, altno);
|
||||
continue;
|
||||
@@ -268,7 +309,9 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
||||
* with the previous one, except for a larger packet size, but
|
||||
* is actually a mislabeled two-channel setting; ignore it.
|
||||
*/
|
||||
if (fmt[4] == 1 && fmt[5] == 2 && altno == 2 && num == 3 &&
|
||||
if (fmt->bNrChannels == 1 &&
|
||||
fmt->bSubframeSize == 2 &&
|
||||
altno == 2 && num == 3 &&
|
||||
fp && fp->altsetting == 1 && fp->channels == 1 &&
|
||||
fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
|
||||
protocol == UAC_VERSION_1 &&
|
||||
@@ -276,17 +319,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
||||
fp->maxpacksize * 2)
|
||||
continue;
|
||||
|
||||
csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
|
||||
/* Creamware Noah has this descriptor after the 2nd endpoint */
|
||||
if (!csep && altsd->bNumEndpoints >= 2)
|
||||
csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
|
||||
if (!csep || csep[0] < 7 || csep[2] != UAC_EP_GENERAL) {
|
||||
snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
|
||||
" class specific endpoint descriptor\n",
|
||||
dev->devnum, iface_no, altno);
|
||||
csep = NULL;
|
||||
}
|
||||
|
||||
fp = kzalloc(sizeof(*fp), GFP_KERNEL);
|
||||
if (! fp) {
|
||||
snd_printk(KERN_ERR "cannot malloc\n");
|
||||
@@ -305,7 +337,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
||||
if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
|
||||
fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
|
||||
* (fp->maxpacksize & 0x7ff);
|
||||
fp->attributes = csep ? csep[3] : 0;
|
||||
fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
|
||||
|
||||
/* some quirks for attributes here */
|
||||
|
||||
|
@@ -278,12 +278,11 @@ err:
|
||||
* parse the format type I and III descriptors
|
||||
*/
|
||||
static int parse_audio_format_i(struct snd_usb_audio *chip,
|
||||
struct audioformat *fp,
|
||||
int format, void *_fmt,
|
||||
struct audioformat *fp, int format,
|
||||
struct uac_format_type_i_continuous_descriptor *fmt,
|
||||
struct usb_host_interface *iface)
|
||||
{
|
||||
struct usb_interface_descriptor *altsd = get_iface_desc(iface);
|
||||
struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
|
||||
int protocol = altsd->bInterfaceProtocol;
|
||||
int pcm_format, ret;
|
||||
|
||||
@@ -320,7 +319,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
|
||||
switch (protocol) {
|
||||
case UAC_VERSION_1:
|
||||
fp->channels = fmt->bNrChannels;
|
||||
ret = parse_audio_format_rates_v1(chip, fp, _fmt, 7);
|
||||
ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7);
|
||||
break;
|
||||
case UAC_VERSION_2:
|
||||
/* fp->channels is already set in this case */
|
||||
@@ -392,12 +391,12 @@ 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,
|
||||
int format, unsigned char *fmt, int stream,
|
||||
struct usb_host_interface *iface)
|
||||
int format, struct uac_format_type_i_continuous_descriptor *fmt,
|
||||
int stream, struct usb_host_interface *iface)
|
||||
{
|
||||
int err;
|
||||
|
||||
switch (fmt[3]) {
|
||||
switch (fmt->bFormatType) {
|
||||
case UAC_FORMAT_TYPE_I:
|
||||
case UAC_FORMAT_TYPE_III:
|
||||
err = parse_audio_format_i(chip, fp, format, fmt, iface);
|
||||
@@ -407,10 +406,11 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *f
|
||||
break;
|
||||
default:
|
||||
snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
|
||||
chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]);
|
||||
return -1;
|
||||
chip->dev->devnum, fp->iface, fp->altsetting,
|
||||
fmt->bFormatType);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
fp->fmt_type = fmt[3];
|
||||
fp->fmt_type = fmt->bFormatType;
|
||||
if (err < 0)
|
||||
return err;
|
||||
#if 1
|
||||
@@ -421,10 +421,10 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *f
|
||||
if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
|
||||
chip->usb_id == USB_ID(0x041e, 0x3020) ||
|
||||
chip->usb_id == USB_ID(0x041e, 0x3061)) {
|
||||
if (fmt[3] == UAC_FORMAT_TYPE_I &&
|
||||
if (fmt->bFormatType == UAC_FORMAT_TYPE_I &&
|
||||
fp->rates != SNDRV_PCM_RATE_48000 &&
|
||||
fp->rates != SNDRV_PCM_RATE_96000)
|
||||
return -1;
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
@@ -1,8 +1,9 @@
|
||||
#ifndef __USBAUDIO_FORMAT_H
|
||||
#define __USBAUDIO_FORMAT_H
|
||||
|
||||
int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp,
|
||||
int format, unsigned char *fmt, int stream,
|
||||
struct usb_host_interface *iface);
|
||||
int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
|
||||
struct audioformat *fp, int format,
|
||||
struct uac_format_type_i_continuous_descriptor *fmt,
|
||||
int stream, struct usb_host_interface *iface);
|
||||
|
||||
#endif /* __USBAUDIO_FORMAT_H */
|
||||
|
@@ -1126,7 +1126,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
|
||||
} else {
|
||||
struct uac2_feature_unit_descriptor *ftr = _ftr;
|
||||
csize = 4;
|
||||
channels = (hdr->bLength - 6) / 4;
|
||||
channels = (hdr->bLength - 6) / 4 - 1;
|
||||
bmaControls = ftr->bmaControls;
|
||||
}
|
||||
|
||||
|
@@ -120,10 +120,6 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
|
||||
|
||||
ep = get_endpoint(alts, 0)->bEndpointAddress;
|
||||
|
||||
/* if endpoint doesn't have pitch control, bail out */
|
||||
if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL))
|
||||
return 0;
|
||||
|
||||
data[0] = 1;
|
||||
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
|
||||
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
|
||||
@@ -137,8 +133,32 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
|
||||
struct usb_host_interface *alts,
|
||||
struct audioformat *fmt)
|
||||
{
|
||||
struct usb_device *dev = chip->dev;
|
||||
unsigned char data[1];
|
||||
unsigned int ep;
|
||||
int err;
|
||||
|
||||
ep = get_endpoint(alts, 0)->bEndpointAddress;
|
||||
|
||||
data[0] = 1;
|
||||
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
|
||||
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
|
||||
UAC2_EP_CS_PITCH << 8, 0,
|
||||
data, sizeof(data), 1000)) < 0) {
|
||||
snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH (v2)\n",
|
||||
dev->devnum, iface, fmt->altsetting);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize the picth control and sample rate
|
||||
* initialize the pitch control and sample rate
|
||||
*/
|
||||
int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
|
||||
struct usb_host_interface *alts,
|
||||
@@ -146,13 +166,16 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
|
||||
{
|
||||
struct usb_interface_descriptor *altsd = get_iface_desc(alts);
|
||||
|
||||
/* if endpoint doesn't have pitch control, bail out */
|
||||
if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL))
|
||||
return 0;
|
||||
|
||||
switch (altsd->bInterfaceProtocol) {
|
||||
case UAC_VERSION_1:
|
||||
return init_pitch_v1(chip, iface, alts, fmt);
|
||||
|
||||
case UAC_VERSION_2:
|
||||
/* not implemented yet */
|
||||
return 0;
|
||||
return init_pitch_v2(chip, iface, alts, fmt);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
Referencia en una nueva incidencia
Block a user