v4l/atomisp: let pmu driver handle power island states
authorJacob Pan <jacob.jun.pan@linux.intel.com>
Wed, 11 Jan 2012 06:44:25 +0000 (22:44 -0800)
committerbuildbot <buildbot@intel.com>
Fri, 30 Mar 2012 11:56:27 +0000 (04:56 -0700)
BZ: 25359

When atomisp is treated as real PCI device as it should be, ISP
often refuses to transition from D3hot to D0 state. This is likely
caused by an ordering problem where in resume PCI PM core restores
config space prior to calling pci_set_power_state and the driver's
rpm resume function. PMCSR in PCI PM cap is set to D0 from D3 but
refuses to transition possibly due to the fact that power islands
are still down for atomisp.

This patch moves power island control from driver rpm callbacks to
pmu driver such that the action is better coordinated.

Change-Id: I83ac338aa391793a2da12371dd9b6787370cb21d
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
Acked-by: David Cohen <david.a.cohen@intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-on: http://android.intel.com:8080/36782
Reviewed-by: Shevchenko, Andriy <andriy.shevchenko@intel.com>
Reviewed-by: Mansoor, Illyas <illyas.mansoor@intel.com>
Reviewed-by: Hogander, Jouni <jouni.hogander@intel.com>
Reviewed-by: Cohen, David A <david.a.cohen@intel.com>
Reviewed-by: Koski, Anttu <anttu.koski@intel.com>
Tested-by: Koski, Anttu <anttu.koski@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
arch/x86/platform/intel-mid/mfld-pmu.c
drivers/media/video/atomisp/atomisp_cmd.c
drivers/media/video/atomisp/atomisp_cmd.h
drivers/media/video/atomisp/atomisp_v4l2.c

index 2ecb333..f9ab7ed 100644 (file)
@@ -1649,9 +1649,20 @@ int __ref pmu_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
        if (i == GFX_LSS_INDEX)
                mid_pmu_cxt->display_off = (int)(state != PCI_D0);
 
-       /*Update the Camera status per ISP Driver Suspended/Resumed */
-       if (i == MFLD_ISP_POS)
+       /* Update the Camera status per ISP Driver Suspended/Resumed
+        * ISP power islands are also updated accordingly, otherwise Dx state
+        * in PMCSR refuses to change.
+        */
+       if (i == MFLD_ISP_POS) {
+               status = pmu_nc_set_power_state(APM_ISP_ISLAND | APM_IPH_ISLAND,
+                               (state != PCI_D0) ?
+                                       OSPM_ISLAND_DOWN : OSPM_ISLAND_UP,
+                               APM_REG_TYPE);
+               if (status)
+                       goto unlock;
+
                mid_pmu_cxt->camera_off = (int)(state != PCI_D0);
+       }
 
        if (pmu_num == PMU_NUM_2) {
 
index 690f0d0..65be722 100644 (file)
@@ -4191,8 +4191,8 @@ int atomisp_restore_iunit_reg(struct atomisp_device *isp)
        return 0;
 }
 
-/*Turn off ISP power island*/
-int atomisp_ospm_power_island_down(struct atomisp_device *isp)
+/*Turn off ISP dphy */
+int atomisp_ospm_dphy_down(struct atomisp_device *isp)
 {
        u32 pwr_cnt = 0;
        int timeout = 100;
@@ -4221,32 +4221,23 @@ done:
        pwr_cnt = atomisp_msg_read32(isp, IUNITPHY_PORT, CSI_CONTROL);
        pwr_cnt |= 0x300;
        atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_CONTROL, pwr_cnt);
-
-       /* Power down IPH/ISP */
-       if (pmu_nc_set_power_state(APM_ISP_ISLAND | APM_IPH_ISLAND,
-                              OSPM_ISLAND_DOWN, APM_REG_TYPE))
-               return -EINVAL;
-
        isp->sw_contex.power_state = ATOM_ISP_POWER_DOWN;
+
        return 0;
 }
 
-/*Turn on ISP power island*/
-int atomisp_ospm_power_island_up(struct atomisp_device *isp)
+/*Turn on ISP dphy */
+int atomisp_ospm_dphy_up(struct atomisp_device *isp)
 {
        u32 pwr_cnt = 0;
 
-       /* Power up IPH/ISP */
-       if (pmu_nc_set_power_state(APM_ISP_ISLAND | APM_IPH_ISLAND,
-                              OSPM_ISLAND_UP, APM_REG_TYPE))
-               return -EINVAL;
-
        /* power on DPHY */
        pwr_cnt = atomisp_msg_read32(isp, IUNITPHY_PORT, CSI_CONTROL);
        pwr_cnt &= ~0x300;
        atomisp_msg_write32(isp, IUNITPHY_PORT, CSI_CONTROL, pwr_cnt);
 
        isp->sw_contex.power_state = ATOM_ISP_POWER_UP;
+
        return 0;
 }
 
index afcb7eb..ba302d8 100644 (file)
@@ -268,8 +268,8 @@ int atomisp_set_shading_table(struct atomisp_device *isp,
 int atomisp_save_iunit_reg(struct atomisp_device *isp);
 int atomisp_restore_iunit_reg(struct atomisp_device *isp);
 
-int atomisp_ospm_power_island_down(struct atomisp_device *isp);
-int atomisp_ospm_power_island_up(struct atomisp_device *isp);
+int atomisp_ospm_dphy_down(struct atomisp_device *isp);
+int atomisp_ospm_dphy_up(struct atomisp_device *isp);
 int atomisp_exif_makernote(struct atomisp_device *isp,
        void *config);
 
index 6e585e1..a7a0782 100644 (file)
@@ -301,8 +301,8 @@ static int atomisp_runtime_suspend(struct device *dev)
        /* save IUnit context */
        atomisp_save_iunit_reg(isp);
 
-       /*Turn off the ISP power island*/
-       ret = atomisp_ospm_power_island_down(isp);
+       /*Turn off the ISP d-phy*/
+       ret = atomisp_ospm_dphy_down(isp);
 
        return ret;
 }
@@ -314,8 +314,8 @@ static int atomisp_runtime_resume(struct device *dev)
        int ret;
 
        if (isp->sw_contex.power_state == ATOM_ISP_POWER_DOWN) {
-               /*Turn on ISP power island*/
-               ret = atomisp_ospm_power_island_up(isp);
+               /*Turn on ISP d-phy */
+               ret = atomisp_ospm_dphy_up(isp);
                if (ret) {
                        v4l2_err(&atomisp_dev,
                                    "Failed to power up ISP!.\n");
@@ -353,8 +353,8 @@ static int atomisp_suspend(struct device *dev)
        /* save IUnit context */
        atomisp_save_iunit_reg(isp);
 
-       /*Turn off the ISP power island*/
-       ret = atomisp_ospm_power_island_down(isp);
+       /*Turn off the ISP d-phy */
+       ret = atomisp_ospm_dphy_down(isp);
        if (ret)
                v4l2_err(&atomisp_dev,
                            "fail to power off ISP\n");
@@ -368,8 +368,8 @@ static int atomisp_resume(struct device *dev)
                dev_get_drvdata(dev);
        int ret;
 
-       /*Turn on ISP power island*/
-       ret = atomisp_ospm_power_island_up(isp);
+       /*Turn on ISP d-phy */
+       ret = atomisp_ospm_dphy_up(isp);
        if (ret) {
                v4l2_err(&atomisp_dev,
                            "Failed to power up ISP!.\n");