struct snd_sst_mmap_buff_entry *tmp_buf;
pr_debug("called for str_id %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
+ stream = get_stream_info(str_id);
+ if (!stream)
return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
if (stream->mmapped != true)
return -EIO;
struct iovec iovec;
unsigned long nr_segs;
- retval = sst_validate_strid(str_id);
- if (retval)
+ stream = get_stream_info(str_id);
+ if (!stream)
return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
if (stream->mmapped == true) {
pr_warn("user write and stream is mapped\n");
return -EIO;
return -EINVAL;
pr_debug("called for str_id %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
+ stream = get_stream_info(str_id);
+ if (!stream)
return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
if (stream->mmapped == true)
return -EIO;
if (stream->status == STREAM_UN_INIT ||
}
pr_debug("called for str_id %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
+ stream = get_stream_info(str_id);
+ if (!stream)
return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
if (stream->mmapped == true)
return -EIO;
if (stream->status == STREAM_UN_INIT ||
retval = -EINVAL;
break;
}
- retval = sst_validate_strid(str_id);
- if (retval)
+ stream = get_stream_info(str_id);
+ if (!stream) {
+ retval = -EINVAL;
break;
- stream = &sst_drv_ctx->streams[str_id];
+ }
mutex_lock(&stream->lock);
if (stream->status == STREAM_INIT &&
stream->need_draining != true) {
int sst_set_vol(struct snd_sst_vol *set_vol);
int sst_set_mute(struct snd_sst_mute *set_mute);
-
+int sst_sync_post_message(struct ipc_post *msg);
void sst_post_message(struct work_struct *work);
void sst_process_message(struct work_struct *work);
void sst_process_reply(struct work_struct *work);
sst_drv_ctx->sst_state = sst_state;
mutex_unlock(&sst_drv_ctx->sst_lock);
}
-
+static inline struct stream_info *get_stream_info(int str_id)
+{
+ if (sst_validate_strid(str_id))
+ return NULL;
+ return &sst_drv_ctx->streams[str_id];
+}
int register_sst(struct device *);
int unregister_sst(struct device *);
#endif /* __INTEL_SST_COMMON_H__ */
void free_stream_context(unsigned int str_id)
{
struct stream_info *stream;
-
- if (!sst_validate_strid(str_id)) {
+ stream = get_stream_info(str_id);
+ if (stream) {
/* str_id is valid, so stream is alloacted */
- stream = &sst_drv_ctx->streams[str_id];
if (sst_free_stream(str_id))
sst_clean_stream(&sst_drv_ctx->streams[str_id]);
if (stream->ops == STREAM_OPS_PLAYBACK ||
struct stream_info *stream;
pr_debug("stream free called\n");
- if (sst_validate_strid(str_id))
+ stream = get_stream_info(str_id);
+ if (!stream)
return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
free_stream_context(str_id);
stream->pcm_substream = NULL;
stream->status = STREAM_UN_INIT;
return 0;
}
+int sst_send_sync_msg(int ipc, int str_id)
+{
+ struct ipc_post *msg = NULL;
+
+ if (sst_create_short_msg(&msg))
+ return -ENOMEM;
+ sst_fill_header(&msg->header, ipc, 0, str_id);
+ return sst_sync_post_message(msg);
+}
+
/*
* sst_device_control - Set Control params
*
switch (cmd) {
case SST_SND_PAUSE:
- case SST_SND_RESUME:
- case SST_SND_DROP:
- case SST_SND_START: {
+ case SST_SND_RESUME: {
struct mad_ops_wq *work = kzalloc(sizeof(*work), GFP_ATOMIC);
if (!work)
return -ENOMEM;
queue_work(sst_drv_ctx->mad_wq, &work->wq);
break;
}
+ case SST_SND_START: {
+ struct stream_info *str_info;
+ int ipc;
+ str_id = *(int *)arg;
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
+ ipc = IPC_IA_START_STREAM;
+ str_info->prev = str_info->status;
+ str_info->status = STREAM_RUNNING;
+ retval = sst_send_sync_msg(ipc, str_id);
+ break;
+ }
+ case SST_SND_DROP: {
+ struct stream_info *str_info;
+ int ipc;
+ str_id = *(int *)arg;
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
+ ipc = IPC_IA_DROP_STREAM;
+ str_info->prev = STREAM_UN_INIT;
+ str_info->status = STREAM_INIT;
+ retval = sst_send_sync_msg(ipc, str_id);
+ break;
+ }
case SST_SND_STREAM_INIT: {
struct pcm_stream_info *str_info;
struct stream_info *stream;
pr_debug("stream init called\n");
str_info = (struct pcm_stream_info *)arg;
str_id = str_info->str_id;
- retval = sst_validate_strid(str_id);
- if (retval)
+ stream = get_stream_info(str_id);
+ if (!stream) {
+ retval = -EINVAL;
break;
-
- stream = &sst_drv_ctx->streams[str_id];
+ }
pr_debug("setting the period ptrs\n");
stream->pcm_substream = str_info->mad_substream;
stream->period_elapsed = str_info->period_elapsed;
stream_info = (struct pcm_stream_info *)arg;
str_id = stream_info->str_id;
- retval = sst_validate_strid(str_id);
- if (retval)
+ stream = get_stream_info(str_id);
+ if (!stream) {
+ retval = -EINVAL;
break;
- stream = &sst_drv_ctx->streams[str_id];
+ }
if (!stream->pcm_substream)
break;
#include <linux/pci.h>
#include <linux/firmware.h>
#include <linux/sched.h>
+#include <linux/delay.h>
#include <sound/intel_sst_ioctl.h>
#include "../sst_platform.h"
#include "intel_sst_fw_ipc.h"
kfree(msg);
}
+/* use this for trigger ops to post syncronous msgs
+ */
+int sst_sync_post_message(struct ipc_post *msg)
+{
+ union ipc_header header;
+ unsigned int loop_count = 0;
+ int retval = 0;
+
+ pr_debug("sst: sync post message called\n");
+ spin_lock(&sst_drv_ctx->list_spin_lock);
+
+ /* check busy bit */
+ header.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCX);
+ while (header.part.busy) {
+ if (loop_count > 10) {
+ pr_err("busy wait failed, cant send this msg\n");
+ retval = -EBUSY;
+ goto out;
+ }
+ usleep_range(5000, 5000);
+ loop_count++;
+ header.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCX);
+ };
+ pr_debug("sst: Post message: header = %x\n", msg->header.full);
+ pr_debug("sst: size: = %x\n", msg->header.part.data);
+ if (msg->header.part.large)
+ memcpy_toio(sst_drv_ctx->mailbox + SST_MAILBOX_SEND,
+ msg->mailbox_data, msg->header.part.data);
+
+ sst_shim_write(sst_drv_ctx->shim, SST_IPCX, msg->header.full);
+
+out:
+ spin_unlock(&sst_drv_ctx->list_spin_lock);
+ kfree(msg->mailbox_data);
+ kfree(msg);
+ return retval;
+}
+
/*
* sst_clear_interrupt - clear the SST FW interrupt
*
if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
struct stream_info *stream ;
- if (sst_validate_strid(str_id)) {
+ stream = get_stream_info(str_id);
+ if (!stream) {
pr_err("strid %d invalid\n", str_id);
break;
}
/* call sst_play_frame */
- stream = &sst_drv_ctx->streams[str_id];
pr_debug("sst_play_frames for %d\n",
msg->header.part.str_id);
mutex_lock(&sst_drv_ctx->streams[str_id].lock);
if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) {
struct stream_info *stream;
/* call sst_capture_frame */
- if (sst_validate_strid(str_id)) {
+ stream = get_stream_info(str_id);
+ if (!stream) {
pr_err("str id %d invalid\n", str_id);
break;
}
- stream = &sst_drv_ctx->streams[str_id];
pr_debug("sst_capture_frames for %d\n",
msg->header.part.str_id);
mutex_lock(&stream->lock);
break;
case IPC_IA_GET_STREAM_PARAMS:
- if (sst_validate_strid(str_id)) {
+ str_info = get_stream_info(str_id);
+ if (!str_info) {
pr_err("stream id %d invalid\n", str_id);
break;
}
- str_info = &sst_drv_ctx->streams[str_id];
if (msg->header.part.large) {
pr_debug("Get stream large success\n");
memcpy_fromio(str_info->ctrl_blk.data,
}
break;
case IPC_IA_DECODE_FRAMES:
- if (sst_validate_strid(str_id)) {
+ str_info = get_stream_info(str_id);
+ if (!str_info) {
pr_err("stream id %d invalid\n", str_id);
break;
}
- str_info = &sst_drv_ctx->streams[str_id];
if (msg->header.part.large) {
pr_debug("Msg succeeded %x\n",
msg->header.part.msg_id);
}
break;
case IPC_IA_DRAIN_STREAM:
- if (sst_validate_strid(str_id)) {
+ str_info = get_stream_info(str_id);
+ if (!str_info) {
pr_err("stream id %d invalid\n", str_id);
break;
}
- str_info = &sst_drv_ctx->streams[str_id];
if (!msg->header.part.data) {
pr_debug("Msg succeeded %x\n",
msg->header.part.msg_id);
break;
case IPC_IA_DROP_STREAM:
- if (sst_validate_strid(str_id)) {
+ str_info = get_stream_info(str_id);
+ if (!str_info) {
pr_err("str id %d invalid\n", str_id);
break;
}
- str_info = &sst_drv_ctx->streams[str_id];
if (msg->header.part.large) {
struct snd_sst_drop_response *drop_resp =
(struct snd_sst_drop_response *)msg->mailbox;
case IPC_IA_PAUSE_STREAM:
case IPC_IA_RESUME_STREAM:
case IPC_IA_SET_STREAM_PARAMS:
- str_info = &sst_drv_ctx->streams[str_id];
+ str_info = get_stream_info(str_id);
+ if (!str_info) {
+ pr_err(" stream id %d invalid\n", str_id);
+ break;
+ }
if (!msg->header.part.data) {
pr_debug("Msg succeeded %x\n",
msg->header.part.msg_id);
msg->header.part.data);
str_info->ctrl_blk.ret_code = -msg->header.part.data;
}
- if (sst_validate_strid(str_id)) {
- pr_err(" stream id %d invalid\n", str_id);
- break;
- }
if (str_info->ctrl_blk.on == true) {
str_info->ctrl_blk.on = false;
*/
int sst_start_stream(int str_id)
{
- int retval = 0;
struct ipc_post *msg = NULL;
struct stream_info *str_info;
pr_debug("sst_start_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
if (str_info->status != STREAM_INIT)
return -EBADRQC;
if (sst_create_short_msg(&msg))
list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
spin_unlock(&sst_drv_ctx->list_spin_lock);
sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
- return retval;
+ return 0;
}
/*
struct stream_info *str_info;
pr_debug("SST DBG:sst_pause_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
if (str_info->status == STREAM_PAUSED)
return 0;
if (str_info->status == STREAM_RUNNING ||
struct stream_info *str_info;
pr_debug("SST DBG:sst_resume_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
if (str_info->status == STREAM_RUNNING)
return 0;
if (str_info->status == STREAM_PAUSED) {
struct stream_info *str_info;
pr_debug("SST DBG:sst_drop_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
mutex_lock(&str_info->lock);
if (str_info->status != STREAM_UN_INIT &&
struct stream_info *str_info;
pr_debug("SST DBG:sst_drain_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
if (str_info->status != STREAM_RUNNING &&
str_info->status != STREAM_INIT &&
struct stream_info *str_info;
pr_debug("SST DBG:sst_free_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- str_info = &sst_drv_ctx->streams[str_id];
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
mutex_lock(&str_info->lock);
if (str_info->status != STREAM_UN_INIT) {
struct snd_sst_fw_get_stream_params *fw_params;
pr_debug("get_stream for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
- str_info = &sst_drv_ctx->streams[str_id];
if (str_info->status != STREAM_UN_INIT) {
if (str_info->ctrl_blk.on == true) {
pr_err("control path in use\n");
pr_err("Invalid operation\n");
return -EINVAL;
}
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
pr_debug("set_stream for %d\n", str_id);
- str_info = &sst_drv_ctx->streams[str_id];
if (sst_drv_ctx->streams[str_id].status == STREAM_INIT) {
if (str_info->ctrl_blk.on == true) {
pr_err("control path in use\n");
*/
int sst_play_frame(int str_id)
{
- int retval = 0;
struct ipc_post *msg = NULL;
struct sst_frame_info sg_list = {0};
struct sst_stream_bufs *kbufs = NULL, *_kbufs;
struct stream_info *stream;
pr_debug("play frame for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
+ stream = get_stream_info(str_id);
+ if (!stream)
+ return -EINVAL;
- stream = &sst_drv_ctx->streams[str_id];
/* clear prev sent buffers */
list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
if (kbufs->in_use == true) {
*/
int sst_capture_frame(int str_id)
{
- int retval = 0;
struct ipc_post *msg = NULL;
struct sst_frame_info sg_list = {0};
struct sst_stream_bufs *kbufs = NULL, *_kbufs;
pr_debug("capture frame for %d\n", str_id);
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
- stream = &sst_drv_ctx->streams[str_id];
+ stream = get_stream_info(str_id);
+ if (!stream)
+ return -EINVAL;
/* clear prev sent buffers */
list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) {
if (kbufs->in_use == true) {
pr_debug("Powering_down_PMIC...\n");
- retval = sst_validate_strid(str_id);
- if (retval)
- return retval;
+ str_info = get_stream_info(str_id);
+ if (!str_info)
+ return -EINVAL;
- str_info = &sst_drv_ctx->streams[str_id];
if (str_info->status != STREAM_INIT) {
pr_err("invalid stream state = %d\n",
str_info->status);