Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * VCNL4035 Ambient Light and Proximity Sensor - 7-bit I2C slave address 0x60
0004  *
0005  * Copyright (c) 2018, DENX Software Engineering GmbH
0006  * Author: Parthiban Nallathambi <pn@denx.de>
0007  *
0008  * TODO: Proximity
0009  */
0010 #include <linux/bitops.h>
0011 #include <linux/i2c.h>
0012 #include <linux/module.h>
0013 #include <linux/pm_runtime.h>
0014 #include <linux/regmap.h>
0015 
0016 #include <linux/iio/buffer.h>
0017 #include <linux/iio/events.h>
0018 #include <linux/iio/iio.h>
0019 #include <linux/iio/sysfs.h>
0020 #include <linux/iio/trigger.h>
0021 #include <linux/iio/trigger_consumer.h>
0022 #include <linux/iio/triggered_buffer.h>
0023 
0024 #define VCNL4035_DRV_NAME   "vcnl4035"
0025 #define VCNL4035_IRQ_NAME   "vcnl4035_event"
0026 #define VCNL4035_REGMAP_NAME    "vcnl4035_regmap"
0027 
0028 /* Device registers */
0029 #define VCNL4035_ALS_CONF   0x00
0030 #define VCNL4035_ALS_THDH   0x01
0031 #define VCNL4035_ALS_THDL   0x02
0032 #define VCNL4035_ALS_DATA   0x0B
0033 #define VCNL4035_WHITE_DATA 0x0C
0034 #define VCNL4035_INT_FLAG   0x0D
0035 #define VCNL4035_DEV_ID     0x0E
0036 
0037 /* Register masks */
0038 #define VCNL4035_MODE_ALS_MASK      BIT(0)
0039 #define VCNL4035_MODE_ALS_WHITE_CHAN    BIT(8)
0040 #define VCNL4035_MODE_ALS_INT_MASK  BIT(1)
0041 #define VCNL4035_ALS_IT_MASK        GENMASK(7, 5)
0042 #define VCNL4035_ALS_PERS_MASK      GENMASK(3, 2)
0043 #define VCNL4035_INT_ALS_IF_H_MASK  BIT(12)
0044 #define VCNL4035_INT_ALS_IF_L_MASK  BIT(13)
0045 
0046 /* Default values */
0047 #define VCNL4035_MODE_ALS_ENABLE    BIT(0)
0048 #define VCNL4035_MODE_ALS_DISABLE   0x00
0049 #define VCNL4035_MODE_ALS_INT_ENABLE    BIT(1)
0050 #define VCNL4035_MODE_ALS_INT_DISABLE   0
0051 #define VCNL4035_DEV_ID_VAL     0x80
0052 #define VCNL4035_ALS_IT_DEFAULT     0x01
0053 #define VCNL4035_ALS_PERS_DEFAULT   0x00
0054 #define VCNL4035_ALS_THDH_DEFAULT   5000
0055 #define VCNL4035_ALS_THDL_DEFAULT   100
0056 #define VCNL4035_SLEEP_DELAY_MS     2000
0057 
0058 struct vcnl4035_data {
0059     struct i2c_client *client;
0060     struct regmap *regmap;
0061     unsigned int als_it_val;
0062     unsigned int als_persistence;
0063     unsigned int als_thresh_low;
0064     unsigned int als_thresh_high;
0065     struct iio_trigger *drdy_trigger0;
0066 };
0067 
0068 static inline bool vcnl4035_is_triggered(struct vcnl4035_data *data)
0069 {
0070     int ret;
0071     int reg;
0072 
0073     ret = regmap_read(data->regmap, VCNL4035_INT_FLAG, &reg);
0074     if (ret < 0)
0075         return false;
0076 
0077     return !!(reg &
0078         (VCNL4035_INT_ALS_IF_H_MASK | VCNL4035_INT_ALS_IF_L_MASK));
0079 }
0080 
0081 static irqreturn_t vcnl4035_drdy_irq_thread(int irq, void *private)
0082 {
0083     struct iio_dev *indio_dev = private;
0084     struct vcnl4035_data *data = iio_priv(indio_dev);
0085 
0086     if (vcnl4035_is_triggered(data)) {
0087         iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
0088                             0,
0089                             IIO_EV_TYPE_THRESH,
0090                             IIO_EV_DIR_EITHER),
0091                 iio_get_time_ns(indio_dev));
0092         iio_trigger_poll_chained(data->drdy_trigger0);
0093         return IRQ_HANDLED;
0094     }
0095 
0096     return IRQ_NONE;
0097 }
0098 
0099 /* Triggered buffer */
0100 static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p)
0101 {
0102     struct iio_poll_func *pf = p;
0103     struct iio_dev *indio_dev = pf->indio_dev;
0104     struct vcnl4035_data *data = iio_priv(indio_dev);
0105     /* Ensure naturally aligned timestamp */
0106     u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)]  __aligned(8);
0107     int ret;
0108 
0109     ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer);
0110     if (ret < 0) {
0111         dev_err(&data->client->dev,
0112             "Trigger consumer can't read from sensor.\n");
0113         goto fail_read;
0114     }
0115     iio_push_to_buffers_with_timestamp(indio_dev, buffer,
0116                     iio_get_time_ns(indio_dev));
0117 
0118 fail_read:
0119     iio_trigger_notify_done(indio_dev->trig);
0120 
0121     return IRQ_HANDLED;
0122 }
0123 
0124 static int vcnl4035_als_drdy_set_state(struct iio_trigger *trigger,
0125                     bool enable_drdy)
0126 {
0127     struct iio_dev *indio_dev = iio_trigger_get_drvdata(trigger);
0128     struct vcnl4035_data *data = iio_priv(indio_dev);
0129     int val = enable_drdy ? VCNL4035_MODE_ALS_INT_ENABLE :
0130                     VCNL4035_MODE_ALS_INT_DISABLE;
0131 
0132     return regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
0133                  VCNL4035_MODE_ALS_INT_MASK,
0134                  val);
0135 }
0136 
0137 static const struct iio_trigger_ops vcnl4035_trigger_ops = {
0138     .validate_device = iio_trigger_validate_own_device,
0139     .set_trigger_state = vcnl4035_als_drdy_set_state,
0140 };
0141 
0142 static int vcnl4035_set_pm_runtime_state(struct vcnl4035_data *data, bool on)
0143 {
0144     int ret;
0145     struct device *dev = &data->client->dev;
0146 
0147     if (on) {
0148         ret = pm_runtime_resume_and_get(dev);
0149     } else {
0150         pm_runtime_mark_last_busy(dev);
0151         ret = pm_runtime_put_autosuspend(dev);
0152     }
0153 
0154     return ret;
0155 }
0156 
0157 /*
0158  *  Device IT   INT Time (ms)   Scale (lux/step)
0159  *  000     50      0.064
0160  *  001     100     0.032
0161  *  010     200     0.016
0162  *  100     400     0.008
0163  *  101 - 111   800     0.004
0164  * Values are proportional, so ALS INT is selected for input due to
0165  * simplicity reason. Integration time value and scaling is
0166  * calculated based on device INT value
0167  *
0168  * Raw value needs to be scaled using ALS steps
0169  */
0170 static int vcnl4035_read_raw(struct iio_dev *indio_dev,
0171                 struct iio_chan_spec const *chan, int *val,
0172                 int *val2, long mask)
0173 {
0174     struct vcnl4035_data *data = iio_priv(indio_dev);
0175     int ret;
0176     int raw_data;
0177     unsigned int reg;
0178 
0179     switch (mask) {
0180     case IIO_CHAN_INFO_RAW:
0181         ret = vcnl4035_set_pm_runtime_state(data, true);
0182         if  (ret < 0)
0183             return ret;
0184 
0185         ret = iio_device_claim_direct_mode(indio_dev);
0186         if (!ret) {
0187             if (chan->channel)
0188                 reg = VCNL4035_ALS_DATA;
0189             else
0190                 reg = VCNL4035_WHITE_DATA;
0191             ret = regmap_read(data->regmap, reg, &raw_data);
0192             iio_device_release_direct_mode(indio_dev);
0193             if (!ret) {
0194                 *val = raw_data;
0195                 ret = IIO_VAL_INT;
0196             }
0197         }
0198         vcnl4035_set_pm_runtime_state(data, false);
0199         return ret;
0200     case IIO_CHAN_INFO_INT_TIME:
0201         *val = 50;
0202         if (data->als_it_val)
0203             *val = data->als_it_val * 100;
0204         return IIO_VAL_INT;
0205     case IIO_CHAN_INFO_SCALE:
0206         *val = 64;
0207         if (!data->als_it_val)
0208             *val2 = 1000;
0209         else
0210             *val2 = data->als_it_val * 2 * 1000;
0211         return IIO_VAL_FRACTIONAL;
0212     default:
0213         return -EINVAL;
0214     }
0215 }
0216 
0217 static int vcnl4035_write_raw(struct iio_dev *indio_dev,
0218                 struct iio_chan_spec const *chan,
0219                 int val, int val2, long mask)
0220 {
0221     int ret;
0222     struct vcnl4035_data *data = iio_priv(indio_dev);
0223 
0224     switch (mask) {
0225     case IIO_CHAN_INFO_INT_TIME:
0226         if (val <= 0 || val > 800)
0227             return -EINVAL;
0228 
0229         ret = vcnl4035_set_pm_runtime_state(data, true);
0230         if  (ret < 0)
0231             return ret;
0232 
0233         ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
0234                      VCNL4035_ALS_IT_MASK,
0235                      val / 100);
0236         if (!ret)
0237             data->als_it_val = val / 100;
0238 
0239         vcnl4035_set_pm_runtime_state(data, false);
0240         return ret;
0241     default:
0242         return -EINVAL;
0243     }
0244 }
0245 
0246 /* No direct ABI for persistence and threshold, so eventing */
0247 static int vcnl4035_read_thresh(struct iio_dev *indio_dev,
0248         const struct iio_chan_spec *chan, enum iio_event_type type,
0249         enum iio_event_direction dir, enum iio_event_info info,
0250         int *val, int *val2)
0251 {
0252     struct vcnl4035_data *data = iio_priv(indio_dev);
0253 
0254     switch (info) {
0255     case IIO_EV_INFO_VALUE:
0256         switch (dir) {
0257         case IIO_EV_DIR_RISING:
0258             *val = data->als_thresh_high;
0259             return IIO_VAL_INT;
0260         case IIO_EV_DIR_FALLING:
0261             *val = data->als_thresh_low;
0262             return IIO_VAL_INT;
0263         default:
0264             return -EINVAL;
0265         }
0266         break;
0267     case IIO_EV_INFO_PERIOD:
0268         *val = data->als_persistence;
0269         return IIO_VAL_INT;
0270     default:
0271         return -EINVAL;
0272     }
0273 
0274 }
0275 
0276 static int vcnl4035_write_thresh(struct iio_dev *indio_dev,
0277         const struct iio_chan_spec *chan, enum iio_event_type type,
0278         enum iio_event_direction dir, enum iio_event_info info, int val,
0279         int val2)
0280 {
0281     struct vcnl4035_data *data = iio_priv(indio_dev);
0282     int ret;
0283 
0284     switch (info) {
0285     case IIO_EV_INFO_VALUE:
0286         /* 16 bit threshold range 0 - 65535 */
0287         if (val < 0 || val > 65535)
0288             return -EINVAL;
0289         if (dir == IIO_EV_DIR_RISING) {
0290             if (val < data->als_thresh_low)
0291                 return -EINVAL;
0292             ret = regmap_write(data->regmap, VCNL4035_ALS_THDH,
0293                        val);
0294             if (ret)
0295                 return ret;
0296             data->als_thresh_high = val;
0297         } else {
0298             if (val > data->als_thresh_high)
0299                 return -EINVAL;
0300             ret = regmap_write(data->regmap, VCNL4035_ALS_THDL,
0301                        val);
0302             if (ret)
0303                 return ret;
0304             data->als_thresh_low = val;
0305         }
0306         return ret;
0307     case IIO_EV_INFO_PERIOD:
0308         /* allow only 1 2 4 8 as persistence value */
0309         if (val < 0 || val > 8 || hweight8(val) != 1)
0310             return -EINVAL;
0311         ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
0312                      VCNL4035_ALS_PERS_MASK, val);
0313         if (!ret)
0314             data->als_persistence = val;
0315         return ret;
0316     default:
0317         return -EINVAL;
0318     }
0319 }
0320 
0321 static IIO_CONST_ATTR_INT_TIME_AVAIL("50 100 200 400 800");
0322 
0323 static struct attribute *vcnl4035_attributes[] = {
0324     &iio_const_attr_integration_time_available.dev_attr.attr,
0325     NULL,
0326 };
0327 
0328 static const struct attribute_group vcnl4035_attribute_group = {
0329     .attrs = vcnl4035_attributes,
0330 };
0331 
0332 static const struct iio_info vcnl4035_info = {
0333     .read_raw       = vcnl4035_read_raw,
0334     .write_raw      = vcnl4035_write_raw,
0335     .read_event_value   = vcnl4035_read_thresh,
0336     .write_event_value  = vcnl4035_write_thresh,
0337     .attrs          = &vcnl4035_attribute_group,
0338 };
0339 
0340 static const struct iio_event_spec vcnl4035_event_spec[] = {
0341     {
0342         .type = IIO_EV_TYPE_THRESH,
0343         .dir = IIO_EV_DIR_RISING,
0344         .mask_separate = BIT(IIO_EV_INFO_VALUE),
0345     }, {
0346         .type = IIO_EV_TYPE_THRESH,
0347         .dir = IIO_EV_DIR_FALLING,
0348         .mask_separate = BIT(IIO_EV_INFO_VALUE),
0349     }, {
0350         .type = IIO_EV_TYPE_THRESH,
0351         .dir = IIO_EV_DIR_EITHER,
0352         .mask_separate = BIT(IIO_EV_INFO_PERIOD),
0353     },
0354 };
0355 
0356 enum vcnl4035_scan_index_order {
0357     VCNL4035_CHAN_INDEX_LIGHT,
0358     VCNL4035_CHAN_INDEX_WHITE_LED,
0359 };
0360 
0361 static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
0362     .validate_scan_mask = &iio_validate_scan_mask_onehot,
0363 };
0364 
0365 static const struct iio_chan_spec vcnl4035_channels[] = {
0366     {
0367         .type = IIO_LIGHT,
0368         .channel = 0,
0369         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0370                 BIT(IIO_CHAN_INFO_INT_TIME) |
0371                 BIT(IIO_CHAN_INFO_SCALE),
0372         .event_spec = vcnl4035_event_spec,
0373         .num_event_specs = ARRAY_SIZE(vcnl4035_event_spec),
0374         .scan_index = VCNL4035_CHAN_INDEX_LIGHT,
0375         .scan_type = {
0376             .sign = 'u',
0377             .realbits = 16,
0378             .storagebits = 16,
0379             .endianness = IIO_LE,
0380         },
0381     },
0382     {
0383         .type = IIO_INTENSITY,
0384         .channel = 1,
0385         .modified = 1,
0386         .channel2 = IIO_MOD_LIGHT_BOTH,
0387         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
0388         .scan_index = VCNL4035_CHAN_INDEX_WHITE_LED,
0389         .scan_type = {
0390             .sign = 'u',
0391             .realbits = 16,
0392             .storagebits = 16,
0393             .endianness = IIO_LE,
0394         },
0395     },
0396 };
0397 
0398 static int vcnl4035_set_als_power_state(struct vcnl4035_data *data, u8 status)
0399 {
0400     return regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
0401                     VCNL4035_MODE_ALS_MASK,
0402                     status);
0403 }
0404 
0405 static int vcnl4035_init(struct vcnl4035_data *data)
0406 {
0407     int ret;
0408     int id;
0409 
0410     ret = regmap_read(data->regmap, VCNL4035_DEV_ID, &id);
0411     if (ret < 0) {
0412         dev_err(&data->client->dev, "Failed to read DEV_ID register\n");
0413         return ret;
0414     }
0415 
0416     if (id != VCNL4035_DEV_ID_VAL) {
0417         dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
0418             id, VCNL4035_DEV_ID_VAL);
0419         return -ENODEV;
0420     }
0421 
0422     ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
0423     if (ret < 0)
0424         return ret;
0425 
0426     /* ALS white channel enable */
0427     ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
0428                  VCNL4035_MODE_ALS_WHITE_CHAN,
0429                  1);
0430     if (ret) {
0431         dev_err(&data->client->dev, "set white channel enable %d\n",
0432             ret);
0433         return ret;
0434     }
0435 
0436     /* set default integration time - 100 ms for ALS */
0437     ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
0438                  VCNL4035_ALS_IT_MASK,
0439                  VCNL4035_ALS_IT_DEFAULT);
0440     if (ret) {
0441         dev_err(&data->client->dev, "set default ALS IT returned %d\n",
0442             ret);
0443         return ret;
0444     }
0445     data->als_it_val = VCNL4035_ALS_IT_DEFAULT;
0446 
0447     /* set default persistence time - 1 for ALS */
0448     ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
0449                  VCNL4035_ALS_PERS_MASK,
0450                  VCNL4035_ALS_PERS_DEFAULT);
0451     if (ret) {
0452         dev_err(&data->client->dev, "set default PERS returned %d\n",
0453             ret);
0454         return ret;
0455     }
0456     data->als_persistence = VCNL4035_ALS_PERS_DEFAULT;
0457 
0458     /* set default HIGH threshold for ALS */
0459     ret = regmap_write(data->regmap, VCNL4035_ALS_THDH,
0460                 VCNL4035_ALS_THDH_DEFAULT);
0461     if (ret) {
0462         dev_err(&data->client->dev, "set default THDH returned %d\n",
0463             ret);
0464         return ret;
0465     }
0466     data->als_thresh_high = VCNL4035_ALS_THDH_DEFAULT;
0467 
0468     /* set default LOW threshold for ALS */
0469     ret = regmap_write(data->regmap, VCNL4035_ALS_THDL,
0470                 VCNL4035_ALS_THDL_DEFAULT);
0471     if (ret) {
0472         dev_err(&data->client->dev, "set default THDL returned %d\n",
0473             ret);
0474         return ret;
0475     }
0476     data->als_thresh_low = VCNL4035_ALS_THDL_DEFAULT;
0477 
0478     return 0;
0479 }
0480 
0481 static bool vcnl4035_is_volatile_reg(struct device *dev, unsigned int reg)
0482 {
0483     switch (reg) {
0484     case VCNL4035_ALS_CONF:
0485     case VCNL4035_DEV_ID:
0486         return false;
0487     default:
0488         return true;
0489     }
0490 }
0491 
0492 static const struct regmap_config vcnl4035_regmap_config = {
0493     .name       = VCNL4035_REGMAP_NAME,
0494     .reg_bits   = 8,
0495     .val_bits   = 16,
0496     .max_register   = VCNL4035_DEV_ID,
0497     .cache_type = REGCACHE_RBTREE,
0498     .volatile_reg   = vcnl4035_is_volatile_reg,
0499     .val_format_endian = REGMAP_ENDIAN_LITTLE,
0500 };
0501 
0502 static int vcnl4035_probe_trigger(struct iio_dev *indio_dev)
0503 {
0504     int ret;
0505     struct vcnl4035_data *data = iio_priv(indio_dev);
0506 
0507     data->drdy_trigger0 = devm_iio_trigger_alloc(
0508             indio_dev->dev.parent,
0509             "%s-dev%d", indio_dev->name, iio_device_id(indio_dev));
0510     if (!data->drdy_trigger0)
0511         return -ENOMEM;
0512 
0513     data->drdy_trigger0->ops = &vcnl4035_trigger_ops;
0514     iio_trigger_set_drvdata(data->drdy_trigger0, indio_dev);
0515     ret = devm_iio_trigger_register(indio_dev->dev.parent,
0516                     data->drdy_trigger0);
0517     if (ret) {
0518         dev_err(&data->client->dev, "iio trigger register failed\n");
0519         return ret;
0520     }
0521 
0522     /* Trigger setup */
0523     ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
0524                     NULL, vcnl4035_trigger_consumer_handler,
0525                     &iio_triggered_buffer_setup_ops);
0526     if (ret < 0) {
0527         dev_err(&data->client->dev, "iio triggered buffer setup failed\n");
0528         return ret;
0529     }
0530 
0531     /* IRQ to trigger mapping */
0532     ret = devm_request_threaded_irq(&data->client->dev, data->client->irq,
0533             NULL, vcnl4035_drdy_irq_thread,
0534             IRQF_TRIGGER_LOW | IRQF_ONESHOT,
0535             VCNL4035_IRQ_NAME, indio_dev);
0536     if (ret < 0)
0537         dev_err(&data->client->dev, "request irq %d for trigger0 failed\n",
0538                 data->client->irq);
0539     return ret;
0540 }
0541 
0542 static int vcnl4035_probe(struct i2c_client *client,
0543                 const struct i2c_device_id *id)
0544 {
0545     struct vcnl4035_data *data;
0546     struct iio_dev *indio_dev;
0547     struct regmap *regmap;
0548     int ret;
0549 
0550     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0551     if (!indio_dev)
0552         return -ENOMEM;
0553 
0554     regmap = devm_regmap_init_i2c(client, &vcnl4035_regmap_config);
0555     if (IS_ERR(regmap)) {
0556         dev_err(&client->dev, "regmap_init failed!\n");
0557         return PTR_ERR(regmap);
0558     }
0559 
0560     data = iio_priv(indio_dev);
0561     i2c_set_clientdata(client, indio_dev);
0562     data->client = client;
0563     data->regmap = regmap;
0564 
0565     indio_dev->info = &vcnl4035_info;
0566     indio_dev->name = VCNL4035_DRV_NAME;
0567     indio_dev->channels = vcnl4035_channels;
0568     indio_dev->num_channels = ARRAY_SIZE(vcnl4035_channels);
0569     indio_dev->modes = INDIO_DIRECT_MODE;
0570 
0571     ret = vcnl4035_init(data);
0572     if (ret < 0) {
0573         dev_err(&client->dev, "vcnl4035 chip init failed\n");
0574         return ret;
0575     }
0576 
0577     if (client->irq > 0) {
0578         ret = vcnl4035_probe_trigger(indio_dev);
0579         if (ret < 0) {
0580             dev_err(&client->dev, "vcnl4035 unable init trigger\n");
0581             goto fail_poweroff;
0582         }
0583     }
0584 
0585     ret = pm_runtime_set_active(&client->dev);
0586     if (ret < 0)
0587         goto fail_poweroff;
0588 
0589     ret = iio_device_register(indio_dev);
0590     if (ret < 0)
0591         goto fail_poweroff;
0592 
0593     pm_runtime_enable(&client->dev);
0594     pm_runtime_set_autosuspend_delay(&client->dev, VCNL4035_SLEEP_DELAY_MS);
0595     pm_runtime_use_autosuspend(&client->dev);
0596 
0597     return 0;
0598 
0599 fail_poweroff:
0600     vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
0601     return ret;
0602 }
0603 
0604 static int vcnl4035_remove(struct i2c_client *client)
0605 {
0606     struct iio_dev *indio_dev = i2c_get_clientdata(client);
0607     int ret;
0608 
0609     pm_runtime_dont_use_autosuspend(&client->dev);
0610     pm_runtime_disable(&client->dev);
0611     iio_device_unregister(indio_dev);
0612     pm_runtime_set_suspended(&client->dev);
0613 
0614     ret = vcnl4035_set_als_power_state(iio_priv(indio_dev),
0615                        VCNL4035_MODE_ALS_DISABLE);
0616     if (ret)
0617         dev_warn(&client->dev, "Failed to put device into standby (%pe)\n",
0618              ERR_PTR(ret));
0619 
0620     return 0;
0621 }
0622 
0623 static int vcnl4035_runtime_suspend(struct device *dev)
0624 {
0625     struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
0626     struct vcnl4035_data *data = iio_priv(indio_dev);
0627     int ret;
0628 
0629     ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
0630     regcache_mark_dirty(data->regmap);
0631 
0632     return ret;
0633 }
0634 
0635 static int vcnl4035_runtime_resume(struct device *dev)
0636 {
0637     struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
0638     struct vcnl4035_data *data = iio_priv(indio_dev);
0639     int ret;
0640 
0641     regcache_sync(data->regmap);
0642     ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
0643     if (ret < 0)
0644         return ret;
0645 
0646     /* wait for 1 ALS integration cycle */
0647     msleep(data->als_it_val * 100);
0648 
0649     return 0;
0650 }
0651 
0652 static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4035_pm_ops, vcnl4035_runtime_suspend,
0653                  vcnl4035_runtime_resume, NULL);
0654 
0655 static const struct i2c_device_id vcnl4035_id[] = {
0656     { "vcnl4035", 0 },
0657     { }
0658 };
0659 MODULE_DEVICE_TABLE(i2c, vcnl4035_id);
0660 
0661 static const struct of_device_id vcnl4035_of_match[] = {
0662     { .compatible = "vishay,vcnl4035", },
0663     { }
0664 };
0665 MODULE_DEVICE_TABLE(of, vcnl4035_of_match);
0666 
0667 static struct i2c_driver vcnl4035_driver = {
0668     .driver = {
0669         .name   = VCNL4035_DRV_NAME,
0670         .pm = pm_ptr(&vcnl4035_pm_ops),
0671         .of_match_table = vcnl4035_of_match,
0672     },
0673     .probe  = vcnl4035_probe,
0674     .remove = vcnl4035_remove,
0675     .id_table = vcnl4035_id,
0676 };
0677 
0678 module_i2c_driver(vcnl4035_driver);
0679 
0680 MODULE_AUTHOR("Parthiban Nallathambi <pn@denx.de>");
0681 MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver");
0682 MODULE_LICENSE("GPL v2");