struct atomisp_device *isp;
unsigned int start;
int err, val;
- u32 irq;
/* Pointer to struct device. */
atomisp_dev = &pdev->dev;
/* Load isp firmware from user space */
isp->firmware = atomisp_load_firmware(isp);
- if (!isp->firmware) {
- err = -ENOENT;
- dev_dbg(&pdev->dev, "Firmware load failed\n");
- goto error_power_off;
- }
+ if (!isp->firmware)
+ return -ENOENT;
err = sh_css_check_firmware_version(isp->dev, isp->firmware->data);
if (err) {
/* save the iunit context only once after all the values are init'ed. */
atomisp_save_iunit_reg(isp);
+ /* Init ISP memory management */
+ hmm_init();
+
+ err = devm_request_threaded_irq(&pdev->dev, pdev->irq,
+ atomisp_isr, atomisp_isr_thread,
+ IRQF_SHARED, "isp_irq", isp);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to request irq (%d)\n", err);
+ goto error_unregister_entities;
+ }
+
+ /* Load firmware into ISP memory */
+ err = atomisp_css_load_firmware(isp);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to init css.\n");
+ goto error_free_irq;
+ }
+ /* Clear FW image from memory */
+ release_firmware(isp->firmware);
+ isp->firmware = NULL;
+ isp->css_env.isp_css_fw.data = NULL;
+
/*
* The atomisp does not use standard PCI power-management through the
* PCI config space. Instead this driver directly tells the P-Unit to
cpu_latency_qos_add_request(&isp->pm_qos, PM_QOS_DEFAULT_VALUE);
dev_pm_domain_set(&pdev->dev, &isp->pm_domain);
- pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
-
- /* Init ISP memory management */
- hmm_init();
-
- err = devm_request_threaded_irq(&pdev->dev, pdev->irq,
- atomisp_isr, atomisp_isr_thread,
- IRQF_SHARED, "isp_irq", isp);
- if (err) {
- dev_err(&pdev->dev, "Failed to request irq (%d)\n", err);
- goto error_unregister_entities;
- }
-
- /* Load firmware into ISP memory */
- err = atomisp_css_load_firmware(isp);
- if (err) {
- dev_err(&pdev->dev, "Failed to init css.\n");
- goto error_free_irq;
- }
- /* Clear FW image from memory */
- release_firmware(isp->firmware);
- isp->firmware = NULL;
- isp->css_env.isp_css_fw.data = NULL;
+ pm_runtime_put_sync_suspend(&pdev->dev);
err = v4l2_async_nf_register(&isp->notifier);
if (err) {
return 0;
error_unload_firmware:
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_forbid(&pdev->dev);
+ dev_pm_domain_set(&pdev->dev, NULL);
+ cpu_latency_qos_remove_request(&isp->pm_qos);
ia_css_unload_firmware();
error_free_irq:
devm_free_irq(&pdev->dev, pdev->irq, isp);
error_unregister_entities:
hmm_cleanup();
- pm_runtime_forbid(&pdev->dev);
- pm_runtime_get_noresume(&pdev->dev);
- dev_pm_domain_set(&pdev->dev, NULL);
- cpu_latency_qos_remove_request(&isp->pm_qos);
atomisp_unregister_entities(isp);
error_uninitialize_modules:
atomisp_uninitialize_modules(isp);
pci_free_irq_vectors(pdev);
error_release_firmware:
release_firmware(isp->firmware);
-error_power_off:
- /*
- * Switch off ISP, as keeping it powered on would prevent
- * reaching S0ix states.
- *
- * The following lines have been copied from atomisp suspend path
- */
-
- pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- irq &= BIT(INTR_IIR);
- pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
-
- pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq);
- irq &= ~BIT(INTR_IER);
- pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq);
-
- atomisp_msi_irq_uninit(isp);
-
- /* Address later when we worry about the ...field chips */
- if (IS_ENABLED(CONFIG_PM) && atomisp_mrfld_power(isp, false))
- dev_err(&pdev->dev, "Failed to switch off ISP\n");
-
return err;
}
atomisp_drvfs_exit();
- ia_css_unload_firmware();
- devm_free_irq(&pdev->dev, pdev->irq, isp);
- hmm_cleanup();
-
+ pm_runtime_get_sync(&pdev->dev);
pm_runtime_forbid(&pdev->dev);
- pm_runtime_get_noresume(&pdev->dev);
dev_pm_domain_set(&pdev->dev, NULL);
cpu_latency_qos_remove_request(&isp->pm_qos);
+ /* Undo ia_css_init() from atomisp_power_on() */
+ atomisp_css_uninit(isp);
+ ia_css_unload_firmware();
+ devm_free_irq(&pdev->dev, pdev->irq, isp);
+ hmm_cleanup();
+
atomisp_unregister_entities(isp);
atomisp_uninitialize_modules(isp);
atomisp_msi_irq_uninit(isp);