Commit b3c4014c authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-fix-v5.0-rc2' of...

Merge tag 'asoc-fix-v5.0-rc2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v5.0

Quite a big batch of fixes here.  There's a couple of things going on,
the main one is that we found some issues with not deferring probe when
we should, causing us to skip some driver initialization.  The fixes for
this then in turn exposed some issues with how we were searching for
components which had previously gone unnoticed due to the original
issue.

There's also been the normal driver specific stuff and there's been what
looks like several batches of automated scanning for issues which have
generated quite a large set of smaller fixes for potential crashes and
missed error handling.
parents 687ae9e2 4cb79ef9
...@@ -985,6 +985,12 @@ struct snd_soc_dai_link { ...@@ -985,6 +985,12 @@ struct snd_soc_dai_link {
/* Do not create a PCM for this DAI link (Backend link) */ /* Do not create a PCM for this DAI link (Backend link) */
unsigned int ignore:1; unsigned int ignore:1;
/*
* This driver uses legacy platform naming. Set by the core, machine
* drivers should not modify this value.
*/
unsigned int legacy_platform:1;
struct list_head list; /* DAI link list of the soc card */ struct list_head list; /* DAI link list of the soc card */
struct snd_soc_dobj dobj; /* For topology */ struct snd_soc_dobj dobj; /* For topology */
}; };
......
...@@ -541,7 +541,8 @@ static int snd_compress_check_input(struct snd_compr_params *params) ...@@ -541,7 +541,8 @@ static int snd_compress_check_input(struct snd_compr_params *params)
{ {
/* first let's check the buffer parameter's */ /* first let's check the buffer parameter's */
if (params->buffer.fragment_size == 0 || if (params->buffer.fragment_size == 0 ||
params->buffer.fragments > INT_MAX / params->buffer.fragment_size) params->buffer.fragments > INT_MAX / params->buffer.fragment_size ||
params->buffer.fragments == 0)
return -EINVAL; return -EINVAL;
/* now codec parameters */ /* now codec parameters */
......
...@@ -611,14 +611,16 @@ static int acp3x_audio_probe(struct platform_device *pdev) ...@@ -611,14 +611,16 @@ static int acp3x_audio_probe(struct platform_device *pdev)
} }
irqflags = *((unsigned int *)(pdev->dev.platform_data)); irqflags = *((unsigned int *)(pdev->dev.platform_data));
adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
GFP_KERNEL);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
return -ENODEV; return -ENODEV;
} }
adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
if (!adata)
return -ENOMEM;
adata->acp3x_base = devm_ioremap(&pdev->dev, res->start, adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res)); resource_size(res));
......
...@@ -1400,24 +1400,20 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute) ...@@ -1400,24 +1400,20 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
if (ret != 0) { if (ret != 0) {
dev_err(component->dev, dev_err(component->dev,
"Failed to set digital mute: %d\n", ret); "Failed to set digital mute: %d\n", ret);
mutex_unlock(&pcm512x->mutex); goto unlock;
return ret;
} }
regmap_read_poll_timeout(pcm512x->regmap, regmap_read_poll_timeout(pcm512x->regmap,
PCM512x_ANALOG_MUTE_DET, PCM512x_ANALOG_MUTE_DET,
mute_det, (mute_det & 0x3) == 0, mute_det, (mute_det & 0x3) == 0,
200, 10000); 200, 10000);
mutex_unlock(&pcm512x->mutex);
} else { } else {
pcm512x->mute &= ~0x1; pcm512x->mute &= ~0x1;
ret = pcm512x_update_mute(pcm512x); ret = pcm512x_update_mute(pcm512x);
if (ret != 0) { if (ret != 0) {
dev_err(component->dev, dev_err(component->dev,
"Failed to update digital mute: %d\n", ret); "Failed to update digital mute: %d\n", ret);
mutex_unlock(&pcm512x->mutex); goto unlock;
return ret;
} }
regmap_read_poll_timeout(pcm512x->regmap, regmap_read_poll_timeout(pcm512x->regmap,
...@@ -1428,9 +1424,10 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute) ...@@ -1428,9 +1424,10 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
200, 10000); 200, 10000);
} }
unlock:
mutex_unlock(&pcm512x->mutex); mutex_unlock(&pcm512x->mutex);
return 0; return ret;
} }
static const struct snd_soc_dai_ops pcm512x_dai_ops = { static const struct snd_soc_dai_ops pcm512x_dai_ops = {
......
...@@ -1128,8 +1128,11 @@ static int rt274_i2c_probe(struct i2c_client *i2c, ...@@ -1128,8 +1128,11 @@ static int rt274_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
regmap_read(rt274->regmap, ret = regmap_read(rt274->regmap,
RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val); RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
if (ret)
return ret;
if (val != RT274_VENDOR_ID) { if (val != RT274_VENDOR_ID) {
dev_err(&i2c->dev, dev_err(&i2c->dev,
"Device with ID register %#x is not rt274\n", val); "Device with ID register %#x is not rt274\n", val);
......
...@@ -280,6 +280,8 @@ static int rt5514_spi_pcm_probe(struct snd_soc_component *component) ...@@ -280,6 +280,8 @@ static int rt5514_spi_pcm_probe(struct snd_soc_component *component)
rt5514_dsp = devm_kzalloc(component->dev, sizeof(*rt5514_dsp), rt5514_dsp = devm_kzalloc(component->dev, sizeof(*rt5514_dsp),
GFP_KERNEL); GFP_KERNEL);
if (!rt5514_dsp)
return -ENOMEM;
rt5514_dsp->dev = &rt5514_spi->dev; rt5514_dsp->dev = &rt5514_spi->dev;
mutex_init(&rt5514_dsp->dma_lock); mutex_init(&rt5514_dsp->dma_lock);
......
...@@ -2512,6 +2512,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) ...@@ -2512,6 +2512,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000); regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000);
regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000); regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000);
regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005); regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005);
regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4);
mutex_unlock(&rt5682->calibrate_mutex); mutex_unlock(&rt5682->calibrate_mutex);
......
...@@ -849,18 +849,18 @@ ...@@ -849,18 +849,18 @@
#define RT5682_SCLK_SRC_PLL2 (0x2 << 13) #define RT5682_SCLK_SRC_PLL2 (0x2 << 13)
#define RT5682_SCLK_SRC_SDW (0x3 << 13) #define RT5682_SCLK_SRC_SDW (0x3 << 13)
#define RT5682_SCLK_SRC_RCCLK (0x4 << 13) #define RT5682_SCLK_SRC_RCCLK (0x4 << 13)
#define RT5682_PLL1_SRC_MASK (0x3 << 10) #define RT5682_PLL2_SRC_MASK (0x3 << 10)
#define RT5682_PLL1_SRC_SFT 10 #define RT5682_PLL2_SRC_SFT 10
#define RT5682_PLL1_SRC_MCLK (0x0 << 10) #define RT5682_PLL2_SRC_MCLK (0x0 << 10)
#define RT5682_PLL1_SRC_BCLK1 (0x1 << 10) #define RT5682_PLL2_SRC_BCLK1 (0x1 << 10)
#define RT5682_PLL1_SRC_SDW (0x2 << 10) #define RT5682_PLL2_SRC_SDW (0x2 << 10)
#define RT5682_PLL1_SRC_RC (0x3 << 10) #define RT5682_PLL2_SRC_RC (0x3 << 10)
#define RT5682_PLL2_SRC_MASK (0x3 << 8) #define RT5682_PLL1_SRC_MASK (0x3 << 8)
#define RT5682_PLL2_SRC_SFT 8 #define RT5682_PLL1_SRC_SFT 8
#define RT5682_PLL2_SRC_MCLK (0x0 << 8) #define RT5682_PLL1_SRC_MCLK (0x0 << 8)
#define RT5682_PLL2_SRC_BCLK1 (0x1 << 8) #define RT5682_PLL1_SRC_BCLK1 (0x1 << 8)
#define RT5682_PLL2_SRC_SDW (0x2 << 8) #define RT5682_PLL1_SRC_SDW (0x2 << 8)
#define RT5682_PLL2_SRC_RC (0x3 << 8) #define RT5682_PLL1_SRC_RC (0x3 << 8)
......
...@@ -822,6 +822,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component, ...@@ -822,6 +822,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* Initial cold start */
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
break;
/* Switch off BCLK_N Divider */ /* Switch off BCLK_N Divider */
snd_soc_component_update_bits(component, AIC32X4_BCLKN, snd_soc_component_update_bits(component, AIC32X4_BCLKN,
AIC32X4_BCLKEN, 0); AIC32X4_BCLKEN, 0);
......
...@@ -86,49 +86,49 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, ...@@ -86,49 +86,49 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n", ret = scnprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
pdcr, ptcr); pdcr, ptcr);
if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR) if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"TxFS output from %s, ", "TxFS output from %s, ",
audmux_port_string((ptcr >> 27) & 0x7)); audmux_port_string((ptcr >> 27) & 0x7));
else else
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"TxFS input, "); "TxFS input, ");
if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR) if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"TxClk output from %s", "TxClk output from %s",
audmux_port_string((ptcr >> 22) & 0x7)); audmux_port_string((ptcr >> 22) & 0x7));
else else
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"TxClk input"); "TxClk input");
ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) { if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"Port is symmetric"); "Port is symmetric");
} else { } else {
if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR) if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"RxFS output from %s, ", "RxFS output from %s, ",
audmux_port_string((ptcr >> 17) & 0x7)); audmux_port_string((ptcr >> 17) & 0x7));
else else
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"RxFS input, "); "RxFS input, ");
if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR) if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"RxClk output from %s", "RxClk output from %s",
audmux_port_string((ptcr >> 12) & 0x7)); audmux_port_string((ptcr >> 12) & 0x7));
else else
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"RxClk input"); "RxClk input");
} }
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"\nData received from %s\n", "\nData received from %s\n",
audmux_port_string((pdcr >> 13) & 0x7)); audmux_port_string((pdcr >> 13) & 0x7));
......
...@@ -91,7 +91,7 @@ config SND_SST_ATOM_HIFI2_PLATFORM_PCI ...@@ -91,7 +91,7 @@ config SND_SST_ATOM_HIFI2_PLATFORM_PCI
config SND_SST_ATOM_HIFI2_PLATFORM_ACPI config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms" tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
default ACPI default ACPI
depends on X86 && ACPI depends on X86 && ACPI && PCI
select SND_SST_IPC_ACPI select SND_SST_IPC_ACPI
select SND_SST_ATOM_HIFI2_PLATFORM select SND_SST_ATOM_HIFI2_PLATFORM
select SND_SOC_ACPI_INTEL_MATCH select SND_SOC_ACPI_INTEL_MATCH
......
...@@ -399,7 +399,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream, ...@@ -399,7 +399,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); int ret;
ret =
snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(params));
if (ret)
return ret;
memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
return 0; return 0;
} }
......
...@@ -192,7 +192,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { ...@@ -192,7 +192,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
.stream_name = "Loopback", .stream_name = "Loopback",
.cpu_dai_name = "Loopback Pin", .cpu_dai_name = "Loopback Pin",
.platform_name = "haswell-pcm-audio", .platform_name = "haswell-pcm-audio",
.dynamic = 0, .dynamic = 1,
.codec_name = "snd-soc-dummy", .codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai", .codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
......
...@@ -55,39 +55,6 @@ enum { ...@@ -55,39 +55,6 @@ enum {
GLK_DPCM_AUDIO_HDMI3_PB, GLK_DPCM_AUDIO_HDMI3_PB,
}; };
static int platform_clock_control(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct snd_soc_dai *codec_dai;
int ret = 0;
codec_dai = snd_soc_card_get_codec_dai(card, GLK_REALTEK_CODEC_DAI);
if (!codec_dai) {
dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
return -EIO;
}
if (SND_SOC_DAPM_EVENT_OFF(event)) {
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
if (ret)
dev_err(card->dev, "failed to stop sysclk: %d\n", ret);
} else if (SND_SOC_DAPM_EVENT_ON(event)) {
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
if (ret < 0) {
dev_err(card->dev, "can't set codec pll: %d\n", ret);
return ret;
}
}
if (ret)
dev_err(card->dev, "failed to start internal clk: %d\n", ret);
return ret;
}
static const struct snd_kcontrol_new geminilake_controls[] = { static const struct snd_kcontrol_new geminilake_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Headset Mic"),
...@@ -102,14 +69,10 @@ static const struct snd_soc_dapm_widget geminilake_widgets[] = { ...@@ -102,14 +69,10 @@ static const struct snd_soc_dapm_widget geminilake_widgets[] = {
SND_SOC_DAPM_SPK("HDMI1", NULL), SND_SOC_DAPM_SPK("HDMI1", NULL),
SND_SOC_DAPM_SPK("HDMI2", NULL), SND_SOC_DAPM_SPK("HDMI2", NULL),
SND_SOC_DAPM_SPK("HDMI3", NULL), SND_SOC_DAPM_SPK("HDMI3", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
}; };
static const struct snd_soc_dapm_route geminilake_map[] = { static const struct snd_soc_dapm_route geminilake_map[] = {
/* HP jack connectors - unknown if we have jack detection */ /* HP jack connectors - unknown if we have jack detection */
{ "Headphone Jack", NULL, "Platform Clock" },
{ "Headphone Jack", NULL, "HPOL" }, { "Headphone Jack", NULL, "HPOL" },
{ "Headphone Jack", NULL, "HPOR" }, { "Headphone Jack", NULL, "HPOR" },
...@@ -117,7 +80,6 @@ static const struct snd_soc_dapm_route geminilake_map[] = { ...@@ -117,7 +80,6 @@ static const struct snd_soc_dapm_route geminilake_map[] = {
{ "Spk", NULL, "Speaker" }, { "Spk", NULL, "Speaker" },
/* other jacks */ /* other jacks */
{ "Headset Mic", NULL, "Platform Clock" },
{ "IN1P", NULL, "Headset Mic" }, { "IN1P", NULL, "Headset Mic" },
/* digital mics */ /* digital mics */
...@@ -177,6 +139,13 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -177,6 +139,13 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
int ret; int ret;
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
if (ret < 0) {
dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
return ret;
}
/* Configure sysclk for codec */ /* Configure sysclk for codec */
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1, ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
......
...@@ -146,7 +146,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { ...@@ -146,7 +146,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = {
.stream_name = "Loopback", .stream_name = "Loopback",
.cpu_dai_name = "Loopback Pin", .cpu_dai_name = "Loopback Pin",
.platform_name = "haswell-pcm-audio", .platform_name = "haswell-pcm-audio",
.dynamic = 0, .dynamic = 1,
.codec_name = "snd-soc-dummy", .codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai", .codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
......
...@@ -570,10 +570,10 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream) ...@@ -570,10 +570,10 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
prtd->audio_client = q6asm_audio_client_alloc(dev, prtd->audio_client = q6asm_audio_client_alloc(dev,
(q6asm_cb)compress_event_handler, (q6asm_cb)compress_event_handler,
prtd, stream_id, LEGACY_PCM_MODE); prtd, stream_id, LEGACY_PCM_MODE);
if (!prtd->audio_client) { if (IS_ERR(prtd->audio_client)) {
dev_err(dev, "Could not allocate memory\n"); dev_err(dev, "Could not allocate memory\n");
kfree(prtd); ret = PTR_ERR(prtd->audio_client);
return -ENOMEM; goto free_prtd;
} }
size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE * size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
...@@ -582,7 +582,7 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream) ...@@ -582,7 +582,7 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
&prtd->dma_buffer); &prtd->dma_buffer);
if (ret) { if (ret) {
dev_err(dev, "Cannot allocate buffer(s)\n"); dev_err(dev, "Cannot allocate buffer(s)\n");
return ret; goto free_client;
} }
if (pdata->sid < 0) if (pdata->sid < 0)
...@@ -595,6 +595,13 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream) ...@@ -595,6 +595,13 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
runtime->private_data = prtd; runtime->private_data = prtd;
return 0; return 0;
free_client:
q6asm_audio_client_free(prtd->audio_client);
free_prtd:
kfree(prtd);
return ret;
} }
static int q6asm_dai_compr_free(struct snd_compr_stream *stream) static int q6asm_dai_compr_free(struct snd_compr_stream *stream)
...@@ -874,7 +881,7 @@ static int of_q6asm_parse_dai_data(struct device *dev, ...@@ -874,7 +881,7 @@ static int of_q6asm_parse_dai_data(struct device *dev,
for_each_child_of_node(dev->of_node, node) { for_each_child_of_node(dev->of_node, node) {
ret = of_property_read_u32(node, "reg", &id); ret = of_property_read_u32(node, "reg", &id);
if (ret || id > MAX_SESSIONS || id < 0) { if (ret || id >= MAX_SESSIONS || id < 0) {
dev_err(dev, "valid dai id not found:%d\n", ret); dev_err(dev, "valid dai id not found:%d\n", ret);
continue; continue;
} }
......
...@@ -158,17 +158,24 @@ static int sdm845_snd_hw_params(struct snd_pcm_substream *substream, ...@@ -158,17 +158,24 @@ static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
} }
static void sdm845_jack_free(struct snd_jack *jack)
{
struct snd_soc_component *component = jack->private_data;
snd_soc_component_set_jack(component, NULL, NULL);
}
static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_component *component; struct snd_soc_component *component;
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card); struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
int i, rval; struct snd_jack *jack;
int rval;
if (!pdata->jack_setup) { if (!pdata->jack_setup) {
struct snd_jack *jack;
rval = snd_soc_card_jack_new(card, "Headset Jack", rval = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_HEADSET |
SND_JACK_HEADPHONE | SND_JACK_HEADPHONE |
...@@ -190,16 +197,22 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -190,16 +197,22 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
pdata->jack_setup = true; pdata->jack_setup = true;
} }
for (i = 0 ; i < dai_link->num_codecs; i++) { switch (cpu_dai->id) {
struct snd_soc_dai *dai = rtd->codec_dais[i]; case PRIMARY_MI2S_RX:
jack = pdata->jack.jack;
component = codec_dai->component;
component = dai->component; jack->private_data = component;
rval = snd_soc_component_set_jack( jack->private_free = sdm845_jack_free;
component, &pdata->jack, NULL); rval = snd_soc_component_set_jack(component,
&pdata->jack, NULL);
if (rval != 0 && rval != -ENOTSUPP) { if (rval != 0 && rval != -ENOTSUPP) {
dev_warn(card->dev, "Failed to set jack: %d\n", rval); dev_warn(card->dev, "Failed to set jack: %d\n", rval);
return rval; return rval;
} }
break;
default:
break;
} }
return 0; return 0;
......
...@@ -202,7 +202,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream) ...@@ -202,7 +202,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id]; struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
pr_debug("PCM data: addr 0x%08ulx len %d\n", pr_debug("PCM data: addr 0x%08lx len %d\n",
(u32)runtime->dma_addr, runtime->dma_bytes); (u32)runtime->dma_addr, runtime->dma_bytes);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
......
...@@ -742,7 +742,7 @@ static struct snd_soc_component *soc_find_component( ...@@ -742,7 +742,7 @@ static struct snd_soc_component *soc_find_component(
if (of_node) { if (of_node) {
if (component->dev->of_node == of_node) if (component->dev->of_node == of_node)
return component; return component;
} else if (strcmp(component->name, name) == 0) { } else if (name && strcmp(component->name, name) == 0) {
return component; return component;
} }
} }
...@@ -1034,17 +1034,18 @@ static int snd_soc_init_platform(struct snd_soc_card *card, ...@@ -1034,17 +1034,18 @@ static int snd_soc_init_platform(struct snd_soc_card *card,
* this function should be removed in the future * this function should be removed in the future
*/ */
/* convert Legacy platform link */ /* convert Legacy platform link */
if (!platform) { if (!platform || dai_link->legacy_platform) {
platform = devm_kzalloc(card->dev, platform = devm_kzalloc(card->dev,
sizeof(struct snd_soc_dai_link_component), sizeof(struct snd_soc_dai_link_component),
GFP_KERNEL); GFP_KERNEL);
if (!platform) if (!platform)
return -ENOMEM; return -ENOMEM;
dai_link->platform = platform; dai_link->platform = platform;
platform->name = dai_link->platform_name; dai_link->legacy_platform = 1;
platform->of_node = dai_link->platform_of_node; platform->name = dai_link->platform_name;
platform->dai_name = NULL; platform->of_node = dai_link->platform_of_node;
platform->dai_name = NULL;
} }
/* if there's no platform we match on the empty platform */ /* if there's no platform we match on the empty platform */
...@@ -1129,6 +1130,15 @@ static int soc_init_dai_link(struct snd_soc_card *card, ...@@ -1129,6 +1130,15 @@ static int soc_init_dai_link(struct snd_soc_card *card,
link->name); link->name);
return -EINVAL; return -EINVAL;
} }
/*
* Defer card registartion if platform dai component is not added to
* component list.
*/
if ((link->platform->of_node || link->platform->name) &&
!soc_find_component(link->platform->of_node, link->platform->name))
return -EPROBE_DEFER;
/* /*
* CPU device may be specified by either name or OF node, but * CPU device may be specified by either name or OF node, but
* can be left unspecified, and will be matched based on DAI * can be left unspecified, and will be matched based on DAI
...@@ -1140,6 +1150,15 @@ static int soc_init_dai_link(struct snd_soc_card *card, ...@@ -1140,6 +1150,15 @@ static int soc_init_dai_link(struct snd_soc_card *card,
link->name); link->name);
return -EINVAL; return -EINVAL;
} }
/*
* Defer card registartion if cpu dai component is not added to
* component list.
*/
if ((link->cpu_of_node || link->cpu_name) &&
!soc_find_component(link->cpu_of_node, link->cpu_name))
return -EPROBE_DEFER;
/* /*
* At least one of CPU DAI name or CPU device name/node must be * At least one of CPU DAI name or CPU device name/node must be
* specified * specified
...@@ -2739,15 +2758,18 @@ int snd_soc_register_card(struct snd_soc_card *card) ...@@ -2739,15 +2758,18 @@ int snd_soc_register_card(struct snd_soc_card *card)
if (!card->name || !card->dev) if (!card->name || !card->dev)
return -EINVAL; return -EINVAL;
mutex_lock(&client_mutex);
for_each_card_prelinks(card, i, link) { for_each_card_prelinks(card, i, link) {
ret = soc_init_dai_link(card, link); ret = soc_init_dai_link(card, link);
if (ret) { if (ret) {
dev_err(card->dev, "ASoC: failed to init link %s\n", dev_err(card->dev, "ASoC: failed to init link %s\n",
link->name); link->name);
mutex_unlock(&client_mutex);
return ret; return ret;
} }
} }
mutex_unlock(&client_mutex);
dev_set_drvdata(card->dev, card); dev_set_drvdata(card->dev, card);
......
...@@ -2019,19 +2019,19 @@ static ssize_t dapm_widget_power_read_file(struct file *file, ...@@ -2019,19 +2019,19 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
out = is_connected_output_ep(w, NULL, NULL); out = is_connected_output_ep(w, NULL, NULL);
} }
ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", ret = scnprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
w->name, w->power ? "On" : "Off", w->name, w->power ? "On" : "Off",
w->force ? " (forced)" : "", in, out); w->force ? " (forced)" : "", in, out);
if (w->reg >= 0) if (w->reg >= 0)
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
" - R%d(0x%x) mask 0x%x", " - R%d(0x%x) mask 0x%x",
w->reg, w->reg, w->mask << w->shift); w->reg, w->reg, w->mask << w->shift);
ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
if (w->sname) if (w->sname)
ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n", ret += scnprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
w->sname, w->sname,
w->active ? "active" : "inactive"); w->active ? "active" : "inactive");
...@@ -2044,7 +2044,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, ...@@ -2044,7 +2044,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
if (!p->connect) if (!p->connect)
continue; continue;
ret += snprintf(buf + ret, PAGE_SIZE - ret, ret += scnprintf(buf + ret, PAGE_SIZE - ret,
" %s \"%s\" \"%s\"\n", " %s \"%s\" \"%s\"\n",
(rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out", (rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",
p->name ? p->name : "static", p->name ? p->name : "static",
......
...@@ -108,7 +108,7 @@ struct davinci_mcasp { ...@@ -108,7 +108,7 @@ struct davinci_mcasp {
/* Used for comstraint setting on the second stream */ /* Used for comstraint setting on the second stream */
u32 channels; u32 channels;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
struct davinci_mcasp_context context; struct davinci_mcasp_context context;
#endif #endif
...@@ -1486,74 +1486,6 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) ...@@ -1486,74 +1486,6 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
{
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
struct davinci_mcasp_context *context = &mcasp->context;
u32 reg;
int i;
context->pm_state = pm_runtime_active(mcasp->dev);
if (!context->pm_state)
pm_runtime_get_sync(mcasp->dev);
for (i = 0; i < ARRAY_SIZE(context_regs); i++)
context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
if (mcasp->txnumevt) {
reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
}
if (mcasp->rxnumevt) {
reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
}
for (i = 0; i < mcasp->num_serializer; i++)
context->xrsr_regs[i] = mcasp_get_reg(mcasp,
DAVINCI_MCASP_XRSRCTL_REG(i));
pm_runtime_put_sync(mcasp->dev);
return 0;
}
static int davinci_mcasp_resume(struct snd_soc_dai *dai)
{
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
struct davinci_mcasp_context *context = &mcasp->context;
u32 reg;
int i;
pm_runtime_get_sync(mcasp->dev);
for (i = 0; i < ARRAY_SIZE(context_regs); i++)
mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
if (mcasp->txnumevt) {
reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
}
if (mcasp->rxnumevt) {
reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
}
for (i = 0; i < mcasp->num_serializer; i++)
mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
context->xrsr_regs[i]);
if (!context->pm_state)
pm_runtime_put_sync(mcasp->dev);
return 0;
}
#else
#define davinci_mcasp_suspend NULL
#define davinci_mcasp_resume NULL
#endif
#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000
#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
...@@ -1571,8 +1503,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { ...@@ -1571,8 +1503,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
{ {
.name = "davinci-mcasp.0", .name = "davinci-mcasp.0",
.probe = davinci_mcasp_dai_probe, .probe = davinci_mcasp_dai_probe,
.suspend = davinci_mcasp_suspend,
.resume = davinci_mcasp_resume,
.playback = { .playback = {
.channels_min = 1, .channels_min = 1,
.channels_max = 32 * 16, .channels_max = 32 * 16,
...@@ -1976,7 +1906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) ...@@ -1976,7 +1906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
} }
mcasp->num_serializer = pdata->num_serializer; mcasp->num_serializer = pdata->num_serializer;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev, mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev,
mcasp->num_serializer, sizeof(u32), mcasp->num_serializer, sizeof(u32),
GFP_KERNEL); GFP_KERNEL);
...@@ -2196,11 +2126,73 @@ static int davinci_mcasp_remove(struct platform_device *pdev) ...@@ -2196,11 +2126,73 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int davinci_mcasp_runtime_suspend(struct device *dev)
{
struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
struct davinci_mcasp_context *context = &mcasp->context;
u32 reg;
int i;
for (i = 0; i < ARRAY_SIZE(context_regs); i++)
context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
if (mcasp->txnumevt) {
reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
}
if (mcasp->rxnumevt) {
reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
}
for (i = 0; i < mcasp->num_serializer; i++)
context->xrsr_regs[i] = mcasp_get_reg(mcasp,
DAVINCI_MCASP_XRSRCTL_REG(i));
return 0;
}
static int davinci_mcasp_runtime_resume(struct device *dev)
{
struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
struct davinci_mcasp_context *context = &mcasp->context;
u32 reg;
int i;
for (i = 0; i < ARRAY_SIZE(context_regs); i++)
mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
if (mcasp->txnumevt) {
reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
}
if (mcasp->rxnumevt) {
reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
}
for (i = 0; i < mcasp->num_serializer; i++)
mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
context->xrsr_regs[i]);
return 0;
}
#endif
static const struct dev_pm_ops davinci_mcasp_pm_ops = {
SET_RUNTIME_PM_OPS(davinci_mcasp_runtime_suspend,
davinci_mcasp_runtime_resume,
NULL)
};
static struct platform_driver davinci_mcasp_driver = { static struct platform_driver davinci_mcasp_driver = {
.probe = davinci_mcasp_probe, .probe = davinci_mcasp_probe,
.remove = davinci_mcasp_remove, .remove = davinci_mcasp_remove,
.driver = { .driver = {
.name = "davinci-mcasp", .name = "davinci-mcasp",
.pm = &davinci_mcasp_pm_ops,
.of_match_table = mcasp_dt_ids, .of_match_table = mcasp_dt_ids,
}, },
}; };
......
config SND_SOC_XILINX_I2S config SND_SOC_XILINX_I2S
tristate "Audio support for the the Xilinx I2S" tristate "Audio support for the Xilinx I2S"
help help
Select this option to enable Xilinx I2S Audio. This enables Select this option to enable Xilinx I2S Audio. This enables
I2S playback and capture using xilinx soft IP. In transmitter I2S playback and capture using xilinx soft IP. In transmitter
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* //
* Xilinx ASoC I2S audio support // Xilinx ASoC I2S audio support
* //
* Copyright (C) 2018 Xilinx, Inc. // Copyright (C) 2018 Xilinx, Inc.
* //
* Author: Praveen Vuppala <praveenv@xilinx.com> // Author: Praveen Vuppala <praveenv@xilinx.com>
* Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com> // Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
*/
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment