@@ -62,24 +62,66 @@ struct dai_data {
6262 struct dai * dai ;
6363 struct dma * dma ;
6464 uint32_t period_bytes ;
65- completion_t complete ;
6665 int xrun ; /* true if we are doing xrun recovery */
6766 int pointer_init ; /* true if buffer pointer was initialized */
6867
69- uint32_t last_bytes ; /* the last bytes(<period size) it copies. */
7068 uint32_t dai_pos_blks ; /* position in bytes (nearest block) */
7169
7270 volatile uint64_t * dai_pos ; /* host can read back this value without IPC */
7371 uint64_t wallclock ; /* wall clock at stream start */
7472};
7573
74+ static void dai_buffer_process (struct comp_dev * dev )
75+ {
76+ struct dai_data * dd = comp_get_drvdata (dev );
77+ struct comp_buffer * dma_buffer ;
78+ void * buffer_ptr ;
79+
80+ if (dev -> params .direction == SOF_IPC_STREAM_PLAYBACK ) {
81+ dma_buffer = list_first_item (& dev -> bsource_list ,
82+ struct comp_buffer , sink_list );
83+
84+ /* recalc available buffer space */
85+ comp_update_buffer_consume (dma_buffer , dd -> period_bytes );
86+
87+ buffer_ptr = dma_buffer -> r_ptr ;
88+
89+ /* make sure there is available bytes for next period */
90+ if (dma_buffer -> avail < dd -> period_bytes ) {
91+ trace_dai_error ("xru" );
92+ comp_underrun (dev , dma_buffer , dd -> period_bytes , 0 );
93+ }
94+ } else {
95+ dma_buffer = list_first_item (& dev -> bsink_list ,
96+ struct comp_buffer , source_list );
97+
98+ /* recalc available buffer space */
99+ comp_update_buffer_produce (dma_buffer , dd -> period_bytes );
100+
101+ buffer_ptr = dma_buffer -> w_ptr ;
102+
103+ /* make sure there is free bytes for next period */
104+ if (dma_buffer -> free < dd -> period_bytes ) {
105+ trace_dai_error ("xro" );
106+ comp_overrun (dev , dma_buffer , dd -> period_bytes , 0 );
107+ }
108+ }
109+
110+ /* update host position (in bytes offset) for drivers */
111+ dev -> position += dd -> period_bytes ;
112+ if (dd -> dai_pos ) {
113+ dd -> dai_pos_blks += dd -> period_bytes ;
114+ * dd -> dai_pos = dd -> dai_pos_blks +
115+ buffer_ptr - dma_buffer -> addr ;
116+ }
117+ }
118+
76119/* this is called by DMA driver every time descriptor has completed */
77120static void dai_dma_cb (void * data , uint32_t type , struct dma_sg_elem * next )
78121{
79122 struct comp_dev * dev = (struct comp_dev * )data ;
80123 struct dai_data * dd = comp_get_drvdata (dev );
81124 struct comp_buffer * dma_buffer ;
82- uint32_t copied_size ;
83125
84126 tracev_dai ("irq" );
85127
@@ -91,9 +133,6 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next)
91133
92134 /* tell DMA not to reload */
93135 next -> size = DMA_RELOAD_END ;
94-
95- /* inform waiters */
96- wait_completed (& dd -> complete );
97136 }
98137
99138 /* is our pipeline handling an XRUN ? */
@@ -111,50 +150,7 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next)
111150 return ;
112151 }
113152
114- if (dev -> params .direction == SOF_IPC_STREAM_PLAYBACK ) {
115- dma_buffer = list_first_item (& dev -> bsource_list ,
116- struct comp_buffer , sink_list );
117-
118- copied_size = dd -> last_bytes ? dd -> last_bytes : dd -> period_bytes ;
119-
120- /* recalc available buffer space */
121- comp_update_buffer_consume (dma_buffer , copied_size );
122-
123- /* update host position(in bytes offset) for drivers */
124- dev -> position += copied_size ;
125- if (dd -> dai_pos ) {
126- dd -> dai_pos_blks += copied_size ;
127- * dd -> dai_pos = dd -> dai_pos_blks +
128- dma_buffer -> r_ptr - dma_buffer -> addr ;
129- }
130-
131- /* make sure there is availble bytes for next period */
132- if (dma_buffer -> avail < dd -> period_bytes ) {
133- trace_dai_error ("xru" );
134- comp_underrun (dev , dma_buffer , copied_size , 0 );
135- }
136-
137- } else {
138- dma_buffer = list_first_item (& dev -> bsink_list ,
139- struct comp_buffer , source_list );
140-
141- /* recalc available buffer space */
142- comp_update_buffer_produce (dma_buffer , dd -> period_bytes );
143-
144- /* update positions */
145- dev -> position += dd -> period_bytes ;
146- if (dd -> dai_pos ) {
147- dd -> dai_pos_blks += dd -> period_bytes ;
148- * dd -> dai_pos = dd -> dai_pos_blks +
149- dma_buffer -> w_ptr - dma_buffer -> addr ;
150- }
151-
152- /* make sure there is free bytes for next period */
153- if (dma_buffer -> free < dd -> period_bytes ) {
154- trace_dai_error ("xro" );
155- comp_overrun (dev , dma_buffer , dd -> period_bytes , 0 );
156- }
157- }
153+ dai_buffer_process (dev );
158154
159155 /* notify pipeline that DAI needs its buffer processed */
160156 if (dev -> state == COMP_STATE_ACTIVE )
@@ -206,7 +202,6 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp)
206202 list_init (& dd -> config .elem_list );
207203 dd -> dai_pos = NULL ;
208204 dd -> dai_pos_blks = 0 ;
209- dd -> last_bytes = 0 ;
210205 dd -> xrun = 0 ;
211206 dd -> pointer_init = 0 ;
212207
@@ -489,7 +484,6 @@ static int dai_reset(struct comp_dev *dev)
489484 if (dd -> dai_pos )
490485 * dd -> dai_pos = 0 ;
491486 dd -> dai_pos = NULL ;
492- dd -> last_bytes = 0 ;
493487 dd -> wallclock = 0 ;
494488 dev -> position = 0 ;
495489 dd -> xrun = 0 ;
@@ -536,13 +530,12 @@ static void dai_pointer_init(struct comp_dev *dev)
536530static int dai_comp_trigger (struct comp_dev * dev , int cmd )
537531{
538532 struct dai_data * dd = comp_get_drvdata (dev );
533+ struct comp_buffer * dma_buffer ;
539534 int ret ;
540535
541536 trace_dai ("trg" );
542537 tracev_value (cmd );
543538
544- wait_init (& dd -> complete );
545-
546539 ret = comp_set_state (dev , cmd );
547540 if (ret < 0 )
548541 return ret ;
@@ -572,14 +565,22 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd)
572565 * this is only supported at capture mode.
573566 */
574567 if (dev -> params .direction == SOF_IPC_STREAM_CAPTURE ) {
575- struct comp_buffer * dma_buffer =
576- list_first_item ( & dev -> bsink_list ,
577- struct comp_buffer , source_list );
568+ dma_buffer = list_first_item ( & dev -> bsink_list ,
569+ struct comp_buffer ,
570+ source_list );
578571 buffer_zero (dma_buffer );
579572 }
580573
581574 /* only start the DAI if we are not XRUN handling */
582575 if (dd -> xrun == 0 ) {
576+ /* set valid buffer pointer */
577+ dai_buffer_process (dev );
578+
579+ /* recover valid start position */
580+ ret = dma_release (dd -> dma , dd -> chan );
581+ if (ret < 0 )
582+ return ret ;
583+
583584 /* start the DAI */
584585 ret = dma_start (dd -> dma , dd -> chan );
585586 if (ret < 0 )
@@ -595,26 +596,13 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd)
595596 case COMP_TRIGGER_XRUN :
596597 trace_dai ("txr" );
597598 dd -> xrun = 1 ;
598- /* stop the DAI unconditionally */
599- dai_trigger (dd -> dai , COMP_TRIGGER_STOP , dev -> params .direction );
600- ret = dma_stop (dd -> dma , dd -> chan );
601- break ;
599+
600+ /* fallthrough */
602601 case COMP_TRIGGER_PAUSE :
603602 case COMP_TRIGGER_STOP :
604603 trace_dai ("tsp" );
605- wait_init (& dd -> complete );
606-
607- /* wait for DMA to complete */
608- dd -> complete .timeout = dev -> pipeline -> ipc_pipe .deadline ;
609- ret = wait_for_completion_timeout (& dd -> complete );
610- if (ret < 0 ) {
611- trace_dai_error ("ed0" );
612- trace_error_value (cmd );
613- /* forced stop of DMA+DAI to avoid refcount issues */
614- dai_trigger (dd -> dai , COMP_TRIGGER_STOP ,
615- dev -> params .direction );
616- ret = dma_stop (dd -> dma , dd -> chan );
617- }
604+ ret = dma_stop (dd -> dma , dd -> chan );
605+ dai_trigger (dd -> dai , COMP_TRIGGER_STOP , dev -> params .direction );
618606 break ;
619607 default :
620608 break ;
0 commit comments