Skip to content
Closed
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
9 changes: 9 additions & 0 deletions src/audio/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,9 +683,18 @@ static int dai_reset(struct comp_dev *dev)
{
struct dai_data *dd = comp_get_drvdata(dev);
struct dma_sg_config *config = &dd->config;
int ret;

comp_info(dev, "dai_reset()");

if (dd->chan) {
ret = dma_reset(dd->chan);
if (ret < 0) {
comp_err(dev, "dai_reset(): failed to reset DMA chan");
return ret;
}
}

dai_config_reset(dev);

dma_sg_free(&config->elem_array);
Expand Down
7 changes: 7 additions & 0 deletions src/audio/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,13 @@ static int host_reset(struct comp_dev *dev)
comp_dbg(dev, "host_reset()");

if (hd->chan) {
int ret = dma_reset(hd->chan);

if (ret < 0) {
comp_err(dev, "host_reset(): failed to reset DMA chan");
return ret;
}

/* remove callback */
notifier_unregister(dev, hd->chan, NOTIFIER_ID_DMA_COPY);
dma_channel_put(hd->chan);
Expand Down
36 changes: 29 additions & 7 deletions src/drivers/intel/hda/hda-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ DECLARE_TR_CTX(hdma_tr, SOF_UUID(hda_dma_uuid), LOG_LEVEL_INFO);
#define DGCS_SCS BIT(31)
#define DGCS_GEN BIT(26)
#define DGCS_FWCB BIT(23)
#define DGCS_GBUSY BIT(15)
#define DGCS_BSC BIT(11)
/* NOTE: both XRUN bits are the same, just direction is different */
#define DGCS_BOR BIT(10) /* buffer overrun (input streams) */
Expand Down Expand Up @@ -522,7 +523,6 @@ static void hda_dma_channel_put(struct dma_chan_data *channel)
static int hda_dma_start(struct dma_chan_data *channel)
{
uint32_t flags;
uint32_t dgcs;
int ret = 0;

irq_local_disable(flags);
Expand All @@ -532,13 +532,12 @@ static int hda_dma_start(struct dma_chan_data *channel)

hda_dma_dbg_count_reset(channel);

/* is channel idle, disabled and ready ? */
dgcs = dma_chan_reg_read(channel, DGCS);
if (channel->status != COMP_STATE_PREPARE || (dgcs & DGCS_GEN)) {
/* is channel active? */
if (channel->status != COMP_STATE_PREPARE) {
ret = -EBUSY;
tr_err(&hdma_tr, "hda-dmac: %d channel %d busy. dgcs 0x%x status %d",
tr_err(&hdma_tr, "hda-dmac: %d channel %d status %d",
channel->dma->plat_data.id,
channel->index, dgcs, channel->status);
channel->index, channel->status);
goto out;
}

Expand Down Expand Up @@ -618,7 +617,7 @@ static int hda_dma_stop(struct dma_chan_data *channel)
hda_dma_host_stop(channel);

/* disable the channel */
dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN | DGCS_FIFORDY, 0);
dma_chan_reg_update_bits(channel, DGCS, DGCS_FIFORDY, 0);
channel->status = COMP_STATE_PREPARE;
hda_chan = dma_chan_get_data(channel);
hda_chan->state = 0;
Expand All @@ -630,6 +629,28 @@ static int hda_dma_stop(struct dma_chan_data *channel)
return 0;
}

static int hda_dma_reset(struct dma_chan_data *channel)
{
uint32_t val, flags;

irq_local_disable(flags);

/* reset GEN bit */
dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN, 0);

val = dma_chan_reg_read(channel, DGCS);

irq_local_enable(flags);

/* and verify if channel is idle */
if (!(val & DGCS_GBUSY))
Copy link
Contributor

@keyonjie keyonjie Sep 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need some timeout check here to wait for the flushing finish?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@keyonjie I checked this in the cavs fw and they do not have a wait before checking for GBUSY

return 0;

tr_err(&hdma_tr, "hda-dmac: %d channel %d busy", channel->dma->plat_data.id,
channel->index);
return -EBUSY;
}

/* fill in "status" with current DMA channel state and position */
static int hda_dma_status(struct dma_chan_data *channel,
struct dma_chan_status *status, uint8_t direction)
Expand Down Expand Up @@ -1004,6 +1025,7 @@ const struct dma_ops hda_link_dma_ops = {
.channel_put = hda_dma_channel_put,
.start = hda_dma_start,
.stop = hda_dma_stop,
.reset = hda_dma_reset,
.copy = hda_dma_link_copy,
.pause = hda_dma_pause,
.release = hda_dma_release,
Expand Down
9 changes: 9 additions & 0 deletions src/include/sof/lib/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ struct dma_ops {

int (*start)(struct dma_chan_data *channel);
int (*stop)(struct dma_chan_data *channel);
int (*reset)(struct dma_chan_data *channel);
int (*copy)(struct dma_chan_data *channel, int bytes, uint32_t flags);
int (*pause)(struct dma_chan_data *channel);
int (*release)(struct dma_chan_data *channel);
Expand Down Expand Up @@ -318,6 +319,14 @@ static inline int dma_stop(struct dma_chan_data *channel)
return ret;
}

static inline int dma_reset(struct dma_chan_data *channel)
{
if (channel->dma->ops->reset)
return channel->dma->ops->reset(channel);

return 0;
}

/** \defgroup sof_dma_copy_func static int dma_copy (struct dma_chan_data * channel, int bytes, uint32_t flags)
*
* This function is in a separate subgroup to solve a name clash with
Expand Down
1 change: 1 addition & 0 deletions src/include/sof/trace/dma-trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ int dma_trace_host_buffer(struct dma_trace_data *d,
struct dma_sg_elem_array *elem_array,
uint32_t host_size);
int dma_trace_enable(struct dma_trace_data *d);
void dma_trace_disable(struct dma_trace_data *d);
void dma_trace_flush(void *destination);
void dma_trace_on(void);
void dma_trace_off(void);
Expand Down
5 changes: 5 additions & 0 deletions src/ipc/ipc3/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,11 @@ static int ipc_pm_context_save(uint32_t header)
//struct sof_ipc_pm_ctx *pm_ctx = _ipc->comp_data;

tr_info(&ipc_tr, "ipc: pm -> save");
#if CONFIG_TRACE
struct dma_trace_data *dmat = dma_trace_data_get();

dma_trace_disable(dmat);
#endif

sa_exit(sof_get());

Expand Down
6 changes: 3 additions & 3 deletions src/trace/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@ config TRACEM
config TRACE_FILTERING
bool "Trace filtering"
depends on TRACE
default y
default n
help
Filtering of trace messages based on their verbosity level and frequency.

config TRACE_FILTERING_VERBOSITY
bool "Filter by verbosity"
depends on TRACE_FILTERING
default y
default n
help
Filtering by log verbosity level, where maximum verbosity allowed is specified for each
context and may be adjusted in runtime.

config TRACE_FILTERING_ADAPTIVE
bool "Adaptive rate limiting"
depends on TRACE_FILTERING
default y
default n
help
Adaptive filtering of trace messages, tracking up to CONFIG_TRACE_RECENT_ENTRIES_COUNT,
suppressing all repeated messages for up to CONFIG_TRACE_RECENT_TIME_THRESHOLD cycles.
Expand Down
7 changes: 7 additions & 0 deletions src/trace/dma-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,13 @@ int dma_trace_enable(struct dma_trace_data *d)
return err;
}

void dma_trace_disable(struct dma_trace_data *d)
{
schedule_task_cancel(&d->dmat_work);
dma_reset(d->dc.chan);
dma_trace_buffer_free(d);
}

/** Sends all pending DMA messages to mailbox (for emergencies) */
void dma_trace_flush(void *t)
{
Expand Down