Merge branch 'fix/misc' into for-linus

This commit is contained in:
Takashi Iwai 2010-05-29 21:50:33 +02:00
commit a98d3984c8
18 changed files with 170 additions and 157 deletions

View File

@ -105,6 +105,22 @@ struct uac_as_header_descriptor_v2 {
__u8 iChannelNames;
} __attribute__((packed));
/* 4.10.1.2 Class-Specific AS Isochronous Audio Data Endpoint Descriptor */
struct uac2_iso_endpoint_descriptor {
__u8 bLength; /* in bytes: 8 */
__u8 bDescriptorType; /* USB_DT_CS_ENDPOINT */
__u8 bDescriptorSubtype; /* EP_GENERAL */
__u8 bmAttributes;
__u8 bmControls;
__u8 bLockDelayUnits;
__le16 wLockDelay;
} __attribute__((packed));
#define UAC2_CONTROL_PITCH (3 << 0)
#define UAC2_CONTROL_DATA_OVERRUN (3 << 2)
#define UAC2_CONTROL_DATA_UNDERRUN (3 << 4)
/* 6.1 Interrupt Data Message */
#define UAC2_INTERRUPT_DATA_MSG_VENDOR (1 << 0)

View File

@ -516,6 +516,7 @@ get the interrupt driven case to work efficiently */
break;
if (i == 0x5000) {
printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n");
spin_unlock(&au1000->ac97_lock);
return 0;
}

View File

@ -1277,7 +1277,7 @@ static irqreturn_t AtaInterrupt(int irq, void *dummy)
* (almost) like on the TT.
*/
write_sq_ignore_int = 0;
return IRQ_HANDLED;
goto out;
}
if (!write_sq.active) {
@ -1285,7 +1285,7 @@ static irqreturn_t AtaInterrupt(int irq, void *dummy)
* the sq variables, so better don't do anything here.
*/
WAKE_UP(write_sq.sync_queue);
return IRQ_HANDLED;
goto out;
}
/* Probably ;) one frame is finished. Well, in fact it may be that a
@ -1322,6 +1322,7 @@ static irqreturn_t AtaInterrupt(int irq, void *dummy)
/* We are not playing after AtaPlay(), so there
is nothing to play any more. Wake up a process
waiting for audio output to drain. */
out:
spin_unlock(&dmasound.lock);
return IRQ_HANDLED;
}

View File

@ -50,7 +50,7 @@ i.e 3.05.02 is a development version
#define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
/* Use single digits for versions less that 10 to avoid octal. */
#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 3, 18)
#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 3, 25)
/* Library version as documented in hpi-api-versions.txt */
#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0)
@ -1632,6 +1632,12 @@ u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *pquality);
u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *pblend);
u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
u32 h_control, const u32 blend);
/****************************/
/* PADs control */
/****************************/

View File

@ -691,9 +691,6 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
case 0x6200:
boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
break;
case 0x8800:
boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x8800);
break;
default:
return HPI6000_ERROR_UNHANDLED_SUBSYS_ID;
}
@ -1775,7 +1772,6 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
u16 error = 0;
u16 dsp_index = 0;
u16 num_dsp = ((struct hpi_hw_obj *)pao->priv)->num_dsp;
hpios_dsplock_lock(pao);
if (num_dsp < 2)
dsp_index = 0;
@ -1796,6 +1792,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
}
}
}
hpios_dsplock_lock(pao);
error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
/* maybe an error response */

View File

@ -965,24 +965,17 @@ static void outstream_write(struct hpi_adapter_obj *pao,
hpi_init_response(phr, phm->object, phm->function, 0);
status = &interface->outstream_host_buffer_status[phm->obj_index];
if (phw->flag_outstream_just_reset[phm->obj_index]) {
/* Format can only change after reset. Must tell DSP. */
u16 function = phm->function;
phw->flag_outstream_just_reset[phm->obj_index] = 0;
phm->function = HPI_OSTREAM_SET_FORMAT;
hw_message(pao, phm, phr); /* send the format to the DSP */
phm->function = function;
if (phr->error)
return;
}
#if 1
if (phw->flag_outstream_just_reset[phm->obj_index]) {
/* First OutStremWrite() call following reset will write data to the
adapter's buffers, reducing delay before stream can start
adapter's buffers, reducing delay before stream can start. The DSP
takes care of setting the stream data format using format information
embedded in phm.
*/
int partial_write = 0;
unsigned int original_size = 0;
phw->flag_outstream_just_reset[phm->obj_index] = 0;
/* Send the first buffer to the DSP the old way. */
/* Limit size of first transfer - */
/* expect that this will not usually be triggered. */
@ -1012,7 +1005,6 @@ static void outstream_write(struct hpi_adapter_obj *pao,
original_size - HPI6205_SIZEOF_DATA;
phm->u.d.u.data.pb_data += HPI6205_SIZEOF_DATA;
}
#endif
space_available = outstream_get_space_available(status);
if (space_available < (long)phm->u.d.u.data.data_size) {
@ -1369,6 +1361,9 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
case HPI_ADAPTER_FAMILY_ASI(0x6500):
firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600);
break;
case HPI_ADAPTER_FAMILY_ASI(0x8800):
firmware_id = HPI_ADAPTER_FAMILY_ASI(0x8900);
break;
}
boot_code_id[1] = firmware_id;

View File

@ -232,6 +232,8 @@ enum HPI_BUSES {
#define HPI_TUNER_HDRADIO_SDK_VERSION HPI_CTL_ATTR(TUNER, 13)
/** HD Radio DSP firmware version. */
#define HPI_TUNER_HDRADIO_DSP_VERSION HPI_CTL_ATTR(TUNER, 14)
/** HD Radio signal blend (force analog, or automatic). */
#define HPI_TUNER_HDRADIO_BLEND HPI_CTL_ATTR(TUNER, 15)
/** \} */
@ -478,8 +480,10 @@ Threshold is a -ve number in units of dB/100,
/** First 2 hex digits define the adapter family */
#define HPI_ADAPTER_FAMILY_MASK 0xff00
#define HPI_MODULE_FAMILY_MASK 0xfff0
#define HPI_ADAPTER_FAMILY_ASI(f) (f & HPI_ADAPTER_FAMILY_MASK)
#define HPI_MODULE_FAMILY_ASI(f) (f & HPI_MODULE_FAMILY_MASK)
#define HPI_ADAPTER_ASI(f) (f)
/******************************************* message types */
@ -970,6 +974,7 @@ struct hpi_control_union_msg {
u32 mode;
u32 value;
} mode;
u32 blend;
} tuner;
} u;
};

View File

@ -347,20 +347,15 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
found = 0;
break;
case HPI_CONTROL_TUNER:
{
struct hpi_control_cache_single *pCT =
(struct hpi_control_cache_single *)pI;
if (phm->u.c.attribute == HPI_TUNER_FREQ)
phr->u.c.param1 = pCT->u.t.freq_ink_hz;
else if (phm->u.c.attribute == HPI_TUNER_BAND)
phr->u.c.param1 = pCT->u.t.band;
else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
&& (phm->u.c.param1 ==
HPI_TUNER_LEVEL_AVERAGE))
phr->u.c.param1 = pCT->u.t.level;
else
found = 0;
}
if (phm->u.c.attribute == HPI_TUNER_FREQ)
phr->u.c.param1 = pC->u.t.freq_ink_hz;
else if (phm->u.c.attribute == HPI_TUNER_BAND)
phr->u.c.param1 = pC->u.t.band;
else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
&& (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
phr->u.c.param1 = pC->u.t.level;
else
found = 0;
break;
case HPI_CONTROL_AESEBU_RECEIVER:
if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
@ -503,6 +498,9 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
struct hpi_control_cache_single *pC;
struct hpi_control_cache_info *pI;
if (phr->error)
return;
if (!find_control(phm, p_cache, &pI, &control_index))
return;
@ -520,8 +518,6 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
break;
case HPI_CONTROL_MULTIPLEXER:
/* mux does not return its setting on Set command. */
if (phr->error)
return;
if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
pC->u.x.source_node_type = (u16)phm->u.c.param1;
pC->u.x.source_node_index = (u16)phm->u.c.param2;
@ -529,8 +525,6 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
break;
case HPI_CONTROL_CHANNEL_MODE:
/* mode does not return its setting on Set command. */
if (phr->error)
return;
if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
pC->u.m.mode = (u16)phm->u.c.param1;
break;
@ -545,20 +539,14 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
pC->u.phantom_power.state = (u16)phm->u.c.param1;
break;
case HPI_CONTROL_AESEBU_TRANSMITTER:
if (phr->error)
return;
if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
pC->u.aes3tx.format = phm->u.c.param1;
break;
case HPI_CONTROL_AESEBU_RECEIVER:
if (phr->error)
return;
if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
pC->u.aes3rx.source = phm->u.c.param1;
break;
case HPI_CONTROL_SAMPLECLOCK:
if (phr->error)
return;
if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
pC->u.clk.source = (u16)phm->u.c.param1;
else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
@ -590,7 +578,7 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32
void hpi_free_control_cache(struct hpi_control_cache *p_cache)
{
if ((p_cache->init) && (p_cache->p_info)) {
if (p_cache->init) {
kfree(p_cache->p_info);
p_cache->p_info = NULL;
p_cache->init = 0;

View File

@ -2946,6 +2946,20 @@ u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
HPI_TUNER_HDRADIO_SIGNAL_QUALITY, 0, 0, pquality, NULL);
}
u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *pblend)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_TUNER_HDRADIO_BLEND, 0, 0, pblend, NULL);
}
u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
u32 h_control, const u32 blend)
{
return hpi_control_param_set(ph_subsys, h_control,
HPI_TUNER_HDRADIO_BLEND, blend, 0);
}
u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
char *p_data)
{
@ -3266,8 +3280,7 @@ u16 hpi_entity_find_next(struct hpi_entity *container_entity,
void hpi_entity_free(struct hpi_entity *entity)
{
if (entity != NULL)
kfree(entity);
kfree(entity);
}
static u16 hpi_entity_alloc_and_copy(struct hpi_entity *src,

View File

@ -89,26 +89,3 @@ u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area)
void hpios_locked_mem_free_all(void)
{
}
void __iomem *hpios_map_io(struct pci_dev *pci_dev, int idx,
unsigned int length)
{
HPI_DEBUG_LOG(DEBUG, "mapping %d %s %08llx-%08llx %04llx len 0x%x\n",
idx, pci_dev->resource[idx].name,
(unsigned long long)pci_resource_start(pci_dev, idx),
(unsigned long long)pci_resource_end(pci_dev, idx),
(unsigned long long)pci_resource_flags(pci_dev, idx), length);
if (!(pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM)) {
HPI_DEBUG_LOG(ERROR, "not an io memory resource\n");
return NULL;
}
if (length > pci_resource_len(pci_dev, idx)) {
HPI_DEBUG_LOG(ERROR, "resource too small for requested %d \n",
length);
return NULL;
}
return ioremap(pci_resource_start(pci_dev, idx), length);
}

View File

@ -166,13 +166,4 @@ struct hpi_adapter {
void __iomem *ap_remapped_mem_base[HPI_MAX_ADAPTER_MEM_SPACES];
};
static inline void hpios_unmap_io(void __iomem *addr,
unsigned long size)
{
iounmap(addr);
}
void __iomem *hpios_map_io(struct pci_dev *pci_dev, int idx,
unsigned int length);
#endif

View File

@ -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]

View File

@ -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 +

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;