Skip to content
Merged
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
111 changes: 68 additions & 43 deletions src/audio/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ struct host_data {

static int host_stop(struct comp_dev *dev);
static int host_copy(struct comp_dev *dev);

#if !CONFIG_DMA_GW
static int host_copy_one_shot(struct comp_dev *dev);

static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc)
{
Expand Down Expand Up @@ -235,7 +235,8 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next)
#endif
}

static int create_local_elems(struct comp_dev *dev)
static int create_local_elems(struct comp_dev *dev, uint32_t buffer_count,
uint32_t buffer_bytes)
{
struct host_data *hd = comp_get_drvdata(dev);
struct dma_sg_elem_array *elem_array;
Expand All @@ -249,9 +250,8 @@ static int create_local_elems(struct comp_dev *dev)
err = dma_sg_alloc(elem_array, RZONE_RUNTIME,
dev->params.direction == SOF_IPC_STREAM_PLAYBACK ?
DMA_DIR_HMEM_TO_LMEM : DMA_DIR_LMEM_TO_HMEM,
hd->period_count,
hd->period_bytes, (uintptr_t)(hd->dma_buffer->addr),
0);
buffer_count, buffer_bytes,
(uintptr_t)(hd->dma_buffer->addr), 0);

if (err < 0) {
trace_host_error("create_local_elems() error: "
Expand Down Expand Up @@ -319,7 +319,7 @@ static int host_trigger(struct comp_dev *dev, int cmd)
#else
/* preload first playback period for preloader task */
if (pipeline_is_preload(dev->pipeline))
ret = host_copy(dev);
ret = host_copy_one_shot(dev);
#endif
break;
default:
Expand Down Expand Up @@ -440,15 +440,15 @@ static int host_elements_reset(struct comp_dev *dev)
/* local element */
local_elem = hd->config.elem_array.elems;
local_elem->dest = sink_elem->dest;
local_elem->size = hd->period_bytes;
local_elem->size = dev->params.direction == SOF_IPC_STREAM_PLAYBACK ?
sink_elem->size : source_elem->size;
local_elem->src = source_elem->src;
hd->next_inc = hd->period_bytes;

return 0;
}
#endif

#if defined CONFIG_DMA_GW
static void host_buffer_cb(void *data, uint32_t bytes)
{
struct comp_dev *dev = (struct comp_dev *)data;
Expand All @@ -475,12 +475,18 @@ static void host_buffer_cb(void *data, uint32_t bytes)

tracev_host("host_buffer_cb(), copy_bytes = 0x%x", copy_bytes);

#if CONFIG_DMA_GW
ret = dma_copy(hd->dma, hd->chan, copy_bytes, 0);
if (ret < 0)
trace_host_error("host_buffer_cb() error: dma_copy() failed, "
"ret = %u", ret);
}
#else
ret = host_copy_one_shot(dev);
if (ret < 0)
trace_host_error("host_buffer_cb() error: host_copy_one_shot()"
" failed, ret = %u", ret);
#endif
}

/* configure the DMA params and descriptors for host buffer IO */
static int host_params(struct comp_dev *dev)
Expand All @@ -489,6 +495,8 @@ static int host_params(struct comp_dev *dev)
struct sof_ipc_comp_config *cconfig = COMP_GET_CONFIG(dev);
struct dma_sg_config *config = &hd->config;
uint32_t buffer_size;
uint32_t buffer_count;
uint32_t buffer_single_size;
int err;

trace_event(TRACE_CLASS_HOST, "host_params()");
Expand All @@ -498,37 +506,43 @@ static int host_params(struct comp_dev *dev)

/* determine source and sink buffer elems */
if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) {
#if !CONFIG_DMA_GW
hd->source = &hd->host;
hd->sink = &hd->local;
#endif
hd->dma_buffer = list_first_item(&dev->bsink_list,
struct comp_buffer, source_list);

#if defined CONFIG_DMA_GW
/* set callback on buffer consume */
buffer_set_cb(hd->dma_buffer, &host_buffer_cb, dev,
BUFF_CB_TYPE_CONSUME);
#endif

config->direction = DMA_DIR_HMEM_TO_LMEM;
hd->period_count = cconfig->periods_sink;
} else {
#if !CONFIG_DMA_GW
hd->source = &hd->local;
hd->sink = &hd->host;
#if CONFIG_DMA_GW
buffer_count = hd->period_count;
buffer_single_size = dev->frames * comp_frame_bytes(dev);
#else
buffer_count = 1;
buffer_single_size = hd->period_count * dev->frames *
comp_frame_bytes(dev);

hd->source = &hd->host;
hd->sink = &hd->local;
#endif
} else {
hd->dma_buffer = list_first_item(&dev->bsource_list,
struct comp_buffer, sink_list);

#if defined CONFIG_DMA_GW
/* set callback on buffer produce */
buffer_set_cb(hd->dma_buffer, &host_buffer_cb, dev,
BUFF_CB_TYPE_PRODUCE);
#endif

config->direction = DMA_DIR_LMEM_TO_HMEM;
hd->period_count = cconfig->periods_source;
buffer_count = hd->period_count;
buffer_single_size = dev->frames * comp_frame_bytes(dev);

#if !CONFIG_DMA_GW
hd->source = &hd->local;
hd->sink = &hd->host;
#endif
}

/* validate period count */
Expand Down Expand Up @@ -566,7 +580,7 @@ static int host_params(struct comp_dev *dev)
#endif

/* create SG DMA elems for local DMA buffer */
err = create_local_elems(dev);
err = create_local_elems(dev, buffer_count, buffer_single_size);
if (err < 0)
return err;

Expand Down Expand Up @@ -710,6 +724,24 @@ static int host_reset(struct comp_dev *dev)
return 0;
}

#if !CONFIG_DMA_GW
/* perform one shot copy from source to sink buffers */
static int host_copy_one_shot(struct comp_dev *dev)
{
struct host_data *hd = comp_get_drvdata(dev);
int ret;

/* do DMA transfer */
ret = dma_set_config(hd->dma, hd->chan, &hd->config);
if (ret < 0)
return ret;

ret = dma_start(hd->dma, hd->chan);

return ret;
}
#endif

/* copy and process stream data from source to sink buffers */
static int host_copy(struct comp_dev *dev)
{
Expand Down Expand Up @@ -739,34 +771,27 @@ static int host_copy(struct comp_dev *dev)
}
}

/* TODO: this could be run-time if() based on the same attribute
* as in the host_trigger().
*/
/* TODO: this could be run-time if() based on the same attribute
* as in the host_trigger().
*/
#if CONFIG_DMA_GW
/* here only do preload, further copies happen
* in host_buffer_cb()
*/
if (pipeline_is_preload(dev->pipeline)) {
ret = dma_copy(hd->dma, hd->chan, hd->period_bytes, DMA_COPY_PRELOAD);
if (ret < 0)
goto out;
ret = dma_copy(hd->dma, hd->chan, hd->period_bytes,
DMA_COPY_PRELOAD);
if (ret < 0) {
trace_host_error("host_copy() error: dma_copy() "
"failed, ret = %u", ret);
return ret;
}
}

/* note: update() moved to callback */
#else
/* do DMA transfer */
ret = dma_set_config(hd->dma, hd->chan, &hd->config);
if (ret < 0)
goto out;
ret = dma_start(hd->dma, hd->chan);
if (ret < 0)
goto out;
#endif
return 0;
out:
trace_host_error("host_copy() error: "
"dma_set_config() or dma_start() failed, ret = %u",
ret);
/* For !CONFIG_DMA_GW preload happens in host_trigger() and
* further copies happen in host_buffer_cb()
*/

return ret;
}

Expand Down