/** * sst_get_fw_info - Send msg to query for firmware configurations * @info: out param that holds the firmare configurations * * This function is called when the firmware configurations are queiried for */ int sst_get_fw_info(struct snd_sst_fw_info *info) { int retval = 0; struct ipc_post *msg = NULL; unsigned long irq_flags; pr_debug("sst_get_fw_info called\n"); if (sst_create_short_msg(&msg)) { pr_err("message creation failed\n"); return -ENOMEM; } sst_fill_header(&msg->header, IPC_IA_GET_FW_INFO, 0, 0); sst_drv_ctx->fw_info_blk.condition = false; sst_drv_ctx->fw_info_blk.ret_code = 0; sst_drv_ctx->fw_info_blk.on = true; sst_drv_ctx->fw_info_blk.data = info; spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags); list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list); spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags); sst_drv_ctx->ops->post_message(&sst_drv_ctx->ipc_post_msg_wq); retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->fw_info_blk); if (retval) { pr_err("error in fw_info = %d\n", retval); retval = -EIO; } return retval; }
/** * sst_resume_stream - Send msg for resuming stream * @str_id: stream ID * * This function is called by any function which wants to resume * an already paused stream. */ int sst_resume_stream(int str_id) { int retval = 0; struct ipc_post *msg = NULL; struct stream_info *str_info; struct intel_sst_ops *ops; unsigned long irq_flags; pr_debug("SST DBG:sst_resume_stream for %d\n", str_id); str_info = get_stream_info(str_id); if (!str_info) return -EINVAL; ops = sst_drv_ctx->ops; if (str_info->status == STREAM_RUNNING) return 0; if (str_info->status == STREAM_PAUSED) { if (str_info->ctrl_blk.on == true) { pr_err("SST ERR: control path in use\n"); return -EINVAL; } if (sst_create_short_msg(&msg)) { pr_err("SST ERR: mem allocation failed\n"); return -ENOMEM; } sst_fill_header(&msg->header, IPC_IA_RESUME_STREAM, 0, str_id); str_info->ctrl_blk.condition = false; str_info->ctrl_blk.ret_code = 0; str_info->ctrl_blk.on = true; spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags); list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list); spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags); ops->post_message(&sst_drv_ctx->ipc_post_msg_wq); retval = sst_wait_timeout(sst_drv_ctx, &str_info->ctrl_blk); if (!retval) { if (str_info->prev == STREAM_RUNNING) str_info->status = STREAM_RUNNING; else str_info->status = STREAM_INIT; str_info->prev = STREAM_PAUSED; } else if (retval == -SST_ERR_INVALID_STREAM_ID) { retval = -EINVAL; mutex_lock(&sst_drv_ctx->stream_lock); sst_clean_stream(str_info); mutex_unlock(&sst_drv_ctx->stream_lock); } } else { retval = -EBADRQC; pr_err("SST ERR: BADQRC for stream\n"); } return retval; }
/* * sst_send_sound_card_type - send sound card type * * this function sends the sound card type to sst dsp engine */ static void sst_send_sound_card_type(void) { struct ipc_post *msg = NULL; if (sst_create_short_msg(&msg)) return; sst_fill_header(&msg->header, IPC_IA_SET_PMIC_TYPE, 0, 0); msg->header.part.data = sst_drv_ctx->pmic_vendor; spin_lock(&sst_drv_ctx->list_spin_lock); 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; }
/** * sst_drain_stream - Send msg for draining stream * @str_id: stream ID * * This function is called by any function which wants to drain * a stream. */ int sst_drain_stream(int str_id) { int retval = 0; struct ipc_post *msg = NULL; struct stream_info *str_info; struct intel_sst_ops *ops; unsigned long irq_flags; pr_debug("SST DBG:sst_drain_stream for %d\n", str_id); str_info = get_stream_info(str_id); if (!str_info) return -EINVAL; ops = sst_drv_ctx->ops; if (str_info->status != STREAM_RUNNING && str_info->status != STREAM_INIT && str_info->status != STREAM_PAUSED) { pr_err("SST ERR: BADQRC for stream = %d\n", str_info->status); return -EBADRQC; } if (str_info->status == STREAM_INIT) { if (sst_create_short_msg(&msg)) { pr_err("SST ERR: mem allocation failed\n"); return -ENOMEM; } sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM, 0, str_id); spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags); list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list); spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags); ops->post_message(&sst_drv_ctx->ipc_post_msg_wq); str_info->data_blk.condition = false; str_info->data_blk.ret_code = 0; str_info->data_blk.on = true; retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk); } return retval; }
/** * sst_free_stream - Frees a stream * @str_id: stream ID * * This function is called by any function which wants to free * a stream. */ int sst_free_stream(int str_id) { int retval = 0; struct ipc_post *msg = NULL; struct stream_info *str_info; struct intel_sst_ops *ops; unsigned long irq_flags; pr_debug("SST DBG:sst_free_stream for %d\n", str_id); mutex_lock(&sst_drv_ctx->sst_lock); if (sst_drv_ctx->sst_state == SST_UN_INIT) { mutex_unlock(&sst_drv_ctx->sst_lock); return -ENODEV; } mutex_unlock(&sst_drv_ctx->sst_lock); str_info = get_stream_info(str_id); if (!str_info) return -EINVAL; ops = sst_drv_ctx->ops; mutex_lock(&str_info->lock); if (str_info->status != STREAM_UN_INIT) { str_info->prev = str_info->status; str_info->status = STREAM_UN_INIT; mutex_unlock(&str_info->lock); if (str_info->ctrl_blk.on == true) { pr_err("SST ERR: control path in use\n"); return -EINVAL; } if (sst_create_short_msg(&msg)) { pr_err("SST ERR: mem allocation failed\n"); return -ENOMEM; } if (sst_drv_ctx->pci_id == SST_MRFLD_PCI_ID) sst_fill_header_mrfld(&msg->mrfld_header, IPC_IA_FREE_STREAM, 0, str_id); else sst_fill_header(&msg->header, IPC_IA_FREE_STREAM, 0, str_id); spin_lock_irqsave(&sst_drv_ctx->ipc_spin_lock, irq_flags); list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list); spin_unlock_irqrestore(&sst_drv_ctx->ipc_spin_lock, irq_flags); if (str_info->data_blk.on == true) { str_info->data_blk.condition = true; str_info->data_blk.ret_code = 0; wake_up(&sst_drv_ctx->wait_queue); } str_info->ctrl_blk.on = true; str_info->ctrl_blk.condition = false; ops->post_message(&sst_drv_ctx->ipc_post_msg_wq); retval = sst_wait_timeout(sst_drv_ctx, &str_info->ctrl_blk); pr_debug("sst: wait for free returned %d\n", retval); mutex_lock(&sst_drv_ctx->stream_lock); sst_clean_stream(str_info); mutex_unlock(&sst_drv_ctx->stream_lock); pr_debug("SST DBG:Stream freed\n"); } else { mutex_unlock(&str_info->lock); retval = -EBADRQC; pr_debug("SST DBG:BADQRC for stream\n"); } return retval; }