media: atomisp: Bind and do power-management without firmware

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@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Hans de Goede
2023-12-30 15:31:41 +01:00
committed by Mauro Carvalho Chehab
parent 25752a6231
commit a6be73e97f
2 changed files with 25 additions and 8 deletions

View File

@@ -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;

View File

@@ -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();