Skip to content

Commit 173d64b

Browse files
topology2: ipc3: add Cherry Trail RT5677 topology
Add topology2 support for generating and deploying IPC3 topology files alongside the existing IPC4 production set. Describe the Yoga Book RT5677 SSP2 playback, capture, low-latency and deep-buffer paths while preserving the Cherry Trail memory, scheduler and hardware configuration required by the legacy IPC3 firmware. Keep the four-slot, 25-bit frame geometry but activate only slots 0 and 1 for the stereo stream. The generated topology is byte-identical to the artifact validated on a Lenovo Yoga Book YB1-X91L with PCM0 playback and capture in S16_LE, S24_LE and S32_LE at 48 kHz stereo, plus PCM1 deep-buffer playback. Signed-off-by: Maurizio Casciano <mauriziocasciano7@gmail.com>
1 parent 460f18d commit 173d64b

13 files changed

Lines changed: 876 additions & 1 deletion

File tree

‎tools/topology/topology2/CMakeLists.txt‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ add_custom_target(topologies2 ALL
77
# Create directory structure to be provided for deployment
88
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/target/sof-ipc4-tplg
99
COMMAND ${CMAKE_COMMAND} -E create_symlink sof-ipc4-tplg ${CMAKE_CURRENT_BINARY_DIR}/target/sof-ace-tplg
10+
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/target/sof-tplg
1011
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/target/development
1112
# copy the topology files only to target, preserving symbolic links
1213
COMMAND sh -c "cp -a production/*.tplg \"${CMAKE_CURRENT_BINARY_DIR}/target/sof-ipc4-tplg/\""
14+
COMMAND sh -c "cp -a production/ipc3/*.tplg \"${CMAKE_CURRENT_BINARY_DIR}/target/sof-tplg/\""
1315
COMMAND sh -c "cp -a development/*.tplg \"${CMAKE_CURRENT_BINARY_DIR}/target/development/\""
1416
)
1517

@@ -37,6 +39,18 @@ add_custom_target(abi_target
3739
DEPENDS abi.conf
3840
)
3941

42+
# Atom platforms use IPC3 even when the source topology is written using the
43+
# topology2 object model. Keep a separate ABI manifest so IPC3 and IPC4 output
44+
# can be built together without changing the existing production topologies.
45+
add_custom_command(OUTPUT abi-ipc3.conf
46+
COMMAND > abi-ipc3.conf ${CMAKE_CURRENT_SOURCE_DIR}/get_abi.sh
47+
${SOF_ROOT_SOURCE_DIRECTORY} "ipc3"
48+
DEPENDS ${SOF_ROOT_SOURCE_DIRECTORY}/src/include/kernel/abi.h
49+
)
50+
add_custom_target(abi_ipc3_target
51+
DEPENDS abi-ipc3.conf
52+
)
53+
4054
add_dependencies(topologies2 topology2_dev topology2_prod)
4155
add_subdirectory(development)
4256
add_subdirectory(production)

‎tools/topology/topology2/README.md‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,12 +395,29 @@ target is a semicolon-separated tuple:
395395

396396
Select the cmake file matching the target platform generation:
397397

398-
| Platform | CMake Target File |
398+
| Target family | CMake target file |
399399
|---|---|
400+
| IPC3 | `tplg-targets-ipc3.cmake` |
400401
| Tiger Lake / Alder Lake | `tplg-targets-cavs25.cmake` |
401402
| Meteor Lake | `tplg-targets-ace1.cmake` |
402403
| Lunar Lake | `tplg-targets-ace2.cmake` |
403404
| Panther Lake | `tplg-targets-ace3.cmake` |
404405
| HDA generic | `tplg-targets-hda-generic.cmake` |
405406

407+
### IPC3 topology targets
408+
409+
Topology2 source files can also target firmware that uses IPC3. Register IPC3
410+
targets in `production/tplg-targets-ipc3.cmake`; they are built with a separate
411+
IPC3 ABI manifest and installed under `target/sof-tplg` instead of the IPC4/ACE
412+
topology directory.
413+
414+
Build an individual registered IPC3 target with:
415+
416+
```bash
417+
cmake --build . --target topology2_prod_ipc3_OUTPUT_NAME
418+
```
419+
420+
Replace `OUTPUT_NAME` with the target's output name from
421+
`tplg-targets-ipc3.cmake`.
422+
406423
Development and testing topologies go in `development/tplg-targets.cmake`.
Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
3+
<searchdir:include>
4+
<searchdir:include/common>
5+
<searchdir:include/components>
6+
<searchdir:include/dais>
7+
<searchdir:include/pipelines>
8+
<searchdir:platform>
9+
<searchdir:platform/intel>
10+
11+
<vendor-token.conf>
12+
<tokens.conf>
13+
<manifest.conf>
14+
<data.conf>
15+
<pcm.conf>
16+
<pcm_caps.conf>
17+
<fe_dai.conf>
18+
<route.conf>
19+
<common_definitions.conf>
20+
<virtual.conf>
21+
<ipc3/volume-playback.conf>
22+
<ipc3/mixer-volume-dai-playback.conf>
23+
<ipc3/volume-dai-capture.conf>
24+
<ssp.conf>
25+
<intel/cht-hw-config.conf>
26+
27+
Define {
28+
# Cherry Trail uses the first-generation SSP configuration blob and IPC3.
29+
SSP_BLOB_VERSION $SSP_BLOB_VERSION_1_0
30+
}
31+
32+
# The machine driver connects the RT5677 AIF routes through these platform
33+
# widgets. They mirror the widgets exposed by the legacy Cherry Trail topology.
34+
Object.Widget.virtual [
35+
{ name "codec_out0" type "output" index 1 }
36+
{ name "codec_out1" type "output" index 2 }
37+
{ name "codec_in0" type "input" index 3 }
38+
{ name "codec_in1" type "input" index 4 }
39+
{ name "ssp2 Rx" type "input" index 5 }
40+
{ name "ssp2 Tx" type "output" index 6 }
41+
]
42+
43+
# SSP2 carries the RT5677 AIF1 stream. The bit and frame clocks are driven by
44+
# the Cherry Trail SSP; the codec consumes both clocks.
45+
Object.Dai.SSP [
46+
{
47+
id 0
48+
dai_index 2
49+
direction "duplex"
50+
name "SSP2-Codec"
51+
default_hw_config_id 0
52+
sample_bits 24
53+
54+
Object.Base.hw_config.1 {
55+
name "SSP2"
56+
id 0
57+
format "DSP_B"
58+
mclk "codec_mclk_in"
59+
mclk_freq 19200000
60+
bclk "codec_consumer"
61+
bclk_freq 4800000
62+
# Match SND_SOC_DAIFMT_IB_NF in the machine driver:
63+
# invert BCLK while leaving the frame clock non-inverted.
64+
bclk_invert "true"
65+
fsync "codec_consumer"
66+
fsync_freq 48000
67+
fsync_invert "false"
68+
tdm_slots 4
69+
tdm_slot_width 25
70+
# The frame has four slots, but the stereo stream uses slots 0 and 1.
71+
# IPC3 derives the DAI channel count from these active-slot masks.
72+
tx_slots 3
73+
rx_slots 3
74+
}
75+
}
76+
]
77+
78+
Object.Pipeline {
79+
ipc3-mixer-volume-dai-playback.1 {
80+
index 1
81+
format "s24le"
82+
channels 2
83+
dai_type "SSP"
84+
dai_index 2
85+
periods 2
86+
# Two 1 ms periods at 48 kHz, stereo, four bytes per sample.
87+
size 768
88+
89+
Object.Widget.pipeline.1 {
90+
stream_name "dai.SSP.2.playback"
91+
priority 1
92+
core 0
93+
frames 0
94+
mips 5000
95+
}
96+
Object.Widget.dai.playback {
97+
format "s24le"
98+
stream_name "SSP2-Codec"
99+
core_id 0
100+
}
101+
Object.Widget.pga.1 {
102+
ramp_step_ms 20
103+
Object.Control.mixer.1 {
104+
name "1 Master Playback Volume"
105+
Object.Base.tlv.vtlv_m64s2 {
106+
Object.Base.scale.m64s2 {}
107+
}
108+
}
109+
}
110+
Object.Base.route.4 {
111+
source "buffer.1.2"
112+
sink "dai.SSP.2.playback"
113+
}
114+
}
115+
116+
ipc3-volume-dai-capture.2 {
117+
index 2
118+
format "s32le"
119+
channels 2
120+
dai_type "SSP"
121+
dai_index 2
122+
periods 2
123+
# Two 1 ms periods at 48 kHz, stereo, four bytes per sample.
124+
size 768
125+
126+
Object.Widget.pipeline.1 {
127+
stream_name "dai.SSP.2.capture"
128+
priority 0
129+
core 0
130+
frames 0
131+
mips 5000
132+
}
133+
Object.Widget.dai.capture {
134+
format "s24le"
135+
stream_name "SSP2-Codec"
136+
core_id 0
137+
}
138+
Object.Widget.host.capture {
139+
stream_name "Low Latency Capture 0"
140+
core_id 0
141+
}
142+
Object.Widget.pga.1 {
143+
ramp_step_ms 250
144+
Object.Control.mixer.1 {
145+
name "2 PCM 0 Capture Volume"
146+
max 40
147+
Object.Base.channel.1 {
148+
name "fl"
149+
reg 0
150+
shift 0
151+
}
152+
Object.Base.channel.2 {
153+
name "fr"
154+
reg 0
155+
shift 1
156+
}
157+
Object.Base.tlv.vtlv_m64s2 {
158+
Object.Base.scale.m64s2 {}
159+
}
160+
}
161+
}
162+
Object.Base.route.4 {
163+
source "dai.SSP.2.capture"
164+
sink "buffer.2.1"
165+
}
166+
}
167+
168+
ipc3-volume-playback.3 {
169+
index 3
170+
format "s32le"
171+
channels 2
172+
period 1000
173+
time_domain "dma"
174+
175+
Object.Widget.pipeline.1 {
176+
priority 0
177+
core 0
178+
frames 0
179+
mips 100000
180+
stream_name "dai.SSP.2.playback"
181+
}
182+
Object.Widget.host.playback {
183+
stream_name "Playback 0"
184+
core_id 0
185+
period_sink_count 0
186+
period_source_count 2
187+
}
188+
Object.Widget.pga.1 {
189+
ramp_step_ms 20
190+
period_sink_count 2
191+
period_source_count 2
192+
Object.Control.mixer.1 {
193+
name "3 Playback Volume"
194+
Object.Base.tlv.vtlv_m64s2 {
195+
Object.Base.scale.m64s2 {}
196+
}
197+
}
198+
}
199+
Object.Widget.buffer.1 {
200+
caps "ram_dma_cache"
201+
# IPC3 needs SOF_TKN_BUF_SIZE serialized explicitly. An object
202+
# value takes precedence over the class's automatic size value.
203+
size 768
204+
}
205+
Object.Widget.buffer.2 {
206+
caps "ram_dma_cache"
207+
size 768
208+
}
209+
}
210+
211+
ipc3-volume-playback.4 {
212+
index 4
213+
format "s32le"
214+
channels 2
215+
period 5000
216+
time_domain "dma"
217+
218+
Object.Widget.pipeline.1 {
219+
priority 0
220+
core 0
221+
frames 0
222+
mips 100000
223+
stream_name "dai.SSP.2.playback"
224+
}
225+
Object.Widget.host.playback {
226+
stream_name "Playback 1"
227+
core_id 0
228+
period_sink_count 0
229+
period_source_count 2
230+
}
231+
Object.Widget.pga.1 {
232+
ramp_step_ms 20
233+
period_sink_count 2
234+
period_source_count 2
235+
Object.Control.mixer.1 {
236+
name "4 Playback Volume"
237+
Object.Base.tlv.vtlv_m64s2 {
238+
Object.Base.scale.m64s2 {}
239+
}
240+
}
241+
}
242+
Object.Widget.buffer.1 {
243+
caps "ram_dma_cache"
244+
# Five milliseconds at 48 kHz, two channels and four bytes per
245+
# sample, with two periods: 5 ms * 48 * 2 * 4 * 2 = 3840.
246+
size 3840
247+
}
248+
Object.Widget.buffer.2 {
249+
caps "ram_dma_cache"
250+
size 3840
251+
}
252+
}
253+
}
254+
255+
# Both playback front ends feed the low-latency SSP2 mixer.
256+
Object.Base.route [
257+
{ source "buffer.3.2" sink "ipc3-mixer.1.1" }
258+
{ source "buffer.4.2" sink "ipc3-mixer.1.1" }
259+
]
260+
261+
Object.PCM.pcm [
262+
{
263+
name "PCM"
264+
id 0
265+
direction "duplex"
266+
267+
Object.Base.fe_dai.1 {
268+
name "PCM 0"
269+
}
270+
Object.PCM.pcm_caps.playback {
271+
direction "playback"
272+
name "Playback 0"
273+
formats "S16_LE,S24_LE,S32_LE"
274+
rates "48000"
275+
rate_min 48000
276+
rate_max 48000
277+
channels_min 2
278+
channels_max 2
279+
# Match the proven Cherry Trail IPC3 topology instead of the
280+
# much larger generic topology2 PCM capability defaults.
281+
periods_min 2
282+
periods_max 16
283+
period_size_min 192
284+
period_size_max 16384
285+
buffer_size_min 65536
286+
buffer_size_max 65536
287+
}
288+
Object.PCM.pcm_caps.capture {
289+
direction "capture"
290+
name "Low Latency Capture 0"
291+
formats "S16_LE,S24_LE,S32_LE"
292+
rates "48000"
293+
rate_min 48000
294+
rate_max 48000
295+
channels_min 2
296+
channels_max 2
297+
periods_min 2
298+
# The low-latency capture path supports fewer queued periods
299+
# than playback in the legacy Cherry Trail topology.
300+
periods_max 4
301+
period_size_min 192
302+
period_size_max 16384
303+
buffer_size_min 65536
304+
buffer_size_max 65536
305+
}
306+
}
307+
{
308+
name "PCM Deep Buffer"
309+
id 1
310+
direction "playback"
311+
312+
Object.Base.fe_dai.1 {
313+
name "PCM Deep Buffer 1"
314+
}
315+
Object.PCM.pcm_caps.playback {
316+
direction "playback"
317+
name "Playback 1"
318+
formats "S16_LE,S24_LE,S32_LE"
319+
rates "48000"
320+
rate_min 48000
321+
rate_max 48000
322+
channels_min 2
323+
channels_max 2
324+
# Keep userspace constraints identical for the low-latency and
325+
# deep-buffer playback PCMs, as on the legacy CHT topology.
326+
periods_min 2
327+
periods_max 16
328+
period_size_min 192
329+
period_size_max 16384
330+
buffer_size_min 65536
331+
buffer_size_max 65536
332+
}
333+
}
334+
]

0 commit comments

Comments
 (0)