diff options
-rw-r--r-- | sound/soc/intel/sst/sst.c | 165 |
1 files changed, 94 insertions, 71 deletions
diff --git a/sound/soc/intel/sst/sst.c b/sound/soc/intel/sst/sst.c index 55bb1f7764f..09d367aeaa1 100644 --- a/sound/soc/intel/sst/sst.c +++ b/sound/soc/intel/sst/sst.c @@ -243,6 +243,94 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx, return 0; } +int sst_context_init(struct intel_sst_drv *ctx) +{ + int ret = 0, i; + + if (!ctx->pdata) + return -EINVAL; + + if (!ctx->pdata->probe_data) + return -EINVAL; + + memcpy(&ctx->info, ctx->pdata->probe_data, sizeof(ctx->info)); + + ret = sst_driver_ops(ctx); + if (ret != 0) + return -EINVAL; + + sst_init_locks(ctx); + + /* pvt_id 0 reserved for async messages */ + ctx->pvt_id = 1; + ctx->stream_cnt = 0; + ctx->fw_in_mem = NULL; + /* we use memcpy, so set to 0 */ + ctx->use_dma = 0; + ctx->use_lli = 0; + + if (sst_workqueue_init(ctx)) + return -EINVAL; + + ctx->mailbox_recv_offset = ctx->pdata->ipc_info->mbox_recv_off; + ctx->ipc_reg.ipcx = SST_IPCX + ctx->pdata->ipc_info->ipc_offset; + ctx->ipc_reg.ipcd = SST_IPCD + ctx->pdata->ipc_info->ipc_offset; + + dev_info(ctx->dev, "Got drv data max stream %d\n", + ctx->info.max_streams); + + for (i = 1; i <= ctx->info.max_streams; i++) { + struct stream_info *stream = &ctx->streams[i]; + + memset(stream, 0, sizeof(*stream)); + stream->pipe_id = PIPE_RSVD; + mutex_init(&stream->lock); + } + + /* Register the ISR */ + ret = devm_request_threaded_irq(ctx->dev, ctx->irq_num, ctx->ops->interrupt, + ctx->ops->irq_thread, 0, SST_DRV_NAME, + ctx); + if (ret) + goto do_free_mem; + + dev_dbg(ctx->dev, "Registered IRQ %#x\n", ctx->irq_num); + + /* default intr are unmasked so set this as masked */ + sst_shim_write64(ctx->shim, SST_IMRX, 0xFFFF0038); + + ctx->qos = devm_kzalloc(ctx->dev, + sizeof(struct pm_qos_request), GFP_KERNEL); + if (!ctx->qos) { + ret = -ENOMEM; + goto do_free_mem; + } + pm_qos_add_request(ctx->qos, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + return 0; + +do_free_mem: + destroy_workqueue(ctx->post_msg_wq); + return ret; +} + +void sst_context_cleanup(struct intel_sst_drv *ctx) +{ + pm_runtime_get_noresume(ctx->dev); + pm_runtime_forbid(ctx->dev); + sst_unregister(ctx->dev); + sst_set_fw_state_locked(ctx, SST_SHUTDOWN); + flush_scheduled_work(); + destroy_workqueue(ctx->post_msg_wq); + pm_qos_remove_request(ctx->qos); + kfree(ctx->fw_sg_list.src); + kfree(ctx->fw_sg_list.dst); + ctx->fw_sg_list.list_len = 0; + kfree(ctx->fw_in_mem); + ctx->fw_in_mem = NULL; + sst_memcpy_free_resources(ctx); + ctx = NULL; +} /* * intel_sst_probe - PCI probe function @@ -254,9 +342,8 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx, static int intel_sst_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - int i, ret = 0; + int ret = 0; struct intel_sst_drv *sst_drv_ctx; - struct intel_sst_ops *ops; struct sst_platform_info *sst_pdata = pci->dev.platform_data; int ddr_base; @@ -266,43 +353,12 @@ static int intel_sst_probe(struct pci_dev *pci, if (ret < 0) return ret; - if (!sst_pdata) - return -EINVAL; - sst_drv_ctx->pdata = sst_pdata; - if (!sst_drv_ctx->pdata->probe_data) - return -EINVAL; - - memcpy(&sst_drv_ctx->info, sst_drv_ctx->pdata->probe_data, - sizeof(sst_drv_ctx->info)); - - if (0 != sst_driver_ops(sst_drv_ctx)) - return -EINVAL; - - ops = sst_drv_ctx->ops; - sst_init_locks(sst_drv_ctx); - - /* pvt_id 0 reserved for async messages */ - sst_drv_ctx->pvt_id = 1; - sst_drv_ctx->stream_cnt = 0; - sst_drv_ctx->fw_in_mem = NULL; - - /* we use memcpy, so set to 0 */ - sst_drv_ctx->use_dma = 0; - sst_drv_ctx->use_lli = 0; - - if (sst_workqueue_init(sst_drv_ctx)) - return -EINVAL; - dev_info(sst_drv_ctx->dev, "Got drv data max stream %d\n", - sst_drv_ctx->info.max_streams); - for (i = 1; i <= sst_drv_ctx->info.max_streams; i++) { - struct stream_info *stream = &sst_drv_ctx->streams[i]; + ret = sst_context_init(sst_drv_ctx); + if (ret < 0) + goto do_free_drv_ctx; - memset(stream, 0, sizeof(*stream)); - stream->pipe_id = PIPE_RSVD; - mutex_init(&stream->lock); - } /* Init the device */ ret = pcim_enable_device(pci); @@ -402,18 +458,6 @@ static int intel_sst_probe(struct pci_dev *pci, } sst_drv_ctx->irq_num = pci->irq; - /* Register the ISR */ - ret = devm_request_threaded_irq(&pci->dev, pci->irq, - sst_drv_ctx->ops->interrupt, - sst_drv_ctx->ops->irq_thread, 0, SST_DRV_NAME, - sst_drv_ctx); - if (ret) - goto do_release_regions; - dev_dbg(sst_drv_ctx->dev, "Registered IRQ 0x%x\n", pci->irq); - - /* default intr are unmasked so set this as masked */ - if (sst_drv_ctx->dev_id == SST_MRFLD_PCI_ID) - sst_shim_write64(sst_drv_ctx->shim, SST_IMRX, 0xFFFF0038); pci_set_drvdata(pci, sst_drv_ctx); pm_runtime_set_autosuspend_delay(sst_drv_ctx->dev, SST_SUSPEND_DELAY); @@ -421,14 +465,6 @@ static int intel_sst_probe(struct pci_dev *pci, pm_runtime_allow(sst_drv_ctx->dev); pm_runtime_put_noidle(sst_drv_ctx->dev); sst_register(sst_drv_ctx->dev); - sst_drv_ctx->qos = devm_kzalloc(&pci->dev, - sizeof(struct pm_qos_request), GFP_KERNEL); - if (!sst_drv_ctx->qos) { - ret = -ENOMEM; - goto do_release_regions; - } - pm_qos_add_request(sst_drv_ctx->qos, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); return ret; @@ -436,6 +472,7 @@ do_release_regions: pci_release_regions(pci); do_free_mem: destroy_workqueue(sst_drv_ctx->post_msg_wq); +do_free_drv_ctx: dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret); return ret; } @@ -452,22 +489,8 @@ static void intel_sst_remove(struct pci_dev *pci) { struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci); - pm_runtime_get_noresume(sst_drv_ctx->dev); - pm_runtime_forbid(sst_drv_ctx->dev); - sst_unregister(sst_drv_ctx->dev); + sst_context_cleanup(sst_drv_ctx); pci_dev_put(sst_drv_ctx->pci); - sst_set_fw_state_locked(sst_drv_ctx, SST_SHUTDOWN); - - flush_scheduled_work(); - destroy_workqueue(sst_drv_ctx->post_msg_wq); - pm_qos_remove_request(sst_drv_ctx->qos); - kfree(sst_drv_ctx->fw_sg_list.src); - kfree(sst_drv_ctx->fw_sg_list.dst); - sst_drv_ctx->fw_sg_list.list_len = 0; - kfree(sst_drv_ctx->fw_in_mem); - sst_drv_ctx->fw_in_mem = NULL; - sst_memcpy_free_resources(sst_drv_ctx); - sst_drv_ctx = NULL; pci_release_regions(pci); pci_set_drvdata(pci, NULL); } |