Skip to content
Merged
Show file tree
Hide file tree
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
26 changes: 15 additions & 11 deletions src/audio/detect_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ struct comp_data {
struct kpb_event_data event_data;
struct kpb_client client_data;

struct ipc_msg msg; /**< host notification */
struct sof_ipc_comp_event event;
struct ipc_msg *msg; /**< host notification */

void (*detect_func)(struct comp_dev *dev,
const struct audio_stream *source, uint32_t frames);
Expand Down Expand Up @@ -105,19 +106,10 @@ static inline bool detector_is_sample_width_supported(enum sof_ipc_frame sf)
static void notify_host(const struct comp_dev *dev)
{
struct comp_data *cd = comp_get_drvdata(dev);
struct sof_ipc_comp_event event;

comp_info(dev, "notify_host()");

event.event_type = SOF_CTRL_EVENT_KD;
event.num_elems = 0;

ipc_build_comp_notification(dev, &event);
ipc_prepare_host_message(&cd->msg, event.rhdr.hdr.cmd, &event,
sizeof(event));

/* Send IPC message right away to wake host up ASAP */
ipc_platform_send_msg(&cd->msg);
ipc_msg_send(cd->msg, &cd->event, true);
}

static void notify_kpb(const struct comp_dev *dev)
Expand Down Expand Up @@ -346,6 +338,17 @@ static struct comp_dev *test_keyword_new(const struct comp_driver *drv,
goto fail;
}

/* build component event */
ipc_build_comp_event(&cd->event, comp->type, comp->id);
cd->event.event_type = SOF_CTRL_EVENT_KD;
cd->event.num_elems = 0;

cd->msg = ipc_msg_init(cd->event.rhdr.hdr.cmd, sizeof(cd->event));
if (!cd->msg) {
comp_err(dev, "test_keyword_new() error: ipc notification init failed");
goto fail;
}

dev->state = COMP_STATE_READY;
return dev;

Expand All @@ -362,6 +365,7 @@ static void test_keyword_free(struct comp_dev *dev)

comp_info(dev, "test_keyword_free()");

ipc_msg_free(cd->msg);
free_mem_load(cd);
rfree(cd);
rfree(dev);
Expand Down
19 changes: 17 additions & 2 deletions src/audio/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <sof/drivers/ipc.h>
#include <sof/lib/alloc.h>
#include <sof/lib/dma.h>
#include <sof/lib/mailbox.h>
#include <sof/lib/memory.h>
#include <sof/lib/notifier.h>
#include <sof/list.h>
Expand Down Expand Up @@ -83,6 +84,7 @@ struct host_data {

/* stream info */
struct sof_ipc_stream_posn posn; /* TODO: update this */
struct ipc_msg *msg; /**< host notification */
};

static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc)
Expand Down Expand Up @@ -155,7 +157,9 @@ static void host_update_position(struct comp_dev *dev, uint32_t bytes)
* (updates position first, by calling ops.position())
*/
pipeline_get_timestamp(dev->pipeline, dev, &hd->posn);
ipc_stream_send_position(dev, &hd->posn);
mailbox_stream_write(dev->pipeline->posn_offset,
&hd->posn, sizeof(hd->posn));
ipc_msg_send(hd->msg, &hd->posn, false);
}
}
}
Expand Down Expand Up @@ -362,9 +366,19 @@ static struct comp_dev *host_new(const struct comp_driver *drv,
dma_sg_init(&hd->host.elem_array);
dma_sg_init(&hd->local.elem_array);

ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, comp->id);

hd->msg = ipc_msg_init(hd->posn.rhdr.hdr.cmd, sizeof(hd->posn));
if (!hd->msg) {
comp_err(dev, "host_new() error: ipc_msg_init failed");
dma_put(hd->dma);
rfree(hd);
rfree(dev);
return NULL;
}

hd->chan = NULL;
hd->copy_type = COMP_COPY_NORMAL;
hd->posn.comp_id = comp->id;
dev->state = COMP_STATE_READY;

return dev;
Expand All @@ -378,6 +392,7 @@ static void host_free(struct comp_dev *dev)

dma_put(hd->dma);

ipc_msg_free(hd->msg);
dma_sg_free(&hd->config.elem_array);
rfree(hd);
rfree(dev);
Expand Down
23 changes: 22 additions & 1 deletion src/audio/pipeline.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
#include <sof/drivers/ipc.h>
#include <sof/drivers/timer.h>
#include <sof/lib/alloc.h>
#include <sof/lib/mailbox.h>
#include <sof/list.h>
#include <sof/math/numbers.h>
#include <sof/schedule/ll_schedule.h>
#include <sof/schedule/schedule.h>
#include <sof/schedule/task.h>
#include <sof/spinlock.h>
#include <sof/string.h>
#include <ipc/header.h>
#include <ipc/stream.h>
#include <ipc/topology.h>
#include <errno.h>
Expand All @@ -41,6 +43,7 @@ static enum task_state pipeline_task(void *arg);
struct pipeline *pipeline_new(struct sof_ipc_pipe_new *pipe_desc,
struct comp_dev *cd)
{
struct sof_ipc_stream_posn posn;
struct pipeline *p;
int ret;

Expand All @@ -63,6 +66,17 @@ struct pipeline *pipeline_new(struct sof_ipc_pipe_new *pipe_desc,
pipe_desc, sizeof(*pipe_desc));
assert(!ret);

/* just for retrieving valid ipc_msg header */
ipc_build_stream_posn(&posn, SOF_IPC_STREAM_TRIG_XRUN,
p->ipc_pipe.comp_id);

p->msg = ipc_msg_init(posn.rhdr.hdr.cmd, sizeof(posn));
if (!p->msg) {
pipe_cl_err("pipeline_new() error: ipc_msg_init failed");
rfree(p);
return NULL;
}

return p;
}

Expand Down Expand Up @@ -241,6 +255,8 @@ int pipeline_free(struct pipeline *p)
rfree(p->pipe_task);
}

ipc_msg_free(p->msg);

/* now free the pipeline */
rfree(p);

Expand Down Expand Up @@ -829,7 +845,9 @@ static int pipeline_comp_xrun(struct comp_dev *current,
platform_host_timestamp(current, ppl_data->posn);

/* send XRUN to host */
ipc_stream_send_xrun(current, ppl_data->posn);
mailbox_stream_write(ppl_data->p->posn_offset, ppl_data->posn,
sizeof(*ppl_data->posn));
ipc_msg_send(ppl_data->p->msg, ppl_data->posn, true);
}

return pipeline_for_each_comp(current, &pipeline_comp_xrun, data, NULL,
Expand Down Expand Up @@ -859,10 +877,13 @@ void pipeline_xrun(struct pipeline *p, struct comp_dev *dev,
ret);

memset(&posn, 0, sizeof(posn));
ipc_build_stream_posn(&posn, SOF_IPC_STREAM_TRIG_XRUN,
dev_comp_id(dev));
p->xrun_bytes = bytes;
posn.xrun_size = bytes;
posn.xrun_comp_id = dev_comp_id(dev);
data.posn = &posn;
data.p = p;

pipeline_comp_xrun(dev, NULL, &data, dev->direction);
}
Expand Down
20 changes: 12 additions & 8 deletions src/drivers/imx/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <ipc/topology.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tlauda do we have a real usecase where checking IPC bits is not enough?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbaluta Yes, during specific power flows on cAVS DSP.

#include <config.h>
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

Expand Down Expand Up @@ -50,6 +51,8 @@ static void irq_handler(void *arg)

interrupt_clear(PLATFORM_IPC_INTERRUPT);

ipc->is_notification_pending = false;

/* unmask GP interrupt #1 */
imx_mu_xcr_rmw(IMX_MU_xCR_GIEn(1), 0);
}
Expand Down Expand Up @@ -106,33 +109,34 @@ void ipc_platform_complete_cmd(void *data)
platform_shared_commit(ipc, sizeof(*ipc));
}

void ipc_platform_send_msg(struct ipc_msg *msg)
int ipc_platform_send_msg(struct ipc_msg *msg)
{
struct ipc *ipc = ipc_get();
uint32_t flags;

spin_lock_irq(&ipc->lock, flags);
int ret = 0;

/* can't send notification when one is in progress */
if (imx_mu_read(IMX_MU_xCR) & IMX_MU_xCR_GIRn(1))
if (ipc->is_notification_pending ||
imx_mu_read(IMX_MU_xCR) & IMX_MU_xCR_GIRn(1)) {
ret = -EBUSY;
goto out;
}

/* now send the message */
mailbox_dspbox_write(0, msg->tx_data, msg->tx_size);
list_item_del(&msg->list);
tracev_ipc("ipc: msg tx -> 0x%x", msg->header);

ipc->is_notification_pending = true;

/* now interrupt host to tell it we have sent a message */
imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(1), 0);

list_item_append(&msg->list, &ipc->empty_list);

platform_shared_commit(msg, sizeof(*msg));

out:
platform_shared_commit(ipc, sizeof(*ipc));

spin_unlock_irq(&ipc->lock, flags);
return ret;
}

#if CONFIG_HOST_PTABLE
Expand Down
20 changes: 12 additions & 8 deletions src/drivers/intel/baytrail/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <sof/spinlock.h>
#include <ipc/header.h>
#include <ipc/topology.h>
#include <stdbool.h>
#include <stdint.h>

/* private data for IPC */
Expand Down Expand Up @@ -50,6 +51,8 @@ static void irq_handler(void *arg)
shim_write(SHIM_IPCDH,
shim_read(SHIM_IPCDH) & ~SHIM_IPCDH_DONE);

ipc->is_notification_pending = false;

/* unmask Done interrupt */
shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DONE);
}
Expand Down Expand Up @@ -94,34 +97,35 @@ void ipc_platform_complete_cmd(void *data)
shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_BUSY);
}

void ipc_platform_send_msg(struct ipc_msg *msg)
int ipc_platform_send_msg(struct ipc_msg *msg)
{
struct ipc *ipc = ipc_get();
uint32_t flags;

spin_lock_irq(&ipc->lock, flags);
int ret = 0;

/* can't send notification when one is in progress */
if (shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE))
if (ipc->is_notification_pending ||
shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE)) {
ret = -EBUSY;
goto out;
}

/* now send the message */
mailbox_dspbox_write(0, msg->tx_data, msg->tx_size);
list_item_del(&msg->list);
tracev_ipc("ipc: msg tx -> 0x%x", msg->header);

ipc->is_notification_pending = true;

/* now interrupt host to tell it we have message sent */
shim_write(SHIM_IPCDL, msg->header);
shim_write(SHIM_IPCDH, SHIM_IPCDH_BUSY);

list_item_append(&msg->list, &ipc->empty_list);

platform_shared_commit(msg, sizeof(*msg));

out:
platform_shared_commit(ipc, sizeof(*ipc));

spin_unlock_irq(&ipc->lock, flags);
return ret;
}

struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc)
Expand Down
24 changes: 14 additions & 10 deletions src/drivers/intel/cavs/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <ipc/pm.h>
#endif
#include <config.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

Expand Down Expand Up @@ -119,6 +120,8 @@ static void ipc_irq_handler(void *arg)
ipc_read(IPC_DIPCIDA) | IPC_DIPCIDA_DONE);
#endif

ipc->is_notification_pending = false;

/* unmask Done interrupt */
ipc_write(IPC_DIPCCTL,
ipc_read(IPC_DIPCCTL) | IPC_DIPCCTL_IPCIDIE);
Expand Down Expand Up @@ -240,26 +243,29 @@ void ipc_platform_complete_cmd(void *data)
#endif
}

void ipc_platform_send_msg(struct ipc_msg *msg)
int ipc_platform_send_msg(struct ipc_msg *msg)
{
struct ipc *ipc = ipc_get();
uint32_t flags;

spin_lock_irq(&ipc->lock, flags);
int ret = 0;

if (ipc->is_notification_pending ||
#if CAVS_VERSION == CAVS_VERSION_1_5
if (ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY)
ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY) {
#else
if (ipc_read(IPC_DIPCIDR) & IPC_DIPCIDR_BUSY ||
ipc_read(IPC_DIPCIDA) & IPC_DIPCIDA_DONE)
ipc_read(IPC_DIPCIDR) & IPC_DIPCIDR_BUSY ||
ipc_read(IPC_DIPCIDA) & IPC_DIPCIDA_DONE) {
#endif
ret = -EBUSY;
goto out;
}

/* now send the message */
mailbox_dspbox_write(0, msg->tx_data, msg->tx_size);
list_item_del(&msg->list);
tracev_ipc("ipc: msg tx -> 0x%x", msg->header);

ipc->is_notification_pending = true;

/* now interrupt host to tell it we have message sent */
#if CAVS_VERSION == CAVS_VERSION_1_5
ipc_write(IPC_DIPCIE, 0);
Expand All @@ -269,14 +275,12 @@ void ipc_platform_send_msg(struct ipc_msg *msg)
ipc_write(IPC_DIPCIDR, 0x80000000 | msg->header);
#endif

list_item_append(&msg->list, &ipc->empty_list);

platform_shared_commit(msg, sizeof(*msg));

out:
platform_shared_commit(ipc, sizeof(*ipc));

spin_unlock_irq(&ipc->lock, flags);
return ret;
}

int platform_ipc_init(struct ipc *ipc)
Expand Down
Loading