]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: SDCA: Populate regmap cache for readable Controls
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Thu, 20 Nov 2025 15:30:18 +0000 (15:30 +0000)
committerMark Brown <broonie@kernel.org>
Thu, 20 Nov 2025 17:22:57 +0000 (17:22 +0000)
It is not uncommon for an SDCA Control to have no specified default
value in the DisCo. Non-volatile registers with no defaults will not be
present in the cache until they are accessed. However, if the first
operation user-space performs is a read whilst the device is runtime
suspended this read will fail.

To avoid such problems we should populate values from the hardware into
the cache for all non-volatile readable registers with no defaults.
Update the defaults handling to do this cache population since it is
iterating over the Controls and happens at a time the hardware is
always powered up.

Tested-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Maciej Strozek <mstrozek@opensource.cirrus.com>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Tested-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20251120153023.2105663-10-ckeepax@opensource.cirrus.com
Reviewed-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sdca/sdca_regmap.c

index 5104ae99df33a954136f422a6f544cdbeeca3f27..6fbb241d9d357940071463c40a594ad45c4d57ff 100644 (file)
@@ -286,24 +286,33 @@ static int populate_control_defaults(struct device *dev, struct regmap *regmap,
        if (control->mode == SDCA_ACCESS_MODE_DC)
                return 0;
 
-       if (!control->has_default && !control->has_fixed)
+       if (control->layers & SDCA_ACCESS_LAYER_DEVICE)
                return 0;
 
        i = 0;
        for_each_set_bit(cn, (unsigned long *)&control->cn_list,
                         BITS_PER_TYPE(control->cn_list)) {
-               unsigned int reg;
+               unsigned int reg, val;
 
                reg = SDW_SDCA_CTL(function->desc->adr, entity->id, control->sel, cn);
 
-               ret = regmap_write(regmap, reg, control->values[i]);
-               if (ret) {
-                       dev_err(dev, "Failed to write default %#x: %d\n",
-                               reg, ret);
-                       return ret;
-               }
+               if (control->has_default || control->has_fixed) {
+                       ret = regmap_write(regmap, reg, control->values[i]);
+                       if (ret) {
+                               dev_err(dev, "Failed to write default %#x: %d\n",
+                                       reg, ret);
+                               return ret;
+                       }
 
-               i++;
+                       i++;
+               } else if (!control->is_volatile) {
+                       ret = regmap_read(regmap, reg, &val);
+                       if (ret) {
+                               dev_err(dev, "Failed to read initial %#x: %d\n",
+                                       reg, ret);
+                               return ret;
+                       }
+               }
        }
 
        return 0;
@@ -317,7 +326,10 @@ static int populate_control_defaults(struct device *dev, struct regmap *regmap,
  *
  * This function will write out to the hardware all the DisCo default and
  * fixed value controls. This will cause them to be populated into the cache,
- * and subsequent handling can be done through a cache sync.
+ * and subsequent handling can be done through a cache sync. It will also
+ * read any non-volatile registers that don't have defaults/fixed values to
+ * populate those into the cache, this ensures they are available for reads
+ * even when the device is runtime suspended.
  *
  * Return: Returns zero on success, and a negative error code on failure.
  */