diff options
| author | Takashi Iwai <tiwai@suse.de> | 2010-05-29 21:50:33 +0200 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2010-05-29 21:50:33 +0200 | 
| commit | a98d3984c85222aa9efc63c4f9dd3d805ce469f2 (patch) | |
| tree | aeb9ebdcc06ca92b8114f30cedf16b8f3780b3f2 /sound | |
| parent | 52593de4c11fb24c83d8036ba34706881aab5e3d (diff) | |
| parent | 55567ab70bd8551c73253e44ea5244db41eac81b (diff) | |
Merge branch 'fix/misc' into for-linus
Diffstat (limited to 'sound')
| -rw-r--r-- | sound/mips/au1x00.c | 1 | ||||
| -rw-r--r-- | sound/oss/dmasound/dmasound_atari.c | 5 | ||||
| -rw-r--r-- | sound/pci/asihpi/hpi.h | 8 | ||||
| -rw-r--r-- | sound/pci/asihpi/hpi6000.c | 6 | ||||
| -rw-r--r-- | sound/pci/asihpi/hpi6205.c | 21 | ||||
| -rw-r--r-- | sound/pci/asihpi/hpi_internal.h | 5 | ||||
| -rw-r--r-- | sound/pci/asihpi/hpicmn.c | 38 | ||||
| -rw-r--r-- | sound/pci/asihpi/hpifunc.c | 17 | ||||
| -rw-r--r-- | sound/pci/asihpi/hpios.c | 23 | ||||
| -rw-r--r-- | sound/pci/asihpi/hpios.h | 9 | ||||
| -rw-r--r-- | sound/usb/caiaq/control.c | 36 | ||||
| -rw-r--r-- | sound/usb/caiaq/device.c | 8 | ||||
| -rw-r--r-- | sound/usb/endpoint.c | 64 | ||||
| -rw-r--r-- | sound/usb/format.c | 24 | ||||
| -rw-r--r-- | sound/usb/format.h | 7 | ||||
| -rw-r--r-- | sound/usb/mixer.c | 2 | ||||
| -rw-r--r-- | sound/usb/pcm.c | 37 | 
17 files changed, 154 insertions, 157 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;  } 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/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; | 
