Merge tag 'iio-for-3.20a_take2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / iio / accel / kxcjk-1013.c
index da2fe93..567de26 100644 (file)
@@ -108,6 +108,7 @@ struct kxcjk1013_data {
        bool motion_trigger_on;
        int64_t timestamp;
        enum kx_chipset chipset;
+       bool is_smo8500_device;
 };
 
 enum kxcjk1013_axis {
@@ -377,6 +378,7 @@ static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
 
 static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
 {
+#ifdef CONFIG_PM
        int ret;
 
        if (on)
@@ -388,8 +390,11 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "Failed: kxcjk1013_set_power_state for %d\n", on);
+               if (on)
+                       pm_runtime_put_noidle(&data->client->dev);
                return ret;
        }
+#endif
 
        return 0;
 }
@@ -858,6 +863,8 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
 
        ret =  kxcjk1013_setup_any_motion_interrupt(data, state);
        if (ret < 0) {
+               kxcjk1013_set_power_state(data, false);
+               data->ev_enable_state = 0;
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -1008,6 +1015,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
        else
                ret = kxcjk1013_setup_new_data_interrupt(data, state);
        if (ret < 0) {
+               kxcjk1013_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -1131,12 +1139,16 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
 }
 
 static const char *kxcjk1013_match_acpi_device(struct device *dev,
-                                              enum kx_chipset *chipset)
+                                              enum kx_chipset *chipset,
+                                              bool *is_smo8500_device)
 {
        const struct acpi_device_id *id;
+
        id = acpi_match_device(dev->driver->acpi_match_table, dev);
        if (!id)
                return NULL;
+       if (strcmp(id->id, "SMO8500") == 0)
+               *is_smo8500_device = true;
        *chipset = (enum kx_chipset)id->driver_data;
 
        return dev_name(dev);
@@ -1151,6 +1163,8 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client,
 
        if (!client)
                return -EINVAL;
+       if (data->is_smo8500_device)
+               return -ENOTSUPP;
 
        dev = &client->dev;
 
@@ -1200,7 +1214,8 @@ static int kxcjk1013_probe(struct i2c_client *client,
                name = id->name;
        } else if (ACPI_HANDLE(&client->dev)) {
                name = kxcjk1013_match_acpi_device(&client->dev,
-                                                  &data->chipset);
+                                                  &data->chipset,
+                                                  &data->is_smo8500_device);
        } else
                return -ENODEV;
 
@@ -1228,21 +1243,25 @@ static int kxcjk1013_probe(struct i2c_client *client,
                                                KXCJK1013_IRQ_NAME,
                                                indio_dev);
                if (ret)
-                       return ret;
+                       goto err_poweroff;
 
                data->dready_trig = devm_iio_trigger_alloc(&client->dev,
                                                           "%s-dev%d",
                                                           indio_dev->name,
                                                           indio_dev->id);
-               if (!data->dready_trig)
-                       return -ENOMEM;
+               if (!data->dready_trig) {
+                       ret = -ENOMEM;
+                       goto err_poweroff;
+               }
 
                data->motion_trig = devm_iio_trigger_alloc(&client->dev,
                                                          "%s-any-motion-dev%d",
                                                          indio_dev->name,
                                                          indio_dev->id);
-               if (!data->motion_trig)
-                       return -ENOMEM;
+               if (!data->motion_trig) {
+                       ret = -ENOMEM;
+                       goto err_poweroff;
+               }
 
                data->dready_trig->dev.parent = &client->dev;
                data->dready_trig->ops = &kxcjk1013_trigger_ops;
@@ -1251,7 +1270,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
                iio_trigger_get(indio_dev->trig);
                ret = iio_trigger_register(data->dready_trig);
                if (ret)
-                       return ret;
+                       goto err_poweroff;
 
                data->motion_trig->dev.parent = &client->dev;
                data->motion_trig->ops = &kxcjk1013_trigger_ops;
@@ -1300,6 +1319,8 @@ err_trigger_unregister:
                iio_trigger_unregister(data->dready_trig);
        if (data->motion_trig)
                iio_trigger_unregister(data->motion_trig);
+err_poweroff:
+       kxcjk1013_set_mode(data, STANDBY);
 
        return ret;
 }
@@ -1349,10 +1370,7 @@ static int kxcjk1013_resume(struct device *dev)
        int ret = 0;
 
        mutex_lock(&data->mutex);
-       /* Check, if the suspend occured while active */
-       if (data->dready_trigger_on || data->motion_trigger_on ||
-                                                       data->ev_enable_state)
-               ret = kxcjk1013_set_mode(data, OPERATION);
+       ret = kxcjk1013_set_mode(data, OPERATION);
        mutex_unlock(&data->mutex);
 
        return ret;
@@ -1364,8 +1382,14 @@ static int kxcjk1013_runtime_suspend(struct device *dev)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct kxcjk1013_data *data = iio_priv(indio_dev);
+       int ret;
 
-       return kxcjk1013_set_mode(data, STANDBY);
+       ret = kxcjk1013_set_mode(data, STANDBY);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "powering off device failed\n");
+               return -EAGAIN;
+       }
+       return 0;
 }
 
 static int kxcjk1013_runtime_resume(struct device *dev)
@@ -1399,6 +1423,7 @@ static const struct acpi_device_id kx_acpi_match[] = {
        {"KXCJ1013", KXCJK1013},
        {"KXCJ1008", KXCJ91008},
        {"KXTJ1009", KXTJ21009},
+       {"SMO8500",  KXCJ91008},
        { },
 };
 MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
@@ -1407,6 +1432,7 @@ static const struct i2c_device_id kxcjk1013_id[] = {
        {"kxcjk1013", KXCJK1013},
        {"kxcj91008", KXCJ91008},
        {"kxtj21009", KXTJ21009},
+       {"SMO8500",   KXCJ91008},
        {}
 };