static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg)
{
struct sst_byt_stream *stream;
- u64 header = msg->header;
+ u64 header = msg->tx.header;
u8 stream_id = sst_byt_header_str_id(header);
u8 stream_msg = sst_byt_header_msg_id(header);
if (msg == NULL)
return 1;
+ msg->rx.header = header;
if (header & IPC_HEADER_LARGE(true)) {
- msg->rx_size = sst_byt_header_data(header);
- sst_dsp_inbox_read(byt->dsp, msg->rx_data, msg->rx_size);
+ msg->rx.size = sst_byt_header_data(header);
+ sst_dsp_inbox_read(byt->dsp, msg->rx.data, msg->rx.size);
}
/* update any stream states */
int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream)
{
- struct sst_byt_alloc_params *str_req = &stream->request;
- struct sst_byt_alloc_response *reply = &stream->reply;
- u64 header;
+ struct sst_ipc_message request, reply = {0};
int ret;
- header = sst_byt_header(IPC_IA_ALLOC_STREAM,
- sizeof(*str_req) + sizeof(u32),
+ request.header = sst_byt_header(IPC_IA_ALLOC_STREAM,
+ sizeof(stream->request) + sizeof(u32),
true, stream->str_id);
- ret = sst_ipc_tx_message_wait(&byt->ipc, header, str_req,
- sizeof(*str_req),
- reply, sizeof(*reply));
+ request.data = &stream->request;
+ request.size = sizeof(stream->request);
+ reply.data = &stream->reply;
+ reply.size = sizeof(stream->reply);
+
+ ret = sst_ipc_tx_message_wait(&byt->ipc, request, &reply);
if (ret < 0) {
dev_err(byt->dev, "ipc: error stream commit failed\n");
return ret;
int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream)
{
- u64 header;
+ struct sst_ipc_message request = {0};
int ret = 0;
struct sst_dsp *sst = byt->dsp;
unsigned long flags;
if (!stream->commited)
goto out;
- header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id);
- ret = sst_ipc_tx_message_wait(&byt->ipc, header, NULL, 0, NULL, 0);
+ request.header = sst_byt_header(IPC_IA_FREE_STREAM,
+ 0, false, stream->str_id);
+ ret = sst_ipc_tx_message_wait(&byt->ipc, request, NULL);
if (ret < 0) {
dev_err(byt->dev, "ipc: free stream %d failed\n",
stream->str_id);
static int sst_byt_stream_operations(struct sst_byt *byt, int type,
int stream_id, int wait)
{
- u64 header;
+ struct sst_ipc_message request = {0};
- header = sst_byt_header(type, 0, false, stream_id);
+ request.header = sst_byt_header(type, 0, false, stream_id);
if (wait)
- return sst_ipc_tx_message_wait(&byt->ipc, header, NULL,
- 0, NULL, 0);
+ return sst_ipc_tx_message_wait(&byt->ipc, request, NULL);
else
- return sst_ipc_tx_message_nowait(&byt->ipc, header,
- NULL, 0);
+ return sst_ipc_tx_message_nowait(&byt->ipc, request);
}
/* stream ALSA trigger operations */
u32 start_offset)
{
struct sst_byt_start_stream_params start_stream;
- void *tx_msg;
- size_t size;
- u64 header;
+ struct sst_ipc_message request;
int ret;
start_stream.byte_offset = start_offset;
- header = sst_byt_header(IPC_IA_START_STREAM,
+ request.header = sst_byt_header(IPC_IA_START_STREAM,
sizeof(start_stream) + sizeof(u32),
true, stream->str_id);
- tx_msg = &start_stream;
- size = sizeof(start_stream);
+ request.data = &start_stream;
+ request.size = sizeof(start_stream);
- ret = sst_ipc_tx_message_nowait(&byt->ipc, header, tx_msg, size);
+ ret = sst_ipc_tx_message_nowait(&byt->ipc, request);
if (ret < 0)
dev_err(byt->dev, "ipc: error failed to start stream %d\n",
stream->str_id);
static void byt_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
{
- if (msg->header & IPC_HEADER_LARGE(true))
- sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
+ if (msg->tx.header & IPC_HEADER_LARGE(true))
+ sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size);
- sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->header);
+ sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->tx.header);
}
static void byt_shim_dbg(struct sst_generic_ipc *ipc, const char *text)
size_t tx_size)
{
/* msg content = lower 32-bit of the header + data */
- *(u32 *)msg->tx_data = (u32)(msg->header & (u32)-1);
- memcpy(msg->tx_data + sizeof(u32), tx_data, tx_size);
- msg->tx_size += sizeof(u32);
+ *(u32 *)msg->tx.data = (u32)(msg->tx.header & (u32)-1);
+ memcpy(msg->tx.data + sizeof(u32), tx_data, tx_size);
+ msg->tx.size += sizeof(u32);
}
static u64 byt_reply_msg_match(u64 header, u64 *mask)
}
static int tx_wait_done(struct sst_generic_ipc *ipc,
- struct ipc_message *msg, void *rx_data)
+ struct ipc_message *msg, struct sst_ipc_message *reply)
{
unsigned long flags;
int ret;
} else {
/* copy the data returned from DSP */
- if (rx_data)
- memcpy(rx_data, msg->rx_data, msg->rx_size);
+ if (reply) {
+ reply->header = msg->rx.header;
+ if (reply->data)
+ memcpy(reply->data, msg->rx.data, msg->rx.size);
+ }
ret = msg->errno;
}
return ret;
}
-static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header,
- void *tx_data, size_t tx_bytes, void *rx_data,
- size_t rx_bytes, int wait)
+static int ipc_tx_message(struct sst_generic_ipc *ipc,
+ struct sst_ipc_message request,
+ struct sst_ipc_message *reply, int wait)
{
struct ipc_message *msg;
unsigned long flags;
return -EBUSY;
}
- msg->header = header;
- msg->tx_size = tx_bytes;
- msg->rx_size = rx_bytes;
+ msg->tx.header = request.header;
+ msg->tx.size = request.size;
+ msg->rx.header = 0;
+ msg->rx.size = reply ? reply->size : 0;
msg->wait = wait;
msg->errno = 0;
msg->pending = false;
msg->complete = false;
- if ((tx_bytes) && (ipc->ops.tx_data_copy != NULL))
- ipc->ops.tx_data_copy(msg, tx_data, tx_bytes);
+ if ((request.size) && (ipc->ops.tx_data_copy != NULL))
+ ipc->ops.tx_data_copy(msg, request.data, request.size);
list_add_tail(&msg->list, &ipc->tx_list);
schedule_work(&ipc->kwork);
spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
if (wait)
- return tx_wait_done(ipc, msg, rx_data);
+ return tx_wait_done(ipc, msg, reply);
else
return 0;
}
return -ENOMEM;
for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
- ipc->msg[i].tx_data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL);
- if (ipc->msg[i].tx_data == NULL)
+ ipc->msg[i].tx.data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL);
+ if (ipc->msg[i].tx.data == NULL)
goto free_mem;
- ipc->msg[i].rx_data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL);
- if (ipc->msg[i].rx_data == NULL) {
- kfree(ipc->msg[i].tx_data);
+ ipc->msg[i].rx.data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL);
+ if (ipc->msg[i].rx.data == NULL) {
+ kfree(ipc->msg[i].tx.data);
goto free_mem;
}
free_mem:
while (i > 0) {
- kfree(ipc->msg[i-1].tx_data);
- kfree(ipc->msg[i-1].rx_data);
+ kfree(ipc->msg[i-1].tx.data);
+ kfree(ipc->msg[i-1].rx.data);
--i;
}
kfree(ipc->msg);
spin_unlock_irq(&ipc->dsp->spinlock);
}
-int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header,
- void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes)
+int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc,
+ struct sst_ipc_message request, struct sst_ipc_message *reply)
{
int ret;
if (ipc->ops.check_dsp_lp_on(ipc->dsp, true))
return -EIO;
- ret = ipc_tx_message(ipc, header, tx_data, tx_bytes,
- rx_data, rx_bytes, 1);
+ ret = ipc_tx_message(ipc, request, reply, 1);
if (ipc->ops.check_dsp_lp_on)
if (ipc->ops.check_dsp_lp_on(ipc->dsp, false))
}
EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait);
-int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header,
- void *tx_data, size_t tx_bytes)
+int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc,
+ struct sst_ipc_message request)
{
- return ipc_tx_message(ipc, header, tx_data, tx_bytes,
- NULL, 0, 0);
+ return ipc_tx_message(ipc, request, NULL, 0);
}
EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait);
-int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, u64 header,
- void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes)
+int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc,
+ struct sst_ipc_message request, struct sst_ipc_message *reply)
{
- return ipc_tx_message(ipc, header, tx_data, tx_bytes,
- rx_data, rx_bytes, 1);
+ return ipc_tx_message(ipc, request, reply, 1);
}
EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nopm);
}
list_for_each_entry(msg, &ipc->rx_list, list) {
- if ((msg->header & mask) == header)
+ if ((msg->tx.header & mask) == header)
return msg;
}
if (ipc->msg) {
for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
- kfree(ipc->msg[i].tx_data);
- kfree(ipc->msg[i].rx_data);
+ kfree(ipc->msg[i].tx.data);
+ kfree(ipc->msg[i].rx.data);
}
kfree(ipc->msg);
}
#define IPC_MAX_MAILBOX_BYTES 256
-struct ipc_message {
- struct list_head list;
+struct sst_ipc_message {
u64 header;
+ void *data;
+ size_t size;
+};
- /* direction wrt host CPU */
- char *tx_data;
- size_t tx_size;
- char *rx_data;
- size_t rx_size;
+struct ipc_message {
+ struct list_head list;
+ struct sst_ipc_message tx;
+ struct sst_ipc_message rx;
wait_queue_head_t waitq;
bool pending;
struct sst_plat_ipc_ops ops;
};
-int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header,
- void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes);
+int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc,
+ struct sst_ipc_message request, struct sst_ipc_message *reply);
-int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header,
- void *tx_data, size_t tx_bytes);
+int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc,
+ struct sst_ipc_message request);
-int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc, u64 header,
- void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes);
+int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc,
+ struct sst_ipc_message request, struct sst_ipc_message *reply);
struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
u64 header);
static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg)
{
struct sst_hsw_stream *stream;
- u32 header = msg->header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK);
+ u32 header = msg->tx.header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK);
u32 stream_id = msg_get_stream_id(header);
u32 stream_msg = msg_get_stream_type(header);
return -EIO;
}
+ msg->rx.header = header;
/* first process the header */
switch (reply) {
case IPC_GLB_REPLY_PENDING:
case IPC_GLB_REPLY_SUCCESS:
if (msg->pending) {
trace_ipc_pending_reply("completed", header);
- sst_dsp_inbox_read(hsw->dsp, msg->rx_data,
- msg->rx_size);
+ sst_dsp_inbox_read(hsw->dsp, msg->rx.data,
+ msg->rx.size);
hsw->ipc.pending = false;
} else {
/* copy data from the DSP */
- sst_dsp_outbox_read(hsw->dsp, msg->rx_data,
- msg->rx_size);
+ sst_dsp_outbox_read(hsw->dsp, msg->rx.data,
+ msg->rx.size);
}
break;
/* these will be rare - but useful for debug */
int sst_hsw_fw_get_version(struct sst_hsw *hsw,
struct sst_hsw_ipc_fw_version *version)
{
+ struct sst_ipc_message request = {0}, reply = {0};
int ret;
- ret = sst_ipc_tx_message_wait(&hsw->ipc,
- IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION),
- NULL, 0, version, sizeof(*version));
+ request.header = IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION);
+ reply.data = version;
+ reply.size = sizeof(*version);
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply);
if (ret < 0)
dev_err(hsw->dev, "error: get version failed\n");
struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume)
{
struct sst_hsw_ipc_volume_req *req;
- u32 header;
+ struct sst_ipc_message request;
int ret;
trace_ipc_request("set stream volume", stream->reply.stream_hw_id);
if (channel >= 2 && channel != SST_HSW_CHANNELS_ALL)
return -EINVAL;
- header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) |
+ request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) |
IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE);
- header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT);
- header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT);
- header |= (stage_id << IPC_STG_ID_SHIFT);
+ request.header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT);
+ request.header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT);
+ request.header |= (stage_id << IPC_STG_ID_SHIFT);
req = &stream->vol_req;
req->target_volume = volume;
req->channel = channel;
}
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header, req,
- sizeof(*req), NULL, 0);
+ request.data = req;
+ request.size = sizeof(*req);
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL);
if (ret < 0) {
dev_err(hsw->dev, "error: set stream volume failed\n");
return ret;
u32 volume)
{
struct sst_hsw_ipc_volume_req req;
- u32 header;
+ struct sst_ipc_message request;
int ret;
trace_ipc_request("set mixer volume", volume);
req.channel = channel;
}
- header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) |
+ request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) |
IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE);
- header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT);
- header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT);
- header |= (stage_id << IPC_STG_ID_SHIFT);
+ request.header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT);
+ request.header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT);
+ request.header |= (stage_id << IPC_STG_ID_SHIFT);
req.curve_duration = hsw->curve_duration;
req.curve_type = hsw->curve_type;
req.target_volume = volume;
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &req,
- sizeof(req), NULL, 0);
+ request.data = &req;
+ request.size = sizeof(req);
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL);
if (ret < 0) {
dev_err(hsw->dev, "error: set mixer volume failed\n");
return ret;
int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
{
- u32 header;
+ struct sst_ipc_message request;
int ret = 0;
struct sst_dsp *sst = hsw->dsp;
unsigned long flags;
trace_ipc_request("stream free", stream->host_id);
stream->free_req.stream_id = stream->reply.stream_hw_id;
- header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM);
+ request.header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM);
+ request.data = &stream->free_req;
+ request.size = sizeof(stream->free_req);
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &stream->free_req,
- sizeof(stream->free_req), NULL, 0);
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL);
if (ret < 0) {
dev_err(hsw->dev, "error: free stream %d failed\n",
stream->free_req.stream_id);
int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
{
- struct sst_hsw_ipc_stream_alloc_req *str_req = &stream->request;
- struct sst_hsw_ipc_stream_alloc_reply *reply = &stream->reply;
- u32 header;
+ struct sst_ipc_message request, reply = {0};
int ret;
if (!stream) {
trace_ipc_request("stream alloc", stream->host_id);
- header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM);
+ request.header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM);
+ request.data = &stream->request;
+ request.size = sizeof(stream->request);
+ reply.data = &stream->reply;
+ reply.size = sizeof(stream->reply);
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header, str_req,
- sizeof(*str_req), reply, sizeof(*reply));
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply);
if (ret < 0) {
dev_err(hsw->dev, "error: stream commit failed\n");
return ret;
ABI to be opaque to client PCM drivers to cope with any future ABI changes */
int sst_hsw_mixer_get_info(struct sst_hsw *hsw)
{
- struct sst_hsw_ipc_stream_info_reply *reply;
- u32 header;
+ struct sst_ipc_message request = {0}, reply = {0};
int ret;
- reply = &hsw->mixer_info;
- header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO);
+ request.header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO);
+ reply.data = &hsw->mixer_info;
+ reply.size = sizeof(hsw->mixer_info);
trace_ipc_request("get global mixer info", 0);
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header, NULL, 0,
- reply, sizeof(*reply));
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply);
if (ret < 0) {
dev_err(hsw->dev, "error: get stream info failed\n");
return ret;
}
- trace_hsw_mixer_info_reply(reply);
+ trace_hsw_mixer_info_reply(&hsw->mixer_info);
return 0;
}
static int sst_hsw_stream_operations(struct sst_hsw *hsw, int type,
int stream_id, int wait)
{
- u32 header;
+ struct sst_ipc_message request = {0};
- header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(type);
- header |= (stream_id << IPC_STR_ID_SHIFT);
+ request.header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE);
+ request.header |= IPC_STR_TYPE(type) | (stream_id << IPC_STR_ID_SHIFT);
if (wait)
- return sst_ipc_tx_message_wait(&hsw->ipc, header,
- NULL, 0, NULL, 0);
+ return sst_ipc_tx_message_wait(&hsw->ipc, request, NULL);
else
- return sst_ipc_tx_message_nowait(&hsw->ipc, header, NULL, 0);
+ return sst_ipc_tx_message_nowait(&hsw->ipc, request);
}
/* Stream ALSA trigger operations */
enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk,
enum sst_hsw_device_mode mode, u32 clock_divider)
{
+ struct sst_ipc_message request;
struct sst_hsw_ipc_device_config_req config;
- u32 header;
int ret;
trace_ipc_request("set device config", dev);
trace_hsw_device_config_req(&config);
- header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS);
+ request.header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS);
+ request.data = &config;
+ request.size = sizeof(config);
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &config,
- sizeof(config), NULL, 0);
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL);
if (ret < 0)
dev_err(hsw->dev, "error: set device formats failed\n");
int sst_hsw_dx_set_state(struct sst_hsw *hsw,
enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx)
{
- u32 header, state_;
+ struct sst_ipc_message request, reply = {0};
+ u32 state_;
int ret, item;
- header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE);
state_ = state;
+ request.header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE);
+ request.data = &state_;
+ request.size = sizeof(state_);
+ reply.data = dx;
+ reply.size = sizeof(*dx);
trace_ipc_request("PM enter Dx state", state);
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &state_,
- sizeof(state_), dx, sizeof(*dx));
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, &reply);
if (ret < 0) {
dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state);
return ret;
u32 module_id, u32 instance_id)
{
int ret;
- u32 header = 0;
+ struct sst_ipc_message request;
struct sst_hsw_ipc_module_config config;
struct sst_module *module;
struct sst_module_runtime *runtime;
return -ENXIO;
}
- header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
+ request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
IPC_MODULE_OPERATION(IPC_MODULE_ENABLE) |
IPC_MODULE_ID(module_id);
- dev_dbg(dev, "module enable header: %x\n", header);
+ dev_dbg(dev, "module enable header: %x\n", (u32)request.header);
config.map.module_entries_count = 1;
config.map.module_entries[0].module_id = module->id;
config.scratch_mem.size, config.scratch_mem.offset,
config.map.module_entries[0].entry_point);
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header,
- &config, sizeof(config), NULL, 0);
+ request.data = &config;
+ request.size = sizeof(config);
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL);
if (ret < 0)
dev_err(dev, "ipc: module enable failed - %d\n", ret);
else
u32 module_id, u32 instance_id)
{
int ret;
- u32 header;
+ struct sst_ipc_message request = {0};
struct sst_module *module;
struct device *dev = hsw->dev;
struct sst_dsp *dsp = hsw->dsp;
return -ENXIO;
}
- header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
+ request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
IPC_MODULE_OPERATION(IPC_MODULE_DISABLE) |
IPC_MODULE_ID(module_id);
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header, NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL);
if (ret < 0)
dev_err(dev, "module disable failed - %d\n", ret);
else
u32 param_size, char *param)
{
int ret;
- u32 header = 0;
- u32 payload_size = 0, transfer_parameter_size = 0;
+ struct sst_ipc_message request = {0};
+ u32 payload_size = 0;
struct sst_hsw_transfer_parameter *parameter;
struct device *dev = hsw->dev;
- header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
+ request.header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
IPC_MODULE_OPERATION(IPC_MODULE_SET_PARAMETER) |
IPC_MODULE_ID(module_id);
- dev_dbg(dev, "sst_hsw_module_set_param header=%x\n", header);
+ dev_dbg(dev, "sst_hsw_module_set_param header=%x\n",
+ (u32)request.header);
payload_size = param_size +
sizeof(struct sst_hsw_transfer_parameter) -
if (payload_size <= SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE) {
/* short parameter, mailbox can contain data */
- dev_dbg(dev, "transfer parameter size : %d\n",
- transfer_parameter_size);
+ dev_dbg(dev, "transfer parameter size : %lu\n",
+ request.size);
- transfer_parameter_size = ALIGN(payload_size, 4);
- dev_dbg(dev, "transfer parameter aligned size : %d\n",
- transfer_parameter_size);
+ request.size = ALIGN(payload_size, 4);
+ dev_dbg(dev, "transfer parameter aligned size : %lu\n",
+ request.size);
- parameter = kzalloc(transfer_parameter_size, GFP_KERNEL);
+ parameter = kzalloc(request.size, GFP_KERNEL);
if (parameter == NULL)
return -ENOMEM;
parameter->parameter_id = parameter_id;
parameter->data_size = param_size;
+ request.data = parameter;
- ret = sst_ipc_tx_message_wait(&hsw->ipc, header,
- parameter, transfer_parameter_size , NULL, 0);
+ ret = sst_ipc_tx_message_wait(&hsw->ipc, request, NULL);
if (ret < 0)
dev_err(dev, "ipc: module set parameter failed - %d\n", ret);
static void hsw_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
{
/* send the message */
- sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
- sst_dsp_ipc_msg_tx(ipc->dsp, msg->header);
+ sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size);
+ sst_dsp_ipc_msg_tx(ipc->dsp, msg->tx.header);
}
static void hsw_shim_dbg(struct sst_generic_ipc *ipc, const char *text)
static void hsw_tx_data_copy(struct ipc_message *msg, char *tx_data,
size_t tx_size)
{
- memcpy(msg->tx_data, tx_data, tx_size);
+ memcpy(msg->tx.data, tx_data, tx_size);
}
static u64 hsw_reply_msg_match(u64 header, u64 *mask)
static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
{
- struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
+ struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header);
- if (msg->tx_size)
- sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
+ if (msg->tx.size)
+ sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size);
sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD,
header->extension);
sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR,
size_t tx_size)
{
if (tx_size)
- memcpy(msg->tx_data, tx_data, tx_size);
+ memcpy(msg->tx.data, tx_data, tx_size);
}
static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
/* Lock to be held by caller */
static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
{
- struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
+ struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header);
- if (msg->tx_size)
- sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
+ if (msg->tx.size)
+ sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size);
sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
header->extension);
sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
return;
}
+ msg->rx.header = *ipc_header;
/* first process the header */
if (reply == IPC_GLB_REPLY_SUCCESS) {
dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
/* copy the rx data from the mailbox */
- sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
+ sst_dsp_inbox_read(ipc->dsp, msg->rx.data, msg->rx.size);
switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
case IPC_GLB_LOAD_MULTIPLE_MODS:
case IPC_GLB_LOAD_LIBRARY:
u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0};
int ret;
header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
header.extension = IPC_PPL_LP_MODE(lp_mode);
+ request.header = *(u64 *)(&header);
dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
return ret;
int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0};
int ret;
header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
header.primary |= IPC_INSTANCE_ID(instance_id);
+ request.header = *(u64 *)(&header);
dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
return ret;
u8 instance_id, enum skl_ipc_pipeline_state state)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0};
int ret;
header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
header.primary |= IPC_INSTANCE_ID(instance_id);
header.primary |= IPC_PPL_STATE(state);
+ request.header = *(u64 *)(&header);
dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
return ret;
skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0};
int ret;
header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
header.primary |= IPC_INSTANCE_ID(instance_id);
header.extension = IPC_DMA_ID(dma_id);
+ request.header = *(u64 *)(&header);
+
dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
return ret;
int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0};
int ret;
header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
header.primary |= IPC_INSTANCE_ID(instance_id);
+ request.header = *(u64 *)(&header);
dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret);
return ret;
u16 module_id, struct skl_ipc_dxstate_info *dx)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request;
int ret;
header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
header.primary |= IPC_MOD_ID(module_id);
+ request.header = *(u64 *)(&header);
+ request.data = dx;
+ request.size = sizeof(*dx);
+
dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
header.primary, header.extension);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
- dx, sizeof(*dx), NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
return ret;
struct skl_ipc_init_instance_msg *msg, void *param_data)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request;
int ret;
u32 *buffer = (u32 *)param_data;
/* param_block_size must be in dwords */
header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
header.extension |= IPC_DOMAIN(msg->domain);
+ request.header = *(u64 *)(&header);
+ request.data = param_data;
+ request.size = msg->param_data_size;
+
dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
header.primary, header.extension);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data,
- msg->param_data_size, NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev, "ipc: init instance failed\n");
struct skl_ipc_bind_unbind_msg *msg)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0};
u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
int ret;
header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
header.extension |= IPC_DST_QUEUE(msg->dst_queue);
header.extension |= IPC_SRC_QUEUE(msg->src_queue);
+ request.header = *(u64 *)(&header);
dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
header.extension);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev, "ipc: bind/unbind failed\n");
return ret;
u8 module_cnt, void *data)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request;
int ret;
header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
- ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, data,
- (sizeof(u16) * module_cnt));
+ request.header = *(u64 *)(&header);
+ request.data = data;
+ request.size = sizeof(u16) * module_cnt;
+
+ ret = sst_ipc_tx_message_nowait(ipc, request);
if (ret < 0)
dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
void *data)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request;
int ret;
header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
- (sizeof(u16) * module_cnt), NULL, 0);
+ request.header = *(u64 *)(&header);
+ request.data = data;
+ request.size = sizeof(u16) * module_cnt;
+
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0)
dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
struct skl_ipc_large_config_msg *msg, u32 *param)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request;
int ret = 0;
size_t sz_remaining, tx_size, data_offset;
header.primary, header.extension);
dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
(unsigned)data_offset, (unsigned)tx_size);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
- ((char *)param) + data_offset,
- tx_size, NULL, 0);
+
+ request.header = *(u64 *)(&header);
+ request.data = ((char *)param) + data_offset;
+ request.size = tx_size;
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
if (ret < 0) {
dev_err(ipc->dev,
"ipc: set large config fail, err: %d\n", ret);
struct skl_ipc_large_config_msg *msg, u32 *param)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0}, reply = {0};
int ret = 0;
size_t sz_remaining, rx_size, data_offset;
if (rx_size == sz_remaining)
header.extension |= IPC_FINAL_BLOCK(1);
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0,
- ((char *)param) + data_offset,
- msg->param_data_size);
+ request.header = *(u64 *)(&header);
+ reply.data = ((char *)param) + data_offset;
+ reply.size = msg->param_data_size;
+ ret = sst_ipc_tx_message_wait(ipc, request, &reply);
if (ret < 0) {
dev_err(ipc->dev,
"ipc: get large config fail, err: %d\n", ret);
u8 dma_id, u8 table_id, bool wait)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0};
int ret = 0;
header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY);
header.primary |= IPC_MOD_INSTANCE_ID(table_id);
header.primary |= IPC_MOD_ID(dma_id);
+ request.header = *(u64 *)(&header);
if (wait)
- ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
- NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_wait(ipc, request, NULL);
else
- ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, NULL, 0);
+ ret = sst_ipc_tx_message_nowait(ipc, request);
if (ret < 0)
dev_err(ipc->dev, "ipc: load lib failed\n");
int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
{
struct skl_ipc_header header = {0};
- u64 *ipc_header = (u64 *)(&header);
+ struct sst_ipc_message request = {0};
int ret;
header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
header.extension = IPC_D0IX_WAKE(msg->wake);
header.extension |= IPC_D0IX_STREAMING(msg->streaming);
+ request.header = *(u64 *)(&header);
dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
header.primary, header.extension);
/*
* Use the nopm IPC here as we dont want it checking for D0iX
*/
- ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0);
+ ret = sst_ipc_tx_message_nopm(ipc, request, NULL);
if (ret < 0)
dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);