diff options
Diffstat (limited to 'sound/usb/pcm.c')
| -rw-r--r-- | sound/usb/pcm.c | 61 | 
1 files changed, 37 insertions, 24 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 54607f8c4f6..a1298f37942 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -261,19 +261,6 @@ static void stop_endpoints(struct snd_usb_substream *subs,  				      force, can_sleep, wait);  } -static int activate_endpoints(struct snd_usb_substream *subs) -{ -	if (subs->sync_endpoint) { -		int ret; - -		ret = snd_usb_endpoint_activate(subs->sync_endpoint); -		if (ret < 0) -			return ret; -	} - -	return snd_usb_endpoint_activate(subs->data_endpoint); -} -  static int deactivate_endpoints(struct snd_usb_substream *subs)  {  	int reta, retb; @@ -314,6 +301,33 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)  	if (fmt == subs->cur_audiofmt)  		return 0; +	/* close the old interface */ +	if (subs->interface >= 0 && subs->interface != fmt->iface) { +		err = usb_set_interface(subs->dev, subs->interface, 0); +		if (err < 0) { +			snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n", +				dev->devnum, fmt->iface, fmt->altsetting, err); +			return -EIO; +		} +		subs->interface = -1; +		subs->altset_idx = 0; +	} + +	/* set interface */ +	if (subs->interface != fmt->iface || +	    subs->altset_idx != fmt->altset_idx) { +		err = usb_set_interface(dev, fmt->iface, fmt->altsetting); +		if (err < 0) { +			snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n", +				   dev->devnum, fmt->iface, fmt->altsetting, err); +			return -EIO; +		} +		snd_printdd(KERN_INFO "setting usb interface %d:%d\n", +				fmt->iface, fmt->altsetting); +		subs->interface = fmt->iface; +		subs->altset_idx = fmt->altset_idx; +	} +  	subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,  						   alts, fmt->endpoint, subs->direction,  						   SND_USB_ENDPOINT_TYPE_DATA); @@ -387,7 +401,7 @@ add_sync_ep:  		subs->data_endpoint->sync_master = subs->sync_endpoint;  	} -	if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) +	if ((err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt)) < 0)  		return err;  	subs->cur_audiofmt = fmt; @@ -450,7 +464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,  		struct usb_interface *iface;  		iface = usb_ifnum_to_if(subs->dev, fmt->iface);  		alts = &iface->altsetting[fmt->altset_idx]; -		ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); +		ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate);  		if (ret < 0)  			return ret;  		subs->cur_rate = rate; @@ -460,12 +474,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,  		mutex_lock(&subs->stream->chip->shutdown_mutex);  		/* format changed */  		stop_endpoints(subs, 0, 0, 0); -		deactivate_endpoints(subs); - -		ret = activate_endpoints(subs); -		if (ret < 0) -			goto unlock; -  		ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,  						  subs->sync_endpoint);  		if (ret < 0) @@ -500,6 +508,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)  	subs->period_bytes = 0;  	mutex_lock(&subs->stream->chip->shutdown_mutex);  	stop_endpoints(subs, 0, 1, 1); +	deactivate_endpoints(subs);  	mutex_unlock(&subs->stream->chip->shutdown_mutex);  	return snd_pcm_lib_free_vmalloc_buffer(substream);  } @@ -938,16 +947,20 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)  static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)  { -	int ret;  	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);  	struct snd_usb_substream *subs = &as->substream[direction];  	stop_endpoints(subs, 0, 0, 0); -	ret = deactivate_endpoints(subs); + +	if (!as->chip->shutdown && subs->interface >= 0) { +		usb_set_interface(subs->dev, subs->interface, 0); +		subs->interface = -1; +	} +  	subs->pcm_substream = NULL;  	snd_usb_autosuspend(subs->stream->chip); -	return ret; +	return 0;  }  /* Since a URB can handle only a single linear buffer, we must use double  |