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