Skip to content

Commit 72e2c8a

Browse files
committed
docs: extend topology2 README with conventions and ID tables
- document directory structure, class-based object model, and build pipeline - add PCM ID and pipeline ID convention tables for Intel SoundWire and HDA - describe cmake target registration, platform overrides, and route definitions Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent 51b166b commit 72e2c8a

File tree

1 file changed

+309
-0
lines changed

1 file changed

+309
-0
lines changed

tools/topology/topology2/README.md

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,35 @@
22

33
This directory contains the ALSA Topology v2 source files for Sound Open Firmware.
44

5+
This readme is a quick intro to the topic. Please refer to full documentation
6+
at https://thesofproject.github.io/latest/developer_guides/topology2/topology2.html
7+
58
## Overview
69

710
Topology v2 is a modernization of the ALSA topology infrastructure. It aims to solve the verbosity and complexity issues of Topology v1 without relying as heavily on external macro processors like `m4`.
811

912
Topology v2 introduces an object-oriented pre-processing layer directly into the newer `alsatplg` compiler (invoked via the `-p` flag). This allows the configuration files to define classes, objects, and attributes natively within the ALSA configuration syntax.
1013

14+
Building topologies requires `alsatplg` version 1.2.7 or later. The version check is
15+
enforced in `CMakeLists.txt` at configure time.
16+
1117
## Key Advantages
1218

1319
- **Object-Oriented Syntax**: Topology v2 allows for the definition of classes (`Class.Widget`, `Class.Pipeline`) and object instantiation, making the topology files much easier to read, maintain, and extend.
1420
- **Reduced Pre-Processing**: By handling templating and instantiation inside the `alsatplg` tool itself, the build process is cleaner and errors are easier to trace back to the source files, as opposed to deciphering expanded `m4` output.
1521
- **Dynamic Variables**: Attributes can be parameterized and passed down to nested objects, allowing for highly flexible definitions of audio pipelines.
1622

23+
Topology2 uses a class-based object model built on four core concepts:
24+
25+
* **Classes** (`Class.Pipeline`, `Class.Widget`, `Class.PCM`) define reusable templates
26+
with default attribute values
27+
* **Objects** (`Object.Pipeline`, `Object.Widget`, `Object.PCM`) instantiate classes with
28+
specific parameter values
29+
* **Define blocks** provide variable substitution using `$VARIABLE` syntax, enabling
30+
parameterized topologies
31+
* **IncludeByKey** enables conditional includes based on variable values, used primarily
32+
for platform-specific overrides
33+
1734
## Structure and Component Assembly
1835

1936
Topology v2 shifts the source code layout from macro definitions to class definitions, leveraging the structured nature of the newer compiler.
@@ -28,6 +45,35 @@ The directory is built around these core parts:
2845
- **`platform/`**: Hardware-specific configurations and overrides (e.g., Intel-specific IPC attributes).
2946
- **Top-Level `.conf` files**: The board-specific configurations (e.g., `cavs-rt5682.conf`). These behave like standard ALSA `.conf` files but utilize the `@include` directive to import classes and instantiate them dynamically.
3047

48+
### Detailed Directory Layout
49+
50+
```text
51+
tools/topology/topology2/
52+
├── CMakeLists.txt # Build system entry point
53+
├── get_abi.sh # ABI version extraction script
54+
├── cavs-sdw.conf # SoundWire topology entry point
55+
├── sof-hda-generic.conf # HDA generic topology entry point
56+
├── cavs-mixin-mixout-hda.conf # HDA with mixer pipelines
57+
├── cavs-nocodec.conf # SSP nocodec topology
58+
├── ... # Other top-level .conf entry points
59+
├── include/
60+
│ ├── common/ # Core class definitions (PCM, route, audio formats)
61+
│ ├── components/ # Widget/component classes (gain, mixin, EQ, DRC)
62+
│ ├── controls/ # Control classes (mixer, enum, bytes)
63+
│ ├── dais/ # DAI classes (SSP, DMIC, HDA, ALH)
64+
│ └── pipelines/ # Pipeline template classes
65+
│ └── cavs/ # CAVS-architecture pipeline classes
66+
├── platform/
67+
│ └── intel/ # Platform-specific overrides (tgl, mtl, lnl, ptl)
68+
├── production/ # CMake targets for production topologies
69+
│ ├── tplg-targets-ace1.cmake # Intel ACE1 (MTL) targets
70+
│ ├── tplg-targets-ace2.cmake # Intel ACE2 (LNL) targets
71+
│ ├── tplg-targets-ace3.cmake # Intel ACE3 (PTL) targets
72+
│ └── ... # Additional platform target files
73+
├── development/ # CMake targets for development/testing
74+
└── doc/ # Doxygen documentation source
75+
```
76+
3177
```mermaid
3278
graph TD
3379
subgraph "Class Definitions (include/)"
@@ -90,3 +136,266 @@ make topologies2
90136
# OR
91137
cmake --build . --target topologies2
92138
```
139+
140+
To build a specific topology target:
141+
142+
```bash
143+
make sof-lnl-sdw-cs42l43-l0-cs35l56-l12
144+
```
145+
146+
## Best Practices for Adding New Topology Definitions
147+
148+
### Topology Structure
149+
150+
A top-level topology `.conf` file follows a layered configuration pattern:
151+
152+
```conf
153+
# 1. Search directories
154+
<searchdir:include>
155+
<searchdir:include/common>
156+
<searchdir:include/components>
157+
<searchdir:include/dais>
158+
<searchdir:include/pipelines/cavs>
159+
<searchdir:platform/intel>
160+
161+
# 2. Include class files
162+
<vendor-token.conf>
163+
<tokens.conf>
164+
<pcm.conf>
165+
<host-copier-gain-mixin-playback.conf>
166+
<mixout-gain-alh-dai-copier-playback.conf>
167+
168+
# 3. Define block (default variable values)
169+
Define {
170+
PLATFORM ""
171+
NUM_HDMIS 3
172+
DEEP_BUFFER_PCM_ID 31
173+
}
174+
175+
# 4. Platform overrides (conditional includes)
176+
IncludeByKey.PLATFORM {
177+
"mtl" "platform/intel/mtl.conf"
178+
"lnl" "platform/intel/lnl.conf"
179+
"ptl" "platform/intel/ptl.conf"
180+
}
181+
182+
# 5. Conditional feature includes
183+
IncludeByKey.NUM_HDMIS {
184+
"3" "platform/intel/hdmi-generic.conf"
185+
}
186+
187+
# 6. DAI, Pipeline, PCM objects
188+
# 7. Route definitions
189+
```
190+
191+
### Reusing Existing Bases
192+
193+
The most common way to add a new topology is to reuse an existing base `.conf` file and
194+
override variables through a cmake target entry. Targets are defined in
195+
`production/tplg-targets-*.cmake` files using a tuple format:
196+
197+
```text
198+
"input-conf;output-name;variables"
199+
```
200+
201+
For example, to add a new SoundWire topology variant for ACE2 (Lunar Lake):
202+
203+
```text
204+
"cavs-sdw\;sof-lnl-sdw-cs42l43-l0-cs35l56-l12\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=2"
205+
```
206+
207+
The first element is the base `.conf` file (without extension), the second is the output
208+
`.tplg` filename, and the third is a comma-separated list of variable overrides.
209+
210+
### Creating a New Base Topology
211+
212+
When existing bases do not cover a new use case, create a new top-level `.conf` file:
213+
214+
1. Create a new `.conf` file in `tools/topology/topology2/` following the layered
215+
structure described above
216+
2. Include the required class files from `include/` directories via search directives
217+
3. Define default variables in a `Define` block
218+
4. Add `IncludeByKey.PLATFORM` entries for platform-specific overrides
219+
5. Instantiate DAI, Pipeline, and PCM objects with appropriate IDs
220+
6. Define routes connecting FE mixin outputs to BE mixout inputs
221+
7. Register the topology as a cmake target in the appropriate
222+
`production/tplg-targets-*.cmake` file
223+
224+
### PCM ID Conventions
225+
226+
PCM IDs identify audio streams exposed to userspace via ALSA. Each PCM ID must be unique
227+
within a single topology. Different topology families (Intel SoundWire vs HDA) use different
228+
default ID ranges for the same endpoint types.
229+
230+
**Intel SoundWire PCM IDs:**
231+
232+
| Endpoint | Default PCM ID | Override Variable |
233+
|---|---|---|
234+
| Jack (playback/capture) | 0 ||
235+
| Speaker amplifier | 2 ||
236+
| SDW DMIC | 4 ||
237+
| HDMI 1 | 5 | `HDMI1_PCM_ID` |
238+
| HDMI 2 | 6 | `HDMI2_PCM_ID` |
239+
| HDMI 3 | 7 | `HDMI3_PCM_ID` |
240+
| PCH DMIC0 | 10 | `DMIC0_PCM_ID` |
241+
| PCH DMIC1 | 11 | `DMIC1_PCM_ID` |
242+
| Jack Echo Ref | 11 | `SDW_JACK_ECHO_REF_PCM_ID` |
243+
| Speaker Echo Ref | 12 | `SDW_SPK_ECHO_REF_PCM_ID` |
244+
| Bluetooth | 2 or 20 | `BT_PCM_ID` |
245+
| Deep Buffer (Jack) | 31 | `DEEP_BUFFER_PCM_ID` |
246+
| Deep Buffer (Speaker) | 35 | `DEEP_BUFFER_PCM_ID_2` |
247+
| DMIC Deep Buffer | 46 | `DMIC0_DEEP_BUFFER_PCM_ID` |
248+
| Compress Jack Out | 50 | `COMPR_PCM_ID` |
249+
| Compress Speaker | 52 | `COMPR_2_PCM_ID` |
250+
251+
> **Note:** Bluetooth defaults to PCM ID 2 in some topologies and 20 in others. Use the
252+
> `BT_PCM_ID` override variable to set the correct value when BT coexists with a speaker
253+
> amplifier (which also uses PCM ID 2 by default).
254+
255+
**Intel HDA PCM IDs:**
256+
257+
| Endpoint | Default PCM ID | Override Variable |
258+
|---|---|---|
259+
| HDA Analog | 0 ||
260+
| HDMI 1 | 3 | `HDMI1_PCM_ID` |
261+
| HDMI 2 | 4 | `HDMI2_PCM_ID` |
262+
| HDMI 3 | 5 | `HDMI3_PCM_ID` |
263+
| DMIC0 | 6 | `DMIC0_PCM_ID` |
264+
| Deep Buffer | 31 | `DEEP_BUFFER_PCM_ID` |
265+
| Compress HDA Analog | 50 | `COMPR_PCM_ID` |
266+
267+
Key rules:
268+
269+
* PCM ID 0 is always the primary playback endpoint
270+
* PCM IDs must be unique within a single topology
271+
* When features coexist (SDW + PCH DMIC + HDMI), adjust IDs via `Define` overrides in
272+
cmake targets to avoid conflicts
273+
* Different topology families (SDW vs HDA) use different default ID ranges for the same
274+
endpoint types
275+
276+
### Pipeline ID Conventions
277+
278+
Pipeline IDs are set via the `index` attribute on pipeline objects. Front-end (FE) and
279+
back-end (BE) pipelines are paired, with the FE pipeline at index N and the BE pipeline
280+
at index N+1.
281+
282+
In SoundWire topologies, pipeline indexes follow the convention documented in
283+
`sdw-amp-generic.conf` and `sdw-dmic-generic.conf`: pipeline index = PCM ID × 10. HDMI
284+
pipelines use a stride-10 pattern where the host pipeline is at N0 and the DAI pipeline
285+
is at N1 (50/51, 60/61, 70/71, 80/81).
286+
287+
**Intel SoundWire Pipeline IDs:**
288+
289+
| Pipeline | Default Index | Override Variable |
290+
|---|---|---|
291+
| Jack Playback FE / BE | 0 / 1 ||
292+
| Jack Capture FE / BE | 10 / 11 ||
293+
| Deep Buffer (Jack) | 15 | `DEEP_BUFFER_PIPELINE_ID` |
294+
| Deep Buffer (Speaker) | 16 | `DEEP_BUFFER_PIPELINE_ID_2` |
295+
| Speaker FE / BE | 20 / 21 ||
296+
| Speaker Echo Ref FE / BE | 22 / 23 ||
297+
| SDW DMIC FE / BE | 40 / 41 | `SDW_DMIC_HOST_PIPELINE_ID` |
298+
| HDMI 1 Host / DAI | 50 / 51 | `HDMI1_HOST_PIPELINE_ID` / `HDMI1_DAI_PIPELINE_ID` |
299+
| HDMI 2 Host / DAI | 60 / 61 | `HDMI2_HOST_PIPELINE_ID` / `HDMI2_DAI_PIPELINE_ID` |
300+
| HDMI 3 Host / DAI | 70 / 71 | `HDMI3_HOST_PIPELINE_ID` / `HDMI3_DAI_PIPELINE_ID` |
301+
| HDMI 4 Host / DAI | 80 / 81 | `HDMI4_HOST_PIPELINE_ID` / `HDMI4_DAI_PIPELINE_ID` |
302+
| Compress Jack / Speaker | 90 / 92 | `COMPR_PIPELINE_ID` / `COMPR_2_PIPELINE_ID` |
303+
| PCH DMIC0 Host / DAI | 100 / 101 | `DMIC0_HOST_PIPELINE_ID` / `DMIC0_DAI_PIPELINE_ID` |
304+
305+
**Intel HDA Pipeline IDs:**
306+
307+
| Pipeline | Default Index | Override Variable |
308+
|---|---|---|
309+
| Analog Playback FE / BE | 1 / 2 ||
310+
| Analog Capture FE / BE | 3 / 4 ||
311+
| DMIC0 Host / DAI | 11 / 12 | `DMIC0_HOST_PIPELINE_ID` / `DMIC0_DAI_PIPELINE_ID` |
312+
| Deep Buffer | 15 | `DEEP_BUFFER_PIPELINE_ID` |
313+
| HDMI 1 Host / DAI | 50 / 51 | `HDMI1_HOST_PIPELINE_ID` / `HDMI1_DAI_PIPELINE_ID` |
314+
| HDMI 2 Host / DAI | 60 / 61 | `HDMI2_HOST_PIPELINE_ID` / `HDMI2_DAI_PIPELINE_ID` |
315+
| HDMI 3 Host / DAI | 70 / 71 | `HDMI3_HOST_PIPELINE_ID` / `HDMI3_DAI_PIPELINE_ID` |
316+
| HDMI 4 Host / DAI | 80 / 81 | `HDMI4_HOST_PIPELINE_ID` / `HDMI4_DAI_PIPELINE_ID` |
317+
| Compress HDA Analog Host / DAI | 90 / 91 | `COMPR_PIPELINE_ID` |
318+
319+
Key rules:
320+
321+
* FE and BE pipelines are paired: FE = N, BE = N+1
322+
* SDW convention: pipeline index = PCM ID × 10 (documented in `sdw-amp-generic.conf` and
323+
`sdw-dmic-generic.conf`)
324+
* HDMI uses stride-10: Host = N0, DAI = N1
325+
* Pipeline IDs must be unique within a single topology
326+
* When adding new endpoints, select IDs in unused ranges that do not conflict with
327+
existing assignments
328+
329+
### Widget Naming
330+
331+
Widget names follow the convention `<type>.<pipeline-index>.<instance>`. Examples:
332+
333+
* `gain.1.1` — gain widget in pipeline 1, instance 1
334+
* `mixin.15.1` — mixin widget in pipeline 15, instance 1
335+
* `host-copier.0.playback` — host copier in pipeline 0, playback direction
336+
* `dai-copier.1.ALH` — DAI copier in pipeline 1, ALH type
337+
338+
### Route Definitions
339+
340+
Routes connect FE pipeline mixin outputs to BE pipeline mixout inputs. This is the
341+
primary mechanism for linking front-end and back-end pipelines:
342+
343+
```conf
344+
Object.Base.route [
345+
{
346+
source "mixin.15.1"
347+
sink "mixout.2.1"
348+
}
349+
]
350+
```
351+
352+
Multiple FE pipelines can feed into a single BE mixout. For example, both a normal
353+
playback pipeline and a deep buffer pipeline can route to the same DAI output:
354+
355+
```text
356+
host-copier.0 -> gain.0 -> mixin.0 ─┐
357+
├─> mixout.1 -> gain.1 -> dai-copier.1 -> DAI
358+
host-copier.15 -> gain.15 -> mixin.15┘
359+
```
360+
361+
### Platform Overrides
362+
363+
Platform-specific configurations are applied using the `IncludeByKey.PLATFORM` mechanism.
364+
Each platform `.conf` file under `platform/intel/` contains `Define` blocks that override
365+
variables such as `DMIC_DRIVER_VERSION`, `SSP_BLOB_VERSION`, and `NUM_HDMIS`.
366+
367+
Supported platforms:
368+
369+
* `tgl` — Intel Tiger Lake / Alder Lake (CAVS 2.5)
370+
* `mtl` — Intel Meteor Lake (ACE 1.x)
371+
* `lnl` — Intel Lunar Lake (ACE 2.x)
372+
* `ptl` — Intel Panther Lake (ACE 3.x)
373+
374+
```conf
375+
IncludeByKey.PLATFORM {
376+
"mtl" "platform/intel/mtl.conf"
377+
"lnl" "platform/intel/lnl.conf"
378+
"ptl" "platform/intel/ptl.conf"
379+
}
380+
```
381+
382+
### Registering CMake Targets
383+
384+
Production topologies are registered in `production/tplg-targets-*.cmake` files. Each
385+
target is a semicolon-separated tuple:
386+
387+
```text
388+
"input-conf;output-name;variable1=value1,variable2=value2"
389+
```
390+
391+
Select the cmake file matching the target platform generation:
392+
393+
| Platform | CMake Target File |
394+
|---|---|
395+
| Tiger Lake / Alder Lake | `tplg-targets-cavs25.cmake` |
396+
| Meteor Lake | `tplg-targets-ace1.cmake` |
397+
| Lunar Lake | `tplg-targets-ace2.cmake` |
398+
| Panther Lake | `tplg-targets-ace3.cmake` |
399+
| HDA generic | `tplg-targets-hda-generic.cmake` |
400+
401+
Development and testing topologies go in `development/tplg-targets.cmake`.

0 commit comments

Comments
 (0)