diff options
| author | Takashi Iwai <tiwai@suse.de> | 2014-11-17 22:16:03 +0100 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2014-11-17 22:16:03 +0100 | 
| commit | 39ae97ea4b773be81bae9eec08ed1e5c53606c1a (patch) | |
| tree | 4d55635fb46a86b970c1491cc529eb2770bf3076 /sound | |
| parent | a358a0ef861dae6f8330fb034aaa43adae71ebc1 (diff) | |
| parent | cf9a7f7823c67243da44da2ac47ca944a3108282 (diff) | |
| download | linux-39ae97ea4b773be81bae9eec08ed1e5c53606c1a.tar.bz2 | |
Merge tag 'asoc-v3.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v3.18
As well as the usual driver fixes there's a few other things here:
One is a fix for a race in DPCM which is unfortuantely a rather large
diffstat, this is the result of growing usage of the mainline code and
hence more detailed testing so I'm relatively happy.
The other is a fix for non-DT machine driver matching following some of
the componentization work which is much more focused.
Both have had a while to cook in -next.
Diffstat (limited to 'sound')
| -rw-r--r-- | sound/soc/codecs/cs42l51-i2c.c | 1 | ||||
| -rw-r--r-- | sound/soc/codecs/cs42l51.c | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/cs42l51.h | 1 | ||||
| -rw-r--r-- | sound/soc/codecs/es8328-i2c.c | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/max98090.c | 6 | ||||
| -rw-r--r-- | sound/soc/codecs/rt5645.c | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/rt5670.c | 36 | ||||
| -rw-r--r-- | sound/soc/codecs/sgtl5000.c | 3 | ||||
| -rw-r--r-- | sound/soc/codecs/sgtl5000.h | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/wm_adsp.c | 1 | ||||
| -rw-r--r-- | sound/soc/fsl/fsl_asrc.c | 26 | ||||
| -rw-r--r-- | sound/soc/rockchip/rockchip_i2s.c | 4 | ||||
| -rw-r--r-- | sound/soc/samsung/snow.c | 1 | ||||
| -rw-r--r-- | sound/soc/sh/fsi.c | 3 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/core.c | 3 | ||||
| -rw-r--r-- | sound/soc/soc-core.c | 2 | ||||
| -rw-r--r-- | sound/soc/soc-pcm.c | 72 | 
17 files changed, 121 insertions, 48 deletions
| diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index cee51ae177c1..c40428f25ba5 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c @@ -46,6 +46,7 @@ static struct i2c_driver cs42l51_i2c_driver = {  	.driver = {  		.name = "cs42l51",  		.owner = THIS_MODULE, +		.of_match_table = cs42l51_of_match,  	},  	.probe = cs42l51_i2c_probe,  	.remove = cs42l51_i2c_remove, diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 09488d97de60..669c38fc3034 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -558,11 +558,13 @@ error:  }  EXPORT_SYMBOL_GPL(cs42l51_probe); -static const struct of_device_id cs42l51_of_match[] = { +const struct of_device_id cs42l51_of_match[] = {  	{ .compatible = "cirrus,cs42l51", },  	{ }  };  MODULE_DEVICE_TABLE(of, cs42l51_of_match); +EXPORT_SYMBOL_GPL(cs42l51_of_match); +  MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");  MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");  MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 8c55bf384bc6..0ca805492ac4 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h @@ -22,6 +22,7 @@ struct device;  extern const struct regmap_config cs42l51_regmap;  int cs42l51_probe(struct device *dev, struct regmap *regmap); +extern const struct of_device_id cs42l51_of_match[];  #define CS42L51_CHIP_ID			0x1B  #define CS42L51_CHIP_REV_A		0x00 diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c index aae410d122ee..2d05b5d3a6ce 100644 --- a/sound/soc/codecs/es8328-i2c.c +++ b/sound/soc/codecs/es8328-i2c.c @@ -19,7 +19,7 @@  #include "es8328.h"  static const struct i2c_device_id es8328_id[] = { -	{ "everest,es8328", 0 }, +	{ "es8328", 0 },  	{ }  };  MODULE_DEVICE_TABLE(i2c, es8328_id); diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index d519294f57c7..1229554f1464 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -1941,13 +1941,13 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,  	 *		 0x02 (when master clk is 20MHz to 40MHz)..  	 *		 0x03 (when master clk is 40MHz to 60MHz)..  	 */ -	if ((freq >= 10000000) && (freq < 20000000)) { +	if ((freq >= 10000000) && (freq <= 20000000)) {  		snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,  			M98090_PSCLK_DIV1); -	} else if ((freq >= 20000000) && (freq < 40000000)) { +	} else if ((freq > 20000000) && (freq <= 40000000)) {  		snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,  			M98090_PSCLK_DIV2); -	} else if ((freq >= 40000000) && (freq < 60000000)) { +	} else if ((freq > 40000000) && (freq <= 60000000)) {  		snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,  			M98090_PSCLK_DIV4);  	} else { diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 3fb83bf09768..d16331e0b64d 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -139,6 +139,7 @@ static const struct reg_default rt5645_reg[] = {  	{ 0x76, 0x000a },  	{ 0x77, 0x0c00 },  	{ 0x78, 0x0000 }, +	{ 0x79, 0x0123 },  	{ 0x80, 0x0000 },  	{ 0x81, 0x0000 },  	{ 0x82, 0x0000 }, @@ -334,6 +335,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg)  	case RT5645_DMIC_CTRL2:  	case RT5645_TDM_CTRL_1:  	case RT5645_TDM_CTRL_2: +	case RT5645_TDM_CTRL_3:  	case RT5645_GLB_CLK:  	case RT5645_PLL_CTRL1:  	case RT5645_PLL_CTRL2: diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index ba9d9b4d4857..9bd8b4f63303 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -100,18 +100,18 @@ static const struct reg_default rt5670_reg[] = {  	{ 0x4c, 0x5380 },  	{ 0x4f, 0x0073 },  	{ 0x52, 0x00d3 }, -	{ 0x53, 0xf0f0 }, +	{ 0x53, 0xf000 },  	{ 0x61, 0x0000 },  	{ 0x62, 0x0001 },  	{ 0x63, 0x00c3 },  	{ 0x64, 0x0000 }, -	{ 0x65, 0x0000 }, +	{ 0x65, 0x0001 },  	{ 0x66, 0x0000 },  	{ 0x6f, 0x8000 },  	{ 0x70, 0x8000 },  	{ 0x71, 0x8000 },  	{ 0x72, 0x8000 }, -	{ 0x73, 0x1110 }, +	{ 0x73, 0x7770 },  	{ 0x74, 0x0e00 },  	{ 0x75, 0x1505 },  	{ 0x76, 0x0015 }, @@ -125,21 +125,21 @@ static const struct reg_default rt5670_reg[] = {  	{ 0x83, 0x0000 },  	{ 0x84, 0x0000 },  	{ 0x85, 0x0000 }, -	{ 0x86, 0x0008 }, +	{ 0x86, 0x0004 },  	{ 0x87, 0x0000 },  	{ 0x88, 0x0000 },  	{ 0x89, 0x0000 },  	{ 0x8a, 0x0000 },  	{ 0x8b, 0x0000 }, -	{ 0x8c, 0x0007 }, +	{ 0x8c, 0x0003 },  	{ 0x8d, 0x0000 },  	{ 0x8e, 0x0004 },  	{ 0x8f, 0x1100 },  	{ 0x90, 0x0646 },  	{ 0x91, 0x0c06 },  	{ 0x93, 0x0000 }, -	{ 0x94, 0x0000 }, -	{ 0x95, 0x0000 }, +	{ 0x94, 0x1270 }, +	{ 0x95, 0x1000 },  	{ 0x97, 0x0000 },  	{ 0x98, 0x0000 },  	{ 0x99, 0x0000 }, @@ -150,11 +150,11 @@ static const struct reg_default rt5670_reg[] = {  	{ 0x9e, 0x0400 },  	{ 0xae, 0x7000 },  	{ 0xaf, 0x0000 }, -	{ 0xb0, 0x6000 }, +	{ 0xb0, 0x7000 },  	{ 0xb1, 0x0000 },  	{ 0xb2, 0x0000 },  	{ 0xb3, 0x001f }, -	{ 0xb4, 0x2206 }, +	{ 0xb4, 0x220c },  	{ 0xb5, 0x1f00 },  	{ 0xb6, 0x0000 },  	{ 0xb7, 0x0000 }, @@ -171,25 +171,25 @@ static const struct reg_default rt5670_reg[] = {  	{ 0xcf, 0x1813 },  	{ 0xd0, 0x0690 },  	{ 0xd1, 0x1c17 }, -	{ 0xd3, 0xb320 }, +	{ 0xd3, 0xa220 },  	{ 0xd4, 0x0000 },  	{ 0xd6, 0x0400 },  	{ 0xd9, 0x0809 },  	{ 0xda, 0x0000 },  	{ 0xdb, 0x0001 },  	{ 0xdc, 0x0049 }, -	{ 0xdd, 0x0009 }, +	{ 0xdd, 0x0024 },  	{ 0xe6, 0x8000 },  	{ 0xe7, 0x0000 }, -	{ 0xec, 0xb300 }, +	{ 0xec, 0xa200 },  	{ 0xed, 0x0000 }, -	{ 0xee, 0xb300 }, +	{ 0xee, 0xa200 },  	{ 0xef, 0x0000 },  	{ 0xf8, 0x0000 },  	{ 0xf9, 0x0000 },  	{ 0xfa, 0x8010 },  	{ 0xfb, 0x0033 }, -	{ 0xfc, 0x0080 }, +	{ 0xfc, 0x0100 },  };  static bool rt5670_volatile_register(struct device *dev, unsigned int reg) @@ -1877,6 +1877,10 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = {  	{ "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" },  	{ "DAC1 MIXR", NULL, "DAC Stereo1 Filter" }, +	{ "DAC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll }, +	{ "DAC Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll }, +	{ "DAC Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll }, +  	{ "DAC MIX", NULL, "DAC1 MIXL" },  	{ "DAC MIX", NULL, "DAC1 MIXR" }, @@ -1926,14 +1930,10 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = {  	{ "DAC L1", NULL, "DAC L1 Power" },  	{ "DAC L1", NULL, "Stereo DAC MIXL" }, -	{ "DAC L1", NULL, "PLL1", is_sys_clk_from_pll },  	{ "DAC R1", NULL, "DAC R1 Power" },  	{ "DAC R1", NULL, "Stereo DAC MIXR" }, -	{ "DAC R1", NULL, "PLL1", is_sys_clk_from_pll },  	{ "DAC L2", NULL, "Mono DAC MIXL" }, -	{ "DAC L2", NULL, "PLL1", is_sys_clk_from_pll },  	{ "DAC R2", NULL, "Mono DAC MIXR" }, -	{ "DAC R2", NULL, "PLL1", is_sys_clk_from_pll },  	{ "OUT MIXL", "BST1 Switch", "BST1" },  	{ "OUT MIXL", "INL Switch", "INL VOL" }, diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 6bb77d76561b..dab9b15304af 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1299,8 +1299,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)  	/* enable small pop, introduce 400ms delay in turning off */  	snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, -				SGTL5000_SMALL_POP, -				SGTL5000_SMALL_POP); +				SGTL5000_SMALL_POP, 1);  	/* disable short cut detector */  	snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0); diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 2f8c88931f69..bd7a344bf8c5 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -275,7 +275,7 @@  #define SGTL5000_BIAS_CTRL_MASK			0x000e  #define SGTL5000_BIAS_CTRL_SHIFT		1  #define SGTL5000_BIAS_CTRL_WIDTH		3 -#define SGTL5000_SMALL_POP			0x0001 +#define SGTL5000_SMALL_POP			0  /*   * SGTL5000_CHIP_MIC_CTRL diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f412a9911a75..67124783558a 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1355,6 +1355,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)  			  file, blocks, pos - firmware->size);  out_fw: +	regmap_async_complete(regmap);  	release_firmware(firmware);  	wm_adsp_buf_free(&buf_list);  out: diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index ed866e9a2928..9deabdd2b1a2 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -684,12 +684,38 @@ static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg)  	}  } +static struct reg_default fsl_asrc_reg[] = { +	{ REG_ASRCTR, 0x0000 }, { REG_ASRIER, 0x0000 }, +	{ REG_ASRCNCR, 0x0000 }, { REG_ASRCFG, 0x0000 }, +	{ REG_ASRCSR, 0x0000 }, { REG_ASRCDR1, 0x0000 }, +	{ REG_ASRCDR2, 0x0000 }, { REG_ASRSTR, 0x0000 }, +	{ REG_ASRRA, 0x0000 }, { REG_ASRRB, 0x0000 }, +	{ REG_ASRRC, 0x0000 }, { REG_ASRPM1, 0x0000 }, +	{ REG_ASRPM2, 0x0000 }, { REG_ASRPM3, 0x0000 }, +	{ REG_ASRPM4, 0x0000 }, { REG_ASRPM5, 0x0000 }, +	{ REG_ASRTFR1, 0x0000 }, { REG_ASRCCR, 0x0000 }, +	{ REG_ASRDIA, 0x0000 }, { REG_ASRDOA, 0x0000 }, +	{ REG_ASRDIB, 0x0000 }, { REG_ASRDOB, 0x0000 }, +	{ REG_ASRDIC, 0x0000 }, { REG_ASRDOC, 0x0000 }, +	{ REG_ASRIDRHA, 0x0000 }, { REG_ASRIDRLA, 0x0000 }, +	{ REG_ASRIDRHB, 0x0000 }, { REG_ASRIDRLB, 0x0000 }, +	{ REG_ASRIDRHC, 0x0000 }, { REG_ASRIDRLC, 0x0000 }, +	{ REG_ASR76K, 0x0A47 }, { REG_ASR56K, 0x0DF3 }, +	{ REG_ASRMCRA, 0x0000 }, { REG_ASRFSTA, 0x0000 }, +	{ REG_ASRMCRB, 0x0000 }, { REG_ASRFSTB, 0x0000 }, +	{ REG_ASRMCRC, 0x0000 }, { REG_ASRFSTC, 0x0000 }, +	{ REG_ASRMCR1A, 0x0000 }, { REG_ASRMCR1B, 0x0000 }, +	{ REG_ASRMCR1C, 0x0000 }, +}; +  static const struct regmap_config fsl_asrc_regmap_config = {  	.reg_bits = 32,  	.reg_stride = 4,  	.val_bits = 32,  	.max_register = REG_ASRMCR1C, +	.reg_defaults = fsl_asrc_reg, +	.num_reg_defaults = ARRAY_SIZE(fsl_asrc_reg),  	.readable_reg = fsl_asrc_readable_reg,  	.volatile_reg = fsl_asrc_volatile_reg,  	.writeable_reg = fsl_asrc_writeable_reg, diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index f373e37f8305..c74ba37f862c 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -154,8 +154,10 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)  			while (val) {  				regmap_read(i2s->regmap, I2S_CLR, &val);  				retry--; -				if (!retry) +				if (!retry) {  					dev_warn(i2s->dev, "fail to clear\n"); +					break; +				}  			}  		}  	} diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 0acf5d0eed53..72118a77dd5b 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -110,6 +110,7 @@ static const struct of_device_id snow_of_match[] = {  	{ .compatible = "google,snow-audio-max98095", },  	{},  }; +MODULE_DEVICE_TABLE(of, snow_of_match);  static struct platform_driver snow_driver = {  	.driver = { diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 66fddec9543d..88e5df474ccf 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1711,8 +1711,7 @@ static const struct snd_soc_dai_ops fsi_dai_ops = {  static struct snd_pcm_hardware fsi_pcm_hardware = {  	.info =		SNDRV_PCM_INFO_INTERLEAVED	|  			SNDRV_PCM_INFO_MMAP		| -			SNDRV_PCM_INFO_MMAP_VALID	| -			SNDRV_PCM_INFO_PAUSE, +			SNDRV_PCM_INFO_MMAP_VALID,  	.buffer_bytes_max	= 64 * 1024,  	.period_bytes_min	= 32,  	.period_bytes_max	= 8192, diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1922ec57d10a..70042197f9e2 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -886,8 +886,7 @@ static int rsnd_dai_probe(struct platform_device *pdev,  static struct snd_pcm_hardware rsnd_pcm_hardware = {  	.info =		SNDRV_PCM_INFO_INTERLEAVED	|  			SNDRV_PCM_INFO_MMAP		| -			SNDRV_PCM_INFO_MMAP_VALID	| -			SNDRV_PCM_INFO_PAUSE, +			SNDRV_PCM_INFO_MMAP_VALID,  	.buffer_bytes_max	= 64 * 1024,  	.period_bytes_min	= 32,  	.period_bytes_max	= 8192, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4c8f8a23a0e9..b60ff56ebc0f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -884,7 +884,7 @@ static struct snd_soc_dai *snd_soc_find_dai(  	list_for_each_entry(component, &component_list, list) {  		if (dlc->of_node && component->dev->of_node != dlc->of_node)  			continue; -		if (dlc->name && strcmp(dev_name(component->dev), dlc->name)) +		if (dlc->name && strcmp(component->name, dlc->name))  			continue;  		list_for_each_entry(dai, &component->dai_list, list) {  			if (dlc->dai_name && strcmp(dai->name, dlc->dai_name)) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 002311afdeaa..57277dd79e11 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1522,13 +1522,36 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)  		dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture);  } +static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); + +/* Set FE's runtime_update state; the state is protected via PCM stream lock + * for avoiding the race with trigger callback. + * If the state is unset and a trigger is pending while the previous operation, + * process the pending trigger action here. + */ +static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, +				     int stream, enum snd_soc_dpcm_update state) +{ +	struct snd_pcm_substream *substream = +		snd_soc_dpcm_get_substream(fe, stream); + +	snd_pcm_stream_lock_irq(substream); +	if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { +		dpcm_fe_dai_do_trigger(substream, +				       fe->dpcm[stream].trigger_pending - 1); +		fe->dpcm[stream].trigger_pending = 0; +	} +	fe->dpcm[stream].runtime_update = state; +	snd_pcm_stream_unlock_irq(substream); +} +  static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)  {  	struct snd_soc_pcm_runtime *fe = fe_substream->private_data;  	struct snd_pcm_runtime *runtime = fe_substream->runtime;  	int stream = fe_substream->stream, ret = 0; -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);  	ret = dpcm_be_dai_startup(fe, fe_substream->stream);  	if (ret < 0) { @@ -1550,13 +1573,13 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)  	dpcm_set_fe_runtime(fe_substream);  	snd_pcm_limit_hw_rates(runtime); -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);  	return 0;  unwind:  	dpcm_be_dai_startup_unwind(fe, fe_substream->stream);  be_err: -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);  	return ret;  } @@ -1603,7 +1626,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)  	struct snd_soc_pcm_runtime *fe = substream->private_data;  	int stream = substream->stream; -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);  	/* shutdown the BEs */  	dpcm_be_dai_shutdown(fe, substream->stream); @@ -1617,7 +1640,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)  	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);  	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);  	return 0;  } @@ -1665,7 +1688,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)  	int err, stream = substream->stream;  	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);  	dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name); @@ -1680,7 +1703,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)  	err = dpcm_be_dai_hw_free(fe, stream);  	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);  	mutex_unlock(&fe->card->mutex);  	return 0; @@ -1773,7 +1796,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,  	int ret, stream = substream->stream;  	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);  	memcpy(&fe->dpcm[substream->stream].hw_params, params,  			sizeof(struct snd_pcm_hw_params)); @@ -1796,7 +1819,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,  		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;  out: -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);  	mutex_unlock(&fe->card->mutex);  	return ret;  } @@ -1910,7 +1933,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,  }  EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); -static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) +static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)  {  	struct snd_soc_pcm_runtime *fe = substream->private_data;  	int stream = substream->stream, ret; @@ -1984,6 +2007,23 @@ out:  	return ret;  } +static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) +{ +	struct snd_soc_pcm_runtime *fe = substream->private_data; +	int stream = substream->stream; + +	/* if FE's runtime_update is already set, we're in race; +	 * process this trigger later at exit +	 */ +	if (fe->dpcm[stream].runtime_update != SND_SOC_DPCM_UPDATE_NO) { +		fe->dpcm[stream].trigger_pending = cmd + 1; +		return 0; /* delayed, assuming it's successful */ +	} + +	/* we're alone, let's trigger */ +	return dpcm_fe_dai_do_trigger(substream, cmd); +} +  int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)  {  	struct snd_soc_dpcm *dpcm; @@ -2027,7 +2067,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)  	dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name); -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);  	/* there is no point preparing this FE if there are no BEs */  	if (list_empty(&fe->dpcm[stream].be_clients)) { @@ -2054,7 +2094,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)  	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;  out: -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);  	mutex_unlock(&fe->card->mutex);  	return ret; @@ -2201,11 +2241,11 @@ static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)  {  	int ret; -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);  	ret = dpcm_run_update_startup(fe, stream);  	if (ret < 0)  		dev_err(fe->dev, "ASoC: failed to startup some BEs\n"); -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);  	return ret;  } @@ -2214,11 +2254,11 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)  {  	int ret; -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);  	ret = dpcm_run_update_shutdown(fe, stream);  	if (ret < 0)  		dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n"); -	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; +	dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);  	return ret;  } |