sound fixes for 3.13-rc5
We have a bit more changes than usual in ASoC here, as it was slipped from the previous update. There are one minr ASoC PCM code fix and ASoC dmaengine fix, in addition of a collection of small ASoC driver fixes. The rest are a couple of HD-audio stable fixups, and a long-standing fix for the paused stream handling. So, all commits look not scary (and hopefully won't give you disastrous holiday season). -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJSstz0AAoJEGwxgFQ9KSmkc7UP/A5n/mgQlsyyjax0bJSEK0gx 0GpqnCo4mQFypDnPpb6MN3Xa8GDS+MbUFUmZYOpuB3aAoUm0quiBpB9u7tfjr/BO lMS42dhvDQSe+EGJDoBo6TAp8yb2uU7x70GqnzijWvISqn5rMzgFRWuUPKnXEuaE On++cPZhfy0f8sWmh2FdBXDeKNa/32n2RU3PcO8vdAG3BRz8eO05cVxGV8hywHHa BGMwsVUUq+9jT4sF5a8pbqC9J1+EmJk1xkNc3I+i7KDw0MrwUsyt/i/MbcNBcNgH FyG2VejPHkcpPs/wSZNRZe0nHjAyCYsYMFjmS0V7HqZYdKWUTzBhP63QRrUC5Dgw lEDpApKIk+6gFgBY7tyqD3MEG5K6YSs7h0jElm32ei649U15IMr1nXB4FYM3zYyY PBzFpTcO+lpIj/kV7GJeIdCROLUKaTheHEd4TpbNt2lLWwFs05B1b/QhMF50zw3X 7ad+VxZx+3PbvQrUU2IsBth23I9x4a9HwSScTq9xZdMzWT3TQ7O4B/Ii15rI4QTK oQ3tofuqx3IJFoRcrXMZwF8RfKYopseO208so1v9qHt+5UeYxp8xokpa8QHzY3Yw UjsaymLdp+uCeEYE2reaE6d4xFPXiEr2vPgBDR7ZAZLVKrlDl5+AND1m6E0FVG2v FHlJjFh58wngEbSfQbbk =OXEI -----END PGP SIGNATURE----- Merge tag 'sound-3.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "We have a bit more changes than usual in ASoC here, as it was slipped from the previous update. There are one minr ASoC PCM code fix and ASoC dmaengine fix, in addition of a collection of small ASoC driver fixes. The rest are a couple of HD-audio stable fixups, and a long-standing fix for the paused stream handling. So, all commits look not scary (and hopefully won't give you disastrous holiday season)" * tag 'sound-3.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: hda - Add Dell headset detection quirk for one more laptop model ASoC: wm8904: fix DSP mode B configuration ASoC: wm_adsp: Add small delay while polling DSP RAM start ALSA: Add SNDRV_PCM_STATE_PAUSED case in wait_for_avail function ASoC: kirkwood: Fix the CPU DAI rates ASoC: wm5110: Correct HPOUT3 DAPM route typo ALSA: hda - Add Dell headset detection quirk for three laptop models ALSA: hda - Add enable_msi=0 workaround for four HP machines ASoC: don't leak on error in snd_dmaengine_pcm_register ASoC: fsl: imx-wm8962: Don't update bias_level in machine driver ASoC: tegra: fix uninitialized variables in set_fmt ASoC: wm8962: Enable SYSCLK provisonally before fetching generated DSPCLK_DIV ASoC: sam9x5_wm8731: change to work in DSP A mode ASoC: atmel_ssc_dai: add dai trigger ops ASoC: soc-pcm: Use valid condition for snd_soc_dai_digital_mute() in hw_free()
This commit is contained in:
commit
9b1be0f976
|
@ -1937,6 +1937,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
|
||||||
case SNDRV_PCM_STATE_DISCONNECTED:
|
case SNDRV_PCM_STATE_DISCONNECTED:
|
||||||
err = -EBADFD;
|
err = -EBADFD;
|
||||||
goto _endloop;
|
goto _endloop;
|
||||||
|
case SNDRV_PCM_STATE_PAUSED:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (!tout) {
|
if (!tout) {
|
||||||
snd_printd("%s write error (DMA or IRQ trouble?)\n",
|
snd_printd("%s write error (DMA or IRQ trouble?)\n",
|
||||||
|
|
|
@ -3433,6 +3433,10 @@ static void check_probe_mask(struct azx *chip, int dev)
|
||||||
* white/black-list for enable_msi
|
* white/black-list for enable_msi
|
||||||
*/
|
*/
|
||||||
static struct snd_pci_quirk msi_black_list[] = {
|
static struct snd_pci_quirk msi_black_list[] = {
|
||||||
|
SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
|
||||||
|
SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
|
||||||
|
SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
|
||||||
|
SND_PCI_QUIRK(0x103c, 0x21fa, "HP", 0), /* AMD Hudson */
|
||||||
SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
|
SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
|
||||||
SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
|
SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
|
||||||
SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
|
SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
|
||||||
|
|
|
@ -4247,12 +4247,16 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||||
SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
|
SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
|
SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
|
||||||
SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
|
SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS),
|
SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS),
|
||||||
|
SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
|
SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
|
||||||
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
|
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
|
||||||
|
|
|
@ -648,7 +648,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
dma_params = ssc_p->dma_params[dir];
|
dma_params = ssc_p->dma_params[dir];
|
||||||
|
|
||||||
ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
|
ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
|
||||||
ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
|
ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
|
||||||
|
|
||||||
pr_debug("%s enabled SSC_SR=0x%08x\n",
|
pr_debug("%s enabled SSC_SR=0x%08x\n",
|
||||||
|
@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
|
||||||
|
int cmd, struct snd_soc_dai *dai)
|
||||||
|
{
|
||||||
|
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
|
||||||
|
struct atmel_pcm_dma_params *dma_params;
|
||||||
|
int dir;
|
||||||
|
|
||||||
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
|
dir = 0;
|
||||||
|
else
|
||||||
|
dir = 1;
|
||||||
|
|
||||||
|
dma_params = ssc_p->dma_params[dir];
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
|
ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
|
static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
|
||||||
|
@ -731,6 +758,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
|
||||||
.startup = atmel_ssc_startup,
|
.startup = atmel_ssc_startup,
|
||||||
.shutdown = atmel_ssc_shutdown,
|
.shutdown = atmel_ssc_shutdown,
|
||||||
.prepare = atmel_ssc_prepare,
|
.prepare = atmel_ssc_prepare,
|
||||||
|
.trigger = atmel_ssc_trigger,
|
||||||
.hw_params = atmel_ssc_hw_params,
|
.hw_params = atmel_ssc_hw_params,
|
||||||
.set_fmt = atmel_ssc_set_dai_fmt,
|
.set_fmt = atmel_ssc_set_dai_fmt,
|
||||||
.set_clkdiv = atmel_ssc_set_dai_clkdiv,
|
.set_clkdiv = atmel_ssc_set_dai_clkdiv,
|
||||||
|
|
|
@ -109,7 +109,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
|
||||||
dai->stream_name = "WM8731 PCM";
|
dai->stream_name = "WM8731 PCM";
|
||||||
dai->codec_dai_name = "wm8731-hifi";
|
dai->codec_dai_name = "wm8731-hifi";
|
||||||
dai->init = sam9x5_wm8731_init;
|
dai->init = sam9x5_wm8731_init;
|
||||||
dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF
|
||||||
| SND_SOC_DAIFMT_CBM_CFM;
|
| SND_SOC_DAIFMT_CBM_CFM;
|
||||||
|
|
||||||
ret = snd_soc_of_parse_card_name(card, "atmel,model");
|
ret = snd_soc_of_parse_card_name(card, "atmel,model");
|
||||||
|
|
|
@ -1012,7 +1012,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
|
||||||
{ "AEC Loopback", "HPOUT3L", "OUT3L" },
|
{ "AEC Loopback", "HPOUT3L", "OUT3L" },
|
||||||
{ "AEC Loopback", "HPOUT3R", "OUT3R" },
|
{ "AEC Loopback", "HPOUT3R", "OUT3R" },
|
||||||
{ "HPOUT3L", NULL, "OUT3L" },
|
{ "HPOUT3L", NULL, "OUT3L" },
|
||||||
{ "HPOUT3R", NULL, "OUT3L" },
|
{ "HPOUT3R", NULL, "OUT3R" },
|
||||||
|
|
||||||
{ "AEC Loopback", "SPKOUTL", "OUT4L" },
|
{ "AEC Loopback", "SPKOUTL", "OUT4L" },
|
||||||
{ "SPKOUTLN", NULL, "OUT4L" },
|
{ "SPKOUTLN", NULL, "OUT4L" },
|
||||||
|
|
|
@ -1444,7 +1444,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||||
|
|
||||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||||
case SND_SOC_DAIFMT_DSP_B:
|
case SND_SOC_DAIFMT_DSP_B:
|
||||||
aif1 |= WM8904_AIF_LRCLK_INV;
|
aif1 |= 0x3 | WM8904_AIF_LRCLK_INV;
|
||||||
case SND_SOC_DAIFMT_DSP_A:
|
case SND_SOC_DAIFMT_DSP_A:
|
||||||
aif1 |= 0x3;
|
aif1 |= 0x3;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -2439,7 +2439,20 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
|
||||||
snd_soc_update_bits(codec, WM8962_CLOCKING_4,
|
snd_soc_update_bits(codec, WM8962_CLOCKING_4,
|
||||||
WM8962_SYSCLK_RATE_MASK, clocking4);
|
WM8962_SYSCLK_RATE_MASK, clocking4);
|
||||||
|
|
||||||
|
/* DSPCLK_DIV can be only generated correctly after enabling SYSCLK.
|
||||||
|
* So we here provisionally enable it and then disable it afterward
|
||||||
|
* if current bias_level hasn't reached SND_SOC_BIAS_ON.
|
||||||
|
*/
|
||||||
|
if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
|
||||||
|
snd_soc_update_bits(codec, WM8962_CLOCKING2,
|
||||||
|
WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA);
|
||||||
|
|
||||||
dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
|
dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
|
||||||
|
|
||||||
|
if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
|
||||||
|
snd_soc_update_bits(codec, WM8962_CLOCKING2,
|
||||||
|
WM8962_SYSCLK_ENA_MASK, 0);
|
||||||
|
|
||||||
if (dspclk < 0) {
|
if (dspclk < 0) {
|
||||||
dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
|
dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1474,13 +1474,17 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Wait for the RAM to start, should be near instantaneous */
|
/* Wait for the RAM to start, should be near instantaneous */
|
||||||
count = 0;
|
for (count = 0; count < 10; ++count) {
|
||||||
do {
|
|
||||||
ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
|
ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
|
||||||
&val);
|
&val);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
} while (!(val & ADSP2_RAM_RDY) && ++count < 10);
|
|
||||||
|
if (val & ADSP2_RAM_RDY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
msleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(val & ADSP2_RAM_RDY)) {
|
if (!(val & ADSP2_RAM_RDY)) {
|
||||||
adsp_err(dsp, "Failed to start DSP RAM\n");
|
adsp_err(dsp, "Failed to start DSP RAM\n");
|
||||||
|
|
|
@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dapm->bias_level = level;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -473,17 +473,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
|
||||||
.playback = {
|
.playback = {
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.rates = SNDRV_PCM_RATE_8000_192000 |
|
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||||
SNDRV_PCM_RATE_CONTINUOUS |
|
.rate_min = 5512,
|
||||||
SNDRV_PCM_RATE_KNOT,
|
.rate_max = 192000,
|
||||||
.formats = KIRKWOOD_I2S_FORMATS,
|
.formats = KIRKWOOD_I2S_FORMATS,
|
||||||
},
|
},
|
||||||
.capture = {
|
.capture = {
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.rates = SNDRV_PCM_RATE_8000_192000 |
|
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||||
SNDRV_PCM_RATE_CONTINUOUS |
|
.rate_min = 5512,
|
||||||
SNDRV_PCM_RATE_KNOT,
|
.rate_max = 192000,
|
||||||
.formats = KIRKWOOD_I2S_FORMATS,
|
.formats = KIRKWOOD_I2S_FORMATS,
|
||||||
},
|
},
|
||||||
.ops = &kirkwood_i2s_dai_ops,
|
.ops = &kirkwood_i2s_dai_ops,
|
||||||
|
@ -494,17 +494,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
|
||||||
.playback = {
|
.playback = {
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.rates = SNDRV_PCM_RATE_8000_192000 |
|
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||||
SNDRV_PCM_RATE_CONTINUOUS |
|
.rate_min = 5512,
|
||||||
SNDRV_PCM_RATE_KNOT,
|
.rate_max = 192000,
|
||||||
.formats = KIRKWOOD_SPDIF_FORMATS,
|
.formats = KIRKWOOD_SPDIF_FORMATS,
|
||||||
},
|
},
|
||||||
.capture = {
|
.capture = {
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.rates = SNDRV_PCM_RATE_8000_192000 |
|
.rates = SNDRV_PCM_RATE_CONTINUOUS,
|
||||||
SNDRV_PCM_RATE_CONTINUOUS |
|
.rate_min = 5512,
|
||||||
SNDRV_PCM_RATE_KNOT,
|
.rate_max = 192000,
|
||||||
.formats = KIRKWOOD_SPDIF_FORMATS,
|
.formats = KIRKWOOD_SPDIF_FORMATS,
|
||||||
},
|
},
|
||||||
.ops = &kirkwood_i2s_dai_ops,
|
.ops = &kirkwood_i2s_dai_ops,
|
||||||
|
|
|
@ -305,6 +305,20 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
|
||||||
|
i++) {
|
||||||
|
if (!pcm->chan[i])
|
||||||
|
continue;
|
||||||
|
dma_release_channel(pcm->chan[i]);
|
||||||
|
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_dmaengine_pcm_register - Register a dmaengine based PCM device
|
* snd_dmaengine_pcm_register - Register a dmaengine based PCM device
|
||||||
* @dev: The parent device for the PCM device
|
* @dev: The parent device for the PCM device
|
||||||
|
@ -315,6 +329,7 @@ int snd_dmaengine_pcm_register(struct device *dev,
|
||||||
const struct snd_dmaengine_pcm_config *config, unsigned int flags)
|
const struct snd_dmaengine_pcm_config *config, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct dmaengine_pcm *pcm;
|
struct dmaengine_pcm *pcm;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
|
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
|
||||||
if (!pcm)
|
if (!pcm)
|
||||||
|
@ -326,11 +341,20 @@ int snd_dmaengine_pcm_register(struct device *dev,
|
||||||
dmaengine_pcm_request_chan_of(pcm, dev);
|
dmaengine_pcm_request_chan_of(pcm, dev);
|
||||||
|
|
||||||
if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
|
if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
|
||||||
return snd_soc_add_platform(dev, &pcm->platform,
|
ret = snd_soc_add_platform(dev, &pcm->platform,
|
||||||
&dmaengine_no_residue_pcm_platform);
|
&dmaengine_no_residue_pcm_platform);
|
||||||
else
|
else
|
||||||
return snd_soc_add_platform(dev, &pcm->platform,
|
ret = snd_soc_add_platform(dev, &pcm->platform,
|
||||||
&dmaengine_pcm_platform);
|
&dmaengine_pcm_platform);
|
||||||
|
if (ret)
|
||||||
|
goto err_free_dma;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_free_dma:
|
||||||
|
dmaengine_pcm_release_chan(pcm);
|
||||||
|
kfree(pcm);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register);
|
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register);
|
||||||
|
|
||||||
|
@ -345,7 +369,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
|
||||||
{
|
{
|
||||||
struct snd_soc_platform *platform;
|
struct snd_soc_platform *platform;
|
||||||
struct dmaengine_pcm *pcm;
|
struct dmaengine_pcm *pcm;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
platform = snd_soc_lookup_platform(dev);
|
platform = snd_soc_lookup_platform(dev);
|
||||||
if (!platform)
|
if (!platform)
|
||||||
|
@ -353,15 +376,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
|
||||||
|
|
||||||
pcm = soc_platform_to_pcm(platform);
|
pcm = soc_platform_to_pcm(platform);
|
||||||
|
|
||||||
for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
|
|
||||||
if (pcm->chan[i]) {
|
|
||||||
dma_release_channel(pcm->chan[i]);
|
|
||||||
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_soc_remove_platform(platform);
|
snd_soc_remove_platform(platform);
|
||||||
|
dmaengine_pcm_release_chan(pcm);
|
||||||
kfree(pcm);
|
kfree(pcm);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);
|
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);
|
||||||
|
|
|
@ -600,12 +600,13 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||||
struct snd_soc_platform *platform = rtd->platform;
|
struct snd_soc_platform *platform = rtd->platform;
|
||||||
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||||
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||||
struct snd_soc_codec *codec = rtd->codec;
|
bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||||
|
|
||||||
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
|
||||||
|
|
||||||
/* apply codec digital mute */
|
/* apply codec digital mute */
|
||||||
if (!codec->active)
|
if ((playback && codec_dai->playback_active == 1) ||
|
||||||
|
(!playback && codec_dai->capture_active == 1))
|
||||||
snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
|
snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
|
||||||
|
|
||||||
/* free any machine hw params */
|
/* free any machine hw params */
|
||||||
|
|
|
@ -74,7 +74,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
unsigned int fmt)
|
unsigned int fmt)
|
||||||
{
|
{
|
||||||
struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||||
unsigned int mask, val;
|
unsigned int mask = 0, val = 0;
|
||||||
|
|
||||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||||
case SND_SOC_DAIFMT_NB_NF:
|
case SND_SOC_DAIFMT_NB_NF:
|
||||||
|
@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
|
mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
|
||||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||||
case SND_SOC_DAIFMT_CBS_CFS:
|
case SND_SOC_DAIFMT_CBS_CFS:
|
||||||
val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
|
val |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_CBM_CFM:
|
case SND_SOC_DAIFMT_CBM_CFM:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -67,14 +67,14 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
|
||||||
{
|
{
|
||||||
struct device *dev = dai->dev;
|
struct device *dev = dai->dev;
|
||||||
struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
|
struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
|
||||||
unsigned int mask, val;
|
unsigned int mask = 0, val = 0;
|
||||||
int ret, spdifclock;
|
int ret, spdifclock;
|
||||||
|
|
||||||
mask = TEGRA20_SPDIF_CTRL_PACK |
|
mask |= TEGRA20_SPDIF_CTRL_PACK |
|
||||||
TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
|
TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
val = TEGRA20_SPDIF_CTRL_PACK |
|
val |= TEGRA20_SPDIF_CTRL_PACK |
|
||||||
TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
|
TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -118,7 +118,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
unsigned int fmt)
|
unsigned int fmt)
|
||||||
{
|
{
|
||||||
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||||
unsigned int mask, val;
|
unsigned int mask = 0, val = 0;
|
||||||
|
|
||||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||||
case SND_SOC_DAIFMT_NB_NF:
|
case SND_SOC_DAIFMT_NB_NF:
|
||||||
|
@ -127,10 +127,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
|
mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
|
||||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||||
case SND_SOC_DAIFMT_CBS_CFS:
|
case SND_SOC_DAIFMT_CBS_CFS:
|
||||||
val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
|
val |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
|
||||||
break;
|
break;
|
||||||
case SND_SOC_DAIFMT_CBM_CFM:
|
case SND_SOC_DAIFMT_CBM_CFM:
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue