void sst_save_dsp_context(void) { struct snd_sst_ctxt_params fw_context; unsigned int pvt_id, i; struct ipc_post *msg = NULL; /*check cpu type*/ if (sst_drv_ctx->pci_id != SST_MFLD_PCI_ID) return; /*not supported for rest*/ if (sst_drv_ctx->sst_state != SST_FW_RUNNING) { pr_debug("fw not running no context save ...\n"); return; } /*send msg to fw*/ if (sst_create_large_msg(&msg)) return; pvt_id = sst_assign_pvt_id(sst_drv_ctx); i = sst_get_block_stream(sst_drv_ctx); sst_drv_ctx->alloc_block[i].sst_id = pvt_id; sst_fill_header(&msg->header, IPC_IA_GET_FW_CTXT, 1, pvt_id); msg->header.part.data = sizeof(fw_context) + sizeof(u32); fw_context.address = virt_to_phys((void *)sst_drv_ctx->fw_cntx); fw_context.size = FW_CONTEXT_MEM; memcpy(msg->mailbox_data, &msg->header, sizeof(u32)); memcpy(msg->mailbox_data + sizeof(u32), &fw_context, sizeof(fw_context)); 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); /*wait for reply*/ if (sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i])) pr_debug("err fw context save timeout ...\n"); sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; pr_debug("fw context saved ...\n"); return; }
/*This function is called when any codec/post processing library needs to be downloaded*/ static int sst_download_library(const struct firmware *fw_lib, struct snd_sst_lib_download_info *lib) { /* send IPC message and wait */ int i; u8 pvt_id; struct ipc_post *msg = NULL; union config_status_reg csr; struct snd_sst_str_type str_type = {0}; int retval = 0; if (sst_create_large_msg(&msg)) return -ENOMEM; pvt_id = sst_assign_pvt_id(sst_drv_ctx); i = sst_get_block_stream(sst_drv_ctx); pr_debug("alloc block allocated = %d, pvt_id %d\n", i, pvt_id); if (i < 0) { kfree(msg); return -ENOMEM; } sst_drv_ctx->alloc_block[i].sst_id = pvt_id; sst_fill_header(&msg->header, IPC_IA_PREP_LIB_DNLD, 1, pvt_id); msg->header.part.data = sizeof(u32) + sizeof(str_type); str_type.codec_type = lib->dload_lib.lib_info.lib_type; /*str_type.pvt_id = pvt_id;*/ memcpy(msg->mailbox_data, &msg->header, sizeof(u32)); memcpy(msg->mailbox_data + sizeof(u32), &str_type, sizeof(str_type)); 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); retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]); if (retval) { /* error */ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; pr_err("Prep codec downloaded failed %d\n", retval); return -EIO; } pr_debug("FW responded, ready for download now...\n"); /* downloading on success */ mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_FW_LOADED; mutex_unlock(&sst_drv_ctx->sst_lock); csr.full = readl(sst_drv_ctx->shim + SST_CSR); csr.part.run_stall = 1; sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR); csr.part.bypass = 0x7; sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); sst_parse_fw_image(fw_lib); /* set the FW to running again */ csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR); csr.part.bypass = 0x0; sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR); csr.part.run_stall = 0; sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); /* send download complete and wait */ if (sst_create_large_msg(&msg)) { sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; return -ENOMEM; } sst_fill_header(&msg->header, IPC_IA_LIB_DNLD_CMPLT, 1, pvt_id); sst_drv_ctx->alloc_block[i].sst_id = pvt_id; msg->header.part.data = sizeof(u32) + sizeof(*lib); lib->pvt_id = pvt_id; memcpy(msg->mailbox_data, &msg->header, sizeof(u32)); memcpy(msg->mailbox_data + sizeof(u32), lib, sizeof(*lib)); 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); pr_debug("Waiting for FW response Download complete\n"); sst_drv_ctx->alloc_block[i].ops_block.condition = false; retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]); if (retval) { /* error */ mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_UN_INIT; mutex_unlock(&sst_drv_ctx->sst_lock); sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; return -EIO; } pr_debug("FW success on Download complete\n"); sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_FW_RUNNING; mutex_unlock(&sst_drv_ctx->sst_lock); return 0; }
/* * sst_get_stream - this function prepares for stream allocation * * @str_param : stream param */ int sst_get_stream(struct snd_sst_params *str_param) { int i, retval; struct stream_info *str_info; struct snd_sst_lib_download *lib_dnld; /* stream is not allocated, we are allocating */ retval = sst_get_stream_allocated(str_param, &lib_dnld); if (retval == -(SST_LIB_ERR_LIB_DNLD_REQUIRED)) { /* codec download is required */ struct snd_sst_alloc_response *response; pr_debug("Codec is required.... trying that\n"); if (lib_dnld == NULL) { pr_err("lib download null!!! abort\n"); return -EIO; } i = sst_get_block_stream(sst_drv_ctx); response = sst_drv_ctx->alloc_block[i].ops_block.data; pr_debug("alloc block allocated = %d\n", i); if (i < 0) { kfree(lib_dnld); return -ENOMEM; } retval = sst_load_library(lib_dnld, str_param->ops); kfree(lib_dnld); sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; if (!retval) { pr_debug("codec was downloaded successfully\n"); retval = sst_get_stream_allocated(str_param, &lib_dnld); if (retval <= 0) goto err; pr_debug("Alloc done stream id %d\n", retval); } else { pr_debug("codec download failed\n"); retval = -EIO; goto err; } } else if (retval <= 0) goto err; /*else set_port_params(str_param, str_param->ops);*/ /* store sampling freq */ str_info = &sst_drv_ctx->streams[retval]; str_info->sfreq = sst_get_sfreq(str_param); /* power on the analog, if reqd */ if (str_param->ops == STREAM_OPS_PLAYBACK || str_param->ops == STREAM_OPS_PLAYBACK_DRM) { if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) sst_drv_ctx->scard_ops->power_up_pmic_pb( sst_drv_ctx->pmic_port_instance); else sst_drv_ctx->scard_ops->power_up_pmic_pb( str_info->device); /*Only if the playback is MP3 - Send a message*/ sst_drv_ctx->pb_streams++; } else if (str_param->ops == STREAM_OPS_CAPTURE) { sst_drv_ctx->scard_ops->power_up_pmic_cp( sst_drv_ctx->pmic_port_instance); /*Send a messageif not sent already*/ sst_drv_ctx->cp_streams++; } err: return retval; }