diff options
author | Subhransu S. Prusty <subhransu.s.prusty@intel.com> | 2014-10-30 06:51:48 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-10-31 12:57:32 -0400 |
commit | 250454d8fe65680b26f2917b806e2caf49126a01 (patch) | |
tree | c297bba913e1911fa8ae69bbecbfcabd6b6b3c45 | |
parent | 2559d9928f36f3c0bfb4ded9bb47d47b36337b09 (diff) |
ASoC: Intel: modularize driver probe and remove
The driver probe which initializes driver and remove which cleans up can be
shared with APCI as well, so move them to common init_context and
cleanup_context routines which can be used by ACPI as well
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-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 55bb1f7764f9..09d367aeaa15 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, | |||
243 | return 0; | 243 | return 0; |
244 | } | 244 | } |
245 | 245 | ||
246 | int sst_context_init(struct intel_sst_drv *ctx) | ||
247 | { | ||
248 | int ret = 0, i; | ||
249 | |||
250 | if (!ctx->pdata) | ||
251 | return -EINVAL; | ||
252 | |||
253 | if (!ctx->pdata->probe_data) | ||
254 | return -EINVAL; | ||
255 | |||
256 | memcpy(&ctx->info, ctx->pdata->probe_data, sizeof(ctx->info)); | ||
257 | |||
258 | ret = sst_driver_ops(ctx); | ||
259 | if (ret != 0) | ||
260 | return -EINVAL; | ||
261 | |||
262 | sst_init_locks(ctx); | ||
263 | |||
264 | /* pvt_id 0 reserved for async messages */ | ||
265 | ctx->pvt_id = 1; | ||
266 | ctx->stream_cnt = 0; | ||
267 | ctx->fw_in_mem = NULL; | ||
268 | /* we use memcpy, so set to 0 */ | ||
269 | ctx->use_dma = 0; | ||
270 | ctx->use_lli = 0; | ||
271 | |||
272 | if (sst_workqueue_init(ctx)) | ||
273 | return -EINVAL; | ||
274 | |||
275 | ctx->mailbox_recv_offset = ctx->pdata->ipc_info->mbox_recv_off; | ||
276 | ctx->ipc_reg.ipcx = SST_IPCX + ctx->pdata->ipc_info->ipc_offset; | ||
277 | ctx->ipc_reg.ipcd = SST_IPCD + ctx->pdata->ipc_info->ipc_offset; | ||
278 | |||
279 | dev_info(ctx->dev, "Got drv data max stream %d\n", | ||
280 | ctx->info.max_streams); | ||
281 | |||
282 | for (i = 1; i <= ctx->info.max_streams; i++) { | ||
283 | struct stream_info *stream = &ctx->streams[i]; | ||
284 | |||
285 | memset(stream, 0, sizeof(*stream)); | ||
286 | stream->pipe_id = PIPE_RSVD; | ||
287 | mutex_init(&stream->lock); | ||
288 | } | ||
289 | |||
290 | /* Register the ISR */ | ||
291 | ret = devm_request_threaded_irq(ctx->dev, ctx->irq_num, ctx->ops->interrupt, | ||
292 | ctx->ops->irq_thread, 0, SST_DRV_NAME, | ||
293 | ctx); | ||
294 | if (ret) | ||
295 | goto do_free_mem; | ||
296 | |||
297 | dev_dbg(ctx->dev, "Registered IRQ %#x\n", ctx->irq_num); | ||
298 | |||
299 | /* default intr are unmasked so set this as masked */ | ||
300 | sst_shim_write64(ctx->shim, SST_IMRX, 0xFFFF0038); | ||
301 | |||
302 | ctx->qos = devm_kzalloc(ctx->dev, | ||
303 | sizeof(struct pm_qos_request), GFP_KERNEL); | ||
304 | if (!ctx->qos) { | ||
305 | ret = -ENOMEM; | ||
306 | goto do_free_mem; | ||
307 | } | ||
308 | pm_qos_add_request(ctx->qos, PM_QOS_CPU_DMA_LATENCY, | ||
309 | PM_QOS_DEFAULT_VALUE); | ||
310 | return 0; | ||
311 | |||
312 | do_free_mem: | ||
313 | destroy_workqueue(ctx->post_msg_wq); | ||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | void sst_context_cleanup(struct intel_sst_drv *ctx) | ||
318 | { | ||
319 | pm_runtime_get_noresume(ctx->dev); | ||
320 | pm_runtime_forbid(ctx->dev); | ||
321 | sst_unregister(ctx->dev); | ||
322 | sst_set_fw_state_locked(ctx, SST_SHUTDOWN); | ||
323 | flush_scheduled_work(); | ||
324 | destroy_workqueue(ctx->post_msg_wq); | ||
325 | pm_qos_remove_request(ctx->qos); | ||
326 | kfree(ctx->fw_sg_list.src); | ||
327 | kfree(ctx->fw_sg_list.dst); | ||
328 | ctx->fw_sg_list.list_len = 0; | ||
329 | kfree(ctx->fw_in_mem); | ||
330 | ctx->fw_in_mem = NULL; | ||
331 | sst_memcpy_free_resources(ctx); | ||
332 | ctx = NULL; | ||
333 | } | ||
246 | 334 | ||
247 | /* | 335 | /* |
248 | * intel_sst_probe - PCI probe function | 336 | * intel_sst_probe - PCI probe function |
@@ -254,9 +342,8 @@ int sst_alloc_drv_context(struct intel_sst_drv **ctx, | |||
254 | static int intel_sst_probe(struct pci_dev *pci, | 342 | static int intel_sst_probe(struct pci_dev *pci, |
255 | const struct pci_device_id *pci_id) | 343 | const struct pci_device_id *pci_id) |
256 | { | 344 | { |
257 | int i, ret = 0; | 345 | int ret = 0; |
258 | struct intel_sst_drv *sst_drv_ctx; | 346 | struct intel_sst_drv *sst_drv_ctx; |
259 | struct intel_sst_ops *ops; | ||
260 | struct sst_platform_info *sst_pdata = pci->dev.platform_data; | 347 | struct sst_platform_info *sst_pdata = pci->dev.platform_data; |
261 | int ddr_base; | 348 | int ddr_base; |
262 | 349 | ||
@@ -266,43 +353,12 @@ static int intel_sst_probe(struct pci_dev *pci, | |||
266 | if (ret < 0) | 353 | if (ret < 0) |
267 | return ret; | 354 | return ret; |
268 | 355 | ||
269 | if (!sst_pdata) | ||
270 | return -EINVAL; | ||
271 | |||
272 | sst_drv_ctx->pdata = sst_pdata; | 356 | sst_drv_ctx->pdata = sst_pdata; |
273 | if (!sst_drv_ctx->pdata->probe_data) | ||
274 | return -EINVAL; | ||
275 | |||
276 | memcpy(&sst_drv_ctx->info, sst_drv_ctx->pdata->probe_data, | ||
277 | sizeof(sst_drv_ctx->info)); | ||
278 | |||
279 | if (0 != sst_driver_ops(sst_drv_ctx)) | ||
280 | return -EINVAL; | ||
281 | |||
282 | ops = sst_drv_ctx->ops; | ||
283 | sst_init_locks(sst_drv_ctx); | ||
284 | |||
285 | /* pvt_id 0 reserved for async messages */ | ||
286 | sst_drv_ctx->pvt_id = 1; | ||
287 | sst_drv_ctx->stream_cnt = 0; | ||
288 | sst_drv_ctx->fw_in_mem = NULL; | ||
289 | |||
290 | /* we use memcpy, so set to 0 */ | ||
291 | sst_drv_ctx->use_dma = 0; | ||
292 | sst_drv_ctx->use_lli = 0; | ||
293 | |||
294 | if (sst_workqueue_init(sst_drv_ctx)) | ||
295 | return -EINVAL; | ||
296 | 357 | ||
297 | dev_info(sst_drv_ctx->dev, "Got drv data max stream %d\n", | 358 | ret = sst_context_init(sst_drv_ctx); |
298 | sst_drv_ctx->info.max_streams); | 359 | if (ret < 0) |
299 | for (i = 1; i <= sst_drv_ctx->info.max_streams; i++) { | 360 | goto do_free_drv_ctx; |
300 | struct stream_info *stream = &sst_drv_ctx->streams[i]; | ||
301 | 361 | ||
302 | memset(stream, 0, sizeof(*stream)); | ||
303 | stream->pipe_id = PIPE_RSVD; | ||
304 | mutex_init(&stream->lock); | ||
305 | } | ||
306 | 362 | ||
307 | /* Init the device */ | 363 | /* Init the device */ |
308 | ret = pcim_enable_device(pci); | 364 | ret = pcim_enable_device(pci); |
@@ -402,18 +458,6 @@ static int intel_sst_probe(struct pci_dev *pci, | |||
402 | } | 458 | } |
403 | 459 | ||
404 | sst_drv_ctx->irq_num = pci->irq; | 460 | sst_drv_ctx->irq_num = pci->irq; |
405 | /* Register the ISR */ | ||
406 | ret = devm_request_threaded_irq(&pci->dev, pci->irq, | ||
407 | sst_drv_ctx->ops->interrupt, | ||
408 | sst_drv_ctx->ops->irq_thread, 0, SST_DRV_NAME, | ||
409 | sst_drv_ctx); | ||
410 | if (ret) | ||
411 | goto do_release_regions; | ||
412 | dev_dbg(sst_drv_ctx->dev, "Registered IRQ 0x%x\n", pci->irq); | ||
413 | |||
414 | /* default intr are unmasked so set this as masked */ | ||
415 | if (sst_drv_ctx->dev_id == SST_MRFLD_PCI_ID) | ||
416 | sst_shim_write64(sst_drv_ctx->shim, SST_IMRX, 0xFFFF0038); | ||
417 | 461 | ||
418 | pci_set_drvdata(pci, sst_drv_ctx); | 462 | pci_set_drvdata(pci, sst_drv_ctx); |
419 | pm_runtime_set_autosuspend_delay(sst_drv_ctx->dev, SST_SUSPEND_DELAY); | 463 | 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, | |||
421 | pm_runtime_allow(sst_drv_ctx->dev); | 465 | pm_runtime_allow(sst_drv_ctx->dev); |
422 | pm_runtime_put_noidle(sst_drv_ctx->dev); | 466 | pm_runtime_put_noidle(sst_drv_ctx->dev); |
423 | sst_register(sst_drv_ctx->dev); | 467 | sst_register(sst_drv_ctx->dev); |
424 | sst_drv_ctx->qos = devm_kzalloc(&pci->dev, | ||
425 | sizeof(struct pm_qos_request), GFP_KERNEL); | ||
426 | if (!sst_drv_ctx->qos) { | ||
427 | ret = -ENOMEM; | ||
428 | goto do_release_regions; | ||
429 | } | ||
430 | pm_qos_add_request(sst_drv_ctx->qos, PM_QOS_CPU_DMA_LATENCY, | ||
431 | PM_QOS_DEFAULT_VALUE); | ||
432 | 468 | ||
433 | return ret; | 469 | return ret; |
434 | 470 | ||
@@ -436,6 +472,7 @@ do_release_regions: | |||
436 | pci_release_regions(pci); | 472 | pci_release_regions(pci); |
437 | do_free_mem: | 473 | do_free_mem: |
438 | destroy_workqueue(sst_drv_ctx->post_msg_wq); | 474 | destroy_workqueue(sst_drv_ctx->post_msg_wq); |
475 | do_free_drv_ctx: | ||
439 | dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret); | 476 | dev_err(sst_drv_ctx->dev, "Probe failed with %d\n", ret); |
440 | return ret; | 477 | return ret; |
441 | } | 478 | } |
@@ -452,22 +489,8 @@ static void intel_sst_remove(struct pci_dev *pci) | |||
452 | { | 489 | { |
453 | struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci); | 490 | struct intel_sst_drv *sst_drv_ctx = pci_get_drvdata(pci); |
454 | 491 | ||
455 | pm_runtime_get_noresume(sst_drv_ctx->dev); | 492 | sst_context_cleanup(sst_drv_ctx); |
456 | pm_runtime_forbid(sst_drv_ctx->dev); | ||
457 | sst_unregister(sst_drv_ctx->dev); | ||
458 | pci_dev_put(sst_drv_ctx->pci); | 493 | pci_dev_put(sst_drv_ctx->pci); |
459 | sst_set_fw_state_locked(sst_drv_ctx, SST_SHUTDOWN); | ||
460 | |||
461 | flush_scheduled_work(); | ||
462 | destroy_workqueue(sst_drv_ctx->post_msg_wq); | ||
463 | pm_qos_remove_request(sst_drv_ctx->qos); | ||
464 | kfree(sst_drv_ctx->fw_sg_list.src); | ||
465 | kfree(sst_drv_ctx->fw_sg_list.dst); | ||
466 | sst_drv_ctx->fw_sg_list.list_len = 0; | ||
467 | kfree(sst_drv_ctx->fw_in_mem); | ||
468 | sst_drv_ctx->fw_in_mem = NULL; | ||
469 | sst_memcpy_free_resources(sst_drv_ctx); | ||
470 | sst_drv_ctx = NULL; | ||
471 | pci_release_regions(pci); | 494 | pci_release_regions(pci); |
472 | pci_set_drvdata(pci, NULL); | 495 | pci_set_drvdata(pci, NULL); |
473 | } | 496 | } |