Commit f557d39a authored by Mark Brown's avatar Mark Brown

Merge tag 'asoc-fix-v5.0-rc2' into asoc-5.1

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 e412fcb0 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 */
}; };
......
...@@ -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));
......
...@@ -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);
......
...@@ -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)
......
...@@ -850,6 +850,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component, ...@@ -850,6 +850,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));
......
...@@ -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;
} }
......
...@@ -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);
......
...@@ -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",
......
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