diff options
Diffstat (limited to 'sound')
| -rw-r--r-- | sound/core/compress_offload.c | 8 | ||||
| -rw-r--r-- | sound/pci/hda/hda_codec.c | 12 | ||||
| -rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
| -rw-r--r-- | sound/pci/hda/hda_intel.c | 2 | ||||
| -rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 6 | ||||
| -rw-r--r-- | sound/pci/ice1712/prodigy_hifi.c | 3 | ||||
| -rw-r--r-- | sound/soc/codecs/arizona.c | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/mc13783.c | 8 | ||||
| -rw-r--r-- | sound/soc/codecs/wm8904.c | 2 | ||||
| -rw-r--r-- | sound/soc/fsl/imx-sgtl5000.c | 2 | ||||
| -rw-r--r-- | sound/soc/omap/am3517evm.c | 2 | ||||
| -rw-r--r-- | sound/soc/samsung/dma.c | 8 | ||||
| -rw-r--r-- | sound/soc/soc-dapm.c | 5 | ||||
| -rw-r--r-- | sound/soc/spear/spear_pcm.c | 2 | ||||
| -rw-r--r-- | sound/soc/tegra/tegra_alc5632.c | 1 | ||||
| -rw-r--r-- | sound/soc/tegra/tegra_pcm.c | 4 | ||||
| -rw-r--r-- | sound/soc/ux500/ux500_msp_i2s.c | 25 | ||||
| -rw-r--r-- | sound/usb/card.c | 4 | ||||
| -rw-r--r-- | sound/usb/endpoint.c | 24 | ||||
| -rw-r--r-- | sound/usb/endpoint.h | 3 | ||||
| -rw-r--r-- | sound/usb/pcm.c | 70 | 
21 files changed, 115 insertions, 79 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index ec2118d0e27..eb60cb8dbb8 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -80,14 +80,12 @@ static int snd_compr_open(struct inode *inode, struct file *f)  	int maj = imajor(inode);  	int ret; -	if (f->f_flags & O_WRONLY) +	if ((f->f_flags & O_ACCMODE) == O_WRONLY)  		dirn = SND_COMPRESS_PLAYBACK; -	else if (f->f_flags & O_RDONLY) +	else if ((f->f_flags & O_ACCMODE) == O_RDONLY)  		dirn = SND_COMPRESS_CAPTURE; -	else { -		pr_err("invalid direction\n"); +	else  		return -EINVAL; -	}  	if (maj == snd_major)  		compr = snd_lookup_minor_data(iminor(inode), diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f560051a949..1c65cc5e3a3 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1209,6 +1209,9 @@ static void snd_hda_codec_free(struct hda_codec *codec)  	kfree(codec);  } +static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, +				hda_nid_t fg, unsigned int power_state); +  static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,  				unsigned int power_state); @@ -1317,6 +1320,10 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,  					   AC_VERB_GET_SUBSYSTEM_ID, 0);  	} +	codec->epss = snd_hda_codec_get_supported_ps(codec, +					codec->afg ? codec->afg : codec->mfg, +					AC_PWRST_EPSS); +  	/* power-up all before initialization */  	hda_set_power_state(codec,  			    codec->afg ? codec->afg : codec->mfg, @@ -2346,6 +2353,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)  	}  	if (codec->patch_ops.free)  		codec->patch_ops.free(codec); +	memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));  	snd_hda_jack_tbl_clear(codec);  	codec->proc_widget_hook = NULL;  	codec->spec = NULL; @@ -2361,7 +2369,6 @@ int snd_hda_codec_reset(struct hda_codec *codec)  	codec->num_pcms = 0;  	codec->pcm_info = NULL;  	codec->preset = NULL; -	memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));  	codec->slave_dig_outs = NULL;  	codec->spdif_status_reset = 0;  	module_put(codec->owner); @@ -3543,8 +3550,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,  	/* this delay seems necessary to avoid click noise at power-down */  	if (power_state == AC_PWRST_D3) {  		/* transition time less than 10ms for power down */ -		bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS); -		msleep(epss ? 10 : 100); +		msleep(codec->epss ? 10 : 100);  	}  	/* repeat power states setting at most 10 times*/ diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 7fbc1bcaf1a..e5a7e19a807 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -862,6 +862,7 @@ struct hda_codec {  	unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */  	unsigned int no_jack_detect:1;	/* Machine has no jack-detection */  	unsigned int pcm_format_first:1; /* PCM format must be set first */ +	unsigned int epss:1;		/* supporting EPSS? */  #ifdef CONFIG_SND_HDA_POWER_SAVE  	unsigned int power_on :1;	/* current (global) power-state */  	int power_transition;	/* power-state in transition */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 60882c62f18..c4763c52eaf 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2701,6 +2701,8 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {  	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), +	SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF), +	SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF),  	SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),  	SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ea5775a1a7d..3d4722f0a1c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1075,7 +1075,7 @@ static struct snd_kcontrol_new stac_smux_mixer = {  static const char * const slave_pfxs[] = {  	"Front", "Surround", "Center", "LFE", "Side", -	"Headphone", "Speaker", "IEC958", +	"Headphone", "Speaker", "IEC958", "PCM",  	NULL  }; @@ -4543,6 +4543,9 @@ static void stac92xx_line_out_detect(struct hda_codec *codec,  	struct auto_pin_cfg *cfg = &spec->autocfg;  	int i; +	if (cfg->speaker_outs == 0) +		return; +  	for (i = 0; i < cfg->line_outs; i++) {  		if (presence)  			break; @@ -5531,6 +5534,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)  		snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e);  	} +	codec->epss = 0; /* longer delay needed for D3 */  	codec->no_trigger_sense = 1;  	codec->spec = spec; diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 764cc93dbca..075d5aa1fee 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -297,6 +297,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem  }  static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); +static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);  static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {      { @@ -307,7 +308,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {  	.info = ak4396_dac_vol_info,  	.get = ak4396_dac_vol_get,  	.put = ak4396_dac_vol_put, -	.tlv = { .p = db_scale_wm_dac }, +	.tlv = { .p = ak4396_db_scale },      },  }; diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5c9cacaf2d5..1cf7a32d1b2 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -426,7 +426,7 @@ static const int arizona_44k1_bclk_rates[] = {  	940800,  	1411200,  	1881600, -	2882400, +	2822400,  	3763200,  	5644800,  	7526400, diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 8f726c063f4..115a4030181 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -659,7 +659,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = {  		.id = MC13783_ID_STEREO_DAC,  		.playback = {  			.stream_name = "Playback", -			.channels_min = 1, +			.channels_min = 2,  			.channels_max = 2,  			.rates = SNDRV_PCM_RATE_8000_96000,  			.formats = MC13783_FORMATS, @@ -670,7 +670,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = {  		.id = MC13783_ID_STEREO_CODEC,  		.capture = {  			.stream_name = "Capture", -			.channels_min = 1, +			.channels_min = 2,  			.channels_max = 2,  			.rates = MC13783_RATES_RECORD,  			.formats = MC13783_FORMATS, @@ -692,14 +692,14 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {  		.id = MC13783_ID_SYNC,  		.playback = {  			.stream_name = "Playback", -			.channels_min = 1, +			.channels_min = 2,  			.channels_max = 2,  			.rates = SNDRV_PCM_RATE_8000_96000,  			.formats = MC13783_FORMATS,  		},  		.capture = {  			.stream_name = "Capture", -			.channels_min = 1, +			.channels_min = 2,  			.channels_max = 2,  			.rates = MC13783_RATES_RECORD,  			.formats = MC13783_FORMATS, diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 0013afe48e6..dc4262eea4b 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -100,7 +100,7 @@ static const struct reg_default wm8904_reg_defaults[] = {  	{ 14,  0x0000 },     /* R14  - Power Management 2 */  	{ 15,  0x0000 },     /* R15  - Power Management 3 */  	{ 18,  0x0000 },     /* R18  - Power Management 6 */ -	{ 19,  0x945E },     /* R20  - Clock Rates 0 */ +	{ 20,  0x945E },     /* R20  - Clock Rates 0 */  	{ 21,  0x0C05 },     /* R21  - Clock Rates 1 */  	{ 22,  0x0006 },     /* R22  - Clock Rates 2 */  	{ 24,  0x0050 },     /* R24  - Audio Interface 0 */ diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index fb21b17f17f..199408ec426 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -94,7 +94,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)  		dev_err(&pdev->dev, "audmux internal port setup failed\n");  		return ret;  	} -	imx_audmux_v2_configure_port(ext_port, +	ret = imx_audmux_v2_configure_port(ext_port,  			IMX_AUDMUX_V2_PTCR_SYN,  			IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));  	if (ret) { diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 009533ab8d1..df65f98211e 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c @@ -59,7 +59,7 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,  		return ret;  	} -	snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, +	ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0,  				SND_SOC_CLOCK_IN);  	if (ret < 0) {  		printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index f3ebc38c10f..b70964ea448 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -34,9 +34,7 @@ static const struct snd_pcm_hardware dma_hardware = {  	.info			= SNDRV_PCM_INFO_INTERLEAVED |  				    SNDRV_PCM_INFO_BLOCK_TRANSFER |  				    SNDRV_PCM_INFO_MMAP | -				    SNDRV_PCM_INFO_MMAP_VALID | -				    SNDRV_PCM_INFO_PAUSE | -				    SNDRV_PCM_INFO_RESUME, +				    SNDRV_PCM_INFO_MMAP_VALID,  	.formats		= SNDRV_PCM_FMTBIT_S16_LE |  				    SNDRV_PCM_FMTBIT_U16_LE |  				    SNDRV_PCM_FMTBIT_U8 | @@ -248,15 +246,11 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)  	switch (cmd) {  	case SNDRV_PCM_TRIGGER_START: -	case SNDRV_PCM_TRIGGER_RESUME: -	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:  		prtd->state |= ST_RUNNING;  		prtd->params->ops->trigger(prtd->params->ch);  		break;  	case SNDRV_PCM_TRIGGER_STOP: -	case SNDRV_PCM_TRIGGER_SUSPEND: -	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:  		prtd->state &= ~ST_RUNNING;  		prtd->params->ops->stop(prtd->params->ch);  		break; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dd7c49fafd7..f90139b5f50 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -291,8 +291,11 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,  		if (dapm->codec->driver->set_bias_level)  			ret = dapm->codec->driver->set_bias_level(dapm->codec,  								  level); -	} else +		else +			dapm->bias_level = level; +	} else if (!card || dapm != &card->dapm) {  		dapm->bias_level = level; +	}  	if (ret != 0)  		goto out; diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c index 97c2cac8e92..8c7f2372944 100644 --- a/sound/soc/spear/spear_pcm.c +++ b/sound/soc/spear/spear_pcm.c @@ -138,7 +138,7 @@ static void spear_pcm_free(struct snd_pcm *pcm)  			continue;  		buf = &substream->dma_buffer; -		if (!buf && !buf->area) +		if (!buf || !buf->area)  			continue;  		dma_free_writecombine(pcm->card->dev, buf->bytes, diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index e463529b38b..76cb1b363b7 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -89,7 +89,6 @@ static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {  	.name = "Headset detection",  	.report = SND_JACK_HEADSET,  	.debounce_time = 150, -	.invert = 1,  };  static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = { diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 5658bcec193..8d6900c1ee4 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -334,11 +334,11 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {  		slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;  		slave_config.dst_addr = dmap->addr; -		slave_config.src_maxburst = 0; +		slave_config.dst_maxburst = 4;  	} else {  		slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;  		slave_config.src_addr = dmap->addr; -		slave_config.dst_maxburst = 0; +		slave_config.src_maxburst = 4;  	}  	slave_config.slave_id = dmap->req_sel; diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 5c472f335a6..eb85113d472 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -663,7 +663,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,  			struct ux500_msp **msp_p,  			struct msp_i2s_platform_data *platform_data)  { -	int ret = 0;  	struct resource *res = NULL;  	struct i2s_controller *i2s_cont;  	struct ux500_msp *msp; @@ -685,15 +684,14 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,  	if (res == NULL) {  		dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n",  			__func__); -		ret = -ENOMEM; -		goto err_res; +		return -ENOMEM;  	} -	msp->registers = ioremap(res->start, (res->end - res->start + 1)); +	msp->registers = devm_ioremap(&pdev->dev, res->start, +				      resource_size(res));  	if (msp->registers == NULL) {  		dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__); -		ret = -ENOMEM; -		goto err_res; +		return -ENOMEM;  	}  	msp->msp_state = MSP_STATE_IDLE; @@ -705,7 +703,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,  		dev_err(&pdev->dev,  			"%s: ERROR: Failed to allocate I2S-controller!\n",  			__func__); -		goto err_i2s_cont; +		return -ENOMEM;  	}  	i2s_cont->dev.parent = &pdev->dev;  	i2s_cont->data = (void *)msp; @@ -716,14 +714,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,  	msp->i2s_cont = i2s_cont;  	return 0; - -err_i2s_cont: -	iounmap(msp->registers); - -err_res: -	devm_kfree(&pdev->dev, msp); - -	return ret;  }  void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev, @@ -732,11 +722,6 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,  	dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);  	device_unregister(&msp->i2s_cont->dev); -	devm_kfree(&pdev->dev, msp->i2s_cont); - -	iounmap(msp->registers); - -	devm_kfree(&pdev->dev, msp);  }  MODULE_LICENSE("GPL v2"); diff --git a/sound/usb/card.c b/sound/usb/card.c index d5b5c3388e2..4a469f0cb6d 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -553,7 +553,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,  				     struct snd_usb_audio *chip)  {  	struct snd_card *card; -	struct list_head *p; +	struct list_head *p, *n;  	if (chip == (void *)-1L)  		return; @@ -570,7 +570,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,  			snd_usb_stream_disconnect(p);  		}  		/* release the endpoint resources */ -		list_for_each(p, &chip->ep_list) { +		list_for_each_safe(p, n, &chip->ep_list) {  			snd_usb_endpoint_free(p);  		}  		/* release the midi resources */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index c4118120268..d6e2bb49c59 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -141,7 +141,7 @@ int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)   *   * For implicit feedback, next_packet_size() is unused.   */ -static int next_packet_size(struct snd_usb_endpoint *ep) +int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)  {  	unsigned long flags;  	int ret; @@ -177,15 +177,6 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,  		ep->retire_data_urb(ep->data_subs, urb);  } -static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep, -				       struct snd_urb_ctx *ctx) -{ -	int i; - -	for (i = 0; i < ctx->packets; ++i) -		ctx->packet_size[i] = next_packet_size(ep); -} -  /*   * Prepare a PLAYBACK urb for submission to the bus.   */ @@ -370,7 +361,6 @@ static void snd_complete_urb(struct urb *urb)  			goto exit_clear;  		} -		prepare_outbound_urb_sizes(ep, ctx);  		prepare_outbound_urb(ep, ctx);  	} else {  		retire_inbound_urb(ep, ctx); @@ -799,7 +789,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,  /**   * snd_usb_endpoint_start: start an snd_usb_endpoint   * - * @ep: the endpoint to start + * @ep:		the endpoint to start + * @can_sleep:	flag indicating whether the operation is executed in + * 		non-atomic context   *   * A call to this function will increment the use count of the endpoint.   * In case it is not already running, the URBs for this endpoint will be @@ -809,7 +801,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,   *   * Returns an error if the URB submission failed, 0 in all other cases.   */ -int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) +int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)  {  	int err;  	unsigned int i; @@ -821,6 +813,11 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)  	if (++ep->use_count != 1)  		return 0; +	/* just to be sure */ +	deactivate_urbs(ep, 0, can_sleep); +	if (can_sleep) +		wait_clear_urbs(ep); +  	ep->active_mask = 0;  	ep->unlink_mask = 0;  	ep->phase = 0; @@ -850,7 +847,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)  			goto __error;  		if (usb_pipeout(ep->pipe)) { -			prepare_outbound_urb_sizes(ep, urb->context);  			prepare_outbound_urb(ep, urb->context);  		} else {  			prepare_inbound_urb(ep, urb->context); diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index ee2723fb174..cbbbdf226d6 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -13,7 +13,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,  				struct audioformat *fmt,  				struct snd_usb_endpoint *sync_ep); -int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep); +int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);  void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,  			   int force, int can_sleep, int wait);  int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); @@ -21,6 +21,7 @@ int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);  void snd_usb_endpoint_free(struct list_head *head);  int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep); +int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);  void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,  			     struct snd_usb_endpoint *sender, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 62ec808ed79..f782ce19bf5 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,  	}  } -static int start_endpoints(struct snd_usb_substream *subs) +static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)  {  	int err; @@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs)  		snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);  		ep->data_subs = subs; -		err = snd_usb_endpoint_start(ep); +		err = snd_usb_endpoint_start(ep, can_sleep);  		if (err < 0) {  			clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);  			return err; @@ -236,10 +236,25 @@ static int start_endpoints(struct snd_usb_substream *subs)  	    !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {  		struct snd_usb_endpoint *ep = subs->sync_endpoint; +		if (subs->data_endpoint->iface != subs->sync_endpoint->iface || +		    subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) { +			err = usb_set_interface(subs->dev, +						subs->sync_endpoint->iface, +						subs->sync_endpoint->alt_idx); +			if (err < 0) { +				snd_printk(KERN_ERR +					   "%d:%d:%d: cannot set interface (%d)\n", +					   subs->dev->devnum, +					   subs->sync_endpoint->iface, +					   subs->sync_endpoint->alt_idx, err); +				return -EIO; +			} +		} +  		snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);  		ep->sync_slave = subs->data_endpoint; -		err = snd_usb_endpoint_start(ep); +		err = snd_usb_endpoint_start(ep, can_sleep);  		if (err < 0) {  			clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);  			return err; @@ -544,13 +559,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)  	subs->last_frame_number = 0;  	runtime->delay = 0; -	/* clear the pending deactivation on the target EPs */ -	deactivate_endpoints(subs); -  	/* for playback, submit the URBs now; otherwise, the first hwptr_done  	 * updates for all URBs would happen at the same time when starting */  	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) -		return start_endpoints(subs); +		return start_endpoints(subs, 1);  	return 0;  } @@ -1032,6 +1044,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,  				 struct urb *urb)  {  	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; +	struct snd_usb_endpoint *ep = subs->data_endpoint;  	struct snd_urb_ctx *ctx = urb->context;  	unsigned int counts, frames, bytes;  	int i, stride, period_elapsed = 0; @@ -1043,7 +1056,11 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,  	urb->number_of_packets = 0;  	spin_lock_irqsave(&subs->lock, flags);  	for (i = 0; i < ctx->packets; i++) { -		counts = ctx->packet_size[i]; +		if (ctx->packet_size[i]) +			counts = ctx->packet_size[i]; +		else +			counts = snd_usb_endpoint_next_packet_size(ep); +  		/* set up descriptor */  		urb->iso_frame_desc[i].offset = frames * stride;  		urb->iso_frame_desc[i].length = counts * stride; @@ -1094,7 +1111,16 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,  	subs->hwptr_done += bytes;  	if (subs->hwptr_done >= runtime->buffer_size * stride)  		subs->hwptr_done -= runtime->buffer_size * stride; + +	/* update delay with exact number of samples queued */ +	runtime->delay = subs->last_delay;  	runtime->delay += frames; +	subs->last_delay = runtime->delay; + +	/* realign last_frame_number */ +	subs->last_frame_number = usb_get_current_frame_number(subs->dev); +	subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ +  	spin_unlock_irqrestore(&subs->lock, flags);  	urb->transfer_buffer_length = bytes;  	if (period_elapsed) @@ -1112,12 +1138,32 @@ static void retire_playback_urb(struct snd_usb_substream *subs,  	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;  	int stride = runtime->frame_bits >> 3;  	int processed = urb->transfer_buffer_length / stride; +	int est_delay; + +	/* ignore the delay accounting when procssed=0 is given, i.e. +	 * silent payloads are procssed before handling the actual data +	 */ +	if (!processed) +		return;  	spin_lock_irqsave(&subs->lock, flags); -	if (processed > runtime->delay) -		runtime->delay = 0; +	est_delay = snd_usb_pcm_delay(subs, runtime->rate); +	/* update delay with exact number of samples played */ +	if (processed > subs->last_delay) +		subs->last_delay = 0;  	else -		runtime->delay -= processed; +		subs->last_delay -= processed; +	runtime->delay = subs->last_delay; + +	/* +	 * Report when delay estimate is off by more than 2ms. +	 * The error should be lower than 2ms since the estimate relies +	 * on two reads of a counter updated every ms. +	 */ +	if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) +		snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n", +			est_delay, subs->last_delay); +  	spin_unlock_irqrestore(&subs->lock, flags);  } @@ -1175,7 +1221,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream  	switch (cmd) {  	case SNDRV_PCM_TRIGGER_START: -		err = start_endpoints(subs); +		err = start_endpoints(subs, 0);  		if (err < 0)  			return err;  |