summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-30 02:31:57 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-30 02:31:57 +0400
commit52b0ace7dfe8f70350218017a95d7cab1eb41fbb (patch)
treee474f8e2c5ac1712e1e1155b879420dde4aa3922
parent24010e460454ec0d2f4f0213b667b4349cbdb8e1 (diff)
parentd6695f09ea30de712662fcf8dd0e8c4d4306a15a (diff)
downloadlinux-52b0ace7dfe8f70350218017a95d7cab1eb41fbb.tar.xz
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 ...
-rw-r--r--include/linux/usb/audio-v2.h16
-rw-r--r--sound/mips/au1x00.c1
-rw-r--r--sound/oss/dmasound/dmasound_atari.c5
-rw-r--r--sound/pci/asihpi/hpi.h8
-rw-r--r--sound/pci/asihpi/hpi6000.c6
-rw-r--r--sound/pci/asihpi/hpi6205.c21
-rw-r--r--sound/pci/asihpi/hpi_internal.h5
-rw-r--r--sound/pci/asihpi/hpicmn.c38
-rw-r--r--sound/pci/asihpi/hpifunc.c17
-rw-r--r--sound/pci/asihpi/hpios.c23
-rw-r--r--sound/pci/asihpi/hpios.h9
-rw-r--r--sound/pci/hda/hda_intel.c2
-rw-r--r--sound/pci/hda/patch_conexant.c2
-rw-r--r--sound/soc/codecs/wm8350.c4
-rw-r--r--sound/soc/codecs/wm8400.c18
-rw-r--r--sound/soc/codecs/wm8990.c18
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c7
-rw-r--r--sound/soc/sh/siu_dai.c2
-rw-r--r--sound/usb/caiaq/control.c36
-rw-r--r--sound/usb/caiaq/device.c8
-rw-r--r--sound/usb/endpoint.c64
-rw-r--r--sound/usb/format.c24
-rw-r--r--sound/usb/format.h7
-rw-r--r--sound/usb/mixer.c2
-rw-r--r--sound/usb/pcm.c37
25 files changed, 200 insertions, 180 deletions
diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h
index 2389f93a28b5..92f1d99f0f17 100644
--- a/include/linux/usb/audio-v2.h
+++ b/include/linux/usb/audio-v2.h
@@ -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)
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index 3e763d6a5d67..446cf9748664 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -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;
}
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
index 1f4774123064..13c214466d3b 100644
--- a/sound/oss/dmasound/dmasound_atari.c
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -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;
}
diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h
index 99400de6c075..0173bbe62b67 100644
--- a/sound/pci/asihpi/hpi.h
+++ b/sound/pci/asihpi/hpi.h
@@ -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 */
/****************************/
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
index 839ecb2e4b64..12dab5e4892c 100644
--- a/sound/pci/asihpi/hpi6000.c
+++ b/sound/pci/asihpi/hpi6000.c
@@ -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 */
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
index 5e88c1fc2b9e..e89991ea3543 100644
--- a/sound/pci/asihpi/hpi6205.c
+++ b/sound/pci/asihpi/hpi6205.c
@@ -966,23 +966,16 @@ static void outstream_write(struct hpi_adapter_obj *pao,
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;
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h
index f1cd6f1a0d44..fdd0ce02aa68 100644
--- a/sound/pci/asihpi/hpi_internal.h
+++ b/sound/pci/asihpi/hpi_internal.h
@@ -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;
};
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c
index 565102cae4f8..fcd64539d9ef 100644
--- a/sound/pci/asihpi/hpicmn.c
+++ b/sound/pci/asihpi/hpicmn.c
@@ -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;
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c
index eda26b312324..298eef3e20e9 100644
--- a/sound/pci/asihpi/hpifunc.c
+++ b/sound/pci/asihpi/hpifunc.c
@@ -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,
diff --git a/sound/pci/asihpi/hpios.c b/sound/pci/asihpi/hpios.c
index de615cfdb950..742ee12a9e17 100644
--- a/sound/pci/asihpi/hpios.c
+++ b/sound/pci/asihpi/hpios.c
@@ -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);
-}
diff --git a/sound/pci/asihpi/hpios.h b/sound/pci/asihpi/hpios.h
index a62c3f1e5f09..370f39b43f85 100644
--- a/sound/pci/asihpi/hpios.h
+++ b/sound/pci/asihpi/hpios.h
@@ -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
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 77e22c2a8caa..dc79564fea30 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -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(0x103c, 0x306d, "HP dv3", 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(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(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index e863649d31f5..2bf2cb5da956 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -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, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
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, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
{}
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 8ae20208e7be..0221ca79b3ae 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -426,8 +426,8 @@ static const struct soc_enum wm8350_enum[] = {
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_LINEAR(out_pga_tlv, -5700, 600);
+static DECLARE_TLV_DB_SCALE(pre_amp_tlv, -1200, 3525, 0);
+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(adc_pcm_tlv, -12700, 50, 1);
static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1);
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 7f5d080536a0..8f294066b0ed 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -107,21 +107,21 @@ static void wm8400_codec_reset(struct snd_soc_codec *codec)
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,
struct snd_ctl_elem_value *ucontrol)
@@ -440,7 +440,7 @@ static int outmixer_event (struct snd_soc_dapm_widget *w,
/* INMIX dB values */
static const unsigned int in_mix_tlv[] = {
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 */
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 7b536d923ea9..c018772cc430 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -111,21 +111,21 @@ static const u16 wm8990_reg[] = {
#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,
struct snd_ctl_elem_value *ucontrol)
@@ -451,7 +451,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
/* INMIX dB values */
static const unsigned int in_mix_tlv[] = {
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 */
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 2b31ac673ea4..05f19c9284f4 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -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_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 imx_pcm_runtime_data *iprtd = runtime->private_data;
int ret;
@@ -102,7 +103,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
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);
if (iprtd->dma < 0) {
@@ -212,7 +213,7 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
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->buf = (unsigned int *)substream->dma_buffer.area;
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index d86ee1bfc03a..eeed5edd722b 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -588,6 +588,8 @@ static int siu_dai_prepare(struct snd_pcm_substream *substream,
ret = siu_dai_spbstart(port_info);
if (ret < 0)
goto fail;
+ } else {
+ ret = 0;
}
port_info->play_cap |= self;
diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c
index 36ed703a7416..91c804cd2782 100644
--- a/sound/usb/caiaq/control.c
+++ b/sound/usb/caiaq/control.c
@@ -42,21 +42,12 @@ static int control_info(struct snd_kcontrol *kcontrol,
switch (dev->chip.usb_id) {
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):
if (pos == 0) {
- /* current input mode of A4DJ */
+ /* current input mode of A8DJ and A4DJ */
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
+ uinfo->value.integer.max = 2;
return 0;
}
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]
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 805271827675..cdfb856bddd2 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -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 +
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index ef07a6d0dd5f..28ee1ce3971a 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -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 */
diff --git a/sound/usb/format.c b/sound/usb/format.c
index b87cf87c4e7b..fe29d61de19b 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -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;
diff --git a/sound/usb/format.h b/sound/usb/format.h
index 8298c4e8ddfa..387924f0af85 100644
--- a/sound/usb/format.h
+++ b/sound/usb/format.h
@@ -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 */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 97dd17655104..03ce971e0027 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -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;
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 2bf0d77d1768..056587de7be4 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -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;