Skip to content

Commit 149d1e6

Browse files
author
Jyri Sarha
committed
audio: src: move filter and delay line allocation to init phase
Refactor SRC and SRC-lite so that filter stage setup and delay line allocation happen during the module init callback instead of prepare. This ensures the bulk of SRC memory allocation occurs while the vregion allocator is still in its lifetime phase, before the interim heap is created. The allocations then persist across prepare/reset cycles without needing to be re-allocated each time. A new setup_stages() callback is added to struct comp_data, set by each variant (src.c, src_lite.c) to point at its own coefficient tables. The common src_allocate_delay_lines() is factored out of the old prepare path into src_common.c. For IPC4, src_init_stages() calls setup_stages() and src_allocate_delay_lines() at init time. The prepare path (src_prepare_do) only validates rates and sets downstream params. For IPC3, src_init_stages() is a no-op and src_prepare_do() retains the original behavior of doing full setup at prepare time, since IPC3 cannot be tested at this time. Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
1 parent 2104a66 commit 149d1e6

6 files changed

Lines changed: 240 additions & 38 deletions

File tree

src/audio/src/src.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,47 +34,63 @@
3434

3535
LOG_MODULE_DECLARE(src, CONFIG_SOF_LOG_LEVEL);
3636

37-
static int src_prepare(struct processing_module *mod,
38-
struct sof_source **sources, int num_of_sources,
39-
struct sof_sink **sinks, int num_of_sinks)
37+
/* Set rate table pointers, compute rate indices, and copy filter stages.
38+
* Must be in src.c because src_table1/2, src_in_fs, etc. come from
39+
* the coefficient headers included by this file.
40+
*/
41+
static int src_setup_stages(struct processing_module *mod)
4042
{
4143
struct comp_data *cd = module_get_private_data(mod);
4244
struct src_param *a = &cd->param;
4345
int ret;
4446

45-
comp_info(mod->dev, "entry");
46-
47-
if (num_of_sources != 1 || num_of_sinks != 1)
48-
return -EINVAL;
49-
5047
a->in_fs = src_in_fs;
5148
a->out_fs = src_out_fs;
5249
a->num_in_fs = NUM_IN_FS;
5350
a->num_out_fs = NUM_OUT_FS;
5451
a->max_fir_delay_size_xnch = (PLATFORM_MAX_CHANNELS * MAX_FIR_DELAY_SIZE);
5552
a->max_out_delay_size_xnch = (PLATFORM_MAX_CHANNELS * MAX_OUT_DELAY_SIZE);
5653

57-
src_get_source_sink_params(mod->dev, sources[0], sinks[0]);
58-
5954
ret = src_param_set(mod->dev, cd);
6055
if (ret < 0)
6156
return ret;
6257

63-
ret = src_allocate_copy_stages(mod, a,
64-
src_table1[a->idx_out][a->idx_in],
65-
src_table2[a->idx_out][a->idx_in]);
66-
if (ret < 0)
67-
return ret;
58+
return src_allocate_copy_stages(mod, a,
59+
src_table1[a->idx_out][a->idx_in],
60+
src_table2[a->idx_out][a->idx_in]);
61+
}
6862

69-
ret = src_params_general(mod, sources[0], sinks[0]);
63+
static int src_do_init(struct processing_module *mod)
64+
{
65+
struct comp_data *cd;
66+
int ret;
67+
68+
ret = src_init(mod);
7069
if (ret < 0)
7170
return ret;
7271

73-
return src_prepare_general(mod, sources[0], sinks[0]);
72+
cd = module_get_private_data(mod);
73+
cd->setup_stages = src_setup_stages;
74+
75+
return src_init_stages(mod);
76+
}
77+
78+
static int src_prepare(struct processing_module *mod,
79+
struct sof_source **sources, int num_of_sources,
80+
struct sof_sink **sinks, int num_of_sinks)
81+
{
82+
comp_info(mod->dev, "entry");
83+
84+
if (num_of_sources != 1 || num_of_sinks != 1)
85+
return -EINVAL;
86+
87+
src_get_source_sink_params(mod->dev, sources[0], sinks[0]);
88+
89+
return src_prepare_do(mod, sources[0], sinks[0]);
7490
}
7591

7692
static const struct module_interface src_interface = {
77-
.init = src_init,
93+
.init = src_do_init,
7894
.prepare = src_prepare,
7995
.process = src_process,
8096
.is_ready_to_process = src_is_ready_to_process,

src/audio/src/src_common.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,86 @@ int src_params_general(struct processing_module *mod,
574574
return 0;
575575
}
576576

577+
/* Allocate delay lines and initialize the polyphase SRC filter.
578+
* Assumes that cd->param rate table pointers (in_fs, out_fs, etc.)
579+
* and stage pointers (stage1, stage2) are already set up via
580+
* cd->setup_stages().
581+
*/
582+
int src_allocate_delay_lines(struct processing_module *mod)
583+
{
584+
struct comp_data *cd = module_get_private_data(mod);
585+
struct comp_dev *dev = mod->dev;
586+
size_t delay_lines_size;
587+
int32_t *buffer_start;
588+
int n;
589+
int ret;
590+
591+
/* For LL modules dev->period is already set from the pipeline.
592+
* Compute dev->frames so buffer sizing works.
593+
*/
594+
if (!dev->frames)
595+
component_set_nearest_period_frames(dev, cd->sink_rate);
596+
597+
if (!cd->sink_rate) {
598+
comp_err(dev, "zero sink rate");
599+
return -EINVAL;
600+
}
601+
602+
cd->source_frames = dev->frames * cd->source_rate / cd->sink_rate;
603+
cd->sink_frames = dev->frames;
604+
605+
/* Allocate needed memory for delay lines */
606+
ret = src_buffer_lengths(dev, cd, cd->channels_count);
607+
if (ret < 0) {
608+
comp_err(dev, "src_buffer_lengths() failed");
609+
return ret;
610+
}
611+
612+
delay_lines_size = ALIGN_UP(sizeof(int32_t) * cd->param.total, 8);
613+
if (delay_lines_size == 0) {
614+
comp_err(dev, "delay_lines_size = 0");
615+
return -EINVAL;
616+
}
617+
618+
mod_free(mod, cd->delay_lines);
619+
620+
cd->delay_lines = mod_alloc(mod, delay_lines_size);
621+
if (!cd->delay_lines) {
622+
comp_err(dev, "failed to alloc cd->delay_lines, delay_lines_size = %zu",
623+
delay_lines_size);
624+
return -ENOMEM;
625+
}
626+
627+
memset(cd->delay_lines, 0, delay_lines_size);
628+
buffer_start = cd->delay_lines + ALIGN_UP(cd->param.sbuf_length, 2);
629+
630+
/* Initialize SRC for actual sample rate */
631+
n = src_polyphase_init(&cd->src, &cd->param, buffer_start);
632+
633+
/* Reset stage buffer */
634+
cd->sbuf_r_ptr = cd->delay_lines;
635+
cd->sbuf_w_ptr = cd->delay_lines;
636+
cd->sbuf_avail = 0;
637+
638+
switch (n) {
639+
case 0:
640+
cd->src_func = src_copy_sxx;
641+
break;
642+
case 1:
643+
cd->src_func = src_1s;
644+
break;
645+
case 2:
646+
cd->src_func = src_2s;
647+
break;
648+
default:
649+
comp_info(dev, "missing coefficients for requested rates combination");
650+
cd->src_func = src_fallback;
651+
return -EINVAL;
652+
}
653+
654+
return 0;
655+
}
656+
577657
int src_param_set(struct comp_dev *dev, struct comp_data *cd)
578658
{
579659
struct src_param *a = &cd->param;

src/audio/src/src_common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ struct comp_data {
167167
int (*src_func)(struct comp_data *cd, struct sof_source *source,
168168
struct sof_sink *sink);
169169
void (*polyphase_func)(struct src_stage_prm *s);
170+
int (*setup_stages)(struct processing_module *mod);
170171
};
171172

172173
#if CONFIG_IPC_MAJOR_4
@@ -218,6 +219,7 @@ static inline int src_fallback(struct comp_data *cd,
218219
int src_allocate_copy_stages(struct processing_module *mod, struct src_param *prm,
219220
const struct src_stage *stage_src1,
220221
const struct src_stage *stage_src2);
222+
int src_allocate_delay_lines(struct processing_module *mod);
221223
int src_rate_check(const void *spec);
222224
int src_set_params(struct processing_module *mod, struct sof_sink *sink);
223225

@@ -227,6 +229,9 @@ int src_prepare_general(struct processing_module *mod,
227229
struct sof_source *source,
228230
struct sof_sink *sink);
229231
int src_init(struct processing_module *mod);
232+
int src_init_stages(struct processing_module *mod);
233+
int src_prepare_do(struct processing_module *mod,
234+
struct sof_source *source, struct sof_sink *sink);
230235

231236
int src_copy_sxx(struct comp_data *cd, struct sof_source *source,
232237
struct sof_sink *sink);

src/audio/src/src_ipc3.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,27 @@ int src_init(struct processing_module *mod)
195195
return 0;
196196
}
197197

198+
/* IPC3: No filter allocation at init, change ipc3 behavior as little as possible */
199+
int src_init_stages(struct processing_module *mod)
200+
{
201+
return 0;
202+
}
203+
204+
/* IPC3: Full filter setup at prepare time */
205+
int src_prepare_do(struct processing_module *mod,
206+
struct sof_source *source, struct sof_sink *sink)
207+
{
208+
struct comp_data *cd = module_get_private_data(mod);
209+
int ret;
210+
211+
ret = cd->setup_stages(mod);
212+
if (ret < 0)
213+
return ret;
214+
215+
ret = src_params_general(mod, source, sink);
216+
if (ret < 0)
217+
return ret;
218+
219+
return src_prepare_general(mod, source, sink);
220+
}
221+

src/audio/src/src_ipc4.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,67 @@ __cold int src_init(struct processing_module *mod)
246246
return 0;
247247
}
248248

249+
/* Called after src_init() and setup_stages callback is set.
250+
* Allocate filter stages and delay lines at init time.
251+
*/
252+
int src_init_stages(struct processing_module *mod)
253+
{
254+
struct comp_data *cd = module_get_private_data(mod);
255+
struct comp_dev *dev = mod->dev;
256+
int ret;
257+
258+
ret = cd->setup_stages(mod);
259+
if (ret < 0)
260+
return ret;
261+
262+
/* For DP modules, dev->period is not yet set at init time (it's
263+
* computed in src_set_params at prepare). Derive it here from the
264+
* IPC config's output buffer size so that delay line allocation
265+
* uses correct buffer sizes.
266+
*/
267+
if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP && !dev->frames) {
268+
uint32_t frame_bytes = cd->channels_count * cd->sample_container_bytes;
269+
270+
if (frame_bytes && cd->sink_rate) {
271+
dev->period = 1000000ULL *
272+
(cd->ipc_config.base.obs / frame_bytes) /
273+
cd->sink_rate;
274+
dev->period /= LL_TIMER_PERIOD_US;
275+
dev->period *= LL_TIMER_PERIOD_US;
276+
component_set_nearest_period_frames(dev, cd->sink_rate);
277+
}
278+
}
279+
280+
return src_allocate_delay_lines(mod);
281+
}
282+
283+
/* At prepare time just verify rates and set downstream params */
284+
int src_prepare_do(struct processing_module *mod,
285+
struct sof_source *source, struct sof_sink *sink)
286+
{
287+
struct comp_data *cd = module_get_private_data(mod);
288+
struct comp_dev *dev = mod->dev;
289+
int ret;
290+
291+
if (cd->source_rate != cd->ipc_config.base.audio_fmt.sampling_frequency ||
292+
cd->sink_rate != cd->ipc_config.sink_rate) {
293+
comp_err(mod->dev, "rate mismatch: source %u/%u sink %u/%u",
294+
cd->source_rate,
295+
cd->ipc_config.base.audio_fmt.sampling_frequency,
296+
cd->sink_rate, cd->ipc_config.sink_rate);
297+
return -EINVAL;
298+
}
299+
300+
ret = src_set_params(mod, sink);
301+
if (ret < 0) {
302+
comp_err(mod->dev, "set params failed.");
303+
return ret;
304+
}
305+
306+
/* Update frame counts with final dev->frames from src_set_params */
307+
cd->source_frames = dev->frames * cd->source_rate / cd->sink_rate;
308+
cd->sink_frames = dev->frames;
309+
310+
return src_prepare_general(mod, source, sink);
311+
}
312+

src/audio/src/src_lite.c

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,16 @@
1414

1515
LOG_MODULE_REGISTER(src_lite, CONFIG_SOF_LOG_LEVEL);
1616

17-
/*
18-
* This function is 100% identical to src_prepare(), but it's
19-
* assigning different coefficient arrays because it's including
20-
* different headers.
17+
/* Set rate table pointers, compute rate indices, and copy filter stages.
18+
* Must be in src_lite.c because src_table1/2, src_in_fs, etc. come from
19+
* the coefficient headers included by this file.
2120
*/
22-
static int src_lite_prepare(struct processing_module *mod,
23-
struct sof_source **sources, int num_of_sources,
24-
struct sof_sink **sinks, int num_of_sinks)
21+
static int src_lite_setup_stages(struct processing_module *mod)
2522
{
2623
struct comp_data *cd = module_get_private_data(mod);
2724
struct src_param *a = &cd->param;
2825
int ret;
2926

30-
comp_info(mod->dev, "entry");
31-
32-
if (num_of_sources != 1 || num_of_sinks != 1)
33-
return -EINVAL;
34-
3527
a->in_fs = src_in_fs;
3628
a->out_fs = src_out_fs;
3729
a->num_in_fs = NUM_IN_FS;
@@ -43,21 +35,42 @@ static int src_lite_prepare(struct processing_module *mod,
4335
if (ret < 0)
4436
return ret;
4537

46-
ret = src_allocate_copy_stages(mod, a,
47-
src_table1[a->idx_out][a->idx_in],
48-
src_table2[a->idx_out][a->idx_in]);
49-
if (ret < 0)
50-
return ret;
38+
return src_allocate_copy_stages(mod, a,
39+
src_table1[a->idx_out][a->idx_in],
40+
src_table2[a->idx_out][a->idx_in]);
41+
}
42+
43+
static int src_lite_do_init(struct processing_module *mod)
44+
{
45+
struct comp_data *cd;
46+
int ret;
5147

52-
ret = src_params_general(mod, sources[0], sinks[0]);
48+
ret = src_init(mod);
5349
if (ret < 0)
5450
return ret;
5551

56-
return src_prepare_general(mod, sources[0], sinks[0]);
52+
cd = module_get_private_data(mod);
53+
cd->setup_stages = src_lite_setup_stages;
54+
55+
return src_init_stages(mod);
56+
}
57+
58+
static int src_lite_prepare(struct processing_module *mod,
59+
struct sof_source **sources, int num_of_sources,
60+
struct sof_sink **sinks, int num_of_sinks)
61+
{
62+
comp_info(mod->dev, "entry");
63+
64+
if (num_of_sources != 1 || num_of_sinks != 1)
65+
return -EINVAL;
66+
67+
src_get_source_sink_params(mod->dev, sources[0], sinks[0]);
68+
69+
return src_prepare_do(mod, sources[0], sinks[0]);
5770
}
5871

5972
const struct module_interface src_lite_interface = {
60-
.init = src_init,
73+
.init = src_lite_do_init,
6174
.prepare = src_lite_prepare,
6275
.process = src_process,
6376
.is_ready_to_process = src_is_ready_to_process,

0 commit comments

Comments
 (0)