[PATCH v2 2/3] soundwire: SDCA: add helper macro to access controls
From: Pierre-Louis Bossart
Date: Tue Sep 01 2020 - 12:22:55 EST
The upcoming SDCA (SoundWire Device Class Audio) specification defines
a hierarchical encoding to interface with Class-defined capabilities.
The specification is not yet accessible to the general public but this
information is released with explicit permission from the MIPI Board
to avoid delays with SDCA support on Linux platforms.
A block of 64 MBytes of register addresses is allocated to SDCA
controls, starting at address 0x40000000. The 26 LSBs which identify
individual controls are set based on the following variables:
- Function Number. An SCDA device can be split in up to 8 independent
Functions. Each of these Functions is described in the SDCA
specification, e.g. Smart Amplifier, Smart Microphone, Simple
Microphone, Jack codec, HID, etc.
- Entity Number. Within each Function, an Entity is an identifiable
block. Up to 127 Entities are connected in a pre-defined
graph (similar to USB), with Entity0 reserved for Function-level
configurations. In contrast to USB, the SDCA spec pre-defines
Function Types, topologies, and allowed options, i.e. the degree of
freedom is not unlimited to limit the possibility of errors in
descriptors leading to software quirks.
- Control Selector. Within each Entity, the SDCA specification defines
up-to 48 controls such as Mute, Gain, AGC, etc, and 16
implementation defined ones. Some Control Selectors might be used
for low-level platform setup, and other exposed to applications and
users. Note that the same Control Selector capability, e.g. Latency
control, might be located at different offsets in different
entities - the Control Selector mapping is Entity-specific.
- Control Number. Some Control Selectors allow channel-specific values
to be set, with up to 64 channels allowed. This is mostly used for
volume control.
- Current/Next values. Some Control Selectors are
'Dual-Ranked'. Software may either update the Current value directly
for immediate effect. Alternatively, software may write into the
'Next' values and update the SoundWire 1.2 'Commit Groups' register
to copy 'Next' values into 'Current' ones in a synchronized
manner. This is different from bank switching which is typically
used to change the bus configuration only.
- MBQ. the Multi-Byte Quantity bit is used to provide atomic updates
when accessing more that one byte, for example a 16-bit volume
control would be updated consistently, the intermediate values
mixing old MSB with new LSB are not applied.
These 6 parameters are used to build a 32-bit address to access the
desired Controls. Because of address range, paging is required, but
the most often used parameter values are placed in the lower 16 bits
of the address. This helps to keep the paging registers constant while
updating Controls for a specific Device/Function.
Reviewed-by: Rander Wang <rander.wang@xxxxxxxxxxxxxxx>
Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@xxxxxxxxxxxxxxx>
Reviewed-by: Kai Vehmanen <kai.vehmanen@xxxxxxxxxxxxxxx>
Acked-by: Bard Liao <yung-chuan.liao@xxxxxxxxxxxxxxx>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@xxxxxxxxxxxxxxx>
---
include/linux/soundwire/sdw_registers.h | 33 +++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/include/linux/soundwire/sdw_registers.h b/include/linux/soundwire/sdw_registers.h
index 5d3c271af7d1..99ff7afc27a2 100644
--- a/include/linux/soundwire/sdw_registers.h
+++ b/include/linux/soundwire/sdw_registers.h
@@ -305,4 +305,37 @@
#define SDW_CASC_PORT_MASK_INTSTAT3 1
#define SDW_CASC_PORT_REG_OFFSET_INTSTAT3 2
+/*
+ * v1.2 device - SDCA address mapping
+ *
+ * Spec definition
+ * Bits Contents
+ * 31 0 (required by addressing range)
+ * 30:26 0b10000 (Control Prefix)
+ * 25 0 (Reserved)
+ * 24:22 Function Number [2:0]
+ * 21 Entity[6]
+ * 20:19 Control Selector[5:4]
+ * 18 0 (Reserved)
+ * 17:15 Control Number[5:3]
+ * 14 Next
+ * 13 MBQ
+ * 12:7 Entity[5:0]
+ * 6:3 Control Selector[3:0]
+ * 2:0 Control Number[2:0]
+ */
+
+#define SDW_SDCA_CTL(fun, ent, ctl, ch) \
+ (BIT(30) | \
+ FIELD_PREP(GENMASK(24, 22), FIELD_GET(GENMASK(2, 0), (fun))) | \
+ FIELD_PREP(BIT(21), FIELD_GET(BIT(6), (ent))) | \
+ FIELD_PREP(GENMASK(20, 19), FIELD_GET(GENMASK(5, 4), (ctl))) | \
+ FIELD_PREP(GENMASK(17, 15), FIELD_GET(GENMASK(5, 3), (ch))) | \
+ FIELD_PREP(GENMASK(12, 7), FIELD_GET(GENMASK(5, 0), (ent))) | \
+ FIELD_PREP(GENMASK(6, 3), FIELD_GET(GENMASK(3, 0), (ctl))) | \
+ FIELD_PREP(GENMASK(2, 0), FIELD_GET(GENMASK(2, 0), (ch))))
+
+#define SDW_SDCA_MBQ_CTL(reg) ((reg) | BIT(13))
+#define SDW_SDCA_NEXT_CTL(reg) ((reg) | BIT(14))
+
#endif /* __SDW_REGISTERS_H */
--
2.25.1