diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/evdev.c | 35 | ||||
-rw-r--r-- | drivers/input/keyboard/adp5588-keys.c | 134 | ||||
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 19 | ||||
-rw-r--r-- | drivers/input/keyboard/lm8323.c | 12 | ||||
-rw-r--r-- | drivers/input/keyboard/matrix_keypad.c | 108 | ||||
-rw-r--r-- | drivers/input/misc/Kconfig | 37 | ||||
-rw-r--r-- | drivers/input/misc/Makefile | 3 | ||||
-rw-r--r-- | drivers/input/misc/adxl34x-i2c.c | 163 | ||||
-rw-r--r-- | drivers/input/misc/adxl34x-spi.c | 145 | ||||
-rw-r--r-- | drivers/input/misc/adxl34x.c | 894 | ||||
-rw-r--r-- | drivers/input/misc/adxl34x.h | 30 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 4 | ||||
-rw-r--r-- | drivers/input/mouse/bcm5974.c | 23 | ||||
-rw-r--r-- | drivers/input/serio/i8042-ppcio.h | 75 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.c | 44 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.h | 1 | ||||
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 5 | ||||
-rw-r--r-- | drivers/input/touchscreen/tps6507x-ts.c | 3 | ||||
-rw-r--r-- | drivers/input/touchscreen/usbtouchscreen.c | 55 |
20 files changed, 1628 insertions, 166 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 2ee6c7a68bd..cd323254ca6 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -10,7 +10,8 @@ | |||
10 | 10 | ||
11 | #define EVDEV_MINOR_BASE 64 | 11 | #define EVDEV_MINOR_BASE 64 |
12 | #define EVDEV_MINORS 32 | 12 | #define EVDEV_MINORS 32 |
13 | #define EVDEV_BUFFER_SIZE 64 | 13 | #define EVDEV_MIN_BUFFER_SIZE 64U |
14 | #define EVDEV_BUF_PACKETS 8 | ||
14 | 15 | ||
15 | #include <linux/poll.h> | 16 | #include <linux/poll.h> |
16 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
@@ -36,13 +37,14 @@ struct evdev { | |||
36 | }; | 37 | }; |
37 | 38 | ||
38 | struct evdev_client { | 39 | struct evdev_client { |
39 | struct input_event buffer[EVDEV_BUFFER_SIZE]; | ||
40 | int head; | 40 | int head; |
41 | int tail; | 41 | int tail; |
42 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ | 42 | spinlock_t buffer_lock; /* protects access to buffer, head and tail */ |
43 | struct fasync_struct *fasync; | 43 | struct fasync_struct *fasync; |
44 | struct evdev *evdev; | 44 | struct evdev *evdev; |
45 | struct list_head node; | 45 | struct list_head node; |
46 | int bufsize; | ||
47 | struct input_event buffer[]; | ||
46 | }; | 48 | }; |
47 | 49 | ||
48 | static struct evdev *evdev_table[EVDEV_MINORS]; | 50 | static struct evdev *evdev_table[EVDEV_MINORS]; |
@@ -52,11 +54,15 @@ static void evdev_pass_event(struct evdev_client *client, | |||
52 | struct input_event *event) | 54 | struct input_event *event) |
53 | { | 55 | { |
54 | /* | 56 | /* |
55 | * Interrupts are disabled, just acquire the lock | 57 | * Interrupts are disabled, just acquire the lock. |
58 | * Make sure we don't leave with the client buffer | ||
59 | * "empty" by having client->head == client->tail. | ||
56 | */ | 60 | */ |
57 | spin_lock(&client->buffer_lock); | 61 | spin_lock(&client->buffer_lock); |
58 | client->buffer[client->head++] = *event; | 62 | do { |
59 | client->head &= EVDEV_BUFFER_SIZE - 1; | 63 | client->buffer[client->head++] = *event; |
64 | client->head &= client->bufsize - 1; | ||
65 | } while (client->head == client->tail); | ||
60 | spin_unlock(&client->buffer_lock); | 66 | spin_unlock(&client->buffer_lock); |
61 | 67 | ||
62 | if (event->type == EV_SYN) | 68 | if (event->type == EV_SYN) |
@@ -242,11 +248,21 @@ static int evdev_release(struct inode *inode, struct file *file) | |||
242 | return 0; | 248 | return 0; |
243 | } | 249 | } |
244 | 250 | ||
251 | static unsigned int evdev_compute_buffer_size(struct input_dev *dev) | ||
252 | { | ||
253 | unsigned int n_events = | ||
254 | max(dev->hint_events_per_packet * EVDEV_BUF_PACKETS, | ||
255 | EVDEV_MIN_BUFFER_SIZE); | ||
256 | |||
257 | return roundup_pow_of_two(n_events); | ||
258 | } | ||
259 | |||
245 | static int evdev_open(struct inode *inode, struct file *file) | 260 | static int evdev_open(struct inode *inode, struct file *file) |
246 | { | 261 | { |
247 | struct evdev *evdev; | 262 | struct evdev *evdev; |
248 | struct evdev_client *client; | 263 | struct evdev_client *client; |
249 | int i = iminor(inode) - EVDEV_MINOR_BASE; | 264 | int i = iminor(inode) - EVDEV_MINOR_BASE; |
265 | unsigned int bufsize; | ||
250 | int error; | 266 | int error; |
251 | 267 | ||
252 | if (i >= EVDEV_MINORS) | 268 | if (i >= EVDEV_MINORS) |
@@ -263,12 +279,17 @@ static int evdev_open(struct inode *inode, struct file *file) | |||
263 | if (!evdev) | 279 | if (!evdev) |
264 | return -ENODEV; | 280 | return -ENODEV; |
265 | 281 | ||
266 | client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); | 282 | bufsize = evdev_compute_buffer_size(evdev->handle.dev); |
283 | |||
284 | client = kzalloc(sizeof(struct evdev_client) + | ||
285 | bufsize * sizeof(struct input_event), | ||
286 | GFP_KERNEL); | ||
267 | if (!client) { | 287 | if (!client) { |
268 | error = -ENOMEM; | 288 | error = -ENOMEM; |
269 | goto err_put_evdev; | 289 | goto err_put_evdev; |
270 | } | 290 | } |
271 | 291 | ||
292 | client->bufsize = bufsize; | ||
272 | spin_lock_init(&client->buffer_lock); | 293 | spin_lock_init(&client->buffer_lock); |
273 | client->evdev = evdev; | 294 | client->evdev = evdev; |
274 | evdev_attach_client(evdev, client); | 295 | evdev_attach_client(evdev, client); |
@@ -334,7 +355,7 @@ static int evdev_fetch_next_event(struct evdev_client *client, | |||
334 | have_event = client->head != client->tail; | 355 | have_event = client->head != client->tail; |
335 | if (have_event) { | 356 | if (have_event) { |
336 | *event = client->buffer[client->tail++]; | 357 | *event = client->buffer[client->tail++]; |
337 | client->tail &= EVDEV_BUFFER_SIZE - 1; | 358 | client->tail &= client->bufsize - 1; |
338 | } | 359 | } |
339 | 360 | ||
340 | spin_unlock_irq(&client->buffer_lock); | 361 | spin_unlock_irq(&client->buffer_lock); |
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 744600eff22..9096db73c3c 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c | |||
@@ -67,6 +67,8 @@ struct adp5588_kpad { | |||
67 | struct delayed_work work; | 67 | struct delayed_work work; |
68 | unsigned long delay; | 68 | unsigned long delay; |
69 | unsigned short keycode[ADP5588_KEYMAPSIZE]; | 69 | unsigned short keycode[ADP5588_KEYMAPSIZE]; |
70 | const struct adp5588_gpi_map *gpimap; | ||
71 | unsigned short gpimapsize; | ||
70 | }; | 72 | }; |
71 | 73 | ||
72 | static int adp5588_read(struct i2c_client *client, u8 reg) | 74 | static int adp5588_read(struct i2c_client *client, u8 reg) |
@@ -84,12 +86,37 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val) | |||
84 | return i2c_smbus_write_byte_data(client, reg, val); | 86 | return i2c_smbus_write_byte_data(client, reg, val); |
85 | } | 87 | } |
86 | 88 | ||
89 | static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt) | ||
90 | { | ||
91 | int i, j; | ||
92 | |||
93 | for (i = 0; i < ev_cnt; i++) { | ||
94 | int key = adp5588_read(kpad->client, Key_EVENTA + i); | ||
95 | int key_val = key & KEY_EV_MASK; | ||
96 | |||
97 | if (key_val >= GPI_PIN_BASE && key_val <= GPI_PIN_END) { | ||
98 | for (j = 0; j < kpad->gpimapsize; j++) { | ||
99 | if (key_val == kpad->gpimap[j].pin) { | ||
100 | input_report_switch(kpad->input, | ||
101 | kpad->gpimap[j].sw_evt, | ||
102 | key & KEY_EV_PRESSED); | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | } else { | ||
107 | input_report_key(kpad->input, | ||
108 | kpad->keycode[key_val - 1], | ||
109 | key & KEY_EV_PRESSED); | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
87 | static void adp5588_work(struct work_struct *work) | 114 | static void adp5588_work(struct work_struct *work) |
88 | { | 115 | { |
89 | struct adp5588_kpad *kpad = container_of(work, | 116 | struct adp5588_kpad *kpad = container_of(work, |
90 | struct adp5588_kpad, work.work); | 117 | struct adp5588_kpad, work.work); |
91 | struct i2c_client *client = kpad->client; | 118 | struct i2c_client *client = kpad->client; |
92 | int i, key, status, ev_cnt; | 119 | int status, ev_cnt; |
93 | 120 | ||
94 | status = adp5588_read(client, INT_STAT); | 121 | status = adp5588_read(client, INT_STAT); |
95 | 122 | ||
@@ -99,12 +126,7 @@ static void adp5588_work(struct work_struct *work) | |||
99 | if (status & KE_INT) { | 126 | if (status & KE_INT) { |
100 | ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC; | 127 | ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC; |
101 | if (ev_cnt) { | 128 | if (ev_cnt) { |
102 | for (i = 0; i < ev_cnt; i++) { | 129 | adp5588_report_events(kpad, ev_cnt); |
103 | key = adp5588_read(client, Key_EVENTA + i); | ||
104 | input_report_key(kpad->input, | ||
105 | kpad->keycode[(key & KEY_EV_MASK) - 1], | ||
106 | key & KEY_EV_PRESSED); | ||
107 | } | ||
108 | input_sync(kpad->input); | 130 | input_sync(kpad->input); |
109 | } | 131 | } |
110 | } | 132 | } |
@@ -130,6 +152,7 @@ static int __devinit adp5588_setup(struct i2c_client *client) | |||
130 | { | 152 | { |
131 | struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; | 153 | struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; |
132 | int i, ret; | 154 | int i, ret; |
155 | unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; | ||
133 | 156 | ||
134 | ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows)); | 157 | ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows)); |
135 | ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF); | 158 | ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF); |
@@ -144,6 +167,23 @@ static int __devinit adp5588_setup(struct i2c_client *client) | |||
144 | for (i = 0; i < KEYP_MAX_EVENT; i++) | 167 | for (i = 0; i < KEYP_MAX_EVENT; i++) |
145 | ret |= adp5588_read(client, Key_EVENTA); | 168 | ret |= adp5588_read(client, Key_EVENTA); |
146 | 169 | ||
170 | for (i = 0; i < pdata->gpimapsize; i++) { | ||
171 | unsigned short pin = pdata->gpimap[i].pin; | ||
172 | |||
173 | if (pin <= GPI_PIN_ROW_END) { | ||
174 | evt_mode1 |= (1 << (pin - GPI_PIN_ROW_BASE)); | ||
175 | } else { | ||
176 | evt_mode2 |= ((1 << (pin - GPI_PIN_COL_BASE)) & 0xFF); | ||
177 | evt_mode3 |= ((1 << (pin - GPI_PIN_COL_BASE)) >> 8); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | if (pdata->gpimapsize) { | ||
182 | ret |= adp5588_write(client, GPI_EM1, evt_mode1); | ||
183 | ret |= adp5588_write(client, GPI_EM2, evt_mode2); | ||
184 | ret |= adp5588_write(client, GPI_EM3, evt_mode3); | ||
185 | } | ||
186 | |||
147 | ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT | | 187 | ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT | |
148 | OVR_FLOW_INT | K_LCK_INT | | 188 | OVR_FLOW_INT | K_LCK_INT | |
149 | GPI_INT | KE_INT); /* Status is W1C */ | 189 | GPI_INT | KE_INT); /* Status is W1C */ |
@@ -158,6 +198,44 @@ static int __devinit adp5588_setup(struct i2c_client *client) | |||
158 | return 0; | 198 | return 0; |
159 | } | 199 | } |
160 | 200 | ||
201 | static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad) | ||
202 | { | ||
203 | int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1); | ||
204 | int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2); | ||
205 | int gpi_stat3 = adp5588_read(kpad->client, GPIO_DAT_STAT3); | ||
206 | int gpi_stat_tmp, pin_loc; | ||
207 | int i; | ||
208 | |||
209 | for (i = 0; i < kpad->gpimapsize; i++) { | ||
210 | unsigned short pin = kpad->gpimap[i].pin; | ||
211 | |||
212 | if (pin <= GPI_PIN_ROW_END) { | ||
213 | gpi_stat_tmp = gpi_stat1; | ||
214 | pin_loc = pin - GPI_PIN_ROW_BASE; | ||
215 | } else if ((pin - GPI_PIN_COL_BASE) < 8) { | ||
216 | gpi_stat_tmp = gpi_stat2; | ||
217 | pin_loc = pin - GPI_PIN_COL_BASE; | ||
218 | } else { | ||
219 | gpi_stat_tmp = gpi_stat3; | ||
220 | pin_loc = pin - GPI_PIN_COL_BASE - 8; | ||
221 | } | ||
222 | |||
223 | if (gpi_stat_tmp < 0) { | ||
224 | dev_err(&kpad->client->dev, | ||
225 | "Can't read GPIO_DAT_STAT switch %d default to OFF\n", | ||
226 | pin); | ||
227 | gpi_stat_tmp = 0; | ||
228 | } | ||
229 | |||
230 | input_report_switch(kpad->input, | ||
231 | kpad->gpimap[i].sw_evt, | ||
232 | !(gpi_stat_tmp & (1 << pin_loc))); | ||
233 | } | ||
234 | |||
235 | input_sync(kpad->input); | ||
236 | } | ||
237 | |||
238 | |||
161 | static int __devinit adp5588_probe(struct i2c_client *client, | 239 | static int __devinit adp5588_probe(struct i2c_client *client, |
162 | const struct i2c_device_id *id) | 240 | const struct i2c_device_id *id) |
163 | { | 241 | { |
@@ -189,6 +267,37 @@ static int __devinit adp5588_probe(struct i2c_client *client, | |||
189 | return -EINVAL; | 267 | return -EINVAL; |
190 | } | 268 | } |
191 | 269 | ||
270 | if (!pdata->gpimap && pdata->gpimapsize) { | ||
271 | dev_err(&client->dev, "invalid gpimap from pdata\n"); | ||
272 | return -EINVAL; | ||
273 | } | ||
274 | |||
275 | if (pdata->gpimapsize > ADP5588_GPIMAPSIZE_MAX) { | ||
276 | dev_err(&client->dev, "invalid gpimapsize\n"); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | for (i = 0; i < pdata->gpimapsize; i++) { | ||
281 | unsigned short pin = pdata->gpimap[i].pin; | ||
282 | |||
283 | if (pin < GPI_PIN_BASE || pin > GPI_PIN_END) { | ||
284 | dev_err(&client->dev, "invalid gpi pin data\n"); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | if (pin <= GPI_PIN_ROW_END) { | ||
289 | if (pin - GPI_PIN_ROW_BASE + 1 <= pdata->rows) { | ||
290 | dev_err(&client->dev, "invalid gpi row data\n"); | ||
291 | return -EINVAL; | ||
292 | } | ||
293 | } else { | ||
294 | if (pin - GPI_PIN_COL_BASE + 1 <= pdata->cols) { | ||
295 | dev_err(&client->dev, "invalid gpi col data\n"); | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | |||
192 | if (!client->irq) { | 301 | if (!client->irq) { |
193 | dev_err(&client->dev, "no IRQ?\n"); | 302 | dev_err(&client->dev, "no IRQ?\n"); |
194 | return -EINVAL; | 303 | return -EINVAL; |
@@ -233,6 +342,9 @@ static int __devinit adp5588_probe(struct i2c_client *client, | |||
233 | memcpy(kpad->keycode, pdata->keymap, | 342 | memcpy(kpad->keycode, pdata->keymap, |
234 | pdata->keymapsize * input->keycodesize); | 343 | pdata->keymapsize * input->keycodesize); |
235 | 344 | ||
345 | kpad->gpimap = pdata->gpimap; | ||
346 | kpad->gpimapsize = pdata->gpimapsize; | ||
347 | |||
236 | /* setup input device */ | 348 | /* setup input device */ |
237 | __set_bit(EV_KEY, input->evbit); | 349 | __set_bit(EV_KEY, input->evbit); |
238 | 350 | ||
@@ -243,6 +355,11 @@ static int __devinit adp5588_probe(struct i2c_client *client, | |||
243 | __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit); | 355 | __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit); |
244 | __clear_bit(KEY_RESERVED, input->keybit); | 356 | __clear_bit(KEY_RESERVED, input->keybit); |
245 | 357 | ||
358 | if (kpad->gpimapsize) | ||
359 | __set_bit(EV_SW, input->evbit); | ||
360 | for (i = 0; i < kpad->gpimapsize; i++) | ||
361 | __set_bit(kpad->gpimap[i].sw_evt, input->swbit); | ||
362 | |||
246 | error = input_register_device(input); | 363 | error = input_register_device(input); |
247 | if (error) { | 364 | if (error) { |
248 | dev_err(&client->dev, "unable to register input device\n"); | 365 | dev_err(&client->dev, "unable to register input device\n"); |
@@ -261,6 +378,9 @@ static int __devinit adp5588_probe(struct i2c_client *client, | |||
261 | if (error) | 378 | if (error) |
262 | goto err_free_irq; | 379 | goto err_free_irq; |
263 | 380 | ||
381 | if (kpad->gpimapsize) | ||
382 | adp5588_report_switch_state(kpad); | ||
383 | |||
264 | device_init_wakeup(&client->dev, 1); | 384 | device_init_wakeup(&client->dev, 1); |
265 | i2c_set_clientdata(client, kpad); | 385 | i2c_set_clientdata(client, kpad); |
266 | 386 | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index b8213fd13c3..a9fd147f2ba 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -31,6 +31,7 @@ struct gpio_button_data { | |||
31 | struct input_dev *input; | 31 | struct input_dev *input; |
32 | struct timer_list timer; | 32 | struct timer_list timer; |
33 | struct work_struct work; | 33 | struct work_struct work; |
34 | int timer_debounce; /* in msecs */ | ||
34 | bool disabled; | 35 | bool disabled; |
35 | }; | 36 | }; |
36 | 37 | ||
@@ -109,7 +110,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata) | |||
109 | * Disable IRQ and possible debouncing timer. | 110 | * Disable IRQ and possible debouncing timer. |
110 | */ | 111 | */ |
111 | disable_irq(gpio_to_irq(bdata->button->gpio)); | 112 | disable_irq(gpio_to_irq(bdata->button->gpio)); |
112 | if (bdata->button->debounce_interval) | 113 | if (bdata->timer_debounce) |
113 | del_timer_sync(&bdata->timer); | 114 | del_timer_sync(&bdata->timer); |
114 | 115 | ||
115 | bdata->disabled = true; | 116 | bdata->disabled = true; |
@@ -347,9 +348,9 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | |||
347 | 348 | ||
348 | BUG_ON(irq != gpio_to_irq(button->gpio)); | 349 | BUG_ON(irq != gpio_to_irq(button->gpio)); |
349 | 350 | ||
350 | if (button->debounce_interval) | 351 | if (bdata->timer_debounce) |
351 | mod_timer(&bdata->timer, | 352 | mod_timer(&bdata->timer, |
352 | jiffies + msecs_to_jiffies(button->debounce_interval)); | 353 | jiffies + msecs_to_jiffies(bdata->timer_debounce)); |
353 | else | 354 | else |
354 | schedule_work(&bdata->work); | 355 | schedule_work(&bdata->work); |
355 | 356 | ||
@@ -383,6 +384,14 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, | |||
383 | goto fail3; | 384 | goto fail3; |
384 | } | 385 | } |
385 | 386 | ||
387 | if (button->debounce_interval) { | ||
388 | error = gpio_set_debounce(button->gpio, | ||
389 | button->debounce_interval * 1000); | ||
390 | /* use timer if gpiolib doesn't provide debounce */ | ||
391 | if (error < 0) | ||
392 | bdata->timer_debounce = button->debounce_interval; | ||
393 | } | ||
394 | |||
386 | irq = gpio_to_irq(button->gpio); | 395 | irq = gpio_to_irq(button->gpio); |
387 | if (irq < 0) { | 396 | if (irq < 0) { |
388 | error = irq; | 397 | error = irq; |
@@ -498,7 +507,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
498 | fail2: | 507 | fail2: |
499 | while (--i >= 0) { | 508 | while (--i >= 0) { |
500 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); | 509 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); |
501 | if (pdata->buttons[i].debounce_interval) | 510 | if (ddata->data[i].timer_debounce) |
502 | del_timer_sync(&ddata->data[i].timer); | 511 | del_timer_sync(&ddata->data[i].timer); |
503 | cancel_work_sync(&ddata->data[i].work); | 512 | cancel_work_sync(&ddata->data[i].work); |
504 | gpio_free(pdata->buttons[i].gpio); | 513 | gpio_free(pdata->buttons[i].gpio); |
@@ -526,7 +535,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
526 | for (i = 0; i < pdata->nbuttons; i++) { | 535 | for (i = 0; i < pdata->nbuttons; i++) { |
527 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 536 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
528 | free_irq(irq, &ddata->data[i]); | 537 | free_irq(irq, &ddata->data[i]); |
529 | if (pdata->buttons[i].debounce_interval) | 538 | if (ddata->data[i].timer_debounce) |
530 | del_timer_sync(&ddata->data[i].timer); | 539 | del_timer_sync(&ddata->data[i].timer); |
531 | cancel_work_sync(&ddata->data[i].work); | 540 | cancel_work_sync(&ddata->data[i].work); |
532 | gpio_free(pdata->buttons[i].gpio); | 541 | gpio_free(pdata->buttons[i].gpio); |
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 40b032f0e32..f7c2a166576 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c | |||
@@ -642,6 +642,7 @@ static int __devinit lm8323_probe(struct i2c_client *client, | |||
642 | struct lm8323_platform_data *pdata = client->dev.platform_data; | 642 | struct lm8323_platform_data *pdata = client->dev.platform_data; |
643 | struct input_dev *idev; | 643 | struct input_dev *idev; |
644 | struct lm8323_chip *lm; | 644 | struct lm8323_chip *lm; |
645 | int pwm; | ||
645 | int i, err; | 646 | int i, err; |
646 | unsigned long tmo; | 647 | unsigned long tmo; |
647 | u8 data[2]; | 648 | u8 data[2]; |
@@ -710,8 +711,9 @@ static int __devinit lm8323_probe(struct i2c_client *client, | |||
710 | goto fail1; | 711 | goto fail1; |
711 | } | 712 | } |
712 | 713 | ||
713 | for (i = 0; i < LM8323_NUM_PWMS; i++) { | 714 | for (pwm = 0; pwm < LM8323_NUM_PWMS; pwm++) { |
714 | err = init_pwm(lm, i + 1, &client->dev, pdata->pwm_names[i]); | 715 | err = init_pwm(lm, pwm + 1, &client->dev, |
716 | pdata->pwm_names[pwm]); | ||
715 | if (err < 0) | 717 | if (err < 0) |
716 | goto fail2; | 718 | goto fail2; |
717 | } | 719 | } |
@@ -764,9 +766,9 @@ fail4: | |||
764 | fail3: | 766 | fail3: |
765 | device_remove_file(&client->dev, &dev_attr_disable_kp); | 767 | device_remove_file(&client->dev, &dev_attr_disable_kp); |
766 | fail2: | 768 | fail2: |
767 | while (--i >= 0) | 769 | while (--pwm >= 0) |
768 | if (lm->pwm[i].enabled) | 770 | if (lm->pwm[pwm].enabled) |
769 | led_classdev_unregister(&lm->pwm[i].cdev); | 771 | led_classdev_unregister(&lm->pwm[pwm].cdev); |
770 | fail1: | 772 | fail1: |
771 | input_free_device(idev); | 773 | input_free_device(idev); |
772 | kfree(lm); | 774 | kfree(lm); |
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index b443e088fd3..b02e4268e18 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -37,6 +37,7 @@ struct matrix_keypad { | |||
37 | spinlock_t lock; | 37 | spinlock_t lock; |
38 | bool scan_pending; | 38 | bool scan_pending; |
39 | bool stopped; | 39 | bool stopped; |
40 | bool gpio_all_disabled; | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | /* | 43 | /* |
@@ -87,8 +88,12 @@ static void enable_row_irqs(struct matrix_keypad *keypad) | |||
87 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 88 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
88 | int i; | 89 | int i; |
89 | 90 | ||
90 | for (i = 0; i < pdata->num_row_gpios; i++) | 91 | if (pdata->clustered_irq > 0) |
91 | enable_irq(gpio_to_irq(pdata->row_gpios[i])); | 92 | enable_irq(pdata->clustered_irq); |
93 | else { | ||
94 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
95 | enable_irq(gpio_to_irq(pdata->row_gpios[i])); | ||
96 | } | ||
92 | } | 97 | } |
93 | 98 | ||
94 | static void disable_row_irqs(struct matrix_keypad *keypad) | 99 | static void disable_row_irqs(struct matrix_keypad *keypad) |
@@ -96,8 +101,12 @@ static void disable_row_irqs(struct matrix_keypad *keypad) | |||
96 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 101 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
97 | int i; | 102 | int i; |
98 | 103 | ||
99 | for (i = 0; i < pdata->num_row_gpios; i++) | 104 | if (pdata->clustered_irq > 0) |
100 | disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i])); | 105 | disable_irq_nosync(pdata->clustered_irq); |
106 | else { | ||
107 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
108 | disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i])); | ||
109 | } | ||
101 | } | 110 | } |
102 | 111 | ||
103 | /* | 112 | /* |
@@ -216,45 +225,69 @@ static void matrix_keypad_stop(struct input_dev *dev) | |||
216 | } | 225 | } |
217 | 226 | ||
218 | #ifdef CONFIG_PM | 227 | #ifdef CONFIG_PM |
219 | static int matrix_keypad_suspend(struct device *dev) | 228 | static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad) |
220 | { | 229 | { |
221 | struct platform_device *pdev = to_platform_device(dev); | ||
222 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
223 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 230 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
231 | unsigned int gpio; | ||
224 | int i; | 232 | int i; |
225 | 233 | ||
226 | matrix_keypad_stop(keypad->input_dev); | 234 | if (pdata->clustered_irq > 0) { |
235 | if (enable_irq_wake(pdata->clustered_irq) == 0) | ||
236 | keypad->gpio_all_disabled = true; | ||
237 | } else { | ||
227 | 238 | ||
228 | if (device_may_wakeup(&pdev->dev)) { | ||
229 | for (i = 0; i < pdata->num_row_gpios; i++) { | 239 | for (i = 0; i < pdata->num_row_gpios; i++) { |
230 | if (!test_bit(i, keypad->disabled_gpios)) { | 240 | if (!test_bit(i, keypad->disabled_gpios)) { |
231 | unsigned int gpio = pdata->row_gpios[i]; | 241 | gpio = pdata->row_gpios[i]; |
232 | 242 | ||
233 | if (enable_irq_wake(gpio_to_irq(gpio)) == 0) | 243 | if (enable_irq_wake(gpio_to_irq(gpio)) == 0) |
234 | __set_bit(i, keypad->disabled_gpios); | 244 | __set_bit(i, keypad->disabled_gpios); |
235 | } | 245 | } |
236 | } | 246 | } |
237 | } | 247 | } |
238 | |||
239 | return 0; | ||
240 | } | 248 | } |
241 | 249 | ||
242 | static int matrix_keypad_resume(struct device *dev) | 250 | static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad) |
243 | { | 251 | { |
244 | struct platform_device *pdev = to_platform_device(dev); | ||
245 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
246 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 252 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
253 | unsigned int gpio; | ||
247 | int i; | 254 | int i; |
248 | 255 | ||
249 | if (device_may_wakeup(&pdev->dev)) { | 256 | if (pdata->clustered_irq > 0) { |
257 | if (keypad->gpio_all_disabled) { | ||
258 | disable_irq_wake(pdata->clustered_irq); | ||
259 | keypad->gpio_all_disabled = false; | ||
260 | } | ||
261 | } else { | ||
250 | for (i = 0; i < pdata->num_row_gpios; i++) { | 262 | for (i = 0; i < pdata->num_row_gpios; i++) { |
251 | if (test_and_clear_bit(i, keypad->disabled_gpios)) { | 263 | if (test_and_clear_bit(i, keypad->disabled_gpios)) { |
252 | unsigned int gpio = pdata->row_gpios[i]; | 264 | gpio = pdata->row_gpios[i]; |
253 | |||
254 | disable_irq_wake(gpio_to_irq(gpio)); | 265 | disable_irq_wake(gpio_to_irq(gpio)); |
255 | } | 266 | } |
256 | } | 267 | } |
257 | } | 268 | } |
269 | } | ||
270 | |||
271 | static int matrix_keypad_suspend(struct device *dev) | ||
272 | { | ||
273 | struct platform_device *pdev = to_platform_device(dev); | ||
274 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
275 | |||
276 | matrix_keypad_stop(keypad->input_dev); | ||
277 | |||
278 | if (device_may_wakeup(&pdev->dev)) | ||
279 | matrix_keypad_enable_wakeup(keypad); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int matrix_keypad_resume(struct device *dev) | ||
285 | { | ||
286 | struct platform_device *pdev = to_platform_device(dev); | ||
287 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
288 | |||
289 | if (device_may_wakeup(&pdev->dev)) | ||
290 | matrix_keypad_disable_wakeup(keypad); | ||
258 | 291 | ||
259 | matrix_keypad_start(keypad->input_dev); | 292 | matrix_keypad_start(keypad->input_dev); |
260 | 293 | ||
@@ -296,17 +329,31 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev, | |||
296 | gpio_direction_input(pdata->row_gpios[i]); | 329 | gpio_direction_input(pdata->row_gpios[i]); |
297 | } | 330 | } |
298 | 331 | ||
299 | for (i = 0; i < pdata->num_row_gpios; i++) { | 332 | if (pdata->clustered_irq > 0) { |
300 | err = request_irq(gpio_to_irq(pdata->row_gpios[i]), | 333 | err = request_irq(pdata->clustered_irq, |
301 | matrix_keypad_interrupt, | 334 | matrix_keypad_interrupt, |
302 | IRQF_DISABLED | | 335 | pdata->clustered_irq_flags, |
303 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
304 | "matrix-keypad", keypad); | 336 | "matrix-keypad", keypad); |
305 | if (err) { | 337 | if (err) { |
306 | dev_err(&pdev->dev, | 338 | dev_err(&pdev->dev, |
307 | "Unable to acquire interrupt for GPIO line %i\n", | 339 | "Unable to acquire clustered interrupt\n"); |
308 | pdata->row_gpios[i]); | 340 | goto err_free_rows; |
309 | goto err_free_irqs; | 341 | } |
342 | } else { | ||
343 | for (i = 0; i < pdata->num_row_gpios; i++) { | ||
344 | err = request_irq(gpio_to_irq(pdata->row_gpios[i]), | ||
345 | matrix_keypad_interrupt, | ||
346 | IRQF_DISABLED | | ||
347 | IRQF_TRIGGER_RISING | | ||
348 | IRQF_TRIGGER_FALLING, | ||
349 | "matrix-keypad", keypad); | ||
350 | if (err) { | ||
351 | dev_err(&pdev->dev, | ||
352 | "Unable to acquire interrupt " | ||
353 | "for GPIO line %i\n", | ||
354 | pdata->row_gpios[i]); | ||
355 | goto err_free_irqs; | ||
356 | } | ||
310 | } | 357 | } |
311 | } | 358 | } |
312 | 359 | ||
@@ -418,11 +465,16 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev) | |||
418 | 465 | ||
419 | device_init_wakeup(&pdev->dev, 0); | 466 | device_init_wakeup(&pdev->dev, 0); |
420 | 467 | ||
421 | for (i = 0; i < pdata->num_row_gpios; i++) { | 468 | if (pdata->clustered_irq > 0) { |
422 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | 469 | free_irq(pdata->clustered_irq, keypad); |
423 | gpio_free(pdata->row_gpios[i]); | 470 | } else { |
471 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
472 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
424 | } | 473 | } |
425 | 474 | ||
475 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
476 | gpio_free(pdata->row_gpios[i]); | ||
477 | |||
426 | for (i = 0; i < pdata->num_col_gpios; i++) | 478 | for (i = 0; i < pdata->num_col_gpios; i++) |
427 | gpio_free(pdata->col_gpios[i]); | 479 | gpio_free(pdata->col_gpios[i]); |
428 | 480 | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index c44b9eafc55..ede6d52fe95 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -390,4 +390,41 @@ config INPUT_PCAP | |||
390 | To compile this driver as a module, choose M here: the | 390 | To compile this driver as a module, choose M here: the |
391 | module will be called pcap_keys. | 391 | module will be called pcap_keys. |
392 | 392 | ||
393 | config INPUT_ADXL34X | ||
394 | tristate "Analog Devices ADXL34x Three-Axis Digital Accelerometer" | ||
395 | default n | ||
396 | help | ||
397 | Say Y here if you have a Accelerometer interface using the | ||
398 | ADXL345/6 controller, and your board-specific initialization | ||
399 | code includes that in its table of devices. | ||
400 | |||
401 | This driver can use either I2C or SPI communication to the | ||
402 | ADXL345/6 controller. Select the appropriate method for | ||
403 | your system. | ||
404 | |||
405 | If unsure, say N (but it's safe to say "Y"). | ||
406 | |||
407 | To compile this driver as a module, choose M here: the | ||
408 | module will be called adxl34x. | ||
409 | |||
410 | config INPUT_ADXL34X_I2C | ||
411 | tristate "support I2C bus connection" | ||
412 | depends on INPUT_ADXL34X && I2C | ||
413 | default y | ||
414 | help | ||
415 | Say Y here if you have ADXL345/6 hooked to an I2C bus. | ||
416 | |||
417 | To compile this driver as a module, choose M here: the | ||
418 | module will be called adxl34x-i2c. | ||
419 | |||
420 | config INPUT_ADXL34X_SPI | ||
421 | tristate "support SPI bus connection" | ||
422 | depends on INPUT_ADXL34X && SPI | ||
423 | default y | ||
424 | help | ||
425 | Say Y here if you have ADXL345/6 hooked to a SPI bus. | ||
426 | |||
427 | To compile this driver as a module, choose M here: the | ||
428 | module will be called adxl34x-spi. | ||
429 | |||
393 | endif | 430 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 71fe57d8023..97b5dc32df1 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -8,6 +8,9 @@ obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o | |||
8 | obj-$(CONFIG_INPUT_AD714X) += ad714x.o | 8 | obj-$(CONFIG_INPUT_AD714X) += ad714x.o |
9 | obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o | 9 | obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o |
10 | obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o | 10 | obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o |
11 | obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o | ||
12 | obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o | ||
13 | obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o | ||
11 | obj-$(CONFIG_INPUT_APANEL) += apanel.o | 14 | obj-$(CONFIG_INPUT_APANEL) += apanel.o |
12 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | 15 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o |
13 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 16 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c new file mode 100644 index 00000000000..76194b58bd0 --- /dev/null +++ b/drivers/input/misc/adxl34x-i2c.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * ADLX345/346 Three-Axis Digital Accelerometers (I2C Interface) | ||
3 | * | ||
4 | * Enter bugs at http://blackfin.uclinux.org/ | ||
5 | * | ||
6 | * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc. | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/input.h> /* BUS_I2C */ | ||
11 | #include <linux/i2c.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/types.h> | ||
14 | #include "adxl34x.h" | ||
15 | |||
16 | static int adxl34x_smbus_read(struct device *dev, unsigned char reg) | ||
17 | { | ||
18 | struct i2c_client *client = to_i2c_client(dev); | ||
19 | |||
20 | return i2c_smbus_read_byte_data(client, reg); | ||
21 | } | ||
22 | |||
23 | static int adxl34x_smbus_write(struct device *dev, | ||
24 | unsigned char reg, unsigned char val) | ||
25 | { | ||
26 | struct i2c_client *client = to_i2c_client(dev); | ||
27 | |||
28 | return i2c_smbus_write_byte_data(client, reg, val); | ||
29 | } | ||
30 | |||
31 | static int adxl34x_smbus_read_block(struct device *dev, | ||
32 | unsigned char reg, int count, | ||
33 | void *buf) | ||
34 | { | ||
35 | struct i2c_client *client = to_i2c_client(dev); | ||
36 | |||
37 | return i2c_smbus_read_i2c_block_data(client, reg, count, buf); | ||
38 | } | ||
39 | |||
40 | static int adxl34x_i2c_read_block(struct device *dev, | ||
41 | unsigned char reg, int count, | ||
42 | void *buf) | ||
43 | { | ||
44 | struct i2c_client *client = to_i2c_client(dev); | ||
45 | int ret; | ||
46 | |||
47 | ret = i2c_master_send(client, ®, 1); | ||
48 | if (ret < 0) | ||
49 | return ret; | ||
50 | |||
51 | ret = i2c_master_recv(client, buf, count); | ||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | |||
55 | if (ret != count) | ||
56 | return -EIO; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static const struct adxl34x_bus_ops adx134x_smbus_bops = { | ||
62 | .bustype = BUS_I2C, | ||
63 | .write = adxl34x_smbus_write, | ||
64 | .read = adxl34x_smbus_read, | ||
65 | .read_block = adxl34x_smbus_read_block, | ||
66 | }; | ||
67 | |||
68 | static const struct adxl34x_bus_ops adx134x_i2c_bops = { | ||
69 | .bustype = BUS_I2C, | ||
70 | .write = adxl34x_smbus_write, | ||
71 | .read = adxl34x_smbus_read, | ||
72 | .read_block = adxl34x_i2c_read_block, | ||
73 | }; | ||
74 | |||
75 | static int __devinit adxl34x_i2c_probe(struct i2c_client *client, | ||
76 | const struct i2c_device_id *id) | ||
77 | { | ||
78 | struct adxl34x *ac; | ||
79 | int error; | ||
80 | |||
81 | error = i2c_check_functionality(client->adapter, | ||
82 | I2C_FUNC_SMBUS_BYTE_DATA); | ||
83 | if (!error) { | ||
84 | dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); | ||
85 | return -EIO; | ||
86 | } | ||
87 | |||
88 | ac = adxl34x_probe(&client->dev, client->irq, false, | ||
89 | i2c_check_functionality(client->adapter, | ||
90 | I2C_FUNC_SMBUS_READ_I2C_BLOCK) ? | ||
91 | &adx134x_smbus_bops : &adx134x_i2c_bops); | ||
92 | if (IS_ERR(ac)) | ||
93 | return PTR_ERR(ac); | ||
94 | |||
95 | i2c_set_clientdata(client, ac); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int __devexit adxl34x_i2c_remove(struct i2c_client *client) | ||
101 | { | ||
102 | struct adxl34x *ac = i2c_get_clientdata(client); | ||
103 | |||
104 | return adxl34x_remove(ac); | ||
105 | } | ||
106 | |||
107 | #ifdef CONFIG_PM | ||
108 | static int adxl34x_suspend(struct i2c_client *client, pm_message_t message) | ||
109 | { | ||
110 | struct adxl34x *ac = i2c_get_clientdata(client); | ||
111 | |||
112 | adxl34x_disable(ac); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int adxl34x_resume(struct i2c_client *client) | ||
118 | { | ||
119 | struct adxl34x *ac = i2c_get_clientdata(client); | ||
120 | |||
121 | adxl34x_enable(ac); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | #else | ||
126 | # define adxl34x_suspend NULL | ||
127 | # define adxl34x_resume NULL | ||
128 | #endif | ||
129 | |||
130 | static const struct i2c_device_id adxl34x_id[] = { | ||
131 | { "adxl34x", 0 }, | ||
132 | { } | ||
133 | }; | ||
134 | |||
135 | MODULE_DEVICE_TABLE(i2c, adxl34x_id); | ||
136 | |||
137 | static struct i2c_driver adxl34x_driver = { | ||
138 | .driver = { | ||
139 | .name = "adxl34x", | ||
140 | .owner = THIS_MODULE, | ||
141 | }, | ||
142 | .probe = adxl34x_i2c_probe, | ||
143 | .remove = __devexit_p(adxl34x_i2c_remove), | ||
144 | .suspend = adxl34x_suspend, | ||
145 | .resume = adxl34x_resume, | ||
146 | .id_table = adxl34x_id, | ||
147 | }; | ||
148 | |||
149 | static int __init adxl34x_i2c_init(void) | ||
150 | { | ||
151 | return i2c_add_driver(&adxl34x_driver); | ||
152 | } | ||
153 | module_init(adxl34x_i2c_init); | ||
154 | |||
155 | static void __exit adxl34x_i2c_exit(void) | ||
156 | { | ||
157 | i2c_del_driver(&adxl34x_driver); | ||
158 | } | ||
159 | module_exit(adxl34x_i2c_exit); | ||
160 | |||
161 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
162 | MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer I2C Bus Driver"); | ||
163 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c new file mode 100644 index 00000000000..7f992353ffd --- /dev/null +++ b/drivers/input/misc/adxl34x-spi.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * ADLX345/346 Three-Axis Digital Accelerometers (SPI Interface) | ||
3 | * | ||
4 | * Enter bugs at http://blackfin.uclinux.org/ | ||
5 | * | ||
6 | * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc. | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/input.h> /* BUS_SPI */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/spi/spi.h> | ||
13 | #include <linux/types.h> | ||
14 | #include "adxl34x.h" | ||
15 | |||
16 | #define MAX_SPI_FREQ_HZ 5000000 | ||
17 | #define MAX_FREQ_NO_FIFODELAY 1500000 | ||
18 | #define ADXL34X_CMD_MULTB (1 << 6) | ||
19 | #define ADXL34X_CMD_READ (1 << 7) | ||
20 | #define ADXL34X_WRITECMD(reg) (reg & 0x3F) | ||
21 | #define ADXL34X_READCMD(reg) (ADXL34X_CMD_READ | (reg & 0x3F)) | ||
22 | #define ADXL34X_READMB_CMD(reg) (ADXL34X_CMD_READ | ADXL34X_CMD_MULTB \ | ||
23 | | (reg & 0x3F)) | ||
24 | |||
25 | static int adxl34x_spi_read(struct device *dev, unsigned char reg) | ||
26 | { | ||
27 | struct spi_device *spi = to_spi_device(dev); | ||
28 | unsigned char cmd; | ||
29 | |||
30 | cmd = ADXL34X_READCMD(reg); | ||
31 | |||
32 | return spi_w8r8(spi, cmd); | ||
33 | } | ||
34 | |||
35 | static int adxl34x_spi_write(struct device *dev, | ||
36 | unsigned char reg, unsigned char val) | ||
37 | { | ||
38 | struct spi_device *spi = to_spi_device(dev); | ||
39 | unsigned char buf[2]; | ||
40 | |||
41 | buf[0] = ADXL34X_WRITECMD(reg); | ||
42 | buf[1] = val; | ||
43 | |||
44 | return spi_write(spi, buf, sizeof(buf)); | ||
45 | } | ||
46 | |||
47 | static int adxl34x_spi_read_block(struct device *dev, | ||
48 | unsigned char reg, int count, | ||
49 | void *buf) | ||
50 | { | ||
51 | struct spi_device *spi = to_spi_device(dev); | ||
52 | ssize_t status; | ||
53 | |||
54 | reg = ADXL34X_READMB_CMD(reg); | ||
55 | status = spi_write_then_read(spi, ®, 1, buf, count); | ||
56 | |||
57 | return (status < 0) ? status : 0; | ||
58 | } | ||
59 | |||
60 | static const struct adxl34x_bus_ops adx134x_spi_bops = { | ||
61 | .bustype = BUS_SPI, | ||
62 | .write = adxl34x_spi_write, | ||
63 | .read = adxl34x_spi_read, | ||
64 | .read_block = adxl34x_spi_read_block, | ||
65 | }; | ||
66 | |||
67 | static int __devinit adxl34x_spi_probe(struct spi_device *spi) | ||
68 | { | ||
69 | struct adxl34x *ac; | ||
70 | |||
71 | /* don't exceed max specified SPI CLK frequency */ | ||
72 | if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) { | ||
73 | dev_err(&spi->dev, "SPI CLK %d Hz too fast\n", spi->max_speed_hz); | ||
74 | return -EINVAL; | ||
75 | } | ||
76 | |||
77 | ac = adxl34x_probe(&spi->dev, spi->irq, | ||
78 | spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY, | ||
79 | &adx134x_spi_bops); | ||
80 | |||
81 | if (IS_ERR(ac)) | ||
82 | return PTR_ERR(ac); | ||
83 | |||
84 | spi_set_drvdata(spi, ac); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int __devexit adxl34x_spi_remove(struct spi_device *spi) | ||
90 | { | ||
91 | struct adxl34x *ac = dev_get_drvdata(&spi->dev); | ||
92 | |||
93 | return adxl34x_remove(ac); | ||
94 | } | ||
95 | |||
96 | #ifdef CONFIG_PM | ||
97 | static int adxl34x_suspend(struct spi_device *spi, pm_message_t message) | ||
98 | { | ||
99 | struct adxl34x *ac = dev_get_drvdata(&spi->dev); | ||
100 | |||
101 | adxl34x_disable(ac); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int adxl34x_resume(struct spi_device *spi) | ||
107 | { | ||
108 | struct adxl34x *ac = dev_get_drvdata(&spi->dev); | ||
109 | |||
110 | adxl34x_enable(ac); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | #else | ||
115 | # define adxl34x_suspend NULL | ||
116 | # define adxl34x_resume NULL | ||
117 | #endif | ||
118 | |||
119 | static struct spi_driver adxl34x_driver = { | ||
120 | .driver = { | ||
121 | .name = "adxl34x", | ||
122 | .bus = &spi_bus_type, | ||
123 | .owner = THIS_MODULE, | ||
124 | }, | ||
125 | .probe = adxl34x_spi_probe, | ||
126 | .remove = __devexit_p(adxl34x_spi_remove), | ||
127 | .suspend = adxl34x_suspend, | ||
128 | .resume = adxl34x_resume, | ||
129 | }; | ||
130 | |||
131 | static int __init adxl34x_spi_init(void) | ||
132 | { | ||
133 | return spi_register_driver(&adxl34x_driver); | ||
134 | } | ||
135 | module_init(adxl34x_spi_init); | ||
136 | |||
137 | static void __exit adxl34x_spi_exit(void) | ||
138 | { | ||
139 | spi_unregister_driver(&adxl34x_driver); | ||
140 | } | ||
141 | module_exit(adxl34x_spi_exit); | ||
142 | |||
143 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
144 | MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer SPI Bus Driver"); | ||
145 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c new file mode 100644 index 00000000000..77fb4098705 --- /dev/null +++ b/drivers/input/misc/adxl34x.c | |||
@@ -0,0 +1,894 @@ | |||
1 | /* | ||
2 | * ADXL345/346 Three-Axis Digital Accelerometers | ||
3 | * | ||
4 | * Enter bugs at http://blackfin.uclinux.org/ | ||
5 | * | ||
6 | * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc. | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/device.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/input.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/workqueue.h> | ||
18 | #include <linux/input/adxl34x.h> | ||
19 | |||
20 | #include "adxl34x.h" | ||
21 | |||
22 | /* ADXL345/6 Register Map */ | ||
23 | #define DEVID 0x00 /* R Device ID */ | ||
24 | #define THRESH_TAP 0x1D /* R/W Tap threshold */ | ||
25 | #define OFSX 0x1E /* R/W X-axis offset */ | ||
26 | #define OFSY 0x1F /* R/W Y-axis offset */ | ||
27 | #define OFSZ 0x20 /* R/W Z-axis offset */ | ||
28 | #define DUR 0x21 /* R/W Tap duration */ | ||
29 | #define LATENT 0x22 /* R/W Tap latency */ | ||
30 | #define WINDOW 0x23 /* R/W Tap window */ | ||
31 | #define THRESH_ACT 0x24 /* R/W Activity threshold */ | ||
32 | #define THRESH_INACT 0x25 /* R/W Inactivity threshold */ | ||
33 | #define TIME_INACT 0x26 /* R/W Inactivity time */ | ||
34 | #define ACT_INACT_CTL 0x27 /* R/W Axis enable control for activity and */ | ||
35 | /* inactivity detection */ | ||
36 | #define THRESH_FF 0x28 /* R/W Free-fall threshold */ | ||
37 | #define TIME_FF 0x29 /* R/W Free-fall time */ | ||
38 | #define TAP_AXES 0x2A /* R/W Axis control for tap/double tap */ | ||
39 | #define ACT_TAP_STATUS 0x2B /* R Source of tap/double tap */ | ||
40 | #define BW_RATE 0x2C /* R/W Data rate and power mode control */ | ||
41 | #define POWER_CTL 0x2D /* R/W Power saving features control */ | ||
42 | #define INT_ENABLE 0x2E /* R/W Interrupt enable control */ | ||
43 | #define INT_MAP 0x2F /* R/W Interrupt mapping control */ | ||
44 | #define INT_SOURCE 0x30 /* R Source of interrupts */ | ||
45 | #define DATA_FORMAT 0x31 /* R/W Data format control */ | ||
46 | #define DATAX0 0x32 /* R X-Axis Data 0 */ | ||
47 | #define DATAX1 0x33 /* R X-Axis Data 1 */ | ||
48 | #define DATAY0 0x34 /* R Y-Axis Data 0 */ | ||
49 | #define DATAY1 0x35 /* R Y-Axis Data 1 */ | ||
50 | #define DATAZ0 0x36 /* R Z-Axis Data 0 */ | ||
51 | #define DATAZ1 0x37 /* R Z-Axis Data 1 */ | ||
52 | #define FIFO_CTL 0x38 /* R/W FIFO control */ | ||
53 | #define FIFO_STATUS 0x39 /* R FIFO status */ | ||
54 | #define TAP_SIGN 0x3A /* R Sign and source for tap/double tap */ | ||
55 | /* Orientation ADXL346 only */ | ||
56 | #define ORIENT_CONF 0x3B /* R/W Orientation configuration */ | ||
57 | #define ORIENT 0x3C /* R Orientation status */ | ||
58 | |||
59 | /* DEVIDs */ | ||
60 | #define ID_ADXL345 0xE5 | ||
61 | #define ID_ADXL346 0xE6 | ||
62 | |||
63 | /* INT_ENABLE/INT_MAP/INT_SOURCE Bits */ | ||
64 | #define DATA_READY (1 << 7) | ||
65 | #define SINGLE_TAP (1 << 6) | ||
66 | #define DOUBLE_TAP (1 << 5) | ||
67 | #define ACTIVITY (1 << 4) | ||
68 | #define INACTIVITY (1 << 3) | ||
69 | #define FREE_FALL (1 << 2) | ||
70 | #define WATERMARK (1 << 1) | ||
71 | #define OVERRUN (1 << 0) | ||
72 | |||
73 | /* ACT_INACT_CONTROL Bits */ | ||
74 | #define ACT_ACDC (1 << 7) | ||
75 | #define ACT_X_EN (1 << 6) | ||
76 | #define ACT_Y_EN (1 << 5) | ||
77 | #define ACT_Z_EN (1 << 4) | ||
78 | #define INACT_ACDC (1 << 3) | ||
79 | #define INACT_X_EN (1 << 2) | ||
80 | #define INACT_Y_EN (1 << 1) | ||
81 | #define INACT_Z_EN (1 << 0) | ||
82 | |||
83 | /* TAP_AXES Bits */ | ||
84 | #define SUPPRESS (1 << 3) | ||
85 | #define TAP_X_EN (1 << 2) | ||
86 | #define TAP_Y_EN (1 << 1) | ||
87 | #define TAP_Z_EN (1 << 0) | ||
88 | |||
89 | /* ACT_TAP_STATUS Bits */ | ||
90 | #define ACT_X_SRC (1 << 6) | ||
91 | #define ACT_Y_SRC (1 << 5) | ||
92 | #define ACT_Z_SRC (1 << 4) | ||
93 | #define ASLEEP (1 << 3) | ||
94 | #define TAP_X_SRC (1 << 2) | ||
95 | #define TAP_Y_SRC (1 << 1) | ||
96 | #define TAP_Z_SRC (1 << 0) | ||
97 | |||
98 | /* BW_RATE Bits */ | ||
99 | #define LOW_POWER (1 << 4) | ||
100 | #define RATE(x) ((x) & 0xF) | ||
101 | |||
102 | /* POWER_CTL Bits */ | ||
103 | #define PCTL_LINK (1 << 5) | ||
104 | #define PCTL_AUTO_SLEEP (1 << 4) | ||
105 | #define PCTL_MEASURE (1 << 3) | ||
106 | #define PCTL_SLEEP (1 << 2) | ||
107 | #define PCTL_WAKEUP(x) ((x) & 0x3) | ||
108 | |||
109 | /* DATA_FORMAT Bits */ | ||
110 | #define SELF_TEST (1 << 7) | ||
111 | #define SPI (1 << 6) | ||
112 | #define INT_INVERT (1 << 5) | ||
113 | #define FULL_RES (1 << 3) | ||
114 | #define JUSTIFY (1 << 2) | ||
115 | #define RANGE(x) ((x) & 0x3) | ||
116 | #define RANGE_PM_2g 0 | ||
117 | #define RANGE_PM_4g 1 | ||
118 | #define RANGE_PM_8g 2 | ||
119 | #define RANGE_PM_16g 3 | ||
120 | |||
121 | /* | ||
122 | * Maximum value our axis may get in full res mode for the input device | ||
123 | * (signed 13 bits) | ||
124 | */ | ||
125 | #define ADXL_FULLRES_MAX_VAL 4096 | ||
126 | |||
127 | /* | ||
128 | * Maximum value our axis may get in fixed res mode for the input device | ||
129 | * (signed 10 bits) | ||
130 | */ | ||
131 | #define ADXL_FIXEDRES_MAX_VAL 512 | ||
132 | |||
133 | /* FIFO_CTL Bits */ | ||
134 | #define FIFO_MODE(x) (((x) & 0x3) << 6) | ||
135 | #define FIFO_BYPASS 0 | ||
136 | #define FIFO_FIFO 1 | ||
137 | #define FIFO_STREAM 2 | ||
138 | #define FIFO_TRIGGER 3 | ||
139 | #define TRIGGER (1 << 5) | ||
140 | #define SAMPLES(x) ((x) & 0x1F) | ||
141 | |||
142 | /* FIFO_STATUS Bits */ | ||
143 | #define FIFO_TRIG (1 << 7) | ||
144 | #define ENTRIES(x) ((x) & 0x3F) | ||
145 | |||
146 | /* TAP_SIGN Bits ADXL346 only */ | ||
147 | #define XSIGN (1 << 6) | ||
148 | #define YSIGN (1 << 5) | ||
149 | #define ZSIGN (1 << 4) | ||
150 | #define XTAP (1 << 3) | ||
151 | #define YTAP (1 << 2) | ||
152 | #define ZTAP (1 << 1) | ||
153 | |||
154 | /* ORIENT_CONF ADXL346 only */ | ||
155 | #define ORIENT_DEADZONE(x) (((x) & 0x7) << 4) | ||
156 | #define ORIENT_DIVISOR(x) ((x) & 0x7) | ||
157 | |||
158 | /* ORIENT ADXL346 only */ | ||
159 | #define ADXL346_2D_VALID (1 << 6) | ||
160 | #define ADXL346_2D_ORIENT(x) (((x) & 0x3) >> 4) | ||
161 | #define ADXL346_3D_VALID (1 << 3) | ||
162 | #define ADXL346_3D_ORIENT(x) ((x) & 0x7) | ||
163 | #define ADXL346_2D_PORTRAIT_POS 0 /* +X */ | ||
164 | #define ADXL346_2D_PORTRAIT_NEG 1 /* -X */ | ||
165 | #define ADXL346_2D_LANDSCAPE_POS 2 /* +Y */ | ||
166 | #define ADXL346_2D_LANDSCAPE_NEG 3 /* -Y */ | ||
167 | |||
168 | #define ADXL346_3D_FRONT 3 /* +X */ | ||
169 | #define ADXL346_3D_BACK 4 /* -X */ | ||
170 | #define ADXL346_3D_RIGHT 2 /* +Y */ | ||
171 | #define ADXL346_3D_LEFT 5 /* -Y */ | ||
172 | #define ADXL346_3D_TOP 1 /* +Z */ | ||
173 | #define ADXL346_3D_BOTTOM 6 /* -Z */ | ||
174 | |||
175 | #undef ADXL_DEBUG | ||
176 | |||
177 | #define ADXL_X_AXIS 0 | ||
178 | #define ADXL_Y_AXIS 1 | ||
179 | #define ADXL_Z_AXIS 2 | ||
180 | |||
181 | #define AC_READ(ac, reg) ((ac)->bops->read((ac)->dev, reg)) | ||
182 | #define AC_WRITE(ac, reg, val) ((ac)->bops->write((ac)->dev, reg, val)) | ||
183 | |||
184 | struct axis_triple { | ||
185 | int x; | ||
186 | int y; | ||
187 | int z; | ||
188 | }; | ||
189 | |||
190 | struct adxl34x { | ||
191 | struct device *dev; | ||
192 | struct input_dev *input; | ||
193 | struct mutex mutex; /* reentrant protection for struct */ | ||
194 | struct adxl34x_platform_data pdata; | ||
195 | struct axis_triple swcal; | ||
196 | struct axis_triple hwcal; | ||
197 | struct axis_triple saved; | ||
198 | char phys[32]; | ||
199 | unsigned orient2d_saved; | ||
200 | unsigned orient3d_saved; | ||
201 | bool disabled; /* P: mutex */ | ||
202 | bool opened; /* P: mutex */ | ||
203 | bool fifo_delay; | ||
204 | int irq; | ||
205 | unsigned model; | ||
206 | unsigned int_mask; | ||
207 | |||
208 | const struct adxl34x_bus_ops *bops; | ||
209 | }; | ||
210 | |||
211 | static const struct adxl34x_platform_data adxl34x_default_init = { | ||
212 | .tap_threshold = 35, | ||
213 | .tap_duration = 3, | ||
214 | .tap_latency = 20, | ||
215 | .tap_window = 20, | ||
216 | .tap_axis_control = ADXL_TAP_X_EN | ADXL_TAP_Y_EN | ADXL_TAP_Z_EN, | ||
217 | .act_axis_control = 0xFF, | ||
218 | .activity_threshold = 6, | ||
219 | .inactivity_threshold = 4, | ||
220 | .inactivity_time = 3, | ||
221 | .free_fall_threshold = 8, | ||
222 | .free_fall_time = 0x20, | ||
223 | .data_rate = 8, | ||
224 | .data_range = ADXL_FULL_RES, | ||
225 | |||
226 | .ev_type = EV_ABS, | ||
227 | .ev_code_x = ABS_X, /* EV_REL */ | ||
228 | .ev_code_y = ABS_Y, /* EV_REL */ | ||
229 | .ev_code_z = ABS_Z, /* EV_REL */ | ||
230 | |||
231 | .ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY {x,y,z} */ | ||
232 | .power_mode = ADXL_AUTO_SLEEP | ADXL_LINK, | ||
233 | .fifo_mode = FIFO_STREAM, | ||
234 | .watermark = 0, | ||
235 | }; | ||
236 | |||
237 | static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis) | ||
238 | { | ||
239 | short buf[3]; | ||
240 | |||
241 | ac->bops->read_block(ac->dev, DATAX0, DATAZ1 - DATAX0 + 1, buf); | ||
242 | |||
243 | mutex_lock(&ac->mutex); | ||
244 | ac->saved.x = (s16) le16_to_cpu(buf[0]); | ||
245 | axis->x = ac->saved.x; | ||
246 | |||
247 | ac->saved.y = (s16) le16_to_cpu(buf[1]); | ||
248 | axis->y = ac->saved.y; | ||
249 | |||
250 | ac->saved.z = (s16) le16_to_cpu(buf[2]); | ||
251 | axis->z = ac->saved.z; | ||
252 | mutex_unlock(&ac->mutex); | ||
253 | } | ||
254 | |||
255 | static void adxl34x_service_ev_fifo(struct adxl34x *ac) | ||
256 | { | ||
257 | struct adxl34x_platform_data *pdata = &ac->pdata; | ||
258 | struct axis_triple axis; | ||
259 | |||
260 | adxl34x_get_triple(ac, &axis); | ||
261 | |||
262 | input_event(ac->input, pdata->ev_type, pdata->ev_code_x, | ||
263 | axis.x - ac->swcal.x); | ||
264 | input_event(ac->input, pdata->ev_type, pdata->ev_code_y, | ||
265 | axis.y - ac->swcal.y); | ||
266 | input_event(ac->input, pdata->ev_type, pdata->ev_code_z, | ||
267 | axis.z - ac->swcal.z); | ||
268 | } | ||
269 | |||
270 | static void adxl34x_report_key_single(struct input_dev *input, int key) | ||
271 | { | ||
272 | input_report_key(input, key, true); | ||
273 | input_sync(input); | ||
274 | input_report_key(input, key, false); | ||
275 | } | ||
276 | |||
277 | static void adxl34x_send_key_events(struct adxl34x *ac, | ||
278 | struct adxl34x_platform_data *pdata, int status, int press) | ||
279 | { | ||
280 | int i; | ||
281 | |||
282 | for (i = ADXL_X_AXIS; i <= ADXL_Z_AXIS; i++) { | ||
283 | if (status & (1 << (ADXL_Z_AXIS - i))) | ||
284 | input_report_key(ac->input, | ||
285 | pdata->ev_code_tap[i], press); | ||
286 | } | ||
287 | } | ||
288 | |||
289 | static void adxl34x_do_tap(struct adxl34x *ac, | ||
290 | struct adxl34x_platform_data *pdata, int status) | ||
291 | { | ||
292 | adxl34x_send_key_events(ac, pdata, status, true); | ||
293 | input_sync(ac->input); | ||
294 | adxl34x_send_key_events(ac, pdata, status, false); | ||
295 | } | ||
296 | |||
297 | static irqreturn_t adxl34x_irq(int irq, void *handle) | ||
298 | { | ||
299 | struct adxl34x *ac = handle; | ||
300 | struct adxl34x_platform_data *pdata = &ac->pdata; | ||
301 | int int_stat, tap_stat, samples, orient, orient_code; | ||
302 | |||
303 | /* | ||
304 | * ACT_TAP_STATUS should be read before clearing the interrupt | ||
305 | * Avoid reading ACT_TAP_STATUS in case TAP detection is disabled | ||
306 | */ | ||
307 | |||
308 | if (pdata->tap_axis_control & (TAP_X_EN | TAP_Y_EN | TAP_Z_EN)) | ||
309 | tap_stat = AC_READ(ac, ACT_TAP_STATUS); | ||
310 | else | ||
311 | tap_stat = 0; | ||
312 | |||
313 | int_stat = AC_READ(ac, INT_SOURCE); | ||
314 | |||
315 | if (int_stat & FREE_FALL) | ||
316 | adxl34x_report_key_single(ac->input, pdata->ev_code_ff); | ||
317 | |||
318 | if (int_stat & OVERRUN) | ||
319 | dev_dbg(ac->dev, "OVERRUN\n"); | ||
320 | |||
321 | if (int_stat & (SINGLE_TAP | DOUBLE_TAP)) { | ||
322 | adxl34x_do_tap(ac, pdata, tap_stat); | ||
323 | |||
324 | if (int_stat & DOUBLE_TAP) | ||
325 | adxl34x_do_tap(ac, pdata, tap_stat); | ||
326 | } | ||
327 | |||
328 | if (pdata->ev_code_act_inactivity) { | ||
329 | if (int_stat & ACTIVITY) | ||
330 | input_report_key(ac->input, | ||
331 | pdata->ev_code_act_inactivity, 1); | ||
332 | if (int_stat & INACTIVITY) | ||
333 | input_report_key(ac->input, | ||
334 | pdata->ev_code_act_inactivity, 0); | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * ORIENTATION SENSING ADXL346 only | ||
339 | */ | ||
340 | if (pdata->orientation_enable) { | ||
341 | orient = AC_READ(ac, ORIENT); | ||
342 | if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) && | ||
343 | (orient & ADXL346_2D_VALID)) { | ||
344 | |||
345 | orient_code = ADXL346_2D_ORIENT(orient); | ||
346 | /* Report orientation only when it changes */ | ||
347 | if (ac->orient2d_saved != orient_code) { | ||
348 | ac->orient2d_saved = orient_code; | ||
349 | adxl34x_report_key_single(ac->input, | ||
350 | pdata->ev_codes_orient_2d[orient_code]); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) && | ||
355 | (orient & ADXL346_3D_VALID)) { | ||
356 | |||
357 | orient_code = ADXL346_3D_ORIENT(orient) - 1; | ||
358 | /* Report orientation only when it changes */ | ||
359 | if (ac->orient3d_saved != orient_code) { | ||
360 | ac->orient3d_saved = orient_code; | ||
361 | adxl34x_report_key_single(ac->input, | ||
362 | pdata->ev_codes_orient_3d[orient_code]); | ||
363 | } | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (int_stat & (DATA_READY | WATERMARK)) { | ||
368 | |||
369 | if (pdata->fifo_mode) | ||
370 | samples = ENTRIES(AC_READ(ac, FIFO_STATUS)) + 1; | ||
371 | else | ||
372 | samples = 1; | ||
373 | |||
374 | for (; samples > 0; samples--) { | ||
375 | adxl34x_service_ev_fifo(ac); | ||
376 | /* | ||
377 | * To ensure that the FIFO has | ||
378 | * completely popped, there must be at least 5 us between | ||
379 | * the end of reading the data registers, signified by the | ||
380 | * transition to register 0x38 from 0x37 or the CS pin | ||
381 | * going high, and the start of new reads of the FIFO or | ||
382 | * reading the FIFO_STATUS register. For SPI operation at | ||
383 | * 1.5 MHz or lower, the register addressing portion of the | ||
384 | * transmission is sufficient delay to ensure the FIFO has | ||
385 | * completely popped. It is necessary for SPI operation | ||
386 | * greater than 1.5 MHz to de-assert the CS pin to ensure a | ||
387 | * total of 5 us, which is at most 3.4 us at 5 MHz | ||
388 | * operation. | ||
389 | */ | ||
390 | if (ac->fifo_delay && (samples > 1)) | ||
391 | udelay(3); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | input_sync(ac->input); | ||
396 | |||
397 | return IRQ_HANDLED; | ||
398 | } | ||
399 | |||
400 | static void __adxl34x_disable(struct adxl34x *ac) | ||
401 | { | ||
402 | if (!ac->disabled && ac->opened) { | ||
403 | /* | ||
404 | * A '0' places the ADXL34x into standby mode | ||
405 | * with minimum power consumption. | ||
406 | */ | ||
407 | AC_WRITE(ac, POWER_CTL, 0); | ||
408 | |||
409 | ac->disabled = true; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | static void __adxl34x_enable(struct adxl34x *ac) | ||
414 | { | ||
415 | if (ac->disabled && ac->opened) { | ||
416 | AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); | ||
417 | ac->disabled = false; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | void adxl34x_disable(struct adxl34x *ac) | ||
422 | { | ||
423 | mutex_lock(&ac->mutex); | ||
424 | __adxl34x_disable(ac); | ||
425 | mutex_unlock(&ac->mutex); | ||
426 | } | ||
427 | EXPORT_SYMBOL_GPL(adxl34x_disable); | ||
428 | |||
429 | void adxl34x_enable(struct adxl34x *ac) | ||
430 | { | ||
431 | mutex_lock(&ac->mutex); | ||
432 | __adxl34x_enable(ac); | ||
433 | mutex_unlock(&ac->mutex); | ||
434 | } | ||
435 | |||
436 | EXPORT_SYMBOL_GPL(adxl34x_enable); | ||
437 | |||
438 | static ssize_t adxl34x_disable_show(struct device *dev, | ||
439 | struct device_attribute *attr, char *buf) | ||
440 | { | ||
441 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
442 | |||
443 | return sprintf(buf, "%u\n", ac->disabled); | ||
444 | } | ||
445 | |||
446 | static ssize_t adxl34x_disable_store(struct device *dev, | ||
447 | struct device_attribute *attr, | ||
448 | const char *buf, size_t count) | ||
449 | { | ||
450 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
451 | unsigned long val; | ||
452 | int error; | ||
453 | |||
454 | error = strict_strtoul(buf, 10, &val); | ||
455 | if (error) | ||
456 | return error; | ||
457 | |||
458 | if (val) | ||
459 | adxl34x_disable(ac); | ||
460 | else | ||
461 | adxl34x_enable(ac); | ||
462 | |||
463 | return count; | ||
464 | } | ||
465 | |||
466 | static DEVICE_ATTR(disable, 0664, adxl34x_disable_show, adxl34x_disable_store); | ||
467 | |||
468 | static ssize_t adxl34x_calibrate_show(struct device *dev, | ||
469 | struct device_attribute *attr, char *buf) | ||
470 | { | ||
471 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
472 | ssize_t count; | ||
473 | |||
474 | mutex_lock(&ac->mutex); | ||
475 | count = sprintf(buf, "%d,%d,%d\n", | ||
476 | ac->hwcal.x * 4 + ac->swcal.x, | ||
477 | ac->hwcal.y * 4 + ac->swcal.y, | ||
478 | ac->hwcal.z * 4 + ac->swcal.z); | ||
479 | mutex_unlock(&ac->mutex); | ||
480 | |||
481 | return count; | ||
482 | } | ||
483 | |||
484 | static ssize_t adxl34x_calibrate_store(struct device *dev, | ||
485 | struct device_attribute *attr, | ||
486 | const char *buf, size_t count) | ||
487 | { | ||
488 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
489 | |||
490 | /* | ||
491 | * Hardware offset calibration has a resolution of 15.6 mg/LSB. | ||
492 | * We use HW calibration and handle the remaining bits in SW. (4mg/LSB) | ||
493 | */ | ||
494 | |||
495 | mutex_lock(&ac->mutex); | ||
496 | ac->hwcal.x -= (ac->saved.x / 4); | ||
497 | ac->swcal.x = ac->saved.x % 4; | ||
498 | |||
499 | ac->hwcal.y -= (ac->saved.y / 4); | ||
500 | ac->swcal.y = ac->saved.y % 4; | ||
501 | |||
502 | ac->hwcal.z -= (ac->saved.z / 4); | ||
503 | ac->swcal.z = ac->saved.z % 4; | ||
504 | |||
505 | AC_WRITE(ac, OFSX, (s8) ac->hwcal.x); | ||
506 | AC_WRITE(ac, OFSY, (s8) ac->hwcal.y); | ||
507 | AC_WRITE(ac, OFSZ, (s8) ac->hwcal.z); | ||
508 | mutex_unlock(&ac->mutex); | ||
509 | |||
510 | return count; | ||
511 | } | ||
512 | |||
513 | static DEVICE_ATTR(calibrate, 0664, | ||
514 | adxl34x_calibrate_show, adxl34x_calibrate_store); | ||
515 | |||
516 | static ssize_t adxl34x_rate_show(struct device *dev, | ||
517 | struct device_attribute *attr, char *buf) | ||
518 | { | ||
519 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
520 | |||
521 | return sprintf(buf, "%u\n", RATE(ac->pdata.data_rate)); | ||
522 | } | ||
523 | |||
524 | static ssize_t adxl34x_rate_store(struct device *dev, | ||
525 | struct device_attribute *attr, | ||
526 | const char *buf, size_t count) | ||
527 | { | ||
528 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
529 | unsigned long val; | ||
530 | int error; | ||
531 | |||
532 | error = strict_strtoul(buf, 10, &val); | ||
533 | if (error) | ||
534 | return error; | ||
535 | |||
536 | mutex_lock(&ac->mutex); | ||
537 | |||
538 | ac->pdata.data_rate = RATE(val); | ||
539 | AC_WRITE(ac, BW_RATE, | ||
540 | ac->pdata.data_rate | | ||
541 | (ac->pdata.low_power_mode ? LOW_POWER : 0)); | ||
542 | |||
543 | mutex_unlock(&ac->mutex); | ||
544 | |||
545 | return count; | ||
546 | } | ||
547 | |||
548 | static DEVICE_ATTR(rate, 0664, adxl34x_rate_show, adxl34x_rate_store); | ||
549 | |||
550 | static ssize_t adxl34x_autosleep_show(struct device *dev, | ||
551 | struct device_attribute *attr, char *buf) | ||
552 | { | ||
553 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
554 | |||
555 | return sprintf(buf, "%u\n", | ||
556 | ac->pdata.power_mode & (PCTL_AUTO_SLEEP | PCTL_LINK) ? 1 : 0); | ||
557 | } | ||
558 | |||
559 | static ssize_t adxl34x_autosleep_store(struct device *dev, | ||
560 | struct device_attribute *attr, | ||
561 | const char *buf, size_t count) | ||
562 | { | ||
563 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
564 | unsigned long val; | ||
565 | int error; | ||
566 | |||
567 | error = strict_strtoul(buf, 10, &val); | ||
568 | if (error) | ||
569 | return error; | ||
570 | |||
571 | mutex_lock(&ac->mutex); | ||
572 | |||
573 | if (val) | ||
574 | ac->pdata.power_mode |= (PCTL_AUTO_SLEEP | PCTL_LINK); | ||
575 | else | ||
576 | ac->pdata.power_mode &= ~(PCTL_AUTO_SLEEP | PCTL_LINK); | ||
577 | |||
578 | if (!ac->disabled && ac->opened) | ||
579 | AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); | ||
580 | |||
581 | mutex_unlock(&ac->mutex); | ||
582 | |||
583 | return count; | ||
584 | } | ||
585 | |||
586 | static DEVICE_ATTR(autosleep, 0664, | ||
587 | adxl34x_autosleep_show, adxl34x_autosleep_store); | ||
588 | |||
589 | static ssize_t adxl34x_position_show(struct device *dev, | ||
590 | struct device_attribute *attr, char *buf) | ||
591 | { | ||
592 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
593 | ssize_t count; | ||
594 | |||
595 | mutex_lock(&ac->mutex); | ||
596 | count = sprintf(buf, "(%d, %d, %d)\n", | ||
597 | ac->saved.x, ac->saved.y, ac->saved.z); | ||
598 | mutex_unlock(&ac->mutex); | ||
599 | |||
600 | return count; | ||
601 | } | ||
602 | |||
603 | static DEVICE_ATTR(position, S_IRUGO, adxl34x_position_show, NULL); | ||
604 | |||
605 | #ifdef ADXL_DEBUG | ||
606 | static ssize_t adxl34x_write_store(struct device *dev, | ||
607 | struct device_attribute *attr, | ||
608 | const char *buf, size_t count) | ||
609 | { | ||
610 | struct adxl34x *ac = dev_get_drvdata(dev); | ||
611 | unsigned long val; | ||
612 | int error; | ||
613 | |||
614 | /* | ||
615 | * This allows basic ADXL register write access for debug purposes. | ||
616 | */ | ||
617 | error = strict_strtoul(buf, 16, &val); | ||
618 | if (error) | ||
619 | return error; | ||
620 | |||
621 | mutex_lock(&ac->mutex); | ||
622 | AC_WRITE(ac, val >> 8, val & 0xFF); | ||
623 | mutex_unlock(&ac->mutex); | ||
624 | |||
625 | return count; | ||
626 | } | ||
627 | |||
628 | static DEVICE_ATTR(write, 0664, NULL, adxl34x_write_store); | ||
629 | #endif | ||
630 | |||
631 | static struct attribute *adxl34x_attributes[] = { | ||
632 | &dev_attr_disable.attr, | ||
633 | &dev_attr_calibrate.attr, | ||
634 | &dev_attr_rate.attr, | ||
635 | &dev_attr_autosleep.attr, | ||
636 | &dev_attr_position.attr, | ||
637 | #ifdef ADXL_DEBUG | ||
638 | &dev_attr_write.attr, | ||
639 | #endif | ||
640 | NULL | ||
641 | }; | ||
642 | |||
643 | static const struct attribute_group adxl34x_attr_group = { | ||
644 | .attrs = adxl34x_attributes, | ||
645 | }; | ||
646 | |||
647 | static int adxl34x_input_open(struct input_dev *input) | ||
648 | { | ||
649 | struct adxl34x *ac = input_get_drvdata(input); | ||
650 | |||
651 | mutex_lock(&ac->mutex); | ||
652 | ac->opened = true; | ||
653 | __adxl34x_enable(ac); | ||
654 | mutex_unlock(&ac->mutex); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static void adxl34x_input_close(struct input_dev *input) | ||
660 | { | ||
661 | struct adxl34x *ac = input_get_drvdata(input); | ||
662 | |||
663 | mutex_lock(&ac->mutex); | ||
664 | __adxl34x_disable(ac); | ||
665 | ac->opened = false; | ||
666 | mutex_unlock(&ac->mutex); | ||
667 | } | ||
668 | |||
669 | struct adxl34x *adxl34x_probe(struct device *dev, int irq, | ||
670 | bool fifo_delay_default, | ||
671 | const struct adxl34x_bus_ops *bops) | ||
672 | { | ||
673 | struct adxl34x *ac; | ||
674 | struct input_dev *input_dev; | ||
675 | const struct adxl34x_platform_data *pdata; | ||
676 | int err, range, i; | ||
677 | unsigned char revid; | ||
678 | |||
679 | if (!irq) { | ||
680 | dev_err(dev, "no IRQ?\n"); | ||
681 | err = -ENODEV; | ||
682 | goto err_out; | ||
683 | } | ||
684 | |||
685 | ac = kzalloc(sizeof(*ac), GFP_KERNEL); | ||
686 | input_dev = input_allocate_device(); | ||
687 | if (!ac || !input_dev) { | ||
688 | err = -ENOMEM; | ||
689 | goto err_out; | ||
690 | } | ||
691 | |||
692 | ac->fifo_delay = fifo_delay_default; | ||
693 | |||
694 | pdata = dev->platform_data; | ||
695 | if (!pdata) { | ||
696 | dev_dbg(dev, | ||
697 | "No platfrom data: Using default initialization\n"); | ||
698 | pdata = &adxl34x_default_init; | ||
699 | } | ||
700 | |||
701 | ac->pdata = *pdata; | ||
702 | pdata = &ac->pdata; | ||
703 | |||
704 | ac->input = input_dev; | ||
705 | ac->disabled = true; | ||
706 | ac->dev = dev; | ||
707 | ac->irq = irq; | ||
708 | ac->bops = bops; | ||
709 | |||
710 | mutex_init(&ac->mutex); | ||
711 | |||
712 | input_dev->name = "ADXL34x accelerometer"; | ||
713 | revid = ac->bops->read(dev, DEVID); | ||
714 | |||
715 | switch (revid) { | ||
716 | case ID_ADXL345: | ||
717 | ac->model = 345; | ||
718 | break; | ||
719 | case ID_ADXL346: | ||
720 | ac->model = 346; | ||
721 | break; | ||
722 | default: | ||
723 | dev_err(dev, "Failed to probe %s\n", input_dev->name); | ||
724 | err = -ENODEV; | ||
725 | goto err_free_mem; | ||
726 | } | ||
727 | |||
728 | snprintf(ac->phys, sizeof(ac->phys), "%s/input0", dev_name(dev)); | ||
729 | |||
730 | input_dev->phys = ac->phys; | ||
731 | input_dev->dev.parent = dev; | ||
732 | input_dev->id.product = ac->model; | ||
733 | input_dev->id.bustype = bops->bustype; | ||
734 | input_dev->open = adxl34x_input_open; | ||
735 | input_dev->close = adxl34x_input_close; | ||
736 | |||
737 | input_set_drvdata(input_dev, ac); | ||
738 | |||
739 | __set_bit(ac->pdata.ev_type, input_dev->evbit); | ||
740 | |||
741 | if (ac->pdata.ev_type == EV_REL) { | ||
742 | __set_bit(REL_X, input_dev->relbit); | ||
743 | __set_bit(REL_Y, input_dev->relbit); | ||
744 | __set_bit(REL_Z, input_dev->relbit); | ||
745 | } else { | ||
746 | /* EV_ABS */ | ||
747 | __set_bit(ABS_X, input_dev->absbit); | ||
748 | __set_bit(ABS_Y, input_dev->absbit); | ||
749 | __set_bit(ABS_Z, input_dev->absbit); | ||
750 | |||
751 | if (pdata->data_range & FULL_RES) | ||
752 | range = ADXL_FULLRES_MAX_VAL; /* Signed 13-bit */ | ||
753 | else | ||
754 | range = ADXL_FIXEDRES_MAX_VAL; /* Signed 10-bit */ | ||
755 | |||
756 | input_set_abs_params(input_dev, ABS_X, -range, range, 3, 3); | ||
757 | input_set_abs_params(input_dev, ABS_Y, -range, range, 3, 3); | ||
758 | input_set_abs_params(input_dev, ABS_Z, -range, range, 3, 3); | ||
759 | } | ||
760 | |||
761 | __set_bit(EV_KEY, input_dev->evbit); | ||
762 | __set_bit(pdata->ev_code_tap[ADXL_X_AXIS], input_dev->keybit); | ||
763 | __set_bit(pdata->ev_code_tap[ADXL_Y_AXIS], input_dev->keybit); | ||
764 | __set_bit(pdata->ev_code_tap[ADXL_Z_AXIS], input_dev->keybit); | ||
765 | |||
766 | if (pdata->ev_code_ff) { | ||
767 | ac->int_mask = FREE_FALL; | ||
768 | __set_bit(pdata->ev_code_ff, input_dev->keybit); | ||
769 | } | ||
770 | |||
771 | if (pdata->ev_code_act_inactivity) | ||
772 | __set_bit(pdata->ev_code_act_inactivity, input_dev->keybit); | ||
773 | |||
774 | ac->int_mask |= ACTIVITY | INACTIVITY; | ||
775 | |||
776 | if (pdata->watermark) { | ||
777 | ac->int_mask |= WATERMARK; | ||
778 | if (!FIFO_MODE(pdata->fifo_mode)) | ||
779 | ac->pdata.fifo_mode |= FIFO_STREAM; | ||
780 | } else { | ||
781 | ac->int_mask |= DATA_READY; | ||
782 | } | ||
783 | |||
784 | if (pdata->tap_axis_control & (TAP_X_EN | TAP_Y_EN | TAP_Z_EN)) | ||
785 | ac->int_mask |= SINGLE_TAP | DOUBLE_TAP; | ||
786 | |||
787 | if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS) | ||
788 | ac->fifo_delay = false; | ||
789 | |||
790 | ac->bops->write(dev, POWER_CTL, 0); | ||
791 | |||
792 | err = request_threaded_irq(ac->irq, NULL, adxl34x_irq, | ||
793 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
794 | dev_name(dev), ac); | ||
795 | if (err) { | ||
796 | dev_err(dev, "irq %d busy?\n", ac->irq); | ||
797 | goto err_free_mem; | ||
798 | } | ||
799 | |||
800 | err = sysfs_create_group(&dev->kobj, &adxl34x_attr_group); | ||
801 | if (err) | ||
802 | goto err_free_irq; | ||
803 | |||
804 | err = input_register_device(input_dev); | ||
805 | if (err) | ||
806 | goto err_remove_attr; | ||
807 | |||
808 | AC_WRITE(ac, THRESH_TAP, pdata->tap_threshold); | ||
809 | AC_WRITE(ac, OFSX, pdata->x_axis_offset); | ||
810 | ac->hwcal.x = pdata->x_axis_offset; | ||
811 | AC_WRITE(ac, OFSY, pdata->y_axis_offset); | ||
812 | ac->hwcal.y = pdata->y_axis_offset; | ||
813 | AC_WRITE(ac, OFSZ, pdata->z_axis_offset); | ||
814 | ac->hwcal.z = pdata->z_axis_offset; | ||
815 | AC_WRITE(ac, THRESH_TAP, pdata->tap_threshold); | ||
816 | AC_WRITE(ac, DUR, pdata->tap_duration); | ||
817 | AC_WRITE(ac, LATENT, pdata->tap_latency); | ||
818 | AC_WRITE(ac, WINDOW, pdata->tap_window); | ||
819 | AC_WRITE(ac, THRESH_ACT, pdata->activity_threshold); | ||
820 | AC_WRITE(ac, THRESH_INACT, pdata->inactivity_threshold); | ||
821 | AC_WRITE(ac, TIME_INACT, pdata->inactivity_time); | ||
822 | AC_WRITE(ac, THRESH_FF, pdata->free_fall_threshold); | ||
823 | AC_WRITE(ac, TIME_FF, pdata->free_fall_time); | ||
824 | AC_WRITE(ac, TAP_AXES, pdata->tap_axis_control); | ||
825 | AC_WRITE(ac, ACT_INACT_CTL, pdata->act_axis_control); | ||
826 | AC_WRITE(ac, BW_RATE, RATE(ac->pdata.data_rate) | | ||
827 | (pdata->low_power_mode ? LOW_POWER : 0)); | ||
828 | AC_WRITE(ac, DATA_FORMAT, pdata->data_range); | ||
829 | AC_WRITE(ac, FIFO_CTL, FIFO_MODE(pdata->fifo_mode) | | ||
830 | SAMPLES(pdata->watermark)); | ||
831 | |||
832 | if (pdata->use_int2) { | ||
833 | /* Map all INTs to INT2 */ | ||
834 | AC_WRITE(ac, INT_MAP, ac->int_mask | OVERRUN); | ||
835 | } else { | ||
836 | /* Map all INTs to INT1 */ | ||
837 | AC_WRITE(ac, INT_MAP, 0); | ||
838 | } | ||
839 | |||
840 | if (ac->model == 346 && ac->pdata.orientation_enable) { | ||
841 | AC_WRITE(ac, ORIENT_CONF, | ||
842 | ORIENT_DEADZONE(ac->pdata.deadzone_angle) | | ||
843 | ORIENT_DIVISOR(ac->pdata.divisor_length)); | ||
844 | |||
845 | ac->orient2d_saved = 1234; | ||
846 | ac->orient3d_saved = 1234; | ||
847 | |||
848 | if (pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) | ||
849 | for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_3d); i++) | ||
850 | __set_bit(pdata->ev_codes_orient_3d[i], | ||
851 | input_dev->keybit); | ||
852 | |||
853 | if (pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) | ||
854 | for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_2d); i++) | ||
855 | __set_bit(pdata->ev_codes_orient_2d[i], | ||
856 | input_dev->keybit); | ||
857 | } else { | ||
858 | ac->pdata.orientation_enable = 0; | ||
859 | } | ||
860 | |||
861 | AC_WRITE(ac, INT_ENABLE, ac->int_mask | OVERRUN); | ||
862 | |||
863 | ac->pdata.power_mode &= (PCTL_AUTO_SLEEP | PCTL_LINK); | ||
864 | |||
865 | return ac; | ||
866 | |||
867 | err_remove_attr: | ||
868 | sysfs_remove_group(&dev->kobj, &adxl34x_attr_group); | ||
869 | err_free_irq: | ||
870 | free_irq(ac->irq, ac); | ||
871 | err_free_mem: | ||
872 | input_free_device(input_dev); | ||
873 | kfree(ac); | ||
874 | err_out: | ||
875 | return ERR_PTR(err); | ||
876 | } | ||
877 | EXPORT_SYMBOL_GPL(adxl34x_probe); | ||
878 | |||
879 | int adxl34x_remove(struct adxl34x *ac) | ||
880 | { | ||
881 | adxl34x_disable(ac); | ||
882 | sysfs_remove_group(&ac->dev->kobj, &adxl34x_attr_group); | ||
883 | free_irq(ac->irq, ac); | ||
884 | input_unregister_device(ac->input); | ||
885 | kfree(ac); | ||
886 | |||
887 | dev_dbg(ac->dev, "unregistered accelerometer\n"); | ||
888 | return 0; | ||
889 | } | ||
890 | EXPORT_SYMBOL_GPL(adxl34x_remove); | ||
891 | |||
892 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
893 | MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer Driver"); | ||
894 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/adxl34x.h b/drivers/input/misc/adxl34x.h new file mode 100644 index 00000000000..ea9093c15c8 --- /dev/null +++ b/drivers/input/misc/adxl34x.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * ADXL345/346 Three-Axis Digital Accelerometers (I2C/SPI Interface) | ||
3 | * | ||
4 | * Enter bugs at http://blackfin.uclinux.org/ | ||
5 | * | ||
6 | * Copyright (C) 2009 Michael Hennerich, Analog Devices Inc. | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #ifndef _ADXL34X_H_ | ||
11 | #define _ADXL34X_H_ | ||
12 | |||
13 | struct device; | ||
14 | struct adxl34x; | ||
15 | |||
16 | struct adxl34x_bus_ops { | ||
17 | u16 bustype; | ||
18 | int (*read)(struct device *, unsigned char); | ||
19 | int (*read_block)(struct device *, unsigned char, int, void *); | ||
20 | int (*write)(struct device *, unsigned char, unsigned char); | ||
21 | }; | ||
22 | |||
23 | void adxl34x_disable(struct adxl34x *ac); | ||
24 | void adxl34x_enable(struct adxl34x *ac); | ||
25 | struct adxl34x *adxl34x_probe(struct device *dev, int irq, | ||
26 | bool fifo_delay_default, | ||
27 | const struct adxl34x_bus_ops *bops); | ||
28 | int adxl34x_remove(struct adxl34x *ac); | ||
29 | |||
30 | #endif | ||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 4dac8b79fcd..12501de0c5c 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -1347,7 +1347,7 @@ static int __init wb_module_init(void) | |||
1347 | 1347 | ||
1348 | err = map_bios(); | 1348 | err = map_bios(); |
1349 | if (err) | 1349 | if (err) |
1350 | return err; | 1350 | goto err_free_keymap; |
1351 | 1351 | ||
1352 | err = platform_driver_register(&wistron_driver); | 1352 | err = platform_driver_register(&wistron_driver); |
1353 | if (err) | 1353 | if (err) |
@@ -1371,6 +1371,8 @@ static int __init wb_module_init(void) | |||
1371 | platform_driver_unregister(&wistron_driver); | 1371 | platform_driver_unregister(&wistron_driver); |
1372 | err_unmap_bios: | 1372 | err_unmap_bios: |
1373 | unmap_bios(); | 1373 | unmap_bios(); |
1374 | err_free_keymap: | ||
1375 | kfree(keymap); | ||
1374 | 1376 | ||
1375 | return err; | 1377 | return err; |
1376 | } | 1378 | } |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 6dedded2722..ea67c49146a 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -312,6 +312,8 @@ static void setup_events_to_report(struct input_dev *input_dev, | |||
312 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | 312 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); |
313 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | 313 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); |
314 | __set_bit(BTN_LEFT, input_dev->keybit); | 314 | __set_bit(BTN_LEFT, input_dev->keybit); |
315 | |||
316 | input_set_events_per_packet(input_dev, 60); | ||
315 | } | 317 | } |
316 | 318 | ||
317 | /* report button data as logical button state */ | 319 | /* report button data as logical button state */ |
@@ -580,23 +582,30 @@ exit: | |||
580 | */ | 582 | */ |
581 | static int bcm5974_start_traffic(struct bcm5974 *dev) | 583 | static int bcm5974_start_traffic(struct bcm5974 *dev) |
582 | { | 584 | { |
583 | if (bcm5974_wellspring_mode(dev, true)) { | 585 | int error; |
586 | |||
587 | error = bcm5974_wellspring_mode(dev, true); | ||
588 | if (error) { | ||
584 | dprintk(1, "bcm5974: mode switch failed\n"); | 589 | dprintk(1, "bcm5974: mode switch failed\n"); |
585 | goto error; | 590 | goto err_out; |
586 | } | 591 | } |
587 | 592 | ||
588 | if (usb_submit_urb(dev->bt_urb, GFP_KERNEL)) | 593 | error = usb_submit_urb(dev->bt_urb, GFP_KERNEL); |
589 | goto error; | 594 | if (error) |
595 | goto err_reset_mode; | ||
590 | 596 | ||
591 | if (usb_submit_urb(dev->tp_urb, GFP_KERNEL)) | 597 | error = usb_submit_urb(dev->tp_urb, GFP_KERNEL); |
598 | if (error) | ||
592 | goto err_kill_bt; | 599 | goto err_kill_bt; |
593 | 600 | ||
594 | return 0; | 601 | return 0; |
595 | 602 | ||
596 | err_kill_bt: | 603 | err_kill_bt: |
597 | usb_kill_urb(dev->bt_urb); | 604 | usb_kill_urb(dev->bt_urb); |
598 | error: | 605 | err_reset_mode: |
599 | return -EIO; | 606 | bcm5974_wellspring_mode(dev, false); |
607 | err_out: | ||
608 | return error; | ||
600 | } | 609 | } |
601 | 610 | ||
602 | static void bcm5974_pause_traffic(struct bcm5974 *dev) | 611 | static void bcm5974_pause_traffic(struct bcm5974 *dev) |
diff --git a/drivers/input/serio/i8042-ppcio.h b/drivers/input/serio/i8042-ppcio.h index 2906e1b60c0..f708c75d16f 100644 --- a/drivers/input/serio/i8042-ppcio.h +++ b/drivers/input/serio/i8042-ppcio.h | |||
@@ -52,81 +52,6 @@ static inline void i8042_platform_exit(void) | |||
52 | { | 52 | { |
53 | } | 53 | } |
54 | 54 | ||
55 | #elif defined(CONFIG_SPRUCE) | ||
56 | |||
57 | #define I8042_KBD_IRQ 22 | ||
58 | #define I8042_AUX_IRQ 21 | ||
59 | |||
60 | #define I8042_KBD_PHYS_DESC "spruceps2/serio0" | ||
61 | #define I8042_AUX_PHYS_DESC "spruceps2/serio1" | ||
62 | #define I8042_MUX_PHYS_DESC "spruceps2/serio%d" | ||
63 | |||
64 | #define I8042_COMMAND_REG 0xff810000 | ||
65 | #define I8042_DATA_REG 0xff810001 | ||
66 | |||
67 | static inline int i8042_read_data(void) | ||
68 | { | ||
69 | unsigned long kbd_data; | ||
70 | |||
71 | __raw_writel(0x00000088, 0xff500008); | ||
72 | eieio(); | ||
73 | |||
74 | __raw_writel(0x03000000, 0xff50000c); | ||
75 | eieio(); | ||
76 | |||
77 | asm volatile("lis 7,0xff88 \n\ | ||
78 | lswi 6,7,0x8 \n\ | ||
79 | mr %0,6" | ||
80 | : "=r" (kbd_data) :: "6", "7"); | ||
81 | |||
82 | __raw_writel(0x00000000, 0xff50000c); | ||
83 | eieio(); | ||
84 | |||
85 | return (unsigned char)(kbd_data >> 24); | ||
86 | } | ||
87 | |||
88 | static inline int i8042_read_status(void) | ||
89 | { | ||
90 | unsigned long kbd_status; | ||
91 | |||
92 | __raw_writel(0x00000088, 0xff500008); | ||
93 | eieio(); | ||
94 | |||
95 | __raw_writel(0x03000000, 0xff50000c); | ||
96 | eieio(); | ||
97 | |||
98 | asm volatile("lis 7,0xff88 \n\ | ||
99 | ori 7,7,0x8 \n\ | ||
100 | lswi 6,7,0x8 \n\ | ||
101 | mr %0,6" | ||
102 | : "=r" (kbd_status) :: "6", "7"); | ||
103 | |||
104 | __raw_writel(0x00000000, 0xff50000c); | ||
105 | eieio(); | ||
106 | |||
107 | return (unsigned char)(kbd_status >> 24); | ||
108 | } | ||
109 | |||
110 | static inline void i8042_write_data(int val) | ||
111 | { | ||
112 | *((unsigned char *)0xff810000) = (char)val; | ||
113 | } | ||
114 | |||
115 | static inline void i8042_write_command(int val) | ||
116 | { | ||
117 | *((unsigned char *)0xff810001) = (char)val; | ||
118 | } | ||
119 | |||
120 | static inline int i8042_platform_init(void) | ||
121 | { | ||
122 | i8042_reset = 1; | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static inline void i8042_platform_exit(void) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | #else | 55 | #else |
131 | 56 | ||
132 | #include "i8042-io.h" | 57 | #include "i8042-io.h" |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index d564af58175..555ef26e206 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -158,6 +158,39 @@ static int wacom_ptu_irq(struct wacom_wac *wacom) | |||
158 | return 1; | 158 | return 1; |
159 | } | 159 | } |
160 | 160 | ||
161 | static int wacom_dtu_irq(struct wacom_wac *wacom) | ||
162 | { | ||
163 | struct wacom_features *features = &wacom->features; | ||
164 | char *data = wacom->data; | ||
165 | struct input_dev *input = wacom->input; | ||
166 | int prox = data[1] & 0x20, pressure; | ||
167 | |||
168 | dbg("wacom_dtu_irq: received report #%d", data[0]); | ||
169 | |||
170 | if (prox) { | ||
171 | /* Going into proximity select tool */ | ||
172 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
173 | if (wacom->tool[0] == BTN_TOOL_PEN) | ||
174 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
175 | else | ||
176 | wacom->id[0] = ERASER_DEVICE_ID; | ||
177 | } | ||
178 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); | ||
179 | input_report_key(input, BTN_STYLUS2, data[1] & 0x10); | ||
180 | input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); | ||
181 | input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); | ||
182 | pressure = ((data[7] & 0x01) << 8) | data[6]; | ||
183 | if (pressure < 0) | ||
184 | pressure = features->pressure_max + pressure + 1; | ||
185 | input_report_abs(input, ABS_PRESSURE, pressure); | ||
186 | input_report_key(input, BTN_TOUCH, data[1] & 0x05); | ||
187 | if (!prox) /* out-prox */ | ||
188 | wacom->id[0] = 0; | ||
189 | input_report_key(input, wacom->tool[0], prox); | ||
190 | input_report_abs(input, ABS_MISC, wacom->id[0]); | ||
191 | return 1; | ||
192 | } | ||
193 | |||
161 | static int wacom_graphire_irq(struct wacom_wac *wacom) | 194 | static int wacom_graphire_irq(struct wacom_wac *wacom) |
162 | { | 195 | { |
163 | struct wacom_features *features = &wacom->features; | 196 | struct wacom_features *features = &wacom->features; |
@@ -844,6 +877,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
844 | sync = wacom_ptu_irq(wacom_wac); | 877 | sync = wacom_ptu_irq(wacom_wac); |
845 | break; | 878 | break; |
846 | 879 | ||
880 | case DTU: | ||
881 | sync = wacom_dtu_irq(wacom_wac); | ||
882 | break; | ||
883 | |||
847 | case INTUOS: | 884 | case INTUOS: |
848 | case INTUOS3S: | 885 | case INTUOS3S: |
849 | case INTUOS3: | 886 | case INTUOS3: |
@@ -1029,6 +1066,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1029 | 1066 | ||
1030 | case PL: | 1067 | case PL: |
1031 | case PTU: | 1068 | case PTU: |
1069 | case DTU: | ||
1032 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | 1070 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
1033 | __set_bit(BTN_STYLUS, input_dev->keybit); | 1071 | __set_bit(BTN_STYLUS, input_dev->keybit); |
1034 | __set_bit(BTN_STYLUS2, input_dev->keybit); | 1072 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
@@ -1154,6 +1192,10 @@ static const struct wacom_features wacom_features_0xC6 = | |||
1154 | { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }; | 1192 | { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }; |
1155 | static const struct wacom_features wacom_features_0xC7 = | 1193 | static const struct wacom_features wacom_features_0xC7 = |
1156 | { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }; | 1194 | { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }; |
1195 | static const struct wacom_features wacom_features_0xCE = | ||
1196 | { "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511, 0, DTU }; | ||
1197 | static const struct wacom_features wacom_features_0xF0 = | ||
1198 | { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, 0, DTU }; | ||
1157 | static const struct wacom_features wacom_features_0xCC = | 1199 | static const struct wacom_features wacom_features_0xCC = |
1158 | { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2 }; | 1200 | { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2 }; |
1159 | static const struct wacom_features wacom_features_0x90 = | 1201 | static const struct wacom_features wacom_features_0x90 = |
@@ -1233,6 +1275,8 @@ const struct usb_device_id wacom_ids[] = { | |||
1233 | { USB_DEVICE_WACOM(0xC5) }, | 1275 | { USB_DEVICE_WACOM(0xC5) }, |
1234 | { USB_DEVICE_WACOM(0xC6) }, | 1276 | { USB_DEVICE_WACOM(0xC6) }, |
1235 | { USB_DEVICE_WACOM(0xC7) }, | 1277 | { USB_DEVICE_WACOM(0xC7) }, |
1278 | { USB_DEVICE_WACOM(0xCE) }, | ||
1279 | { USB_DEVICE_WACOM(0xF0) }, | ||
1236 | { USB_DEVICE_WACOM(0xCC) }, | 1280 | { USB_DEVICE_WACOM(0xCC) }, |
1237 | { USB_DEVICE_WACOM(0x90) }, | 1281 | { USB_DEVICE_WACOM(0x90) }, |
1238 | { USB_DEVICE_WACOM(0x93) }, | 1282 | { USB_DEVICE_WACOM(0x93) }, |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 854b92092df..99e1a54cd30 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -43,6 +43,7 @@ enum { | |||
43 | WACOM_G4, | 43 | WACOM_G4, |
44 | PTU, | 44 | PTU, |
45 | PL, | 45 | PL, |
46 | DTU, | ||
46 | INTUOS, | 47 | INTUOS, |
47 | INTUOS3S, | 48 | INTUOS3S, |
48 | INTUOS3, | 49 | INTUOS3, |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 3b9d5e2105d..e835f04bc0d 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -540,9 +540,9 @@ config TOUCHSCREEN_USB_ZYTRONIC | |||
540 | bool "Zytronic controller" if EMBEDDED | 540 | bool "Zytronic controller" if EMBEDDED |
541 | depends on TOUCHSCREEN_USB_COMPOSITE | 541 | depends on TOUCHSCREEN_USB_COMPOSITE |
542 | 542 | ||
543 | config TOUCHSCREEN_USB_ETT_TC5UH | 543 | config TOUCHSCREEN_USB_ETT_TC45USB |
544 | default y | 544 | default y |
545 | bool "ET&T TC5UH touchscreen controler support" if EMBEDDED | 545 | bool "ET&T USB series TC4UM/TC5UH touchscreen controler support" if EMBEDDED |
546 | depends on TOUCHSCREEN_USB_COMPOSITE | 546 | depends on TOUCHSCREEN_USB_COMPOSITE |
547 | 547 | ||
548 | config TOUCHSCREEN_USB_NEXIO | 548 | config TOUCHSCREEN_USB_NEXIO |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index a9fdf55c023..69210cb56c5 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -1174,7 +1174,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1174 | goto err_put_regulator; | 1174 | goto err_put_regulator; |
1175 | } | 1175 | } |
1176 | 1176 | ||
1177 | if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, | 1177 | if (!pdata->irq_flags) |
1178 | pdata->irq_flags = IRQF_TRIGGER_FALLING; | ||
1179 | |||
1180 | if (request_irq(spi->irq, ads7846_irq, pdata->irq_flags, | ||
1178 | spi->dev.driver->name, ts)) { | 1181 | spi->dev.driver->name, ts)) { |
1179 | dev_info(&spi->dev, | 1182 | dev_info(&spi->dev, |
1180 | "trying pin change workaround on irq %d\n", spi->irq); | 1183 | "trying pin change workaround on irq %d\n", spi->irq); |
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index 5b70a1419b4..a644d18c04d 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c | |||
@@ -355,9 +355,6 @@ static int __devexit tps6507x_ts_remove(struct platform_device *pdev) | |||
355 | struct tps6507x_ts *tsc = tps6507x_dev->ts; | 355 | struct tps6507x_ts *tsc = tps6507x_dev->ts; |
356 | struct input_dev *input_dev = tsc->input_dev; | 356 | struct input_dev *input_dev = tsc->input_dev; |
357 | 357 | ||
358 | if (!tsc) | ||
359 | return 0; | ||
360 | |||
361 | cancel_delayed_work_sync(&tsc->work); | 358 | cancel_delayed_work_sync(&tsc->work); |
362 | destroy_workqueue(tsc->wq); | 359 | destroy_workqueue(tsc->wq); |
363 | 360 | ||
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 567d57215c2..b9cee2738ad 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -135,7 +135,7 @@ enum { | |||
135 | DEVTYPE_JASTEC, | 135 | DEVTYPE_JASTEC, |
136 | DEVTYPE_E2I, | 136 | DEVTYPE_E2I, |
137 | DEVTYPE_ZYTRONIC, | 137 | DEVTYPE_ZYTRONIC, |
138 | DEVTYPE_TC5UH, | 138 | DEVTYPE_TC45USB, |
139 | DEVTYPE_NEXIO, | 139 | DEVTYPE_NEXIO, |
140 | }; | 140 | }; |
141 | 141 | ||
@@ -222,8 +222,11 @@ static const struct usb_device_id usbtouch_devices[] = { | |||
222 | {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, | 222 | {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, |
223 | #endif | 223 | #endif |
224 | 224 | ||
225 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | 225 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB |
226 | {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC5UH}, | 226 | /* TC5UH */ |
227 | {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB}, | ||
228 | /* TC4UM */ | ||
229 | {USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB}, | ||
227 | #endif | 230 | #endif |
228 | 231 | ||
229 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | 232 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO |
@@ -574,10 +577,10 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
574 | #endif | 577 | #endif |
575 | 578 | ||
576 | /***************************************************************************** | 579 | /***************************************************************************** |
577 | * ET&T TC5UH part | 580 | * ET&T TC5UH/TC4UM part |
578 | */ | 581 | */ |
579 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | 582 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB |
580 | static int tc5uh_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 583 | static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
581 | { | 584 | { |
582 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; | 585 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; |
583 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | 586 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; |
@@ -849,29 +852,32 @@ static void nexio_exit(struct usbtouch_usb *usbtouch) | |||
849 | 852 | ||
850 | static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) | 853 | static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) |
851 | { | 854 | { |
852 | int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; | ||
853 | struct nexio_touch_packet *packet = (void *) pkt; | 855 | struct nexio_touch_packet *packet = (void *) pkt; |
854 | struct nexio_priv *priv = usbtouch->priv; | 856 | struct nexio_priv *priv = usbtouch->priv; |
857 | unsigned int data_len = be16_to_cpu(packet->data_len); | ||
858 | unsigned int x_len = be16_to_cpu(packet->x_len); | ||
859 | unsigned int y_len = be16_to_cpu(packet->y_len); | ||
860 | int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; | ||
855 | 861 | ||
856 | /* got touch data? */ | 862 | /* got touch data? */ |
857 | if ((pkt[0] & 0xe0) != 0xe0) | 863 | if ((pkt[0] & 0xe0) != 0xe0) |
858 | return 0; | 864 | return 0; |
859 | 865 | ||
860 | if (be16_to_cpu(packet->data_len) > 0xff) | 866 | if (data_len > 0xff) |
861 | packet->data_len = cpu_to_be16(be16_to_cpu(packet->data_len) - 0x100); | 867 | data_len -= 0x100; |
862 | if (be16_to_cpu(packet->x_len) > 0xff) | 868 | if (x_len > 0xff) |
863 | packet->x_len = cpu_to_be16(be16_to_cpu(packet->x_len) - 0x80); | 869 | x_len -= 0x80; |
864 | 870 | ||
865 | /* send ACK */ | 871 | /* send ACK */ |
866 | ret = usb_submit_urb(priv->ack, GFP_ATOMIC); | 872 | ret = usb_submit_urb(priv->ack, GFP_ATOMIC); |
867 | 873 | ||
868 | if (!usbtouch->type->max_xc) { | 874 | if (!usbtouch->type->max_xc) { |
869 | usbtouch->type->max_xc = 2 * be16_to_cpu(packet->x_len); | 875 | usbtouch->type->max_xc = 2 * x_len; |
870 | input_set_abs_params(usbtouch->input, ABS_X, 0, | 876 | input_set_abs_params(usbtouch->input, ABS_X, |
871 | 2 * be16_to_cpu(packet->x_len), 0, 0); | 877 | 0, usbtouch->type->max_xc, 0, 0); |
872 | usbtouch->type->max_yc = 2 * be16_to_cpu(packet->y_len); | 878 | usbtouch->type->max_yc = 2 * y_len; |
873 | input_set_abs_params(usbtouch->input, ABS_Y, 0, | 879 | input_set_abs_params(usbtouch->input, ABS_Y, |
874 | 2 * be16_to_cpu(packet->y_len), 0, 0); | 880 | 0, usbtouch->type->max_yc, 0, 0); |
875 | } | 881 | } |
876 | /* | 882 | /* |
877 | * The device reports state of IR sensors on X and Y axes. | 883 | * The device reports state of IR sensors on X and Y axes. |
@@ -881,22 +887,21 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) | |||
881 | * it's disabled (and untested) here as there's no X driver for that. | 887 | * it's disabled (and untested) here as there's no X driver for that. |
882 | */ | 888 | */ |
883 | begin_x = end_x = begin_y = end_y = -1; | 889 | begin_x = end_x = begin_y = end_y = -1; |
884 | for (x = 0; x < be16_to_cpu(packet->x_len); x++) { | 890 | for (x = 0; x < x_len; x++) { |
885 | if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { | 891 | if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { |
886 | begin_x = x; | 892 | begin_x = x; |
887 | continue; | 893 | continue; |
888 | } | 894 | } |
889 | if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { | 895 | if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { |
890 | end_x = x - 1; | 896 | end_x = x - 1; |
891 | for (y = be16_to_cpu(packet->x_len); | 897 | for (y = x_len; y < data_len; y++) { |
892 | y < be16_to_cpu(packet->data_len); y++) { | ||
893 | if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { | 898 | if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { |
894 | begin_y = y - be16_to_cpu(packet->x_len); | 899 | begin_y = y - x_len; |
895 | continue; | 900 | continue; |
896 | } | 901 | } |
897 | if (end_y == -1 && | 902 | if (end_y == -1 && |
898 | begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { | 903 | begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { |
899 | end_y = y - 1 - be16_to_cpu(packet->x_len); | 904 | end_y = y - 1 - x_len; |
900 | w = end_x - begin_x; | 905 | w = end_x - begin_x; |
901 | h = end_y - begin_y; | 906 | h = end_y - begin_y; |
902 | #if 0 | 907 | #if 0 |
@@ -1104,14 +1109,14 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
1104 | }, | 1109 | }, |
1105 | #endif | 1110 | #endif |
1106 | 1111 | ||
1107 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | 1112 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB |
1108 | [DEVTYPE_TC5UH] = { | 1113 | [DEVTYPE_TC45USB] = { |
1109 | .min_xc = 0x0, | 1114 | .min_xc = 0x0, |
1110 | .max_xc = 0x0fff, | 1115 | .max_xc = 0x0fff, |
1111 | .min_yc = 0x0, | 1116 | .min_yc = 0x0, |
1112 | .max_yc = 0x0fff, | 1117 | .max_yc = 0x0fff, |
1113 | .rept_size = 5, | 1118 | .rept_size = 5, |
1114 | .read_data = tc5uh_read_data, | 1119 | .read_data = tc45usb_read_data, |
1115 | }, | 1120 | }, |
1116 | #endif | 1121 | #endif |
1117 | 1122 | ||