Skip to content

Commit 4ba9605

Browse files
committed
mixer: Add support for underrun notifications
Add to the mixin the capability to send notifications when an underrun occurs, leading to the generation of silence in the output. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
1 parent bb5aed1 commit 4ba9605

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

src/audio/mixin_mixout/mixin_mixout.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <sof/compiler_attributes.h>
1313
#include <rtos/panic.h>
1414
#include <sof/ipc/msg.h>
15+
#include <sof/ipc/notification_pool.h>
1516
#include <rtos/alloc.h>
1617
#include <rtos/init.h>
1718
#include <sof/lib/uuid.h>
@@ -24,6 +25,7 @@
2425
#include <ipc/stream.h>
2526
#include <ipc/topology.h>
2627
#include <ipc4/base-config.h>
28+
#include <ipc4/notification.h>
2729
#include <user/trace.h>
2830
#include <stddef.h>
2931
#include <stdint.h>
@@ -74,6 +76,10 @@ struct mixin_data {
7476
mix_func mix;
7577
mix_func gain_mix;
7678
struct mixin_sink_config sink_config[MIXIN_MAX_SINKS];
79+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
80+
uint32_t last_reported_underrun;
81+
uint32_t underrun_notification_period;
82+
#endif
7783
};
7884

7985
/*
@@ -138,6 +144,9 @@ static int mixin_init(struct processing_module *mod)
138144
return -ENOMEM;
139145

140146
mod_data->private = md;
147+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
148+
md->underrun_notification_period = MIXIN_MODULE_DEFAULT_UNDERRUN_NOTIFICATION_PERIOD;
149+
#endif
141150

142151
for (i = 0; i < MIXIN_MAX_SINKS; i++) {
143152
md->sink_config[i].mixer_mode = IPC4_MIXER_NORMAL_MODE;
@@ -237,6 +246,29 @@ static void silence(struct cir_buf_ptr *stream, uint32_t start_offset,
237246
}
238247
}
239248

249+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
250+
static void mixin_check_notify_underrun(struct comp_dev *dev, struct mixin_data *mixin_data,
251+
size_t source_avail, size_t sinks_free)
252+
{
253+
struct ipc_msg *notify;
254+
255+
mixin_data->last_reported_underrun++;
256+
257+
if (!source_avail && mixin_data->last_reported_underrun >=
258+
mixin_data->underrun_notification_period) {
259+
mixin_data->last_reported_underrun = 0;
260+
261+
notify = ipc_notification_pool_get(IPC4_RESOURCE_EVENT_SIZE);
262+
if (!notify)
263+
return;
264+
265+
mixer_underrun_notif_msg_init(notify, dev->ipc_config.id, false,
266+
source_avail, sinks_free);
267+
ipc_msg_send(notify, notify->tx_data, false);
268+
}
269+
}
270+
#endif
271+
240272
/* Most of the mixing is done here on mixin side. mixin mixes its source data
241273
* into each connected mixout sink buffer. Basically, if mixout sink buffer has
242274
* no data, mixin copies its source data into mixout sink buffer. If mixout sink
@@ -356,6 +388,15 @@ static int mixin_process(struct processing_module *mod,
356388
if (sinks_free_frames == 0 || sinks_free_frames == INT32_MAX)
357389
return 0;
358390

391+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
392+
size_t frame_bytes = source_get_frame_bytes(sources[0]);
393+
size_t min_frames = MIN(dev->frames, sinks_free_frames);
394+
395+
mixin_check_notify_underrun(dev, mixin_data,
396+
source_avail_frames * frame_bytes,
397+
min_frames * frame_bytes);
398+
#endif
399+
359400
if (source_avail_frames > 0) {
360401
size_t buf_size;
361402

@@ -917,11 +958,49 @@ static int mixin_set_config(struct processing_module *mod, uint32_t config_id,
917958
return 0;
918959
}
919960

961+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
962+
static int mixin_set_config_param(struct processing_module *mod, uint32_t param_id_data)
963+
{
964+
struct mixin_data *mixin_data = module_get_private_data(mod);
965+
union config_param_id_data cfg;
966+
967+
cfg.dw = param_id_data;
968+
969+
if (cfg.f.id == IPC4_MIXER_UNDERRUN_NOTIF_PERIOD) {
970+
if (cfg.f.data16 < MIXIN_MODULE_MIN_UNDERRUN_NOTIFICATION_PERIOD)
971+
return -EINVAL;
972+
973+
mixin_data->underrun_notification_period = cfg.f.data16;
974+
return 0;
975+
}
976+
return -EINVAL;
977+
}
978+
979+
static int mixin_get_config_param(struct processing_module *mod, uint32_t *param_id_data)
980+
{
981+
struct mixin_data *mixin_data = module_get_private_data(mod);
982+
union config_param_id_data cfg;
983+
984+
cfg.dw = *param_id_data;
985+
986+
if (cfg.f.id == IPC4_MIXER_UNDERRUN_NOTIF_PERIOD) {
987+
cfg.f.data16 = mixin_data->underrun_notification_period;
988+
*param_id_data = cfg.dw;
989+
return 0;
990+
}
991+
return -EINVAL;
992+
}
993+
#endif
994+
920995
static const struct module_interface mixin_interface = {
921996
.init = mixin_init,
922997
.prepare = mixin_prepare,
923998
.process = mixin_process,
924999
.set_configuration = mixin_set_config,
1000+
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
1001+
.set_config_param = mixin_set_config_param,
1002+
.get_config_param = mixin_get_config_param,
1003+
#endif
9251004
.reset = mixin_reset,
9261005
.free = mixin_free
9271006
};

src/audio/mixin_mixout/mixin_mixout.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include <stddef.h>
3333

3434
enum ipc4_mixin_config_param {
35+
/* config_param param id to set/get underrun notification period. */
36+
IPC4_MIXER_UNDERRUN_NOTIF_PERIOD = 0,
3537
/* large_config_set param id for ipc4_mixer_mode_config */
3638
IPC4_MIXER_MODE = 1
3739
};
@@ -42,6 +44,13 @@ enum ipc4_mixin_config_param {
4244
/* Number of supported input pins that are mixed together */
4345
#define IPC4_MIXOUT_MODULE_MAX_INPUT_QUEUES 8
4446

47+
/* Each mixin instance by default has set default notification
48+
* period to avoid notification flooding.
49+
*/
50+
#define MIXIN_MODULE_DEFAULT_UNDERRUN_NOTIFICATION_PERIOD 10
51+
#define MIXIN_MODULE_MIN_UNDERRUN_NOTIFICATION_PERIOD 1
52+
#define MIXIN_MODULE_MAX_UNDERRUN_NOTIFICATION_PERIOD 65535
53+
4554
enum ipc4_mixer_mode {
4655
/* Normal mode, just mixing */
4756
IPC4_MIXER_NORMAL_MODE = 0,

0 commit comments

Comments
 (0)