summaryrefslogtreecommitdiff
path: root/Documentation
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@google.com>2020-04-29 15:53:43 -0700
committerDuncan Laurie <dlaurie@chromium.org>2020-05-22 01:49:11 +0000
commitba56da85e8cb7f4918ec10d1e5aaab9f553e4e3e (patch)
tree423c2706fc6678cdda5941747540bb66dceee048 /Documentation
parent73ce9fb18a24cab40975d7e674120b90283e8ab1 (diff)
Documentation: Add info about SoundWire coreboot implementation
This change adds a document about the SoundWire implementation in coreboot with details adding new controllers and codecs and connecting them in the mainboard devicetree. BUG=b:146482091 Signed-off-by: Duncan Laurie <dlaurie@google.com> Change-Id: Ibc04442e22acfc03ff86c49c8a7a215ceefc24c7 Reviewed-on: https://review.coreboot.org/c/coreboot/+/40892 Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-by: Sathyanarayana Nujella <sathyanarayana.nujella@intel.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/drivers/index.md1
-rw-r--r--Documentation/drivers/soundwire.md496
2 files changed, 497 insertions, 0 deletions
diff --git a/Documentation/drivers/index.md b/Documentation/drivers/index.md
index 807ed85ed6..e215c6ab11 100644
--- a/Documentation/drivers/index.md
+++ b/Documentation/drivers/index.md
@@ -6,3 +6,4 @@ they allow to easily reuse existing code accross platforms.
* [IPMI KCS](ipmi_kcs.md)
* [SMMSTORE](smmstore.md)
+* [SoundWire](soundwire.md)
diff --git a/Documentation/drivers/soundwire.md b/Documentation/drivers/soundwire.md
new file mode 100644
index 0000000000..9c48b75b37
--- /dev/null
+++ b/Documentation/drivers/soundwire.md
@@ -0,0 +1,496 @@
+# SoundWire Implementation in coreboot
+
+## Introduction
+
+SoundWire is an audio interface specification from the MIPI Alliance.
+
+- Low complexity
+- Low power
+- Low latency
+- Two pins (clock and data)
+- Multi-drop capable
+- Multiple audio streams
+- Embedded control/command channel
+
+The main *SoundWire Specification* is at version 1.2 and can be downloaded from
+<https://mipi.org> but it is unfortunately only available to MIPI Alliance members.
+
+There is a separate *SoundWire Discovery and Configuration (DisCo) Specification* which
+is at version 1.0 and is available for non-members after providing name and email at
+<https://resources.mipi.org/disco_soundwire>.
+
+The coreboot implementation is based on the SoundWire DisCo Specification which defines
+object hierarchy and properties for providing topology and configuration information to
+OS kernel drivers via ACPI or DeviceTree.
+
+SoundWire itself is architecture independent and the coreboot basic definition is also not
+specific to any to any SoC. The examples in this document use ACPI to generate properties,
+but the same structures and properties would be needed in a DeviceTree implementation.
+
+## Bus
+
+The SoundWire bus commonly consists of two pins:
+
+* Clock: A common clock signal distributed from the master to all of the slaves.
+* Data: A shared data signal that can be driven by any of the devices, and has a defined
+value when no device is driving it.
+
+While most designs have one data lane it is possible for a multi-lane device to have up
+to 8 data lanes and thus would have more than two pins.
+
+A SoundWire bus consists of one master device, up to 11 slave devices, and an optional
+monitor interface for debug.
+
+SoundWire is an enumerable bus, but not a discoverable one. That means it is required
+for firmware to provide details about the connected devices to the OS.
+
+### Controller
+
+A SoundWire controller contains one or more master devices. The handling of multiple
+masters is left up to the implementation, they may share a clock or be operated
+independently or entirely in tandem. The master devices connected to a controller are
+also referred to as links.
+
+In coreboot the controller device is provided by the SoC or an add-in PCI card.
+
+### Master
+
+A SoundWire master (or link) device is responsible for clock and data handling, bus
+management, and bit slot allocation.
+
+In coreboot the definition of the master device is left up to the controller and the
+mainboard should only need to know the controller's SoundWire topology (number of masters)
+to configure `devicetree.cb`.
+
+It may however be expected to provide some additional SoC-specific configuration data to
+the controller, such as an input clock rate or a list of available masters that cannot
+be determined at run time.
+
+### Slave
+
+SoundWire slave devices are connected to a master and respond to the two-wire control
+information on the SoundWire bus. There can be up to 11 slave devices on a bus and they
+are capable of interrupting and waking the host.
+
+Slave devices may also have master links which can be connected to other slave devices.
+It is also possible for a multi-lane slave device to have multiple data lanes connected
+to different combinations of master and slave devices.
+
+In coreboot the slave device is defined by a codec driver which should be found in the
+source tree at `src/drivers/soundwire`.
+
+The mainboard provides:
+
+* Master link that this slave device is connected to.
+* Unique ID that this codec responds to on the SoundWire bus.
+* Multi-lane mapping. (optional)
+
+The codec driver provides:
+
+* Slave device properties.
+* Audio Mode properties including bus frequencies and sampling rates.
+* Data Port 1-14 properties such as word lengths, interrupt support, channels.
+* Data Port 0 and Bulk Register Access properties. (optional)
+
+### Monitor
+
+A SoundWire monitor device is defined that allows for test equipment to snoop the bus and
+take over and issue commands. The monitor interface is not defined for coreboot.
+
+### Example SoundWire Bus
+
+```
++---------------+ +---------------+
+| | Clock Signal | |
+| Master |-------+-------------------------------| Slave |
+| Interface | | Data Signal | Interface 1 |
+| |-------|-------+-----------------------| |
++---------------+ | | +---------------+
+ | |
+ | |
+ | |
+ +--+-------+--+
+ | |
+ | Slave |
+ | Interface 2 |
+ | |
+ +-------------+
+```
+
+## coreboot
+
+The coreboot implementation of SoundWire integrates with the device model and takes
+advantage of the hierarchical nature of `devicetree.cb` to populate the topology.
+
+The architecture-independent SoundWire tables are defined at
+
+ src/include/device/soundwire.h
+
+Support for new devices comes in three forms:
+
+1. New controller and master drivers. The first implementation in coreboot is for an Intel
+SoC but the SoundWire specification is in wide use on various ARM SoCs.
+
+ Controller drivers can be implemented in `src/soc` or `src/drivers` and should
+ strive to re-use code as much as possible between different SoC generations from the
+ same vendor.
+
+2. New codec drivers. These should be implemented for each codec that is added which
+supports SoundWire. The properties vary between codecs and careful study of the data sheet
+is necessary to ensure proper operation.
+
+ Codec drivers should be implemented in `src/drivers/soundwire` as separate chip drivers.
+ As every codec is different there may not be opportunities of code re-use except between
+ similar codecs from the same vendor.
+
+3. New mainboards with SoundWire support. The mainboard will combine controllers and codecs
+to form a topology that is described in `devicetree.cb`. Some devices may need to provide
+board-specific configuration information, and multi-lane devices will need to provide the
+master/slave lane map.
+
+## ACPI Implementation
+
+The implementation for x86 devices relies on ACPI for providing device properties to the OS
+kernel drivers.
+
+The ACPI implementation can be found at
+
+ src/acpi/soundwire.c
+
+And used by including
+
+ #include <acpi/acpi_soundwire.h>
+
+### Controller
+
+The controller driver should populate a `struct soundwire_controller`:
+
+```c
+/**
+ * struct soundwire_controller - SoundWire controller properties.
+ * @master_count: Number of masters present on this device.
+ * @master_list: One entry for each master device.
+ */
+struct soundwire_controller {
+ unsigned int master_list_count;
+ struct soundwire_link master_list[SOUNDWIRE_MAX_DEV];
+};
+```
+
+Once the detail of the master links are specified in the `master_list` variable, the controller
+properties for the ACPI object can be generated:
+
+```c
+struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
+soundwire_gen_controller(dsd, &soc_controller, NULL);
+acpi_dp_write(dsd);
+```
+
+If the controller needs to generate custom properties for links it can provide a callback
+function to `soundwire_gen_controller()` instead of passing NULL:
+
+```c
+static void controller_link_prop_cb(struct acpi_dp *dsd, unsigned int id,
+ struct soundwire_controller *controller)
+{
+ acpi_dp_add_integer(dsd, "custom-link-property", 1);
+}
+```
+
+### Codec
+
+The codec driver should populate a *struct soundwire_codec* with necessary properties:
+
+```c
+/**
+ * struct soundwire_codec - Contains all configuration for a SoundWire codec slave device.
+ * @slave: Properties for slave device.
+ * @audio_mode: Properties for Audio Mode for Data Ports 1-14.
+ * @dpn: Properties for Data Ports 1-14.
+ * @multilane: Properties for slave multilane device. (optional)
+ * @dp0_bra_mode: Properties for Bulk Register Access mode for Data Port 0. (optional)
+ * @dp0: Properties for Data Port 0 for Bulk Register Access. (optional)
+ */
+struct soundwire_codec {
+ struct soundwire_slave *slave;
+ struct soundwire_audio_mode *audio_mode[SOUNDWIRE_MAX_DEV];
+ struct soundwire_dpn_entry dpn[SOUNDWIRE_MAX_DPN - SOUNDWIRE_MIN_DPN];
+ struct soundwire_multilane *multilane;
+ struct soundwire_bra_mode *dp0_bra_mode[SOUNDWIRE_MAX_DEV];
+ struct soundwire_dp0 *dp0;
+};
+```
+
+Many of these properties are optional, and depending on the codec will not be supported.
+
+#### Slave Device Properties
+
+These properties provide information about the codec device and what features it supports:
+
+* Wake capability
+* Clock stop behavior
+* Clock and channel state machine behavior
+* Features like register pages, broadcast read, bank delay, and high performance PHY
+
+#### Multi-lane Slave Device Properties
+
+Most slave devices have a single data pin and a single lane, but it is possible for up to
+7 other lanes to be supported on a device. These lanes can be connected to other master
+links or to other slave devices.
+
+If a codec supports this feature it must indicate that by providing an entry for
+`struct soundwire_multilane` in the chip configuration.
+
+```c
+/**
+ * struct drivers_soundwire_example_config - Example codec configuration.
+ * @multilane: Multi-lane slave configuration.
+ */
+struct drivers_soundwire_example_config {
+ struct soundwire_multilane multilane;
+};
+```
+
+The mainboard is required to provide the lane map in `devicetree.cb` for any codec that has
+multiple lanes connected. This includes the definition up to 7 entries that indicate which
+lane number on the slave devices (array index starting at 1) maps to which other device:
+
+```
+chip drivers/soundwire/multilane_codec
+ register "multilane.lane_mapping" = "{
+ {
+ # Slave Lane 1 maps to Master Lane 2
+ .lane = 1,
+ .direction = MASTER_LANE,
+ .connection.master_lane = 2
+ },
+ {
+ # Slave Lane 3 maps to Slave Link B
+ .lane = 3,
+ .direction = SLAVE_LINK,
+ .connection.slave_link = 1
+ }
+ }"
+ device generic 0.0 on end
+end
+```
+
+#### Data Port 0 Properties
+
+SoundWire Data Port 0 (DP0) is a special port used for control and status operation relating
+to the whole device interface, and as a special data port for bulk read/write operations.
+
+The properties for data port 0 are different from that of data ports 1-14 and are about the
+control channel behavior and the overall bulk register mode.
+
+Data port 0 is not required to be supported by the slave device.
+
+#### Bulk Register Access Mode Properties
+
+Bulk Register Access (BRA) is an optional mechanism for transporting higher bandwidth of
+register operations than the typical command mechanism. The BRA protocol is a particular
+format of the data on the (optional) data port 0 connection between the master and slave.
+
+The BRA protocol may have alignment or timing requirements that are directly related to the
+bus frequencies. As a result there may be several configurations listed, for symmetry with
+the audio modes paired with data ports 1-14.
+
+#### Data Port 1-14 Properties
+
+Data ports 1-14 are typically dedicated to streaming audio payloads, and each data port can
+have from 1 to 8 channels. There are different levels of data ports, with some registers
+being required and supported on all data ports and some optional registers only being used
+on some data ports.
+
+Data ports can have both a sink and a source component, and the codec may support one or
+both of these on each port.
+
+Similar to data port 0 the properties defined here describe the capabilities and supported
+features of each data port, and they may be configured separately. For example the Maxim
+MAX98373 codec supports a 32bit source data port for speaker output, and a 16bit sink data
+port for speaker sense data.
+
+#### Audio Mode Properties
+
+Each data port may be tied to one or more audio modes. The audio mode describes the actual
+audio capabilities of the codec, including supported frequencies and sample rates. These
+modes can be shared by multiple data ports and do not need to be duplicated.
+
+For example:
+
+```
+static struct soundwire_audio_mode audio_mode = {
+ .bus_frequency_max = 24 * MHz,
+ .bus_frequency_min = 24 * KHz,
+ .max_sampling_frequency = 192 * KHz,
+ .min_sampling_frequency = 8 * KHz,
+};
+static struct soundwire_dpn codec_dp1 = {
+ [...]
+ .port_audio_mode_count = 1,
+ .port_audio_mode_list = {0}
+};
+static struct soundwire_dpn codec_dp3 = {
+ [...]
+ .port_audio_mode_count = 1,
+ .port_audio_mode_list = {0}
+};
+```
+
+### Generating Codec Properties
+
+Once the properties are known it can generate the ACPI code with:
+
+```c
+struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
+soundwire_gen_codec(dsd, &soundwire_codec, NULL);
+acpi_dp_write(dsd);
+```
+
+If the codec needs to generate custom properties for links it can provide a callback
+function to `soundwire_gen_codec()` instead of passing NULL:
+
+```c
+static void codec_dp_prop_cb(struct acpi_dp *dsd, unsigned int id,
+ struct soundwire_codec *codec)
+{
+ acpi_dp_add_integer(dsd, "custom-dp-property", 1);
+}
+```
+
+#### Codec Address
+
+SoundWire slave devices use a SoundWire defined ACPI _ADR that requires a 64-bit integer
+and uses the master link ID and slave device unique ID to form a unique address for the
+device on this controller.
+
+SoundWire addresses must be distinguishable from all other slave devices on the same master
+link, so multiple instances of the same manufacturer and part on the same master link will
+need different unique IDs. The value is typically determined by strapping pins on the codec
+chip and can be decoded for this table with the codec datasheet and board schematics.
+
+```c
+/**
+ * struct soundwire_address - SoundWire ACPI Device Address Encoding.
+ * @version: SoundWire specification version from &enum soundwire_version.
+ * @link_id: Zero-based SoundWire Link Number.
+ * @unique_id: Unique ID for multiple devices.
+ * @manufacturer_id: Manufacturer ID from include/device/mipi_ids.h.
+ * @part_id: Vendor defined part ID.
+ * @class: MIPI class encoding in &enum mipi_class.
+ */
+struct soundwire_address {
+ enum soundwire_version version;
+ uint8_t link_id;
+ uint8_t unique_id;
+ uint16_t manufacturer_id;
+ uint16_t part_id;
+ enum mipi_class class;
+};
+```
+
+This ACPI address can be generated by calling the provided acpigen function:
+
+ acpigen_write_ADR_soundwire_device(const struct soundwire_address *sdw);
+
+### Mainboard
+
+The mainboard needs to select appropriate drivers in `Kconfig` and define the topology in
+`devicetree.cb` with the controllers and codecs that exist on the board.
+
+The topology uses the **generic** device to describe SoundWire:
+
+```c
+struct generic_path {
+ unsigned int id; /* SoundWire Master Link ID */
+ unsigned int subid; /* SoundWire Slave Unique ID */
+};
+```
+
+This allows devices to be specified in `devicetree.cb` with the necessary information to
+generate ACPI address and device properties.
+
+```
+chip drivers/intel/soundwire
+ # SoundWire Controller 0
+ device generic 0 on
+ chip drivers/soundwire/codec1
+ # SoundWire Link 0 ID 0
+ device generic 0.0 on end
+ end
+ chip drivers/soundwire/codec2
+ # SoundWire Link 1 ID 2
+ device generic 1.2 on end
+ end
+ end
+end
+```
+
+## Volteer Example
+
+This is an example of an Intel Tiger Lake reference board using SoundWire Link 0 for the
+headphone codec connection, and Link 1 for connecting two speaker amps for stereo speakers.
+
+The mainboard can be found at
+
+ src/mainboard/google/volteer
+
+```
+ +------------------+ +-------------------+
+ | | | Headphone Codec |
+ | Intel Tiger Lake | +--->| Realtek ALC5682 |
+ | SoundWire | | | ID 1 |
+ | Controller | | +-------------------+
+ | | |
+ | Link 0 +----+ +-------------------+
+ | | | Left Speaker Amp |
+ | Link 1 +----+--->| Maxim MAX98373 |
+ | | | | ID 3 |
+ | Link 2 | | +-------------------+
+ | | |
+ | Link 3 | | +-------------------+
+ | | | | Right Speaker Amp |
+ +------------------+ +--->| Maxim MAX98373 |
+ | ID 7 |
+ +-------------------+
+```
+
+This implementation requires a controller driver for the Intel Tigerlake SoC and a codec
+driver for the Realtek and Maxim chips. If those drivers did not already exist they would
+need to be added and reviewed separately before adding the support to the mainboard.
+
+The volteer example requires some `Kconfig` options to be selected:
+
+```
+config BOARD_GOOGLE_BASEBOARD_VOLTEER
+ select DRIVERS_INTEL_SOUNDWIRE
+ select DRIVERS_SOUNDWIRE_ALC5682
+ select DRIVERS_SOUNDWIRE_MAX98373
+```
+
+And the following `devicetree.cb` entries to define this topology:
+
+```
+device pci 1f.3 on
+ chip drivers/intel/soundwire
+ # SoundWire Controller 0
+ device generic 0 on
+ chip drivers/soundwire/alc5682
+ # SoundWire Link 0 ID 1
+ register "desc" = ""Headphone Jack""
+ device generic 0.1 on end
+ end
+ chip drivers/soundwire/max98373
+ # SoundWire Link 0 ID 1
+ register "desc" = ""Left Speaker Amp""
+ device generic 1.3 on end
+ end
+ chip drivers/soundwire/max98373
+ # SoundWire Link 1 ID 7
+ register "desc" = ""Right Speaker Amp""
+ device generic 1.7 on end
+ end
+ end
+ end
+end
+```