[Sound-open-firmware] [PATCH] ssp: pause: fix pause/release logic
SSP can either be in paused or prepared state during stream pause depending on the state of the other SSP data direction. Make sure this is taken into account.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/ssp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/drivers/ssp.c b/src/drivers/ssp.c index a472974..404abd8 100644 --- a/src/drivers/ssp.c +++ b/src/drivers/ssp.c @@ -356,7 +356,8 @@ static int ssp_trigger(struct dai *dai, int cmd, int direction) ssp_start(dai, direction); break; case COMP_CMD_RELEASE: - if (ssp->state[direction] == COMP_STATE_PAUSED) + if (ssp->state[direction] == COMP_STATE_PAUSED || + ssp->state[direction] == COMP_STATE_PREPARE) ssp_start(dai, direction); break; case COMP_CMD_STOP:
Make sure SSP does not assert FIFO requests for trailing bytes.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/ssp.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/src/drivers/ssp.c b/src/drivers/ssp.c index 404abd8..8eacd0c 100644 --- a/src/drivers/ssp.c +++ b/src/drivers/ssp.c @@ -213,21 +213,17 @@ static inline int ssp_set_config(struct dai *dai,
/* enable I2S mode */ sscr3 |= SSCR3_I2S_ENA | SSCR3_I2S_TX_ENA | SSCR3_I2S_RX_ENA; - sscr0 |= SSCR0_PSP; - sscr1 |= SSCR1_TRAIL;
/* set asserted frame length */ frame_len = config->sample_container_bits; break; case SOF_DAI_FMT_DSP_A: sscr0 |= SSCR0_PSP | SSCR0_MOD | SSCR0_FRDC(config->num_slots); - sscr1 |= SSCR1_TRAIL; sspsp |= SSPSP_SFRMWDTH(1) | SSPSP_SFRMDLY(2); break; case SOF_DAI_FMT_DSP_B: sscr0 |= SSCR0_PSP | SSCR0_MOD | SSCR0_FRDC(config->num_slots); - sscr1 |= SSCR1_TRAIL; sspsp |= SSPSP_SFRMWDTH(1); break; default:
Make sure we check all component state transitions and report any errors to trace by calling comp_set_state().
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com
comp fixup --- src/audio/component.c | 22 +++++++++++++++++++++- src/audio/dai.c | 12 +++++++++--- src/audio/eq_fir.c | 16 +++++++++++----- src/audio/eq_iir.c | 16 +++++++++++----- src/audio/host.c | 7 ++++++- src/audio/mixer.c | 13 +++++++++---- src/audio/src.c | 7 ++++--- src/audio/tone.c | 14 ++++++++++---- src/audio/volume.c | 20 ++++++++++++++------ src/include/reef/audio/component.h | 2 ++ 10 files changed, 97 insertions(+), 32 deletions(-)
diff --git a/src/audio/component.c b/src/audio/component.c index 80311e3..5815fad 100644 --- a/src/audio/component.c +++ b/src/audio/component.c @@ -142,7 +142,7 @@ int comp_set_state(struct comp_dev *dev, int cmd) break; case COMP_CMD_STOP: if (dev->state == COMP_STATE_ACTIVE) { - dev->state = COMP_STATE_READY; + dev->state = COMP_STATE_PREPARE; } else { trace_comp_error("CEs"); trace_value(dev->state); @@ -159,6 +159,26 @@ int comp_set_state(struct comp_dev *dev, int cmd) ret = -EINVAL; } break; + case COMP_CMD_RESET: + /* reset always succeeds */ + dev->state = COMP_STATE_READY; + if (dev->state == COMP_STATE_ACTIVE || + dev->state == COMP_STATE_PAUSED) { + trace_comp_error("CER"); + trace_value(dev->state); + ret = 0; + } + break; + case COMP_CMD_PREPARE: + if (dev->state == COMP_STATE_PREPARE || + dev->state == COMP_STATE_READY) { + dev->state = COMP_STATE_PREPARE; + } else { + trace_comp_error("CEP"); + trace_value(dev->state); + ret = -EINVAL; + } + break; default: break; } diff --git a/src/audio/dai.c b/src/audio/dai.c index 4f9a082..25049c2 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -396,10 +396,15 @@ static int dai_prepare(struct comp_dev *dev)
trace_dai("pre");
+ ret = comp_set_state(dev, COMP_CMD_PREPARE); + if (ret < 0) + return ret; + dev->position = 0;
if (list_is_empty(&dd->config.elem_list)) { trace_dai_error("wdm"); + comp_set_state(dev, COMP_CMD_RESET); return -EINVAL; }
@@ -412,8 +417,9 @@ static int dai_prepare(struct comp_dev *dev) }
ret = dma_set_config(dd->dma, dd->chan, &dd->config); - if (ret == 0) - dev->state = COMP_STATE_PREPARE; + if (ret < 0) + comp_set_state(dev, COMP_CMD_RESET); + return ret; }
@@ -440,7 +446,7 @@ static int dai_reset(struct comp_dev *dev) dd->last_bytes = 0; dd->wallclock = 0; dev->position = 0; - dev->state = COMP_STATE_READY; + comp_set_state(dev, COMP_CMD_RESET);
return 0; } diff --git a/src/audio/eq_fir.c b/src/audio/eq_fir.c index 323c702..d1f5072 100644 --- a/src/audio/eq_fir.c +++ b/src/audio/eq_fir.c @@ -468,18 +468,24 @@ static int eq_fir_prepare(struct comp_dev *dev)
trace_eq("EPp");
+ ret = comp_set_state(dev, COMP_CMD_PREPARE); + if (ret < 0) + return ret; + cd->eq_fir_func = eq_fir_s32_default;
/* Initialize EQ */ - if (cd->config == NULL) + if (cd->config == NULL) { + comp_set_state(dev, COMP_CMD_RESET); return -EINVAL; + }
ret = eq_fir_setup(cd->fir, cd->config, dev->params.channels); - if (ret < 0) + if (ret < 0) { + comp_set_state(dev, COMP_CMD_RESET); return ret; + }
- //dev->preload = PLAT_INT_PERIODS; - dev->state = COMP_STATE_PREPARE; return 0; }
@@ -502,7 +508,7 @@ static int eq_fir_reset(struct comp_dev *dev) for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) fir_reset(&cd->fir[i]);
- dev->state = COMP_STATE_INIT; + comp_set_state(dev, COMP_CMD_RESET); return 0; }
diff --git a/src/audio/eq_iir.c b/src/audio/eq_iir.c index f8e3040..723e5b3 100644 --- a/src/audio/eq_iir.c +++ b/src/audio/eq_iir.c @@ -463,21 +463,27 @@ static int eq_iir_prepare(struct comp_dev *dev)
trace_eq_iir("EPp");
+ ret = comp_set_state(dev, COMP_CMD_PREPARE); + if (ret < 0) + return ret; + cd->eq_iir_func = eq_iir_s32_default;
/* Initialize EQ. Note that if EQ has not received command to * configure the response the EQ prepare returns an error that * interrupts pipeline prepare for downstream. */ - if (cd->config == NULL) + if (cd->config == NULL) { + comp_set_state(dev, COMP_CMD_RESET); return -EINVAL; + }
ret = eq_iir_setup(cd->iir, cd->config, dev->params.channels); - if (ret < 0) + if (ret < 0) { + comp_set_state(dev, COMP_CMD_RESET); return ret; + }
- //dev->preload = PLAT_INT_PERIODS; - dev->state = COMP_STATE_PREPARE; return 0; }
@@ -500,7 +506,7 @@ static int eq_iir_reset(struct comp_dev *dev) for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) iir_reset_df2t(&cd->iir[i]);
- dev->state = COMP_STATE_INIT; + comp_set_state(dev, COMP_CMD_RESET); return 0; }
diff --git a/src/audio/host.c b/src/audio/host.c index 4990f11..14a77d4 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -487,9 +487,14 @@ static int host_prepare(struct comp_dev *dev) { struct host_data *hd = comp_get_drvdata(dev); struct comp_buffer *dma_buffer; + int ret;
trace_host("pre");
+ ret = comp_set_state(dev, COMP_CMD_PREPARE); + if (ret < 0) + return ret; + if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) dma_buffer = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); @@ -505,7 +510,6 @@ static int host_prepare(struct comp_dev *dev) hd->split_remaining = 0; dev->position = 0;
- dev->state = COMP_STATE_PREPARE; return 0; }
@@ -519,6 +523,7 @@ static int host_pointer_reset(struct comp_dev *dev) hd->local_pos = 0; hd->report_pos = 0; dev->position = 0; + comp_set_state(dev, COMP_CMD_RESET);
return 0; } diff --git a/src/audio/mixer.c b/src/audio/mixer.c index 3321684..cf265a7 100644 --- a/src/audio/mixer.c +++ b/src/audio/mixer.c @@ -286,7 +286,7 @@ static int mixer_reset(struct comp_dev *dev) return 1; /* should not reset the downstream components */ }
- dev->state = COMP_STATE_READY; + comp_set_state(dev, COMP_CMD_RESET); return 0; }
@@ -304,13 +304,20 @@ static int mixer_prepare(struct comp_dev *dev) struct list_item * blist; struct comp_buffer *source; int downstream = 0; + int ret;
trace_mixer("pre");
+ /* does mixer already have active source streams ? */ if (dev->state != COMP_STATE_ACTIVE) { + + /* currently inactive so setup mixer */ md->mix_func = mix_n; dev->state = COMP_STATE_PREPARE; - //dev->preload = PLAT_INT_PERIODS; + + ret = comp_set_state(dev, COMP_CMD_PREPARE); + if (ret < 0) + return ret; }
/* check each mixer source state */ @@ -324,8 +331,6 @@ static int mixer_prepare(struct comp_dev *dev) } }
- dev->state = COMP_STATE_PREPARE; - /* prepare downstream */ return downstream; } diff --git a/src/audio/src.c b/src/audio/src.c index 993c76b..4c4bc6e 100644 --- a/src/audio/src.c +++ b/src/audio/src.c @@ -549,8 +549,9 @@ static int src_copy(struct comp_dev *dev)
static int src_prepare(struct comp_dev *dev) { - dev->state = COMP_STATE_PREPARE; - return 0; + trace_src("pre"); + + return comp_set_state(dev, COMP_CMD_PREPARE); }
static int src_preload(struct comp_dev *dev) @@ -569,7 +570,7 @@ static int src_reset(struct comp_dev *dev) for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) src_polyphase_reset(&cd->src[i]);
- dev->state = COMP_STATE_READY; + comp_set_state(dev, COMP_CMD_RESET); return 0; }
diff --git a/src/audio/tone.c b/src/audio/tone.c index 0a91f09..0baf247 100644 --- a/src/audio/tone.c +++ b/src/audio/tone.c @@ -517,12 +517,17 @@ static int tone_copy(struct comp_dev *dev)
static int tone_prepare(struct comp_dev *dev) { + struct comp_data *cd = comp_get_drvdata(dev); int32_t f; int32_t a; - struct comp_data *cd = comp_get_drvdata(dev); + int ret;
trace_tone("TPp");
+ ret = comp_set_state(dev, COMP_CMD_PREPARE); + if (ret < 0) + return ret; + cd->channels = dev->params.channels; cd->rate = dev->params.rate; tracev_value(cd->channels); @@ -530,10 +535,11 @@ static int tone_prepare(struct comp_dev *dev)
f = tonegen_get_f(&cd->sg); a = tonegen_get_a(&cd->sg); - if (tonegen_init(&cd->sg, cd->rate, f, a) < 0) + if (tonegen_init(&cd->sg, cd->rate, f, a) < 0) { + comp_set_state(dev, COMP_CMD_RESET); return -EINVAL; + }
- dev->state = COMP_STATE_PREPARE; return 0; }
@@ -552,7 +558,7 @@ static int tone_reset(struct comp_dev *dev) /* Initialize with the defaults */ tonegen_reset(&cd->sg);
- dev->state = COMP_STATE_READY; + comp_set_state(dev, COMP_CMD_RESET);
return 0; } diff --git a/src/audio/volume.c b/src/audio/volume.c index 04d1b34..472aab9 100644 --- a/src/audio/volume.c +++ b/src/audio/volume.c @@ -566,6 +566,10 @@ static int volume_prepare(struct comp_dev *dev)
trace_volume("pre");
+ ret = comp_set_state(dev, COMP_CMD_PREPARE); + if (ret < 0) + return ret; + /* volume components will only ever have 1 source and 1 sink buffer */ sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); @@ -617,7 +621,7 @@ static int volume_prepare(struct comp_dev *dev) config->periods_sink); if (ret < 0) { trace_volume_error("vp0"); - return ret; + goto err; }
buffer_reset_pos(sinkb); @@ -627,13 +631,15 @@ static int volume_prepare(struct comp_dev *dev) trace_volume_error("vp1"); trace_value(dev->frames); trace_value(sinkb->sink->frame_bytes); - return -EINVAL; + ret = -EINVAL; + goto err; } if (cd->source_period_bytes == 0) { trace_volume_error("vp2"); trace_value(dev->frames); trace_value(sourceb->source->frame_bytes); - return -EINVAL; + ret = -EINVAL; + goto err; }
/* map the volume function for source and sink buffers */ @@ -653,13 +659,15 @@ static int volume_prepare(struct comp_dev *dev) trace_value(cd->source_format); trace_value(cd->sink_format); trace_value(dev->params.channels); - return -EINVAL; + +err: + comp_set_state(dev, COMP_CMD_RESET); + return ret;
found: for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) vol_sync_host(cd, i);
- dev->state = COMP_STATE_PREPARE; return 0; }
@@ -683,7 +691,7 @@ static int volume_reset(struct comp_dev *dev) { trace_volume("res");
- dev->state = COMP_STATE_READY; + comp_set_state(dev, COMP_CMD_RESET); return 0; }
diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h index 436a758..db5f35b 100644 --- a/src/include/reef/audio/component.h +++ b/src/include/reef/audio/component.h @@ -78,6 +78,8 @@ #define COMP_CMD_RELEASE 3 /* release paused component stream */ #define COMP_CMD_SUSPEND 5 /* suspend component */ #define COMP_CMD_RESUME 6 /* resume component */ +#define COMP_CMD_RESET 6 /* reset component */ +#define COMP_CMD_PREPARE 7 /* prepare component */
/* * standard component control commands
Use platform timer for timestamp.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/dw-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index 007bf3f..3606611 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -422,7 +422,7 @@ static int dw_dma_status(struct dma *dma, int channel, status->state = p->chan[channel].status; status->r_pos = dw_read(dma, DW_SAR(channel)); status->w_pos = dw_read(dma, DW_DAR(channel)); - status->timestamp = timer_get_system(NULL); + status->timestamp = timer_get_system(platform_timer);
return 0; }
Use the COMP_STATE_READY to indicate a channel has an assigned user and ready for use.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/dw-dma.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index 3606611..2289787 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -215,10 +215,10 @@ static int dw_dma_channel_get(struct dma *dma) for (i = 0; i < DW_MAX_CHAN; i++) {
/* use channel if it's free */ - if (p->chan[i].status != COMP_STATE_READY) + if (p->chan[i].status != COMP_STATE_INIT) continue;
- p->chan[i].status = COMP_STATE_PREPARE; + p->chan[i].status = COMP_STATE_READY;
/* unmask block, transfer and error interrupts for channel */ dw_write(dma, DW_MASK_TFR, INT_UNMASK(i)); @@ -255,7 +255,7 @@ static void dw_dma_channel_put_unlocked(struct dma *dma, int channel) }
/* set new state */ - p->chan[channel].status = COMP_STATE_READY; + p->chan[channel].status = COMP_STATE_INIT; p->chan[channel].cb = NULL; p->chan[channel].desc_count = 0; } @@ -406,7 +406,7 @@ static int dw_dma_stop(struct dma *dma, int channel) goto out; }
- p->chan[channel].status = COMP_STATE_PAUSED; + p->chan[channel].status = COMP_STATE_PREPARE;
out: spin_unlock_irq(&dma->lock, flags); @@ -578,6 +578,7 @@ static int dw_dma_set_config(struct dma *dma, int channel, #endif }
+ p->chan[channel].status = COMP_STATE_PREPARE; spin_unlock_irq(&dma->lock, flags);
return 0; @@ -842,7 +843,7 @@ static int dw_dma_probe(struct dma *dma) for (i = 0; i < DW_MAX_CHAN; i++) { dw_pdata->chan[i].dma = dma; dw_pdata->chan[i].channel = i; - dw_pdata->chan[i].status = COMP_STATE_READY; + dw_pdata->chan[i].status = COMP_STATE_INIT; }
/* register our IRQ handler */
The reload handling code has 3 outcomes that are better represented in a switch statement. Remove unreachable if statement too.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/dw-dma.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index 2289787..e9d584f 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -746,17 +746,17 @@ static void dw_dma_irq_handler(void *data) * if we are waiting for pause, pause it; * otherwise, reload lli */ - if (next.size == DMA_RELOAD_END) { + switch (next.size) { + case DMA_RELOAD_END: p->chan[i].status = COMP_STATE_PREPARE; - continue; - } - else if (next.size != DMA_RELOAD_LLI) - dw_dma_chan_reload_next(dma, i, &next); - /* reload lli, but let's check if we are pausing first */ - else if (p->chan[i].status == COMP_STATE_PAUSED) { - continue; - } else + break; + case DMA_RELOAD_LLI: dw_dma_chan_reload_lli(dma, i); + break; + default: + dw_dma_chan_reload_next(dma, i, &next); + break; + } } #if DW_USE_HW_LLI /* end of a LLI block */
Report an error if channel is still active during stop.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/dw-dma.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index e9d584f..66d0cf5 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -398,17 +398,16 @@ static int dw_dma_stop(struct dma *dma, int channel)
spin_lock_irq(&dma->lock, flags);
- tracev_dma("DDi"); + trace_dma("DDi");
- /* has channel already disabled ? */ - if (!(dw_read(dma, DW_DMA_CHAN_EN) & (0x1 << channel))) { - p->chan[channel].status = COMP_STATE_PREPARE; - goto out; + /* is channel stii active ? */ + if ((dw_read(dma, DW_DMA_CHAN_EN) & (0x1 << channel))) { + trace_dma_error("ea0"); + trace_value(channel); }
p->chan[channel].status = COMP_STATE_PREPARE;
-out: spin_unlock_irq(&dma->lock, flags); return ret; }
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/dw-dma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index 66d0cf5..108a96b 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -717,8 +717,10 @@ static void dw_dma_irq_handler(void *data) platform_interrupt_clear(dma_irq(dma), pmask);
/* confirm IRQ cleared */ - if (dw_read(dma, DW_STATUS_BLOCK)) { + status_block = dw_read(dma, DW_STATUS_BLOCK); + if (status_block) { trace_dma_error("eii"); + trace_value(status_block); }
for (i = 0; i < DW_MAX_CHAN; i++) {
Block on DMA completion for stop/pause to serialise IPC with host. i.e. new host IPC is queued until DMA completes.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/dai.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 25049c2..36671fe 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -62,6 +62,7 @@ struct dai_data { struct dai *dai; struct dma *dma; uint32_t period_bytes; + completion_t complete;
uint32_t last_bytes; /* the last bytes(<period size) it copies. */ uint32_t dai_pos_blks; /* position in bytes (nearest block) */ @@ -90,6 +91,9 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next)
/* tell DMA not to reload */ next->size = DMA_RELOAD_END; + + /* inform waiters */ + wait_completed(&dd->complete); return; }
@@ -460,6 +464,8 @@ static int dai_cmd(struct comp_dev *dev, int cmd, void *data) trace_dai("cmd"); tracev_value(cmd);
+ wait_init(&dd->complete); + ret = comp_set_state(dev, cmd); if (ret < 0) return ret; @@ -475,6 +481,18 @@ static int dai_cmd(struct comp_dev *dev, int cmd, void *data) /* update starting wallclock */ platform_dai_wallclock(dev, &dd->wallclock); break; + case COMP_CMD_PAUSE: + case COMP_CMD_STOP: + wait_init(&dd->complete); + + /* wait for DMA to complete */ + dd->complete.timeout = dev->pipeline->ipc_pipe.deadline; + ret = wait_for_completion_timeout(&dd->complete); + if (ret < 0) { + trace_dai_error("ed0"); + trace_value(cmd); + } + break; default: break; }
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/drivers/dw-dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index 108a96b..05791e6 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -544,8 +544,8 @@ static int dw_dma_set_config(struct dma *dma, int channel, }
if (sg_elem->size > DW_CTLH_BLOCK_TS_MASK) { - trace_dma_error("eDS"); - return -EINVAL; + trace_dma_error("eDS"); + return -EINVAL; } /* set transfer size of element */ #if defined CONFIG_BAYTRAIL || defined CONFIG_CHERRYTRAIL
Also place a TODO for future improvement.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/audio/host.c b/src/audio/host.c index 14a77d4..3c77aca 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -315,6 +315,7 @@ static int create_local_elems(struct comp_dev *dev) struct list_item *tlist; int i;
+ /* TODO: simplify elem storage by using an array */ for (i = 0; i < hd->period_count; i++) { /* allocate new host DMA elem and add it to our list */ e = rzalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*e)); @@ -337,11 +338,11 @@ static int create_local_elems(struct comp_dev *dev)
unwind: list_for_item_safe(elist, tlist, &hd->local.elem_list) { - e = container_of(elist, struct dma_sg_elem, list); list_item_del(&e->list); rfree(e); } + trace_host_error("el0"); return -ENOMEM; }
participants (1)
-
Liam Girdwood