atomisp: request sufficiently low CPU wakeup latency with pm_qos
authorTuukka Toivonen <tuukka.toivonen@intel.com>
Thu, 17 May 2012 11:36:36 +0000 (14:36 +0300)
committerbuildbot <buildbot@intel.com>
Wed, 30 May 2012 18:08:31 +0000 (11:08 -0700)
BZ: 34648

Request sufficiently low CPU wakeup time to ensure that ISP interrupts
are served in time and that no frames are dropped.

Change-Id: Ia3bf36c05111555cd06321e1e40f14d34a4db488
Signed-off-by: Tuukka Toivonen <tuukka.toivonen@intel.com>
Reviewed-on: http://android.intel.com:8080/50074
Reviewed-by: Laakso, Antti <antti.laakso@intel.com>
Reviewed-by: Gross, Mark <mark.gross@intel.com>
Reviewed-by: Kontola, Kalervo <kalervo.kontola@intel.com>
Tested-by: Koski, Anttu <anttu.koski@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/media/video/atomisp/atomisp_v4l2.c
drivers/media/video/atomisp/include/atomisp/atomisp_internal.h

index 34295d3..5e26551 100644 (file)
@@ -20,6 +20,7 @@
  * 02110-1301, USA.
  *
  */
+#include <linux/pm_qos_params.h>
 #include <linux/async.h>
 #include "atomisp_ioctl.h"
 #include "atomisp_cmd.h"
@@ -307,6 +308,8 @@ static int atomisp_runtime_suspend(struct device *dev)
 
        /*Turn off the ISP d-phy*/
        ret = atomisp_ospm_dphy_down(isp);
+       if (!ret)
+               pm_qos_update_request(&isp->pm_qos, PM_QOS_DEFAULT_VALUE);
 
        return ret;
 }
@@ -317,6 +320,7 @@ static int atomisp_runtime_resume(struct device *dev)
                dev_get_drvdata(dev);
        int ret;
 
+       pm_qos_update_request(&isp->pm_qos, ATOMISP_MAX_ISR_LATENCY);
        if (isp->sw_contex.power_state == ATOM_ISP_POWER_DOWN) {
                /*Turn on ISP d-phy */
                ret = atomisp_ospm_dphy_up(isp);
@@ -362,6 +366,8 @@ static int atomisp_suspend(struct device *dev)
        if (ret)
                v4l2_err(&atomisp_dev,
                            "fail to power off ISP\n");
+       else
+               pm_qos_update_request(&isp->pm_qos, PM_QOS_DEFAULT_VALUE);
 
        return ret;
 }
@@ -372,6 +378,8 @@ static int atomisp_resume(struct device *dev)
                dev_get_drvdata(dev);
        int ret;
 
+       pm_qos_update_request(&isp->pm_qos, ATOMISP_MAX_ISR_LATENCY);
+
        /*Turn on ISP d-phy */
        ret = atomisp_ospm_dphy_up(isp);
        if (ret) {
@@ -869,6 +877,8 @@ static int __devinit atomisp_pci_probe(struct pci_dev *dev,
 
        atomisp_msi_irq_init(isp, dev);
 
+       pm_qos_add_request(&isp->pm_qos, PM_QOS_CPU_DMA_LATENCY,
+                          PM_QOS_DEFAULT_VALUE);
        /*
         * fixing me!
         * MRFLD VP does not implement
@@ -911,6 +921,7 @@ static void __devexit atomisp_pci_remove(struct pci_dev *dev)
 
        pm_runtime_forbid(&dev->dev);
        pm_runtime_get_noresume(&dev->dev);
+       pm_qos_remove_request(&isp->pm_qos);
 
        atomisp_msi_irq_uninit(isp, dev);
        free_irq(dev->irq, isp);
index e8bb816..3bb859c 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef ATOMISP_INTERNAL_H_
 #define ATOMISP_INTERNAL_H_
 
+#include <linux/pm_qos_params.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
 #define ATOMISP_WDT_TIMEOUT            (4 * MSEC_PER_SEC) /* msecs */
 #define ATOMISP_WDT_MAX_TIMEOUTS       5
 
+/*
+ * Define how fast CPU should be able to serve ISP interrupts.
+ * The bigger the value, the higher risk that the ISP is not
+ * triggered sufficiently fast for it to process image during
+ * vertical blanking time, increasing risk of dropped frames.
+ * 1000 us is a reasonable value considering that the processing
+ * time is typically ~2000 us.
+ */
+#define ATOMISP_MAX_ISR_LATENCY        1000
+
 int atomisp_video_init(struct atomisp_video_pipe *video, const char *name);
 void atomisp_video_unregister(struct atomisp_video_pipe *video);
 int atomisp_video_register(struct atomisp_video_pipe *video,
@@ -242,6 +253,8 @@ struct atomisp_device {
        const struct firmware *firmware;
        struct timer_list wdt;
 
+       struct pm_qos_request_list pm_qos;
+
        struct sh_css_acc_fw *acc_fw[ATOMISP_ACC_FW_MAX];
        unsigned int acc_fw_handle;
        int acc_fw_count;