[Sound-open-firmware] [PATCH] byt: mailbox: fix mailbox size.
4k is correct size.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/include/reef/mailbox.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/include/reef/mailbox.h b/src/include/reef/mailbox.h index 44366e4..9233587 100644 --- a/src/include/reef/mailbox.h +++ b/src/include/reef/mailbox.h @@ -35,8 +35,8 @@ #include <arch/cache.h> #include <stdint.h>
-/* almost 1k should be enough for everyone ..... */ -#define IPC_MAX_MAILBOX_BYTES 0xe80 +/* 4k should be enough for everyone ..... */ +#define IPC_MAX_MAILBOX_BYTES 0x1000
#define mailbox_get_exception_base() \ MAILBOX_EXCEPTION_BASE
Add an XRUN handler into the pipeline to report bag overrun and underrun from component buffers to the host. An XRUN on a component will now cause a IPC XRUN message to each PCM interface source/sink to the component.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/pipeline.c | 116 +++++++++++++++++++++++++++++++++++++- src/include/reef/audio/pipeline.h | 6 ++ src/include/reef/ipc.h | 3 + src/include/uapi/ipc.h | 12 +++- src/ipc/intel-ipc.c | 14 +++++ 5 files changed, 148 insertions(+), 3 deletions(-)
diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index 282bec5..f213dc4 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -183,6 +183,28 @@ static void disconnect_downstream(struct pipeline *p, struct comp_dev *start, spin_unlock(¤t->lock); }
+/* update pipeline state based on cmd */ +static void pipeline_cmd_update(struct pipeline *p, int cmd) +{ + switch (cmd) { + case COMP_CMD_PAUSE: + break; + case COMP_CMD_STOP: + break; + case COMP_CMD_RELEASE: + p->xrun_bytes = 0; + break; + case COMP_CMD_START: + p->xrun_bytes = 0; + break; + case COMP_CMD_SUSPEND: + break; + case COMP_CMD_RESUME: + p->xrun_bytes = 0; + break; + } +} + /* create new pipeline - returns pipeline id or negative error */ struct pipeline *pipeline_new(struct sof_ipc_pipe_new *pipe_desc, struct comp_dev *cd) @@ -311,8 +333,10 @@ static int component_op_downstream(struct op_data *op_data, err = comp_params(current); break; case COMP_OPS_CMD: - /* send command to the component */ + /* send command to the component and update pipeline state */ err = comp_cmd(current, op_data->cmd, op_data->cmd_data); + if (err == 0) + pipeline_cmd_update(current->pipeline, op_data->cmd); break; case COMP_OPS_PREPARE: /* prepare the component */ @@ -383,8 +407,10 @@ static int component_op_upstream(struct op_data *op_data, err = comp_params(current); break; case COMP_OPS_CMD: - /* send command to the component */ + /* send command to the component and update pipeline state */ err = comp_cmd(current, op_data->cmd, op_data->cmd_data); + if (err == 0) + pipeline_cmd_update(current->pipeline, op_data->cmd); break; case COMP_OPS_PREPARE: /* prepare the component */ @@ -818,6 +844,92 @@ void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host, } }
+static void xrun(struct comp_dev *dev, void *data) +{ + struct sof_ipc_stream_posn *posn = data; + + /* get host timestamps */ + platform_host_timestamp(dev, posn); + + /* send XRUN to host */ + ipc_stream_send_xrun(dev, posn); +} + + +/* travel down stream from start and run func for each component of type */ +static void pipeline_for_each_downstream(struct pipeline *p, + enum sof_comp_type type, struct comp_dev *current, + void (*func)(struct comp_dev *, void *), void *data) +{ + struct list_item *clist; + + if (current->comp.type == type) + func(current, data); + + /* 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) + continue; + + /* continue downstream */ + pipeline_for_each_downstream(p, type, buffer->sink, + func, data); + } +} + +/* travel up stream from start and run func for each component of type */ +static void pipeline_for_each_upstream(struct pipeline *p, + enum sof_comp_type type, struct comp_dev *current, + void (*func)(struct comp_dev *, void *), void *data) +{ + struct list_item *clist; + + if (current->comp.type == type) + func(current, data); + + /* travel upstream to sink 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) + continue; + + /* continue downstream */ + pipeline_for_each_upstream(p, type, buffer->source, + func, data); + } +} + +/* + * Send an XRUN to each host for this component. + */ +void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, + int32_t bytes) +{ + struct sof_ipc_stream_posn posn; + + /* dont flood host */ + if (p->xrun_bytes) + return; + + memset(&posn, 0, sizeof(posn)); + p->xrun_bytes = posn.xrun_size = bytes; + posn.xrun_comp_id = dev->comp.id; + + if (dev->params.direction == SOF_IPC_STREAM_PLAYBACK) { + pipeline_for_each_upstream(p, SOF_COMP_HOST, dev, xrun, &posn); + } else { + pipeline_for_each_downstream(p, SOF_COMP_HOST, dev, xrun, &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/pipeline.h b/src/include/reef/audio/pipeline.h index 17e8a34..ad01dfd 100644 --- a/src/include/reef/audio/pipeline.h +++ b/src/include/reef/audio/pipeline.h @@ -57,6 +57,9 @@ struct pipeline { spinlock_t lock; struct sof_ipc_pipe_new ipc_pipe;
+ /* runtime status */ + int32_t xrun_bytes; /* last xrun length */ + /* lists */ struct list_item comp_list; /* list of components */ struct list_item buffer_list; /* list of buffers */ @@ -117,4 +120,7 @@ void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host_dev,
void pipeline_schedule(void *arg);
+/* notify host that we have XRUN */ +void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes); + #endif diff --git a/src/include/reef/ipc.h b/src/include/reef/ipc.h index 253f4f4..3eb94d8 100644 --- a/src/include/reef/ipc.h +++ b/src/include/reef/ipc.h @@ -116,6 +116,9 @@ int ipc_process_msg_queue(void);
int ipc_stream_send_position(struct comp_dev *cdev, struct sof_ipc_stream_posn *posn); +int ipc_stream_send_xrun(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, size_t rx_bytes, void (*cb)(void*, void*), void *cb_data); diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index ddca551..ae212be 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -412,14 +412,17 @@ struct sof_ipc_stream {
struct sof_ipc_stream_posn { struct sof_ipc_reply rhdr; - uint32_t comp_id; + uint32_t comp_id; /* host component ID */ 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 comp_posn; /* comp position in bytes */ uint64_t wallclock; /* audio wall clock */ uint64_t timestamp; /* system time stamp */ + uint32_t xrun_comp_id; /* comp ID of XRUN component */ + int32_t xrun_size; /* XRUN size in bytes */ } __attribute__((packed));
/* @@ -467,6 +470,11 @@ enum sof_comp_type { SOF_COMP_EQ_FIR, };
+/* XRUN action for component */ +#define SOF_XRUN_STOP 1 /* stop stream */ +#define SOF_XRUN_UNDER_ZERO 2 /* send 0s to sink */ +#define SOF_XRUN_OVER_NULL 4 /* send data to NULL */ + /* create new generic component - SOF_IPC_TPLG_COMP_NEW */ struct sof_ipc_comp { struct sof_ipc_hdr hdr; @@ -492,6 +500,7 @@ struct sof_ipc_comp_config { uint32_t periods_source; /* 0 means variable */ uint32_t preload_count; /* how many periods to preload */ enum sof_ipc_frame frame_fmt; + uint32_t xrun_action; } __attribute__((packed));
/* generic host component */ @@ -638,6 +647,7 @@ struct sof_ipc_pipe_new { uint32_t priority; /* priority level 0 (low) to 10 (max) */ uint32_t mips; /* worst case instruction count per period */ uint32_t frames_per_sched; /* output frames of pipeline, 0 is variable */ + uint32_t xrun_limit_usecs; /* report xruns greater than limit */ } __attribute__((packed));
/* pipeline construction complete - SOF_IPC_TPLG_PIPE_COMPLETE */ diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c index 681bf64..db48ef0 100644 --- a/src/ipc/intel-ipc.c +++ b/src/ipc/intel-ipc.c @@ -328,6 +328,20 @@ int ipc_stream_send_position(struct comp_dev *cdev, NULL, 0, NULL, NULL); }
+/* send stream position TODO: send compound message */ +int ipc_stream_send_xrun(struct comp_dev *cdev, + struct sof_ipc_stream_posn *posn) +{ + uint32_t header; + + header = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_TRIG_XRUN; + 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;
Add a simple convenience API to allow components to report XRUNs
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/include/reef/audio/component.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h index a8db2ec..2e76a86 100644 --- a/src/include/reef/audio/component.h +++ b/src/include/reef/audio/component.h @@ -41,6 +41,7 @@ #include <reef/dma.h> #include <reef/stream.h> #include <reef/audio/buffer.h> +#include <reef/audio/pipeline.h> #include <uapi/ipc.h>
/* audio component states @@ -356,4 +357,23 @@ static inline uint32_t comp_frame_bytes(struct comp_dev *dev) } }
+/* XRUN handling */ +static inline void comp_underrun(struct comp_dev *dev, struct comp_buffer *source, + uint32_t copy_bytes) +{ + trace_comp("Xun"); + trace_value((source->avail << 16) | copy_bytes); + + pipeline_xrun(dev->pipeline, dev, (int32_t)source->avail - copy_bytes); +} + +static inline void comp_overrun(struct comp_dev *dev, struct comp_buffer *sink, + uint32_t copy_bytes) +{ + trace_comp("Xov"); + trace_value((sink->free << 16) | copy_bytes); + + pipeline_xrun(dev->pipeline, dev, (int32_t)copy_bytes - sink->free); +} + #endif
Use the new XRUN API to report XRUNs to host and trace.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/volume.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/audio/volume.c b/src/audio/volume.c index c81fd33..925a274 100644 --- a/src/audio/volume.c +++ b/src/audio/volume.c @@ -467,9 +467,12 @@ static int volume_copy(struct comp_dev *dev) copy_bytes = comp_buffer_get_copy_bytes(dev, source, sink);
/* Run volume if buffers have enough room */ - if (copy_bytes < cd->source_period_bytes || - copy_bytes < cd->sink_period_bytes) { - trace_volume_error("xru"); + if (copy_bytes < cd->source_period_bytes) { + comp_underrun(dev, source, cd->source_period_bytes); + return 0; + } + if (copy_bytes < cd->sink_period_bytes) { + comp_overrun(dev, source, cd->sink_period_bytes); return 0; }
Stream params has it's own reply message so use it.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/ipc/intel-ipc.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c index db48ef0..60001c3 100644 --- a/src/ipc/intel-ipc.c +++ b/src/ipc/intel-ipc.c @@ -200,6 +200,7 @@ static int ipc_stream_pcm_params(uint32_t stream) { struct intel_ipc_data *iipc = ipc_get_drvdata(_ipc); struct sof_ipc_pcm_params *pcm_params = _ipc->comp_data; + struct sof_ipc_pcm_params_reply reply; struct ipc_comp_dev *pcm_dev; struct comp_dev *cd; int err; @@ -255,6 +256,13 @@ static int ipc_stream_pcm_params(uint32_t stream) }
+ /* write component values to the outbox */ + reply.rhdr.hdr.size = sizeof(reply); + reply.rhdr.hdr.cmd = stream; + reply.rhdr.error = 0; + reply.comp_id = pcm_params->comp_id; + reply.posn_offset = 0; /* TODO: set this up for mmaped components */ + mailbox_outbox_write(0, &reply, sizeof(reply)); return 0;
error:
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/ipc/ipc.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/src/ipc/ipc.c b/src/ipc/ipc.c index 323468b..e589d56 100644 --- a/src/ipc/ipc.c +++ b/src/ipc/ipc.c @@ -186,7 +186,6 @@ int ipc_comp_connect(struct ipc *ipc, struct sof_ipc_pipe_comp_connect *connect) { struct ipc_comp_dev *icd_source, *icd_sink; - //struct ipc_comp_dev *icd_source_pipe, *icd_sink_pipe;
/* check whether the components already exist */ icd_source = ipc_get_comp(ipc, connect->source_id);
participants (1)
-
Liam Girdwood