aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/staging
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+huawei@kernel.org>2020-05-12 15:13:50 +0200
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2020-05-20 14:51:28 +0200
commit0f441fd70b1e7d1a4e035410f9effbfdf5c273fa (patch)
tree995f7f1b7fb422cb27b47c0f8f789a538b201eca /drivers/staging
parentmedia: atomisp: use pcim_enable_device() again (diff)
downloadwireguard-linux-0f441fd70b1e7d1a4e035410f9effbfdf5c273fa.tar.xz
wireguard-linux-0f441fd70b1e7d1a4e035410f9effbfdf5c273fa.zip
media: atomisp: simplify the power down/up code
Use the version from intel_atomisp2_pm.c for power up/down, removing some code duplication and using just one kAPI call for modifying the ISPSSPM0 register. Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c113
1 files changed, 49 insertions, 64 deletions
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
index 36f9b43d31ae..8c7b42221659 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
@@ -761,91 +761,76 @@ static void punit_ddr_dvfs_enable(bool enable)
pr_info("DDR DVFS, door bell is not cleared within 3ms\n");
}
-/* Workaround for pmu_nc_set_power_state not ready in MRFLD */
-int atomisp_mrfld_power_down(struct atomisp_device *isp)
+static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable)
{
unsigned long timeout;
- u32 reg_value;
+ u32 val = enable ? MRFLD_ISPSSPM0_IUNIT_POWER_ON :
+ MRFLD_ISPSSPM0_IUNIT_POWER_OFF;
- /* writing 0x3 to ISPSSPM0 bit[1:0] to power off the IUNIT */
- iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &reg_value);
- reg_value &= ~MRFLD_ISPSSPM0_ISPSSC_MASK;
- reg_value |= MRFLD_ISPSSPM0_IUNIT_POWER_OFF;
- iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, MRFLD_ISPSSPM0, reg_value);
+ dev_dbg(isp->dev, "IUNIT power-%s.\n", enable ? "on" : "off");
/*WA:Enable DVFS*/
- if (IS_CHT)
+ if (IS_CHT && enable)
punit_ddr_dvfs_enable(true);
/*
- * There should be no iunit access while power-down is
- * in progress HW sighting: 4567865
- * FIXME: msecs_to_jiffies(50)- experienced value
- */
- timeout = jiffies + msecs_to_jiffies(50);
- while (1) {
- iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &reg_value);
- dev_dbg(isp->dev, "power-off in progress, ISPSSPM0: 0x%x\n",
- reg_value);
- /* wait until ISPSSPM0 bit[25:24] shows 0x3 */
- if ((reg_value >> MRFLD_ISPSSPM0_ISPSSS_OFFSET) ==
- MRFLD_ISPSSPM0_IUNIT_POWER_OFF) {
- trace_ipu_cstate(0);
- return 0;
- }
-
- if (time_after(jiffies, timeout)) {
- dev_err(isp->dev, "power-off iunit timeout.\n");
- return -EBUSY;
- }
- /* FIXME: experienced value for delay */
- usleep_range(100, 150);
- }
-}
-
-/* Workaround for pmu_nc_set_power_state not ready in MRFLD */
-int atomisp_mrfld_power_up(struct atomisp_device *isp)
-{
- unsigned long timeout;
- u32 reg_value;
-
- /*WA for PUNIT, if DVFS enabled, ISP timeout observed*/
- if (IS_CHT)
- punit_ddr_dvfs_enable(false);
-
- /*
* FIXME:WA for ECS28A, with this sleep, CTS
* android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceAbort
* PASS, no impact on other platforms
*/
- if (IS_BYT)
+ if (IS_BYT && enable)
msleep(10);
- /* writing 0x0 to ISPSSPM0 bit[1:0] to power off the IUNIT */
- iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &reg_value);
- reg_value &= ~MRFLD_ISPSSPM0_ISPSSC_MASK;
- iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, MRFLD_ISPSSPM0, reg_value);
+ /* Write to ISPSSPM0 bit[1:0] to power on/off the IUNIT */
+ iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0,
+ val, MRFLD_ISPSSPM0_ISPSSC_MASK);
+
+ /*WA:Enable DVFS*/
+ if (IS_CHT && !enable)
+ punit_ddr_dvfs_enable(true);
- /* FIXME: experienced value for delay */
+ /*
+ * There should be no IUNIT access while power-down is
+ * in progress. HW sighting: 4567865.
+ * Wait up to 50 ms for the IUNIT to shut down.
+ * And we do the same for power on.
+ */
timeout = jiffies + msecs_to_jiffies(50);
- while (1) {
- iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &reg_value);
- dev_dbg(isp->dev, "power-on in progress, ISPSSPM0: 0x%x\n",
- reg_value);
- /* wait until ISPSSPM0 bit[25:24] shows 0x0 */
- if ((reg_value >> MRFLD_ISPSSPM0_ISPSSS_OFFSET) ==
- MRFLD_ISPSSPM0_IUNIT_POWER_ON) {
- trace_ipu_cstate(1);
+ do {
+ u32 tmp;
+
+ /* Wait until ISPSSPM0 bit[25:24] shows the right value */
+ iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &tmp);
+ tmp = (tmp & MRFLD_ISPSSPM0_ISPSSC_MASK) >> MRFLD_ISPSSPM0_ISPSSS_OFFSET;
+ if (tmp == val) {
+ trace_ipu_cstate(enable);
return 0;
}
- if (time_after(jiffies, timeout)) {
- dev_err(isp->dev, "power-on iunit timeout.\n");
- return -EBUSY;
- }
+ if (time_after(jiffies, timeout))
+ break;
+
/* FIXME: experienced value for delay */
usleep_range(100, 150);
- }
+ } while (1);
+
+ if (enable)
+ msleep(10);
+
+ dev_err(isp->dev, "IUNIT power-%s timeout.\n", enable ? "on" : "off");
+ return -EBUSY;
+}
+
+/* Workaround for pmu_nc_set_power_state not ready in MRFLD */
+int atomisp_mrfld_power_down(struct atomisp_device *isp)
+{
+ return atomisp_mrfld_power(isp, false);
+}
+
+/* Workaround for pmu_nc_set_power_state not ready in MRFLD */
+int atomisp_mrfld_power_up(struct atomisp_device *isp)
+{
+ return atomisp_mrfld_power(isp, true);
}
int atomisp_runtime_suspend(struct device *dev)