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. -----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAlxBy/wTHGJyb29uaWVA a2VybmVsLm9yZwAKCRAk1otyXVSH0HNQB/wI7qx/bNGOX1p2C0M5ENdgsMcYDpMh OHD073hL4wDkNJ/O2josnceCtrPUS5tuOxmx765IFXrAR4FWlNezQL4dHwTNGfG9 Femd6iAxv47lC2fROpuHfB0j32LIjVrHLYDG0wAiDvteXK2VrGbj8vedfWqflOBj PX2kqkkgWfSCTrEYdrE09ExYoYKYdEqU/LEKFmIUnMuXc/HNHLo6e1sFNzTo8DIo g5P8nQ//Qgi1U9UWMabKjy4lYL2Tcid9jcNlz0QIffK2qwIEpVBeuhqJaT4sQrf5 G51UrSk2y4lJ0t9WXv1SwQTDi2slCCGcOHA3fylGkJl1cxgOFMAR37Xs =ev1L -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAlxCJZ0THGJyb29uaWVA a2VybmVsLm9yZwAKCRAk1otyXVSH0L+2B/0VnSutpVWaJnGyBuJ6zrydcSIW4183 G51jmioR10cl5LDV0DiI9l7IoiOwUyODbrIl/swoQPs7FWUsFRGFYytdmAoqaKIC HK1j4D6Tlzac++e6bP6G6NzBMW6TGTu8c7hu3UtIGCz5uPRUKBthnndHmSbEB4h+ 10N7RMs9+/BvH1Zt+x9VqEIP5OHpwc7rP/8yANYbQCY7CPehqDiGpE7SvUgFFl5t IHx0nM1lJNeJyeu0Z/9BGAB5GWM/DzuMSrppNwl2k/QujSSyf1EPZvThpYNCBbnQ 6cQ51+7SZi06ejzMBB5h5z/9yFZTSKmTwFwzJwg/fJ/QngZVkksRRNLV =9LPf -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
f557d39a3c
|
@ -985,6 +985,12 @@ struct snd_soc_dai_link {
|
|||
/* Do not create a PCM for this DAI link (Backend link) */
|
||||
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 snd_soc_dobj dobj; /* For topology */
|
||||
};
|
||||
|
|
|
@ -611,14 +611,16 @@ static int acp3x_audio_probe(struct platform_device *pdev)
|
|||
}
|
||||
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);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
|
||||
if (!adata)
|
||||
return -ENOMEM;
|
||||
|
||||
adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
|
||||
|
|
|
@ -280,6 +280,8 @@ static int rt5514_spi_pcm_probe(struct snd_soc_component *component)
|
|||
|
||||
rt5514_dsp = devm_kzalloc(component->dev, sizeof(*rt5514_dsp),
|
||||
GFP_KERNEL);
|
||||
if (!rt5514_dsp)
|
||||
return -ENOMEM;
|
||||
|
||||
rt5514_dsp->dev = &rt5514_spi->dev;
|
||||
mutex_init(&rt5514_dsp->dma_lock);
|
||||
|
|
|
@ -849,18 +849,18 @@
|
|||
#define RT5682_SCLK_SRC_PLL2 (0x2 << 13)
|
||||
#define RT5682_SCLK_SRC_SDW (0x3 << 13)
|
||||
#define RT5682_SCLK_SRC_RCCLK (0x4 << 13)
|
||||
#define RT5682_PLL1_SRC_MASK (0x3 << 10)
|
||||
#define RT5682_PLL1_SRC_SFT 10
|
||||
#define RT5682_PLL1_SRC_MCLK (0x0 << 10)
|
||||
#define RT5682_PLL1_SRC_BCLK1 (0x1 << 10)
|
||||
#define RT5682_PLL1_SRC_SDW (0x2 << 10)
|
||||
#define RT5682_PLL1_SRC_RC (0x3 << 10)
|
||||
#define RT5682_PLL2_SRC_MASK (0x3 << 8)
|
||||
#define RT5682_PLL2_SRC_SFT 8
|
||||
#define RT5682_PLL2_SRC_MCLK (0x0 << 8)
|
||||
#define RT5682_PLL2_SRC_BCLK1 (0x1 << 8)
|
||||
#define RT5682_PLL2_SRC_SDW (0x2 << 8)
|
||||
#define RT5682_PLL2_SRC_RC (0x3 << 8)
|
||||
#define RT5682_PLL2_SRC_MASK (0x3 << 10)
|
||||
#define RT5682_PLL2_SRC_SFT 10
|
||||
#define RT5682_PLL2_SRC_MCLK (0x0 << 10)
|
||||
#define RT5682_PLL2_SRC_BCLK1 (0x1 << 10)
|
||||
#define RT5682_PLL2_SRC_SDW (0x2 << 10)
|
||||
#define RT5682_PLL2_SRC_RC (0x3 << 10)
|
||||
#define RT5682_PLL1_SRC_MASK (0x3 << 8)
|
||||
#define RT5682_PLL1_SRC_SFT 8
|
||||
#define RT5682_PLL1_SRC_MCLK (0x0 << 8)
|
||||
#define RT5682_PLL1_SRC_BCLK1 (0x1 << 8)
|
||||
#define RT5682_PLL1_SRC_SDW (0x2 << 8)
|
||||
#define RT5682_PLL1_SRC_RC (0x3 << 8)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -850,6 +850,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
|
|||
case SND_SOC_BIAS_PREPARE:
|
||||
break;
|
||||
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 */
|
||||
snd_soc_component_update_bits(component, AIC32X4_BCLKN,
|
||||
AIC32X4_BCLKEN, 0);
|
||||
|
|
|
@ -86,49 +86,49 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
|
|||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
|
||||
ret = scnprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
|
||||
pdcr, ptcr);
|
||||
|
||||
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, ",
|
||||
audmux_port_string((ptcr >> 27) & 0x7));
|
||||
else
|
||||
ret += snprintf(buf + ret, PAGE_SIZE - ret,
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"TxFS input, ");
|
||||
|
||||
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",
|
||||
audmux_port_string((ptcr >> 22) & 0x7));
|
||||
else
|
||||
ret += snprintf(buf + ret, PAGE_SIZE - ret,
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"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) {
|
||||
ret += snprintf(buf + ret, PAGE_SIZE - ret,
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"Port is symmetric");
|
||||
} else {
|
||||
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, ",
|
||||
audmux_port_string((ptcr >> 17) & 0x7));
|
||||
else
|
||||
ret += snprintf(buf + ret, PAGE_SIZE - ret,
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"RxFS input, ");
|
||||
|
||||
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",
|
||||
audmux_port_string((ptcr >> 12) & 0x7));
|
||||
else
|
||||
ret += snprintf(buf + ret, PAGE_SIZE - ret,
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"RxClk input");
|
||||
}
|
||||
|
||||
ret += snprintf(buf + ret, PAGE_SIZE - ret,
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
"\nData received from %s\n",
|
||||
audmux_port_string((pdcr >> 13) & 0x7));
|
||||
|
||||
|
|
|
@ -399,7 +399,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream,
|
|||
struct snd_pcm_hw_params *params,
|
||||
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));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -55,39 +55,6 @@ enum {
|
|||
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[] = {
|
||||
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
|
||||
SOC_DAPM_PIN_SWITCH("Headset Mic"),
|
||||
|
@ -102,14 +69,10 @@ static const struct snd_soc_dapm_widget geminilake_widgets[] = {
|
|||
SND_SOC_DAPM_SPK("HDMI1", NULL),
|
||||
SND_SOC_DAPM_SPK("HDMI2", 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[] = {
|
||||
/* HP jack connectors - unknown if we have jack detection */
|
||||
{ "Headphone Jack", NULL, "Platform Clock" },
|
||||
{ "Headphone Jack", NULL, "HPOL" },
|
||||
{ "Headphone Jack", NULL, "HPOR" },
|
||||
|
||||
|
@ -117,7 +80,6 @@ static const struct snd_soc_dapm_route geminilake_map[] = {
|
|||
{ "Spk", NULL, "Speaker" },
|
||||
|
||||
/* other jacks */
|
||||
{ "Headset Mic", NULL, "Platform Clock" },
|
||||
{ "IN1P", NULL, "Headset Mic" },
|
||||
|
||||
/* digital mics */
|
||||
|
@ -177,6 +139,13 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
|
|||
struct snd_soc_jack *jack;
|
||||
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 */
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
|
||||
RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
|
||||
|
|
|
@ -742,7 +742,7 @@ static struct snd_soc_component *soc_find_component(
|
|||
if (of_node) {
|
||||
if (component->dev->of_node == of_node)
|
||||
return component;
|
||||
} else if (strcmp(component->name, name) == 0) {
|
||||
} else if (name && strcmp(component->name, name) == 0) {
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
@ -1034,17 +1034,18 @@ static int snd_soc_init_platform(struct snd_soc_card *card,
|
|||
* this function should be removed in the future
|
||||
*/
|
||||
/* convert Legacy platform link */
|
||||
if (!platform) {
|
||||
if (!platform || dai_link->legacy_platform) {
|
||||
platform = devm_kzalloc(card->dev,
|
||||
sizeof(struct snd_soc_dai_link_component),
|
||||
GFP_KERNEL);
|
||||
if (!platform)
|
||||
return -ENOMEM;
|
||||
|
||||
dai_link->platform = platform;
|
||||
platform->name = dai_link->platform_name;
|
||||
platform->of_node = dai_link->platform_of_node;
|
||||
platform->dai_name = NULL;
|
||||
dai_link->platform = platform;
|
||||
dai_link->legacy_platform = 1;
|
||||
platform->name = dai_link->platform_name;
|
||||
platform->of_node = dai_link->platform_of_node;
|
||||
platform->dai_name = NULL;
|
||||
}
|
||||
|
||||
/* 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,
|
|||
link->name);
|
||||
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
|
||||
* 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,
|
|||
link->name);
|
||||
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
|
||||
* specified
|
||||
|
@ -2739,15 +2758,18 @@ int snd_soc_register_card(struct snd_soc_card *card)
|
|||
if (!card->name || !card->dev)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&client_mutex);
|
||||
for_each_card_prelinks(card, i, link) {
|
||||
|
||||
ret = soc_init_dai_link(card, link);
|
||||
if (ret) {
|
||||
dev_err(card->dev, "ASoC: failed to init link %s\n",
|
||||
link->name);
|
||||
mutex_unlock(&client_mutex);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&client_mutex);
|
||||
|
||||
dev_set_drvdata(card->dev, card);
|
||||
|
||||
|
|
|
@ -2019,19 +2019,19 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
|
|||
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->force ? " (forced)" : "", in, out);
|
||||
|
||||
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",
|
||||
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)
|
||||
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->active ? "active" : "inactive");
|
||||
|
||||
|
@ -2044,7 +2044,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
|
|||
if (!p->connect)
|
||||
continue;
|
||||
|
||||
ret += snprintf(buf + ret, PAGE_SIZE - ret,
|
||||
ret += scnprintf(buf + ret, PAGE_SIZE - ret,
|
||||
" %s \"%s\" \"%s\"\n",
|
||||
(rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",
|
||||
p->name ? p->name : "static",
|
||||
|
|
Loading…
Reference in New Issue