[Sound-open-firmware] [PATCH] trace: comp: Make high frequency trace output verbose level
make sure our high frequency component and pipeline trace uses verbose trace level.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/dai.c | 2 +- src/audio/host.c | 4 ++-- src/audio/mixer.c | 2 +- src/audio/pipeline.c | 4 ++-- src/audio/volume.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 518836a..8f41026 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -80,7 +80,7 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) struct comp_buffer *dma_buffer; uint32_t copied_size;
- trace_dai("irq"); + tracev_dai("irq");
if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) { dma_buffer = list_first_item(&dev->bsource_list, diff --git a/src/audio/host.c b/src/audio/host.c index 944edfe..5ac2cf4 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -120,7 +120,7 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) local_elem = list_first_item(&hd->config.elem_list, struct dma_sg_elem, list);
- trace_host("irq"); + tracev_host("irq");
/* update buffer positions */ dma_buffer = hd->dma_buffer; @@ -615,7 +615,7 @@ static int host_copy(struct comp_dev *dev) struct host_data *hd = comp_get_drvdata(dev); struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
- trace_host("cpy"); + tracev_host("cpy");
if (dev->state != COMP_STATE_RUNNING) return 0; diff --git a/src/audio/mixer.c b/src/audio/mixer.c index cc4701f..74c0ffb 100644 --- a/src/audio/mixer.c +++ b/src/audio/mixer.c @@ -203,7 +203,7 @@ static int mixer_copy(struct comp_dev *dev) struct list_item *blist; int32_t i = 0, num_mix_sources = 0;
- trace_mixer("cpy"); + tracev_mixer("cpy");
/* calculate the highest runtime component status between input streams */ list_for_item(blist, &dev->bsource_list) { diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index 5674877..185b4f3 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -716,13 +716,13 @@ static void pipeline_task(void *arg) struct task *task = &p->pipe_task; struct comp_dev *dev = task->sdata;
- trace_pipe("PWs"); + tracev_pipe("PWs");
/* copy data from upstream source enpoints to downstream endpoints */ pipeline_copy_from_upstream(dev, dev); pipeline_copy_to_downstream(dev, dev);
- trace_pipe("PWe"); + tracev_pipe("PWe"); }
/* init pipeline */ diff --git a/src/audio/volume.c b/src/audio/volume.c index d0c3e4a..33ac07d 100644 --- a/src/audio/volume.c +++ b/src/audio/volume.c @@ -483,7 +483,7 @@ static int volume_copy(struct comp_dev *dev) struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev); uint32_t copy_bytes;
- trace_volume("cpy"); + tracev_volume("cpy");
/* volume components will only ever have 1 source and 1 sink buffer */ source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list);
Components will now each have a 64bit position counter that will indicate the processing position in bytes for each component. This can be used by time stamping, trace and debug.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/dai.c | 6 ++++++ src/audio/host.c | 6 ++++-- src/include/reef/audio/component.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 8f41026..f7868cd 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -95,6 +95,7 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) dcache_writeback_region(dma_buffer->r_ptr, dd->period_bytes);
/* update host position(in bytes offset) for drivers */ + dev->position += copied_size; if (dd->dai_pos) { dd->dai_pos_blks += copied_size; *dd->dai_pos = dd->dai_pos_blks + @@ -111,6 +112,8 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) /* recalc available buffer space */ comp_update_buffer_produce(dma_buffer, dd->period_bytes);
+ /* update positions */ + dev->position += dd->period_bytes; if (dd->dai_pos) { dd->dai_pos_blks += dd->period_bytes; *dd->dai_pos = dd->dai_pos_blks + @@ -396,6 +399,8 @@ static int dai_prepare(struct comp_dev *dev)
trace_dai("pre");
+ dev->position = 0; + if (list_is_empty(&dd->config.elem_list)) { trace_dai_error("wdm"); return -EINVAL; @@ -436,6 +441,7 @@ static int dai_reset(struct comp_dev *dev) *dd->dai_pos = 0; dd->dai_pos = NULL; dd->last_bytes = 0; + dev->position = 0;
return 0; } diff --git a/src/audio/host.c b/src/audio/host.c index 5ac2cf4..5cdc4da 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -143,6 +143,7 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next)
/* new local period, update host buffer position blks */ hd->local_pos += local_elem->size; + dev->position += local_elem->size;
/* buffer overlap ? */ if (hd->local_pos >= hd->host_size) @@ -150,6 +151,7 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next)
/* send IPC message to driver if needed */ hd->report_pos += local_elem->size; + hd->posn.host_posn += local_elem->size; if (dev->params.host_period_bytes != 0 && hd->report_pos >= dev->params.host_period_bytes) { hd->report_pos = 0; @@ -486,8 +488,7 @@ static int host_prepare(struct comp_dev *dev) *hd->host_pos = 0; hd->report_pos = 0; hd->split_remaining = 0; - - //dev->preload = PLAT_HOST_PERIODS; + dev->position = 0;
dev->state = COMP_STATE_PREPARE; return 0; @@ -502,6 +503,7 @@ static int host_pointer_reset(struct comp_dev *dev) *hd->host_pos = 0; hd->local_pos = 0; hd->report_pos = 0; + dev->position = 0;
return 0; } diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h index 28ce144..3238e13 100644 --- a/src/include/reef/audio/component.h +++ b/src/include/reef/audio/component.h @@ -159,6 +159,7 @@ struct comp_dev { uint16_t state; /* COMP_STATE_ */ uint16_t is_endpoint; /* component is end point in pipeline */ spinlock_t lock; /* lock for this component */ + uint64_t position; /* component rendering position */ struct pipeline *pipeline; /* pipeline we belong to */
/* common runtime configuration for downstream/upstream */
Add support to add negative error values to IPC replies.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/include/uapi/ipc.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index 8600b29..38397dd 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -63,13 +63,11 @@ #define SOF_IPC_GLB_STREAM_MSG SOF_GLB_TYPE(0x6U) #define SOF_IPC_FW_READY SOF_GLB_TYPE(0x7U) #define SOF_IPC_GLB_DAI_MSG SOF_GLB_TYPE(0x8U) + /* * DSP Command Message Types */
-/* reply - error details in mailbox reply */ -#define SOF_IPC_REPLY_SUCCESS SOF_CMD_TYPE(0x001) -#define SOF_IPC_REPLY_ERROR SOF_CMD_TYPE(0x002)
/* topology */ #define SOF_IPC_TPLG_COMP_NEW SOF_CMD_TYPE(0x000) @@ -140,6 +138,16 @@ struct sof_ipc_hdr { } __attribute__((packed));
/* + * Generic reply message. Some commands override this with their own reply + * types that must include this at start. + */ +struct sof_ipc_reply { + struct sof_ipc_hdr hdr; + int32_t error; /* negative error numbers */ +} __attribute__((packed)); + + +/* * Compound commands - SOF_IPC_GLB_COMPOUND. * * Compound commands are sent to the DSP as a single IPC operation. The @@ -332,7 +340,7 @@ struct sof_ipc_pcm_params {
/* PCM params info reply - SOF_IPC_STREAM_PCM_PARAMS_REPLY */ struct sof_ipc_pcm_params_reply { - struct sof_ipc_hdr hdr; + struct sof_ipc_reply rhdr; uint32_t comp_id; uint32_t posn_offset; } __attribute__((packed)); @@ -353,7 +361,7 @@ struct sof_ipc_stream { } __attribute__((packed));
struct sof_ipc_stream_posn { - struct sof_ipc_hdr hdr; + struct sof_ipc_reply rhdr; uint32_t comp_id; uint32_t host_posn; /* in frames */ uint32_t dai_posn; /* in frames */ @@ -567,7 +575,7 @@ struct sof_ipc_free {
struct sof_ipc_comp_reply { - struct sof_ipc_hdr hdr; + struct sof_ipc_reply rhdr; uint32_t id; uint32_t offset; } __attribute__((packed));
Allow pipeline host and DAI components to be timestamped in a platform specific manner so that host DMA & DAI DMA position alongside any local DSP timestamp can be returned to the host drivers.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/pipeline.c | 103 ++++++++++++++++++++++++- src/include/reef/audio/component.h | 13 ++++ src/include/reef/audio/pipeline.h | 5 ++ src/include/uapi/ipc.h | 29 ++++++- src/platform/baytrail/include/platform/timer.h | 14 ++++ src/platform/baytrail/timer.c | 36 +++++++++ 6 files changed, 196 insertions(+), 4 deletions(-)
diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index 185b4f3..817ff08 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -679,7 +679,7 @@ static int pipeline_copy_to_downstream(struct comp_dev *start, return 0; }
- /* travel downstream to source end point(s) */ + /* travel downstream to sink end point(s) */ list_for_item(clist, ¤t->bsink_list) { struct comp_buffer *buffer;
@@ -702,6 +702,107 @@ static int pipeline_copy_to_downstream(struct comp_dev *start, return err; }
+static int timestamp_downstream(struct comp_dev *start, + struct comp_dev *current, struct sof_ipc_stream_posn *posn) +{ + struct list_item *clist; + int res = 0; + + /* is component a DAI endpoint ? */ + if (current != start) { + + /* go downstream if we are not endpoint */ + if (!current->is_endpoint) + goto downstream; + + if (current->comp.id == SOF_COMP_DAI || + current->comp.id == SOF_COMP_SG_DAI) { + platform_dai_timestamp(current, posn); + return 1; + } + } + + +downstream: + /* travel downstream to sink end point(s) */ + list_for_item(clist, ¤t->bsink_list) { + struct comp_buffer *buffer; + + buffer = container_of(clist, struct comp_buffer, source_list); + + /* dont go downstream if this component is not connected */ + if (!buffer->connected || buffer->sink->state != COMP_STATE_RUNNING) + continue; + + /* continue downstream */ + res = timestamp_downstream(start, buffer->sink, posn); + if (res == 1) + break; + } + + /* return back upstream */ + return res; +} + + +static int timestamp_upstream(struct comp_dev *start, + struct comp_dev *current, struct sof_ipc_stream_posn *posn) +{ + struct list_item *clist; + int res = 0; + + /* is component a DAI endpoint ? */ + if (current != start) { + + /* go downstream if we are not endpoint */ + if (!current->is_endpoint) + goto upstream; + + if (current->comp.id == SOF_COMP_DAI || + current->comp.id == SOF_COMP_SG_DAI) { + platform_dai_timestamp(current, posn); + return 1; + } + } + + +upstream: + /* travel upstream to source end point(s) */ + list_for_item(clist, ¤t->bsource_list) { + struct comp_buffer *buffer; + + buffer = container_of(clist, struct comp_buffer, sink_list); + + /* dont go downstream if this component is not connected */ + if (!buffer->connected || buffer->source->state != COMP_STATE_RUNNING) + continue; + + /* continue downstream */ + res = timestamp_upstream(start, buffer->sink, posn); + if (res == 1) + break; + } + + /* return back upstream */ + return res; +} + +/* + * Get the timestamps for host and first active DAI found. + */ +void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ + platform_host_timestamp(host, posn); + + if (host->params.direction == SOF_IPC_STREAM_PLAYBACK) { + timestamp_downstream(host, host, posn); + } else { + timestamp_upstream(host, host, posn); + } +} + + /* notify pipeline that this component requires buffers emptied/filled */ void pipeline_schedule_copy(struct pipeline *p, struct comp_dev *dev) { diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h index 3238e13..a74395c 100644 --- a/src/include/reef/audio/component.h +++ b/src/include/reef/audio/component.h @@ -139,6 +139,10 @@ struct comp_ops { /* host buffer config */ int (*host_buffer)(struct comp_dev *dev, struct dma_sg_elem *elem, uint32_t host_size); + + /* position */ + int (*position)(struct comp_dev *dev, + struct sof_ipc_stream_posn *posn); };
@@ -264,6 +268,15 @@ static inline int comp_dai_config(struct comp_dev *dev, return 0; }
+/* component rendering position */ +static inline int comp_position(struct comp_dev *dev, + struct sof_ipc_stream_posn *posn) +{ + if (dev->drv->ops.position) + return dev->drv->ops.position(dev, posn); + return 0; +} + /* default base component initialisations */ void sys_comp_dai_init(void); void sys_comp_host_init(void); diff --git a/src/include/reef/audio/pipeline.h b/src/include/reef/audio/pipeline.h index 8e029d8..ca1947a 100644 --- a/src/include/reef/audio/pipeline.h +++ b/src/include/reef/audio/pipeline.h @@ -108,8 +108,13 @@ int init_static_pipeline(struct ipc *ipc); /* pipeline creation */ int init_pipeline(void);
+/* schedule a copy operation for this pipeline */ void pipeline_schedule_copy(struct pipeline *p, struct comp_dev *dev);
+/* get time pipeline timestamps from host to dai */ +void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host_dev, + struct sof_ipc_stream_posn *posn); + void pipeline_schedule(void *arg);
#endif diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index 38397dd..19ee898 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -360,12 +360,35 @@ struct sof_ipc_stream { uint32_t comp_id; } __attribute__((packed));
+ +/* flags indicating which time stamps are in sync with each other */ +#define SOF_TIME_HOST_SYNC (1 << 0) +#define SOF_TIME_DAI_SYNC (1 << 1) +#define SOF_TIME_WALL_SYNC (1 << 2) +#define SOF_TIME_STAMP_SYNC (1 << 3) + +/* flags indicating which time stamps are valid */ +#define SOF_TIME_HOST_VALID (1 << 8) +#define SOF_TIME_DAI_VALID (1 << 9) +#define SOF_TIME_WALL_VALID (1 << 10) +#define SOF_TIME_STAMP_VALID (1 << 11) + +/* flags indicating time stamps are 64bit else 3use low 32bit */ +#define SOF_TIME_HOST_64 (1 << 16) +#define SOF_TIME_DAI_64 (1 << 17) +#define SOF_TIME_WALL_64 (1 << 18) +#define SOF_TIME_STAMP_64 (1 << 19) + struct sof_ipc_stream_posn { struct sof_ipc_reply rhdr; uint32_t comp_id; - uint32_t host_posn; /* in frames */ - uint32_t dai_posn; /* in frames */ - uint64_t timestamp; + uint32_t flags; /* SOF_TIME_ */ + uint32_t wallclock_hz; /* frequency of wallclock in Hz */ + uint32_t timestamp_ns; /* resolution of timestamp in ns */ + uint64_t host_posn; /* host DMA position in bytes */ + uint64_t dai_posn; /* DAI DMA position in bytes */ + uint64_t wallclock; /* audio wall clock */ + uint64_t timestamp; /* system time stamp */ } __attribute__((packed));
/* diff --git a/src/platform/baytrail/include/platform/timer.h b/src/platform/baytrail/include/platform/timer.h index 0534958..309828c 100644 --- a/src/platform/baytrail/include/platform/timer.h +++ b/src/platform/baytrail/include/platform/timer.h @@ -46,10 +46,24 @@
#define TIMER_AUDIO TIMER3
+struct comp_dev; +struct sof_ipc_stream_posn; + void platform_timer_set(struct timer *timer, uint32_t ticks); void platform_timer_clear(struct timer *timer); uint32_t platform_timer_get(struct timer *timer); void platform_timer_start(struct timer *timer); void platform_timer_stop(struct timer *timer);
+/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn); + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn); + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock); + #endif diff --git a/src/platform/baytrail/timer.c b/src/platform/baytrail/timer.c index 4bcabc9..3d08f6f 100644 --- a/src/platform/baytrail/timer.c +++ b/src/platform/baytrail/timer.c @@ -33,6 +33,7 @@ #include <platform/timer.h> #include <platform/shim.h> #include <reef/debug.h> +#include <reef/audio/component.h> #include <stdint.h>
void platform_timer_start(struct timer *timer) @@ -71,3 +72,38 @@ uint32_t platform_timer_get(struct timer *timer) { return shim_read(SHIM_EXT_TIMER_STAT); } + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get host postion */ + err = comp_position(host, posn); + if (err == 0) + posn->flags |= SOF_TIME_HOST_VALID; +} + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get DAI postion */ + err = comp_position(dai, posn); + if (err == 0) + posn->flags |= SOF_TIME_DAI_VALID; + + /* get SSP wallclock - DAI sets this to stream start value */ + posn->wallclock = shim_read(SHIM_EXT_TIMER_STAT) - posn->wallclock; + posn->flags |= SOF_TIME_WALL_VALID; +} + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + /* only 1 wallclock on BYT */ + *wallclock = shim_read(SHIM_EXT_TIMER_STAT); +}
Allow the IPC to send and receive pipeline position and timestamp data.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/dai.c | 20 ++++++++++++++++++ src/audio/host.c | 22 +++++++++++++++++++- src/include/reef/ipc.h | 2 +- src/ipc/intel-ipc.c | 56 ++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 87 insertions(+), 13 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index f7868cd..4464398 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -68,6 +68,7 @@ struct dai_data { uint32_t dai_pos_blks; /* position in bytes (nearest block) */
volatile uint64_t *dai_pos; /* host can read back this value without IPC */ + uint64_t wallclock; /* wall clock at stream start */ };
static int dai_cmd(struct comp_dev *dev, int cmd, void *data); @@ -485,6 +486,9 @@ static int dai_cmd(struct comp_dev *dev, int cmd, void *data) if (dev->state == COMP_STATE_PAUSED) { dai_trigger(dd->dai, cmd, dev->params.direction); dma_release(dd->dma, dd->chan); + + /* update starting wallclock */ + platform_dai_wallclock(dev, &dd->wallclock); dev->state = COMP_STATE_RUNNING; } break; @@ -495,6 +499,9 @@ static int dai_cmd(struct comp_dev *dev, int cmd, void *data) if (ret < 0) return ret; dai_trigger(dd->dai, cmd, dev->params.direction); + + /* update starting wallclock */ + platform_dai_wallclock(dev, &dd->wallclock); dev->state = COMP_STATE_RUNNING; } break; @@ -525,6 +532,18 @@ static int dai_preload(struct comp_dev *dev) return 0; }
+static int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + /* TODO: improve accuracy by adding current DMA position */ + posn->dai_posn = dev->position; + + /* set stream start wallclock */ + posn->wallclock = dd->wallclock; + return 0; +} + static int dai_config(struct comp_dev *dev, struct dai_config *dai_config) { struct dai_data *dd = comp_get_drvdata(dev); @@ -562,6 +581,7 @@ static struct comp_driver comp_dai = { .reset = dai_reset, .dai_config = dai_config, .preload = dai_preload, + .position = dai_position, }, };
diff --git a/src/audio/host.c b/src/audio/host.c index 5cdc4da..27b5418 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -152,14 +152,19 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) /* send IPC message to driver if needed */ hd->report_pos += local_elem->size; hd->posn.host_posn += local_elem->size; + + /* NO_IRQ mode if host_period_size == 0 */ if (dev->params.host_period_bytes != 0 && hd->report_pos >= dev->params.host_period_bytes) { hd->report_pos = 0; /* update for host side */ if (hd->host_pos) { *hd->host_pos = hd->local_pos; - ipc_stream_send_notification(dev, &hd->posn); } + + /* send timestamps to host */ + pipeline_get_timestamp(dev->pipeline, dev, &hd->posn); + ipc_stream_send_position(dev, &hd->posn); }
/* update src and dest positions and check for overflow */ @@ -271,6 +276,9 @@ static struct comp_dev *host_new(struct sof_ipc_comp *comp) /* set up callback */ dma_set_cb(hd->dma, hd->chan, DMA_IRQ_TYPE_LLIST, host_dma_cb, dev);
+ /* init posn data. TODO: other fields */ + hd->posn.comp_id = comp->id; + return dev;
error: @@ -523,6 +531,17 @@ static int host_stop(struct comp_dev *dev) return 0; }
+static int host_position(struct comp_dev *dev, + struct sof_ipc_stream_posn *posn) +{ + struct host_data *hd = comp_get_drvdata(dev); + + /* TODO: improve accuracy by adding current DMA position */ + posn->host_posn = hd->local_pos; + + return 0; +} + /* used to pass standard and bespoke commands (with data) to component */ static int host_cmd(struct comp_dev *dev, int cmd, void *data) { @@ -641,6 +660,7 @@ struct comp_driver comp_host = { .prepare = host_prepare, .preload = host_preload, .host_buffer = host_buffer, + .position = host_position, }, };
diff --git a/src/include/reef/ipc.h b/src/include/reef/ipc.h index 92a6f6e..96f2924 100644 --- a/src/include/reef/ipc.h +++ b/src/include/reef/ipc.h @@ -114,7 +114,7 @@ void ipc_free(struct ipc *ipc);
int ipc_process_msg_queue(void);
-int ipc_stream_send_notification(struct comp_dev *cdev, +int ipc_stream_send_position(struct comp_dev *cdev, struct sof_ipc_stream_posn *posn); int ipc_queue_host_message(struct ipc *ipc, uint32_t header, void *tx_data, size_t tx_bytes, void *rx_data, diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c index d122b30..dbb0db1 100644 --- a/src/ipc/intel-ipc.c +++ b/src/ipc/intel-ipc.c @@ -274,9 +274,52 @@ static int ipc_stream_pcm_free(uint32_t header)
/* reset the pipeline */ pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); + +/* get stream position */ +static int ipc_stream_position(uint32_t header) +{ + struct sof_ipc_stream *stream = _ipc->comp_data; + struct sof_ipc_stream_posn posn; + struct ipc_comp_dev *pcm_dev; + + trace_ipc("pos"); + + memset(&posn, 0, sizeof(posn)); + + /* get the pcm_dev */ + pcm_dev = ipc_get_comp(_ipc, stream->comp_id); + if (pcm_dev == NULL) { + trace_ipc_error("epo"); + return -ENODEV; + } + + /* set message fields - TODO; get others */ + posn.rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION; + posn.rhdr.hdr.size = sizeof(posn); + posn.comp_id = stream->comp_id; + + /* get the stream positions and timestamps */ + pipeline_get_timestamp(pcm_dev->cd->pipeline, pcm_dev->cd, &posn); + + /* copy positions to outbox */ + mailbox_outbox_write(0, &posn, sizeof(posn)); return 0; }
+/* send stream position */ +int ipc_stream_send_position(struct comp_dev *cdev, + struct sof_ipc_stream_posn *posn) +{ + uint32_t header; + + header = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION; + posn->rhdr.hdr.cmd = header; + posn->rhdr.hdr.size = sizeof(*posn); + + return ipc_queue_host_message(_ipc, header, posn, sizeof(*posn), + NULL, 0, NULL, NULL); +} + static int ipc_stream_trigger(uint32_t header) { struct ipc_comp_dev *pcm_dev; @@ -343,6 +386,8 @@ static int ipc_glb_stream_message(uint32_t header) case iCS(SOF_IPC_STREAM_TRIG_DRAIN): case iCS(SOF_IPC_STREAM_TRIG_XRUN): return ipc_stream_trigger(header); + case iCS(SOF_IPC_STREAM_POSITION): + return ipc_stream_position(header); default: return -EINVAL; } @@ -712,17 +757,6 @@ static inline struct ipc_msg *msg_get_empty(struct ipc *ipc) return msg; }
-/* Send stream command */ -int ipc_stream_send_notification(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn) -{ - uint32_t header; - - header = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION; -trace_value(header); - return ipc_queue_host_message(_ipc, header, posn, sizeof(*posn), - NULL, 0, NULL, NULL); -}
int ipc_queue_host_message(struct ipc *ipc, uint32_t header, void *tx_data, size_t tx_bytes, void *rx_data,
Improve IPC error reporting and values to host by tracing all failures and making sure errors are returned when detected.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/ipc/byt-ipc.c | 37 ++++++++++++++++++++++++++++--------- src/ipc/intel-ipc.c | 45 ++++++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 26 deletions(-)
diff --git a/src/ipc/byt-ipc.c b/src/ipc/byt-ipc.c index b73ad05..4fd5d62 100644 --- a/src/ipc/byt-ipc.c +++ b/src/ipc/byt-ipc.c @@ -78,6 +78,7 @@ static void do_notify(void)
out: spin_unlock_irq(&_ipc->lock, flags); + /* clear DONE bit - tell Host we have completed */ shim_write(SHIM_IPCDH, shim_read(SHIM_IPCDH) & ~SHIM_IPCDH_DONE);
@@ -121,30 +122,48 @@ static void irq_handler(void *arg) void ipc_platform_do_cmd(struct ipc *ipc) { struct intel_ipc_data *iipc = ipc_get_drvdata(ipc); - uint32_t ipcxh;//, status; + struct sof_ipc_reply reply; + uint32_t ipcxh; + int32_t err;
trace_ipc("Cmd"); - //trace_value(_ipc->host_msg);
- /* TODO: handle error with reply data in mailbox */ - ipc_cmd(); + /* clear old mailbox return values */ + reply.hdr.cmd = SOF_IPC_GLB_REPLY; + reply.hdr.size = sizeof(reply); + reply.error = 0; + mailbox_outbox_write(0, &reply, sizeof(reply)); + + /* perform command and return any error */ + err = ipc_cmd(); + if (err < 0) { + /* read component values from the inbox */ + reply.error = err; + + /* write error back to outbox */ + mailbox_outbox_write(0, &reply, sizeof(reply)); + } ipc->host_pending = 0; - trace_ipc("CmD"); + /* clear BUSY bit and set DONE bit - accept new messages */ ipcxh = shim_read(SHIM_IPCXH); ipcxh &= ~SHIM_IPCXH_BUSY; - ipcxh |= SHIM_IPCXH_DONE;// | status; + ipcxh |= SHIM_IPCXH_DONE; shim_write(SHIM_IPCXH, ipcxh);
+ /* unmask busy interrupt */ + shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_BUSY); + // TODO: signal audio work to enter D3 in normal context /* are we about to enter D3 ? */ if (iipc->pm_prepare_D3) { - while (1) + while (1) { + trace_ipc("pme"); wait_for_interrupt(0); + } }
- /* unmask busy interrupt */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_BUSY); + trace_ipc("CmD"); }
void ipc_platform_send_msg(struct ipc *ipc) diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c index dbb0db1..2d73fbb 100644 --- a/src/ipc/intel-ipc.c +++ b/src/ipc/intel-ipc.c @@ -255,7 +255,9 @@ static int ipc_stream_pcm_params(uint32_t stream) return 0;
error: - pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); + err = pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); + if (err < 0) + trace_ipc_error("eA!"); return -EINVAL; }
@@ -269,11 +271,14 @@ static int ipc_stream_pcm_free(uint32_t header)
/* get the pcm_dev */ pcm_dev = ipc_get_comp(_ipc, free_req->comp_id); - if (pcm_dev == NULL) - return ENODEV; + if (pcm_dev == NULL) { + trace_ipc_error("eFr"); + return -ENODEV; + }
/* reset the pipeline */ - pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); + return pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); +}
/* get stream position */ static int ipc_stream_position(uint32_t header) @@ -326,7 +331,7 @@ static int ipc_stream_trigger(uint32_t header) uint32_t cmd = COMP_CMD_RELEASE; struct sof_ipc_stream *stream = _ipc->comp_data; uint32_t ipc_cmd = (header & SOF_CMD_TYPE_MASK) >> SOF_CMD_TYPE_SHIFT; - int err; + int ret;
trace_ipc("tri");
@@ -334,7 +339,7 @@ static int ipc_stream_trigger(uint32_t header) pcm_dev = ipc_get_comp(_ipc, stream->comp_id); if (pcm_dev == NULL) { trace_ipc_error("eRg"); - goto error; + return -ENODEV; }
switch (ipc_cmd) { @@ -359,15 +364,13 @@ static int ipc_stream_trigger(uint32_t header) }
/* trigger the component */ - err = pipeline_cmd(pcm_dev->cd->pipeline, pcm_dev->cd, + ret = pipeline_cmd(pcm_dev->cd->pipeline, pcm_dev->cd, cmd, NULL); - if (err < 0) { + if (ret < 0) { trace_ipc_error("eRc"); - goto error; }
-error: - return 0; + return ret; }
static int ipc_glb_stream_message(uint32_t header) @@ -532,7 +535,7 @@ static int ipc_glb_pm_message(uint32_t header) case iCS(SOF_IPC_PM_CLK_GET): case iCS(SOF_IPC_PM_CLK_REQ): default: - return -ENOMEM; + return -EINVAL; } }
@@ -545,12 +548,14 @@ static int ipc_comp_set_value(uint32_t header, uint32_t cmd) struct ipc_comp_dev *stream_dev; struct sof_ipc_ctrl_values *values = _ipc->comp_data;
- //trace_ipc("VoS"); + trace_ipc("VoS");
/* get the component */ stream_dev = ipc_get_comp(_ipc, values->comp_id); - if (stream_dev == NULL) + if (stream_dev == NULL) { + trace_ipc_error("eVs"); return -ENODEV; + }
/* set component values */ return comp_cmd(stream_dev->cd, cmd, values); @@ -566,13 +571,17 @@ static int ipc_comp_get_value(uint32_t header, uint32_t cmd)
/* get the component */ stream_dev = ipc_get_comp(_ipc, values->comp_id); - if (stream_dev == NULL) + if (stream_dev == NULL){ + trace_ipc_error("eVg"); return -ENODEV; + } /* get component values */ ret = comp_cmd(stream_dev->cd, COMP_CMD_VOLUME, values); - if (ret < 0) + if (ret < 0) { + trace_ipc_error("eVG"); return ret; + }
/* write component values to the outbox */ mailbox_outbox_write(values, 0, sizeof(*values)); @@ -618,8 +627,10 @@ static int ipc_glb_tplg_comp_new(uint32_t header)
/* register component */ ret = ipc_comp_new(_ipc, comp); - if (ret < 0) + if (ret < 0) { + trace_ipc_error("etc"); return ret; + }
/* write component values to the outbox */ mailbox_outbox_write(0, &reply, sizeof(reply));
participants (1)
-
Liam Girdwood