^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * vcnl4000.c - Support for Vishay VCNL4000/4010/4020/4040/4200 combined ambient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * light and proximity sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2019 Pursim SPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright 2020 Mathieu Othacehe <m.othacehe@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * IIO driver for:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * VCNL4000/10/20 (7-bit I2C slave address 0x13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * VCNL4040 (7-bit I2C slave address 0x60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * VCNL4200 (7-bit I2C slave address 0x51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * allow to adjust IR current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * interrupts (VCNL4040, VCNL4200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/iio/buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/iio/events.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/iio/trigger.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/iio/trigger_consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/iio/triggered_buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define VCNL4000_DRV_NAME "vcnl4000"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define VCNL4000_PROD_ID 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define VCNL4010_PROD_ID 0x02 /* for VCNL4020, VCNL4010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define VCNL4040_PROD_ID 0x86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define VCNL4200_PROD_ID 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define VCNL4000_COMMAND 0x80 /* Command register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define VCNL4010_PROX_RATE 0x82 /* Proximity rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define VCNL4010_ALS_PARAM 0x84 /* ALS rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define VCNL4010_INT_CTRL 0x89 /* Interrupt control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define VCNL4010_LOW_THR_HI 0x8a /* Low threshold, MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define VCNL4010_LOW_THR_LO 0x8b /* Low threshold, LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define VCNL4010_HIGH_THR_HI 0x8c /* High threshold, MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define VCNL4010_HIGH_THR_LO 0x8d /* High threshold, LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define VCNL4010_ISR 0x8e /* Interrupt status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define VCNL4200_PS_DATA 0x08 /* Proximity data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define VCNL4200_AL_DATA 0x09 /* Ambient light data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define VCNL4200_DEV_ID 0x0e /* Device ID, slave address and version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define VCNL4040_DEV_ID 0x0c /* Device ID and version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* Bit masks for COMMAND register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define VCNL4000_AL_RDY BIT(6) /* ALS data ready? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define VCNL4000_ALS_EN BIT(2) /* start ALS measurement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define VCNL4000_PROX_EN BIT(1) /* start proximity measurement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define VCNL4000_SELF_TIMED_EN BIT(0) /* start self-timed measurement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* Bit masks for interrupt registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define VCNL4010_INT_THR_SEL BIT(0) /* Select threshold interrupt source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define VCNL4010_INT_THR_EN BIT(1) /* Threshold interrupt type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define VCNL4010_INT_ALS_EN BIT(2) /* Enable on ALS data ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define VCNL4010_INT_PROX_EN BIT(3) /* Enable on proximity data ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define VCNL4010_INT_THR_HIGH 0 /* High threshold exceeded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define VCNL4010_INT_THR_LOW 1 /* Low threshold exceeded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define VCNL4010_INT_ALS 2 /* ALS data ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define VCNL4010_INT_PROXIMITY 3 /* Proximity data ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define VCNL4010_INT_THR \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) (BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define VCNL4010_INT_DRDY \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static const int vcnl4010_prox_sampling_frequency[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {1, 950000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {3, 906250},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {7, 812500},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {16, 625000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {31, 250000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {62, 500000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {125, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {250, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) enum vcnl4000_device_ids {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) VCNL4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) VCNL4010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) VCNL4040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) VCNL4200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct vcnl4200_channel {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ktime_t last_measurement;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ktime_t sampling_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct vcnl4000_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) enum vcnl4000_device_ids id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int al_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) const struct vcnl4000_chip_spec *chip_spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct mutex vcnl4000_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct vcnl4200_channel vcnl4200_al;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct vcnl4200_channel vcnl4200_ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) uint32_t near_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct vcnl4000_chip_spec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) const char *prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct iio_chan_spec const *channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) const int num_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) const struct iio_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) bool irq_support;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int (*init)(struct vcnl4000_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int (*measure_light)(struct vcnl4000_data *data, int *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int (*measure_proximity)(struct vcnl4000_data *data, int *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int (*set_power_state)(struct vcnl4000_data *data, bool on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static const struct i2c_device_id vcnl4000_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) { "vcnl4000", VCNL4000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { "vcnl4010", VCNL4010 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) { "vcnl4020", VCNL4010 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { "vcnl4040", VCNL4040 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { "vcnl4200", VCNL4200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) MODULE_DEVICE_TABLE(i2c, vcnl4000_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* no suspend op */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static int vcnl4000_init(struct vcnl4000_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int ret, prod_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) prod_id = ret >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) switch (prod_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) case VCNL4000_PROD_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (data->id != VCNL4000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dev_warn(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) "wrong device id, use vcnl4000");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case VCNL4010_PROD_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (data->id != VCNL4010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) dev_warn(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) "wrong device id, use vcnl4010/4020");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) data->rev = ret & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) data->al_scale = 250000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mutex_init(&data->vcnl4000_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return data->chip_spec->set_power_state(data, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u16 val = on ? 0 /* power on */ : 1 /* shut down */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* Wait at least one integration cycle before fetching data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) data->vcnl4200_al.last_measurement = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) data->vcnl4200_ps.last_measurement = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int vcnl4200_init(struct vcnl4000_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int ret, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) id = ret & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (id != VCNL4200_PROD_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) id = ret & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (id != VCNL4040_PROD_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dev_dbg(&data->client->dev, "device id 0x%x", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) data->rev = (ret >> 8) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) data->vcnl4200_al.reg = VCNL4200_AL_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) case VCNL4200_PROD_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* Default wait time is 50ms, add 20% tolerance. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* Default wait time is 4.8ms, add 20% tolerance. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) data->al_scale = 24000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case VCNL4040_PROD_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Default wait time is 80ms, add 20% tolerance. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* Default wait time is 5ms, add 20% tolerance. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) data->al_scale = 120000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mutex_init(&data->vcnl4200_al.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) mutex_init(&data->vcnl4200_ps.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ret = data->chip_spec->set_power_state(data, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) s32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ret = i2c_smbus_read_word_swapped(data->client, data_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) *val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (val > U16_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return i2c_smbus_write_word_swapped(data->client, data_reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) u8 rdy_mask, u8 data_reg, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int tries = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) mutex_lock(&data->vcnl4000_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) req_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* wait for data to become ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) while (tries--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (ret & rdy_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) msleep(20); /* measurement takes up to 100 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (tries < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) dev_err(&data->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) "vcnl4000_measure() failed, data not ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ret = vcnl4000_read_data(data, data_reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) mutex_unlock(&data->vcnl4000_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) mutex_unlock(&data->vcnl4000_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static int vcnl4200_measure(struct vcnl4000_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct vcnl4200_channel *chan, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) s64 delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ktime_t next_measurement;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) mutex_lock(&chan->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) next_measurement = ktime_add(chan->last_measurement,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) chan->sampling_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) delta = ktime_us_delta(next_measurement, ktime_get());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (delta > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) usleep_range(delta, delta + 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) chan->last_measurement = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) mutex_unlock(&chan->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ret = i2c_smbus_read_word_data(data->client, chan->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) *val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return vcnl4000_measure(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) VCNL4000_AL_OD, VCNL4000_AL_RDY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) VCNL4000_AL_RESULT_HI, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return vcnl4200_measure(data, &data->vcnl4200_al, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return vcnl4000_measure(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) VCNL4000_PS_OD, VCNL4000_PS_RDY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) VCNL4000_PS_RESULT_HI, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return vcnl4200_measure(data, &data->vcnl4200_ps, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int *val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) *val = vcnl4010_prox_sampling_frequency[ret][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *val2 = vcnl4010_prox_sampling_frequency[ret][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return !!(ret & VCNL4000_SELF_TIMED_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct device *dev = &data->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ret = pm_runtime_get_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) pm_runtime_put_noidle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) ret = pm_runtime_put_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int vcnl4000_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ret = vcnl4000_set_pm_runtime_state(data, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) case IIO_LIGHT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ret = data->chip_spec->measure_light(data, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ret = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ret = data->chip_spec->measure_proximity(data, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) ret = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) vcnl4000_set_pm_runtime_state(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (chan->type != IIO_LIGHT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) *val2 = data->al_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int vcnl4010_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* Protect against event capture. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (vcnl4010_is_in_periodic_mode(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ret = vcnl4000_read_raw(indio_dev, chan, val, val2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) case IIO_CHAN_INFO_SAMP_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ret = vcnl4010_read_proxy_samp_freq(data, val, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static int vcnl4010_read_avail(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) const int **vals, int *type, int *length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) case IIO_CHAN_INFO_SAMP_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) *vals = (int *)vcnl4010_prox_sampling_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *type = IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return IIO_AVAIL_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int index = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (val == vcnl4010_prox_sampling_frequency[i][0] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) val2 == vcnl4010_prox_sampling_frequency[i][1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (index < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static int vcnl4010_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int val, int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* Protect against event capture. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (vcnl4010_is_in_periodic_mode(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) case IIO_CHAN_INFO_SAMP_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ret = vcnl4010_write_proxy_samp_freq(data, val, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static int vcnl4010_read_event(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) enum iio_event_info info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) int *val, int *val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) switch (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) case IIO_EV_INFO_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) switch (dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case IIO_EV_DIR_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case IIO_EV_DIR_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static int vcnl4010_write_event(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) enum iio_event_info info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) int val, int val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) switch (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) case IIO_EV_INFO_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) switch (dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) case IIO_EV_DIR_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) case IIO_EV_DIR_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return !!(ret & VCNL4010_INT_THR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static int vcnl4010_read_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) enum iio_event_direction dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return vcnl4010_is_thr_enabled(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) int icr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) int command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* Enable periodic measurement of proximity data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * Enable interrupts on threshold, for proximity data by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) icr = VCNL4010_INT_THR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (!vcnl4010_is_thr_enabled(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) command = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) icr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) enum iio_event_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) case IIO_PROXIMITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return vcnl4010_config_threshold(indio_dev, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) uintptr_t priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) const struct iio_chan_spec *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return sprintf(buf, "%u\n", data->near_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .name = "nearlevel",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .shared = IIO_SEPARATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) .read = vcnl4000_read_near_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static const struct iio_event_spec vcnl4000_event_spec[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .dir = IIO_EV_DIR_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .mask_separate = BIT(IIO_EV_INFO_VALUE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) .dir = IIO_EV_DIR_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) .mask_separate = BIT(IIO_EV_INFO_VALUE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .dir = IIO_EV_DIR_EITHER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) .mask_separate = BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static const struct iio_chan_spec vcnl4000_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .type = IIO_LIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .type = IIO_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .ext_info = vcnl4000_ext_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) static const struct iio_chan_spec vcnl4010_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .type = IIO_LIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) .scan_index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .type = IIO_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) .scan_index = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) BIT(IIO_CHAN_INFO_SAMP_FREQ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .event_spec = vcnl4000_event_spec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .ext_info = vcnl4000_ext_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .scan_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .sign = 'u',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .realbits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .storagebits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .endianness = IIO_CPU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) IIO_CHAN_SOFT_TIMESTAMP(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static const struct iio_info vcnl4000_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) .read_raw = vcnl4000_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) static const struct iio_info vcnl4010_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .read_raw = vcnl4010_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .read_avail = vcnl4010_read_avail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .write_raw = vcnl4010_write_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) .read_event_value = vcnl4010_read_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .write_event_value = vcnl4010_write_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .read_event_config = vcnl4010_read_event_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) .write_event_config = vcnl4010_write_event_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) [VCNL4000] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .prod = "VCNL4000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) .init = vcnl4000_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) .measure_light = vcnl4000_measure_light,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) .measure_proximity = vcnl4000_measure_proximity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) .set_power_state = vcnl4000_set_power_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) .channels = vcnl4000_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) .num_channels = ARRAY_SIZE(vcnl4000_channels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) .info = &vcnl4000_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) .irq_support = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) [VCNL4010] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) .prod = "VCNL4010/4020",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) .init = vcnl4000_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) .measure_light = vcnl4000_measure_light,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) .measure_proximity = vcnl4000_measure_proximity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) .set_power_state = vcnl4000_set_power_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) .channels = vcnl4010_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) .num_channels = ARRAY_SIZE(vcnl4010_channels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) .info = &vcnl4010_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) .irq_support = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) [VCNL4040] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .prod = "VCNL4040",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .init = vcnl4200_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) .measure_light = vcnl4200_measure_light,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) .measure_proximity = vcnl4200_measure_proximity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) .set_power_state = vcnl4200_set_power_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .channels = vcnl4000_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .num_channels = ARRAY_SIZE(vcnl4000_channels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) .info = &vcnl4000_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .irq_support = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) [VCNL4200] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) .prod = "VCNL4200",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .init = vcnl4200_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) .measure_light = vcnl4200_measure_light,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) .measure_proximity = vcnl4200_measure_proximity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .set_power_state = vcnl4200_set_power_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .channels = vcnl4000_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .num_channels = ARRAY_SIZE(vcnl4000_channels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) .info = &vcnl4000_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .irq_support = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct iio_dev *indio_dev = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) unsigned long isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) isr = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (isr & VCNL4010_INT_THR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (test_bit(VCNL4010_INT_THR_LOW, &isr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) IIO_UNMOD_EVENT_CODE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) IIO_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) IIO_EV_DIR_FALLING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) IIO_UNMOD_EVENT_CODE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) IIO_PROXIMITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) IIO_EV_DIR_RISING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) isr & VCNL4010_INT_THR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) iio_trigger_poll_chained(indio_dev->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) struct iio_poll_func *pf = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct iio_dev *indio_dev = pf->indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) const unsigned long *active_scan_mask = indio_dev->active_scan_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) bool data_read = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) unsigned long isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) isr = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (test_bit(0, active_scan_mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) ret = vcnl4000_read_data(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) VCNL4000_PS_RESULT_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) buffer[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) data_read = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) isr & VCNL4010_INT_DRDY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (!data_read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) iio_push_to_buffers_with_timestamp(indio_dev, buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) iio_trigger_notify_done(indio_dev->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /* Do not enable the buffer if we are already capturing events. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (vcnl4010_is_in_periodic_mode(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) VCNL4010_INT_PROX_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) .postenable = &vcnl4010_buffer_postenable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) .predisable = &vcnl4010_buffer_predisable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) static const struct iio_trigger_ops vcnl4010_trigger_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) .validate_device = iio_trigger_validate_own_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct i2c_client *client = data->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) struct iio_trigger *trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) indio_dev->name, indio_dev->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (!trigger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) trigger->dev.parent = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) trigger->ops = &vcnl4010_trigger_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) iio_trigger_set_drvdata(trigger, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return devm_iio_trigger_register(&client->dev, trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static int vcnl4000_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct vcnl4000_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) data->id = id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) ret = data->chip_spec->init(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) data->chip_spec->prod, data->rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (device_property_read_u32(&client->dev, "proximity-near-level",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) &data->near_level))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) data->near_level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) indio_dev->info = data->chip_spec->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) indio_dev->channels = data->chip_spec->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) indio_dev->num_channels = data->chip_spec->num_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) indio_dev->name = VCNL4000_DRV_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (client->irq && data->chip_spec->irq_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) vcnl4010_trigger_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) &vcnl4010_buffer_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) "unable to setup iio triggered buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) ret = devm_request_threaded_irq(&client->dev, client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) NULL, vcnl4010_irq_thread,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) IRQF_TRIGGER_FALLING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) "vcnl4010_irq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) dev_err(&client->dev, "irq request failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) ret = vcnl4010_probe_trigger(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) ret = pm_runtime_set_active(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) goto fail_poweroff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ret = iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) goto fail_poweroff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) pm_runtime_enable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) pm_runtime_use_autosuspend(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) fail_poweroff:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) data->chip_spec->set_power_state(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) static const struct of_device_id vcnl_4000_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) .compatible = "vishay,vcnl4000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) .data = (void *)VCNL4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) .compatible = "vishay,vcnl4010",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) .data = (void *)VCNL4010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) .compatible = "vishay,vcnl4020",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) .data = (void *)VCNL4010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) .compatible = "vishay,vcnl4040",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) .data = (void *)VCNL4040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) .compatible = "vishay,vcnl4200",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) .data = (void *)VCNL4200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) MODULE_DEVICE_TABLE(of, vcnl_4000_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) static int vcnl4000_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) struct iio_dev *indio_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) pm_runtime_dont_use_autosuspend(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) pm_runtime_set_suspended(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return data->chip_spec->set_power_state(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) static int __maybe_unused vcnl4000_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return data->chip_spec->set_power_state(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static int __maybe_unused vcnl4000_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) struct vcnl4000_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return data->chip_spec->set_power_state(data, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) static const struct dev_pm_ops vcnl4000_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) pm_runtime_force_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) SET_RUNTIME_PM_OPS(vcnl4000_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) vcnl4000_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) static struct i2c_driver vcnl4000_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) .name = VCNL4000_DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) .pm = &vcnl4000_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) .of_match_table = vcnl_4000_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) .probe = vcnl4000_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) .id_table = vcnl4000_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) .remove = vcnl4000_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) module_i2c_driver(vcnl4000_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) MODULE_LICENSE("GPL");