struct gmin_subdev {
        struct v4l2_subdev *subdev;
        enum clock_rate clock_src;
-       bool clock_on;
        struct clk *pmc_clk;
        struct gpio_desc *gpio0;
        struct gpio_desc *gpio1;
        unsigned int csi_lanes;
        enum atomisp_input_format csi_fmt;
        enum atomisp_bayer_order csi_bayer;
+
+       bool clock_on;
        bool v1p8_on;
        bool v2p8_on;
        bool v1p2_on;
 } pmic_id;
 
 static const char *pmic_name[] = {
-       [PMIC_UNSET]            = "unset",
+       [PMIC_UNSET]            = "ACPI device PM",
        [PMIC_REGULATOR]        = "regulator driver",
        [PMIC_AXP]              = "XPower AXP288 PMIC",
        [PMIC_TI]               = "Dollar Cove TI PMIC",
                gs->gpio1 = NULL;
 
        /*
-        * FIXME: the code below doesn't rely on ACPI device_pm.c code to
-        * set clocks and do power management.
+        * FIXME:
+        *
+        * The ACPI handling code checks for the _PR? tables in order to
+        * know what is required to switch the device from power state
+        * D0 (_PR0) up to D3COLD (_PR3).
+        *
+        * The adev->flags.power_manageable is set to true if the device
+        * has a _PR0 table, which can be checked by calling
+        * acpi_device_power_manageable(adev).
+        *
+        * However, this only says that the device can be set to power off
+        * mode.
+        *
+        * At least on the DSDT tables we've seen so far, there's no _PR3,
+        * nor _PS3 (which would have a somewhat similar effect).
+        * So, using ACPI for power management won't work, except if adding
+        * an ACPI override logic somewhere.
+        *
+        * So, at least for the existing devices we know, the check below
+        * will always be false.
+        */
+       if (acpi_device_can_wakeup(adev) &&
+           acpi_device_can_poweroff(adev)) {
+               dev_info(dev,
+                        "gmin: power management provided via device PM\n");
+
+               return gs;
+       }
+
+       /*
+        * The code below is here due to backward compatibility with devices
+        * whose ACPI BIOS may not contain everything that would be needed
+        * in order to set clocks and do power management.
         */
 
        if (!pmic_id) {
        return -EINVAL;
 }
 
+static int gmin_acpi_pm_ctrl(struct v4l2_subdev *subdev, int on)
+{
+       int ret = 0;
+       struct gmin_subdev *gs = find_gmin_subdev(subdev);
+       struct i2c_client *client = v4l2_get_subdevdata(subdev);
+       struct acpi_device *adev = ACPI_COMPANION(&client->dev);
+
+       /* Use the ACPI power management to control it */
+       on = !!on;
+       if (gs->clock_on == on)
+               return 0;
+
+       dev_dbg(subdev->dev, "Setting power state to %s\n",
+               on ? "on" : "off");
+
+       if (on)
+               ret = acpi_device_set_power(adev,
+                                           ACPI_STATE_D0);
+       else
+               ret = acpi_device_set_power(adev,
+                                           ACPI_STATE_D3_COLD);
+
+       if (!ret)
+               gs->clock_on = on;
+       else
+               dev_err(subdev->dev, "Couldn't set power state to %s\n",
+                       on ? "on" : "off");
+
+       return ret;
+}
+
 static int gmin_flisclk_ctrl(struct v4l2_subdev *subdev, int on)
 {
        int ret = 0;
        return NULL;
 }
 
-static struct camera_sensor_platform_data gmin_plat = {
+static struct camera_sensor_platform_data pmic_gmin_plat = {
        .gpio0_ctrl = gmin_gpio0_ctrl,
        .gpio1_ctrl = gmin_gpio1_ctrl,
        .v1p8_ctrl = gmin_v1p8_ctrl,
        .get_vcm_ctrl = gmin_get_vcm_ctrl,
 };
 
+static struct camera_sensor_platform_data acpi_gmin_plat = {
+       .gpio0_ctrl = gmin_gpio0_ctrl,
+       .gpio1_ctrl = gmin_gpio1_ctrl,
+       .v1p8_ctrl = gmin_acpi_pm_ctrl,
+       .v2p8_ctrl = gmin_acpi_pm_ctrl,
+       .v1p2_ctrl = gmin_acpi_pm_ctrl,
+       .flisclk_ctrl = gmin_acpi_pm_ctrl,
+       .csi_cfg = gmin_csi_cfg,
+       .get_vcm_ctrl = gmin_get_vcm_ctrl,
+};
+
 struct camera_sensor_platform_data *gmin_camera_platform_data(
     struct v4l2_subdev *subdev,
     enum atomisp_input_format csi_format,
        gs->csi_fmt = csi_format;
        gs->csi_bayer = csi_bayer;
 
-       return &gmin_plat;
+       if (gs->pmc_clk)
+               return &pmic_gmin_plat;
+       else
+               return &acpi_gmin_plat;
 }
 EXPORT_SYMBOL_GPL(gmin_camera_platform_data);