62
62
#define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */
63
63
#define VCNL4040_PS_THDL_LM 0x06 /* Proximity threshold low */
64
64
#define VCNL4040_PS_THDH_LM 0x07 /* Proximity threshold high */
65
+ #define VCNL4040_ALS_THDL_LM 0x02 /* Ambient light threshold low */
66
+ #define VCNL4040_ALS_THDH_LM 0x01 /* Ambient light threshold high */
65
67
#define VCNL4200_PS_DATA 0x08 /* Proximity data */
66
68
#define VCNL4200_AL_DATA 0x09 /* Ambient light data */
67
69
#define VCNL4040_INT_FLAGS 0x0b /* Interrupt register */
81
83
82
84
#define VCNL4040_ALS_CONF_ALS_SHUTDOWN BIT(0)
83
85
#define VCNL4040_ALS_CONF_IT GENMASK(7, 6) /* Ambient integration time */
86
+ #define VCNL4040_ALS_CONF_INT_EN BIT(1) /* Ambient light Interrupt enable */
84
87
#define VCNL4040_PS_CONF1_PS_SHUTDOWN BIT(0)
85
88
#define VCNL4040_PS_CONF2_PS_IT GENMASK(3, 1) /* Proximity integration time */
86
89
#define VCNL4040_PS_CONF2_PS_INT GENMASK(9, 8) /* Proximity interrupt mode */
87
90
#define VCNL4040_PS_IF_AWAY BIT(8) /* Proximity event cross low threshold */
88
91
#define VCNL4040_PS_IF_CLOSE BIT(9) /* Proximity event cross high threshold */
92
+ #define VCNL4040_ALS_RISING BIT(12) /* Ambient Light cross high threshold */
93
+ #define VCNL4040_ALS_FALLING BIT(13) /* Ambient Light cross low threshold */
89
94
90
95
/* Bit masks for interrupt registers. */
91
96
#define VCNL4010_INT_THR_SEL BIT(0) /* Select threshold interrupt source */
@@ -170,6 +175,7 @@ struct vcnl4000_data {
170
175
int rev ;
171
176
int al_scale ;
172
177
u8 ps_int ; /* proximity interrupt mode */
178
+ u8 als_int ; /* ambient light interrupt mode*/
173
179
const struct vcnl4000_chip_spec * chip_spec ;
174
180
struct mutex vcnl4000_lock ;
175
181
struct vcnl4200_channel vcnl4200_al ;
@@ -295,7 +301,7 @@ static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
295
301
int ret ;
296
302
297
303
/* Do not power down if interrupts are enabled */
298
- if (!on && data -> ps_int )
304
+ if (!on && ( data -> ps_int || data -> als_int ) )
299
305
return 0 ;
300
306
301
307
ret = vcnl4000_write_als_enable (data , on );
@@ -340,6 +346,7 @@ static int vcnl4200_init(struct vcnl4000_data *data)
340
346
341
347
data -> rev = (ret >> 8 ) & 0xf ;
342
348
data -> ps_int = 0 ;
349
+ data -> als_int = 0 ;
343
350
344
351
data -> vcnl4200_al .reg = VCNL4200_AL_DATA ;
345
352
data -> vcnl4200_ps .reg = VCNL4200_PS_DATA ;
@@ -930,6 +937,26 @@ static int vcnl4040_read_event(struct iio_dev *indio_dev,
930
937
struct vcnl4000_data * data = iio_priv (indio_dev );
931
938
932
939
switch (chan -> type ) {
940
+ case IIO_LIGHT :
941
+ switch (info ) {
942
+ case IIO_EV_INFO_VALUE :
943
+ switch (dir ) {
944
+ case IIO_EV_DIR_RISING :
945
+ ret = i2c_smbus_read_word_data (data -> client ,
946
+ VCNL4040_ALS_THDH_LM );
947
+ break ;
948
+ case IIO_EV_DIR_FALLING :
949
+ ret = i2c_smbus_read_word_data (data -> client ,
950
+ VCNL4040_ALS_THDL_LM );
951
+ break ;
952
+ default :
953
+ return - EINVAL ;
954
+ }
955
+ break ;
956
+ default :
957
+ return - EINVAL ;
958
+ }
959
+ break ;
933
960
case IIO_PROXIMITY :
934
961
switch (info ) {
935
962
case IIO_EV_INFO_VALUE :
@@ -970,6 +997,28 @@ static int vcnl4040_write_event(struct iio_dev *indio_dev,
970
997
struct vcnl4000_data * data = iio_priv (indio_dev );
971
998
972
999
switch (chan -> type ) {
1000
+ case IIO_LIGHT :
1001
+ switch (info ) {
1002
+ case IIO_EV_INFO_VALUE :
1003
+ switch (dir ) {
1004
+ case IIO_EV_DIR_RISING :
1005
+ ret = i2c_smbus_write_word_data (data -> client ,
1006
+ VCNL4040_ALS_THDH_LM ,
1007
+ val );
1008
+ break ;
1009
+ case IIO_EV_DIR_FALLING :
1010
+ ret = i2c_smbus_write_word_data (data -> client ,
1011
+ VCNL4040_ALS_THDL_LM ,
1012
+ val );
1013
+ break ;
1014
+ default :
1015
+ return - EINVAL ;
1016
+ }
1017
+ break ;
1018
+ default :
1019
+ return - EINVAL ;
1020
+ }
1021
+ break ;
973
1022
case IIO_PROXIMITY :
974
1023
switch (info ) {
975
1024
case IIO_EV_INFO_VALUE :
@@ -1091,6 +1140,14 @@ static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
1091
1140
struct vcnl4000_data * data = iio_priv (indio_dev );
1092
1141
1093
1142
switch (chan -> type ) {
1143
+ case IIO_LIGHT :
1144
+ ret = i2c_smbus_read_word_data (data -> client , VCNL4200_AL_CONF );
1145
+ if (ret < 0 )
1146
+ return ret ;
1147
+
1148
+ data -> als_int = FIELD_GET (VCNL4040_ALS_CONF_INT_EN , ret );
1149
+
1150
+ return data -> als_int ;
1094
1151
case IIO_PROXIMITY :
1095
1152
ret = i2c_smbus_read_word_data (data -> client , VCNL4200_PS_CONF1 );
1096
1153
if (ret < 0 )
@@ -1118,6 +1175,21 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
1118
1175
mutex_lock (& data -> vcnl4000_lock );
1119
1176
1120
1177
switch (chan -> type ) {
1178
+ case IIO_LIGHT :
1179
+ ret = i2c_smbus_read_word_data (data -> client , VCNL4200_AL_CONF );
1180
+ if (ret < 0 )
1181
+ goto out ;
1182
+
1183
+ mask = VCNL4040_ALS_CONF_INT_EN ;
1184
+ if (state )
1185
+ val = (ret | mask );
1186
+ else
1187
+ val = (ret & ~mask );
1188
+
1189
+ data -> als_int = FIELD_GET (VCNL4040_ALS_CONF_INT_EN , val );
1190
+ ret = i2c_smbus_write_word_data (data -> client , VCNL4200_AL_CONF ,
1191
+ val );
1192
+ break ;
1121
1193
case IIO_PROXIMITY :
1122
1194
ret = i2c_smbus_read_word_data (data -> client , VCNL4200_PS_CONF1 );
1123
1195
if (ret < 0 )
@@ -1140,7 +1212,7 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
1140
1212
1141
1213
out :
1142
1214
mutex_unlock (& data -> vcnl4000_lock );
1143
- data -> chip_spec -> set_power_state (data , data -> ps_int != 0 );
1215
+ data -> chip_spec -> set_power_state (data , data -> ps_int || data -> als_int );
1144
1216
1145
1217
return ret ;
1146
1218
}
@@ -1171,6 +1243,22 @@ static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
1171
1243
iio_get_time_ns (indio_dev ));
1172
1244
}
1173
1245
1246
+ if (ret & VCNL4040_ALS_FALLING ) {
1247
+ iio_push_event (indio_dev ,
1248
+ IIO_UNMOD_EVENT_CODE (IIO_LIGHT , 0 ,
1249
+ IIO_EV_TYPE_THRESH ,
1250
+ IIO_EV_DIR_FALLING ),
1251
+ iio_get_time_ns (indio_dev ));
1252
+ }
1253
+
1254
+ if (ret & VCNL4040_ALS_RISING ) {
1255
+ iio_push_event (indio_dev ,
1256
+ IIO_UNMOD_EVENT_CODE (IIO_LIGHT , 0 ,
1257
+ IIO_EV_TYPE_THRESH ,
1258
+ IIO_EV_DIR_RISING ),
1259
+ iio_get_time_ns (indio_dev ));
1260
+ }
1261
+
1174
1262
return IRQ_HANDLED ;
1175
1263
}
1176
1264
@@ -1393,6 +1481,8 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
1393
1481
BIT (IIO_CHAN_INFO_SCALE ) |
1394
1482
BIT (IIO_CHAN_INFO_INT_TIME ),
1395
1483
.info_mask_separate_available = BIT (IIO_CHAN_INFO_INT_TIME ),
1484
+ .event_spec = vcnl4000_event_spec ,
1485
+ .num_event_specs = ARRAY_SIZE (vcnl4000_event_spec ),
1396
1486
}, {
1397
1487
.type = IIO_PROXIMITY ,
1398
1488
.info_mask_separate = BIT (IIO_CHAN_INFO_RAW ) |
0 commit comments