summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/rt711-sdca.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/rt711-sdca.c')
-rw-r--r--sound/soc/codecs/rt711-sdca.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c
index 07640d2f6e56..447154cb6010 100644
--- a/sound/soc/codecs/rt711-sdca.c
+++ b/sound/soc/codecs/rt711-sdca.c
@@ -507,6 +507,10 @@ static int rt711_sdca_set_jack_detect(struct snd_soc_component *component,
rt711->hs_jack = hs_jack;
+ /* we can only resume if the device was initialized at least once */
+ if (!rt711->first_hw_init)
+ return 0;
+
ret = pm_runtime_resume_and_get(component->dev);
if (ret < 0) {
if (ret != -EACCES) {
@@ -1215,6 +1219,9 @@ static int rt711_sdca_probe(struct snd_soc_component *component)
rt711_sdca_parse_dt(rt711, &rt711->slave->dev);
rt711->component = component;
+ if (!rt711->first_hw_init)
+ return 0;
+
ret = pm_runtime_resume(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
@@ -1406,6 +1413,9 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap,
rt711->regmap = regmap;
rt711->mbq_regmap = mbq_regmap;
+ regcache_cache_only(rt711->regmap, true);
+ regcache_cache_only(rt711->mbq_regmap, true);
+
mutex_init(&rt711->calibrate_mutex);
mutex_init(&rt711->disable_irq_lock);
@@ -1431,9 +1441,27 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap,
rt711_sdca_dai,
ARRAY_SIZE(rt711_sdca_dai));
- dev_dbg(&slave->dev, "%s\n", __func__);
+ if (ret < 0)
+ return ret;
- return ret;
+ /* set autosuspend parameters */
+ pm_runtime_set_autosuspend_delay(dev, 3000);
+ pm_runtime_use_autosuspend(dev);
+
+ /* make sure the device does not suspend immediately */
+ pm_runtime_mark_last_busy(dev);
+
+ pm_runtime_enable(dev);
+
+ /* important note: the device is NOT tagged as 'active' and will remain
+ * 'suspended' until the hardware is enumerated/initialized. This is required
+ * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently
+ * fail with -EACCESS because of race conditions between card creation and enumeration
+ */
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ return 0;
}
static void rt711_sdca_vd0_io_init(struct rt711_sdca_priv *rt711)
@@ -1500,27 +1528,19 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave)
if (rt711->hw_init)
return 0;
+ regcache_cache_only(rt711->regmap, false);
+ regcache_cache_only(rt711->mbq_regmap, false);
+
if (rt711->first_hw_init) {
- regcache_cache_only(rt711->regmap, false);
regcache_cache_bypass(rt711->regmap, true);
- regcache_cache_only(rt711->mbq_regmap, false);
regcache_cache_bypass(rt711->mbq_regmap, true);
} else {
/*
- * PM runtime is only enabled when a Slave reports as Attached
+ * PM runtime status is marked as 'active' only when a Slave reports as Attached
*/
- /* set autosuspend parameters */
- pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
- pm_runtime_use_autosuspend(&slave->dev);
-
/* update count of parent 'active' children */
pm_runtime_set_active(&slave->dev);
-
- /* make sure the device does not suspend immediately */
- pm_runtime_mark_last_busy(&slave->dev);
-
- pm_runtime_enable(&slave->dev);
}
pm_runtime_get_noresume(&slave->dev);