Archived
161 lines
5.6 KiB
Diff
161 lines
5.6 KiB
Diff
From a80d5cd47c6d2eb3890235a527ad41a73b28009e Mon Sep 17 00:00:00 2001
|
|
From: Charles Keepax <ckeepax@opensource.cirrus.com>
|
|
Date: Wed, 4 Feb 2026 12:59:42 +0000
|
|
Subject: [PATCH 13/17] ASoC: SDCA: Add regmap defaults for specification
|
|
defined values
|
|
|
|
Some of the SDCA Controls have a defined reset value in the
|
|
specification. Update the parsing to add these specification defined
|
|
values into the regmap defaults array. This will reduce the number of
|
|
registers that are synchronised on a cache sync.
|
|
|
|
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
|
|
Link: https://patch.msgid.link/20260204125944.1134011-6-ckeepax@opensource.cirrus.com
|
|
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
|
|
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
---
|
|
include/sound/sdca_function.h | 4 ++++
|
|
sound/soc/sdca/sdca_functions.c | 36 +++++++++++++++++++++++++++++++++
|
|
sound/soc/sdca/sdca_regmap.c | 14 ++++++++++---
|
|
3 files changed, 51 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h
|
|
index 6e9391b3816c..79bd5a7a0f88 100644
|
|
--- a/include/sound/sdca_function.h
|
|
+++ b/include/sound/sdca_function.h
|
|
@@ -798,6 +798,7 @@ struct sdca_control_range {
|
|
* @sel: Identifier used for addressing.
|
|
* @nbits: Number of bits used in the Control.
|
|
* @values: Holds the Control value for constants and defaults.
|
|
+ * @reset: Defined reset value for the Control.
|
|
* @cn_list: A bitmask showing the valid Control Numbers within this Control,
|
|
* Control Numbers typically represent channels.
|
|
* @interrupt_position: SCDA interrupt line that will alert to changes on this
|
|
@@ -808,6 +809,7 @@ struct sdca_control_range {
|
|
* @layers: Bitmask of access layers of the Control.
|
|
* @deferrable: Indicates if the access to the Control can be deferred.
|
|
* @has_default: Indicates the Control has a default value to be written.
|
|
+ * @has_reset: Indicates the Control has a defined reset value.
|
|
* @has_fixed: Indicates the Control only supports a single value.
|
|
*/
|
|
struct sdca_control {
|
|
@@ -816,6 +818,7 @@ struct sdca_control {
|
|
|
|
int nbits;
|
|
int *values;
|
|
+ int reset;
|
|
u64 cn_list;
|
|
int interrupt_position;
|
|
|
|
@@ -827,6 +830,7 @@ struct sdca_control {
|
|
bool deferrable;
|
|
bool is_volatile;
|
|
bool has_default;
|
|
+ bool has_reset;
|
|
bool has_fixed;
|
|
};
|
|
|
|
diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
|
|
index f38791eab4f1..95b67bb904c3 100644
|
|
--- a/sound/soc/sdca/sdca_functions.c
|
|
+++ b/sound/soc/sdca/sdca_functions.c
|
|
@@ -911,6 +911,38 @@ static int find_sdca_control_value(struct device *dev, struct sdca_entity *entit
|
|
return 0;
|
|
}
|
|
|
|
+static int find_sdca_control_reset(const struct sdca_entity *entity,
|
|
+ struct sdca_control *control)
|
|
+{
|
|
+ switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
|
|
+ case SDCA_CTL_TYPE_S(FU, AGC):
|
|
+ case SDCA_CTL_TYPE_S(FU, BASS_BOOST):
|
|
+ case SDCA_CTL_TYPE_S(FU, LOUDNESS):
|
|
+ case SDCA_CTL_TYPE_S(SMPU, TRIGGER_ENABLE):
|
|
+ case SDCA_CTL_TYPE_S(GE, SELECTED_MODE):
|
|
+ case SDCA_CTL_TYPE_S(TG, TONE_DIVIDER):
|
|
+ case SDCA_CTL_TYPE_S(ENTITY_0, COMMIT_GROUP_MASK):
|
|
+ control->has_reset = true;
|
|
+ control->reset = 0;
|
|
+ break;
|
|
+ case SDCA_CTL_TYPE_S(XU, BYPASS):
|
|
+ case SDCA_CTL_TYPE_S(MFPU, BYPASS):
|
|
+ case SDCA_CTL_TYPE_S(FU, MUTE):
|
|
+ case SDCA_CTL_TYPE_S(CX, CLOCK_SELECT):
|
|
+ control->has_reset = true;
|
|
+ control->reset = 1;
|
|
+ break;
|
|
+ case SDCA_CTL_TYPE_S(PDE, REQUESTED_PS):
|
|
+ control->has_reset = true;
|
|
+ control->reset = 3;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int find_sdca_entity_control(struct device *dev, struct sdca_entity *entity,
|
|
struct fwnode_handle *control_node,
|
|
struct sdca_control *control)
|
|
@@ -986,6 +1018,10 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti
|
|
|
|
control->is_volatile = find_sdca_control_volatile(entity, control);
|
|
|
|
+ ret = find_sdca_control_reset(entity, control);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
ret = find_sdca_control_range(dev, control_node, &control->range);
|
|
if (ret) {
|
|
dev_err(dev, "%s: control %#x: range missing: %d\n",
|
|
diff --git a/sound/soc/sdca/sdca_regmap.c b/sound/soc/sdca/sdca_regmap.c
|
|
index 2cca9a9c71ea..4f8a685dc43d 100644
|
|
--- a/sound/soc/sdca/sdca_regmap.c
|
|
+++ b/sound/soc/sdca/sdca_regmap.c
|
|
@@ -218,7 +218,8 @@ int sdca_regmap_count_constants(struct device *dev,
|
|
struct sdca_entity *entity = &function->entities[i];
|
|
|
|
for (j = 0; j < entity->num_controls; j++) {
|
|
- if (entity->controls[j].mode == SDCA_ACCESS_MODE_DC)
|
|
+ if (entity->controls[j].mode == SDCA_ACCESS_MODE_DC ||
|
|
+ entity->controls[j].has_reset)
|
|
nconsts += hweight64(entity->controls[j].cn_list);
|
|
}
|
|
}
|
|
@@ -255,7 +256,8 @@ int sdca_regmap_populate_constants(struct device *dev,
|
|
struct sdca_control *control = &entity->controls[j];
|
|
int cn;
|
|
|
|
- if (control->mode != SDCA_ACCESS_MODE_DC)
|
|
+ if (control->mode != SDCA_ACCESS_MODE_DC &&
|
|
+ !control->has_reset)
|
|
continue;
|
|
|
|
l = 0;
|
|
@@ -264,7 +266,10 @@ int sdca_regmap_populate_constants(struct device *dev,
|
|
consts[k].reg = SDW_SDCA_CTL(function->desc->adr,
|
|
entity->id,
|
|
control->sel, cn);
|
|
- consts[k].def = control->values[l];
|
|
+ if (control->mode == SDCA_ACCESS_MODE_DC)
|
|
+ consts[k].def = control->values[l];
|
|
+ else
|
|
+ consts[k].def = control->reset;
|
|
k++;
|
|
l++;
|
|
}
|
|
@@ -306,6 +311,9 @@ static int populate_control_defaults(struct device *dev, struct regmap *regmap,
|
|
|
|
i++;
|
|
} else if (!control->is_volatile) {
|
|
+ if (control->has_reset)
|
|
+ regcache_drop_region(regmap, reg, reg);
|
|
+
|
|
ret = regmap_read(regmap, reg, &val);
|
|
if (ret) {
|
|
dev_err(dev, "Failed to read initial %#x: %d\n",
|
|
--
|
|
2.43.0
|
|
|