Skip to content

Commit 2389f13

Browse files
schedule: zephyr_dma_domain: Add mixer support
Currently, because of the fact only registrable pipeline tasks can be executed, the mixer no longer works since the pipeline tasks going into the mixer are non-registrable. In order to overcome this issue, non-registrable pipeline tasks will point to the same struct zephyr_dma_domain_data as the registrable pipeline task so when the DMA IRQ comes and marks the registrable pipeline task as executable these non-registrable pipeline tasks can also be executed. This is done by keeping track of how many pipeline task point to the same struct zephyr_dma_domain_data and of how many times domain_is_pending() has been called for said struct zephyr_dma_domain_data. When pending_count reaches 0, data->triggered can be set to false, meaning both the registrable and non-registrable pipeline tasks have been executed. Let's assume the following scenario with 4 pipeline tasks: 1) Host -------> Volume --------> DAI 2) Host -------> Mixer ----------> DAI ^ | Host -----------| This fix assumes that the mixer pipeline tasks will be registered as a group, meaning the first pipeline task will not be registered in between the pipeline tasks associated with the mixer. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
1 parent 481766f commit 2389f13

1 file changed

Lines changed: 60 additions & 21 deletions

File tree

src/schedule/zephyr_dma_domain.c

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@ struct zephyr_dma_domain_data {
5656
* associated channel was triggered.
5757
*/
5858
bool triggered;
59+
/* used to keep track of how many pipeline tasks point
60+
* to the same data structure.
61+
*/
62+
int usage_count;
63+
/* used to keep track of how many times data->triggered
64+
* can be left set to true before resetting it to false.
65+
*
66+
* this is needed for mixer topologies because the
67+
* non-registrable pipeline tasks need to be executed
68+
* when an IRQ comes for the registrable pipeline task.
69+
*/
70+
int pending_count;
71+
/* used when linking a data structure to a non-registrable
72+
* pipeline task.
73+
*
74+
* in the case of mixer, the non-registrable pipeline tasks
75+
* have the same scheduling component as the registrable
76+
* pipeline task so this can be used as a criteria to attach
77+
* the data structure to the non-registrable pipeline task.
78+
*/
79+
struct comp_dev *sched_comp;
5980
};
6081

6182
struct zephyr_dma_domain_thread {
@@ -219,6 +240,24 @@ static int register_dma_irq(struct zephyr_dma_domain *domain,
219240
if (core != crt_chan->core)
220241
continue;
221242

243+
if ((crt_data->sched_comp == pipe_task->sched_comp ||
244+
!crt_data->sched_comp) && !pipe_task->registrable) {
245+
/* attach crt_data to current pipeline
246+
* task only if there's a match between
247+
* the scheduling components or i
248+
* crt_data's sched_comp field wasn't
249+
* set yet.
250+
*/
251+
pipe_task->priv = crt_data;
252+
253+
crt_data->usage_count++;
254+
crt_data->pending_count++;
255+
256+
return 0;
257+
} else if (!pipe_task->registrable) {
258+
return 0;
259+
}
260+
222261
/* skip if IRQ was already registered */
223262
if (crt_data->enabled_irq)
224263
continue;
@@ -230,14 +269,10 @@ static int register_dma_irq(struct zephyr_dma_domain *domain,
230269
crt_data->irq = irq;
231270
crt_data->channel = crt_chan;
232271
crt_data->dt = dt;
272+
crt_data->sched_comp = pipe_task->sched_comp;
273+
crt_data->usage_count++;
274+
crt_data->pending_count++;
233275

234-
/* attach crt_data to pipeline task.
235-
*
236-
* this will be used in
237-
* zephyr_dma_domain_is_pending to decide
238-
* whether there was a DMA IRQ for the channel
239-
* associated with this task.
240-
*/
241276
pipe_task->priv = crt_data;
242277

243278
if (dt->started) {
@@ -285,16 +320,6 @@ static int zephyr_dma_domain_register(struct ll_schedule_domain *domain,
285320

286321
tr_info(&ll_tr, "zephyr_dma_domain_register()");
287322

288-
/* don't even bother trying to register DMA IRQ for
289-
* non-registrable tasks.
290-
*
291-
* this is needed because zephyr_dma_domain_register() will
292-
* return -EINVAL for non-registrable tasks because of
293-
* register_dma_irq() which is not right.
294-
*/
295-
if (!pipe_task->registrable)
296-
return 0;
297-
298323
/* the DMA IRQ has to be registered before the Zephyr thread is
299324
* started.
300325
*
@@ -309,12 +334,16 @@ static int zephyr_dma_domain_register(struct ll_schedule_domain *domain,
309334

310335
if (ret < 0) {
311336
tr_err(&ll_tr,
312-
"failed to register DMA IRQ for pipe task %p on core %d",
313-
pipe_task, core);
337+
"failed to register DMA IRQ for pipe task %p on core %d reg: %d",
338+
pipe_task, core, pipe_task->registrable);
314339

315340
return ret;
316341
}
317342

343+
/* don't let non-registrable tasks go further */
344+
if (!pipe_task->registrable)
345+
return 0;
346+
318347
/* skip if Zephyr thread was already started on this core */
319348
if (dt->handler)
320349
return 0;
@@ -453,15 +482,20 @@ static int zephyr_dma_domain_unregister(struct ll_schedule_domain *domain,
453482
struct zephyr_dma_domain *zephyr_dma_domain;
454483
struct zephyr_dma_domain_thread *dt;
455484
struct pipeline_task *pipe_task;
485+
struct zephyr_dma_domain_data *data;
456486
int ret, core;
457487

458488
zephyr_dma_domain = ll_sch_get_pdata(domain);
459489
pipe_task = pipeline_task_get(task);
460490
core = cpu_get_id();
461491
dt = zephyr_dma_domain->domain_thread + core;
492+
data = pipe_task->priv;
462493

463494
tr_info(&ll_tr, "zephyr_dma_domain_unregister()");
464495

496+
data->pending_count--;
497+
data->usage_count--;
498+
465499
/* unregister the DMA IRQ only for PPL tasks marked as "registrable"
466500
*
467501
* this is done because, in case of mixer topologies there's
@@ -532,9 +566,14 @@ static bool zephyr_dma_domain_is_pending(struct ll_schedule_domain *domain,
532566
* of the atomic area PLEASE make sure to disable IRQs before
533567
* calling it or disable IRQs here.
534568
*/
535-
536569
if (data->triggered) {
537-
data->triggered = false;
570+
data->pending_count--;
571+
572+
if (!data->pending_count) {
573+
data->triggered = false;
574+
data->pending_count = data->usage_count;
575+
}
576+
538577
return true;
539578
}
540579

0 commit comments

Comments
 (0)