2626#include <zephyr/pm/policy.h>
2727#include <rtos/init.h>
2828#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
29+ #include <sof/ipc/notification_pool.h>
2930#include <ipc4/notification.h>
30- #include <sof/ipc/msg.h>
31- #include <ipc/header.h>
3231#endif
3332
3433#define DT_NUM_HDA_HOST_IN DT_PROP(DT_INST(0, intel_adsp_hda_host_in), dma_channels)
@@ -59,7 +58,6 @@ struct chain_dma_data {
5958 uint8_t cs ;
6059#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
6160 bool xrun_notification_sent ;
62- struct ipc_msg * msg_xrun ;
6361#endif
6462
6563 /* local host DMA config */
@@ -145,33 +143,32 @@ static size_t chain_get_transferred_data_size(const uint32_t out_read_pos, const
145143 return buff_size - in_read_pos + out_read_pos ;
146144}
147145
148- #if CONFIG_XRUN_NOTIFICATIONS_ENABLE
149- static void handle_xrun (struct chain_dma_data * cd )
146+ /* get status from dma and check for xrun */
147+ static int chain_get_dma_status (struct chain_dma_data * cd , struct dma_chan_data * chan ,
148+ struct dma_status * stat )
150149{
151- int ret ;
152-
153- if (cd -> link_connector_node_id .f .dma_type == ipc4_hda_link_output_class &&
154- !cd -> xrun_notification_sent ) {
155- tr_warn (& chain_dma_tr , "handle_xrun(): underrun detected" );
156- xrun_notif_msg_init (cd -> msg_xrun , cd -> link_connector_node_id .dw ,
157- SOF_IPC4_GATEWAY_UNDERRUN_DETECTED );
158- ipc_msg_send (cd -> msg_xrun , NULL , true);
159- cd -> xrun_notification_sent = true;
160- } else if (cd -> link_connector_node_id .f .dma_type == ipc4_hda_link_input_class &&
161- !cd -> xrun_notification_sent ) {
162- tr_warn (& chain_dma_tr , "handle_xrun(): overrun detected" );
163- xrun_notif_msg_init (cd -> msg_xrun , cd -> link_connector_node_id .dw ,
164- SOF_IPC4_GATEWAY_OVERRUN_DETECTED );
165- ipc_msg_send (cd -> msg_xrun , NULL , true);
166- cd -> xrun_notification_sent = true;
167- } else {
168- /* if xrun_notification_sent is already set, then it means that link was
169- * able to reach stability therefore next underrun/overrun should be reported.
170- */
150+ int ret = dma_get_status (chan -> dma -> z_dev , chan -> index , stat );
151+ #if CONFIG_XRUN_NOTIFICATIONS_ENABLE
152+ if (ret == - EPIPE && !cd -> xrun_notification_sent ) {
153+ struct ipc_msg * notify = ipc_notification_pool_get (IPC4_RESOURCE_EVENT_SIZE );
154+
155+ if (notify ) {
156+ if (cd -> stream_direction == SOF_IPC_STREAM_PLAYBACK )
157+ gateway_underrun_notif_msg_init (notify ,
158+ cd -> link_connector_node_id .dw );
159+ else
160+ gateway_overrun_notif_msg_init (notify ,
161+ cd -> link_connector_node_id .dw );
162+
163+ ipc_msg_send (notify , notify -> tx_data , false);
164+ cd -> xrun_notification_sent = true;
165+ }
166+ } else if (!ret ) {
171167 cd -> xrun_notification_sent = false;
172168 }
173- }
174169#endif
170+ return ret ;
171+ }
175172
176173static enum task_state chain_task_run (void * data )
177174{
@@ -185,16 +182,13 @@ static enum task_state chain_task_run(void *data)
185182 /* Link DMA can return -EPIPE and current status if xrun occurs, then it is not critical
186183 * and flow shall continue. Other error values will be treated as critical.
187184 */
188- ret = dma_get_status (cd -> chan_link -> dma -> z_dev , cd -> chan_link -> index , & stat );
185+ ret = chain_get_dma_status (cd , cd -> chan_link , & stat );
189186 switch (ret ) {
190187 case 0 :
191188 break ;
192189 case - EPIPE :
193190 tr_warn (& chain_dma_tr , "chain_task_run(): dma_get_status() link xrun occurred,"
194191 " ret = %d" , ret );
195- #if CONFIG_XRUN_NOTIFICATIONS_ENABLE
196- handle_xrun (cd );
197- #endif
198192 break ;
199193 default :
200194 tr_err (& chain_dma_tr , "chain_task_run(): dma_get_status() error, ret = %d" , ret );
@@ -206,7 +200,7 @@ static enum task_state chain_task_run(void *data)
206200 link_read_pos = stat .read_position ;
207201
208202 /* Host DMA does not report xruns. All error values will be treated as critical. */
209- ret = dma_get_status (cd -> chan_host -> dma -> z_dev , cd -> chan_host -> index , & stat );
203+ ret = chain_get_dma_status (cd , cd -> chan_host , & stat );
210204 if (ret < 0 ) {
211205 tr_err (& chain_dma_tr , "chain_task_run(): dma_get_status() error, ret = %d" , ret );
212206 return SOF_TASK_STATE_COMPLETED ;
@@ -685,20 +679,9 @@ __cold static struct comp_dev *chain_task_create(const struct comp_driver *drv,
685679 comp_set_drvdata (dev , cd );
686680
687681 ret = chain_task_init (dev , host_dma_id , link_dma_id , fifo_size );
688- if (ret )
689- goto error_cd ;
690-
691- #if CONFIG_XRUN_NOTIFICATIONS_ENABLE
692- cd -> msg_xrun = ipc_msg_init (header .dat ,
693- sizeof (struct ipc4_resource_event_data_notification ));
694- if (!cd -> msg_xrun )
695- goto error_cd ;
696- cd -> xrun_notification_sent = false;
697- #endif
698-
699- return dev ;
682+ if (!ret )
683+ return dev ;
700684
701- error_cd :
702685 rfree (cd );
703686error :
704687 rfree (dev );
@@ -711,10 +694,6 @@ __cold static void chain_task_free(struct comp_dev *dev)
711694
712695 assert_can_be_cold ();
713696
714- #if CONFIG_XRUN_NOTIFICATIONS_ENABLE
715- ipc_msg_free (cd -> msg_xrun );
716- #endif
717-
718697 chain_release (dev );
719698 rfree (cd );
720699 rfree (dev );
0 commit comments