On 4/13/2018 00:24, Liam Girdwood wrote:
Allow users outside of IPC to make use of compressed host page tables.
Only a typo in patch name: "page tables;" => "page tables:" Others looks fine
Thanks Xiuli
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com
src/include/sof/intel-ipc.h | 1 - src/include/sof/ipc.h | 8 +++ src/ipc/handler.c | 143 +++----------------------------------------- src/ipc/ipc.c | 129 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 135 deletions(-)
diff --git a/src/include/sof/intel-ipc.h b/src/include/sof/intel-ipc.h index f89e9b57..a59c106f 100644 --- a/src/include/sof/intel-ipc.h +++ b/src/include/sof/intel-ipc.h @@ -38,7 +38,6 @@ struct intel_ipc_data { /* DMA */ struct dma *dmac; uint8_t *page_table;
completion_t complete;
/* PM */ int pm_prepare_D3; /* do we need to prepare for D3 */
diff --git a/src/include/sof/ipc.h b/src/include/sof/ipc.h index 2e1818df..06425b34 100644 --- a/src/include/sof/ipc.h +++ b/src/include/sof/ipc.h @@ -134,6 +134,14 @@ int ipc_send_short_msg(uint32_t msg); void ipc_platform_do_cmd(struct ipc *ipc); void ipc_platform_send_msg(struct ipc *ipc);
+/* create a SG page table eme list from a compressed page table */ +int ipc_parse_page_descriptors(uint8_t *page_table,
struct sof_ipc_host_buffer *ring,
struct list_item *elem_list,
uint32_t direction);
+int ipc_get_page_descriptors(struct dma *dmac, uint8_t *page_table,
struct sof_ipc_host_buffer *ring);
- /*
*/
- IPC Component creation and destruction.
diff --git a/src/ipc/handler.c b/src/ipc/handler.c index 6a51765b..581ce9e7 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -83,134 +83,6 @@ static inline struct sof_ipc_hdr *mailbox_validate(void) return hdr; }
-#ifdef CONFIG_HOST_PTABLE -static void dma_complete(void *data, uint32_t type, struct dma_sg_elem *next) -{
- struct intel_ipc_data *iipc = (struct intel_ipc_data *)data;
- if (type == DMA_IRQ_TYPE_LLIST)
wait_completed(&iipc->complete);
-}
-/*
- Copy the audio buffer page tables from the host to the DSP max of 4K.
- */
-static int get_page_descriptors(struct intel_ipc_data *iipc,
- struct sof_ipc_host_buffer *ring)
-{
- struct dma_sg_config config;
- struct dma_sg_elem elem;
- struct dma *dma;
- int chan;
- int ret = 0;
- /* get DMA channel from DMAC */
- chan = dma_channel_get(iipc->dmac, 0);
- if (chan < 0) {
trace_ipc_error("ePC");
return chan;
- }
- dma = iipc->dmac;
- /* set up DMA configuration */
- config.direction = DMA_DIR_HMEM_TO_LMEM;
- config.src_width = sizeof(uint32_t);
- config.dest_width = sizeof(uint32_t);
- config.cyclic = 0;
- list_init(&config.elem_list);
- /* set up DMA descriptor */
- elem.dest = (uint32_t)iipc->page_table;
- elem.src = ring->phy_addr;
- /* source buffer size is always PAGE_SIZE bytes */
- /* 20 bits for each page, round up to 32 */
- elem.size = (ring->pages * 5 * 16 + 31) / 32;
- list_item_prepend(&elem.list, &config.elem_list);
- ret = dma_set_config(dma, chan, &config);
- if (ret < 0) {
trace_ipc_error("ePs");
goto out;
- }
- /* set up callback */
- dma_set_cb(dma, chan, DMA_IRQ_TYPE_LLIST, dma_complete, iipc);
- wait_init(&iipc->complete);
- /* start the copy of page table to DSP */
- dma_start(dma, chan);
- /* wait for DMA to complete */
- iipc->complete.timeout = PLATFORM_HOST_DMA_TIMEOUT;
- ret = wait_for_completion_timeout(&iipc->complete);
- /* compressed page tables now in buffer at _ipc->page_table */
-out:
- dma_channel_put(dma, chan);
- return ret;
-}
-/*
- Parse the host page tables and create the audio DMA SG configuration
- for host audio DMA buffer. This involves creating a dma_sg_elem for each
- page table entry and adding each elem to a list in struct dma_sg_config.
- */
-static int parse_page_descriptors(struct intel_ipc_data *iipc,
- struct sof_ipc_host_buffer *ring, struct list_item *elem_list,
- uint32_t direction)
-{
- int i;
- uint32_t idx;
- uint32_t phy_addr;
- struct dma_sg_elem *e;
- /* the ring size may be not multiple of the page size, the last
* page may be not full used. The used size should be in range
* of (ring->pages - 1, ring->pages] * PAGES.
*/
- if ((ring->size <= HOST_PAGE_SIZE * (ring->pages - 1)) ||
(ring->size > HOST_PAGE_SIZE * ring->pages)) {
/* error buffer size */
trace_ipc_error("eBs");
return -EINVAL;
- }
- for (i = 0; i < ring->pages; i++) {
idx = (((i << 2) + i)) >> 1;
phy_addr = iipc->page_table[idx] | (iipc->page_table[idx + 1] << 8)
| (iipc->page_table[idx + 2] << 16);
if (i & 0x1)
phy_addr <<= 8;
else
phy_addr <<= 12;
phy_addr &= 0xfffff000;
/* allocate new host DMA elem and add it to our list */
e = rzalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, sizeof(*e));
if (!e)
return -ENOMEM;
if (direction == SOF_IPC_STREAM_PLAYBACK)
e->src = phy_addr;
else
e->dest = phy_addr;
/* the last page may be not full used */
if (i == (ring->pages - 1))
e->size = ring->size - HOST_PAGE_SIZE * i;
else
e->size = HOST_PAGE_SIZE;
list_item_append(&e->list, elem_list);
- }
- return 0;
-} -#endif
- /*
*/
- Stream IPC Operations.
@@ -258,7 +130,8 @@ static int ipc_stream_pcm_params(uint32_t stream) list_init(&elem_list);
/* use DMA to read in compressed page table ringbuffer from host */
- err = get_page_descriptors(iipc, &pcm_params->params.buffer);
- err = ipc_get_page_descriptors(iipc->dmac, iipc->page_table,
if (err < 0) { trace_ipc_error("eAp"); goto error;&pcm_params->params.buffer);
@@ -268,8 +141,9 @@ static int ipc_stream_pcm_params(uint32_t stream) host = (struct sof_ipc_comp_host *)&cd->comp; ring_size = pcm_params->params.buffer.size;
- err = parse_page_descriptors(iipc, &pcm_params->params.buffer,
&elem_list, host->direction);
- err = ipc_parse_page_descriptors(iipc->page_table,
&pcm_params->params.buffer,
if (err < 0) { trace_ipc_error("eAP"); goto error;&elem_list, host->direction);
@@ -656,7 +530,8 @@ static int ipc_dma_trace_config(uint32_t header) list_init(&elem_list);
/* use DMA to read in compressed page table ringbuffer from host */
- err = get_page_descriptors(iipc, ¶ms->buffer);
- err = ipc_get_page_descriptors(iipc->dmac, iipc->page_table,
if (err < 0) { trace_ipc_error("eCp"); goto error;¶ms->buffer);
@@ -667,8 +542,8 @@ static int ipc_dma_trace_config(uint32_t header) /* Parse host tables */ ring_size = params->buffer.size;
- err = parse_page_descriptors(iipc, ¶ms->buffer,
&elem_list, SOF_IPC_STREAM_CAPTURE);
- err = ipc_parse_page_descriptors(iipc->page_table, ¶ms->buffer,
if (err < 0) { trace_ipc_error("ePP"); goto error;&elem_list, SOF_IPC_STREAM_CAPTURE);
diff --git a/src/ipc/ipc.c b/src/ipc/ipc.c index ed2cbb8e..fbb1be6c 100644 --- a/src/ipc/ipc.c +++ b/src/ipc/ipc.c @@ -39,6 +39,7 @@ #include <sof/alloc.h> #include <sof/ipc.h> #include <sof/debug.h> +#include <platform/platform.h> #include <sof/audio/component.h> #include <sof/audio/pipeline.h> #include <sof/audio/buffer.h> @@ -366,6 +367,134 @@ int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config) return ret; }
+#ifdef CONFIG_HOST_PTABLE +/*
- Parse the host page tables and create the audio DMA SG configuration
- for host audio DMA buffer. This involves creating a dma_sg_elem for each
- page table entry and adding each elem to a list in struct dma_sg_config.
- */
+int ipc_parse_page_descriptors(uint8_t *page_table,
struct sof_ipc_host_buffer *ring,
struct list_item *elem_list,
uint32_t direction)
+{
- int i;
- uint32_t idx;
- uint32_t phy_addr;
- struct dma_sg_elem *e;
- /* the ring size may be not multiple of the page size, the last
* page may be not full used. The used size should be in range
* of (ring->pages - 1, ring->pages] * PAGES.
*/
- if ((ring->size <= HOST_PAGE_SIZE * (ring->pages - 1)) ||
(ring->size > HOST_PAGE_SIZE * ring->pages)) {
/* error buffer size */
trace_ipc_error("eBs");
return -EINVAL;
- }
- for (i = 0; i < ring->pages; i++) {
idx = (((i << 2) + i)) >> 1;
phy_addr = page_table[idx] | (page_table[idx + 1] << 8)
| (page_table[idx + 2] << 16);
if (i & 0x1)
phy_addr <<= 8;
else
phy_addr <<= 12;
phy_addr &= 0xfffff000;
/* allocate new host DMA elem and add it to our list */
e = rzalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, sizeof(*e));
if (!e)
return -ENOMEM;
if (direction == SOF_IPC_STREAM_PLAYBACK)
e->src = phy_addr;
else
e->dest = phy_addr;
/* the last page may be not full used */
if (i == (ring->pages - 1))
e->size = ring->size - HOST_PAGE_SIZE * i;
else
e->size = HOST_PAGE_SIZE;
list_item_append(&e->list, elem_list);
- }
- return 0;
+}
+static void dma_complete(void *data, uint32_t type, struct dma_sg_elem *next) +{
- completion_t *complete = data;
- if (type == DMA_IRQ_TYPE_LLIST)
wait_completed(complete);
+}
+/*
- Copy the audio buffer page tables from the host to the DSP max of 4K.
- */
+int ipc_get_page_descriptors(struct dma *dmac, uint8_t *page_table,
struct sof_ipc_host_buffer *ring)
+{
- struct dma_sg_config config;
- struct dma_sg_elem elem;
- completion_t complete;
- int chan;
- int ret = 0;
- /* get DMA channel from DMAC */
- chan = dma_channel_get(dmac, 0);
- if (chan < 0) {
trace_ipc_error("ePC");
return chan;
- }
- /* set up DMA configuration */
- config.direction = DMA_DIR_HMEM_TO_LMEM;
- config.src_width = sizeof(uint32_t);
- config.dest_width = sizeof(uint32_t);
- config.cyclic = 0;
- list_init(&config.elem_list);
- /* set up DMA descriptor */
- elem.dest = (uint32_t)page_table;
- elem.src = ring->phy_addr;
- /* source buffer size is always PAGE_SIZE bytes */
- /* 20 bits for each page, round up to 32 */
- elem.size = (ring->pages * 5 * 16 + 31) / 32;
- list_item_prepend(&elem.list, &config.elem_list);
- ret = dma_set_config(dmac, chan, &config);
- if (ret < 0) {
trace_ipc_error("ePs");
goto out;
- }
- /* set up callback */
- dma_set_cb(dmac, chan, DMA_IRQ_TYPE_LLIST, dma_complete, &complete);
- wait_init(&complete);
- /* start the copy of page table to DSP */
- dma_start(dmac, chan);
- /* wait for DMA to complete */
- complete.timeout = PLATFORM_HOST_DMA_TIMEOUT;
- ret = wait_for_completion_timeout(&complete);
- /* compressed page tables now in buffer at _ipc->page_table */
+out:
- dma_channel_put(dmac, chan);
- return ret;
+} +#endif
- int ipc_init(struct sof *sof) { int i;