Merge branch 'fix/misc' into for-linus
This commit is contained in:
commit
a98d3984c8
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
/****************************/
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
|
||||
* 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;
|
||||
|
Loading…
Reference in New Issue
Block a user