diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-01 10:48:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-01 10:48:38 -0400 |
commit | 9f29333dae3488542b1344871e8ecb84084ad80e (patch) | |
tree | 01314a20b6155cfbb881a7a797ab003b64b5f434 /drivers/input | |
parent | 494b9aea6d451e1eaab5d52b65951d7dc6e81cb8 (diff) | |
parent | 8fdc19486f4d3b0fc5f1c7ce69fe5f7b1c653e62 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: make EVIOCGSND return meaningful data
Input: ressurect EVIOCGREP and EVIOCSREP
Input: psmouse - fix new device detection logic
Input: move input_device_id to mod_devicetable.h
Input: allow using several chords for braille
Input: allow passing NULL to input_free_device()
Input: spitzkbd - fix the reversed Address and Calender keys
Input: ads7846 - improve filtering for thumb press accuracy
Input: ads7846 - report 0 pressure value along with pen up event
Input: ads7846 - handle IRQs that were latched during disabled IRQs
Input: ads7846 - miscellaneous fixes
Input: ads7846 - use msleep() instead of udelay() in suspend
Input: ads7846 - debouncing and rudimentary sample filtering
Input: ads7846 - power down ADC a bit later
Input: ads7846 - add pen_down sysfs attribute
Input: wistron - add support for Fujitsu N3510
Input: wistron - add signature for Amilo M7400
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/evdev.c | 21 | ||||
-rw-r--r-- | drivers/input/input.c | 11 | ||||
-rw-r--r-- | drivers/input/keyboard/spitzkbd.c | 4 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 30 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 414 |
6 files changed, 398 insertions, 86 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index a34e3d91d9ed..ba325f16d077 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -403,6 +403,27 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
403 | case EVIOCGID: | 403 | case EVIOCGID: |
404 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) | 404 | if (copy_to_user(p, &dev->id, sizeof(struct input_id))) |
405 | return -EFAULT; | 405 | return -EFAULT; |
406 | return 0; | ||
407 | |||
408 | case EVIOCGREP: | ||
409 | if (!test_bit(EV_REP, dev->evbit)) | ||
410 | return -ENOSYS; | ||
411 | if (put_user(dev->rep[REP_DELAY], ip)) | ||
412 | return -EFAULT; | ||
413 | if (put_user(dev->rep[REP_PERIOD], ip + 1)) | ||
414 | return -EFAULT; | ||
415 | return 0; | ||
416 | |||
417 | case EVIOCSREP: | ||
418 | if (!test_bit(EV_REP, dev->evbit)) | ||
419 | return -ENOSYS; | ||
420 | if (get_user(u, ip)) | ||
421 | return -EFAULT; | ||
422 | if (get_user(v, ip + 1)) | ||
423 | return -EFAULT; | ||
424 | |||
425 | input_event(dev, EV_REP, REP_DELAY, u); | ||
426 | input_event(dev, EV_REP, REP_PERIOD, v); | ||
406 | 427 | ||
407 | return 0; | 428 | return 0; |
408 | 429 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index a935abeffffc..3038c268917d 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -155,6 +155,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in | |||
155 | if (code > SND_MAX || !test_bit(code, dev->sndbit)) | 155 | if (code > SND_MAX || !test_bit(code, dev->sndbit)) |
156 | return; | 156 | return; |
157 | 157 | ||
158 | if (!!test_bit(code, dev->snd) != !!value) | ||
159 | change_bit(code, dev->snd); | ||
160 | |||
158 | if (dev->event) dev->event(dev, type, code, value); | 161 | if (dev->event) dev->event(dev, type, code, value); |
159 | 162 | ||
160 | break; | 163 | break; |
@@ -286,19 +289,19 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st | |||
286 | for (; id->flags || id->driver_info; id++) { | 289 | for (; id->flags || id->driver_info; id++) { |
287 | 290 | ||
288 | if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) | 291 | if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) |
289 | if (id->id.bustype != dev->id.bustype) | 292 | if (id->bustype != dev->id.bustype) |
290 | continue; | 293 | continue; |
291 | 294 | ||
292 | if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) | 295 | if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) |
293 | if (id->id.vendor != dev->id.vendor) | 296 | if (id->vendor != dev->id.vendor) |
294 | continue; | 297 | continue; |
295 | 298 | ||
296 | if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) | 299 | if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) |
297 | if (id->id.product != dev->id.product) | 300 | if (id->product != dev->id.product) |
298 | continue; | 301 | continue; |
299 | 302 | ||
300 | if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) | 303 | if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) |
301 | if (id->id.version != dev->id.version) | 304 | if (id->version != dev->id.version) |
302 | continue; | 305 | continue; |
303 | 306 | ||
304 | MATCH_BIT(evbit, EV_MAX); | 307 | MATCH_BIT(evbit, EV_MAX); |
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index bc61cf8cfc65..1d238a9d52d6 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c | |||
@@ -53,8 +53,8 @@ static unsigned char spitzkbd_keycode[NR_SCANCODES] = { | |||
53 | KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ | 53 | KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ |
54 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ | 54 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ |
55 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | 55 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ |
56 | SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | 56 | SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ |
57 | SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ | 57 | SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ |
58 | SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ | 58 | SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ |
59 | KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ | 59 | KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ |
60 | }; | 60 | }; |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 4b415d9b0123..36cd2e07fce8 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -273,6 +273,18 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] = { | |||
273 | { KE_END, 0 } | 273 | { KE_END, 0 } |
274 | }; | 274 | }; |
275 | 275 | ||
276 | static struct key_entry keymap_fujitsu_n3510[] = { | ||
277 | { KE_KEY, 0x11, KEY_PROG1 }, | ||
278 | { KE_KEY, 0x12, KEY_PROG2 }, | ||
279 | { KE_KEY, 0x36, KEY_WWW }, | ||
280 | { KE_KEY, 0x31, KEY_MAIL }, | ||
281 | { KE_KEY, 0x71, KEY_STOPCD }, | ||
282 | { KE_KEY, 0x72, KEY_PLAYPAUSE }, | ||
283 | { KE_KEY, 0x74, KEY_REWIND }, | ||
284 | { KE_KEY, 0x78, KEY_FORWARD }, | ||
285 | { KE_END, 0 } | ||
286 | }; | ||
287 | |||
276 | static struct key_entry keymap_wistron_ms2141[] = { | 288 | static struct key_entry keymap_wistron_ms2141[] = { |
277 | { KE_KEY, 0x11, KEY_PROG1 }, | 289 | { KE_KEY, 0x11, KEY_PROG1 }, |
278 | { KE_KEY, 0x12, KEY_PROG2 }, | 290 | { KE_KEY, 0x12, KEY_PROG2 }, |
@@ -323,6 +335,24 @@ static struct dmi_system_id dmi_ids[] = { | |||
323 | }, | 335 | }, |
324 | { | 336 | { |
325 | .callback = dmi_matched, | 337 | .callback = dmi_matched, |
338 | .ident = "Fujitsu-Siemens Amilo M7400", | ||
339 | .matches = { | ||
340 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
341 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), | ||
342 | }, | ||
343 | .driver_data = keymap_fs_amilo_pro_v2000 | ||
344 | }, | ||
345 | { | ||
346 | .callback = dmi_matched, | ||
347 | .ident = "Fujitsu N3510", | ||
348 | .matches = { | ||
349 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | ||
350 | DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), | ||
351 | }, | ||
352 | .driver_data = keymap_fujitsu_n3510 | ||
353 | }, | ||
354 | { | ||
355 | .callback = dmi_matched, | ||
326 | .ident = "Acer Aspire 1500", | 356 | .ident = "Acer Aspire 1500", |
327 | .matches = { | 357 | .matches = { |
328 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 358 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 32d70ed8f41d..136321a2cfdb 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -302,8 +302,10 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
302 | * Check if this is a new device announcement (0xAA 0x00) | 302 | * Check if this is a new device announcement (0xAA 0x00) |
303 | */ | 303 | */ |
304 | if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { | 304 | if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { |
305 | if (psmouse->pktcnt == 1) | 305 | if (psmouse->pktcnt == 1) { |
306 | psmouse->last = jiffies; | ||
306 | goto out; | 307 | goto out; |
308 | } | ||
307 | 309 | ||
308 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { | 310 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { |
309 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 311 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 46d1fec2cfd8..1494175ac6fe 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -2,6 +2,8 @@ | |||
2 | * ADS7846 based touchscreen and sensor driver | 2 | * ADS7846 based touchscreen and sensor driver |
3 | * | 3 | * |
4 | * Copyright (c) 2005 David Brownell | 4 | * Copyright (c) 2005 David Brownell |
5 | * Copyright (c) 2006 Nokia Corporation | ||
6 | * Various changes: Imre Deak <imre.deak@nokia.com> | ||
5 | * | 7 | * |
6 | * Using code from: | 8 | * Using code from: |
7 | * - corgi_ts.c | 9 | * - corgi_ts.c |
@@ -34,17 +36,25 @@ | |||
34 | 36 | ||
35 | 37 | ||
36 | /* | 38 | /* |
37 | * This code has been lightly tested on an ads7846. | 39 | * This code has been tested on an ads7846 / N770 device. |
38 | * Support for ads7843 and ads7845 has only been stubbed in. | 40 | * Support for ads7843 and ads7845 has only been stubbed in. |
39 | * | 41 | * |
40 | * Not yet done: investigate the values reported. Are x/y/pressure | 42 | * Not yet done: How accurate are the temperature and voltage |
41 | * event values sane enough for X11? How accurate are the temperature | 43 | * readings? (System-specific calibration should support |
42 | * and voltage readings? (System-specific calibration should support | ||
43 | * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) | 44 | * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) |
44 | * | 45 | * |
46 | * IRQ handling needs a workaround because of a shortcoming in handling | ||
47 | * edge triggered IRQs on some platforms like the OMAP1/2. These | ||
48 | * platforms don't handle the ARM lazy IRQ disabling properly, thus we | ||
49 | * have to maintain our own SW IRQ disabled status. This should be | ||
50 | * removed as soon as the affected platform's IRQ handling is fixed. | ||
51 | * | ||
45 | * app note sbaa036 talks in more detail about accurate sampling... | 52 | * app note sbaa036 talks in more detail about accurate sampling... |
46 | * that ought to help in situations like LCDs inducing noise (which | 53 | * that ought to help in situations like LCDs inducing noise (which |
47 | * can also be helped by using synch signals) and more generally. | 54 | * can also be helped by using synch signals) and more generally. |
55 | * This driver tries to utilize the measures described in the app | ||
56 | * note. The strength of filtering can be set in the board-* specific | ||
57 | * files. | ||
48 | */ | 58 | */ |
49 | 59 | ||
50 | #define TS_POLL_PERIOD msecs_to_jiffies(10) | 60 | #define TS_POLL_PERIOD msecs_to_jiffies(10) |
@@ -61,6 +71,7 @@ struct ts_event { | |||
61 | __be16 x; | 71 | __be16 x; |
62 | __be16 y; | 72 | __be16 y; |
63 | __be16 z1, z2; | 73 | __be16 z1, z2; |
74 | int ignore; | ||
64 | }; | 75 | }; |
65 | 76 | ||
66 | struct ads7846 { | 77 | struct ads7846 { |
@@ -71,12 +82,23 @@ struct ads7846 { | |||
71 | u16 model; | 82 | u16 model; |
72 | u16 vref_delay_usecs; | 83 | u16 vref_delay_usecs; |
73 | u16 x_plate_ohms; | 84 | u16 x_plate_ohms; |
85 | u16 pressure_max; | ||
74 | 86 | ||
75 | u8 read_x, read_y, read_z1, read_z2; | 87 | u8 read_x, read_y, read_z1, read_z2, pwrdown; |
88 | u16 dummy; /* for the pwrdown read */ | ||
76 | struct ts_event tc; | 89 | struct ts_event tc; |
77 | 90 | ||
78 | struct spi_transfer xfer[8]; | 91 | struct spi_transfer xfer[10]; |
79 | struct spi_message msg; | 92 | struct spi_message msg[5]; |
93 | struct spi_message *last_msg; | ||
94 | int msg_idx; | ||
95 | int read_cnt; | ||
96 | int read_rep; | ||
97 | int last_read; | ||
98 | |||
99 | u16 debounce_max; | ||
100 | u16 debounce_tol; | ||
101 | u16 debounce_rep; | ||
80 | 102 | ||
81 | spinlock_t lock; | 103 | spinlock_t lock; |
82 | struct timer_list timer; /* P: lock */ | 104 | struct timer_list timer; /* P: lock */ |
@@ -84,6 +106,9 @@ struct ads7846 { | |||
84 | unsigned pending:1; /* P: lock */ | 106 | unsigned pending:1; /* P: lock */ |
85 | // FIXME remove "irq_disabled" | 107 | // FIXME remove "irq_disabled" |
86 | unsigned irq_disabled:1; /* P: lock */ | 108 | unsigned irq_disabled:1; /* P: lock */ |
109 | unsigned disabled:1; | ||
110 | |||
111 | int (*get_pendown_state)(void); | ||
87 | }; | 112 | }; |
88 | 113 | ||
89 | /* leave chip selected when we're done, for quicker re-select? */ | 114 | /* leave chip selected when we're done, for quicker re-select? */ |
@@ -125,7 +150,9 @@ struct ads7846 { | |||
125 | #define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) | 150 | #define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) |
126 | #define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) | 151 | #define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) |
127 | #define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) | 152 | #define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) |
128 | #define READ_X (READ_12BIT_DFR(x) | ADS_PD10_PDOWN) /* LAST */ | 153 | |
154 | #define READ_X (READ_12BIT_DFR(x) | ADS_PD10_ADC_ON) | ||
155 | #define PWRDOWN (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /* LAST */ | ||
129 | 156 | ||
130 | /* single-ended samples need to first power up reference voltage; | 157 | /* single-ended samples need to first power up reference voltage; |
131 | * we leave both ADC and VREF powered | 158 | * we leave both ADC and VREF powered |
@@ -152,6 +179,15 @@ struct ser_req { | |||
152 | struct spi_transfer xfer[6]; | 179 | struct spi_transfer xfer[6]; |
153 | }; | 180 | }; |
154 | 181 | ||
182 | static void ads7846_enable(struct ads7846 *ts); | ||
183 | static void ads7846_disable(struct ads7846 *ts); | ||
184 | |||
185 | static int device_suspended(struct device *dev) | ||
186 | { | ||
187 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
188 | return dev->power.power_state.event != PM_EVENT_ON || ts->disabled; | ||
189 | } | ||
190 | |||
155 | static int ads7846_read12_ser(struct device *dev, unsigned command) | 191 | static int ads7846_read12_ser(struct device *dev, unsigned command) |
156 | { | 192 | { |
157 | struct spi_device *spi = to_spi_device(dev); | 193 | struct spi_device *spi = to_spi_device(dev); |
@@ -164,7 +200,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) | |||
164 | if (!req) | 200 | if (!req) |
165 | return -ENOMEM; | 201 | return -ENOMEM; |
166 | 202 | ||
167 | INIT_LIST_HEAD(&req->msg.transfers); | 203 | spi_message_init(&req->msg); |
168 | 204 | ||
169 | /* activate reference, so it has time to settle; */ | 205 | /* activate reference, so it has time to settle; */ |
170 | req->ref_on = REF_ON; | 206 | req->ref_on = REF_ON; |
@@ -204,8 +240,10 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) | |||
204 | for (i = 0; i < 6; i++) | 240 | for (i = 0; i < 6; i++) |
205 | spi_message_add_tail(&req->xfer[i], &req->msg); | 241 | spi_message_add_tail(&req->xfer[i], &req->msg); |
206 | 242 | ||
243 | ts->irq_disabled = 1; | ||
207 | disable_irq(spi->irq); | 244 | disable_irq(spi->irq); |
208 | status = spi_sync(spi, &req->msg); | 245 | status = spi_sync(spi, &req->msg); |
246 | ts->irq_disabled = 0; | ||
209 | enable_irq(spi->irq); | 247 | enable_irq(spi->irq); |
210 | 248 | ||
211 | if (req->msg.status) | 249 | if (req->msg.status) |
@@ -233,6 +271,52 @@ SHOW(temp1) | |||
233 | SHOW(vaux) | 271 | SHOW(vaux) |
234 | SHOW(vbatt) | 272 | SHOW(vbatt) |
235 | 273 | ||
274 | static int is_pen_down(struct device *dev) | ||
275 | { | ||
276 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
277 | |||
278 | return ts->pendown; | ||
279 | } | ||
280 | |||
281 | static ssize_t ads7846_pen_down_show(struct device *dev, | ||
282 | struct device_attribute *attr, char *buf) | ||
283 | { | ||
284 | return sprintf(buf, "%u\n", is_pen_down(dev)); | ||
285 | } | ||
286 | |||
287 | static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); | ||
288 | |||
289 | static ssize_t ads7846_disable_show(struct device *dev, | ||
290 | struct device_attribute *attr, char *buf) | ||
291 | { | ||
292 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
293 | |||
294 | return sprintf(buf, "%u\n", ts->disabled); | ||
295 | } | ||
296 | |||
297 | static ssize_t ads7846_disable_store(struct device *dev, | ||
298 | struct device_attribute *attr, | ||
299 | const char *buf, size_t count) | ||
300 | { | ||
301 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
302 | char *endp; | ||
303 | int i; | ||
304 | |||
305 | i = simple_strtoul(buf, &endp, 10); | ||
306 | spin_lock_irq(&ts->lock); | ||
307 | |||
308 | if (i) | ||
309 | ads7846_disable(ts); | ||
310 | else | ||
311 | ads7846_enable(ts); | ||
312 | |||
313 | spin_unlock_irq(&ts->lock); | ||
314 | |||
315 | return count; | ||
316 | } | ||
317 | |||
318 | static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); | ||
319 | |||
236 | /*--------------------------------------------------------------------------*/ | 320 | /*--------------------------------------------------------------------------*/ |
237 | 321 | ||
238 | /* | 322 | /* |
@@ -264,7 +348,7 @@ static void ads7846_rx(void *ads) | |||
264 | if (x == MAX_12BIT) | 348 | if (x == MAX_12BIT) |
265 | x = 0; | 349 | x = 0; |
266 | 350 | ||
267 | if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { | 351 | if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { |
268 | /* compute touch pressure resistance using equation #2 */ | 352 | /* compute touch pressure resistance using equation #2 */ |
269 | Rt = z2; | 353 | Rt = z2; |
270 | Rt -= z1; | 354 | Rt -= z1; |
@@ -275,6 +359,14 @@ static void ads7846_rx(void *ads) | |||
275 | } else | 359 | } else |
276 | Rt = 0; | 360 | Rt = 0; |
277 | 361 | ||
362 | /* Sample found inconsistent by debouncing or pressure is beyond | ||
363 | * the maximum. Don't report it to user space, repeat at least | ||
364 | * once more the measurement */ | ||
365 | if (ts->tc.ignore || Rt > ts->pressure_max) { | ||
366 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); | ||
367 | return; | ||
368 | } | ||
369 | |||
278 | /* NOTE: "pendown" is inferred from pressure; we don't rely on | 370 | /* NOTE: "pendown" is inferred from pressure; we don't rely on |
279 | * being able to check nPENIRQ status, or "friendly" trigger modes | 371 | * being able to check nPENIRQ status, or "friendly" trigger modes |
280 | * (both-edges is much better than just-falling or low-level). | 372 | * (both-edges is much better than just-falling or low-level). |
@@ -296,11 +388,13 @@ static void ads7846_rx(void *ads) | |||
296 | if (Rt) { | 388 | if (Rt) { |
297 | input_report_abs(input_dev, ABS_X, x); | 389 | input_report_abs(input_dev, ABS_X, x); |
298 | input_report_abs(input_dev, ABS_Y, y); | 390 | input_report_abs(input_dev, ABS_Y, y); |
299 | input_report_abs(input_dev, ABS_PRESSURE, Rt); | ||
300 | sync = 1; | 391 | sync = 1; |
301 | } | 392 | } |
302 | if (sync) | 393 | |
394 | if (sync) { | ||
395 | input_report_abs(input_dev, ABS_PRESSURE, Rt); | ||
303 | input_sync(input_dev); | 396 | input_sync(input_dev); |
397 | } | ||
304 | 398 | ||
305 | #ifdef VERBOSE | 399 | #ifdef VERBOSE |
306 | if (Rt || ts->pendown) | 400 | if (Rt || ts->pendown) |
@@ -308,80 +402,138 @@ static void ads7846_rx(void *ads) | |||
308 | x, y, Rt, Rt ? "" : " UP"); | 402 | x, y, Rt, Rt ? "" : " UP"); |
309 | #endif | 403 | #endif |
310 | 404 | ||
311 | /* don't retrigger while we're suspended */ | ||
312 | spin_lock_irqsave(&ts->lock, flags); | 405 | spin_lock_irqsave(&ts->lock, flags); |
313 | 406 | ||
314 | ts->pendown = (Rt != 0); | 407 | ts->pendown = (Rt != 0); |
315 | ts->pending = 0; | 408 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); |
316 | 409 | ||
317 | if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { | 410 | spin_unlock_irqrestore(&ts->lock, flags); |
318 | if (ts->pendown) | 411 | } |
319 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); | 412 | |
320 | else if (ts->irq_disabled) { | 413 | static void ads7846_debounce(void *ads) |
321 | ts->irq_disabled = 0; | 414 | { |
322 | enable_irq(ts->spi->irq); | 415 | struct ads7846 *ts = ads; |
416 | struct spi_message *m; | ||
417 | struct spi_transfer *t; | ||
418 | int val; | ||
419 | int status; | ||
420 | |||
421 | m = &ts->msg[ts->msg_idx]; | ||
422 | t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); | ||
423 | val = (*(u16 *)t->rx_buf) >> 3; | ||
424 | if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) { | ||
425 | /* Repeat it, if this was the first read or the read | ||
426 | * wasn't consistent enough. */ | ||
427 | if (ts->read_cnt < ts->debounce_max) { | ||
428 | ts->last_read = val; | ||
429 | ts->read_cnt++; | ||
430 | } else { | ||
431 | /* Maximum number of debouncing reached and still | ||
432 | * not enough number of consistent readings. Abort | ||
433 | * the whole sample, repeat it in the next sampling | ||
434 | * period. | ||
435 | */ | ||
436 | ts->tc.ignore = 1; | ||
437 | ts->read_cnt = 0; | ||
438 | /* Last message will contain ads7846_rx() as the | ||
439 | * completion function. | ||
440 | */ | ||
441 | m = ts->last_msg; | ||
323 | } | 442 | } |
443 | /* Start over collecting consistent readings. */ | ||
444 | ts->read_rep = 0; | ||
445 | } else { | ||
446 | if (++ts->read_rep > ts->debounce_rep) { | ||
447 | /* Got a good reading for this coordinate, | ||
448 | * go for the next one. */ | ||
449 | ts->tc.ignore = 0; | ||
450 | ts->msg_idx++; | ||
451 | ts->read_cnt = 0; | ||
452 | ts->read_rep = 0; | ||
453 | m++; | ||
454 | } else | ||
455 | /* Read more values that are consistent. */ | ||
456 | ts->read_cnt++; | ||
324 | } | 457 | } |
325 | 458 | status = spi_async(ts->spi, m); | |
326 | spin_unlock_irqrestore(&ts->lock, flags); | 459 | if (status) |
460 | dev_err(&ts->spi->dev, "spi_async --> %d\n", | ||
461 | status); | ||
327 | } | 462 | } |
328 | 463 | ||
329 | static void ads7846_timer(unsigned long handle) | 464 | static void ads7846_timer(unsigned long handle) |
330 | { | 465 | { |
331 | struct ads7846 *ts = (void *)handle; | 466 | struct ads7846 *ts = (void *)handle; |
332 | int status = 0; | 467 | int status = 0; |
333 | unsigned long flags; | 468 | |
469 | spin_lock_irq(&ts->lock); | ||
470 | |||
471 | if (unlikely(ts->msg_idx && !ts->pendown)) { | ||
472 | /* measurment cycle ended */ | ||
473 | if (!device_suspended(&ts->spi->dev)) { | ||
474 | ts->irq_disabled = 0; | ||
475 | enable_irq(ts->spi->irq); | ||
476 | } | ||
477 | ts->pending = 0; | ||
478 | ts->msg_idx = 0; | ||
479 | } else { | ||
480 | /* pen is still down, continue with the measurement */ | ||
481 | ts->msg_idx = 0; | ||
482 | status = spi_async(ts->spi, &ts->msg[0]); | ||
483 | if (status) | ||
484 | dev_err(&ts->spi->dev, "spi_async --> %d\n", status); | ||
485 | } | ||
486 | |||
487 | spin_unlock_irq(&ts->lock); | ||
488 | } | ||
489 | |||
490 | static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) | ||
491 | { | ||
492 | struct ads7846 *ts = handle; | ||
493 | unsigned long flags; | ||
334 | 494 | ||
335 | spin_lock_irqsave(&ts->lock, flags); | 495 | spin_lock_irqsave(&ts->lock, flags); |
336 | if (!ts->pending) { | 496 | if (likely(ts->get_pendown_state())) { |
337 | ts->pending = 1; | ||
338 | if (!ts->irq_disabled) { | 497 | if (!ts->irq_disabled) { |
498 | /* REVISIT irq logic for many ARM chips has cloned a | ||
499 | * bug wherein disabling an irq in its handler won't | ||
500 | * work;(it's disabled lazily, and too late to work. | ||
501 | * until all their irq logic is fixed, we must shadow | ||
502 | * that state here. | ||
503 | */ | ||
339 | ts->irq_disabled = 1; | 504 | ts->irq_disabled = 1; |
340 | disable_irq(ts->spi->irq); | 505 | disable_irq(ts->spi->irq); |
506 | ts->pending = 1; | ||
507 | mod_timer(&ts->timer, jiffies); | ||
341 | } | 508 | } |
342 | status = spi_async(ts->spi, &ts->msg); | ||
343 | if (status) | ||
344 | dev_err(&ts->spi->dev, "spi_async --> %d\n", | ||
345 | status); | ||
346 | } | 509 | } |
347 | spin_unlock_irqrestore(&ts->lock, flags); | 510 | spin_unlock_irqrestore(&ts->lock, flags); |
348 | } | ||
349 | 511 | ||
350 | static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) | ||
351 | { | ||
352 | ads7846_timer((unsigned long) handle); | ||
353 | return IRQ_HANDLED; | 512 | return IRQ_HANDLED; |
354 | } | 513 | } |
355 | 514 | ||
356 | /*--------------------------------------------------------------------------*/ | 515 | /*--------------------------------------------------------------------------*/ |
357 | 516 | ||
358 | static int | 517 | /* Must be called with ts->lock held */ |
359 | ads7846_suspend(struct spi_device *spi, pm_message_t message) | 518 | static void ads7846_disable(struct ads7846 *ts) |
360 | { | 519 | { |
361 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 520 | if (ts->disabled) |
362 | unsigned long flags; | 521 | return; |
363 | 522 | ||
364 | spin_lock_irqsave(&ts->lock, flags); | 523 | ts->disabled = 1; |
365 | |||
366 | spi->dev.power.power_state = message; | ||
367 | 524 | ||
368 | /* are we waiting for IRQ, or polling? */ | 525 | /* are we waiting for IRQ, or polling? */ |
369 | if (!ts->pendown) { | 526 | if (!ts->pending) { |
370 | if (!ts->irq_disabled) { | 527 | ts->irq_disabled = 1; |
371 | ts->irq_disabled = 1; | 528 | disable_irq(ts->spi->irq); |
372 | disable_irq(ts->spi->irq); | ||
373 | } | ||
374 | } else { | 529 | } else { |
375 | /* polling; force a final SPI completion; | 530 | /* the timer will run at least once more, and |
376 | * that will clean things up neatly | 531 | * leave everything in a clean state, IRQ disabled |
377 | */ | 532 | */ |
378 | if (!ts->pending) | 533 | while (ts->pending) { |
379 | mod_timer(&ts->timer, jiffies); | 534 | spin_unlock_irq(&ts->lock); |
380 | 535 | msleep(1); | |
381 | while (ts->pendown || ts->pending) { | 536 | spin_lock_irq(&ts->lock); |
382 | spin_unlock_irqrestore(&ts->lock, flags); | ||
383 | udelay(10); | ||
384 | spin_lock_irqsave(&ts->lock, flags); | ||
385 | } | 537 | } |
386 | } | 538 | } |
387 | 539 | ||
@@ -389,17 +541,45 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message) | |||
389 | * leave it that way after every request | 541 | * leave it that way after every request |
390 | */ | 542 | */ |
391 | 543 | ||
392 | spin_unlock_irqrestore(&ts->lock, flags); | 544 | } |
545 | |||
546 | /* Must be called with ts->lock held */ | ||
547 | static void ads7846_enable(struct ads7846 *ts) | ||
548 | { | ||
549 | if (!ts->disabled) | ||
550 | return; | ||
551 | |||
552 | ts->disabled = 0; | ||
553 | ts->irq_disabled = 0; | ||
554 | enable_irq(ts->spi->irq); | ||
555 | } | ||
556 | |||
557 | static int ads7846_suspend(struct spi_device *spi, pm_message_t message) | ||
558 | { | ||
559 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | ||
560 | |||
561 | spin_lock_irq(&ts->lock); | ||
562 | |||
563 | spi->dev.power.power_state = message; | ||
564 | ads7846_disable(ts); | ||
565 | |||
566 | spin_unlock_irq(&ts->lock); | ||
567 | |||
393 | return 0; | 568 | return 0; |
569 | |||
394 | } | 570 | } |
395 | 571 | ||
396 | static int ads7846_resume(struct spi_device *spi) | 572 | static int ads7846_resume(struct spi_device *spi) |
397 | { | 573 | { |
398 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 574 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
399 | 575 | ||
400 | ts->irq_disabled = 0; | 576 | spin_lock_irq(&ts->lock); |
401 | enable_irq(ts->spi->irq); | 577 | |
402 | spi->dev.power.power_state = PMSG_ON; | 578 | spi->dev.power.power_state = PMSG_ON; |
579 | ads7846_enable(ts); | ||
580 | |||
581 | spin_unlock_irq(&ts->lock); | ||
582 | |||
403 | return 0; | 583 | return 0; |
404 | } | 584 | } |
405 | 585 | ||
@@ -408,6 +588,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
408 | struct ads7846 *ts; | 588 | struct ads7846 *ts; |
409 | struct input_dev *input_dev; | 589 | struct input_dev *input_dev; |
410 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | 590 | struct ads7846_platform_data *pdata = spi->dev.platform_data; |
591 | struct spi_message *m; | ||
411 | struct spi_transfer *x; | 592 | struct spi_transfer *x; |
412 | int err; | 593 | int err; |
413 | 594 | ||
@@ -428,6 +609,11 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
428 | return -EINVAL; | 609 | return -EINVAL; |
429 | } | 610 | } |
430 | 611 | ||
612 | if (pdata->get_pendown_state == NULL) { | ||
613 | dev_dbg(&spi->dev, "no get_pendown_state function?\n"); | ||
614 | return -EINVAL; | ||
615 | } | ||
616 | |||
431 | /* We'd set the wordsize to 12 bits ... except that some controllers | 617 | /* We'd set the wordsize to 12 bits ... except that some controllers |
432 | * will then treat the 8 bit command words as 12 bits (and drop the | 618 | * will then treat the 8 bit command words as 12 bits (and drop the |
433 | * four MSBs of the 12 bit result). Result: inputs must be shifted | 619 | * four MSBs of the 12 bit result). Result: inputs must be shifted |
@@ -451,9 +637,21 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
451 | ts->timer.data = (unsigned long) ts; | 637 | ts->timer.data = (unsigned long) ts; |
452 | ts->timer.function = ads7846_timer; | 638 | ts->timer.function = ads7846_timer; |
453 | 639 | ||
640 | spin_lock_init(&ts->lock); | ||
641 | |||
454 | ts->model = pdata->model ? : 7846; | 642 | ts->model = pdata->model ? : 7846; |
455 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; | 643 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; |
456 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | 644 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; |
645 | ts->pressure_max = pdata->pressure_max ? : ~0; | ||
646 | if (pdata->debounce_max) { | ||
647 | ts->debounce_max = pdata->debounce_max; | ||
648 | ts->debounce_tol = pdata->debounce_tol; | ||
649 | ts->debounce_rep = pdata->debounce_rep; | ||
650 | if (ts->debounce_rep > ts->debounce_max + 1) | ||
651 | ts->debounce_rep = ts->debounce_max - 1; | ||
652 | } else | ||
653 | ts->debounce_tol = ~0; | ||
654 | ts->get_pendown_state = pdata->get_pendown_state; | ||
457 | 655 | ||
458 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); | 656 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); |
459 | 657 | ||
@@ -477,60 +675,100 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
477 | /* set up the transfers to read touchscreen state; this assumes we | 675 | /* set up the transfers to read touchscreen state; this assumes we |
478 | * use formula #2 for pressure, not #3. | 676 | * use formula #2 for pressure, not #3. |
479 | */ | 677 | */ |
480 | INIT_LIST_HEAD(&ts->msg.transfers); | 678 | m = &ts->msg[0]; |
481 | x = ts->xfer; | 679 | x = ts->xfer; |
482 | 680 | ||
681 | spi_message_init(m); | ||
682 | |||
483 | /* y- still on; turn on only y+ (and ADC) */ | 683 | /* y- still on; turn on only y+ (and ADC) */ |
484 | ts->read_y = READ_Y; | 684 | ts->read_y = READ_Y; |
485 | x->tx_buf = &ts->read_y; | 685 | x->tx_buf = &ts->read_y; |
486 | x->len = 1; | 686 | x->len = 1; |
487 | spi_message_add_tail(x, &ts->msg); | 687 | spi_message_add_tail(x, m); |
488 | 688 | ||
489 | x++; | 689 | x++; |
490 | x->rx_buf = &ts->tc.y; | 690 | x->rx_buf = &ts->tc.y; |
491 | x->len = 2; | 691 | x->len = 2; |
492 | spi_message_add_tail(x, &ts->msg); | 692 | spi_message_add_tail(x, m); |
693 | |||
694 | m->complete = ads7846_debounce; | ||
695 | m->context = ts; | ||
696 | |||
697 | m++; | ||
698 | spi_message_init(m); | ||
699 | |||
700 | /* turn y- off, x+ on, then leave in lowpower */ | ||
701 | x++; | ||
702 | ts->read_x = READ_X; | ||
703 | x->tx_buf = &ts->read_x; | ||
704 | x->len = 1; | ||
705 | spi_message_add_tail(x, m); | ||
706 | |||
707 | x++; | ||
708 | x->rx_buf = &ts->tc.x; | ||
709 | x->len = 2; | ||
710 | spi_message_add_tail(x, m); | ||
711 | |||
712 | m->complete = ads7846_debounce; | ||
713 | m->context = ts; | ||
493 | 714 | ||
494 | /* turn y+ off, x- on; we'll use formula #2 */ | 715 | /* turn y+ off, x- on; we'll use formula #2 */ |
495 | if (ts->model == 7846) { | 716 | if (ts->model == 7846) { |
717 | m++; | ||
718 | spi_message_init(m); | ||
719 | |||
496 | x++; | 720 | x++; |
497 | ts->read_z1 = READ_Z1; | 721 | ts->read_z1 = READ_Z1; |
498 | x->tx_buf = &ts->read_z1; | 722 | x->tx_buf = &ts->read_z1; |
499 | x->len = 1; | 723 | x->len = 1; |
500 | spi_message_add_tail(x, &ts->msg); | 724 | spi_message_add_tail(x, m); |
501 | 725 | ||
502 | x++; | 726 | x++; |
503 | x->rx_buf = &ts->tc.z1; | 727 | x->rx_buf = &ts->tc.z1; |
504 | x->len = 2; | 728 | x->len = 2; |
505 | spi_message_add_tail(x, &ts->msg); | 729 | spi_message_add_tail(x, m); |
730 | |||
731 | m->complete = ads7846_debounce; | ||
732 | m->context = ts; | ||
733 | |||
734 | m++; | ||
735 | spi_message_init(m); | ||
506 | 736 | ||
507 | x++; | 737 | x++; |
508 | ts->read_z2 = READ_Z2; | 738 | ts->read_z2 = READ_Z2; |
509 | x->tx_buf = &ts->read_z2; | 739 | x->tx_buf = &ts->read_z2; |
510 | x->len = 1; | 740 | x->len = 1; |
511 | spi_message_add_tail(x, &ts->msg); | 741 | spi_message_add_tail(x, m); |
512 | 742 | ||
513 | x++; | 743 | x++; |
514 | x->rx_buf = &ts->tc.z2; | 744 | x->rx_buf = &ts->tc.z2; |
515 | x->len = 2; | 745 | x->len = 2; |
516 | spi_message_add_tail(x, &ts->msg); | 746 | spi_message_add_tail(x, m); |
747 | |||
748 | m->complete = ads7846_debounce; | ||
749 | m->context = ts; | ||
517 | } | 750 | } |
518 | 751 | ||
519 | /* turn y- off, x+ on, then leave in lowpower */ | 752 | /* power down */ |
753 | m++; | ||
754 | spi_message_init(m); | ||
755 | |||
520 | x++; | 756 | x++; |
521 | ts->read_x = READ_X; | 757 | ts->pwrdown = PWRDOWN; |
522 | x->tx_buf = &ts->read_x; | 758 | x->tx_buf = &ts->pwrdown; |
523 | x->len = 1; | 759 | x->len = 1; |
524 | spi_message_add_tail(x, &ts->msg); | 760 | spi_message_add_tail(x, m); |
525 | 761 | ||
526 | x++; | 762 | x++; |
527 | x->rx_buf = &ts->tc.x; | 763 | x->rx_buf = &ts->dummy; |
528 | x->len = 2; | 764 | x->len = 2; |
529 | CS_CHANGE(*x); | 765 | CS_CHANGE(*x); |
530 | spi_message_add_tail(x, &ts->msg); | 766 | spi_message_add_tail(x, m); |
531 | 767 | ||
532 | ts->msg.complete = ads7846_rx; | 768 | m->complete = ads7846_rx; |
533 | ts->msg.context = ts; | 769 | m->context = ts; |
770 | |||
771 | ts->last_msg = m; | ||
534 | 772 | ||
535 | if (request_irq(spi->irq, ads7846_irq, | 773 | if (request_irq(spi->irq, ads7846_irq, |
536 | SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, | 774 | SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, |
@@ -559,13 +797,27 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
559 | device_create_file(&spi->dev, &dev_attr_vbatt); | 797 | device_create_file(&spi->dev, &dev_attr_vbatt); |
560 | device_create_file(&spi->dev, &dev_attr_vaux); | 798 | device_create_file(&spi->dev, &dev_attr_vaux); |
561 | 799 | ||
800 | device_create_file(&spi->dev, &dev_attr_pen_down); | ||
801 | |||
802 | device_create_file(&spi->dev, &dev_attr_disable); | ||
803 | |||
562 | err = input_register_device(input_dev); | 804 | err = input_register_device(input_dev); |
563 | if (err) | 805 | if (err) |
564 | goto err_free_irq; | 806 | goto err_remove_attr; |
565 | 807 | ||
566 | return 0; | 808 | return 0; |
567 | 809 | ||
568 | err_free_irq: | 810 | err_remove_attr: |
811 | device_remove_file(&spi->dev, &dev_attr_disable); | ||
812 | device_remove_file(&spi->dev, &dev_attr_pen_down); | ||
813 | if (ts->model == 7846) { | ||
814 | device_remove_file(&spi->dev, &dev_attr_temp1); | ||
815 | device_remove_file(&spi->dev, &dev_attr_temp0); | ||
816 | } | ||
817 | if (ts->model != 7845) | ||
818 | device_remove_file(&spi->dev, &dev_attr_vbatt); | ||
819 | device_remove_file(&spi->dev, &dev_attr_vaux); | ||
820 | |||
569 | free_irq(spi->irq, ts); | 821 | free_irq(spi->irq, ts); |
570 | err_free_mem: | 822 | err_free_mem: |
571 | input_free_device(input_dev); | 823 | input_free_device(input_dev); |
@@ -577,20 +829,24 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
577 | { | 829 | { |
578 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 830 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
579 | 831 | ||
832 | input_unregister_device(ts->input); | ||
833 | |||
580 | ads7846_suspend(spi, PMSG_SUSPEND); | 834 | ads7846_suspend(spi, PMSG_SUSPEND); |
581 | free_irq(ts->spi->irq, ts); | ||
582 | if (ts->irq_disabled) | ||
583 | enable_irq(ts->spi->irq); | ||
584 | 835 | ||
836 | device_remove_file(&spi->dev, &dev_attr_disable); | ||
837 | device_remove_file(&spi->dev, &dev_attr_pen_down); | ||
585 | if (ts->model == 7846) { | 838 | if (ts->model == 7846) { |
586 | device_remove_file(&spi->dev, &dev_attr_temp0); | ||
587 | device_remove_file(&spi->dev, &dev_attr_temp1); | 839 | device_remove_file(&spi->dev, &dev_attr_temp1); |
840 | device_remove_file(&spi->dev, &dev_attr_temp0); | ||
588 | } | 841 | } |
589 | if (ts->model != 7845) | 842 | if (ts->model != 7845) |
590 | device_remove_file(&spi->dev, &dev_attr_vbatt); | 843 | device_remove_file(&spi->dev, &dev_attr_vbatt); |
591 | device_remove_file(&spi->dev, &dev_attr_vaux); | 844 | device_remove_file(&spi->dev, &dev_attr_vaux); |
592 | 845 | ||
593 | input_unregister_device(ts->input); | 846 | free_irq(ts->spi->irq, ts); |
847 | /* suspend left the IRQ disabled */ | ||
848 | enable_irq(ts->spi->irq); | ||
849 | |||
594 | kfree(ts); | 850 | kfree(ts); |
595 | 851 | ||
596 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | 852 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); |