summaryrefslogtreecommitdiff
path: root/sound/soc/sdca/sdca_regmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sdca/sdca_regmap.c')
-rw-r--r--sound/soc/sdca/sdca_regmap.c98
1 files changed, 68 insertions, 30 deletions
diff --git a/sound/soc/sdca/sdca_regmap.c b/sound/soc/sdca/sdca_regmap.c
index 72f893e00ff5..2cca9a9c71ea 100644
--- a/sound/soc/sdca/sdca_regmap.c
+++ b/sound/soc/sdca/sdca_regmap.c
@@ -147,14 +147,7 @@ bool sdca_regmap_volatile(struct sdca_function_data *function, unsigned int reg)
if (!control)
return false;
- switch (control->mode) {
- case SDCA_ACCESS_MODE_RO:
- case SDCA_ACCESS_MODE_RW1S:
- case SDCA_ACCESS_MODE_RW1C:
- return true;
- default:
- return false;
- }
+ return control->is_volatile;
}
EXPORT_SYMBOL_NS(sdca_regmap_volatile, "SND_SOC_SDCA");
@@ -282,6 +275,49 @@ int sdca_regmap_populate_constants(struct device *dev,
}
EXPORT_SYMBOL_NS(sdca_regmap_populate_constants, "SND_SOC_SDCA");
+static int populate_control_defaults(struct device *dev, struct regmap *regmap,
+ struct sdca_function_data *function,
+ struct sdca_entity *entity,
+ struct sdca_control *control)
+{
+ int i, ret;
+ int cn;
+
+ if (control->mode == SDCA_ACCESS_MODE_DC)
+ return 0;
+
+ 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, val;
+
+ reg = SDW_SDCA_CTL(function->desc->adr, entity->id, control->sel, cn);
+
+ 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++;
+ } 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;
+}
+
/**
* sdca_regmap_write_defaults - write out DisCo defaults to device
* @dev: Pointer to the device.
@@ -290,14 +326,17 @@ EXPORT_SYMBOL_NS(sdca_regmap_populate_constants, "SND_SOC_SDCA");
*
* 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.
*/
int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap,
struct sdca_function_data *function)
{
- int i, j, k;
+ int i, j;
int ret;
for (i = 0; i < function->num_entities; i++) {
@@ -305,31 +344,30 @@ int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap,
for (j = 0; j < entity->num_controls; j++) {
struct sdca_control *control = &entity->controls[j];
- int cn;
-
- if (control->mode == SDCA_ACCESS_MODE_DC)
- continue;
-
- if (!control->has_default && !control->has_fixed)
- continue;
- k = 0;
- for_each_set_bit(cn, (unsigned long *)&control->cn_list,
- BITS_PER_TYPE(control->cn_list)) {
- unsigned int reg;
+ ret = populate_control_defaults(dev, regmap, function,
+ entity, control);
+ if (ret)
+ return ret;
+ }
+ }
- reg = SDW_SDCA_CTL(function->desc->adr, entity->id,
- control->sel, cn);
+ return 0;
+}
+EXPORT_SYMBOL_NS(sdca_regmap_write_defaults, "SND_SOC_SDCA");
- ret = regmap_write(regmap, reg, control->values[k]);
- if (ret)
- return ret;
+int sdca_regmap_write_init(struct device *dev, struct regmap *regmap,
+ struct sdca_function_data *function)
+{
+ struct sdca_init_write *init = function->init_table;
+ int ret, i;
- k++;
- }
- }
+ for (i = 0; i < function->num_init_table; i++) {
+ ret = regmap_write(regmap, init[i].addr, init[i].val);
+ if (ret)
+ return ret;
}
return 0;
}
-EXPORT_SYMBOL_NS(sdca_regmap_write_defaults, "SND_SOC_SDCA");
+EXPORT_SYMBOL_NS(sdca_regmap_write_init, "SND_SOC_SDCA");