History

Input: add Analog Devices AD714x captouch input driver

AD7142 and AD7147 are integrated capacitance-to-digital converters (CDCs) with on-chip environmental calibration for use in systems requiring a novel user input method. The AD7142 and AD7147 can interface to external capacitance sensors implementing functions such as buttons, scrollwheels, sliders, touchpads and so on. The chips don't restrict the specific usage. Depending on the hardware connection, one special target board can include one or several these components. The platform_data for the device's "struct device" holds these information. The data-struct defined in head file descript the hardware feature of button/scrollwheel/slider/touchpad components on target boards, which need be filled in the arch/mach-/. As the result, the driver is independent of boards. It gets the components layout from the platform_data, registers related devices, fullfills the algorithms and state machines for these components and report related input events to up level.

Bryan Wu committed 16 years ago

Commit 31a62961 parent a5b33e68 files · +1694 −0Browse files

Unified · Split

8 files
  1. drivers/input/misc/Kconfig +30 −0
  2. drivers/input/misc/Makefile +3 −0
  3. drivers/input/misc/ad714x-i2c.c +137 −0
  4. drivers/input/misc/ad714x-spi.c +103 −0
  5. drivers/input/misc/ad714x.c +1331 −0
  6. drivers/input/misc/ad714x.h +26 −0
  7. include/linux/input.h +1 −0
  8. include/linux/input/ad714x.h +63 −0
drivers/input/misc/Kconfig+30−0
@@ -22,6 +22,36 @@ config INPUT_88PM860X_ONKEY · 21 unmodified lines
2222 To compile this driver as a module, choose M here: the module
2323 will be called 88pm860x_onkey.
2424
25+config INPUT_AD714X
26+ tristate "Analog Devices AD714x Capacitance Touch Sensor"
27+ help
28+ Say Y here if you want to support an AD7142/AD7147 touch sensor.
29+
30+ You should select a bus connection too.
31+
32+ To compile this driver as a module, choose M here: the
33+ module will be called ad714x.
34+
35+config INPUT_AD714X_I2C
36+ tristate "support I2C bus connection"
37+ depends on INPUT_AD714X && I2C
38+ default y
39+ help
40+ Say Y here if you have AD7142/AD7147 hooked to an I2C bus.
41+
42+ To compile this driver as a module, choose M here: the
43+ module will be called ad714x-i2c.
44+
45+config INPUT_AD714X_SPI
46+ tristate "support SPI bus connection"
47+ depends on INPUT_AD714X && SPI
48+ default y
49+ help
50+ Say Y here if you have AD7142/AD7147 hooked to a SPI bus.
51+
52+ To compile this driver as a module, choose M here: the
53+ module will be called ad714x-spi.
54+
2555 config INPUT_PCSPKR
2656 tristate "PC Speaker support"
2757 depends on PCSPKR_PLATFORM
drivers/input/misc/Makefile+3−0
@@ -5,6 +5,9 @@ · 4 unmodified lines
55 # Each configuration option enables a list of files.
66
77 obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o
8+obj-$(CONFIG_INPUT_AD714X) += ad714x.o
9+obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o
10+obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o
811 obj-$(CONFIG_INPUT_APANEL) += apanel.o
912 obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o
1013 obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
drivers/input/misc/ad714x-i2c.c+137−0
@@ -0,0 +1,137 @@
1+/*
2+ * AD714X CapTouch Programmable Controller driver (I2C bus)
3+ *
4+ * Copyright 2009 Analog Devices Inc.
5+ *
6+ * Licensed under the GPL-2 or later.
7+ */
8+
9+#include <linux/input.h> /* BUS_I2C */
10+#include <linux/i2c.h>
11+#include <linux/module.h>
12+#include <linux/types.h>
13+#include "ad714x.h"
14+
15+#ifdef CONFIG_PM
16+static int ad714x_i2c_suspend(struct i2c_client *client, pm_message_t message)
17+{
18+ return ad714x_disable(i2c_get_clientdata(client));
19+}
20+
21+static int ad714x_i2c_resume(struct i2c_client *client)
22+{
23+ return ad714x_enable(i2c_get_clientdata(client));
24+}
25+#else
26+# define ad714x_i2c_suspend NULL
27+# define ad714x_i2c_resume NULL
28+#endif
29+
30+static int ad714x_i2c_write(struct device *dev, unsigned short reg,
31+ unsigned short data)
32+{
33+ struct i2c_client *client = to_i2c_client(dev);
34+ int ret = 0;
35+ u8 *_reg = (u8 *)&reg;
36+ u8 *_data = (u8 *)&data;
37+
38+ u8 tx[4] = {
39+ _reg[1],
40+ _reg[0],
41+ _data[1],
42+ _data[0]
43+ };
44+
45+ ret = i2c_master_send(client, tx, 4);
46+ if (ret < 0)
47+ dev_err(&client->dev, "I2C write error\n");
48+
49+ return ret;
50+}
51+
52+static int ad714x_i2c_read(struct device *dev, unsigned short reg,
53+ unsigned short *data)
54+{
55+ struct i2c_client *client = to_i2c_client(dev);
56+ int ret = 0;
57+ u8 *_reg = (u8 *)&reg;
58+ u8 *_data = (u8 *)data;
59+
60+ u8 tx[2] = {
61+ _reg[1],
62+ _reg[0]
63+ };
64+ u8 rx[2];
65+
66+ ret = i2c_master_send(client, tx, 2);
67+ if (ret >= 0)
68+ ret = i2c_master_recv(client, rx, 2);
69+
70+ if (unlikely(ret < 0)) {
71+ dev_err(&client->dev, "I2C read error\n");
72+ } else {
73+ _data[0] = rx[1];
74+ _data[1] = rx[0];
75+ }
76+
77+ return ret;
78+}
79+
80+static int __devinit ad714x_i2c_probe(struct i2c_client *client,
81+ const struct i2c_device_id *id)
82+{
83+ struct ad714x_chip *chip;
84+
85+ chip = ad714x_probe(&client->dev, BUS_I2C, client->irq,
86+ ad714x_i2c_read, ad714x_i2c_write);
87+ if (IS_ERR(chip))
88+ return PTR_ERR(chip);
89+
90+ i2c_set_clientdata(client, chip);
91+
92+ return 0;
93+}
94+
95+static int __devexit ad714x_i2c_remove(struct i2c_client *client)
96+{
97+ struct ad714x_chip *chip = i2c_get_clientdata(client);
98+
99+ ad714x_remove(chip);
100+ i2c_set_clientdata(client, NULL);
101+
102+ return 0;
103+}
104+
105+static const struct i2c_device_id ad714x_id[] = {
106+ { "ad7142_captouch", 0 },
107+ { "ad7147_captouch", 0 },
108+ { }
109+};
110+MODULE_DEVICE_TABLE(i2c, ad714x_id);
111+
112+static struct i2c_driver ad714x_i2c_driver = {
113+ .driver = {
114+ .name = "ad714x_captouch",
115+ },
116+ .probe = ad714x_i2c_probe,
117+ .remove = __devexit_p(ad714x_i2c_remove),
118+ .suspend = ad714x_i2c_suspend,
119+ .resume = ad714x_i2c_resume,
120+ .id_table = ad714x_id,
121+};
122+
123+static __init int ad714x_i2c_init(void)
124+{
125+ return i2c_add_driver(&ad714x_i2c_driver);
126+}
127+module_init(ad714x_i2c_init);
128+
129+static __exit void ad714x_i2c_exit(void)
130+{
131+ i2c_del_driver(&ad714x_i2c_driver);
132+}
133+module_exit(ad714x_i2c_exit);
134+
135+MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor I2C Bus Driver");
136+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
137+MODULE_LICENSE("GPL");
drivers/input/misc/ad714x-spi.c+103−0
@@ -0,0 +1,103 @@
1+/*
2+ * AD714X CapTouch Programmable Controller driver (SPI bus)
3+ *
4+ * Copyright 2009 Analog Devices Inc.
5+ *
6+ * Licensed under the GPL-2 or later.
7+ */
8+
9+#include <linux/input.h> /* BUS_I2C */
10+#include <linux/module.h>
11+#include <linux/spi/spi.h>
12+#include <linux/types.h>
13+#include "ad714x.h"
14+
15+#define AD714x_SPI_CMD_PREFIX 0xE000 /* bits 15:11 */
16+#define AD714x_SPI_READ BIT(10)
17+
18+#ifdef CONFIG_PM
19+static int ad714x_spi_suspend(struct spi_device *spi, pm_message_t message)
20+{
21+ return ad714x_disable(spi_get_drvdata(spi));
22+}
23+
24+static int ad714x_spi_resume(struct spi_device *spi)
25+{
26+ return ad714x_enable(spi_get_drvdata(spi));
27+}
28+#else
29+# define ad714x_spi_suspend NULL
30+# define ad714x_spi_resume NULL
31+#endif
32+
33+static int ad714x_spi_read(struct device *dev, unsigned short reg,
34+ unsigned short *data)
35+{
36+ struct spi_device *spi = to_spi_device(dev);
37+ unsigned short tx = AD714x_SPI_CMD_PREFIX | AD714x_SPI_READ | reg;
38+
39+ return spi_write_then_read(spi, (u8 *)&tx, 2, (u8 *)data, 2);
40+}
41+
42+static int ad714x_spi_write(struct device *dev, unsigned short reg,
43+ unsigned short data)
44+{
45+ struct spi_device *spi = to_spi_device(dev);
46+ unsigned short tx[2] = {
47+ AD714x_SPI_CMD_PREFIX | reg,
48+ data
49+ };
50+
51+ return spi_write(spi, (u8 *)tx, 4);
52+}
53+
54+static int __devinit ad714x_spi_probe(struct spi_device *spi)
55+{
56+ struct ad714x_chip *chip;
57+
58+ chip = ad714x_probe(&spi->dev, BUS_SPI, spi->irq,
59+ ad714x_spi_read, ad714x_spi_write);
60+ if (IS_ERR(chip))
61+ return PTR_ERR(chip);
62+
63+ spi_set_drvdata(spi, chip);
64+
65+ return 0;
66+}
67+
68+static int __devexit ad714x_spi_remove(struct spi_device *spi)
69+{
70+ struct ad714x_chip *chip = spi_get_drvdata(spi);
71+
72+ ad714x_remove(chip);
73+ spi_set_drvdata(spi, NULL);
74+
75+ return 0;
76+}
77+
78+static struct spi_driver ad714x_spi_driver = {
79+ .driver = {
80+ .name = "ad714x_captouch",
81+ .owner = THIS_MODULE,
82+ },
83+ .probe = ad714x_spi_probe,
84+ .remove = __devexit_p(ad714x_spi_remove),
85+ .suspend = ad714x_spi_suspend,
86+ .resume = ad714x_spi_resume,
87+};
88+
89+static __init int ad714x_spi_init(void)
90+{
91+ return spi_register_driver(&ad714x_spi_driver);
92+}
93+module_init(ad714x_spi_init);
94+
95+static __exit void ad714x_spi_exit(void)
96+{
97+ spi_unregister_driver(&ad714x_spi_driver);
98+}
99+module_exit(ad714x_spi_exit);
100+
101+MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor SPI Bus Driver");
102+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
103+MODULE_LICENSE("GPL");
drivers/input/misc/ad714x.c+1331−0
@@ -0,0 +1,1331 @@
1+/*
2+ * AD714X CapTouch Programmable Controller driver
3+ *
4+ * Copyright 2009 Analog Devices Inc.
5+ *
6+ * Licensed under the GPL-2 or later.
7+ */
8+
9+#include <linux/device.h>
10+#include <linux/init.h>
11+#include <linux/input.h>
12+#include <linux/interrupt.h>
13+#include <linux/slab.h>
14+#include <linux/input/ad714x.h>
15+#include "ad714x.h"
16+
17+#define AD714X_PWR_CTRL 0x0
18+#define AD714X_STG_CAL_EN_REG 0x1
19+#define AD714X_AMB_COMP_CTRL0_REG 0x2
20+#define AD714X_PARTID_REG 0x17
21+#define AD7147_PARTID 0x1470
22+#define AD7142_PARTID 0xE620
23+#define AD714X_STAGECFG_REG 0x80
24+#define AD714X_SYSCFG_REG 0x0
25+
26+#define STG_LOW_INT_EN_REG 0x5
27+#define STG_HIGH_INT_EN_REG 0x6
28+#define STG_COM_INT_EN_REG 0x7
29+#define STG_LOW_INT_STA_REG 0x8
30+#define STG_HIGH_INT_STA_REG 0x9
31+#define STG_COM_INT_STA_REG 0xA
32+
33+#define CDC_RESULT_S0 0xB
34+#define CDC_RESULT_S1 0xC
35+#define CDC_RESULT_S2 0xD
36+#define CDC_RESULT_S3 0xE
37+#define CDC_RESULT_S4 0xF
38+#define CDC_RESULT_S5 0x10
39+#define CDC_RESULT_S6 0x11
40+#define CDC_RESULT_S7 0x12
41+#define CDC_RESULT_S8 0x13
42+#define CDC_RESULT_S9 0x14
43+#define CDC_RESULT_S10 0x15
44+#define CDC_RESULT_S11 0x16
45+
46+#define STAGE0_AMBIENT 0xF1
47+#define STAGE1_AMBIENT 0x115
48+#define STAGE2_AMBIENT 0x139
49+#define STAGE3_AMBIENT 0x15D
50+#define STAGE4_AMBIENT 0x181
51+#define STAGE5_AMBIENT 0x1A5
52+#define STAGE6_AMBIENT 0x1C9
53+#define STAGE7_AMBIENT 0x1ED
54+#define STAGE8_AMBIENT 0x211
55+#define STAGE9_AMBIENT 0x234
56+#define STAGE10_AMBIENT 0x259
57+#define STAGE11_AMBIENT 0x27D
58+
59+#define PER_STAGE_REG_NUM 36
60+#define STAGE_NUM 12
61+#define STAGE_CFGREG_NUM 8
62+#define SYS_CFGREG_NUM 8
63+
64+/*
65+ * driver information which will be used to maintain the software flow
66+ */
67+enum ad714x_device_state { IDLE, JITTER, ACTIVE, SPACE };
68+
69+struct ad714x_slider_drv {
70+ int highest_stage;
71+ int abs_pos;
72+ int flt_pos;
73+ enum ad714x_device_state state;
74+ struct input_dev *input;
75+};
76+
77+struct ad714x_wheel_drv {
78+ int abs_pos;
79+ int flt_pos;
80+ int pre_mean_value;
81+ int pre_highest_stage;
82+ int pre_mean_value_no_offset;
83+ int mean_value;
84+ int mean_value_no_offset;
85+ int pos_offset;
86+ int pos_ratio;
87+ int highest_stage;
88+ enum ad714x_device_state state;
89+ struct input_dev *input;
90+};
91+
92+struct ad714x_touchpad_drv {
93+ int x_highest_stage;
94+ int x_flt_pos;
95+ int x_abs_pos;
96+ int y_highest_stage;
97+ int y_flt_pos;
98+ int y_abs_pos;
99+ int left_ep;
100+ int left_ep_val;
101+ int right_ep;
102+ int right_ep_val;
103+ int top_ep;
104+ int top_ep_val;
105+ int bottom_ep;
106+ int bottom_ep_val;
107+ enum ad714x_device_state state;
108+ struct input_dev *input;
109+};
110+
111+struct ad714x_button_drv {
112+ enum ad714x_device_state state;
113+ /*
114+ * Unlike slider/wheel/touchpad, all buttons point to
115+ * same input_dev instance
116+ */
117+ struct input_dev *input;
118+};
119+
120+struct ad714x_driver_data {
121+ struct ad714x_slider_drv *slider;
122+ struct ad714x_wheel_drv *wheel;
123+ struct ad714x_touchpad_drv *touchpad;
124+ struct ad714x_button_drv *button;
125+};
126+
127+/*
128+ * information to integrate all things which will be private data
129+ * of spi/i2c device
130+ */
131+struct ad714x_chip {
132+ unsigned short h_state;
133+ unsigned short l_state;
134+ unsigned short c_state;
135+ unsigned short adc_reg[STAGE_NUM];
136+ unsigned short amb_reg[STAGE_NUM];
137+ unsigned short sensor_val[STAGE_NUM];
138+
139+ struct ad714x_platform_data *hw;
140+ struct ad714x_driver_data *sw;
141+
142+ int irq;
143+ struct device *dev;
144+ ad714x_read_t read;
145+ ad714x_write_t write;
146+
147+ struct mutex mutex;
148+
149+ unsigned product;
150+ unsigned version;
151+};
152+
153+static void ad714x_use_com_int(struct ad714x_chip *ad714x,
154+ int start_stage, int end_stage)
155+{
156+ unsigned short data;
157+ unsigned short mask;
158+
159+ mask = ((1 << (end_stage + 1)) - 1) - (1 << start_stage);
160+
161+ ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data);
162+ data |= 1 << start_stage;
163+ ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data);
164+
165+ ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data);
166+ data &= ~mask;
167+ ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data);
168+}
169+
170+static void ad714x_use_thr_int(struct ad714x_chip *ad714x,
171+ int start_stage, int end_stage)
172+{
173+ unsigned short data;
174+ unsigned short mask;
175+
176+ mask = ((1 << (end_stage + 1)) - 1) - (1 << start_stage);
177+
178+ ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data);
179+ data &= ~(1 << start_stage);
180+ ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data);
181+
182+ ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data);
183+ data |= mask;
184+ ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data);
185+}
186+
187+static int ad714x_cal_highest_stage(struct ad714x_chip *ad714x,
188+ int start_stage, int end_stage)
189+{
190+ int max_res = 0;
191+ int max_idx = 0;
192+ int i;
193+
194+ for (i = start_stage; i <= end_stage; i++) {
195+ if (ad714x->sensor_val[i] > max_res) {
196+ max_res = ad714x->sensor_val[i];
197+ max_idx = i;
198+ }
199+ }
200+
201+ return max_idx;
202+}
203+
204+static int ad714x_cal_abs_pos(struct ad714x_chip *ad714x,
205+ int start_stage, int end_stage,
206+ int highest_stage, int max_coord)
207+{
208+ int a_param, b_param;
209+
210+ if (highest_stage == start_stage) {
211+ a_param = ad714x->sensor_val[start_stage + 1];
212+ b_param = ad714x->sensor_val[start_stage] +
213+ ad714x->sensor_val[start_stage + 1];
214+ } else if (highest_stage == end_stage) {
215+ a_param = ad714x->sensor_val[end_stage] *
216+ (end_stage - start_stage) +
217+ ad714x->sensor_val[end_stage - 1] *
218+ (end_stage - start_stage - 1);
219+ b_param = ad714x->sensor_val[end_stage] +
220+ ad714x->sensor_val[end_stage - 1];
221+ } else {
222+ a_param = ad714x->sensor_val[highest_stage] *
223+ (highest_stage - start_stage) +
224+ ad714x->sensor_val[highest_stage - 1] *
225+ (highest_stage - start_stage - 1) +
226+ ad714x->sensor_val[highest_stage + 1] *
227+ (highest_stage - start_stage + 1);
228+ b_param = ad714x->sensor_val[highest_stage] +
229+ ad714x->sensor_val[highest_stage - 1] +
230+ ad714x->sensor_val[highest_stage + 1];
231+ }
232+
233+ return (max_coord / (end_stage - start_stage)) * a_param / b_param;
234+}
235+
236+/*
237+ * One button can connect to multi positive and negative of CDCs
238+ * Multi-buttons can connect to same positive/negative of one CDC
239+ */
240+static void ad714x_button_state_machine(struct ad714x_chip *ad714x, int idx)
241+{
242+ struct ad714x_button_plat *hw = &ad714x->hw->button[idx];
243+ struct ad714x_button_drv *sw = &ad714x->sw->button[idx];
244+
245+ switch (sw->state) {
246+ case IDLE:
247+ if (((ad714x->h_state & hw->h_mask) == hw->h_mask) &&
248+ ((ad714x->l_state & hw->l_mask) == hw->l_mask)) {
249+ dev_dbg(ad714x->dev, "button %d touched\n", idx);
250+ input_report_key(sw->input, hw->keycode, 1);
251+ input_sync(sw->input);
252+ sw->state = ACTIVE;
253+ }
254+ break;
255+
256+ case ACTIVE:
257+ if (((ad714x->h_state & hw->h_mask) != hw->h_mask) ||
258+ ((ad714x->l_state & hw->l_mask) != hw->l_mask)) {
259+ dev_dbg(ad714x->dev, "button %d released\n", idx);
260+ input_report_key(sw->input, hw->keycode, 0);
261+ input_sync(sw->input);
262+ sw->state = IDLE;
263+ }
264+ break;
265+
266+ default:
267+ break;
268+ }
269+}
270+
271+/*
272+ * The response of a sensor is defined by the absolute number of codes
273+ * between the current CDC value and the ambient value.
274+ */
275+static void ad714x_slider_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
276+{
277+ struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
278+ int i;
279+
280+ for (i = hw->start_stage; i <= hw->end_stage; i++) {
281+ ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
282+ &ad714x->adc_reg[i]);
283+ ad714x->read(ad714x->dev,
284+ STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
285+ &ad714x->amb_reg[i]);
286+
287+ ad714x->sensor_val[i] = abs(ad714x->adc_reg[i] -
288+ ad714x->amb_reg[i]);
289+ }
290+}
291+
292+static void ad714x_slider_cal_highest_stage(struct ad714x_chip *ad714x, int idx)
293+{
294+ struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
295+ struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx];
296+
297+ sw->highest_stage = ad714x_cal_highest_stage(ad714x, hw->start_stage,
298+ hw->end_stage);
299+
300+ dev_dbg(ad714x->dev, "slider %d highest_stage:%d\n", idx,
301+ sw->highest_stage);
302+}
303+
304+/*
305+ * The formulae are very straight forward. It uses the sensor with the
306+ * highest response and the 2 adjacent ones.
307+ * When Sensor 0 has the highest response, only sensor 0 and sensor 1
308+ * are used in the calculations. Similarly when the last sensor has the
309+ * highest response, only the last sensor and the second last sensors
310+ * are used in the calculations.
311+ *
312+ * For i= idx_of_peak_Sensor-1 to i= idx_of_peak_Sensor+1
313+ * v += Sensor response(i)*i
314+ * w += Sensor response(i)
315+ * POS=(Number_of_Positions_Wanted/(Number_of_Sensors_Used-1)) *(v/w)
316+ */
317+static void ad714x_slider_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
318+{
319+ struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
320+ struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx];
321+
322+ sw->abs_pos = ad714x_cal_abs_pos(ad714x, hw->start_stage, hw->end_stage,
323+ sw->highest_stage, hw->max_coord);
324+
325+ dev_dbg(ad714x->dev, "slider %d absolute position:%d\n", idx,
326+ sw->abs_pos);
327+}
328+
329+/*
330+ * To minimise the Impact of the noise on the algorithm, ADI developed a
331+ * routine that filters the CDC results after they have been read by the
332+ * host processor.
333+ * The filter used is an Infinite Input Response(IIR) filter implemented
334+ * in firmware and attenuates the noise on the CDC results after they've
335+ * been read by the host processor.
336+ * Filtered_CDC_result = (Filtered_CDC_result * (10 - Coefficient) +
337+ * Latest_CDC_result * Coefficient)/10
338+ */
339+static void ad714x_slider_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
340+{
341+ struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx];
342+
343+ sw->flt_pos = (sw->flt_pos * (10 - 4) +
344+ sw->abs_pos * 4)/10;
345+
346+ dev_dbg(ad714x->dev, "slider %d filter position:%d\n", idx,
347+ sw->flt_pos);
348+}
349+
350+static void ad714x_slider_use_com_int(struct ad714x_chip *ad714x, int idx)
351+{
352+ struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
353+
354+ ad714x_use_com_int(ad714x, hw->start_stage, hw->end_stage);
355+}
356+
357+static void ad714x_slider_use_thr_int(struct ad714x_chip *ad714x, int idx)
358+{
359+ struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
360+
361+ ad714x_use_thr_int(ad714x, hw->start_stage, hw->end_stage);
362+}
363+
364+static void ad714x_slider_state_machine(struct ad714x_chip *ad714x, int idx)
365+{
366+ struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
367+ struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx];
368+ unsigned short h_state, c_state;
369+ unsigned short mask;
370+
371+ mask = ((1 << (hw->end_stage + 1)) - 1) - ((1 << hw->start_stage) - 1);
372+
373+ h_state = ad714x->h_state & mask;
374+ c_state = ad714x->c_state & mask;
375+
376+ switch (sw->state) {
377+ case IDLE:
378+ if (h_state) {
379+ sw->state = JITTER;
380+ /* In End of Conversion interrupt mode, the AD714X
381+ * continuously generates hardware interrupts.
382+ */
383+ ad714x_slider_use_com_int(ad714x, idx);
384+ dev_dbg(ad714x->dev, "slider %d touched\n", idx);
385+ }
386+ break;
387+
388+ case JITTER:
389+ if (c_state == mask) {
390+ ad714x_slider_cal_sensor_val(ad714x, idx);
391+ ad714x_slider_cal_highest_stage(ad714x, idx);
392+ ad714x_slider_cal_abs_pos(ad714x, idx);
393+ sw->flt_pos = sw->abs_pos;
394+ sw->state = ACTIVE;
395+ }
396+ break;
397+
398+ case ACTIVE:
399+ if (c_state == mask) {
400+ if (h_state) {
401+ ad714x_slider_cal_sensor_val(ad714x, idx);
402+ ad714x_slider_cal_highest_stage(ad714x, idx);
403+ ad714x_slider_cal_abs_pos(ad714x, idx);
404+ ad714x_slider_cal_flt_pos(ad714x, idx);
405+
406+ input_report_abs(sw->input, ABS_X, sw->flt_pos);
407+ input_report_key(sw->input, BTN_TOUCH, 1);
408+ } else {
409+ /* When the user lifts off the sensor, configure
410+ * the AD714X back to threshold interrupt mode.
411+ */
412+ ad714x_slider_use_thr_int(ad714x, idx);
413+ sw->state = IDLE;
414+ input_report_key(sw->input, BTN_TOUCH, 0);
415+ dev_dbg(ad714x->dev, "slider %d released\n",
416+ idx);
417+ }
418+ input_sync(sw->input);
419+ }
420+ break;
421+
422+ default:
423+ break;
424+ }
425+}
426+
427+/*
428+ * When the scroll wheel is activated, we compute the absolute position based
429+ * on the sensor values. To calculate the position, we first determine the
430+ * sensor that has the greatest response among the 8 sensors that constitutes
431+ * the scrollwheel. Then we determined the 2 sensors on either sides of the
432+ * sensor with the highest response and we apply weights to these sensors.
433+ */
434+static void ad714x_wheel_cal_highest_stage(struct ad714x_chip *ad714x, int idx)
435+{
436+ struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
437+ struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
438+
439+ sw->pre_highest_stage = sw->highest_stage;
440+ sw->highest_stage = ad714x_cal_highest_stage(ad714x, hw->start_stage,
441+ hw->end_stage);
442+
443+ dev_dbg(ad714x->dev, "wheel %d highest_stage:%d\n", idx,
444+ sw->highest_stage);
445+}
446+
447+static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
448+{
449+ struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
450+ int i;
451+
452+ for (i = hw->start_stage; i <= hw->end_stage; i++) {
453+ ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
454+ &ad714x->adc_reg[i]);
455+ ad714x->read(ad714x->dev,
456+ STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
457+ &ad714x->amb_reg[i]);
458+ if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
459+ ad714x->sensor_val[i] = ad714x->adc_reg[i] -
460+ ad714x->amb_reg[i];
461+ else
462+ ad714x->sensor_val[i] = 0;
463+ }
464+}
465+
466+/*
467+ * When the scroll wheel is activated, we compute the absolute position based
468+ * on the sensor values. To calculate the position, we first determine the
469+ * sensor that has the greatest response among the 8 sensors that constitutes
470+ * the scrollwheel. Then we determined the 2 sensors on either sides of the
471+ * sensor with the highest response and we apply weights to these sensors. The
472+ * result of this computation gives us the mean value which defined by the
473+ * following formula:
474+ * For i= second_before_highest_stage to i= second_after_highest_stage
475+ * v += Sensor response(i)*WEIGHT*(i+3)
476+ * w += Sensor response(i)
477+ * Mean_Value=v/w
478+ * pos_on_scrollwheel = (Mean_Value - position_offset) / position_ratio
479+ */
480+
481+#define WEIGHT_FACTOR 30
482+/* This constant prevents the "PositionOffset" from reaching a big value */
483+#define OFFSET_POSITION_CLAMP 120
484+static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
485+{
486+ struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
487+ struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
488+ int stage_num = hw->end_stage - hw->start_stage + 1;
489+ int second_before, first_before, highest, first_after, second_after;
490+ int a_param, b_param;
491+
492+ /* Calculate Mean value */
493+
494+ second_before = (sw->highest_stage + stage_num - 2) % stage_num;
495+ first_before = (sw->highest_stage + stage_num - 1) % stage_num;
496+ highest = sw->highest_stage;
497+ first_after = (sw->highest_stage + stage_num + 1) % stage_num;
498+ second_after = (sw->highest_stage + stage_num + 2) % stage_num;
499+
500+ if (((sw->highest_stage - hw->start_stage) > 1) &&
501+ ((hw->end_stage - sw->highest_stage) > 1)) {
502+ a_param = ad714x->sensor_val[second_before] *
503+ (second_before - hw->start_stage + 3) +
504+ ad714x->sensor_val[first_before] *
505+ (second_before - hw->start_stage + 3) +
506+ ad714x->sensor_val[highest] *
507+ (second_before - hw->start_stage + 3) +
508+ ad714x->sensor_val[first_after] *
509+ (first_after - hw->start_stage + 3) +
510+ ad714x->sensor_val[second_after] *
511+ (second_after - hw->start_stage + 3);
512+ } else {
513+ a_param = ad714x->sensor_val[second_before] *
514+ (second_before - hw->start_stage + 1) +
515+ ad714x->sensor_val[first_before] *
516+ (second_before - hw->start_stage + 2) +
517+ ad714x->sensor_val[highest] *
518+ (second_before - hw->start_stage + 3) +
519+ ad714x->sensor_val[first_after] *
520+ (first_after - hw->start_stage + 4) +
521+ ad714x->sensor_val[second_after] *
522+ (second_after - hw->start_stage + 5);
523+ }
524+ a_param *= WEIGHT_FACTOR;
525+
526+ b_param = ad714x->sensor_val[second_before] +
527+ ad714x->sensor_val[first_before] +
528+ ad714x->sensor_val[highest] +
529+ ad714x->sensor_val[first_after] +
530+ ad714x->sensor_val[second_after];
531+
532+ sw->pre_mean_value = sw->mean_value;
533+ sw->mean_value = a_param / b_param;
534+
535+ /* Calculate the offset */
536+
537+ if ((sw->pre_highest_stage == hw->end_stage) &&
538+ (sw->highest_stage == hw->start_stage))
539+ sw->pos_offset = sw->mean_value;
540+ else if ((sw->pre_highest_stage == hw->start_stage) &&
541+ (sw->highest_stage == hw->end_stage))
542+ sw->pos_offset = sw->pre_mean_value;
543+
544+ if (sw->pos_offset > OFFSET_POSITION_CLAMP)
545+ sw->pos_offset = OFFSET_POSITION_CLAMP;
546+
547+ /* Calculate the mean value without the offset */
548+
549+ sw->pre_mean_value_no_offset = sw->mean_value_no_offset;
550+ sw->mean_value_no_offset = sw->mean_value - sw->pos_offset;
551+ if (sw->mean_value_no_offset < 0)
552+ sw->mean_value_no_offset = 0;
553+
554+ /* Calculate ratio to scale down to NUMBER_OF_WANTED_POSITIONS */
555+
556+ if ((sw->pre_highest_stage == hw->end_stage) &&
557+ (sw->highest_stage == hw->start_stage))
558+ sw->pos_ratio = (sw->pre_mean_value_no_offset * 100) /
559+ hw->max_coord;
560+ else if ((sw->pre_highest_stage == hw->start_stage) &&
561+ (sw->highest_stage == hw->end_stage))
562+ sw->pos_ratio = (sw->mean_value_no_offset * 100) /
563+ hw->max_coord;
564+ sw->abs_pos = (sw->mean_value_no_offset * 100) / sw->pos_ratio;
565+ if (sw->abs_pos > hw->max_coord)
566+ sw->abs_pos = hw->max_coord;
567+}
568+
569+static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
570+{
571+ struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
572+ struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
573+ if (((sw->pre_highest_stage == hw->end_stage) &&
574+ (sw->highest_stage == hw->start_stage)) ||
575+ ((sw->pre_highest_stage == hw->start_stage) &&
576+ (sw->highest_stage == hw->end_stage)))
577+ sw->flt_pos = sw->abs_pos;
578+ else
579+ sw->flt_pos = ((sw->flt_pos * 30) + (sw->abs_pos * 71)) / 100;
580+
581+ if (sw->flt_pos > hw->max_coord)
582+ sw->flt_pos = hw->max_coord;
583+}
584+
585+static void ad714x_wheel_use_com_int(struct ad714x_chip *ad714x, int idx)
586+{
587+ struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
588+
589+ ad714x_use_com_int(ad714x, hw->start_stage, hw->end_stage);
590+}
591+
592+static void ad714x_wheel_use_thr_int(struct ad714x_chip *ad714x, int idx)
593+{
594+ struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
595+
596+ ad714x_use_thr_int(ad714x, hw->start_stage, hw->end_stage);
597+}
598+
599+static void ad714x_wheel_state_machine(struct ad714x_chip *ad714x, int idx)
600+{
601+ struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
602+ struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
603+ unsigned short h_state, c_state;
604+ unsigned short mask;
605+
606+ mask = ((1 << (hw->end_stage + 1)) - 1) - ((1 << hw->start_stage) - 1);
607+
608+ h_state = ad714x->h_state & mask;
609+ c_state = ad714x->c_state & mask;
610+
611+ switch (sw->state) {
612+ case IDLE:
613+ if (h_state) {
614+ sw->state = JITTER;
615+ /* In End of Conversion interrupt mode, the AD714X
616+ * continuously generates hardware interrupts.
617+ */
618+ ad714x_wheel_use_com_int(ad714x, idx);
619+ dev_dbg(ad714x->dev, "wheel %d touched\n", idx);
620+ }
621+ break;
622+
623+ case JITTER:
624+ if (c_state == mask) {
625+ ad714x_wheel_cal_sensor_val(ad714x, idx);
626+ ad714x_wheel_cal_highest_stage(ad714x, idx);
627+ ad714x_wheel_cal_abs_pos(ad714x, idx);
628+ sw->flt_pos = sw->abs_pos;
629+ sw->state = ACTIVE;
630+ }
631+ break;
632+
633+ case ACTIVE:
634+ if (c_state == mask) {
635+ if (h_state) {
636+ ad714x_wheel_cal_sensor_val(ad714x, idx);
637+ ad714x_wheel_cal_highest_stage(ad714x, idx);
638+ ad714x_wheel_cal_abs_pos(ad714x, idx);
639+ ad714x_wheel_cal_flt_pos(ad714x, idx);
640+
641+ input_report_abs(sw->input, ABS_WHEEL,
642+ sw->abs_pos);
643+ input_report_key(sw->input, BTN_TOUCH, 1);
644+ } else {
645+ /* When the user lifts off the sensor, configure
646+ * the AD714X back to threshold interrupt mode.
647+ */
648+ ad714x_wheel_use_thr_int(ad714x, idx);
649+ sw->state = IDLE;
650+ input_report_key(sw->input, BTN_TOUCH, 0);
651+
652+ dev_dbg(ad714x->dev, "wheel %d released\n",
653+ idx);
654+ }
655+ input_sync(sw->input);
656+ }
657+ break;
658+
659+ default:
660+ break;
661+ }
662+}
663+
664+static void touchpad_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
665+{
666+ struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
667+ int i;
668+
669+ for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) {
670+ ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
671+ &ad714x->adc_reg[i]);
672+ ad714x->read(ad714x->dev,
673+ STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
674+ &ad714x->amb_reg[i]);
675+ if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
676+ ad714x->sensor_val[i] = ad714x->adc_reg[i] -
677+ ad714x->amb_reg[i];
678+ else
679+ ad714x->sensor_val[i] = 0;
680+ }
681+}
682+
683+static void touchpad_cal_highest_stage(struct ad714x_chip *ad714x, int idx)
684+{
685+ struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
686+ struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
687+
688+ sw->x_highest_stage = ad714x_cal_highest_stage(ad714x,
689+ hw->x_start_stage, hw->x_end_stage);
690+ sw->y_highest_stage = ad714x_cal_highest_stage(ad714x,
691+ hw->y_start_stage, hw->y_end_stage);
692+
693+ dev_dbg(ad714x->dev,
694+ "touchpad %d x_highest_stage:%d, y_highest_stage:%d\n",
695+ idx, sw->x_highest_stage, sw->y_highest_stage);
696+}
697+
698+/*
699+ * If 2 fingers are touching the sensor then 2 peaks can be observed in the
700+ * distribution.
701+ * The arithmetic doesn't support to get absolute coordinates for multi-touch
702+ * yet.
703+ */
704+static int touchpad_check_second_peak(struct ad714x_chip *ad714x, int idx)
705+{
706+ struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
707+ struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
708+ int i;
709+
710+ for (i = hw->x_start_stage; i < sw->x_highest_stage; i++) {
711+ if ((ad714x->sensor_val[i] - ad714x->sensor_val[i + 1])
712+ > (ad714x->sensor_val[i + 1] / 10))
713+ return 1;
714+ }
715+
716+ for (i = sw->x_highest_stage; i < hw->x_end_stage; i++) {
717+ if ((ad714x->sensor_val[i + 1] - ad714x->sensor_val[i])
718+ > (ad714x->sensor_val[i] / 10))
719+ return 1;
720+ }
721+
722+ for (i = hw->y_start_stage; i < sw->y_highest_stage; i++) {
723+ if ((ad714x->sensor_val[i] - ad714x->sensor_val[i + 1])
724+ > (ad714x->sensor_val[i + 1] / 10))
725+ return 1;
726+ }
727+
728+ for (i = sw->y_highest_stage; i < hw->y_end_stage; i++) {
729+ if ((ad714x->sensor_val[i + 1] - ad714x->sensor_val[i])
730+ > (ad714x->sensor_val[i] / 10))
731+ return 1;
732+ }
733+
734+ return 0;
735+}
736+
737+/*
738+ * If only one finger is used to activate the touch pad then only 1 peak will be
739+ * registered in the distribution. This peak and the 2 adjacent sensors will be
740+ * used in the calculation of the absolute position. This will prevent hand
741+ * shadows to affect the absolute position calculation.
742+ */
743+static void touchpad_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
744+{
745+ struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
746+ struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
747+
748+ sw->x_abs_pos = ad714x_cal_abs_pos(ad714x, hw->x_start_stage,
749+ hw->x_end_stage, sw->x_highest_stage, hw->x_max_coord);
750+ sw->y_abs_pos = ad714x_cal_abs_pos(ad714x, hw->y_start_stage,
751+ hw->y_end_stage, sw->y_highest_stage, hw->y_max_coord);
752+
753+ dev_dbg(ad714x->dev, "touchpad %d absolute position:(%d, %d)\n", idx,
754+ sw->x_abs_pos, sw->y_abs_pos);
755+}
756+
757+static void touchpad_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
758+{
759+ struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
760+
761+ sw->x_flt_pos = (sw->x_flt_pos * (10 - 4) +
762+ sw->x_abs_pos * 4)/10;
763+ sw->y_flt_pos = (sw->y_flt_pos * (10 - 4) +
764+ sw->y_abs_pos * 4)/10;
765+
766+ dev_dbg(ad714x->dev, "touchpad %d filter position:(%d, %d)\n",
767+ idx, sw->x_flt_pos, sw->y_flt_pos);
768+}
769+
770+/*
771+ * To prevent distortion from showing in the absolute position, it is
772+ * necessary to detect the end points. When endpoints are detected, the
773+ * driver stops updating the status variables with absolute positions.
774+ * End points are detected on the 4 edges of the touchpad sensor. The
775+ * method to detect them is the same for all 4.
776+ * To detect the end points, the firmware computes the difference in
777+ * percent between the sensor on the edge and the adjacent one. The
778+ * difference is calculated in percent in order to make the end point
779+ * detection independent of the pressure.
780+ */
781+
782+#define LEFT_END_POINT_DETECTION_LEVEL 550
783+#define RIGHT_END_POINT_DETECTION_LEVEL 750
784+#define LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL 850
785+#define TOP_END_POINT_DETECTION_LEVEL 550
786+#define BOTTOM_END_POINT_DETECTION_LEVEL 950
787+#define TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL 700
788+static int touchpad_check_endpoint(struct ad714x_chip *ad714x, int idx)
789+{
790+ struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
791+ struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
792+ int percent_sensor_diff;
793+
794+ /* left endpoint detect */
795+ percent_sensor_diff = (ad714x->sensor_val[hw->x_start_stage] -
796+ ad714x->sensor_val[hw->x_start_stage + 1]) * 100 /
797+ ad714x->sensor_val[hw->x_start_stage + 1];
798+ if (!sw->left_ep) {
799+ if (percent_sensor_diff >= LEFT_END_POINT_DETECTION_LEVEL) {
800+ sw->left_ep = 1;
801+ sw->left_ep_val =
802+ ad714x->sensor_val[hw->x_start_stage + 1];
803+ }
804+ } else {
805+ if ((percent_sensor_diff < LEFT_END_POINT_DETECTION_LEVEL) &&
806+ (ad714x->sensor_val[hw->x_start_stage + 1] >
807+ LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL + sw->left_ep_val))
808+ sw->left_ep = 0;
809+ }
810+
811+ /* right endpoint detect */
812+ percent_sensor_diff = (ad714x->sensor_val[hw->x_end_stage] -
813+ ad714x->sensor_val[hw->x_end_stage - 1]) * 100 /
814+ ad714x->sensor_val[hw->x_end_stage - 1];
815+ if (!sw->right_ep) {
816+ if (percent_sensor_diff >= RIGHT_END_POINT_DETECTION_LEVEL) {
817+ sw->right_ep = 1;
818+ sw->right_ep_val =
819+ ad714x->sensor_val[hw->x_end_stage - 1];
820+ }
821+ } else {
822+ if ((percent_sensor_diff < RIGHT_END_POINT_DETECTION_LEVEL) &&
823+ (ad714x->sensor_val[hw->x_end_stage - 1] >
824+ LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL + sw->right_ep_val))
825+ sw->right_ep = 0;
826+ }
827+
828+ /* top endpoint detect */
829+ percent_sensor_diff = (ad714x->sensor_val[hw->y_start_stage] -
830+ ad714x->sensor_val[hw->y_start_stage + 1]) * 100 /
831+ ad714x->sensor_val[hw->y_start_stage + 1];
832+ if (!sw->top_ep) {
833+ if (percent_sensor_diff >= TOP_END_POINT_DETECTION_LEVEL) {
834+ sw->top_ep = 1;
835+ sw->top_ep_val =
836+ ad714x->sensor_val[hw->y_start_stage + 1];
837+ }
838+ } else {
839+ if ((percent_sensor_diff < TOP_END_POINT_DETECTION_LEVEL) &&
840+ (ad714x->sensor_val[hw->y_start_stage + 1] >
841+ TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL + sw->top_ep_val))
842+ sw->top_ep = 0;
843+ }
844+
845+ /* bottom endpoint detect */
846+ percent_sensor_diff = (ad714x->sensor_val[hw->y_end_stage] -
847+ ad714x->sensor_val[hw->y_end_stage - 1]) * 100 /
848+ ad714x->sensor_val[hw->y_end_stage - 1];
849+ if (!sw->bottom_ep) {
850+ if (percent_sensor_diff >= BOTTOM_END_POINT_DETECTION_LEVEL) {
851+ sw->bottom_ep = 1;
852+ sw->bottom_ep_val =
853+ ad714x->sensor_val[hw->y_end_stage - 1];
854+ }
855+ } else {
856+ if ((percent_sensor_diff < BOTTOM_END_POINT_DETECTION_LEVEL) &&
857+ (ad714x->sensor_val[hw->y_end_stage - 1] >
858+ TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL + sw->bottom_ep_val))
859+ sw->bottom_ep = 0;
860+ }
861+
862+ return sw->left_ep || sw->right_ep || sw->top_ep || sw->bottom_ep;
863+}
864+
865+static void touchpad_use_com_int(struct ad714x_chip *ad714x, int idx)
866+{
867+ struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
868+
869+ ad714x_use_com_int(ad714x, hw->x_start_stage, hw->x_end_stage);
870+}
871+
872+static void touchpad_use_thr_int(struct ad714x_chip *ad714x, int idx)
873+{
874+ struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
875+
876+ ad714x_use_thr_int(ad714x, hw->x_start_stage, hw->x_end_stage);
877+ ad714x_use_thr_int(ad714x, hw->y_start_stage, hw->y_end_stage);
878+}
879+
880+static void ad714x_touchpad_state_machine(struct ad714x_chip *ad714x, int idx)
881+{
882+ struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
883+ struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
884+ unsigned short h_state, c_state;
885+ unsigned short mask;
886+
887+ mask = (((1 << (hw->x_end_stage + 1)) - 1) -
888+ ((1 << hw->x_start_stage) - 1)) +
889+ (((1 << (hw->y_end_stage + 1)) - 1) -
890+ ((1 << hw->y_start_stage) - 1));
891+
892+ h_state = ad714x->h_state & mask;
893+ c_state = ad714x->c_state & mask;
894+
895+ switch (sw->state) {
896+ case IDLE:
897+ if (h_state) {
898+ sw->state = JITTER;
899+ /* In End of Conversion interrupt mode, the AD714X
900+ * continuously generates hardware interrupts.
901+ */
902+ touchpad_use_com_int(ad714x, idx);
903+ dev_dbg(ad714x->dev, "touchpad %d touched\n", idx);
904+ }
905+ break;
906+
907+ case JITTER:
908+ if (c_state == mask) {
909+ touchpad_cal_sensor_val(ad714x, idx);
910+ touchpad_cal_highest_stage(ad714x, idx);
911+ if ((!touchpad_check_second_peak(ad714x, idx)) &&
912+ (!touchpad_check_endpoint(ad714x, idx))) {
913+ dev_dbg(ad714x->dev,
914+ "touchpad%d, 2 fingers or endpoint\n",
915+ idx);
916+ touchpad_cal_abs_pos(ad714x, idx);
917+ sw->x_flt_pos = sw->x_abs_pos;
918+ sw->y_flt_pos = sw->y_abs_pos;
919+ sw->state = ACTIVE;
920+ }
921+ }
922+ break;
923+
924+ case ACTIVE:
925+ if (c_state == mask) {
926+ if (h_state) {
927+ touchpad_cal_sensor_val(ad714x, idx);
928+ touchpad_cal_highest_stage(ad714x, idx);
929+ if ((!touchpad_check_second_peak(ad714x, idx))
930+ && (!touchpad_check_endpoint(ad714x, idx))) {
931+ touchpad_cal_abs_pos(ad714x, idx);
932+ touchpad_cal_flt_pos(ad714x, idx);
933+ input_report_abs(sw->input, ABS_X,
934+ sw->x_flt_pos);
935+ input_report_abs(sw->input, ABS_Y,
936+ sw->y_flt_pos);
937+ input_report_key(sw->input, BTN_TOUCH,
938+ 1);
939+ }
940+ } else {
941+ /* When the user lifts off the sensor, configure
942+ * the AD714X back to threshold interrupt mode.
943+ */
944+ touchpad_use_thr_int(ad714x, idx);
945+ sw->state = IDLE;
946+ input_report_key(sw->input, BTN_TOUCH, 0);
947+ dev_dbg(ad714x->dev, "touchpad %d released\n",
948+ idx);
949+ }
950+ input_sync(sw->input);
951+ }
952+ break;
953+
954+ default:
955+ break;
956+ }
957+}
958+
959+static int ad714x_hw_detect(struct ad714x_chip *ad714x)
960+{
961+ unsigned short data;
962+
963+ ad714x->read(ad714x->dev, AD714X_PARTID_REG, &data);
964+ switch (data & 0xFFF0) {
965+ case AD7147_PARTID:
966+ ad714x->product = 0x7147;
967+ ad714x->version = data & 0xF;
968+ dev_info(ad714x->dev, "found AD7147 captouch, rev:%d\n",
969+ ad714x->version);
970+ return 0;
971+
972+ case AD7142_PARTID:
973+ ad714x->product = 0x7142;
974+ ad714x->version = data & 0xF;
975+ dev_info(ad714x->dev, "found AD7142 captouch, rev:%d\n",
976+ ad714x->version);
977+ return 0;
978+
979+ default:
980+ dev_err(ad714x->dev,
981+ "fail to detect AD714X captouch, read ID is %04x\n",
982+ data);
983+ return -ENODEV;
984+ }
985+}
986+
987+static void ad714x_hw_init(struct ad714x_chip *ad714x)
988+{
989+ int i, j;
990+ unsigned short reg_base;
991+ unsigned short data;
992+
993+ /* configuration CDC and interrupts */
994+
995+ for (i = 0; i < STAGE_NUM; i++) {
996+ reg_base = AD714X_STAGECFG_REG + i * STAGE_CFGREG_NUM;
997+ for (j = 0; j < STAGE_CFGREG_NUM; j++)
998+ ad714x->write(ad714x->dev, reg_base + j,
999+ ad714x->hw->stage_cfg_reg[i][j]);
1000+ }
1001+
1002+ for (i = 0; i < SYS_CFGREG_NUM; i++)
1003+ ad714x->write(ad714x->dev, AD714X_SYSCFG_REG + i,
1004+ ad714x->hw->sys_cfg_reg[i]);
1005+ for (i = 0; i < SYS_CFGREG_NUM; i++)
1006+ ad714x->read(ad714x->dev, AD714X_SYSCFG_REG + i,
1007+ &data);
1008+
1009+ ad714x->write(ad714x->dev, AD714X_STG_CAL_EN_REG, 0xFFF);
1010+
1011+ /* clear all interrupts */
1012+ ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data);
1013+ ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data);
1014+ ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data);
1015+}
1016+
1017+static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
1018+{
1019+ struct ad714x_chip *ad714x = data;
1020+ int i;
1021+
1022+ mutex_lock(&ad714x->mutex);
1023+
1024+ ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &ad714x->l_state);
1025+ ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &ad714x->h_state);
1026+ ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &ad714x->c_state);
1027+
1028+ for (i = 0; i < ad714x->hw->button_num; i++)
1029+ ad714x_button_state_machine(ad714x, i);
1030+ for (i = 0; i < ad714x->hw->slider_num; i++)
1031+ ad714x_slider_state_machine(ad714x, i);
1032+ for (i = 0; i < ad714x->hw->wheel_num; i++)
1033+ ad714x_wheel_state_machine(ad714x, i);
1034+ for (i = 0; i < ad714x->hw->touchpad_num; i++)
1035+ ad714x_touchpad_state_machine(ad714x, i);
1036+
1037+ mutex_unlock(&ad714x->mutex);
1038+
1039+ return IRQ_HANDLED;
1040+}
1041+
1042+#define MAX_DEVICE_NUM 8
1043+struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
1044+ ad714x_read_t read, ad714x_write_t write)
1045+{
1046+ int i, alloc_idx;
1047+ int error;
1048+ struct input_dev *input[MAX_DEVICE_NUM];
1049+
1050+ struct ad714x_platform_data *plat_data = dev->platform_data;
1051+ struct ad714x_chip *ad714x;
1052+ void *drv_mem;
1053+
1054+ struct ad714x_button_drv *bt_drv;
1055+ struct ad714x_slider_drv *sd_drv;
1056+ struct ad714x_wheel_drv *wl_drv;
1057+ struct ad714x_touchpad_drv *tp_drv;
1058+
1059+
1060+ if (irq <= 0) {
1061+ dev_err(dev, "IRQ not configured!\n");
1062+ error = -EINVAL;
1063+ goto err_out;
1064+ }
1065+
1066+ if (dev->platform_data == NULL) {
1067+ dev_err(dev, "platform data for ad714x doesn't exist\n");
1068+ error = -EINVAL;
1069+ goto err_out;
1070+ }
1071+
1072+ ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) +
1073+ sizeof(*sd_drv) * plat_data->slider_num +
1074+ sizeof(*wl_drv) * plat_data->wheel_num +
1075+ sizeof(*tp_drv) * plat_data->touchpad_num +
1076+ sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL);
1077+ if (!ad714x) {
1078+ error = -ENOMEM;
1079+ goto err_out;
1080+ }
1081+
1082+ ad714x->hw = plat_data;
1083+
1084+ drv_mem = ad714x + 1;
1085+ ad714x->sw = drv_mem;
1086+ drv_mem += sizeof(*ad714x->sw);
1087+ ad714x->sw->slider = sd_drv = drv_mem;
1088+ drv_mem += sizeof(*sd_drv) * ad714x->hw->slider_num;
1089+ ad714x->sw->wheel = wl_drv = drv_mem;
1090+ drv_mem += sizeof(*wl_drv) * ad714x->hw->wheel_num;
1091+ ad714x->sw->touchpad = tp_drv = drv_mem;
1092+ drv_mem += sizeof(*tp_drv) * ad714x->hw->touchpad_num;
1093+ ad714x->sw->button = bt_drv = drv_mem;
1094+ drv_mem += sizeof(*bt_drv) * ad714x->hw->button_num;
1095+
1096+ ad714x->read = read;
1097+ ad714x->write = write;
1098+ ad714x->irq = irq;
1099+ ad714x->dev = dev;
1100+
1101+ error = ad714x_hw_detect(ad714x);
1102+ if (error)
1103+ goto err_free_mem;
1104+
1105+ /* initilize and request sw/hw resources */
1106+
1107+ ad714x_hw_init(ad714x);
1108+ mutex_init(&ad714x->mutex);
1109+
1110+ /*
1111+ * Allocate and register AD714X input device
1112+ */
1113+ alloc_idx = 0;
1114+
1115+ /* a slider uses one input_dev instance */
1116+ if (ad714x->hw->slider_num > 0) {
1117+ struct ad714x_slider_plat *sd_plat = ad714x->hw->slider;
1118+
1119+ for (i = 0; i < ad714x->hw->slider_num; i++) {
1120+ sd_drv[i].input = input[alloc_idx] = input_allocate_device();
1121+ if (!input[alloc_idx]) {
1122+ error = -ENOMEM;
1123+ goto err_free_dev;
1124+ }
1125+
1126+ __set_bit(EV_ABS, input[alloc_idx]->evbit);
1127+ __set_bit(EV_KEY, input[alloc_idx]->evbit);
1128+ __set_bit(ABS_X, input[alloc_idx]->absbit);
1129+ __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
1130+ input_set_abs_params(input[alloc_idx],
1131+ ABS_X, 0, sd_plat->max_coord, 0, 0);
1132+
1133+ input[alloc_idx]->id.bustype = bus_type;
1134+ input[alloc_idx]->id.product = ad714x->product;
1135+ input[alloc_idx]->id.version = ad714x->version;
1136+
1137+ error = input_register_device(input[alloc_idx]);
1138+ if (error)
1139+ goto err_free_dev;
1140+
1141+ alloc_idx++;
1142+ }
1143+ }
1144+
1145+ /* a wheel uses one input_dev instance */
1146+ if (ad714x->hw->wheel_num > 0) {
1147+ struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel;
1148+
1149+ for (i = 0; i < ad714x->hw->wheel_num; i++) {
1150+ wl_drv[i].input = input[alloc_idx] = input_allocate_device();
1151+ if (!input[alloc_idx]) {
1152+ error = -ENOMEM;
1153+ goto err_free_dev;
1154+ }
1155+
1156+ __set_bit(EV_KEY, input[alloc_idx]->evbit);
1157+ __set_bit(EV_ABS, input[alloc_idx]->evbit);
1158+ __set_bit(ABS_WHEEL, input[alloc_idx]->absbit);
1159+ __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
1160+ input_set_abs_params(input[alloc_idx],
1161+ ABS_WHEEL, 0, wl_plat->max_coord, 0, 0);
1162+
1163+ input[alloc_idx]->id.bustype = bus_type;
1164+ input[alloc_idx]->id.product = ad714x->product;
1165+ input[alloc_idx]->id.version = ad714x->version;
1166+
1167+ error = input_register_device(input[alloc_idx]);
1168+ if (error)
1169+ goto err_free_dev;
1170+
1171+ alloc_idx++;
1172+ }
1173+ }
1174+
1175+ /* a touchpad uses one input_dev instance */
1176+ if (ad714x->hw->touchpad_num > 0) {
1177+ struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad;
1178+
1179+ for (i = 0; i < ad714x->hw->touchpad_num; i++) {
1180+ tp_drv[i].input = input[alloc_idx] = input_allocate_device();
1181+ if (!input[alloc_idx]) {
1182+ error = -ENOMEM;
1183+ goto err_free_dev;
1184+ }
1185+
1186+ __set_bit(EV_ABS, input[alloc_idx]->evbit);
1187+ __set_bit(EV_KEY, input[alloc_idx]->evbit);
1188+ __set_bit(ABS_X, input[alloc_idx]->absbit);
1189+ __set_bit(ABS_Y, input[alloc_idx]->absbit);
1190+ __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
1191+ input_set_abs_params(input[alloc_idx],
1192+ ABS_X, 0, tp_plat->x_max_coord, 0, 0);
1193+ input_set_abs_params(input[alloc_idx],
1194+ ABS_Y, 0, tp_plat->y_max_coord, 0, 0);
1195+
1196+ input[alloc_idx]->id.bustype = bus_type;
1197+ input[alloc_idx]->id.product = ad714x->product;
1198+ input[alloc_idx]->id.version = ad714x->version;
1199+
1200+ error = input_register_device(input[alloc_idx]);
1201+ if (error)
1202+ goto err_free_dev;
1203+
1204+ alloc_idx++;
1205+ }
1206+ }
1207+
1208+ /* all buttons use one input node */
1209+ if (ad714x->hw->button_num > 0) {
1210+ struct ad714x_button_plat *bt_plat = ad714x->hw->button;
1211+
1212+ input[alloc_idx] = input_allocate_device();
1213+ if (!input[alloc_idx]) {
1214+ error = -ENOMEM;
1215+ goto err_free_dev;
1216+ }
1217+
1218+ __set_bit(EV_KEY, input[alloc_idx]->evbit);
1219+ for (i = 0; i < ad714x->hw->button_num; i++) {
1220+ bt_drv[i].input = input[alloc_idx];
1221+ __set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit);
1222+ }
1223+
1224+ input[alloc_idx]->id.bustype = bus_type;
1225+ input[alloc_idx]->id.product = ad714x->product;
1226+ input[alloc_idx]->id.version = ad714x->version;
1227+
1228+ error = input_register_device(input[alloc_idx]);
1229+ if (error)
1230+ goto err_free_dev;
1231+
1232+ alloc_idx++;
1233+ }
1234+
1235+ error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread,
1236+ IRQF_TRIGGER_FALLING, "ad714x_captouch", ad714x);
1237+ if (error) {
1238+ dev_err(dev, "can't allocate irq %d\n", ad714x->irq);
1239+ goto err_unreg_dev;
1240+ }
1241+
1242+ return ad714x;
1243+
1244+ err_free_dev:
1245+ dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx);
1246+ input_free_device(input[alloc_idx]);
1247+ err_unreg_dev:
1248+ while (--alloc_idx >= 0)
1249+ input_unregister_device(input[alloc_idx]);
1250+ err_free_mem:
1251+ kfree(ad714x);
1252+ err_out:
1253+ return ERR_PTR(error);
1254+}
1255+EXPORT_SYMBOL(ad714x_probe);
1256+
1257+void ad714x_remove(struct ad714x_chip *ad714x)
1258+{
1259+ struct ad714x_platform_data *hw = ad714x->hw;
1260+ struct ad714x_driver_data *sw = ad714x->sw;
1261+ int i;
1262+
1263+ free_irq(ad714x->irq, ad714x);
1264+
1265+ /* unregister and free all input devices */
1266+
1267+ for (i = 0; i < hw->slider_num; i++)
1268+ input_unregister_device(sw->slider[i].input);
1269+
1270+ for (i = 0; i < hw->wheel_num; i++)
1271+ input_unregister_device(sw->wheel[i].input);
1272+
1273+ for (i = 0; i < hw->touchpad_num; i++)
1274+ input_unregister_device(sw->touchpad[i].input);
1275+
1276+ if (hw->button_num)
1277+ input_unregister_device(sw->button[0].input);
1278+
1279+ kfree(ad714x);
1280+}
1281+EXPORT_SYMBOL(ad714x_remove);
1282+
1283+#ifdef CONFIG_PM
1284+int ad714x_disable(struct ad714x_chip *ad714x)
1285+{
1286+ unsigned short data;
1287+
1288+ dev_dbg(ad714x->dev, "%s enter\n", __func__);
1289+
1290+ mutex_lock(&ad714x->mutex);
1291+
1292+ data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3;
1293+ ad714x->write(ad714x->dev, AD714X_PWR_CTRL, data);
1294+
1295+ mutex_unlock(&ad714x->mutex);
1296+
1297+ return 0;
1298+}
1299+EXPORT_SYMBOL(ad714x_disable);
1300+
1301+int ad714x_enable(struct ad714x_chip *ad714x)
1302+{
1303+ unsigned short data;
1304+
1305+ dev_dbg(ad714x->dev, "%s enter\n", __func__);
1306+
1307+ mutex_lock(&ad714x->mutex);
1308+
1309+ /* resume to non-shutdown mode */
1310+
1311+ ad714x->write(ad714x->dev, AD714X_PWR_CTRL,
1312+ ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL]);
1313+
1314+ /* make sure the interrupt output line is not low level after resume,
1315+ * otherwise we will get no chance to enter falling-edge irq again
1316+ */
1317+
1318+ ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data);
1319+ ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data);
1320+ ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data);
1321+
1322+ mutex_unlock(&ad714x->mutex);
1323+
1324+ return 0;
1325+}
1326+EXPORT_SYMBOL(ad714x_enable);
1327+#endif
1328+
1329+MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor Driver");
1330+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
1331+MODULE_LICENSE("GPL");
drivers/input/misc/ad714x.h+26−0
@@ -0,0 +1,26 @@
1+/*
2+ * AD714X CapTouch Programmable Controller driver (bus interfaces)
3+ *
4+ * Copyright 2009 Analog Devices Inc.
5+ *
6+ * Licensed under the GPL-2 or later.
7+ */
8+
9+#ifndef _AD714X_H_
10+#define _AD714X_H_
11+
12+#include <linux/types.h>
13+
14+struct device;
15+struct ad714x_chip;
16+
17+typedef int (*ad714x_read_t)(struct device *, unsigned short, unsigned short *);
18+typedef int (*ad714x_write_t)(struct device *, unsigned short, unsigned short);
19+
20+int ad714x_disable(struct ad714x_chip *ad714x);
21+int ad714x_enable(struct ad714x_chip *ad714x);
22+struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
23+ ad714x_read_t read, ad714x_write_t write);
24+void ad714x_remove(struct ad714x_chip *ad714x);
25+
26+#endif
include/linux/input.h+1−0
@@ -806,6 +806,7 @@ struct input_absinfo { · 805 unmodified lines
806806 #define BUS_HOST 0x19
807807 #define BUS_GSC 0x1A
808808 #define BUS_ATARI 0x1B
809+#define BUS_SPI 0x1C
809810
810811 /*
811812 * MT_TOOL types
include/linux/input/ad714x.h+63−0
@@ -0,0 +1,63 @@
1+/*
2+ * include/linux/input/ad714x.h
3+ *
4+ * AD714x is very flexible, it can be used as buttons, scrollwheel,
5+ * slider, touchpad at the same time. That depends on the boards.
6+ * The platform_data for the device's "struct device" holds this
7+ * information.
8+ *
9+ * Copyright 2009 Analog Devices Inc.
10+ *
11+ * Licensed under the GPL-2 or later.
12+ */
13+
14+#ifndef __LINUX_INPUT_AD714X_H__
15+#define __LINUX_INPUT_AD714X_H__
16+
17+#define STAGE_NUM 12
18+#define STAGE_CFGREG_NUM 8
19+#define SYS_CFGREG_NUM 8
20+
21+/* board information which need be initialized in arch/mach... */
22+struct ad714x_slider_plat {
23+ int start_stage;
24+ int end_stage;
25+ int max_coord;
26+};
27+
28+struct ad714x_wheel_plat {
29+ int start_stage;
30+ int end_stage;
31+ int max_coord;
32+};
33+
34+struct ad714x_touchpad_plat {
35+ int x_start_stage;
36+ int x_end_stage;
37+ int x_max_coord;
38+
39+ int y_start_stage;
40+ int y_end_stage;
41+ int y_max_coord;
42+};
43+
44+struct ad714x_button_plat {
45+ int keycode;
46+ unsigned short l_mask;
47+ unsigned short h_mask;
48+};
49+
50+struct ad714x_platform_data {
51+ int slider_num;
52+ int wheel_num;
53+ int touchpad_num;
54+ int button_num;
55+ struct ad714x_slider_plat *slider;
56+ struct ad714x_wheel_plat *wheel;
57+ struct ad714x_touchpad_plat *touchpad;
58+ struct ad714x_button_plat *button;
59+ unsigned short stage_cfg_reg[STAGE_NUM][STAGE_CFGREG_NUM];
60+ unsigned short sys_cfg_reg[SYS_CFGREG_NUM];
61+};
62+
63+#endif