From 1efddcc981c95e62c4e305fd462e3e98b6f9c5cd Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 26 May 2010 17:59:27 +0200 Subject: [PATCH 01/17] sound: Add missing spin_unlock Add a spin_unlock missing on the error path. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E1; @@ * spin_lock(E1,...); <+... when != E1 if (...) { ... when != E1 * return ...; } ...+> * spin_unlock(E1,...); // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/mips/au1x00.c | 1 + sound/oss/dmasound/dmasound_atari.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) 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; } From 74754f974b36c5a1156be46d0da05ab2c0a0960b Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 26 May 2010 18:11:36 +0200 Subject: [PATCH 02/17] ALSA: usb-audio: parse more format descriptors with structs Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 11 +++++++---- sound/usb/format.c | 20 ++++++++++---------- sound/usb/format.h | 7 ++++--- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index ef07a6d0dd5f..4887342cae27 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -158,8 +158,9 @@ 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; + unsigned char *csep; int num, protocol; + struct uac_format_type_i_continuous_descriptor *fmt; dev = chip->dev; @@ -256,8 +257,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 +269,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 && diff --git a/sound/usb/format.c b/sound/usb/format.c index b87cf87c4e7b..caaa3ef9e622 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -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]); + chip->dev->devnum, fp->iface, fp->altsetting, + fmt->bFormatType); return -1; } - fp->fmt_type = fmt[3]; + fp->fmt_type = fmt->bFormatType; if (err < 0) return err; #if 1 @@ -421,7 +421,7 @@ 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; 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 */ From 8d0912427113723c3f3a4dca631638844c4ab649 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 26 May 2010 18:11:37 +0200 Subject: [PATCH 03/17] ALSA: usb-audio: fix return values -1 is not a good return value as it means -EPERM, "not permitted". Choose -ENOTSUPP instead, which is what the code really wants to tell its callers. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/format.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/format.c b/sound/usb/format.c index caaa3ef9e622..fe29d61de19b 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -408,7 +408,7 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *f snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", chip->dev->devnum, fp->iface, fp->altsetting, fmt->bFormatType); - return -1; + return -ENOTSUPP; } fp->fmt_type = fmt->bFormatType; if (err < 0) @@ -424,7 +424,7 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *f 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; From 43b8e3bc4af0b435fddaa59e827ca1010b024492 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 26 May 2010 18:11:38 +0200 Subject: [PATCH 04/17] ALSA: usb-audio: parse UAC2 endpoint descriptors correctly UAC2 devices have their information about pitch control stored in a different field. Parse it, and emulate the bits for a v1 device. A new struct uac2_iso_endpoint_descriptor is added. Signed-off-by: Daniel Mack Acked-by: Greg Kroah-Hartman Signed-off-by: Takashi Iwai --- include/linux/usb/audio-v2.h | 16 +++++++++++ sound/usb/endpoint.c | 55 +++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 13 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/usb/endpoint.c b/sound/usb/endpoint.c index 4887342cae27..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,7 +199,6 @@ 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 *csep; int num, protocol; struct uac_format_type_i_continuous_descriptor *fmt; @@ -279,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"); @@ -308,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 */ From 92c256110fa9566de639ef8948b4fb430aa495b3 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 26 May 2010 18:11:39 +0200 Subject: [PATCH 05/17] ALSA: usb-audio: add support for UAC2 pitch control This request is again handled differently in comparison to UAC1. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) 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; From f038e27c9e9adc166b6004e3a09cc57d61fdbd7b Mon Sep 17 00:00:00 2001 From: Eliot Blennerhassett Date: Thu, 27 May 2010 17:53:51 +1200 Subject: [PATCH 06/17] ALSA: asihpi - Remove unused io map functions Signed-off-by: Eliot Blennerhassett Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpios.c | 23 ----------------------- sound/pci/asihpi/hpios.h | 9 --------- 2 files changed, 32 deletions(-) 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 From 5a498ef1732ee3cc19b319bf7edcf428c5fad6fd Mon Sep 17 00:00:00 2001 From: Eliot Blennerhassett Date: Thu, 27 May 2010 17:53:52 +1200 Subject: [PATCH 07/17] ALSA: asihpi - Add hd radio blend functions Add hd radio blend functions. HPI version inc to 4.03.25. Signed-off-by: Eliot Blennerhassett Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpi.h | 8 +++++++- sound/pci/asihpi/hpi_internal.h | 5 +++++ sound/pci/asihpi/hpifunc.c | 17 +++++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) 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/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/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, From 70ebe64721ff685129a4016162d6370e4c10ba69 Mon Sep 17 00:00:00 2001 From: Eliot Blennerhassett Date: Thu, 27 May 2010 17:53:53 +1200 Subject: [PATCH 08/17] ALSA: asihpi - Remove support for old ASI8800 family Signed-off-by: Eliot Blennerhassett Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpi6000.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index 839ecb2e4b64..26b3b3f0a152 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; } From bca516bfcfeb545e00bad3b6ca075d91c9c0b365 Mon Sep 17 00:00:00 2001 From: Eliot Blennerhassett Date: Thu, 27 May 2010 17:53:53 +1200 Subject: [PATCH 09/17] ALSA: asihpi - Fix imbalanced lock path in hw_message Signed-off-by: Eliot Blennerhassett Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpi6000.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index 26b3b3f0a152..12dab5e4892c 100644 --- a/sound/pci/asihpi/hpi6000.c +++ b/sound/pci/asihpi/hpi6000.c @@ -1772,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; @@ -1793,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 */ From 1a59fa7cb70b687f1fe2f3fdc4185de57ae9cdc9 Mon Sep 17 00:00:00 2001 From: Eliot Blennerhassett Date: Thu, 27 May 2010 17:53:54 +1200 Subject: [PATCH 10/17] ALSA: asihpi - Fix bug preventing outstream_write preload from happening Signed-off-by: Eliot Blennerhassett Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpi6205.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c index 5e88c1fc2b9e..4f4cb92984ea 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c @@ -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) { From cadae4289d8e6ee8ad863f21ddc1845b38bf8e78 Mon Sep 17 00:00:00 2001 From: Eliot Blennerhassett Date: Thu, 27 May 2010 17:53:54 +1200 Subject: [PATCH 11/17] ALSA: asihpi - Add support for new ASI8800 family Signed-off-by: Eliot Blennerhassett Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpi6205.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c index 4f4cb92984ea..e89991ea3543 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c @@ -1361,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; From 3ee317fe9cf08d81501b142bf0054c25e3ed5e7d Mon Sep 17 00:00:00 2001 From: Eliot Blennerhassett Date: Thu, 27 May 2010 17:53:55 +1200 Subject: [PATCH 12/17] ALSA: asihpi - Minor code cleanup Signed-off-by: Eliot Blennerhassett Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpicmn.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) 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; From e8d0fee70b66694959eab10c41788b9279d73629 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 27 May 2010 20:15:14 +0200 Subject: [PATCH 13/17] ALSA: usb-audio: fix feature unit parser for UAC2 Fix a small off-by-one bug which causes the feature unit to announce a wrong number of channels. This leads to illegal requests sent to the firmware eventually. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; } From bd4cbf6c7689d35d5d1248369d2c350f4711ca0a Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Sat, 29 May 2010 16:53:23 +0100 Subject: [PATCH 14/17] ALSA: snd-usb-caiaq: Restore 'Control vinyl' input mode on A4DJ This feature was undocumented on early A4DJ units. It is indicated by lighting both the 'line' and 'phono' lamps at the same time. Newer units document this and the newer Windows drivers enable this for all units, so restore the functionality. This patch simplifies the code and changes the mode mapping to match the A8DJ, favouring simpler code and consistency over keeping the existing mapping. Both 'Control vinyl' and 'Phono' input modes enable the hardware preamp. The difference is the input impedance. This reverts commit 9a9527e. Acked-by: Daniel Mack Signed-off-by: Mark Hills Signed-off-by: Takashi Iwai --- sound/usb/caiaq/control.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c index 36ed703a7416..70c3866bb627 100644 --- a/sound/usb/caiaq/control.c +++ b/sound/usb/caiaq/control.c @@ -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]; @@ -113,15 +96,6 @@ static int control_put(struct snd_kcontrol *kcontrol, 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): cmd = EP1_CMD_DIMM_LEDS; break; From 4efd7d8f67ac5ff80db06b77c46aca6e0d9f878b Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Sat, 29 May 2010 16:53:24 +0100 Subject: [PATCH 15/17] ALSA: snd-usb-caiaq: Simplify single case to an 'if' After removing code, only one case remains. So use an 'if' instead. Acked-by: Daniel Mack Signed-off-by: Mark Hills Signed-off-by: Takashi Iwai --- sound/usb/caiaq/control.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c index 70c3866bb627..91c804cd2782 100644 --- a/sound/usb/caiaq/control.c +++ b/sound/usb/caiaq/control.c @@ -95,11 +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_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] From 649233562cb1e83ebd2af30bd981881e51961b8b Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Sat, 29 May 2010 16:53:25 +0100 Subject: [PATCH 16/17] ALSA: Revert "ALSA: snd-usb-caiaq: Set default input mode of A4DJ" Do not explicity set the default input mode. Use the hardware default of mode 0 ('Control vinyl'), which is now available. This reverts commit e3ca4c9. Acked-by: Daniel Mack Signed-off-by: Mark Hills Signed-off-by: Takashi Iwai --- sound/usb/caiaq/device.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 805271827675..bf71048e3247 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -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 + From 55567ab70bd8551c73253e44ea5244db41eac81b Mon Sep 17 00:00:00 2001 From: Mark Hills Date: Sat, 29 May 2010 16:53:26 +0100 Subject: [PATCH 17/17] ALSA: snd-usb-caiaq: Bump version number to 1.3.21 Acked-by: Daniel Mack Signed-off-by: Mark Hills Signed-off-by: Takashi Iwai --- sound/usb/caiaq/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index bf71048e3247..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 "); -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},"