Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/audio/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ static int dai_playback_params(struct comp_dev *dev)
config->src_width = comp_sample_bytes(dev);
config->dest_width = comp_sample_bytes(dev);
config->cyclic = 1;
config->irq_disabled = pipeline_is_timer_driven(dev->pipeline);
config->dest_dev = dd->dai->plat_data.fifo[0].handshake;

/* set up local and host DMA elems to reset values */
Expand Down Expand Up @@ -343,6 +344,7 @@ static int dai_capture_params(struct comp_dev *dev)
/* set up DMA configuration */
config->direction = DMA_DIR_DEV_TO_MEM;
config->cyclic = 1;
config->irq_disabled = pipeline_is_timer_driven(dev->pipeline);
config->src_dev = dd->dai->plat_data.fifo[1].handshake;

/* TODO: Make this code platform-specific or move it driver callback */
Expand Down
1 change: 1 addition & 0 deletions src/audio/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ static int host_params(struct comp_dev *dev)
config->src_width = comp_sample_bytes(dev);
config->dest_width = comp_sample_bytes(dev);
config->cyclic = 0;
config->irq_disabled = pipeline_is_timer_driven(dev->pipeline);

#if CONFIG_DMA_GW
dev->params.stream_tag -= 1;
Expand Down
122 changes: 98 additions & 24 deletions src/drivers/dw/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ struct dma_chan_data {
uint32_t cfg_lo;
uint32_t cfg_hi;
struct dma_id id;
bool irq_disabled;

/* pointer data */
struct dma_ptr_data ptr_data;
Expand Down Expand Up @@ -336,6 +337,64 @@ static inline void dw_update_bits(struct dma *dma, uint32_t reg, uint32_t mask,
io_reg_update_bits(dma_base(dma) + reg, mask, value);
}

static void dw_dma_interrupt_mask(struct dma *dma, int channel)
{
const struct dma_pdata *p = dma_get_drvdata(dma);

if (p->chan[channel].irq_disabled) {
tracev_event(TRACE_CLASS_DMA, "dw_dma_interrupt_mask(): "
"dma %d channel %d not working in irq mode",
Comment thread
tlauda marked this conversation as resolved.
Resolved
dma->plat_data.id, channel);
return;
}

/* mask block, transfer and error interrupts for channel */
dw_write(dma, DW_MASK_TFR, INT_MASK(channel));
dw_write(dma, DW_MASK_BLOCK, INT_MASK(channel));
dw_write(dma, DW_MASK_ERR, INT_MASK(channel));
}

static void dw_dma_interrupt_unmask(struct dma *dma, int channel)
{
const struct dma_pdata *p = dma_get_drvdata(dma);

if (p->chan[channel].irq_disabled) {
tracev_event(TRACE_CLASS_DMA, "dw_dma_interrupt_mask(): "
"dma %d channel %d not working in irq mode",
Comment thread
tlauda marked this conversation as resolved.
Resolved
dma->plat_data.id, channel);
return;
}

/* unmask block, transfer and error interrupts for channel */
dw_write(dma, DW_MASK_TFR, INT_UNMASK(channel));
dw_write(dma, DW_MASK_BLOCK, INT_UNMASK(channel));
dw_write(dma, DW_MASK_ERR, INT_UNMASK(channel));
}

static void dw_dma_interrupt_clear(struct dma *dma, int channel)
{
const struct dma_pdata *p = dma_get_drvdata(dma);

if (p->chan[channel].irq_disabled) {
tracev_event(TRACE_CLASS_DMA, "dw_dma_interrupt_mask(): "
"dma %d channel %d not working in irq mode",
Comment thread
tlauda marked this conversation as resolved.
Resolved
dma->plat_data.id, channel);
return;
}

/* write interrupt clear registers for the channel:
* ClearTfr, ClearBlock, ClearSrcTran, ClearDstTran, ClearErr
*/
dw_write(dma, DW_CLEAR_TFR, 0x1 << channel);
dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);
dw_write(dma, DW_CLEAR_SRC_TRAN, 0x1 << channel);
dw_write(dma, DW_CLEAR_DST_TRAN, 0x1 << channel);
dw_write(dma, DW_CLEAR_ERR, 0x1 << channel);

/* clear platform interrupt */
platform_interrupt_clear(dma_irq(dma, cpu_get_id()), 1 << channel);
}

/* allocate next free DMA channel */
static int dw_dma_channel_get(struct dma *dma, int req_chan)
{
Expand Down Expand Up @@ -381,10 +440,7 @@ static void dw_dma_channel_put_unlocked(struct dma *dma, int channel)
return;
}

/* mask block, transfer and error interrupts for channel */
dw_write(dma, DW_MASK_TFR, INT_MASK(channel));
dw_write(dma, DW_MASK_BLOCK, INT_MASK(channel));
dw_write(dma, DW_MASK_ERR, INT_MASK(channel));
dw_dma_interrupt_mask(dma, channel);

/* free the lli allocated by set_config*/
if (chan->lli) {
Expand Down Expand Up @@ -455,18 +511,7 @@ static int dw_dma_start(struct dma *dma, int channel)
goto out;
}

/* write interrupt clear registers for the channel:
* ClearTfr, ClearBlock, ClearSrcTran, ClearDstTran, ClearErr
*/
dw_write(dma, DW_CLEAR_TFR, 0x1 << channel);
dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);
dw_write(dma, DW_CLEAR_SRC_TRAN, 0x1 << channel);
dw_write(dma, DW_CLEAR_DST_TRAN, 0x1 << channel);
dw_write(dma, DW_CLEAR_ERR, 0x1 << channel);

/* clear platform interrupt */
platform_interrupt_clear(dma_irq(dma, cpu_get_id()),
1 << channel);
dw_dma_interrupt_clear(dma, channel);

#if DW_USE_HW_LLI
/* TODO: Revisit: are we using LLP mode or single transfer ? */
Expand Down Expand Up @@ -599,7 +644,8 @@ static int dw_dma_stop(struct dma *dma, int channel)
trace_dwdma_error("dw-dma: %d channel %d timeout",
dma->plat_data.id, channel);

dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);
if (!chan->irq_disabled)
dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);

chan->status = COMP_STATE_PREPARE;

Expand Down Expand Up @@ -641,7 +687,8 @@ static int dw_dma_stop(struct dma *dma, int channel)
sizeof(struct dw_lli2) * chan->desc_count);
#endif

dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);
if (!chan->irq_disabled)
dw_write(dma, DW_CLEAR_BLOCK, 0x1 << channel);

/* disable interrupt */
dw_dma_interrupt_unregister(dma, channel);
Expand Down Expand Up @@ -739,6 +786,7 @@ static int dw_dma_set_config(struct dma *dma, int channel,

/* default channel config */
chan->direction = config->direction;
chan->irq_disabled = config->irq_disabled;
chan->cfg_lo = DW_CFG_LOW_DEF;
chan->cfg_hi = DW_CFG_HIGH_DEF;

Expand Down Expand Up @@ -786,12 +834,7 @@ static int dw_dma_set_config(struct dma *dma, int channel,
}
}

/* unmask block, transfer and error interrupts
* for channel
*/
dw_write(dma, DW_MASK_TFR, INT_UNMASK(channel));
dw_write(dma, DW_MASK_BLOCK, INT_UNMASK(channel));
dw_write(dma, DW_MASK_ERR, INT_UNMASK(channel));
dw_dma_interrupt_unmask(dma, channel);

chan->ptr_data.buffer_bytes = 0;

Expand Down Expand Up @@ -1328,6 +1371,13 @@ static inline int dw_dma_interrupt_register(struct dma *dma, int channel)

trace_event(TRACE_CLASS_DMA, "dw_dma_interrupt_register()");

if (p->chan[channel].irq_disabled) {
tracev_event(TRACE_CLASS_DMA, "dw_dma_interrupt_register(): "
"dma %d channel %d not working in irq mode",
dma->plat_data.id, channel);
return 0;
}

ret = interrupt_register(irq, IRQ_AUTO_UNMASK, dw_dma_irq_handler,
&p->chan[channel].id);
if (ret < 0) {
Expand All @@ -1341,9 +1391,17 @@ static inline int dw_dma_interrupt_register(struct dma *dma, int channel)

static inline void dw_dma_interrupt_unregister(struct dma *dma, int channel)
{
struct dma_pdata *p = dma_get_drvdata(dma);
uint32_t irq = dma_irq(dma, cpu_get_id()) +
(channel << SOF_IRQ_BIT_SHIFT);

if (p->chan[channel].irq_disabled) {
tracev_event(TRACE_CLASS_DMA, "dw_dma_interrupt_unregister(): "
"dma %d channel %d not working in irq mode",
dma->plat_data.id, channel);
return;
}

interrupt_disable(irq);
interrupt_unregister(irq);
}
Expand Down Expand Up @@ -1427,9 +1485,17 @@ static void dw_dma_irq_handler(void *data)

static inline int dw_dma_interrupt_register(struct dma *dma, int channel)
{
struct dma_pdata *p = dma_get_drvdata(dma);
uint32_t irq = dma_irq(dma, cpu_get_id());
int ret;

if (p->chan[channel].irq_disabled) {
tracev_event(TRACE_CLASS_DMA, "dw_dma_interrupt_register(): "
"dma %d channel %d not working in irq mode",
dma->plat_data.id, channel);
return 0;
}

if (!dma->mask_irq_channels) {
ret = interrupt_register(irq, IRQ_AUTO_UNMASK,
dw_dma_irq_handler, dma);
Expand All @@ -1448,8 +1514,16 @@ static inline int dw_dma_interrupt_register(struct dma *dma, int channel)

static inline void dw_dma_interrupt_unregister(struct dma *dma, int channel)
{
struct dma_pdata *p = dma_get_drvdata(dma);
uint32_t irq = dma_irq(dma, cpu_get_id());

if (p->chan[channel].irq_disabled) {
tracev_event(TRACE_CLASS_DMA, "dw_dma_interrupt_unregister(): "
"dma %d channel %d not working in irq mode",
dma->plat_data.id, channel);
return;
}

dma->mask_irq_channels = dma->mask_irq_channels & ~BIT(channel);

if (!dma->mask_irq_channels) {
Expand Down
6 changes: 6 additions & 0 deletions src/include/sof/audio/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ static inline bool pipeline_is_preload(struct pipeline *p)
return p->preload;
}

/* checks if pipeline is scheduled with timer */
static inline bool pipeline_is_timer_driven(struct pipeline *p)
{
return p->ipc_pipe.timer_delay;
}

/* pipeline creation and destruction */
struct pipeline *pipeline_new(struct sof_ipc_pipe_new *pipe_desc,
struct comp_dev *cd);
Expand Down
1 change: 1 addition & 0 deletions src/include/sof/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ struct dma_sg_config {
uint32_t cyclic; /* circular buffer */
struct dma_sg_elem_array elem_array; /* array of dma_sg elems */
bool scatter;
bool irq_disabled;
};

struct dma_chan_status {
Expand Down
1 change: 1 addition & 0 deletions src/ipc/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ int ipc_get_page_descriptors(struct dma *dmac, uint8_t *page_table,
config.src_width = sizeof(uint32_t);
config.dest_width = sizeof(uint32_t);
config.cyclic = 0;
config.irq_disabled = false;
dma_sg_init(&config.elem_array);

/* set up DMA descriptor */
Expand Down