1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
4 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
5 *
6 * IIO features supported by the driver:
7 *
8 * Read-only raw channels:
9 * - illuminance_clear [lux]
10 * - illuminance_ir
11 * - proximity
12 *
13 * Triggered buffer:
14 * - illuminance_clear
15 * - illuminance_ir
16 * - proximity
17 *
18 * Events:
19 * - illuminance_clear (rising and falling)
20 * - proximity (rising and falling)
21 * - both falling and rising thresholds for the proximity events
22 * must be set to the values greater than 0.
23 *
24 * The driver supports triggered buffers for all the three
25 * channels as well as high and low threshold events for the
26 * illuminance_clear and proxmimity channels. Triggers
27 * can be enabled simultaneously with both illuminance_clear
28 * events. Proximity events cannot be enabled simultaneously
29 * with any triggers or illuminance events. Enabling/disabling
30 * one of the proximity events automatically enables/disables
31 * the other one.
32 */
33
34#include <linux/debugfs.h>
35#include <linux/delay.h>
36#include <linux/i2c.h>
37#include <linux/interrupt.h>
38#include <linux/irq.h>
39#include <linux/irq_work.h>
40#include <linux/module.h>
41#include <linux/mod_devicetable.h>
42#include <linux/mutex.h>
43#include <linux/regmap.h>
44#include <linux/regulator/consumer.h>
45#include <linux/slab.h>
46#include <asm/unaligned.h>
47#include <linux/iio/buffer.h>
48#include <linux/iio/events.h>
49#include <linux/iio/iio.h>
50#include <linux/iio/sysfs.h>
51#include <linux/iio/trigger.h>
52#include <linux/iio/trigger_consumer.h>
53#include <linux/iio/triggered_buffer.h>
54
55#define GP2A_I2C_NAME "gp2ap020a00f"
56
57/* Registers */
58#define GP2AP020A00F_OP_REG 0x00 /* Basic operations */
59#define GP2AP020A00F_ALS_REG 0x01 /* ALS related settings */
60#define GP2AP020A00F_PS_REG 0x02 /* PS related settings */
61#define GP2AP020A00F_LED_REG 0x03 /* LED reg */
62#define GP2AP020A00F_TL_L_REG 0x04 /* ALS: Threshold low LSB */
63#define GP2AP020A00F_TL_H_REG 0x05 /* ALS: Threshold low MSB */
64#define GP2AP020A00F_TH_L_REG 0x06 /* ALS: Threshold high LSB */
65#define GP2AP020A00F_TH_H_REG 0x07 /* ALS: Threshold high MSB */
66#define GP2AP020A00F_PL_L_REG 0x08 /* PS: Threshold low LSB */
67#define GP2AP020A00F_PL_H_REG 0x09 /* PS: Threshold low MSB */
68#define GP2AP020A00F_PH_L_REG 0x0a /* PS: Threshold high LSB */
69#define GP2AP020A00F_PH_H_REG 0x0b /* PS: Threshold high MSB */
70#define GP2AP020A00F_D0_L_REG 0x0c /* ALS result: Clear/Illuminance LSB */
71#define GP2AP020A00F_D0_H_REG 0x0d /* ALS result: Clear/Illuminance MSB */
72#define GP2AP020A00F_D1_L_REG 0x0e /* ALS result: IR LSB */
73#define GP2AP020A00F_D1_H_REG 0x0f /* ALS result: IR LSB */
74#define GP2AP020A00F_D2_L_REG 0x10 /* PS result LSB */
75#define GP2AP020A00F_D2_H_REG 0x11 /* PS result MSB */
76#define GP2AP020A00F_NUM_REGS 0x12 /* Number of registers */
77
78/* OP_REG bits */
79#define GP2AP020A00F_OP3_MASK 0x80 /* Software shutdown */
80#define GP2AP020A00F_OP3_SHUTDOWN 0x00
81#define GP2AP020A00F_OP3_OPERATION 0x80
82#define GP2AP020A00F_OP2_MASK 0x40 /* Auto shutdown/Continuous mode */
83#define GP2AP020A00F_OP2_AUTO_SHUTDOWN 0x00
84#define GP2AP020A00F_OP2_CONT_OPERATION 0x40
85#define GP2AP020A00F_OP_MASK 0x30 /* Operating mode selection */
86#define GP2AP020A00F_OP_ALS_AND_PS 0x00
87#define GP2AP020A00F_OP_ALS 0x10
88#define GP2AP020A00F_OP_PS 0x20
89#define GP2AP020A00F_OP_DEBUG 0x30
90#define GP2AP020A00F_PROX_MASK 0x08 /* PS: detection/non-detection */
91#define GP2AP020A00F_PROX_NON_DETECT 0x00
92#define GP2AP020A00F_PROX_DETECT 0x08
93#define GP2AP020A00F_FLAG_P 0x04 /* PS: interrupt result */
94#define GP2AP020A00F_FLAG_A 0x02 /* ALS: interrupt result */
95#define GP2AP020A00F_TYPE_MASK 0x01 /* Output data type selection */
96#define GP2AP020A00F_TYPE_MANUAL_CALC 0x00
97#define GP2AP020A00F_TYPE_AUTO_CALC 0x01
98
99/* ALS_REG bits */
100#define GP2AP020A00F_PRST_MASK 0xc0 /* Number of measurement cycles */
101#define GP2AP020A00F_PRST_ONCE 0x00
102#define GP2AP020A00F_PRST_4_CYCLES 0x40
103#define GP2AP020A00F_PRST_8_CYCLES 0x80
104#define GP2AP020A00F_PRST_16_CYCLES 0xc0
105#define GP2AP020A00F_RES_A_MASK 0x38 /* ALS: Resolution */
106#define GP2AP020A00F_RES_A_800ms 0x00
107#define GP2AP020A00F_RES_A_400ms 0x08
108#define GP2AP020A00F_RES_A_200ms 0x10
109#define GP2AP020A00F_RES_A_100ms 0x18
110#define GP2AP020A00F_RES_A_25ms 0x20
111#define GP2AP020A00F_RES_A_6_25ms 0x28
112#define GP2AP020A00F_RES_A_1_56ms 0x30
113#define GP2AP020A00F_RES_A_0_39ms 0x38
114#define GP2AP020A00F_RANGE_A_MASK 0x07 /* ALS: Max measurable range */
115#define GP2AP020A00F_RANGE_A_x1 0x00
116#define GP2AP020A00F_RANGE_A_x2 0x01
117#define GP2AP020A00F_RANGE_A_x4 0x02
118#define GP2AP020A00F_RANGE_A_x8 0x03
119#define GP2AP020A00F_RANGE_A_x16 0x04
120#define GP2AP020A00F_RANGE_A_x32 0x05
121#define GP2AP020A00F_RANGE_A_x64 0x06
122#define GP2AP020A00F_RANGE_A_x128 0x07
123
124/* PS_REG bits */
125#define GP2AP020A00F_ALC_MASK 0x80 /* Auto light cancel */
126#define GP2AP020A00F_ALC_ON 0x80
127#define GP2AP020A00F_ALC_OFF 0x00
128#define GP2AP020A00F_INTTYPE_MASK 0x40 /* Interrupt type setting */
129#define GP2AP020A00F_INTTYPE_LEVEL 0x00
130#define GP2AP020A00F_INTTYPE_PULSE 0x40
131#define GP2AP020A00F_RES_P_MASK 0x38 /* PS: Resolution */
132#define GP2AP020A00F_RES_P_800ms_x2 0x00
133#define GP2AP020A00F_RES_P_400ms_x2 0x08
134#define GP2AP020A00F_RES_P_200ms_x2 0x10
135#define GP2AP020A00F_RES_P_100ms_x2 0x18
136#define GP2AP020A00F_RES_P_25ms_x2 0x20
137#define GP2AP020A00F_RES_P_6_25ms_x2 0x28
138#define GP2AP020A00F_RES_P_1_56ms_x2 0x30
139#define GP2AP020A00F_RES_P_0_39ms_x2 0x38
140#define GP2AP020A00F_RANGE_P_MASK 0x07 /* PS: Max measurable range */
141#define GP2AP020A00F_RANGE_P_x1 0x00
142#define GP2AP020A00F_RANGE_P_x2 0x01
143#define GP2AP020A00F_RANGE_P_x4 0x02
144#define GP2AP020A00F_RANGE_P_x8 0x03
145#define GP2AP020A00F_RANGE_P_x16 0x04
146#define GP2AP020A00F_RANGE_P_x32 0x05
147#define GP2AP020A00F_RANGE_P_x64 0x06
148#define GP2AP020A00F_RANGE_P_x128 0x07
149
150/* LED reg bits */
151#define GP2AP020A00F_INTVAL_MASK 0xc0 /* Intermittent operating */
152#define GP2AP020A00F_INTVAL_0 0x00
153#define GP2AP020A00F_INTVAL_4 0x40
154#define GP2AP020A00F_INTVAL_8 0x80
155#define GP2AP020A00F_INTVAL_16 0xc0
156#define GP2AP020A00F_IS_MASK 0x30 /* ILED drive peak current */
157#define GP2AP020A00F_IS_13_8mA 0x00
158#define GP2AP020A00F_IS_27_5mA 0x10
159#define GP2AP020A00F_IS_55mA 0x20
160#define GP2AP020A00F_IS_110mA 0x30
161#define GP2AP020A00F_PIN_MASK 0x0c /* INT terminal setting */
162#define GP2AP020A00F_PIN_ALS_OR_PS 0x00
163#define GP2AP020A00F_PIN_ALS 0x04
164#define GP2AP020A00F_PIN_PS 0x08
165#define GP2AP020A00F_PIN_PS_DETECT 0x0c
166#define GP2AP020A00F_FREQ_MASK 0x02 /* LED modulation frequency */
167#define GP2AP020A00F_FREQ_327_5kHz 0x00
168#define GP2AP020A00F_FREQ_81_8kHz 0x02
169#define GP2AP020A00F_RST 0x01 /* Software reset */
170
171#define GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR 0
172#define GP2AP020A00F_SCAN_MODE_LIGHT_IR 1
173#define GP2AP020A00F_SCAN_MODE_PROXIMITY 2
174#define GP2AP020A00F_CHAN_TIMESTAMP 3
175
176#define GP2AP020A00F_DATA_READY_TIMEOUT msecs_to_jiffies(1000)
177#define GP2AP020A00F_DATA_REG(chan) (GP2AP020A00F_D0_L_REG + \
178 (chan) * 2)
179#define GP2AP020A00F_THRESH_REG(th_val_id) (GP2AP020A00F_TL_L_REG + \
180 (th_val_id) * 2)
181#define GP2AP020A00F_THRESH_VAL_ID(reg_addr) ((reg_addr - 4) / 2)
182
183#define GP2AP020A00F_SUBTRACT_MODE 0
184#define GP2AP020A00F_ADD_MODE 1
185
186#define GP2AP020A00F_MAX_CHANNELS 3
187
188enum gp2ap020a00f_opmode {
189 GP2AP020A00F_OPMODE_READ_RAW_CLEAR,
190 GP2AP020A00F_OPMODE_READ_RAW_IR,
191 GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY,
192 GP2AP020A00F_OPMODE_ALS,
193 GP2AP020A00F_OPMODE_PS,
194 GP2AP020A00F_OPMODE_ALS_AND_PS,
195 GP2AP020A00F_OPMODE_PROX_DETECT,
196 GP2AP020A00F_OPMODE_SHUTDOWN,
197 GP2AP020A00F_NUM_OPMODES,
198};
199
200enum gp2ap020a00f_cmd {
201 GP2AP020A00F_CMD_READ_RAW_CLEAR,
202 GP2AP020A00F_CMD_READ_RAW_IR,
203 GP2AP020A00F_CMD_READ_RAW_PROXIMITY,
204 GP2AP020A00F_CMD_TRIGGER_CLEAR_EN,
205 GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS,
206 GP2AP020A00F_CMD_TRIGGER_IR_EN,
207 GP2AP020A00F_CMD_TRIGGER_IR_DIS,
208 GP2AP020A00F_CMD_TRIGGER_PROX_EN,
209 GP2AP020A00F_CMD_TRIGGER_PROX_DIS,
210 GP2AP020A00F_CMD_ALS_HIGH_EV_EN,
211 GP2AP020A00F_CMD_ALS_HIGH_EV_DIS,
212 GP2AP020A00F_CMD_ALS_LOW_EV_EN,
213 GP2AP020A00F_CMD_ALS_LOW_EV_DIS,
214 GP2AP020A00F_CMD_PROX_HIGH_EV_EN,
215 GP2AP020A00F_CMD_PROX_HIGH_EV_DIS,
216 GP2AP020A00F_CMD_PROX_LOW_EV_EN,
217 GP2AP020A00F_CMD_PROX_LOW_EV_DIS,
218};
219
220enum gp2ap020a00f_flags {
221 GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER,
222 GP2AP020A00F_FLAG_ALS_IR_TRIGGER,
223 GP2AP020A00F_FLAG_PROX_TRIGGER,
224 GP2AP020A00F_FLAG_PROX_RISING_EV,
225 GP2AP020A00F_FLAG_PROX_FALLING_EV,
226 GP2AP020A00F_FLAG_ALS_RISING_EV,
227 GP2AP020A00F_FLAG_ALS_FALLING_EV,
228 GP2AP020A00F_FLAG_LUX_MODE_HI,
229 GP2AP020A00F_FLAG_DATA_READY,
230};
231
232enum gp2ap020a00f_thresh_val_id {
233 GP2AP020A00F_THRESH_TL,
234 GP2AP020A00F_THRESH_TH,
235 GP2AP020A00F_THRESH_PL,
236 GP2AP020A00F_THRESH_PH,
237};
238
239struct gp2ap020a00f_data {
240 const struct gp2ap020a00f_platform_data *pdata;
241 struct i2c_client *client;
242 struct mutex lock;
243 char *buffer;
244 struct regulator *vled_reg;
245 unsigned long flags;
246 enum gp2ap020a00f_opmode cur_opmode;
247 struct iio_trigger *trig;
248 struct regmap *regmap;
249 unsigned int thresh_val[4];
250 u8 debug_reg_addr;
251 struct irq_work work;
252 wait_queue_head_t data_ready_queue;
253};
254
255static const u8 gp2ap020a00f_reg_init_tab[] = {
256 [GP2AP020A00F_OP_REG] = GP2AP020A00F_OP3_SHUTDOWN,
257 [GP2AP020A00F_ALS_REG] = GP2AP020A00F_RES_A_25ms |
258 GP2AP020A00F_RANGE_A_x8,
259 [GP2AP020A00F_PS_REG] = GP2AP020A00F_ALC_ON |
260 GP2AP020A00F_RES_P_1_56ms_x2 |
261 GP2AP020A00F_RANGE_P_x4,
262 [GP2AP020A00F_LED_REG] = GP2AP020A00F_INTVAL_0 |
263 GP2AP020A00F_IS_110mA |
264 GP2AP020A00F_FREQ_327_5kHz,
265 [GP2AP020A00F_TL_L_REG] = 0,
266 [GP2AP020A00F_TL_H_REG] = 0,
267 [GP2AP020A00F_TH_L_REG] = 0,
268 [GP2AP020A00F_TH_H_REG] = 0,
269 [GP2AP020A00F_PL_L_REG] = 0,
270 [GP2AP020A00F_PL_H_REG] = 0,
271 [GP2AP020A00F_PH_L_REG] = 0,
272 [GP2AP020A00F_PH_H_REG] = 0,
273};
274
275static bool gp2ap020a00f_is_volatile_reg(struct device *dev, unsigned int reg)
276{
277 switch (reg) {
278 case GP2AP020A00F_OP_REG:
279 case GP2AP020A00F_D0_L_REG:
280 case GP2AP020A00F_D0_H_REG:
281 case GP2AP020A00F_D1_L_REG:
282 case GP2AP020A00F_D1_H_REG:
283 case GP2AP020A00F_D2_L_REG:
284 case GP2AP020A00F_D2_H_REG:
285 return true;
286 default:
287 return false;
288 }
289}
290
291static const struct regmap_config gp2ap020a00f_regmap_config = {
292 .reg_bits = 8,
293 .val_bits = 8,
294
295 .max_register = GP2AP020A00F_D2_H_REG,
296 .cache_type = REGCACHE_RBTREE,
297
298 .volatile_reg = gp2ap020a00f_is_volatile_reg,
299};
300
301static const struct gp2ap020a00f_mutable_config_regs {
302 u8 op_reg;
303 u8 als_reg;
304 u8 ps_reg;
305 u8 led_reg;
306} opmode_regs_settings[GP2AP020A00F_NUM_OPMODES] = {
307 [GP2AP020A00F_OPMODE_READ_RAW_CLEAR] = {
308 GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
309 | GP2AP020A00F_OP3_OPERATION
310 | GP2AP020A00F_TYPE_AUTO_CALC,
311 GP2AP020A00F_PRST_ONCE,
312 GP2AP020A00F_INTTYPE_LEVEL,
313 GP2AP020A00F_PIN_ALS
314 },
315 [GP2AP020A00F_OPMODE_READ_RAW_IR] = {
316 GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
317 | GP2AP020A00F_OP3_OPERATION
318 | GP2AP020A00F_TYPE_MANUAL_CALC,
319 GP2AP020A00F_PRST_ONCE,
320 GP2AP020A00F_INTTYPE_LEVEL,
321 GP2AP020A00F_PIN_ALS
322 },
323 [GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY] = {
324 GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
325 | GP2AP020A00F_OP3_OPERATION
326 | GP2AP020A00F_TYPE_MANUAL_CALC,
327 GP2AP020A00F_PRST_ONCE,
328 GP2AP020A00F_INTTYPE_LEVEL,
329 GP2AP020A00F_PIN_PS
330 },
331 [GP2AP020A00F_OPMODE_PROX_DETECT] = {
332 GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
333 | GP2AP020A00F_OP3_OPERATION
334 | GP2AP020A00F_TYPE_MANUAL_CALC,
335 GP2AP020A00F_PRST_4_CYCLES,
336 GP2AP020A00F_INTTYPE_PULSE,
337 GP2AP020A00F_PIN_PS_DETECT
338 },
339 [GP2AP020A00F_OPMODE_ALS] = {
340 GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
341 | GP2AP020A00F_OP3_OPERATION
342 | GP2AP020A00F_TYPE_AUTO_CALC,
343 GP2AP020A00F_PRST_ONCE,
344 GP2AP020A00F_INTTYPE_LEVEL,
345 GP2AP020A00F_PIN_ALS
346 },
347 [GP2AP020A00F_OPMODE_PS] = {
348 GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
349 | GP2AP020A00F_OP3_OPERATION
350 | GP2AP020A00F_TYPE_MANUAL_CALC,
351 GP2AP020A00F_PRST_4_CYCLES,
352 GP2AP020A00F_INTTYPE_LEVEL,
353 GP2AP020A00F_PIN_PS
354 },
355 [GP2AP020A00F_OPMODE_ALS_AND_PS] = {
356 GP2AP020A00F_OP_ALS_AND_PS
357 | GP2AP020A00F_OP2_CONT_OPERATION
358 | GP2AP020A00F_OP3_OPERATION
359 | GP2AP020A00F_TYPE_AUTO_CALC,
360 GP2AP020A00F_PRST_4_CYCLES,
361 GP2AP020A00F_INTTYPE_LEVEL,
362 GP2AP020A00F_PIN_ALS_OR_PS
363 },
364 [GP2AP020A00F_OPMODE_SHUTDOWN] = { GP2AP020A00F_OP3_SHUTDOWN, },
365};
366
367static int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data,
368 enum gp2ap020a00f_opmode op)
369{
370 unsigned int op_reg_val;
371 int err;
372
373 if (op != GP2AP020A00F_OPMODE_SHUTDOWN) {
374 err = regmap_read(map: data->regmap, GP2AP020A00F_OP_REG,
375 val: &op_reg_val);
376 if (err < 0)
377 return err;
378 /*
379 * Shutdown the device if the operation being executed entails
380 * mode transition.
381 */
382 if ((opmode_regs_settings[op].op_reg & GP2AP020A00F_OP_MASK) !=
383 (op_reg_val & GP2AP020A00F_OP_MASK)) {
384 /* set shutdown mode */
385 err = regmap_update_bits(map: data->regmap,
386 GP2AP020A00F_OP_REG, GP2AP020A00F_OP3_MASK,
387 GP2AP020A00F_OP3_SHUTDOWN);
388 if (err < 0)
389 return err;
390 }
391
392 err = regmap_update_bits(map: data->regmap, GP2AP020A00F_ALS_REG,
393 GP2AP020A00F_PRST_MASK, val: opmode_regs_settings[op]
394 .als_reg);
395 if (err < 0)
396 return err;
397
398 err = regmap_update_bits(map: data->regmap, GP2AP020A00F_PS_REG,
399 GP2AP020A00F_INTTYPE_MASK, val: opmode_regs_settings[op]
400 .ps_reg);
401 if (err < 0)
402 return err;
403
404 err = regmap_update_bits(map: data->regmap, GP2AP020A00F_LED_REG,
405 GP2AP020A00F_PIN_MASK, val: opmode_regs_settings[op]
406 .led_reg);
407 if (err < 0)
408 return err;
409 }
410
411 /* Set OP_REG and apply operation mode (power on / off) */
412 err = regmap_update_bits(map: data->regmap,
413 GP2AP020A00F_OP_REG,
414 GP2AP020A00F_OP_MASK | GP2AP020A00F_OP2_MASK |
415 GP2AP020A00F_OP3_MASK | GP2AP020A00F_TYPE_MASK,
416 val: opmode_regs_settings[op].op_reg);
417 if (err < 0)
418 return err;
419
420 data->cur_opmode = op;
421
422 return 0;
423}
424
425static bool gp2ap020a00f_als_enabled(struct gp2ap020a00f_data *data)
426{
427 return test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags) ||
428 test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags) ||
429 test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags) ||
430 test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
431}
432
433static bool gp2ap020a00f_prox_detect_enabled(struct gp2ap020a00f_data *data)
434{
435 return test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags) ||
436 test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
437}
438
439static int gp2ap020a00f_write_event_threshold(struct gp2ap020a00f_data *data,
440 enum gp2ap020a00f_thresh_val_id th_val_id,
441 bool enable)
442{
443 __le16 thresh_buf = 0;
444 unsigned int thresh_reg_val;
445
446 if (!enable)
447 thresh_reg_val = 0;
448 else if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags) &&
449 th_val_id != GP2AP020A00F_THRESH_PL &&
450 th_val_id != GP2AP020A00F_THRESH_PH)
451 /*
452 * For the high lux mode ALS threshold has to be scaled down
453 * to allow for proper comparison with the output value.
454 */
455 thresh_reg_val = data->thresh_val[th_val_id] / 16;
456 else
457 thresh_reg_val = data->thresh_val[th_val_id] > 16000 ?
458 16000 :
459 data->thresh_val[th_val_id];
460
461 thresh_buf = cpu_to_le16(thresh_reg_val);
462
463 return regmap_bulk_write(map: data->regmap,
464 GP2AP020A00F_THRESH_REG(th_val_id),
465 val: (u8 *)&thresh_buf, val_count: 2);
466}
467
468static int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data,
469 enum gp2ap020a00f_opmode diff_mode, int add_sub)
470{
471 enum gp2ap020a00f_opmode new_mode;
472
473 if (diff_mode != GP2AP020A00F_OPMODE_ALS &&
474 diff_mode != GP2AP020A00F_OPMODE_PS)
475 return -EINVAL;
476
477 if (add_sub == GP2AP020A00F_ADD_MODE) {
478 if (data->cur_opmode == GP2AP020A00F_OPMODE_SHUTDOWN)
479 new_mode = diff_mode;
480 else
481 new_mode = GP2AP020A00F_OPMODE_ALS_AND_PS;
482 } else {
483 if (data->cur_opmode == GP2AP020A00F_OPMODE_ALS_AND_PS)
484 new_mode = (diff_mode == GP2AP020A00F_OPMODE_ALS) ?
485 GP2AP020A00F_OPMODE_PS :
486 GP2AP020A00F_OPMODE_ALS;
487 else
488 new_mode = GP2AP020A00F_OPMODE_SHUTDOWN;
489 }
490
491 return gp2ap020a00f_set_operation_mode(data, op: new_mode);
492}
493
494static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
495 enum gp2ap020a00f_cmd cmd)
496{
497 int err = 0;
498
499 switch (cmd) {
500 case GP2AP020A00F_CMD_READ_RAW_CLEAR:
501 if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
502 return -EBUSY;
503 err = gp2ap020a00f_set_operation_mode(data,
504 op: GP2AP020A00F_OPMODE_READ_RAW_CLEAR);
505 break;
506 case GP2AP020A00F_CMD_READ_RAW_IR:
507 if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
508 return -EBUSY;
509 err = gp2ap020a00f_set_operation_mode(data,
510 op: GP2AP020A00F_OPMODE_READ_RAW_IR);
511 break;
512 case GP2AP020A00F_CMD_READ_RAW_PROXIMITY:
513 if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
514 return -EBUSY;
515 err = gp2ap020a00f_set_operation_mode(data,
516 op: GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY);
517 break;
518 case GP2AP020A00F_CMD_TRIGGER_CLEAR_EN:
519 if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
520 return -EBUSY;
521 if (!gp2ap020a00f_als_enabled(data))
522 err = gp2ap020a00f_alter_opmode(data,
523 diff_mode: GP2AP020A00F_OPMODE_ALS,
524 GP2AP020A00F_ADD_MODE);
525 set_bit(nr: GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, addr: &data->flags);
526 break;
527 case GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS:
528 clear_bit(nr: GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, addr: &data->flags);
529 if (gp2ap020a00f_als_enabled(data))
530 break;
531 err = gp2ap020a00f_alter_opmode(data,
532 diff_mode: GP2AP020A00F_OPMODE_ALS,
533 GP2AP020A00F_SUBTRACT_MODE);
534 break;
535 case GP2AP020A00F_CMD_TRIGGER_IR_EN:
536 if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
537 return -EBUSY;
538 if (!gp2ap020a00f_als_enabled(data))
539 err = gp2ap020a00f_alter_opmode(data,
540 diff_mode: GP2AP020A00F_OPMODE_ALS,
541 GP2AP020A00F_ADD_MODE);
542 set_bit(nr: GP2AP020A00F_FLAG_ALS_IR_TRIGGER, addr: &data->flags);
543 break;
544 case GP2AP020A00F_CMD_TRIGGER_IR_DIS:
545 clear_bit(nr: GP2AP020A00F_FLAG_ALS_IR_TRIGGER, addr: &data->flags);
546 if (gp2ap020a00f_als_enabled(data))
547 break;
548 err = gp2ap020a00f_alter_opmode(data,
549 diff_mode: GP2AP020A00F_OPMODE_ALS,
550 GP2AP020A00F_SUBTRACT_MODE);
551 break;
552 case GP2AP020A00F_CMD_TRIGGER_PROX_EN:
553 if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
554 return -EBUSY;
555 err = gp2ap020a00f_alter_opmode(data,
556 diff_mode: GP2AP020A00F_OPMODE_PS,
557 GP2AP020A00F_ADD_MODE);
558 set_bit(nr: GP2AP020A00F_FLAG_PROX_TRIGGER, addr: &data->flags);
559 break;
560 case GP2AP020A00F_CMD_TRIGGER_PROX_DIS:
561 clear_bit(nr: GP2AP020A00F_FLAG_PROX_TRIGGER, addr: &data->flags);
562 err = gp2ap020a00f_alter_opmode(data,
563 diff_mode: GP2AP020A00F_OPMODE_PS,
564 GP2AP020A00F_SUBTRACT_MODE);
565 break;
566 case GP2AP020A00F_CMD_ALS_HIGH_EV_EN:
567 if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
568 return 0;
569 if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
570 return -EBUSY;
571 if (!gp2ap020a00f_als_enabled(data)) {
572 err = gp2ap020a00f_alter_opmode(data,
573 diff_mode: GP2AP020A00F_OPMODE_ALS,
574 GP2AP020A00F_ADD_MODE);
575 if (err < 0)
576 return err;
577 }
578 set_bit(nr: GP2AP020A00F_FLAG_ALS_RISING_EV, addr: &data->flags);
579 err = gp2ap020a00f_write_event_threshold(data,
580 th_val_id: GP2AP020A00F_THRESH_TH, enable: true);
581 break;
582 case GP2AP020A00F_CMD_ALS_HIGH_EV_DIS:
583 if (!test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
584 return 0;
585 clear_bit(nr: GP2AP020A00F_FLAG_ALS_RISING_EV, addr: &data->flags);
586 if (!gp2ap020a00f_als_enabled(data)) {
587 err = gp2ap020a00f_alter_opmode(data,
588 diff_mode: GP2AP020A00F_OPMODE_ALS,
589 GP2AP020A00F_SUBTRACT_MODE);
590 if (err < 0)
591 return err;
592 }
593 err = gp2ap020a00f_write_event_threshold(data,
594 th_val_id: GP2AP020A00F_THRESH_TH, enable: false);
595 break;
596 case GP2AP020A00F_CMD_ALS_LOW_EV_EN:
597 if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
598 return 0;
599 if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
600 return -EBUSY;
601 if (!gp2ap020a00f_als_enabled(data)) {
602 err = gp2ap020a00f_alter_opmode(data,
603 diff_mode: GP2AP020A00F_OPMODE_ALS,
604 GP2AP020A00F_ADD_MODE);
605 if (err < 0)
606 return err;
607 }
608 set_bit(nr: GP2AP020A00F_FLAG_ALS_FALLING_EV, addr: &data->flags);
609 err = gp2ap020a00f_write_event_threshold(data,
610 th_val_id: GP2AP020A00F_THRESH_TL, enable: true);
611 break;
612 case GP2AP020A00F_CMD_ALS_LOW_EV_DIS:
613 if (!test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
614 return 0;
615 clear_bit(nr: GP2AP020A00F_FLAG_ALS_FALLING_EV, addr: &data->flags);
616 if (!gp2ap020a00f_als_enabled(data)) {
617 err = gp2ap020a00f_alter_opmode(data,
618 diff_mode: GP2AP020A00F_OPMODE_ALS,
619 GP2AP020A00F_SUBTRACT_MODE);
620 if (err < 0)
621 return err;
622 }
623 err = gp2ap020a00f_write_event_threshold(data,
624 th_val_id: GP2AP020A00F_THRESH_TL, enable: false);
625 break;
626 case GP2AP020A00F_CMD_PROX_HIGH_EV_EN:
627 if (test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
628 return 0;
629 if (gp2ap020a00f_als_enabled(data) ||
630 data->cur_opmode == GP2AP020A00F_OPMODE_PS)
631 return -EBUSY;
632 if (!gp2ap020a00f_prox_detect_enabled(data)) {
633 err = gp2ap020a00f_set_operation_mode(data,
634 op: GP2AP020A00F_OPMODE_PROX_DETECT);
635 if (err < 0)
636 return err;
637 }
638 set_bit(nr: GP2AP020A00F_FLAG_PROX_RISING_EV, addr: &data->flags);
639 err = gp2ap020a00f_write_event_threshold(data,
640 th_val_id: GP2AP020A00F_THRESH_PH, enable: true);
641 break;
642 case GP2AP020A00F_CMD_PROX_HIGH_EV_DIS:
643 if (!test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
644 return 0;
645 clear_bit(nr: GP2AP020A00F_FLAG_PROX_RISING_EV, addr: &data->flags);
646 err = gp2ap020a00f_set_operation_mode(data,
647 op: GP2AP020A00F_OPMODE_SHUTDOWN);
648 if (err < 0)
649 return err;
650 err = gp2ap020a00f_write_event_threshold(data,
651 th_val_id: GP2AP020A00F_THRESH_PH, enable: false);
652 break;
653 case GP2AP020A00F_CMD_PROX_LOW_EV_EN:
654 if (test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
655 return 0;
656 if (gp2ap020a00f_als_enabled(data) ||
657 data->cur_opmode == GP2AP020A00F_OPMODE_PS)
658 return -EBUSY;
659 if (!gp2ap020a00f_prox_detect_enabled(data)) {
660 err = gp2ap020a00f_set_operation_mode(data,
661 op: GP2AP020A00F_OPMODE_PROX_DETECT);
662 if (err < 0)
663 return err;
664 }
665 set_bit(nr: GP2AP020A00F_FLAG_PROX_FALLING_EV, addr: &data->flags);
666 err = gp2ap020a00f_write_event_threshold(data,
667 th_val_id: GP2AP020A00F_THRESH_PL, enable: true);
668 break;
669 case GP2AP020A00F_CMD_PROX_LOW_EV_DIS:
670 if (!test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
671 return 0;
672 clear_bit(nr: GP2AP020A00F_FLAG_PROX_FALLING_EV, addr: &data->flags);
673 err = gp2ap020a00f_set_operation_mode(data,
674 op: GP2AP020A00F_OPMODE_SHUTDOWN);
675 if (err < 0)
676 return err;
677 err = gp2ap020a00f_write_event_threshold(data,
678 th_val_id: GP2AP020A00F_THRESH_PL, enable: false);
679 break;
680 }
681
682 return err;
683}
684
685static int wait_conversion_complete_irq(struct gp2ap020a00f_data *data)
686{
687 int ret;
688
689 ret = wait_event_timeout(data->data_ready_queue,
690 test_bit(GP2AP020A00F_FLAG_DATA_READY,
691 &data->flags),
692 GP2AP020A00F_DATA_READY_TIMEOUT);
693 clear_bit(nr: GP2AP020A00F_FLAG_DATA_READY, addr: &data->flags);
694
695 return ret > 0 ? 0 : -ETIME;
696}
697
698static int gp2ap020a00f_read_output(struct gp2ap020a00f_data *data,
699 unsigned int output_reg, int *val)
700{
701 u8 reg_buf[2];
702 int err;
703
704 err = wait_conversion_complete_irq(data);
705 if (err < 0)
706 dev_dbg(&data->client->dev, "data ready timeout\n");
707
708 err = regmap_bulk_read(map: data->regmap, reg: output_reg, val: reg_buf, val_count: 2);
709 if (err < 0)
710 return err;
711
712 *val = le16_to_cpup(p: (__le16 *)reg_buf);
713
714 return err;
715}
716
717static bool gp2ap020a00f_adjust_lux_mode(struct gp2ap020a00f_data *data,
718 int output_val)
719{
720 u8 new_range = 0xff;
721 int err;
722
723 if (!test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags)) {
724 if (output_val > 16000) {
725 set_bit(nr: GP2AP020A00F_FLAG_LUX_MODE_HI, addr: &data->flags);
726 new_range = GP2AP020A00F_RANGE_A_x128;
727 }
728 } else {
729 if (output_val < 1000) {
730 clear_bit(nr: GP2AP020A00F_FLAG_LUX_MODE_HI, addr: &data->flags);
731 new_range = GP2AP020A00F_RANGE_A_x8;
732 }
733 }
734
735 if (new_range != 0xff) {
736 /* Clear als threshold registers to avoid spurious
737 * events caused by lux mode transition.
738 */
739 err = gp2ap020a00f_write_event_threshold(data,
740 th_val_id: GP2AP020A00F_THRESH_TH, enable: false);
741 if (err < 0) {
742 dev_err(&data->client->dev,
743 "Clearing als threshold register failed.\n");
744 return false;
745 }
746
747 err = gp2ap020a00f_write_event_threshold(data,
748 th_val_id: GP2AP020A00F_THRESH_TL, enable: false);
749 if (err < 0) {
750 dev_err(&data->client->dev,
751 "Clearing als threshold register failed.\n");
752 return false;
753 }
754
755 /* Change lux mode */
756 err = regmap_update_bits(map: data->regmap,
757 GP2AP020A00F_OP_REG,
758 GP2AP020A00F_OP3_MASK,
759 GP2AP020A00F_OP3_SHUTDOWN);
760
761 if (err < 0) {
762 dev_err(&data->client->dev,
763 "Shutting down the device failed.\n");
764 return false;
765 }
766
767 err = regmap_update_bits(map: data->regmap,
768 GP2AP020A00F_ALS_REG,
769 GP2AP020A00F_RANGE_A_MASK,
770 val: new_range);
771
772 if (err < 0) {
773 dev_err(&data->client->dev,
774 "Adjusting device lux mode failed.\n");
775 return false;
776 }
777
778 err = regmap_update_bits(map: data->regmap,
779 GP2AP020A00F_OP_REG,
780 GP2AP020A00F_OP3_MASK,
781 GP2AP020A00F_OP3_OPERATION);
782
783 if (err < 0) {
784 dev_err(&data->client->dev,
785 "Powering up the device failed.\n");
786 return false;
787 }
788
789 /* Adjust als threshold register values to the new lux mode */
790 if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) {
791 err = gp2ap020a00f_write_event_threshold(data,
792 th_val_id: GP2AP020A00F_THRESH_TH, enable: true);
793 if (err < 0) {
794 dev_err(&data->client->dev,
795 "Adjusting als threshold value failed.\n");
796 return false;
797 }
798 }
799
800 if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) {
801 err = gp2ap020a00f_write_event_threshold(data,
802 th_val_id: GP2AP020A00F_THRESH_TL, enable: true);
803 if (err < 0) {
804 dev_err(&data->client->dev,
805 "Adjusting als threshold value failed.\n");
806 return false;
807 }
808 }
809
810 return true;
811 }
812
813 return false;
814}
815
816static void gp2ap020a00f_output_to_lux(struct gp2ap020a00f_data *data,
817 int *output_val)
818{
819 if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags))
820 *output_val *= 16;
821}
822
823static void gp2ap020a00f_iio_trigger_work(struct irq_work *work)
824{
825 struct gp2ap020a00f_data *data =
826 container_of(work, struct gp2ap020a00f_data, work);
827
828 iio_trigger_poll(trig: data->trig);
829}
830
831static irqreturn_t gp2ap020a00f_prox_sensing_handler(int irq, void *data)
832{
833 struct iio_dev *indio_dev = data;
834 struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
835 unsigned int op_reg_val;
836 int ret;
837
838 /* Read interrupt flags */
839 ret = regmap_read(map: priv->regmap, GP2AP020A00F_OP_REG, val: &op_reg_val);
840 if (ret < 0)
841 return IRQ_HANDLED;
842
843 if (gp2ap020a00f_prox_detect_enabled(data: priv)) {
844 if (op_reg_val & GP2AP020A00F_PROX_DETECT) {
845 iio_push_event(indio_dev,
846 IIO_UNMOD_EVENT_CODE(
847 IIO_PROXIMITY,
848 GP2AP020A00F_SCAN_MODE_PROXIMITY,
849 IIO_EV_TYPE_ROC,
850 IIO_EV_DIR_RISING),
851 timestamp: iio_get_time_ns(indio_dev));
852 } else {
853 iio_push_event(indio_dev,
854 IIO_UNMOD_EVENT_CODE(
855 IIO_PROXIMITY,
856 GP2AP020A00F_SCAN_MODE_PROXIMITY,
857 IIO_EV_TYPE_ROC,
858 IIO_EV_DIR_FALLING),
859 timestamp: iio_get_time_ns(indio_dev));
860 }
861 }
862
863 return IRQ_HANDLED;
864}
865
866static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data)
867{
868 struct iio_dev *indio_dev = data;
869 struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
870 u8 op_reg_flags, d0_reg_buf[2];
871 unsigned int output_val, op_reg_val;
872 int thresh_val_id, ret;
873
874 /* Read interrupt flags */
875 ret = regmap_read(map: priv->regmap, GP2AP020A00F_OP_REG,
876 val: &op_reg_val);
877 if (ret < 0)
878 goto done;
879
880 op_reg_flags = op_reg_val & (GP2AP020A00F_FLAG_A | GP2AP020A00F_FLAG_P
881 | GP2AP020A00F_PROX_DETECT);
882
883 op_reg_val &= (~GP2AP020A00F_FLAG_A & ~GP2AP020A00F_FLAG_P
884 & ~GP2AP020A00F_PROX_DETECT);
885
886 /* Clear interrupt flags (if not in INTTYPE_PULSE mode) */
887 if (priv->cur_opmode != GP2AP020A00F_OPMODE_PROX_DETECT) {
888 ret = regmap_write(map: priv->regmap, GP2AP020A00F_OP_REG,
889 val: op_reg_val);
890 if (ret < 0)
891 goto done;
892 }
893
894 if (op_reg_flags & GP2AP020A00F_FLAG_A) {
895 /* Check D0 register to assess if the lux mode
896 * transition is required.
897 */
898 ret = regmap_bulk_read(map: priv->regmap, GP2AP020A00F_D0_L_REG,
899 val: d0_reg_buf, val_count: 2);
900 if (ret < 0)
901 goto done;
902
903 output_val = le16_to_cpup(p: (__le16 *)d0_reg_buf);
904
905 if (gp2ap020a00f_adjust_lux_mode(data: priv, output_val))
906 goto done;
907
908 gp2ap020a00f_output_to_lux(data: priv, output_val: &output_val);
909
910 /*
911 * We need to check output value to distinguish
912 * between high and low ambient light threshold event.
913 */
914 if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &priv->flags)) {
915 thresh_val_id =
916 GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TH_L_REG);
917 if (output_val > priv->thresh_val[thresh_val_id])
918 iio_push_event(indio_dev,
919 IIO_MOD_EVENT_CODE(
920 IIO_LIGHT,
921 GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
922 IIO_MOD_LIGHT_CLEAR,
923 IIO_EV_TYPE_THRESH,
924 IIO_EV_DIR_RISING),
925 timestamp: iio_get_time_ns(indio_dev));
926 }
927
928 if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &priv->flags)) {
929 thresh_val_id =
930 GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TL_L_REG);
931 if (output_val < priv->thresh_val[thresh_val_id])
932 iio_push_event(indio_dev,
933 IIO_MOD_EVENT_CODE(
934 IIO_LIGHT,
935 GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
936 IIO_MOD_LIGHT_CLEAR,
937 IIO_EV_TYPE_THRESH,
938 IIO_EV_DIR_FALLING),
939 timestamp: iio_get_time_ns(indio_dev));
940 }
941 }
942
943 if (priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_CLEAR ||
944 priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_IR ||
945 priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY) {
946 set_bit(nr: GP2AP020A00F_FLAG_DATA_READY, addr: &priv->flags);
947 wake_up(&priv->data_ready_queue);
948 goto done;
949 }
950
951 if (test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &priv->flags) ||
952 test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &priv->flags) ||
953 test_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &priv->flags))
954 /* This fires off the trigger. */
955 irq_work_queue(work: &priv->work);
956
957done:
958 return IRQ_HANDLED;
959}
960
961static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
962{
963 struct iio_poll_func *pf = data;
964 struct iio_dev *indio_dev = pf->indio_dev;
965 struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
966 size_t d_size = 0;
967 int i, out_val, ret;
968
969 for_each_set_bit(i, indio_dev->active_scan_mask,
970 indio_dev->masklength) {
971 ret = regmap_bulk_read(map: priv->regmap,
972 GP2AP020A00F_DATA_REG(i),
973 val: &priv->buffer[d_size], val_count: 2);
974 if (ret < 0)
975 goto done;
976
977 if (i == GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR ||
978 i == GP2AP020A00F_SCAN_MODE_LIGHT_IR) {
979 out_val = le16_to_cpup(p: (__le16 *)&priv->buffer[d_size]);
980 gp2ap020a00f_output_to_lux(data: priv, output_val: &out_val);
981
982 put_unaligned_le32(val: out_val, p: &priv->buffer[d_size]);
983 d_size += 4;
984 } else {
985 d_size += 2;
986 }
987 }
988
989 iio_push_to_buffers_with_timestamp(indio_dev, data: priv->buffer,
990 timestamp: pf->timestamp);
991done:
992 iio_trigger_notify_done(trig: indio_dev->trig);
993
994 return IRQ_HANDLED;
995}
996
997static u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan,
998 enum iio_event_direction event_dir)
999{
1000 switch (chan->type) {
1001 case IIO_PROXIMITY:
1002 if (event_dir == IIO_EV_DIR_RISING)
1003 return GP2AP020A00F_PH_L_REG;
1004 else
1005 return GP2AP020A00F_PL_L_REG;
1006 case IIO_LIGHT:
1007 if (event_dir == IIO_EV_DIR_RISING)
1008 return GP2AP020A00F_TH_L_REG;
1009 else
1010 return GP2AP020A00F_TL_L_REG;
1011 default:
1012 break;
1013 }
1014
1015 return -EINVAL;
1016}
1017
1018static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
1019 const struct iio_chan_spec *chan,
1020 enum iio_event_type type,
1021 enum iio_event_direction dir,
1022 enum iio_event_info info,
1023 int val, int val2)
1024{
1025 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1026 bool event_en = false;
1027 u8 thresh_val_id;
1028 u8 thresh_reg_l;
1029 int err = 0;
1030
1031 mutex_lock(&data->lock);
1032
1033 thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, event_dir: dir);
1034 thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l);
1035
1036 if (thresh_val_id > GP2AP020A00F_THRESH_PH) {
1037 err = -EINVAL;
1038 goto error_unlock;
1039 }
1040
1041 switch (thresh_reg_l) {
1042 case GP2AP020A00F_TH_L_REG:
1043 event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
1044 &data->flags);
1045 break;
1046 case GP2AP020A00F_TL_L_REG:
1047 event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
1048 &data->flags);
1049 break;
1050 case GP2AP020A00F_PH_L_REG:
1051 if (val == 0) {
1052 err = -EINVAL;
1053 goto error_unlock;
1054 }
1055 event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
1056 &data->flags);
1057 break;
1058 case GP2AP020A00F_PL_L_REG:
1059 if (val == 0) {
1060 err = -EINVAL;
1061 goto error_unlock;
1062 }
1063 event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
1064 &data->flags);
1065 break;
1066 }
1067
1068 data->thresh_val[thresh_val_id] = val;
1069 err = gp2ap020a00f_write_event_threshold(data, th_val_id: thresh_val_id,
1070 enable: event_en);
1071error_unlock:
1072 mutex_unlock(lock: &data->lock);
1073
1074 return err;
1075}
1076
1077static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev,
1078 const struct iio_chan_spec *chan,
1079 enum iio_event_type type,
1080 enum iio_event_direction dir,
1081 enum iio_event_info info,
1082 int *val, int *val2)
1083{
1084 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1085 u8 thresh_reg_l;
1086 int err = IIO_VAL_INT;
1087
1088 mutex_lock(&data->lock);
1089
1090 thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, event_dir: dir);
1091
1092 if (thresh_reg_l > GP2AP020A00F_PH_L_REG) {
1093 err = -EINVAL;
1094 goto error_unlock;
1095 }
1096
1097 *val = data->thresh_val[GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l)];
1098
1099error_unlock:
1100 mutex_unlock(lock: &data->lock);
1101
1102 return err;
1103}
1104
1105static int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev,
1106 int state)
1107{
1108 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1109 enum gp2ap020a00f_cmd cmd_high_ev, cmd_low_ev;
1110 int err;
1111
1112 cmd_high_ev = state ? GP2AP020A00F_CMD_PROX_HIGH_EV_EN :
1113 GP2AP020A00F_CMD_PROX_HIGH_EV_DIS;
1114 cmd_low_ev = state ? GP2AP020A00F_CMD_PROX_LOW_EV_EN :
1115 GP2AP020A00F_CMD_PROX_LOW_EV_DIS;
1116
1117 /*
1118 * In order to enable proximity detection feature in the device
1119 * both high and low threshold registers have to be written
1120 * with different values, greater than zero.
1121 */
1122 if (state) {
1123 if (data->thresh_val[GP2AP020A00F_THRESH_PL] == 0)
1124 return -EINVAL;
1125
1126 if (data->thresh_val[GP2AP020A00F_THRESH_PH] == 0)
1127 return -EINVAL;
1128 }
1129
1130 err = gp2ap020a00f_exec_cmd(data, cmd: cmd_high_ev);
1131 if (err < 0)
1132 return err;
1133
1134 err = gp2ap020a00f_exec_cmd(data, cmd: cmd_low_ev);
1135 if (err < 0)
1136 return err;
1137
1138 free_irq(data->client->irq, indio_dev);
1139
1140 if (state)
1141 err = request_threaded_irq(irq: data->client->irq, NULL,
1142 thread_fn: &gp2ap020a00f_prox_sensing_handler,
1143 IRQF_TRIGGER_RISING |
1144 IRQF_TRIGGER_FALLING |
1145 IRQF_ONESHOT,
1146 name: "gp2ap020a00f_prox_sensing",
1147 dev: indio_dev);
1148 else {
1149 err = request_threaded_irq(irq: data->client->irq, NULL,
1150 thread_fn: &gp2ap020a00f_thresh_event_handler,
1151 IRQF_TRIGGER_FALLING |
1152 IRQF_ONESHOT,
1153 name: "gp2ap020a00f_thresh_event",
1154 dev: indio_dev);
1155 }
1156
1157 return err;
1158}
1159
1160static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
1161 const struct iio_chan_spec *chan,
1162 enum iio_event_type type,
1163 enum iio_event_direction dir,
1164 int state)
1165{
1166 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1167 enum gp2ap020a00f_cmd cmd;
1168 int err;
1169
1170 mutex_lock(&data->lock);
1171
1172 switch (chan->type) {
1173 case IIO_PROXIMITY:
1174 err = gp2ap020a00f_write_prox_event_config(indio_dev, state);
1175 break;
1176 case IIO_LIGHT:
1177 if (dir == IIO_EV_DIR_RISING) {
1178 cmd = state ? GP2AP020A00F_CMD_ALS_HIGH_EV_EN :
1179 GP2AP020A00F_CMD_ALS_HIGH_EV_DIS;
1180 err = gp2ap020a00f_exec_cmd(data, cmd);
1181 } else {
1182 cmd = state ? GP2AP020A00F_CMD_ALS_LOW_EV_EN :
1183 GP2AP020A00F_CMD_ALS_LOW_EV_DIS;
1184 err = gp2ap020a00f_exec_cmd(data, cmd);
1185 }
1186 break;
1187 default:
1188 err = -EINVAL;
1189 }
1190
1191 mutex_unlock(lock: &data->lock);
1192
1193 return err;
1194}
1195
1196static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev,
1197 const struct iio_chan_spec *chan,
1198 enum iio_event_type type,
1199 enum iio_event_direction dir)
1200{
1201 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1202 int event_en = 0;
1203
1204 mutex_lock(&data->lock);
1205
1206 switch (chan->type) {
1207 case IIO_PROXIMITY:
1208 if (dir == IIO_EV_DIR_RISING)
1209 event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
1210 &data->flags);
1211 else
1212 event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
1213 &data->flags);
1214 break;
1215 case IIO_LIGHT:
1216 if (dir == IIO_EV_DIR_RISING)
1217 event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
1218 &data->flags);
1219 else
1220 event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
1221 &data->flags);
1222 break;
1223 default:
1224 event_en = -EINVAL;
1225 break;
1226 }
1227
1228 mutex_unlock(lock: &data->lock);
1229
1230 return event_en;
1231}
1232
1233static int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data,
1234 struct iio_chan_spec const *chan, int *val)
1235{
1236 enum gp2ap020a00f_cmd cmd;
1237 int err;
1238
1239 switch (chan->scan_index) {
1240 case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
1241 cmd = GP2AP020A00F_CMD_READ_RAW_CLEAR;
1242 break;
1243 case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
1244 cmd = GP2AP020A00F_CMD_READ_RAW_IR;
1245 break;
1246 case GP2AP020A00F_SCAN_MODE_PROXIMITY:
1247 cmd = GP2AP020A00F_CMD_READ_RAW_PROXIMITY;
1248 break;
1249 default:
1250 return -EINVAL;
1251 }
1252
1253 err = gp2ap020a00f_exec_cmd(data, cmd);
1254 if (err < 0) {
1255 dev_err(&data->client->dev,
1256 "gp2ap020a00f_exec_cmd failed\n");
1257 goto error_ret;
1258 }
1259
1260 err = gp2ap020a00f_read_output(data, output_reg: chan->address, val);
1261 if (err < 0)
1262 dev_err(&data->client->dev,
1263 "gp2ap020a00f_read_output failed\n");
1264
1265 err = gp2ap020a00f_set_operation_mode(data,
1266 op: GP2AP020A00F_OPMODE_SHUTDOWN);
1267 if (err < 0)
1268 dev_err(&data->client->dev,
1269 "Failed to shut down the device.\n");
1270
1271 if (cmd == GP2AP020A00F_CMD_READ_RAW_CLEAR ||
1272 cmd == GP2AP020A00F_CMD_READ_RAW_IR)
1273 gp2ap020a00f_output_to_lux(data, output_val: val);
1274
1275error_ret:
1276 return err;
1277}
1278
1279static int gp2ap020a00f_read_raw(struct iio_dev *indio_dev,
1280 struct iio_chan_spec const *chan,
1281 int *val, int *val2,
1282 long mask)
1283{
1284 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1285 int err = -EINVAL;
1286
1287 if (mask == IIO_CHAN_INFO_RAW) {
1288 err = iio_device_claim_direct_mode(indio_dev);
1289 if (err)
1290 return err;
1291
1292 err = gp2ap020a00f_read_channel(data, chan, val);
1293 iio_device_release_direct_mode(indio_dev);
1294 }
1295 return err < 0 ? err : IIO_VAL_INT;
1296}
1297
1298static const struct iio_event_spec gp2ap020a00f_event_spec_light[] = {
1299 {
1300 .type = IIO_EV_TYPE_THRESH,
1301 .dir = IIO_EV_DIR_RISING,
1302 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
1303 BIT(IIO_EV_INFO_ENABLE),
1304 }, {
1305 .type = IIO_EV_TYPE_THRESH,
1306 .dir = IIO_EV_DIR_FALLING,
1307 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
1308 BIT(IIO_EV_INFO_ENABLE),
1309 },
1310};
1311
1312static const struct iio_event_spec gp2ap020a00f_event_spec_prox[] = {
1313 {
1314 .type = IIO_EV_TYPE_ROC,
1315 .dir = IIO_EV_DIR_RISING,
1316 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
1317 BIT(IIO_EV_INFO_ENABLE),
1318 }, {
1319 .type = IIO_EV_TYPE_ROC,
1320 .dir = IIO_EV_DIR_FALLING,
1321 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
1322 BIT(IIO_EV_INFO_ENABLE),
1323 },
1324};
1325
1326static const struct iio_chan_spec gp2ap020a00f_channels[] = {
1327 {
1328 .type = IIO_LIGHT,
1329 .channel2 = IIO_MOD_LIGHT_CLEAR,
1330 .modified = 1,
1331 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1332 .scan_type = {
1333 .sign = 'u',
1334 .realbits = 24,
1335 .shift = 0,
1336 .storagebits = 32,
1337 .endianness = IIO_LE,
1338 },
1339 .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
1340 .address = GP2AP020A00F_D0_L_REG,
1341 .event_spec = gp2ap020a00f_event_spec_light,
1342 .num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_light),
1343 },
1344 {
1345 .type = IIO_LIGHT,
1346 .channel2 = IIO_MOD_LIGHT_IR,
1347 .modified = 1,
1348 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1349 .scan_type = {
1350 .sign = 'u',
1351 .realbits = 24,
1352 .shift = 0,
1353 .storagebits = 32,
1354 .endianness = IIO_LE,
1355 },
1356 .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_IR,
1357 .address = GP2AP020A00F_D1_L_REG,
1358 },
1359 {
1360 .type = IIO_PROXIMITY,
1361 .modified = 0,
1362 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1363 .scan_type = {
1364 .sign = 'u',
1365 .realbits = 16,
1366 .shift = 0,
1367 .storagebits = 16,
1368 .endianness = IIO_LE,
1369 },
1370 .scan_index = GP2AP020A00F_SCAN_MODE_PROXIMITY,
1371 .address = GP2AP020A00F_D2_L_REG,
1372 .event_spec = gp2ap020a00f_event_spec_prox,
1373 .num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_prox),
1374 },
1375 IIO_CHAN_SOFT_TIMESTAMP(GP2AP020A00F_CHAN_TIMESTAMP),
1376};
1377
1378static const struct iio_info gp2ap020a00f_info = {
1379 .read_raw = &gp2ap020a00f_read_raw,
1380 .read_event_value = &gp2ap020a00f_read_event_val,
1381 .read_event_config = &gp2ap020a00f_read_event_config,
1382 .write_event_value = &gp2ap020a00f_write_event_val,
1383 .write_event_config = &gp2ap020a00f_write_event_config,
1384};
1385
1386static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev)
1387{
1388 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1389 int i, err = 0;
1390
1391 mutex_lock(&data->lock);
1392
1393 /*
1394 * Enable triggers according to the scan_mask. Enabling either
1395 * LIGHT_CLEAR or LIGHT_IR scan mode results in enabling ALS
1396 * module in the device, which generates samples in both D0 (clear)
1397 * and D1 (ir) registers. As the two registers are bound to the
1398 * two separate IIO channels they are treated in the driver logic
1399 * as if they were controlled independently.
1400 */
1401 for_each_set_bit(i, indio_dev->active_scan_mask,
1402 indio_dev->masklength) {
1403 switch (i) {
1404 case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
1405 err = gp2ap020a00f_exec_cmd(data,
1406 cmd: GP2AP020A00F_CMD_TRIGGER_CLEAR_EN);
1407 break;
1408 case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
1409 err = gp2ap020a00f_exec_cmd(data,
1410 cmd: GP2AP020A00F_CMD_TRIGGER_IR_EN);
1411 break;
1412 case GP2AP020A00F_SCAN_MODE_PROXIMITY:
1413 err = gp2ap020a00f_exec_cmd(data,
1414 cmd: GP2AP020A00F_CMD_TRIGGER_PROX_EN);
1415 break;
1416 }
1417 }
1418
1419 if (err < 0)
1420 goto error_unlock;
1421
1422 data->buffer = kmalloc(size: indio_dev->scan_bytes, GFP_KERNEL);
1423 if (!data->buffer)
1424 err = -ENOMEM;
1425
1426error_unlock:
1427 mutex_unlock(lock: &data->lock);
1428
1429 return err;
1430}
1431
1432static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev)
1433{
1434 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1435 int i, err = 0;
1436
1437 mutex_lock(&data->lock);
1438
1439 for_each_set_bit(i, indio_dev->active_scan_mask,
1440 indio_dev->masklength) {
1441 switch (i) {
1442 case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
1443 err = gp2ap020a00f_exec_cmd(data,
1444 cmd: GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS);
1445 break;
1446 case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
1447 err = gp2ap020a00f_exec_cmd(data,
1448 cmd: GP2AP020A00F_CMD_TRIGGER_IR_DIS);
1449 break;
1450 case GP2AP020A00F_SCAN_MODE_PROXIMITY:
1451 err = gp2ap020a00f_exec_cmd(data,
1452 cmd: GP2AP020A00F_CMD_TRIGGER_PROX_DIS);
1453 break;
1454 }
1455 }
1456
1457 if (err == 0)
1458 kfree(objp: data->buffer);
1459
1460 mutex_unlock(lock: &data->lock);
1461
1462 return err;
1463}
1464
1465static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = {
1466 .postenable = &gp2ap020a00f_buffer_postenable,
1467 .predisable = &gp2ap020a00f_buffer_predisable,
1468};
1469
1470static int gp2ap020a00f_probe(struct i2c_client *client)
1471{
1472 const struct i2c_device_id *id = i2c_client_get_device_id(client);
1473 struct gp2ap020a00f_data *data;
1474 struct iio_dev *indio_dev;
1475 struct regmap *regmap;
1476 int err;
1477
1478 indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*data));
1479 if (!indio_dev)
1480 return -ENOMEM;
1481
1482 data = iio_priv(indio_dev);
1483
1484 data->vled_reg = devm_regulator_get(dev: &client->dev, id: "vled");
1485 if (IS_ERR(ptr: data->vled_reg))
1486 return PTR_ERR(ptr: data->vled_reg);
1487
1488 err = regulator_enable(regulator: data->vled_reg);
1489 if (err)
1490 return err;
1491
1492 regmap = devm_regmap_init_i2c(client, &gp2ap020a00f_regmap_config);
1493 if (IS_ERR(ptr: regmap)) {
1494 dev_err(&client->dev, "Regmap initialization failed.\n");
1495 err = PTR_ERR(ptr: regmap);
1496 goto error_regulator_disable;
1497 }
1498
1499 /* Initialize device registers */
1500 err = regmap_bulk_write(map: regmap, GP2AP020A00F_OP_REG,
1501 val: gp2ap020a00f_reg_init_tab,
1502 ARRAY_SIZE(gp2ap020a00f_reg_init_tab));
1503
1504 if (err < 0) {
1505 dev_err(&client->dev, "Device initialization failed.\n");
1506 goto error_regulator_disable;
1507 }
1508
1509 i2c_set_clientdata(client, data: indio_dev);
1510
1511 data->client = client;
1512 data->cur_opmode = GP2AP020A00F_OPMODE_SHUTDOWN;
1513 data->regmap = regmap;
1514 init_waitqueue_head(&data->data_ready_queue);
1515
1516 mutex_init(&data->lock);
1517 indio_dev->channels = gp2ap020a00f_channels;
1518 indio_dev->num_channels = ARRAY_SIZE(gp2ap020a00f_channels);
1519 indio_dev->info = &gp2ap020a00f_info;
1520 indio_dev->name = id->name;
1521 indio_dev->modes = INDIO_DIRECT_MODE;
1522
1523 /* Allocate buffer */
1524 err = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
1525 &gp2ap020a00f_trigger_handler, &gp2ap020a00f_buffer_setup_ops);
1526 if (err < 0)
1527 goto error_regulator_disable;
1528
1529 /* Allocate trigger */
1530 data->trig = devm_iio_trigger_alloc(&client->dev, "%s-trigger",
1531 indio_dev->name);
1532 if (data->trig == NULL) {
1533 err = -ENOMEM;
1534 dev_err(&indio_dev->dev, "Failed to allocate iio trigger.\n");
1535 goto error_uninit_buffer;
1536 }
1537
1538 /* This needs to be requested here for read_raw calls to work. */
1539 err = request_threaded_irq(irq: client->irq, NULL,
1540 thread_fn: &gp2ap020a00f_thresh_event_handler,
1541 IRQF_TRIGGER_FALLING |
1542 IRQF_ONESHOT,
1543 name: "gp2ap020a00f_als_event",
1544 dev: indio_dev);
1545 if (err < 0) {
1546 dev_err(&client->dev, "Irq request failed.\n");
1547 goto error_uninit_buffer;
1548 }
1549
1550 init_irq_work(work: &data->work, func: gp2ap020a00f_iio_trigger_work);
1551
1552 err = iio_trigger_register(trig_info: data->trig);
1553 if (err < 0) {
1554 dev_err(&client->dev, "Failed to register iio trigger.\n");
1555 goto error_free_irq;
1556 }
1557
1558 err = iio_device_register(indio_dev);
1559 if (err < 0)
1560 goto error_trigger_unregister;
1561
1562 return 0;
1563
1564error_trigger_unregister:
1565 iio_trigger_unregister(trig_info: data->trig);
1566error_free_irq:
1567 free_irq(client->irq, indio_dev);
1568error_uninit_buffer:
1569 iio_triggered_buffer_cleanup(indio_dev);
1570error_regulator_disable:
1571 regulator_disable(regulator: data->vled_reg);
1572
1573 return err;
1574}
1575
1576static void gp2ap020a00f_remove(struct i2c_client *client)
1577{
1578 struct iio_dev *indio_dev = i2c_get_clientdata(client);
1579 struct gp2ap020a00f_data *data = iio_priv(indio_dev);
1580 int err;
1581
1582 err = gp2ap020a00f_set_operation_mode(data,
1583 op: GP2AP020A00F_OPMODE_SHUTDOWN);
1584 if (err < 0)
1585 dev_err(&indio_dev->dev, "Failed to power off the device.\n");
1586
1587 iio_device_unregister(indio_dev);
1588 iio_trigger_unregister(trig_info: data->trig);
1589 free_irq(client->irq, indio_dev);
1590 iio_triggered_buffer_cleanup(indio_dev);
1591 regulator_disable(regulator: data->vled_reg);
1592}
1593
1594static const struct i2c_device_id gp2ap020a00f_id[] = {
1595 { GP2A_I2C_NAME, 0 },
1596 { }
1597};
1598
1599MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id);
1600
1601static const struct of_device_id gp2ap020a00f_of_match[] = {
1602 { .compatible = "sharp,gp2ap020a00f" },
1603 { }
1604};
1605MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
1606
1607static struct i2c_driver gp2ap020a00f_driver = {
1608 .driver = {
1609 .name = GP2A_I2C_NAME,
1610 .of_match_table = gp2ap020a00f_of_match,
1611 },
1612 .probe = gp2ap020a00f_probe,
1613 .remove = gp2ap020a00f_remove,
1614 .id_table = gp2ap020a00f_id,
1615};
1616
1617module_i2c_driver(gp2ap020a00f_driver);
1618
1619MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
1620MODULE_DESCRIPTION("Sharp GP2AP020A00F Proximity/ALS sensor driver");
1621MODULE_LICENSE("GPL v2");
1622

source code of linux/drivers/iio/light/gp2ap020a00f.c