Skip to content

Commit 4b0bbb7

Browse files
committed
topology: kpb: add topology-configurable history buffer depth
Add a bytes kcontrol kpb_cfg_<N> to each KPB widget that lets the topology manifest set the ring-buffer pre-roll duration at load time, without a firmware rebuild. Firmware (IPC4 path): - ipc4/kpb.h: add KP_BUF_CFG_BUFF_TIME_MS = 2 to the param-ID enum - kpb.c: add buff_time_ms field to comp_data; add kpb_get_buff_time_ms() helper (returns topology value when set, falls back to CONFIG_KPB_MAX_BUFF_TIME); wire the helper into kpb_params(), kpb_prepare() buffer allocation, drain-request cap; handle the new LARGE_CONFIG_SET case in kpb_set_large_config() Topology: - kpb.conf: add Object.Control.bytes kpb_cfg_$index with IncludeByKey blobs for 6000/4000/2100 ms; blob is a 36-byte sof_abi_hdr + u32 ms - dmic-wov-multi-manifest.conf: Define KPB_BUFF_TIME_MS 6000 for TGL The kernel sof_ipc4_widget_kcontrol_setup() path sends the blob as a LARGE_CONFIG_SET on pipeline open with no userspace intervention. Omitting KPB_BUFF_TIME_MS from the manifest leaves buff_time_ms = 0, and kpb_get_buff_time_ms() falls back to CONFIG_KPB_MAX_BUFF_TIME. Verified on spider (TGL/CAVS2.5): kpb_cfg_101/102/103 kcontrols appear after modprobe; topology file size increased from 22001 to 22829 bytes.
1 parent 7112519 commit 4b0bbb7

5 files changed

Lines changed: 99 additions & 15 deletions

File tree

‎src/audio/kpb.c‎

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ struct comp_data {
104104
enum comp_copy_type force_copy_type; /**< should we force copy_type on kpb sink? */
105105
#ifdef CONFIG_IPC_MAJOR_4
106106
struct ipc4_kpb_module_cfg ipc4_cfg;
107+
uint32_t buff_time_ms; /**< history depth in ms; 0 = CONFIG_KPB_MAX_BUFF_TIME */
107108
#endif /* CONFIG_IPC_MAJOR_4 */
108109
uint32_t num_of_sel_mic;
109110
uint32_t num_of_in_channels;
@@ -236,6 +237,17 @@ static void kpb_lock_init(struct comp_data *kpb)
236237

237238
#endif /* __ZEPHYR__ */
238239

240+
241+
/* Return per-instance history depth (ms); fall back to Kconfig if not set via topology. */
242+
static inline uint32_t kpb_get_buff_time_ms(const struct comp_data *kpb)
243+
{
244+
#if CONFIG_IPC_MAJOR_4
245+
return kpb->buff_time_ms ? kpb->buff_time_ms : CONFIG_KPB_MAX_BUFF_TIME;
246+
#else
247+
return CONFIG_KPB_MAX_BUFF_TIME;
248+
#endif
249+
}
250+
239251
#if CONFIG_IPC_MAJOR_4
240252
/**
241253
* \brief Set and verify ipc params.
@@ -298,7 +310,7 @@ static void kpb_set_params(struct comp_dev *dev,
298310
params->sample_valid_bytes =
299311
kpb->ipc4_cfg.base_cfg.audio_fmt.valid_bit_depth / 8;
300312
params->buffer_fmt = kpb->ipc4_cfg.base_cfg.audio_fmt.interleaving_style;
301-
params->buffer.size = kpb->ipc4_cfg.base_cfg.ibs * KPB_MAX_BUFF_TIME * params->channels;
313+
params->buffer.size = kpb->ipc4_cfg.base_cfg.ibs * kpb_get_buff_time_ms(kpb) * params->channels;
302314

303315
params->host_period_bytes = params->channels *
304316
params->sample_container_bytes *
@@ -809,7 +821,11 @@ static int kpb_prepare(struct comp_dev *dev)
809821
struct sof_ipc_stream_params params;
810822
int ret = 0;
811823
int i;
812-
size_t hb_size_req = KPB_MAX_BUFFER_SIZE(kpb->config.sampling_width, kpb->config.channels);
824+
/* Use topology-set depth if provided; otherwise Kconfig default. */
825+
uint32_t buff_ms = kpb_get_buff_time_ms(kpb);
826+
size_t hb_size_req = (KPB_SAMPLNG_FREQUENCY / 1000) *
827+
(KPB_SAMPLE_CONTAINER_SIZE(kpb->config.sampling_width) / 8) *
828+
buff_ms * kpb->config.channels;
813829

814830
comp_dbg(dev, "entry");
815831

@@ -1768,7 +1784,7 @@ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli)
17681784
/* TODO: check also if client is registered */
17691785
} else if (!is_sink_ready) {
17701786
comp_err(dev, "sink not ready for draining");
1771-
} else if (cli->drain_req > KPB_MAX_DRAINING_REQ) {
1787+
} else if (cli->drain_req > kpb_get_buff_time_ms(kpb)) {
17721788
comp_cl_err(&comp_kpb, "drain request exceeds max");
17731789
} else {
17741790
if (kpb->hd.buffered < drain_req) {
@@ -2854,6 +2870,16 @@ static int kpb_set_large_config(struct comp_dev *dev, uint32_t param_id,
28542870
#endif
28552871
case KP_BUF_CLIENT_MIC_SELECT:
28562872
return kpb_set_micselect(dev, data, data_offset);
2873+
#if CONFIG_IPC_MAJOR_4
2874+
case KP_BUF_CFG_BUFF_TIME_MS: {
2875+
struct comp_data *kpb = comp_get_drvdata(dev);
2876+
if (data_offset < sizeof(uint32_t))
2877+
return -EINVAL;
2878+
kpb->buff_time_ms = *(const uint32_t *)data;
2879+
comp_info(dev, "kpb: buff_time_ms set to %u ms", kpb->buff_time_ms);
2880+
return 0;
2881+
}
2882+
#endif
28572883
default:
28582884
return -EINVAL;
28592885
}

‎src/audio/wov_arbiter/README.md‎

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -882,10 +882,10 @@ Key parameters in `dmic-wov-multi.conf`:
882882
| `VAD_GATE_CPC` | `5000` | cycles per chunk for VAD gate |
883883
| `FORMAT` | `s16le` | audio format throughout |
884884

885-
> **KPB history depth is not a topology parameter.** It is controlled exclusively by the
886-
> `CONFIG_KPB_MAX_BUFF_TIME` Kconfig option (see [Build System Configuration](#build-system-configuration)).
887-
> The topology `kpb.conf` class exposes no history-depth attribute; the buffer is
888-
> allocated at `prepare()` time using the compiled-in value.
885+
> **KPB history depth is configurable via topology.** Set `KPB_BUFF_TIME_MS` in the topology
886+
> manifest (e.g. `dmic-wov-multi-manifest.conf`) to override `CONFIG_KPB_MAX_BUFF_TIME` at
887+
> runtime — no firmware rebuild required. Omit the define or set it to `0` to fall back to
888+
> the Kconfig default (6000 ms on TGL/CAVS2.5, 2100 ms on other platforms).
889889
890890
Slot 2 (`Pipeline 103`) is deliberately placed on Core 1 (`core_id = 1`) to validate
891891
cross-core scheduling. Set all three to `core_id = 0` if a single-core topology is needed.
@@ -923,22 +923,35 @@ CONFIG_SMP=y
923923
CONFIG_MP_MAX_NUM_CPUS=4 # TGL has 4 DSP cores
924924
CONFIG_SCHED_CPU_MASK_PIN_ONLY=y
925925
926-
# KPB history buffer length (compile-time only — not exposed in topology)
927-
# Default: 6000 ms on CAVS2.5+ (TigerLake), 2100 ms on all other platforms
926+
# KPB history buffer length — compile-time floor; topology can override at runtime.
927+
# Default: 6000 ms on CAVS2.5+ (TigerLake), 2100 ms on all other platforms.
928928
# Override example: west build -- -DCONFIG_KPB_MAX_BUFF_TIME=4000
929929
CONFIG_KPB_MAX_BUFF_TIME=6000 # TGL / CAVS2.5
930930
```
931931

932-
The KPB history depth is **not** configurable via topology. The buffer size is computed
933-
at prepare time as:
932+
The KPB history depth can be set **per-platform in the topology manifest** without a
933+
firmware rebuild. The buffer size is computed at prepare time from whichever source wins:
934+
935+
| Source | Priority | How to set |
936+
|---|---|---|
937+
| Topology `KPB_BUFF_TIME_MS` | **highest** | `Define { KPB_BUFF_TIME_MS "6000" }` in manifest |
938+
| `CONFIG_KPB_MAX_BUFF_TIME` | fallback | `west build -- -DCONFIG_KPB_MAX_BUFF_TIME=4000` |
939+
940+
Buffer byte formula (16 kHz S16LE mono):
934941

935942
```
936-
buffer_bytes = (16000 / 1000) × (sample_width_bytes) × CONFIG_KPB_MAX_BUFF_TIME × channels
937-
= 16 × 2 × 6000 × 1 = 192 000 bytes (TGL, S16LE mono)
938-
= 16 × 2 × 2100 × 1 = 67 200 bytes (other platforms)
943+
buffer_bytes = 16 x 2 x buff_time_ms x channels
944+
= 16 x 2 x 6000 x 1 = 192 000 bytes (TGL, S16LE mono, 6000 ms)
945+
= 16 x 2 x 2100 x 1 = 67 200 bytes (other platforms, 2100 ms)
939946
```
940947

941-
To change the pre-roll window, rebuild with `-DCONFIG_KPB_MAX_BUFF_TIME=<ms>`.
948+
The topology kcontrol `kpb_cfg_<N>` carries a 36-byte SOF ABI blob with
949+
`type = KP_BUF_CFG_BUFF_TIME_MS = 2` and a 4-byte `uint32_t` payload. It is sent
950+
automatically to the firmware LARGE_CONFIG_SET handler when the pipeline is first opened;
951+
no userspace script is required. Supported values in `kpb.conf`: `6000`, `4000`, `2100`.
952+
To add a new value, compute the 4-byte LE payload and add an `IncludeByKey` entry.
953+
954+
To change the compile-time fallback, rebuild with `-DCONFIG_KPB_MAX_BUFF_TIME=<ms>`.
942955

943956
The `CONFIG_VAD_GATE_DEFAULT_THRESHOLD` (if exposed) compiles in a non-zero threshold; otherwise
944957
the compiled-in default is 0 (pass-through). Always set the threshold at runtime via

‎src/include/ipc4/kpb.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ struct ipc4_kpb_module_cfg {
2424
enum ipc4_kpb_module_config_params {
2525
/*! Configure the module ID's which would be part of the Fast mode tasks */
2626
KP_BUF_CFG_FM_MODULE = 1,
27+
/*! Set history ring-buffer duration; 0 = use CONFIG_KPB_MAX_BUFF_TIME */
28+
KP_BUF_CFG_BUFF_TIME_MS = 2,
2729
/* Mic selector for client - sets microphone id for real time sink mic selector
2830
* IPC4-compatible ID - please do not change the number
2931
*/

‎tools/topology/topology2/dmic-wov-multi-manifest.conf‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ Define {
104104
VAD_GATE_CPC 5000
105105
}
106106

107+
# KPB history ring-buffer depth: 6000 ms for TGL/CAVS2.5 (6 s pre-roll).
108+
# Omit or set to 0 to fall back to CONFIG_KPB_MAX_BUFF_TIME.
109+
Define {
110+
KPB_BUFF_TIME_MS "6000"
111+
}
112+
107113
# ---------------------------------------------------------------------------
108114
# Pipeline 100 — DAI (Core 0)
109115
# DMIC DAI copier → VAD Gate → Mixin (fan-out to 3 Mixouts in 101/102/103)

‎tools/topology/topology2/include/components/kpb.conf‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,43 @@ Class.Widget."kpb" {
5959
unique "instance"
6060
}
6161

62+
Object.Control.bytes."1" {
63+
name "kpb_cfg_$index"
64+
access [
65+
tlv_read
66+
tlv_write
67+
tlv_callback
68+
]
69+
Object.Base.extops."extctl" {
70+
get 258
71+
put 258
72+
}
73+
max 64
74+
Object.Base.data."1" {
75+
IncludeByKey.KPB_BUFF_TIME_MS {
76+
# sof_abi_hdr{magic, type=KP_BUF_CFG_BUFF_TIME_MS=2, size=4, abi=4.0} + u32 ms
77+
# 6000 ms = 0x00001770
78+
'6000' {bytes "0x53, 0x4f, 0x46, 0x34, 0x02, 0x00, 0x00, 0x00,
79+
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
80+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82+
0x70, 0x17, 0x00, 0x00"}
83+
# 4000 ms = 0x00000FA0
84+
'4000' {bytes "0x53, 0x4f, 0x46, 0x34, 0x02, 0x00, 0x00, 0x00,
85+
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
86+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88+
0xa0, 0x0f, 0x00, 0x00"}
89+
# 2100 ms = 0x00000834
90+
'2100' {bytes "0x53, 0x4f, 0x46, 0x34, 0x02, 0x00, 0x00, 0x00,
91+
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
92+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94+
0x34, 0x08, 0x00, 0x00"}
95+
}
96+
}
97+
}
98+
6299
#
63100
# Default attributes for kpb
64101
#

0 commit comments

Comments
 (0)