Commit 52b0ace7 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 24010e46 d6695f09
...@@ -105,6 +105,22 @@ struct uac_as_header_descriptor_v2 { ...@@ -105,6 +105,22 @@ struct uac_as_header_descriptor_v2 {
__u8 iChannelNames; __u8 iChannelNames;
} __attribute__((packed)); } __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 */ /* 6.1 Interrupt Data Message */
#define UAC2_INTERRUPT_DATA_MSG_VENDOR (1 << 0) #define UAC2_INTERRUPT_DATA_MSG_VENDOR (1 << 0)
......
...@@ -516,6 +516,7 @@ get the interrupt driven case to work efficiently */ ...@@ -516,6 +516,7 @@ get the interrupt driven case to work efficiently */
break; break;
if (i == 0x5000) { if (i == 0x5000) {
printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n"); printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n");
spin_unlock(&au1000->ac97_lock);
return 0; return 0;
} }
......
...@@ -1277,7 +1277,7 @@ static irqreturn_t AtaInterrupt(int irq, void *dummy) ...@@ -1277,7 +1277,7 @@ static irqreturn_t AtaInterrupt(int irq, void *dummy)
* (almost) like on the TT. * (almost) like on the TT.
*/ */
write_sq_ignore_int = 0; write_sq_ignore_int = 0;
return IRQ_HANDLED; goto out;
} }
if (!write_sq.active) { if (!write_sq.active) {
...@@ -1285,7 +1285,7 @@ static irqreturn_t AtaInterrupt(int irq, void *dummy) ...@@ -1285,7 +1285,7 @@ static irqreturn_t AtaInterrupt(int irq, void *dummy)
* the sq variables, so better don't do anything here. * the sq variables, so better don't do anything here.
*/ */
WAKE_UP(write_sq.sync_queue); WAKE_UP(write_sq.sync_queue);
return IRQ_HANDLED; goto out;
} }
/* Probably ;) one frame is finished. Well, in fact it may be that a /* 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) ...@@ -1322,6 +1322,7 @@ static irqreturn_t AtaInterrupt(int irq, void *dummy)
/* We are not playing after AtaPlay(), so there /* We are not playing after AtaPlay(), so there
is nothing to play any more. Wake up a process is nothing to play any more. Wake up a process
waiting for audio output to drain. */ waiting for audio output to drain. */
out:
spin_unlock(&dmasound.lock); spin_unlock(&dmasound.lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -50,7 +50,7 @@ i.e 3.05.02 is a development version ...@@ -50,7 +50,7 @@ i.e 3.05.02 is a development version
#define HPI_VER_RELEASE(v) ((int)(v & 0xFF)) #define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
/* Use single digits for versions less that 10 to avoid octal. */ /* 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 */ /* Library version as documented in hpi-api-versions.txt */
#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0) #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, ...@@ -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, u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *pquality); 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 */ /* PADs control */
/****************************/ /****************************/
......
...@@ -691,9 +691,6 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, ...@@ -691,9 +691,6 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
case 0x6200: case 0x6200:
boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200); boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
break; break;
case 0x8800:
boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x8800);
break;
default: default:
return HPI6000_ERROR_UNHANDLED_SUBSYS_ID; return HPI6000_ERROR_UNHANDLED_SUBSYS_ID;
} }
...@@ -1775,7 +1772,6 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, ...@@ -1775,7 +1772,6 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
u16 error = 0; u16 error = 0;
u16 dsp_index = 0; u16 dsp_index = 0;
u16 num_dsp = ((struct hpi_hw_obj *)pao->priv)->num_dsp; u16 num_dsp = ((struct hpi_hw_obj *)pao->priv)->num_dsp;
hpios_dsplock_lock(pao);
if (num_dsp < 2) if (num_dsp < 2)
dsp_index = 0; dsp_index = 0;
...@@ -1796,6 +1792,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, ...@@ -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); error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
/* maybe an error response */ /* maybe an error response */
......
...@@ -965,24 +965,17 @@ static void outstream_write(struct hpi_adapter_obj *pao, ...@@ -965,24 +965,17 @@ static void outstream_write(struct hpi_adapter_obj *pao,
hpi_init_response(phr, phm->object, phm->function, 0); hpi_init_response(phr, phm->object, phm->function, 0);
status = &interface->outstream_host_buffer_status[phm->obj_index]; 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]) { if (phw->flag_outstream_just_reset[phm->obj_index]) {
/* First OutStremWrite() call following reset will write data to the /* 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; int partial_write = 0;
unsigned int original_size = 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. */ /* Send the first buffer to the DSP the old way. */
/* Limit size of first transfer - */ /* Limit size of first transfer - */
/* expect that this will not usually be triggered. */ /* expect that this will not usually be triggered. */
...@@ -1012,7 +1005,6 @@ static void outstream_write(struct hpi_adapter_obj *pao, ...@@ -1012,7 +1005,6 @@ static void outstream_write(struct hpi_adapter_obj *pao,
original_size - HPI6205_SIZEOF_DATA; original_size - HPI6205_SIZEOF_DATA;
phm->u.d.u.data.pb_data += HPI6205_SIZEOF_DATA; phm->u.d.u.data.pb_data += HPI6205_SIZEOF_DATA;
} }
#endif
space_available = outstream_get_space_available(status); space_available = outstream_get_space_available(status);
if (space_available < (long)phm->u.d.u.data.data_size) { 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, ...@@ -1369,6 +1361,9 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
case HPI_ADAPTER_FAMILY_ASI(0x6500): case HPI_ADAPTER_FAMILY_ASI(0x6500):
firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600); firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600);
break; break;
case HPI_ADAPTER_FAMILY_ASI(0x8800):
firmware_id = HPI_ADAPTER_FAMILY_ASI(0x8900);
break;
} }
boot_code_id[1] = firmware_id; boot_code_id[1] = firmware_id;
......
...@@ -232,6 +232,8 @@ enum HPI_BUSES { ...@@ -232,6 +232,8 @@ enum HPI_BUSES {
#define HPI_TUNER_HDRADIO_SDK_VERSION HPI_CTL_ATTR(TUNER, 13) #define HPI_TUNER_HDRADIO_SDK_VERSION HPI_CTL_ATTR(TUNER, 13)
/** HD Radio DSP firmware version. */ /** HD Radio DSP firmware version. */
#define HPI_TUNER_HDRADIO_DSP_VERSION HPI_CTL_ATTR(TUNER, 14) #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, ...@@ -478,8 +480,10 @@ Threshold is a -ve number in units of dB/100,
/** First 2 hex digits define the adapter family */ /** First 2 hex digits define the adapter family */
#define HPI_ADAPTER_FAMILY_MASK 0xff00 #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_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) #define HPI_ADAPTER_ASI(f) (f)
/******************************************* message types */ /******************************************* message types */
...@@ -970,6 +974,7 @@ struct hpi_control_union_msg { ...@@ -970,6 +974,7 @@ struct hpi_control_union_msg {
u32 mode; u32 mode;
u32 value; u32 value;
} mode; } mode;
u32 blend;
} tuner; } tuner;
} u; } u;
}; };
......
...@@ -347,20 +347,15 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, ...@@ -347,20 +347,15 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
found = 0; found = 0;
break; break;
case HPI_CONTROL_TUNER: case HPI_CONTROL_TUNER:
{
struct hpi_control_cache_single *pCT =
(struct hpi_control_cache_single *)pI;
if (phm->u.c.attribute == HPI_TUNER_FREQ) if (phm->u.c.attribute == HPI_TUNER_FREQ)
phr->u.c.param1 = pCT->u.t.freq_ink_hz; phr->u.c.param1 = pC->u.t.freq_ink_hz;
else if (phm->u.c.attribute == HPI_TUNER_BAND) else if (phm->u.c.attribute == HPI_TUNER_BAND)
phr->u.c.param1 = pCT->u.t.band; phr->u.c.param1 = pC->u.t.band;
else if ((phm->u.c.attribute == HPI_TUNER_LEVEL) else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
&& (phm->u.c.param1 == && (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
HPI_TUNER_LEVEL_AVERAGE)) phr->u.c.param1 = pC->u.t.level;
phr->u.c.param1 = pCT->u.t.level;
else else
found = 0; found = 0;
}
break; break;
case HPI_CONTROL_AESEBU_RECEIVER: case HPI_CONTROL_AESEBU_RECEIVER:
if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS) if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
...@@ -503,6 +498,9 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, ...@@ -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_single *pC;
struct hpi_control_cache_info *pI; struct hpi_control_cache_info *pI;
if (phr->error)
return;
if (!find_control(phm, p_cache, &pI, &control_index)) if (!find_control(phm, p_cache, &pI, &control_index))
return; return;
...@@ -520,8 +518,6 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, ...@@ -520,8 +518,6 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
break; break;
case HPI_CONTROL_MULTIPLEXER: case HPI_CONTROL_MULTIPLEXER:
/* mux does not return its setting on Set command. */ /* mux does not return its setting on Set command. */
if (phr->error)
return;
if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
pC->u.x.source_node_type = (u16)phm->u.c.param1; pC->u.x.source_node_type = (u16)phm->u.c.param1;
pC->u.x.source_node_index = (u16)phm->u.c.param2; 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, ...@@ -529,8 +525,6 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
break; break;
case HPI_CONTROL_CHANNEL_MODE: case HPI_CONTROL_CHANNEL_MODE:
/* mode does not return its setting on Set command. */ /* mode does not return its setting on Set command. */
if (phr->error)
return;
if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
pC->u.m.mode = (u16)phm->u.c.param1; pC->u.m.mode = (u16)phm->u.c.param1;
break; break;
...@@ -545,20 +539,14 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, ...@@ -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; pC->u.phantom_power.state = (u16)phm->u.c.param1;
break; break;
case HPI_CONTROL_AESEBU_TRANSMITTER: case HPI_CONTROL_AESEBU_TRANSMITTER:
if (phr->error)
return;
if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
pC->u.aes3tx.format = phm->u.c.param1; pC->u.aes3tx.format = phm->u.c.param1;
break; break;
case HPI_CONTROL_AESEBU_RECEIVER: case HPI_CONTROL_AESEBU_RECEIVER:
if (phr->error)
return;
if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
pC->u.aes3rx.source = phm->u.c.param1; pC->u.aes3rx.source = phm->u.c.param1;
break; break;
case HPI_CONTROL_SAMPLECLOCK: case HPI_CONTROL_SAMPLECLOCK:
if (phr->error)
return;
if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
pC->u.clk.source = (u16)phm->u.c.param1; pC->u.clk.source = (u16)phm->u.c.param1;
else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
...@@ -590,7 +578,7 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32 ...@@ -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) 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); kfree(p_cache->p_info);
p_cache->p_info = NULL; p_cache->p_info = NULL;
p_cache->init = 0; p_cache->init = 0;
......
...@@ -2946,6 +2946,20 @@ u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys, ...@@ -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); 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, u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
char *p_data) char *p_data)
{ {
...@@ -3266,7 +3280,6 @@ u16 hpi_entity_find_next(struct hpi_entity *container_entity, ...@@ -3266,7 +3280,6 @@ u16 hpi_entity_find_next(struct hpi_entity *container_entity,
void hpi_entity_free(struct hpi_entity *entity) void hpi_entity_free(struct hpi_entity *entity)
{ {
if (entity != NULL)
kfree(entity); kfree(entity);
} }
......
...@@ -89,26 +89,3 @@ u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area) ...@@ -89,26 +89,3 @@ u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area)
void hpios_locked_mem_free_all(void) 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 { ...@@ -166,13 +166,4 @@ struct hpi_adapter {
void __iomem *ap_remapped_mem_base[HPI_MAX_ADAPTER_MEM_SPACES]; 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 #endif
...@@ -2288,8 +2288,10 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { ...@@ -2288,8 +2288,10 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB), SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
......
...@@ -2975,6 +2975,8 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { ...@@ -2975,6 +2975,8 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
{} {}
......
...@@ -426,8 +426,8 @@ static const struct soc_enum wm8350_enum[] = { ...@@ -426,8 +426,8 @@ static const struct soc_enum wm8350_enum[] = {
SOC_ENUM_SINGLE(WM8350_INPUT_MIXER_VOLUME, 15, 2, wm8350_lr), SOC_ENUM_SINGLE(WM8350_INPUT_MIXER_VOLUME, 15, 2, wm8350_lr),
}; };
static DECLARE_TLV_DB_LINEAR(pre_amp_tlv, -1200, 3525); static DECLARE_TLV_DB_SCALE(pre_amp_tlv, -1200, 3525, 0);
static DECLARE_TLV_DB_LINEAR(out_pga_tlv, -5700, 600); static DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 600, 0);
static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1); static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1);
static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1); static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1);
static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1); static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1);
......
...@@ -107,21 +107,21 @@ static void wm8400_codec_reset(struct snd_soc_codec *codec) ...@@ -107,21 +107,21 @@ static void wm8400_codec_reset(struct snd_soc_codec *codec)
wm8400_reset_codec_reg_cache(wm8400->wm8400); wm8400_reset_codec_reg_cache(wm8400->wm8400);
} }
static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0);
static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0);
static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, -2100, 0); static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -2100, 0, 0);
static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0);
static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0);
static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0);
static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0);
static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
...@@ -440,7 +440,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w, ...@@ -440,7 +440,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
/* INMIX dB values */ /* INMIX dB values */
static const unsigned int in_mix_tlv[] = { static const unsigned int in_mix_tlv[] = {
TLV_DB_RANGE_HEAD(1), TLV_DB_RANGE_HEAD(1),
0,7, TLV_DB_LINEAR_ITEM(-1200, 600), 0,7, TLV_DB_SCALE_ITEM(-1200, 600, 0),
}; };
/* Left In PGA Connections */ /* Left In PGA Connections */
......
...@@ -111,21 +111,21 @@ static const u16 wm8990_reg[] = { ...@@ -111,21 +111,21 @@ static const u16 wm8990_reg[] = {
#define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0) #define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0);
static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0);
static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100); static const DECLARE_TLV_DB_SCALE(out_mix_tlv, 0, -2100, 0);
static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0);
static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0);
static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0);
static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0);
static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
...@@ -451,7 +451,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, ...@@ -451,7 +451,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
/* INMIX dB values */ /* INMIX dB values */
static const unsigned int in_mix_tlv[] = { static const unsigned int in_mix_tlv[] = {
TLV_DB_RANGE_HEAD(1), TLV_DB_RANGE_HEAD(1),
0, 7, TLV_DB_LINEAR_ITEM(-1200, 600), 0, 7, TLV_DB_SCALE_ITEM(-1200, 600, 0),
}; };
/* Left In PGA Connections */ /* Left In PGA Connections */
......
...@@ -73,7 +73,8 @@ static void snd_imx_dma_err_callback(int channel, void *data, int err) ...@@ -73,7 +73,8 @@ static void snd_imx_dma_err_callback(int channel, void *data, int err)
{ {
struct snd_pcm_substream *substream = data; struct snd_pcm_substream *substream = data;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; struct imx_pcm_dma_params *dma_params =
snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct imx_pcm_runtime_data *iprtd = runtime->private_data;
int ret; int ret;
...@@ -102,7 +103,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream) ...@@ -102,7 +103,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct imx_pcm_runtime_data *iprtd = runtime->private_data;
int ret; int ret;
dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream); dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH); iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);
if (iprtd->dma < 0) { if (iprtd->dma < 0) {
...@@ -212,7 +213,7 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -212,7 +213,7 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct imx_pcm_runtime_data *iprtd = runtime->private_data;
int err; int err;
dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream); dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
iprtd->substream = substream; iprtd->substream = substream;
iprtd->buf = (unsigned int *)substream->dma_buffer.area; iprtd->buf = (unsigned int *)substream->dma_buffer.area;
......
...@@ -588,6 +588,8 @@ static int siu_dai_prepare(struct snd_pcm_substream *substream, ...@@ -588,6 +588,8 @@ static int siu_dai_prepare(struct snd_pcm_substream *substream,
ret = siu_dai_spbstart(port_info); ret = siu_dai_spbstart(port_info);
if (ret < 0) if (ret < 0)
goto fail; goto fail;
} else {
ret = 0;
} }
port_info->play_cap |= self; port_info->play_cap |= self;
......
...@@ -42,21 +42,12 @@ static int control_info(struct snd_kcontrol *kcontrol, ...@@ -42,21 +42,12 @@ static int control_info(struct snd_kcontrol *kcontrol,
switch (dev->chip.usb_id) { switch (dev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
if (pos == 0) {
/* current input mode of A8DJ */
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 2;
return 0;
}
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
if (pos == 0) { if (pos == 0) {
/* current input mode of A4DJ */ /* current input mode of A8DJ and A4DJ */
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->value.integer.min = 0; uinfo->value.integer.min = 0;
uinfo->value.integer.max = 1; uinfo->value.integer.max = 2;
return 0; return 0;
} }
break; break;
...@@ -86,14 +77,6 @@ static int control_get(struct snd_kcontrol *kcontrol, ...@@ -86,14 +77,6 @@ static int control_get(struct snd_kcontrol *kcontrol,
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
int pos = kcontrol->private_value; 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) if (pos & CNT_INTVAL)
ucontrol->value.integer.value[0] ucontrol->value.integer.value[0]
= dev->control_state[pos & ~CNT_INTVAL]; = dev->control_state[pos & ~CNT_INTVAL];
...@@ -112,20 +95,9 @@ static int control_put(struct snd_kcontrol *kcontrol, ...@@ -112,20 +95,9 @@ static int control_put(struct snd_kcontrol *kcontrol,
int pos = kcontrol->private_value; int pos = kcontrol->private_value;
unsigned char cmd = EP1_CMD_WRITE_IO; unsigned char cmd = EP1_CMD_WRITE_IO;
switch (dev->chip.usb_id) { if (dev->chip.usb_id ==
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): { USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1))
/* 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):
cmd = EP1_CMD_DIMM_LEDS; cmd = EP1_CMD_DIMM_LEDS;
break;
}
if (pos & CNT_INTVAL) { if (pos & CNT_INTVAL) {
dev->control_state[pos & ~CNT_INTVAL] dev->control_state[pos & ~CNT_INTVAL]
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "input.h" #include "input.h"
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); 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_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
"{Native Instruments, RigKontrol3}," "{Native Instruments, RigKontrol3},"
...@@ -320,12 +320,6 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev) ...@@ -320,12 +320,6 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev)
} }
break; 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 + 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 ...@@ -149,6 +149,47 @@ int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct au
return 0; 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) int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
{ {
struct usb_device *dev; struct usb_device *dev;
...@@ -158,8 +199,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) ...@@ -158,8 +199,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
int i, altno, err, stream; int i, altno, err, stream;
int format = 0, num_channels = 0; int format = 0, num_channels = 0;
struct audioformat *fp = NULL; struct audioformat *fp = NULL;
unsigned char *fmt, *csep;
int num, protocol; int num, protocol;
struct uac_format_type_i_continuous_descriptor *fmt;
dev = chip->dev; dev = chip->dev;
...@@ -256,8 +297,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) ...@@ -256,8 +297,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
dev->devnum, iface_no, altno); dev->devnum, iface_no, altno);
continue; continue;
} }
if (((protocol == UAC_VERSION_1) && (fmt[0] < 8)) || if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
((protocol == UAC_VERSION_2) && (fmt[0] != 6))) { ((protocol == UAC_VERSION_2) && (fmt->bLength != 6))) {
snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
dev->devnum, iface_no, altno); dev->devnum, iface_no, altno);
continue; continue;
...@@ -268,7 +309,9 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) ...@@ -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 * with the previous one, except for a larger packet size, but
* is actually a mislabeled two-channel setting; ignore it. * 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 && fp->altsetting == 1 && fp->channels == 1 &&
fp->formats == SNDRV_PCM_FMTBIT_S16_LE && fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
protocol == UAC_VERSION_1 && protocol == UAC_VERSION_1 &&
...@@ -276,17 +319,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) ...@@ -276,17 +319,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
fp->maxpacksize * 2) fp->maxpacksize * 2)
continue; 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); fp = kzalloc(sizeof(*fp), GFP_KERNEL);
if (! fp) { if (! fp) {
snd_printk(KERN_ERR "cannot malloc\n"); 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) ...@@ -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) if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
* (fp->maxpacksize & 0x7ff); * (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 */ /* some quirks for attributes here */
......
...@@ -278,12 +278,11 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, ...@@ -278,12 +278,11 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
* parse the format type I and III descriptors * parse the format type I and III descriptors
*/ */
static int parse_audio_format_i(struct snd_usb_audio *chip, static int parse_audio_format_i(struct snd_usb_audio *chip,
struct audioformat *fp, struct audioformat *fp, int format,
int format, void *_fmt, struct uac_format_type_i_continuous_descriptor *fmt,
struct usb_host_interface *iface) struct usb_host_interface *iface)
{ {
struct usb_interface_descriptor *altsd = get_iface_desc(iface); struct usb_interface_descriptor *altsd = get_iface_desc(iface);
struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
int protocol = altsd->bInterfaceProtocol; int protocol = altsd->bInterfaceProtocol;
int pcm_format, ret; int pcm_format, ret;
...@@ -320,7 +319,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, ...@@ -320,7 +319,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
switch (protocol) { switch (protocol) {
case UAC_VERSION_1: case UAC_VERSION_1:
fp->channels = fmt->bNrChannels; 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; break;
case UAC_VERSION_2: case UAC_VERSION_2:
/* fp->channels is already set in this case */ /* fp->channels is already set in this case */
...@@ -392,12 +391,12 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, ...@@ -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 snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp,
int format, unsigned char *fmt, int stream, int format, struct uac_format_type_i_continuous_descriptor *fmt,
struct usb_host_interface *iface) int stream, struct usb_host_interface *iface)
{ {
int err; int err;
switch (fmt[3]) { switch (fmt->bFormatType) {
case UAC_FORMAT_TYPE_I: case UAC_FORMAT_TYPE_I:
case UAC_FORMAT_TYPE_III: case UAC_FORMAT_TYPE_III:
err = parse_audio_format_i(chip, fp, format, fmt, iface); 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 ...@@ -407,10 +406,11 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *f
break; break;
default: default:
snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]); chip->dev->devnum, fp->iface, fp->altsetting,
return -1; fmt->bFormatType);
return -ENOTSUPP;
} }
fp->fmt_type = fmt[3]; fp->fmt_type = fmt->bFormatType;
if (err < 0) if (err < 0)
return err; return err;
#if 1 #if 1
...@@ -421,10 +421,10 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *f ...@@ -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) || if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
chip->usb_id == USB_ID(0x041e, 0x3020) || chip->usb_id == USB_ID(0x041e, 0x3020) ||
chip->usb_id == USB_ID(0x041e, 0x3061)) { 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_48000 &&
fp->rates != SNDRV_PCM_RATE_96000) fp->rates != SNDRV_PCM_RATE_96000)
return -1; return -ENOTSUPP;
} }
#endif #endif
return 0; return 0;
......
#ifndef __USBAUDIO_FORMAT_H #ifndef __USBAUDIO_FORMAT_H
#define __USBAUDIO_FORMAT_H #define __USBAUDIO_FORMAT_H
int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp, int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
int format, unsigned char *fmt, int stream, struct audioformat *fp, int format,
struct usb_host_interface *iface); struct uac_format_type_i_continuous_descriptor *fmt,
int stream, struct usb_host_interface *iface);
#endif /* __USBAUDIO_FORMAT_H */ #endif /* __USBAUDIO_FORMAT_H */
...@@ -1126,7 +1126,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void ...@@ -1126,7 +1126,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
} else { } else {
struct uac2_feature_unit_descriptor *ftr = _ftr; struct uac2_feature_unit_descriptor *ftr = _ftr;
csize = 4; csize = 4;
channels = (hdr->bLength - 6) / 4; channels = (hdr->bLength - 6) / 4 - 1;
bmaControls = ftr->bmaControls; bmaControls = ftr->bmaControls;
} }
......
...@@ -120,10 +120,6 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface, ...@@ -120,10 +120,6 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
ep = get_endpoint(alts, 0)->bEndpointAddress; 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; data[0] = 1;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 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, ...@@ -137,8 +133,32 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
return 0; 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, int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts, struct usb_host_interface *alts,
...@@ -146,13 +166,16 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, ...@@ -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); 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) { switch (altsd->bInterfaceProtocol) {
case UAC_VERSION_1: case UAC_VERSION_1:
return init_pitch_v1(chip, iface, alts, fmt); return init_pitch_v1(chip, iface, alts, fmt);
case UAC_VERSION_2: case UAC_VERSION_2:
/* not implemented yet */ return init_pitch_v2(chip, iface, alts, fmt);
return 0;
} }
return -EINVAL; return -EINVAL;
......
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