summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/rt711.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/rt711.c')
-rw-r--r--sound/soc/codecs/rt711.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c
index af53cbcc7bf2..66eaed13b0d6 100644
--- a/sound/soc/codecs/rt711.c
+++ b/sound/soc/codecs/rt711.c
@@ -462,6 +462,10 @@ static int rt711_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) {
@@ -941,6 +945,9 @@ static int rt711_probe(struct snd_soc_component *component)
rt711_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;
@@ -1183,6 +1190,8 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap,
rt711->sdw_regmap = sdw_regmap;
rt711->regmap = regmap;
+ regcache_cache_only(rt711->regmap, true);
+
mutex_init(&rt711->calibrate_mutex);
mutex_init(&rt711->disable_irq_lock);
@@ -1204,8 +1213,25 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap,
&soc_codec_dev_rt711,
rt711_dai,
ARRAY_SIZE(rt711_dai));
+ if (ret < 0)
+ return ret;
+
+ /* set autosuspend parameters */
+ pm_runtime_set_autosuspend_delay(dev, 3000);
+ pm_runtime_use_autosuspend(dev);
- dev_dbg(&slave->dev, "%s\n", __func__);
+ /* 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 ret;
}
@@ -1219,28 +1245,17 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave)
if (rt711->hw_init)
return 0;
- if (rt711->first_hw_init) {
- regcache_cache_only(rt711->regmap, false);
+ regcache_cache_only(rt711->regmap, false);
+ if (rt711->first_hw_init)
regcache_cache_bypass(rt711->regmap, true);
- }
/*
- * 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
*/
- if (!rt711->first_hw_init) {
- /* set autosuspend parameters */
- pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
- pm_runtime_use_autosuspend(&slave->dev);
-
+ if (!rt711->first_hw_init)
/* 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);
rt711_reset(rt711->regmap);