Browse Source

Merge branch 'asoc-4.18' into asoc-linus

Mark Brown 7 years ago
parent
commit
6c08483987

+ 2 - 1
sound/soc/amd/acp-pcm-dma.c

@@ -773,7 +773,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
 	if (WARN_ON(!rtd))
 	if (WARN_ON(!rtd))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	rtd->i2s_instance = pinfo->i2s_instance;
+	if (pinfo)
+		rtd->i2s_instance = pinfo->i2s_instance;
 	if (adata->asic_type == CHIP_STONEY) {
 	if (adata->asic_type == CHIP_STONEY) {
 		val = acp_reg_read(adata->acp_mmio,
 		val = acp_reg_read(adata->acp_mmio,
 				   mmACP_I2S_16BIT_RESOLUTION_EN);
 				   mmACP_I2S_16BIT_RESOLUTION_EN);

+ 8 - 0
sound/soc/codecs/cs47l24.c

@@ -1283,6 +1283,12 @@ static int cs47l24_probe(struct platform_device *pdev)
 		return ret;
 		return ret;
 	}
 	}
 
 
+	ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1);
+	if (ret != 0)
+		dev_warn(&pdev->dev,
+			 "Failed to set compressed IRQ as a wake source: %d\n",
+			 ret);
+
 	arizona_init_common(arizona);
 	arizona_init_common(arizona);
 
 
 	ret = arizona_init_vol_limit(arizona);
 	ret = arizona_init_vol_limit(arizona);
@@ -1306,6 +1312,7 @@ static int cs47l24_probe(struct platform_device *pdev)
 err_spk_irqs:
 err_spk_irqs:
 	arizona_free_spk_irqs(arizona);
 	arizona_free_spk_irqs(arizona);
 err_dsp_irq:
 err_dsp_irq:
+	arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24);
 
 
 	return ret;
 	return ret;
@@ -1323,6 +1330,7 @@ static int cs47l24_remove(struct platform_device *pdev)
 
 
 	arizona_free_spk_irqs(arizona);
 	arizona_free_spk_irqs(arizona);
 
 
+	arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24);
 
 
 	return 0;
 	return 0;

+ 15 - 6
sound/soc/codecs/hdmi-codec.c

@@ -291,10 +291,6 @@ static const struct snd_soc_dapm_widget hdmi_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("TX"),
 	SND_SOC_DAPM_OUTPUT("TX"),
 };
 };
 
 
-static const struct snd_soc_dapm_route hdmi_routes[] = {
-	{ "TX", NULL, "Playback" },
-};
-
 enum {
 enum {
 	DAI_ID_I2S = 0,
 	DAI_ID_I2S = 0,
 	DAI_ID_SPDIF,
 	DAI_ID_SPDIF,
@@ -689,9 +685,23 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
 	return snd_ctl_add(rtd->card->snd_card, kctl);
 	return snd_ctl_add(rtd->card->snd_card, kctl);
 }
 }
 
 
+static int hdmi_dai_probe(struct snd_soc_dai *dai)
+{
+	struct snd_soc_dapm_context *dapm;
+	struct snd_soc_dapm_route route = {
+		.sink = "TX",
+		.source = dai->driver->playback.stream_name,
+	};
+
+	dapm = snd_soc_component_get_dapm(dai->component);
+
+	return snd_soc_dapm_add_routes(dapm, &route, 1);
+}
+
 static const struct snd_soc_dai_driver hdmi_i2s_dai = {
 static const struct snd_soc_dai_driver hdmi_i2s_dai = {
 	.name = "i2s-hifi",
 	.name = "i2s-hifi",
 	.id = DAI_ID_I2S,
 	.id = DAI_ID_I2S,
+	.probe = hdmi_dai_probe,
 	.playback = {
 	.playback = {
 		.stream_name = "I2S Playback",
 		.stream_name = "I2S Playback",
 		.channels_min = 2,
 		.channels_min = 2,
@@ -707,6 +717,7 @@ static const struct snd_soc_dai_driver hdmi_i2s_dai = {
 static const struct snd_soc_dai_driver hdmi_spdif_dai = {
 static const struct snd_soc_dai_driver hdmi_spdif_dai = {
 	.name = "spdif-hifi",
 	.name = "spdif-hifi",
 	.id = DAI_ID_SPDIF,
 	.id = DAI_ID_SPDIF,
+	.probe = hdmi_dai_probe,
 	.playback = {
 	.playback = {
 		.stream_name = "SPDIF Playback",
 		.stream_name = "SPDIF Playback",
 		.channels_min = 2,
 		.channels_min = 2,
@@ -733,8 +744,6 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
 static const struct snd_soc_component_driver hdmi_driver = {
 static const struct snd_soc_component_driver hdmi_driver = {
 	.dapm_widgets		= hdmi_widgets,
 	.dapm_widgets		= hdmi_widgets,
 	.num_dapm_widgets	= ARRAY_SIZE(hdmi_widgets),
 	.num_dapm_widgets	= ARRAY_SIZE(hdmi_widgets),
-	.dapm_routes		= hdmi_routes,
-	.num_dapm_routes	= ARRAY_SIZE(hdmi_routes),
 	.of_xlate_dai_id	= hdmi_of_xlate_dai_id,
 	.of_xlate_dai_id	= hdmi_of_xlate_dai_id,
 	.idle_bias_on		= 1,
 	.idle_bias_on		= 1,
 	.use_pmdown_time	= 1,
 	.use_pmdown_time	= 1,

+ 1 - 0
sound/soc/codecs/max98373.c

@@ -488,6 +488,7 @@ static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv,
 static bool max98373_readable_register(struct device *dev, unsigned int reg)
 static bool max98373_readable_register(struct device *dev, unsigned int reg)
 {
 {
 	switch (reg) {
 	switch (reg) {
+	case MAX98373_R2000_SW_RESET:
 	case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3:
 	case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3:
 	case MAX98373_R2010_IRQ_CTRL:
 	case MAX98373_R2010_IRQ_CTRL:
 	case MAX98373_R2014_THERM_WARN_THRESH
 	case MAX98373_R2014_THERM_WARN_THRESH

+ 4 - 4
sound/soc/codecs/rt5514.c

@@ -64,8 +64,8 @@ static const struct reg_sequence rt5514_patch[] = {
 	{RT5514_ANA_CTRL_LDO10,		0x00028604},
 	{RT5514_ANA_CTRL_LDO10,		0x00028604},
 	{RT5514_ANA_CTRL_ADCFED,	0x00000800},
 	{RT5514_ANA_CTRL_ADCFED,	0x00000800},
 	{RT5514_ASRC_IN_CTRL1,		0x00000003},
 	{RT5514_ASRC_IN_CTRL1,		0x00000003},
-	{RT5514_DOWNFILTER0_CTRL3,	0x10000362},
-	{RT5514_DOWNFILTER1_CTRL3,	0x10000362},
+	{RT5514_DOWNFILTER0_CTRL3,	0x10000352},
+	{RT5514_DOWNFILTER1_CTRL3,	0x10000352},
 };
 };
 
 
 static const struct reg_default rt5514_reg[] = {
 static const struct reg_default rt5514_reg[] = {
@@ -92,10 +92,10 @@ static const struct reg_default rt5514_reg[] = {
 	{RT5514_ASRC_IN_CTRL1,		0x00000003},
 	{RT5514_ASRC_IN_CTRL1,		0x00000003},
 	{RT5514_DOWNFILTER0_CTRL1,	0x00020c2f},
 	{RT5514_DOWNFILTER0_CTRL1,	0x00020c2f},
 	{RT5514_DOWNFILTER0_CTRL2,	0x00020c2f},
 	{RT5514_DOWNFILTER0_CTRL2,	0x00020c2f},
-	{RT5514_DOWNFILTER0_CTRL3,	0x10000362},
+	{RT5514_DOWNFILTER0_CTRL3,	0x10000352},
 	{RT5514_DOWNFILTER1_CTRL1,	0x00020c2f},
 	{RT5514_DOWNFILTER1_CTRL1,	0x00020c2f},
 	{RT5514_DOWNFILTER1_CTRL2,	0x00020c2f},
 	{RT5514_DOWNFILTER1_CTRL2,	0x00020c2f},
-	{RT5514_DOWNFILTER1_CTRL3,	0x10000362},
+	{RT5514_DOWNFILTER1_CTRL3,	0x10000352},
 	{RT5514_ANA_CTRL_LDO10,		0x00028604},
 	{RT5514_ANA_CTRL_LDO10,		0x00028604},
 	{RT5514_ANA_CTRL_LDO18_16,	0x02000345},
 	{RT5514_ANA_CTRL_LDO18_16,	0x02000345},
 	{RT5514_ANA_CTRL_ADC12,		0x0000a2a8},
 	{RT5514_ANA_CTRL_ADC12,		0x0000a2a8},

+ 8 - 0
sound/soc/codecs/wm5102.c

@@ -2094,6 +2094,12 @@ static int wm5102_probe(struct platform_device *pdev)
 		return ret;
 		return ret;
 	}
 	}
 
 
+	ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1);
+	if (ret != 0)
+		dev_warn(&pdev->dev,
+			 "Failed to set compressed IRQ as a wake source: %d\n",
+			 ret);
+
 	arizona_init_common(arizona);
 	arizona_init_common(arizona);
 
 
 	ret = arizona_init_vol_limit(arizona);
 	ret = arizona_init_vol_limit(arizona);
@@ -2117,6 +2123,7 @@ static int wm5102_probe(struct platform_device *pdev)
 err_spk_irqs:
 err_spk_irqs:
 	arizona_free_spk_irqs(arizona);
 	arizona_free_spk_irqs(arizona);
 err_dsp_irq:
 err_dsp_irq:
+	arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102);
 
 
 	return ret;
 	return ret;
@@ -2133,6 +2140,7 @@ static int wm5102_remove(struct platform_device *pdev)
 
 
 	arizona_free_spk_irqs(arizona);
 	arizona_free_spk_irqs(arizona);
 
 
+	arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102);
 
 
 	return 0;
 	return 0;

+ 8 - 0
sound/soc/codecs/wm5110.c

@@ -2455,6 +2455,12 @@ static int wm5110_probe(struct platform_device *pdev)
 		return ret;
 		return ret;
 	}
 	}
 
 
+	ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1);
+	if (ret != 0)
+		dev_warn(&pdev->dev,
+			 "Failed to set compressed IRQ as a wake source: %d\n",
+			 ret);
+
 	arizona_init_common(arizona);
 	arizona_init_common(arizona);
 
 
 	ret = arizona_init_vol_limit(arizona);
 	ret = arizona_init_vol_limit(arizona);
@@ -2478,6 +2484,7 @@ static int wm5110_probe(struct platform_device *pdev)
 err_spk_irqs:
 err_spk_irqs:
 	arizona_free_spk_irqs(arizona);
 	arizona_free_spk_irqs(arizona);
 err_dsp_irq:
 err_dsp_irq:
+	arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110);
 
 
 	return ret;
 	return ret;
@@ -2496,6 +2503,7 @@ static int wm5110_remove(struct platform_device *pdev)
 
 
 	arizona_free_spk_irqs(arizona);
 	arizona_free_spk_irqs(arizona);
 
 
+	arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110);
 	arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110);
 
 
 	return 0;
 	return 0;

+ 2 - 2
sound/soc/codecs/wm8988.c

@@ -522,7 +522,7 @@ static inline int get_coeff(int mclk, int rate)
 /* The set of rates we can generate from the above for each SYSCLK */
 /* The set of rates we can generate from the above for each SYSCLK */
 
 
 static const unsigned int rates_12288[] = {
 static const unsigned int rates_12288[] = {
-	8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000,
+	8000, 12000, 16000, 24000, 32000, 48000, 96000,
 };
 };
 
 
 static const struct snd_pcm_hw_constraint_list constraints_12288 = {
 static const struct snd_pcm_hw_constraint_list constraints_12288 = {
@@ -540,7 +540,7 @@ static const struct snd_pcm_hw_constraint_list constraints_112896 = {
 };
 };
 
 
 static const unsigned int rates_12[] = {
 static const unsigned int rates_12[] = {
-	8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000,
+	8000, 11025, 12000, 16000, 22050, 24000, 32000, 41100, 48000,
 	48000, 88235, 96000,
 	48000, 88235, 96000,
 };
 };
 
 

+ 8 - 2
sound/soc/codecs/wm_adsp.c

@@ -2642,7 +2642,10 @@ int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
 			   struct snd_ctl_elem_value *ucontrol)
 			   struct snd_ctl_elem_value *ucontrol)
 {
 {
 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
-	struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
+	struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
+	struct soc_mixer_control *mc =
+		(struct soc_mixer_control *)kcontrol->private_value;
+	struct wm_adsp *dsp = &dsps[mc->shift - 1];
 
 
 	ucontrol->value.integer.value[0] = dsp->preloaded;
 	ucontrol->value.integer.value[0] = dsp->preloaded;
 
 
@@ -2654,10 +2657,11 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
 			   struct snd_ctl_elem_value *ucontrol)
 			   struct snd_ctl_elem_value *ucontrol)
 {
 {
 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
-	struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
+	struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
 	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
 	struct soc_mixer_control *mc =
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 		(struct soc_mixer_control *)kcontrol->private_value;
+	struct wm_adsp *dsp = &dsps[mc->shift - 1];
 	char preload[32];
 	char preload[32];
 
 
 	snprintf(preload, ARRAY_SIZE(preload), "DSP%u Preload", mc->shift);
 	snprintf(preload, ARRAY_SIZE(preload), "DSP%u Preload", mc->shift);
@@ -2671,6 +2675,8 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
 
 
 	snd_soc_dapm_sync(dapm);
 	snd_soc_dapm_sync(dapm);
 
 
+	flush_work(&dsp->boot_work);
+
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);

+ 4 - 1
sound/soc/qcom/qdsp6/q6afe-dai.c

@@ -315,6 +315,9 @@ static void q6afe_dai_shutdown(struct snd_pcm_substream *substream,
 	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
 	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);
 	int rc;
 	int rc;
 
 
+	if (!dai_data->is_port_started[dai->id])
+		return;
+
 	rc = q6afe_port_stop(dai_data->port[dai->id]);
 	rc = q6afe_port_stop(dai_data->port[dai->id]);
 	if (rc < 0)
 	if (rc < 0)
 		dev_err(dai->dev, "fail to close AFE port (%d)\n", rc);
 		dev_err(dai->dev, "fail to close AFE port (%d)\n", rc);
@@ -1180,7 +1183,7 @@ static void of_q6afe_parse_dai_data(struct device *dev,
 		int id, i, num_lines;
 		int id, i, num_lines;
 
 
 		ret = of_property_read_u32(node, "reg", &id);
 		ret = of_property_read_u32(node, "reg", &id);
-		if (ret || id > AFE_PORT_MAX) {
+		if (ret || id < 0 || id >= AFE_PORT_MAX) {
 			dev_err(dev, "valid dai id not found:%d\n", ret);
 			dev_err(dev, "valid dai id not found:%d\n", ret);
 			continue;
 			continue;
 		}
 		}

+ 3 - 1
sound/soc/qcom/qdsp6/q6asm-dai.c

@@ -390,7 +390,9 @@ static int q6asm_dai_close(struct snd_pcm_substream *substream)
 	struct q6asm_dai_rtd *prtd = runtime->private_data;
 	struct q6asm_dai_rtd *prtd = runtime->private_data;
 
 
 	if (prtd->audio_client) {
 	if (prtd->audio_client) {
-		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+		if (prtd->state)
+			q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+
 		q6asm_unmap_memory_regions(substream->stream,
 		q6asm_unmap_memory_regions(substream->stream,
 					   prtd->audio_client);
 					   prtd->audio_client);
 		q6asm_audio_client_free(prtd->audio_client);
 		q6asm_audio_client_free(prtd->audio_client);

+ 1 - 1
sound/soc/qcom/qdsp6/q6routing.c

@@ -899,7 +899,7 @@ static int routing_hw_params(struct snd_pcm_substream *substream,
 	else
 	else
 		path_type = ADM_PATH_LIVE_REC;
 		path_type = ADM_PATH_LIVE_REC;
 
 
-	if (be_id > AFE_MAX_PORTS)
+	if (be_id >= AFE_MAX_PORTS)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	session = &data->port_data[be_id];
 	session = &data->port_data[be_id];

+ 6 - 0
sound/soc/sh/rcar/core.c

@@ -1085,6 +1085,12 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
 		of_node_put(capture);
 		of_node_put(capture);
 	}
 	}
 
 
+	if (rsnd_ssi_is_pin_sharing(io_capture) ||
+	    rsnd_ssi_is_pin_sharing(io_playback)) {
+		/* should have symmetric_rates if pin sharing */
+		drv->symmetric_rates = 1;
+	}
+
 	dev_dbg(dev, "%s (%s/%s)\n", rdai->name,
 	dev_dbg(dev, "%s (%s/%s)\n", rdai->name,
 		rsnd_io_to_mod_ssi(io_playback) ? "play"    : " -- ",
 		rsnd_io_to_mod_ssi(io_playback) ? "play"    : " -- ",
 		rsnd_io_to_mod_ssi(io_capture) ? "capture" : "  --   ");
 		rsnd_io_to_mod_ssi(io_capture) ? "capture" : "  --   ");

+ 24 - 13
sound/soc/sh/rcar/ssi.c

@@ -37,6 +37,7 @@
 #define	CHNL_4		(1 << 22)	/* Channels */
 #define	CHNL_4		(1 << 22)	/* Channels */
 #define	CHNL_6		(2 << 22)	/* Channels */
 #define	CHNL_6		(2 << 22)	/* Channels */
 #define	CHNL_8		(3 << 22)	/* Channels */
 #define	CHNL_8		(3 << 22)	/* Channels */
+#define DWL_MASK	(7 << 19)	/* Data Word Length mask */
 #define	DWL_8		(0 << 19)	/* Data Word Length */
 #define	DWL_8		(0 << 19)	/* Data Word Length */
 #define	DWL_16		(1 << 19)	/* Data Word Length */
 #define	DWL_16		(1 << 19)	/* Data Word Length */
 #define	DWL_18		(2 << 19)	/* Data Word Length */
 #define	DWL_18		(2 << 19)	/* Data Word Length */
@@ -353,21 +354,18 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
 	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-	u32 cr_own;
-	u32 cr_mode;
-	u32 wsr;
+	u32 cr_own	= ssi->cr_own;
+	u32 cr_mode	= ssi->cr_mode;
+	u32 wsr		= ssi->wsr;
 	int is_tdm;
 	int is_tdm;
 
 
-	if (rsnd_ssi_is_parent(mod, io))
-		return;
-
 	is_tdm = rsnd_runtime_is_ssi_tdm(io);
 	is_tdm = rsnd_runtime_is_ssi_tdm(io);
 
 
 	/*
 	/*
 	 * always use 32bit system word.
 	 * always use 32bit system word.
 	 * see also rsnd_ssi_master_clk_enable()
 	 * see also rsnd_ssi_master_clk_enable()
 	 */
 	 */
-	cr_own = FORCE | SWL_32;
+	cr_own |= FORCE | SWL_32;
 
 
 	if (rdai->bit_clk_inv)
 	if (rdai->bit_clk_inv)
 		cr_own |= SCKP;
 		cr_own |= SCKP;
@@ -377,9 +375,18 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
 		cr_own |= SDTA;
 		cr_own |= SDTA;
 	if (rdai->sys_delay)
 	if (rdai->sys_delay)
 		cr_own |= DEL;
 		cr_own |= DEL;
+
+	/*
+	 * We shouldn't exchange SWSP after running.
+	 * This means, parent needs to care it.
+	 */
+	if (rsnd_ssi_is_parent(mod, io))
+		goto init_end;
+
 	if (rsnd_io_is_play(io))
 	if (rsnd_io_is_play(io))
 		cr_own |= TRMD;
 		cr_own |= TRMD;
 
 
+	cr_own &= ~DWL_MASK;
 	switch (snd_pcm_format_width(runtime->format)) {
 	switch (snd_pcm_format_width(runtime->format)) {
 	case 16:
 	case 16:
 		cr_own |= DWL_16;
 		cr_own |= DWL_16;
@@ -406,7 +413,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
 		wsr	|= WS_MODE;
 		wsr	|= WS_MODE;
 		cr_own	|= CHNL_8;
 		cr_own	|= CHNL_8;
 	}
 	}
-
+init_end:
 	ssi->cr_own	= cr_own;
 	ssi->cr_own	= cr_own;
 	ssi->cr_mode	= cr_mode;
 	ssi->cr_mode	= cr_mode;
 	ssi->wsr	= wsr;
 	ssi->wsr	= wsr;
@@ -470,15 +477,18 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
-	if (!rsnd_ssi_is_parent(mod, io))
-		ssi->cr_own	= 0;
-
 	rsnd_ssi_master_clk_stop(mod, io);
 	rsnd_ssi_master_clk_stop(mod, io);
 
 
 	rsnd_mod_power_off(mod);
 	rsnd_mod_power_off(mod);
 
 
 	ssi->usrcnt--;
 	ssi->usrcnt--;
 
 
+	if (!ssi->usrcnt) {
+		ssi->cr_own	= 0;
+		ssi->cr_mode	= 0;
+		ssi->wsr	= 0;
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1055,9 +1065,10 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
 
 
 int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
 int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
 {
 {
-	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	if (!mod)
+		return 0;
 
 
-	return !!(rsnd_flags_has(ssi, RSND_SSI_CLK_PIN_SHARE));
+	return !!(rsnd_flags_has(rsnd_mod_to_ssi(mod), RSND_SSI_CLK_PIN_SHARE));
 }
 }
 
 
 static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,
 static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,

+ 7 - 0
sound/soc/soc-dapm.c

@@ -4073,6 +4073,13 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
 			continue;
 			continue;
 		}
 		}
 
 
+		/* let users know there is no DAI to link */
+		if (!dai_w->priv) {
+			dev_dbg(card->dev, "dai widget %s has no DAI\n",
+				dai_w->name);
+			continue;
+		}
+
 		dai = dai_w->priv;
 		dai = dai_w->priv;
 
 
 		/* ...find all widgets with the same stream and link them */
 		/* ...find all widgets with the same stream and link them */

+ 8 - 0
sound/soc/soc-pcm.c

@@ -1694,6 +1694,14 @@ static u64 dpcm_runtime_base_format(struct snd_pcm_substream *substream)
 		int i;
 		int i;
 
 
 		for (i = 0; i < be->num_codecs; i++) {
 		for (i = 0; i < be->num_codecs; i++) {
+			/*
+			 * Skip CODECs which don't support the current stream
+			 * type. See soc_pcm_init_runtime_hw() for more details
+			 */
+			if (!snd_soc_dai_stream_valid(be->codec_dais[i],
+						      stream))
+				continue;
+
 			codec_dai_drv = be->codec_dais[i]->driver;
 			codec_dai_drv = be->codec_dais[i]->driver;
 			if (stream == SNDRV_PCM_STREAM_PLAYBACK)
 			if (stream == SNDRV_PCM_STREAM_PLAYBACK)
 				codec_stream = &codec_dai_drv->playback;
 				codec_stream = &codec_dai_drv->playback;

+ 1 - 1
sound/soc/soc-utils.c

@@ -381,6 +381,6 @@ int __init snd_soc_util_init(void)
 
 
 void __exit snd_soc_util_exit(void)
 void __exit snd_soc_util_exit(void)
 {
 {
-	platform_device_unregister(soc_dummy_dev);
 	platform_driver_unregister(&soc_dummy_driver);
 	platform_driver_unregister(&soc_dummy_driver);
+	platform_device_unregister(soc_dummy_dev);
 }
 }

+ 1 - 1
sound/soc/tegra/tegra30_i2s.h

@@ -173,7 +173,7 @@
 /* Number of slots in frame, minus 1 */
 /* Number of slots in frame, minus 1 */
 #define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT		16
 #define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT		16
 #define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US	7
 #define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US	7
-#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK		(TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOT_MASK_US << TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOT_SHIFT)
+#define TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK		(TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK_US << TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT)
 
 
 /* TDM mode slot enable bitmask */
 /* TDM mode slot enable bitmask */
 #define TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT	8
 #define TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT	8