diff --git a/src/include/reef/audio/pipeline.h b/src/include/reef/audio/pipeline.h index 08a3f3065..dca9413b4 100644 --- a/src/include/reef/audio/pipeline.h +++ b/src/include/reef/audio/pipeline.h @@ -69,6 +69,9 @@ struct pipeline { struct task pipe_task; /* pipeline processing task */ struct comp_dev *sched_comp; /* component that drives scheduling in this pipe */ struct comp_dev *source_comp; /* source component for this pipe */ + + /* position update */ + uint32_t posn_offset; /* position update array offset*/ }; /* static pipeline */ diff --git a/src/include/reef/ipc.h b/src/include/reef/ipc.h index 9261addc7..58d1f299d 100644 --- a/src/include/reef/ipc.h +++ b/src/include/reef/ipc.h @@ -103,6 +103,9 @@ struct ipc { /* DMA for Trace*/ struct dma_trace_data *dmat; + /* mmap for posn_offset */ + struct pipeline *posn_map[PLATFORM_MAX_STREAMS]; + void *private; }; @@ -169,4 +172,6 @@ int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config); /* send DMA trace host buffer position to host */ int ipc_dma_trace_send_position(void); +/* get posn offset by pipeline. */ +int ipc_get_posn_offset(struct ipc *ipc, struct pipeline *pipe); #endif diff --git a/src/include/reef/mailbox.h b/src/include/reef/mailbox.h index c0580a9d3..f13454811 100644 --- a/src/include/reef/mailbox.h +++ b/src/include/reef/mailbox.h @@ -78,4 +78,11 @@ dcache_invalidate_region((void*)(MAILBOX_HOSTBOX_BASE + src), bytes); \ rmemcpy(dest, (void*)(MAILBOX_HOSTBOX_BASE + src), bytes); +#define mailbox_stream_write(dest, src, bytes) \ + do { \ + rmemcpy((void *)(MAILBOX_STREAM_BASE + dest), src, bytes); \ + dcache_writeback_region((void *)(MAILBOX_STREAM_BASE + dest), \ + bytes); \ + } while (0) + #endif diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c index feb67969c..ffc6f29e8 100644 --- a/src/ipc/intel-ipc.c +++ b/src/ipc/intel-ipc.c @@ -230,7 +230,7 @@ static int ipc_stream_pcm_params(uint32_t stream) struct sof_ipc_pcm_params_reply reply; struct ipc_comp_dev *pcm_dev; struct comp_dev *cd; - int err; + int err, posn_offset; trace_ipc("SAl"); @@ -301,13 +301,17 @@ static int ipc_stream_pcm_params(uint32_t stream) goto error; } - + posn_offset = ipc_get_posn_offset(_ipc, pcm_dev->cd->pipeline); + if (posn_offset < 0) { + trace_ipc_error("eAo"); + goto error; + } /* 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 */ + reply.posn_offset = posn_offset; mailbox_hostbox_write(0, &reply, sizeof(reply)); return 1; @@ -371,15 +375,18 @@ static int ipc_stream_position(uint32_t header) } /* set message fields - TODO; get others */ - posn.rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION; + posn.rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION | + stream->comp_id; 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_hostbox_write(0, &posn, sizeof(posn)); + /* copy positions to stream region */ + mailbox_stream_write(pcm_dev->cd->pipeline->posn_offset, + &posn, sizeof(posn)); + return 1; } @@ -387,24 +394,38 @@ static int ipc_stream_position(uint32_t header) int ipc_stream_send_position(struct comp_dev *cdev, struct sof_ipc_stream_posn *posn) { - posn->rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION; + struct sof_ipc_hdr hdr; + + tracev_ipc("Pos"); + posn->rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION | + cdev->comp.id; posn->rhdr.hdr.size = sizeof(*posn); posn->comp_id = cdev->comp.id; - return ipc_queue_host_message(_ipc, posn->rhdr.hdr.cmd, posn, - sizeof(*posn), NULL, 0, NULL, NULL, 1); + hdr.cmd = posn->rhdr.hdr.cmd; + hdr.size = sizeof(hdr); + + mailbox_stream_write(cdev->pipeline->posn_offset, posn, sizeof(*posn)); + return ipc_queue_host_message(_ipc, posn->rhdr.hdr.cmd, &hdr, + sizeof(hdr), NULL, 0, NULL, NULL, 0); } /* send stream position TODO: send compound message */ int ipc_stream_send_xrun(struct comp_dev *cdev, struct sof_ipc_stream_posn *posn) { + struct sof_ipc_hdr hdr; + posn->rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_TRIG_XRUN; posn->rhdr.hdr.size = sizeof(*posn); posn->comp_id = cdev->comp.id; - return ipc_queue_host_message(_ipc, posn->rhdr.hdr.cmd, posn, - sizeof(*posn), NULL, 0, NULL, NULL, 1); + hdr.cmd = posn->rhdr.hdr.cmd; + hdr.size = sizeof(hdr); + + mailbox_stream_write(cdev->pipeline->posn_offset, posn, sizeof(*posn)); + return ipc_queue_host_message(_ipc, posn->rhdr.hdr.cmd, &hdr, + sizeof(hdr), NULL, 0, NULL, NULL, 0); } static int ipc_stream_trigger(uint32_t header) diff --git a/src/ipc/ipc.c b/src/ipc/ipc.c index 4aebfb774..762bbf5c2 100644 --- a/src/ipc/ipc.c +++ b/src/ipc/ipc.c @@ -77,6 +77,27 @@ struct ipc_comp_dev *ipc_get_comp(struct ipc *ipc, uint32_t id) return NULL; } +int ipc_get_posn_offset(struct ipc *ipc, struct pipeline *pipe) +{ + int i; + uint32_t posn_size = sizeof(struct sof_ipc_stream_posn); + + for (i = 0; i < PLATFORM_MAX_STREAMS; i++) { + if (ipc->posn_map[i] == pipe) + return pipe->posn_offset; + } + + for (i = 0; i < PLATFORM_MAX_STREAMS; i++) { + if (ipc->posn_map[i] == NULL) { + ipc->posn_map[i] = pipe; + pipe->posn_offset = i * posn_size; + return pipe->posn_offset; + } + } + + return -EINVAL; +} + int ipc_comp_new(struct ipc *ipc, struct sof_ipc_comp *comp) { struct comp_dev *cd; @@ -347,6 +368,7 @@ int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config) int ipc_init(struct reef *reef) { + int i; trace_ipc("IPI"); /* init ipc data */ @@ -355,6 +377,9 @@ int ipc_init(struct reef *reef) SOF_IPC_MSG_MAX_SIZE); reef->ipc->dmat = reef->dmat; + for (i = 0; i < PLATFORM_MAX_STREAMS; i++) + reef->ipc->posn_map[i] = NULL; + list_init(&reef->ipc->comp_list); return platform_ipc_init(reef->ipc);