The ISP needs to be turned off in a special manner for the SoC to be able to reach S0i3 during suspend. When the firmware is missing still bind to the PCI device and run in pm-only mode which takes care of turning the ISP off (including turning it off again if the firmware has turned it on during resume). In this new pm-only mode the atomisp driver works exactly the same as the non-staging, pm-only drivers/platform/x86/intel/atomisp2/pm.c driver. Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- .../media/atomisp/pci/atomisp_internal.h | 1 + .../staging/media/atomisp/pci/atomisp_v4l2.c | 32 ++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index d5b077e602ca..bba9bc64d447 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -192,6 +192,7 @@ struct atomisp_device { struct dev_pm_domain pm_domain; struct pm_qos_request pm_qos; s32 max_isr_latency; + bool pm_only; struct atomisp_mipi_csi2_device csi2_port[ATOMISP_CAMERA_NR_PORTS]; struct atomisp_tpg_device tpg; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index f44be2d656a8..7e241f4e9e93 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -548,7 +548,7 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable) dev_dbg(isp->dev, "IUNIT power-%s.\n", enable ? "on" : "off"); /* WA for P-Unit, if DVFS enabled, ISP timeout observed */ - if (IS_CHT && enable) { + if (IS_CHT && enable && !isp->pm_only) { punit_ddr_dvfs_enable(false); msleep(20); } @@ -558,7 +558,7 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable) val, MRFLD_ISPSSPM0_ISPSSC_MASK); /* WA:Enable DVFS */ - if (IS_CHT && !enable) + if (IS_CHT && !enable && !isp->pm_only) punit_ddr_dvfs_enable(true); /* @@ -601,11 +601,15 @@ int atomisp_power_off(struct device *dev) int ret; u32 reg; - atomisp_css_uninit(isp); + if (isp->pm_only) { + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, 0); + } else { + atomisp_css_uninit(isp); - ret = atomisp_mrfld_pre_power_down(isp); - if (ret) - return ret; + ret = atomisp_mrfld_pre_power_down(isp); + if (ret) + return ret; + } /* * MRFLD IUNIT DPHY is located in an always-power-on island @@ -634,6 +638,9 @@ int atomisp_power_on(struct device *dev) pci_restore_state(to_pci_dev(dev)); cpu_latency_qos_update_request(&isp->pm_qos, isp->max_isr_latency); + if (isp->pm_only) + return 0; + /*restore register values for iUnit and iUnitPHY registers*/ if (isp->saved_regs.pcicmdsts) atomisp_restore_iunit_reg(isp); @@ -1252,6 +1259,7 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i isp->dev = &pdev->dev; isp->saved_regs.ispmmadr = start; + isp->asd.isp = isp; mutex_init(&isp->mutex); spin_lock_init(&isp->lock); @@ -1368,8 +1376,13 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i /* Load isp firmware from user space */ isp->firmware = atomisp_load_firmware(isp); - if (!isp->firmware) - return -ENOENT; + if (!isp->firmware) { + /* No firmware continue in pm-only mode for S0i3 support */ + dev_info(&pdev->dev, "Continuing in power-management only mode\n"); + isp->pm_only = true; + atomisp_pm_init(isp); + return 0; + } err = sh_css_check_firmware_version(isp->dev, isp->firmware->data); if (err) { @@ -1507,6 +1520,9 @@ static void atomisp_pci_remove(struct pci_dev *pdev) atomisp_pm_uninit(isp); + if (isp->pm_only) + return; + /* Undo ia_css_init() from atomisp_power_on() */ atomisp_css_uninit(isp); ia_css_unload_firmware(); -- 2.43.0