ASoC: SOF/soundwire: use resume_and_get on component probe
Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>: While testing driver bind/unbind sequences, I stumbled on a corner case where the SoundWire bus can be suspended before the ASoC card registration happens. During the registration, register accesses would then lead to timeouts. This does not happen in regular usages where the card registration happens within the 3-second time window before suspend. Adding a simple pm_runtime_resume_and_get() on component probe solves the issue, but experiments showed it was too invasive to add at the ASoC core level, with multiple regressions reported by our CI. This patchset limits the additional resume to the SOF and SoundWire codec drivers. An additional patch for the soundwire/intel component will be sent separately.
This commit is contained in:
commit
87a36978b2
|
@ -5,6 +5,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cdev.h>
|
||||
|
@ -440,8 +441,19 @@ const struct snd_soc_component_driver soc_codec_dev_max98373 = {
|
|||
};
|
||||
EXPORT_SYMBOL_GPL(soc_codec_dev_max98373);
|
||||
|
||||
static int max98373_sdw_probe(struct snd_soc_component *component)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct snd_soc_component_driver soc_codec_dev_max98373_sdw = {
|
||||
.probe = NULL,
|
||||
.probe = max98373_sdw_probe,
|
||||
.controls = max98373_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(max98373_snd_controls),
|
||||
.dapm_widgets = max98373_dapm_widgets,
|
||||
|
|
|
@ -608,7 +608,19 @@ static const struct sdw_slave_ops rt1308_slave_ops = {
|
|||
.bus_config = rt1308_bus_config,
|
||||
};
|
||||
|
||||
static int rt1308_sdw_component_probe(struct snd_soc_component *component)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver soc_component_sdw_rt1308 = {
|
||||
.probe = rt1308_sdw_component_probe,
|
||||
.controls = rt1308_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(rt1308_snd_controls),
|
||||
.dapm_widgets = rt1308_dapm_widgets,
|
||||
|
|
|
@ -590,7 +590,19 @@ static struct sdw_slave_ops rt1316_slave_ops = {
|
|||
.update_status = rt1316_update_status,
|
||||
};
|
||||
|
||||
static int rt1316_sdw_component_probe(struct snd_soc_component *component)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver soc_component_sdw_rt1316 = {
|
||||
.probe = rt1316_sdw_component_probe,
|
||||
.controls = rt1316_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(rt1316_snd_controls),
|
||||
.dapm_widgets = rt1316_dapm_widgets,
|
||||
|
|
|
@ -818,9 +818,14 @@ static const struct snd_soc_dapm_route rt700_audio_map[] = {
|
|||
static int rt700_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
rt700->component = component;
|
||||
|
||||
ret = pm_runtime_resume(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1194,10 +1194,15 @@ static int rt711_sdca_parse_dt(struct rt711_sdca_priv *rt711, struct device *dev
|
|||
static int rt711_sdca_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
rt711_sdca_parse_dt(rt711, &rt711->slave->dev);
|
||||
rt711->component = component;
|
||||
|
||||
ret = pm_runtime_resume(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -935,10 +935,15 @@ static int rt711_parse_dt(struct rt711_priv *rt711, struct device *dev)
|
|||
static int rt711_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
rt711_parse_dt(rt711, &rt711->slave->dev);
|
||||
rt711->component = component;
|
||||
|
||||
ret = pm_runtime_resume(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -758,7 +758,19 @@ static const struct snd_soc_dapm_route rt715_sdca_audio_map[] = {
|
|||
{"ADC 25 Mux", "DMIC4", "DMIC4"},
|
||||
};
|
||||
|
||||
static int rt715_sdca_probe(struct snd_soc_component *component)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver soc_codec_dev_rt715_sdca = {
|
||||
.probe = rt715_sdca_probe,
|
||||
.controls = rt715_sdca_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(rt715_sdca_snd_controls),
|
||||
.dapm_widgets = rt715_sdca_dapm_widgets,
|
||||
|
|
|
@ -737,7 +737,19 @@ static int rt715_set_bias_level(struct snd_soc_component *component,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rt715_probe(struct snd_soc_component *component)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver soc_codec_dev_rt715 = {
|
||||
.probe = rt715_probe,
|
||||
.set_bias_level = rt715_set_bias_level,
|
||||
.controls = rt715_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(rt715_snd_controls),
|
||||
|
|
|
@ -604,6 +604,14 @@ static int sof_pcm_probe(struct snd_soc_component *component)
|
|||
const char *tplg_filename;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* make sure the device is pm_runtime_active before loading the
|
||||
* topology and initiating IPC or bus transactions
|
||||
*/
|
||||
ret = pm_runtime_resume_and_get(component->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
/* load the default topology */
|
||||
sdev->component = component;
|
||||
|
||||
|
@ -621,6 +629,9 @@ static int sof_pcm_probe(struct snd_soc_component *component)
|
|||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(component->dev);
|
||||
pm_runtime_put_autosuspend(component->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue