Commit 02d851b4 authored by Charles Keepax's avatar Charles Keepax Committed by Mark Brown
Browse files

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: default avatarCharles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20260204125944.1134011-6-ckeepax@opensource.cirrus.com


Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent cc2f22a6
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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;
};

+36 −0
Original line number Diff line number Diff line
@@ -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",
+11 −3
Original line number Diff line number Diff line
@@ -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);
				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",