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