media: i2c: imx319: Support device probe in non-zero ACPI D state
authorRajmohan Mani <rajmohan.mani@intel.com>
Mon, 18 Oct 2021 12:17:28 +0000 (15:17 +0300)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 3 Nov 2021 18:03:55 +0000 (19:03 +0100)
Tell ACPI device PM code that the driver supports the device being in
non-zero ACPI D state when the driver's probe function is entered.

Signed-off-by: Rajmohan Mani <rajmohan.mani@intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Tomasz Figa <tfiga@chromium.org>
Reviewed-by: Bingbu Cao <bingbu.cao@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/media/i2c/imx319.c

index dba0854..daa9768 100644 (file)
@@ -140,6 +140,8 @@ struct imx319 {
 
        /* Streaming on/off */
        bool streaming;
+       /* True if the device has been identified */
+       bool identified;
 };
 
 static const struct imx319_reg imx319_global_regs[] = {
@@ -2084,6 +2086,31 @@ imx319_set_pad_format(struct v4l2_subdev *sd,
        return 0;
 }
 
+/* Verify chip ID */
+static int imx319_identify_module(struct imx319 *imx319)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
+       int ret;
+       u32 val;
+
+       if (imx319->identified)
+               return 0;
+
+       ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val);
+       if (ret)
+               return ret;
+
+       if (val != IMX319_CHIP_ID) {
+               dev_err(&client->dev, "chip id mismatch: %x!=%x",
+                       IMX319_CHIP_ID, val);
+               return -EIO;
+       }
+
+       imx319->identified = true;
+
+       return 0;
+}
+
 /* Start streaming */
 static int imx319_start_streaming(struct imx319 *imx319)
 {
@@ -2091,6 +2118,10 @@ static int imx319_start_streaming(struct imx319 *imx319)
        const struct imx319_reg_list *reg_list;
        int ret;
 
+       ret = imx319_identify_module(imx319);
+       if (ret)
+               return ret;
+
        /* Global Setting */
        reg_list = &imx319_global_setting;
        ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);
@@ -2206,26 +2237,6 @@ error:
        return ret;
 }
 
-/* Verify chip ID */
-static int imx319_identify_module(struct imx319 *imx319)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
-       int ret;
-       u32 val;
-
-       ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val);
-       if (ret)
-               return ret;
-
-       if (val != IMX319_CHIP_ID) {
-               dev_err(&client->dev, "chip id mismatch: %x!=%x",
-                       IMX319_CHIP_ID, val);
-               return -EIO;
-       }
-
-       return 0;
-}
-
 static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = {
        .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
        .unsubscribe_event = v4l2_event_subdev_unsubscribe,
@@ -2420,6 +2431,7 @@ out_err:
 static int imx319_probe(struct i2c_client *client)
 {
        struct imx319 *imx319;
+       bool full_power;
        int ret;
        u32 i;
 
@@ -2432,11 +2444,14 @@ static int imx319_probe(struct i2c_client *client)
        /* Initialize subdev */
        v4l2_i2c_subdev_init(&imx319->sd, client, &imx319_subdev_ops);
 
-       /* Check module identity */
-       ret = imx319_identify_module(imx319);
-       if (ret) {
-               dev_err(&client->dev, "failed to find sensor: %d", ret);
-               goto error_probe;
+       full_power = acpi_dev_state_d0(&client->dev);
+       if (full_power) {
+               /* Check module identity */
+               ret = imx319_identify_module(imx319);
+               if (ret) {
+                       dev_err(&client->dev, "failed to find sensor: %d", ret);
+                       goto error_probe;
+               }
        }
 
        imx319->hwcfg = imx319_get_hwcfg(&client->dev);
@@ -2488,11 +2503,9 @@ static int imx319_probe(struct i2c_client *client)
        if (ret < 0)
                goto error_media_entity;
 
-       /*
-        * Device is already turned on by i2c-core with ACPI domain PM.
-        * Enable runtime PM and turn off the device.
-        */
-       pm_runtime_set_active(&client->dev);
+       /* Set the device's state to active if it's in D0 state. */
+       if (full_power)
+               pm_runtime_set_active(&client->dev);
        pm_runtime_enable(&client->dev);
        pm_runtime_idle(&client->dev);
 
@@ -2545,6 +2558,7 @@ static struct i2c_driver imx319_i2c_driver = {
        },
        .probe_new = imx319_probe,
        .remove = imx319_remove,
+       .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
 };
 module_i2c_driver(imx319_i2c_driver);