Skip to content

Commit d850d94

Browse files
makarukpmwasko
authored andcommitted
hda: enable xrun handling in chain dma
Enable detection of under/overruns and report it by sending notification. Signed-off-by: Piotr Makaruk <piotr.makaruk@intel.com>
1 parent 634c65f commit d850d94

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

src/audio/chain_dma.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
#include <sof/ut.h>
2525
#include <zephyr/pm/policy.h>
2626
#include <rtos/init.h>
27+
#if CONFIG_IPC4_XRUN_NOTIFICATIONS_ENABLE
28+
#include <ipc4/notification.h>
29+
#include <sof/ipc/msg.h>
30+
#include <ipc/header.h>
31+
#endif
2732

2833
static const struct comp_driver comp_chain_dma;
2934
static const uint32_t max_chain_number = DAI_NUM_HDA_OUT + DAI_NUM_HDA_IN;
@@ -47,6 +52,10 @@ struct chain_dma_data {
4752
enum sof_ipc_stream_direction stream_direction;
4853
/* container size in bytes */
4954
uint8_t cs;
55+
#if CONFIG_IPC4_XRUN_NOTIFICATIONS_ENABLE
56+
bool xrun_notification_sent;
57+
struct ipc_msg *msg_xrun;
58+
#endif
5059

5160
/* local host DMA config */
5261
struct dma *dma_host;
@@ -131,6 +140,34 @@ static size_t chain_get_transferred_data_size(const uint32_t out_read_pos, const
131140
return buff_size - in_read_pos + out_read_pos;
132141
}
133142

143+
#if CONFIG_IPC4_XRUN_NOTIFICATIONS_ENABLE
144+
static void handle_xrun(struct chain_dma_data *cd)
145+
{
146+
int ret;
147+
148+
if (cd->link_connector_node_id.f.dma_type == ipc4_hda_link_output_class &&
149+
!cd->xrun_notification_sent) {
150+
tr_warn(&chain_dma_tr, "handle_xrun(): underrun detected");
151+
xrun_notif_msg_init(cd->msg_xrun, cd->link_connector_node_id.dw,
152+
SOF_IPC4_GATEWAY_UNDERRUN_DETECTED);
153+
ipc_msg_send(cd->msg_xrun, NULL, true);
154+
cd->xrun_notification_sent = true;
155+
} else if (cd->link_connector_node_id.f.dma_type == ipc4_hda_link_input_class &&
156+
!cd->xrun_notification_sent) {
157+
tr_warn(&chain_dma_tr, "handle_xrun(): overrun detected");
158+
xrun_notif_msg_init(cd->msg_xrun, cd->link_connector_node_id.dw,
159+
SOF_IPC4_GATEWAY_OVERRUN_DETECTED);
160+
ipc_msg_send(cd->msg_xrun, NULL, true);
161+
cd->xrun_notification_sent = true;
162+
} else {
163+
/* if xrun_notification_sent is already set, then it means that link was
164+
* able to reach stability therefore next underrun/overrun should be reported.
165+
*/
166+
cd->xrun_notification_sent = false;
167+
}
168+
}
169+
#endif
170+
134171
static enum task_state chain_task_run(void *data)
135172
{
136173
size_t link_avail_bytes, link_free_bytes, host_avail_bytes, host_free_bytes;
@@ -150,6 +187,9 @@ static enum task_state chain_task_run(void *data)
150187
case -EPIPE:
151188
tr_warn(&chain_dma_tr, "chain_task_run(): dma_get_status() link xrun occurred,"
152189
" ret = %u", ret);
190+
#if CONFIG_IPC4_XRUN_NOTIFICATIONS_ENABLE
191+
handle_xrun(cd);
192+
#endif
153193
break;
154194
default:
155195
tr_err(&chain_dma_tr, "chain_task_run(): dma_get_status() error, ret = %u", ret);
@@ -622,6 +662,14 @@ static struct comp_dev *chain_task_create(const struct comp_driver *drv,
622662
if (ret)
623663
goto error_cd;
624664

665+
#if CONFIG_IPC4_XRUN_NOTIFICATIONS_ENABLE
666+
cd->msg_xrun = ipc_msg_init(header.dat,
667+
sizeof(struct ipc4_resource_event_data_notification));
668+
if (!cd->msg_xrun)
669+
goto error_cd;
670+
cd->xrun_notification_sent = false;
671+
#endif
672+
625673
return dev;
626674

627675
error_cd:

0 commit comments

Comments
 (0)