diff options
Diffstat (limited to 'drivers')
43 files changed, 2618 insertions, 1068 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 456594bd97bc..0b111e8e444f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -922,7 +922,7 @@ static int platform_pm_restore_noirq(struct device *dev) | |||
922 | 922 | ||
923 | #endif /* !CONFIG_HIBERNATION */ | 923 | #endif /* !CONFIG_HIBERNATION */ |
924 | 924 | ||
925 | static struct dev_pm_ops platform_dev_pm_ops = { | 925 | static const struct dev_pm_ops platform_dev_pm_ops = { |
926 | .prepare = platform_pm_prepare, | 926 | .prepare = platform_pm_prepare, |
927 | .complete = platform_pm_complete, | 927 | .complete = platform_pm_complete, |
928 | .suspend = platform_pm_suspend, | 928 | .suspend = platform_pm_suspend, |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 58a3e572f2c9..1b1a786b7dec 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -157,8 +157,9 @@ void device_pm_move_last(struct device *dev) | |||
157 | * @ops: PM operations to choose from. | 157 | * @ops: PM operations to choose from. |
158 | * @state: PM transition of the system being carried out. | 158 | * @state: PM transition of the system being carried out. |
159 | */ | 159 | */ |
160 | static int pm_op(struct device *dev, struct dev_pm_ops *ops, | 160 | static int pm_op(struct device *dev, |
161 | pm_message_t state) | 161 | const struct dev_pm_ops *ops, |
162 | pm_message_t state) | ||
162 | { | 163 | { |
163 | int error = 0; | 164 | int error = 0; |
164 | 165 | ||
@@ -220,7 +221,8 @@ static int pm_op(struct device *dev, struct dev_pm_ops *ops, | |||
220 | * The operation is executed with interrupts disabled by the only remaining | 221 | * The operation is executed with interrupts disabled by the only remaining |
221 | * functional CPU in the system. | 222 | * functional CPU in the system. |
222 | */ | 223 | */ |
223 | static int pm_noirq_op(struct device *dev, struct dev_pm_ops *ops, | 224 | static int pm_noirq_op(struct device *dev, |
225 | const struct dev_pm_ops *ops, | ||
224 | pm_message_t state) | 226 | pm_message_t state) |
225 | { | 227 | { |
226 | int error = 0; | 228 | int error = 0; |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index f155ad8cdae7..2388cf578a62 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -144,6 +144,7 @@ static const struct xpad_device { | |||
144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
146 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 146 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
147 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | ||
147 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 148 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
148 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } | 149 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } |
149 | }; | 150 | }; |
@@ -208,6 +209,7 @@ static struct usb_device_id xpad_table [] = { | |||
208 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ | 209 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ |
209 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ | 210 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ |
210 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ | 211 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ |
212 | XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */ | ||
211 | { } | 213 | { } |
212 | }; | 214 | }; |
213 | 215 | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a6b989a9dc07..50e407de8a78 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -187,7 +187,7 @@ config KEYBOARD_HIL_OLD | |||
187 | submenu. | 187 | submenu. |
188 | 188 | ||
189 | config KEYBOARD_HIL | 189 | config KEYBOARD_HIL |
190 | tristate "HP HIL keyboard support" | 190 | tristate "HP HIL keyboard/pointer support" |
191 | depends on GSC || HP300 | 191 | depends on GSC || HP300 |
192 | default y | 192 | default y |
193 | select HP_SDC | 193 | select HP_SDC |
@@ -196,7 +196,8 @@ config KEYBOARD_HIL | |||
196 | help | 196 | help |
197 | The "Human Interface Loop" is a older, 8-channel USB-like | 197 | The "Human Interface Loop" is a older, 8-channel USB-like |
198 | controller used in several Hewlett Packard models. | 198 | controller used in several Hewlett Packard models. |
199 | This driver implements support for HIL-keyboards attached | 199 | This driver implements support for HIL-keyboards and pointing |
200 | devices (mice, tablets, touchscreens) attached | ||
200 | to your machine, so normally you should say Y here. | 201 | to your machine, so normally you should say Y here. |
201 | 202 | ||
202 | config KEYBOARD_HP6XX | 203 | config KEYBOARD_HP6XX |
@@ -361,4 +362,14 @@ config KEYBOARD_XTKBD | |||
361 | To compile this driver as a module, choose M here: the | 362 | To compile this driver as a module, choose M here: the |
362 | module will be called xtkbd. | 363 | module will be called xtkbd. |
363 | 364 | ||
365 | config KEYBOARD_W90P910 | ||
366 | tristate "W90P910 Matrix Keypad support" | ||
367 | depends on ARCH_W90X900 | ||
368 | help | ||
369 | Say Y here to enable the matrix keypad on evaluation board | ||
370 | based on W90P910. | ||
371 | |||
372 | To compile this driver as a module, choose M here: the | ||
373 | module will be called w90p910_keypad. | ||
374 | |||
364 | endif | 375 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index b5b5eae9724f..152303029203 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -31,3 +31,4 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | |||
31 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 31 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
32 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | 32 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o |
33 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 33 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
34 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | ||
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index d427f322e207..fe376a27fe57 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -184,14 +184,13 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
184 | int i, error; | 184 | int i, error; |
185 | 185 | ||
186 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | 186 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { |
187 | printk(KERN_ERR DRV_NAME | 187 | dev_err(&pdev->dev, "no rows, cols or keymap from pdata\n"); |
188 | ": No rows, cols or keymap from pdata\n"); | ||
189 | return -EINVAL; | 188 | return -EINVAL; |
190 | } | 189 | } |
191 | 190 | ||
192 | if (!pdata->keymapsize || | 191 | if (!pdata->keymapsize || |
193 | pdata->keymapsize > (pdata->rows * pdata->cols)) { | 192 | pdata->keymapsize > (pdata->rows * pdata->cols)) { |
194 | printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n"); | 193 | dev_err(&pdev->dev, "invalid keymapsize\n"); |
195 | return -EINVAL; | 194 | return -EINVAL; |
196 | } | 195 | } |
197 | 196 | ||
@@ -211,8 +210,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
211 | 210 | ||
212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || | 211 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || |
213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { | 212 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { |
214 | printk(KERN_WARNING DRV_NAME | 213 | dev_warn(&pdev->dev, |
215 | ": Invalid Debounce/Columndrive Time in platform data\n"); | 214 | "invalid platform debounce/columndrive time\n"); |
216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | 215 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ |
217 | } else { | 216 | } else { |
218 | bfin_write_KPAD_MSEL( | 217 | bfin_write_KPAD_MSEL( |
@@ -231,16 +230,14 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
231 | 230 | ||
232 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], | 231 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], |
233 | DRV_NAME)) { | 232 | DRV_NAME)) { |
234 | printk(KERN_ERR DRV_NAME | 233 | dev_err(&pdev->dev, "requesting peripherals failed\n"); |
235 | ": Requesting Peripherals failed\n"); | ||
236 | error = -EFAULT; | 234 | error = -EFAULT; |
237 | goto out0; | 235 | goto out0; |
238 | } | 236 | } |
239 | 237 | ||
240 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], | 238 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], |
241 | DRV_NAME)) { | 239 | DRV_NAME)) { |
242 | printk(KERN_ERR DRV_NAME | 240 | dev_err(&pdev->dev, "requesting peripherals failed\n"); |
243 | ": Requesting Peripherals failed\n"); | ||
244 | error = -EFAULT; | 241 | error = -EFAULT; |
245 | goto out1; | 242 | goto out1; |
246 | } | 243 | } |
@@ -254,9 +251,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
254 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | 251 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, |
255 | 0, DRV_NAME, pdev); | 252 | 0, DRV_NAME, pdev); |
256 | if (error) { | 253 | if (error) { |
257 | printk(KERN_ERR DRV_NAME | 254 | dev_err(&pdev->dev, "unable to claim irq %d\n", |
258 | ": unable to claim irq %d; error %d\n", | 255 | bf54x_kpad->irq); |
259 | bf54x_kpad->irq, error); | ||
260 | goto out2; | 256 | goto out2; |
261 | } | 257 | } |
262 | 258 | ||
@@ -297,8 +293,7 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
297 | 293 | ||
298 | error = input_register_device(input); | 294 | error = input_register_device(input); |
299 | if (error) { | 295 | if (error) { |
300 | printk(KERN_ERR DRV_NAME | 296 | dev_err(&pdev->dev, "unable to register input device\n"); |
301 | ": Unable to register input device (%d)\n", error); | ||
302 | goto out4; | 297 | goto out4; |
303 | } | 298 | } |
304 | 299 | ||
@@ -316,9 +311,6 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
316 | 311 | ||
317 | device_init_wakeup(&pdev->dev, 1); | 312 | device_init_wakeup(&pdev->dev, 1); |
318 | 313 | ||
319 | printk(KERN_ERR DRV_NAME | ||
320 | ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq); | ||
321 | |||
322 | return 0; | 314 | return 0; |
323 | 315 | ||
324 | out4: | 316 | out4: |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index efed0c9e242e..a88aff3816a0 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -216,8 +216,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
216 | 216 | ||
217 | 217 | ||
218 | #ifdef CONFIG_PM | 218 | #ifdef CONFIG_PM |
219 | static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | 219 | static int gpio_keys_suspend(struct device *dev) |
220 | { | 220 | { |
221 | struct platform_device *pdev = to_platform_device(dev); | ||
221 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 222 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
222 | int i; | 223 | int i; |
223 | 224 | ||
@@ -234,8 +235,9 @@ static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | |||
234 | return 0; | 235 | return 0; |
235 | } | 236 | } |
236 | 237 | ||
237 | static int gpio_keys_resume(struct platform_device *pdev) | 238 | static int gpio_keys_resume(struct device *dev) |
238 | { | 239 | { |
240 | struct platform_device *pdev = to_platform_device(dev); | ||
239 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 241 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
240 | int i; | 242 | int i; |
241 | 243 | ||
@@ -251,19 +253,22 @@ static int gpio_keys_resume(struct platform_device *pdev) | |||
251 | 253 | ||
252 | return 0; | 254 | return 0; |
253 | } | 255 | } |
254 | #else | 256 | |
255 | #define gpio_keys_suspend NULL | 257 | static const struct dev_pm_ops gpio_keys_pm_ops = { |
256 | #define gpio_keys_resume NULL | 258 | .suspend = gpio_keys_suspend, |
259 | .resume = gpio_keys_resume, | ||
260 | }; | ||
257 | #endif | 261 | #endif |
258 | 262 | ||
259 | static struct platform_driver gpio_keys_device_driver = { | 263 | static struct platform_driver gpio_keys_device_driver = { |
260 | .probe = gpio_keys_probe, | 264 | .probe = gpio_keys_probe, |
261 | .remove = __devexit_p(gpio_keys_remove), | 265 | .remove = __devexit_p(gpio_keys_remove), |
262 | .suspend = gpio_keys_suspend, | ||
263 | .resume = gpio_keys_resume, | ||
264 | .driver = { | 266 | .driver = { |
265 | .name = "gpio-keys", | 267 | .name = "gpio-keys", |
266 | .owner = THIS_MODULE, | 268 | .owner = THIS_MODULE, |
269 | #ifdef CONFIG_PM | ||
270 | .pm = &gpio_keys_pm_ops, | ||
271 | #endif | ||
267 | } | 272 | } |
268 | }; | 273 | }; |
269 | 274 | ||
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 6f356705ee3b..c83f4b2ec7d3 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c | |||
@@ -37,19 +37,19 @@ | |||
37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/semaphore.h> | 40 | #include <linux/completion.h> |
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/pci_ids.h> | 42 | #include <linux/pci_ids.h> |
43 | 43 | ||
44 | #define PREFIX "HIL KEYB: " | 44 | #define PREFIX "HIL: " |
45 | #define HIL_GENERIC_NAME "HIL keyboard" | ||
46 | 45 | ||
47 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | 46 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); |
48 | MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); | 47 | MODULE_DESCRIPTION("HIL keyboard/mouse driver"); |
49 | MODULE_LICENSE("Dual BSD/GPL"); | 48 | MODULE_LICENSE("Dual BSD/GPL"); |
50 | MODULE_ALIAS("serio:ty03pr25id00ex*"); | 49 | MODULE_ALIAS("serio:ty03pr25id00ex*"); /* HIL keyboard */ |
50 | MODULE_ALIAS("serio:ty03pr25id0Fex*"); /* HIL mouse */ | ||
51 | 51 | ||
52 | #define HIL_KBD_MAX_LENGTH 16 | 52 | #define HIL_PACKET_MAX_LENGTH 16 |
53 | 53 | ||
54 | #define HIL_KBD_SET1_UPBIT 0x01 | 54 | #define HIL_KBD_SET1_UPBIT 0x01 |
55 | #define HIL_KBD_SET1_SHIFT 1 | 55 | #define HIL_KBD_SET1_SHIFT 1 |
@@ -67,308 +67,497 @@ static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly = | |||
67 | 67 | ||
68 | static const char hil_language[][16] = { HIL_LOCALE_MAP }; | 68 | static const char hil_language[][16] = { HIL_LOCALE_MAP }; |
69 | 69 | ||
70 | struct hil_kbd { | 70 | struct hil_dev { |
71 | struct input_dev *dev; | 71 | struct input_dev *dev; |
72 | struct serio *serio; | 72 | struct serio *serio; |
73 | 73 | ||
74 | /* Input buffer and index for packets from HIL bus. */ | 74 | /* Input buffer and index for packets from HIL bus. */ |
75 | hil_packet data[HIL_KBD_MAX_LENGTH]; | 75 | hil_packet data[HIL_PACKET_MAX_LENGTH]; |
76 | int idx4; /* four counts per packet */ | 76 | int idx4; /* four counts per packet */ |
77 | 77 | ||
78 | /* Raw device info records from HIL bus, see hil.h for fields. */ | 78 | /* Raw device info records from HIL bus, see hil.h for fields. */ |
79 | char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */ | 79 | char idd[HIL_PACKET_MAX_LENGTH]; /* DID byte and IDD record */ |
80 | char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */ | 80 | char rsc[HIL_PACKET_MAX_LENGTH]; /* RSC record */ |
81 | char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */ | 81 | char exd[HIL_PACKET_MAX_LENGTH]; /* EXD record */ |
82 | char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */ | 82 | char rnm[HIL_PACKET_MAX_LENGTH + 1]; /* RNM record + NULL term. */ |
83 | 83 | ||
84 | /* Something to sleep around with. */ | 84 | struct completion cmd_done; |
85 | struct semaphore sem; | 85 | |
86 | bool is_pointer; | ||
87 | /* Extra device details needed for pointing devices. */ | ||
88 | unsigned int nbtn, naxes; | ||
89 | unsigned int btnmap[7]; | ||
86 | }; | 90 | }; |
87 | 91 | ||
88 | /* Process a complete packet after transfer from the HIL */ | 92 | static bool hil_dev_is_command_response(hil_packet p) |
89 | static void hil_kbd_process_record(struct hil_kbd *kbd) | ||
90 | { | 93 | { |
91 | struct input_dev *dev = kbd->dev; | 94 | if ((p & ~HIL_CMDCT_POL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) |
92 | hil_packet *data = kbd->data; | 95 | return false; |
93 | hil_packet p; | ||
94 | int idx, i, cnt; | ||
95 | 96 | ||
96 | idx = kbd->idx4/4; | 97 | if ((p & ~HIL_CMDCT_RPL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) |
97 | p = data[idx - 1]; | 98 | return false; |
98 | 99 | ||
99 | if ((p & ~HIL_CMDCT_POL) == | 100 | return true; |
100 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) | 101 | } |
101 | goto report; | 102 | |
102 | if ((p & ~HIL_CMDCT_RPL) == | 103 | static void hil_dev_handle_command_response(struct hil_dev *dev) |
103 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) | 104 | { |
104 | goto report; | 105 | hil_packet p; |
106 | char *buf; | ||
107 | int i, idx; | ||
108 | |||
109 | idx = dev->idx4 / 4; | ||
110 | p = dev->data[idx - 1]; | ||
105 | 111 | ||
106 | /* Not a poll response. See if we are loading config records. */ | ||
107 | switch (p & HIL_PKT_DATA_MASK) { | 112 | switch (p & HIL_PKT_DATA_MASK) { |
108 | case HIL_CMD_IDD: | 113 | case HIL_CMD_IDD: |
109 | for (i = 0; i < idx; i++) | 114 | buf = dev->idd; |
110 | kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
111 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
112 | kbd->idd[i] = 0; | ||
113 | break; | 115 | break; |
114 | 116 | ||
115 | case HIL_CMD_RSC: | 117 | case HIL_CMD_RSC: |
116 | for (i = 0; i < idx; i++) | 118 | buf = dev->rsc; |
117 | kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
118 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
119 | kbd->rsc[i] = 0; | ||
120 | break; | 119 | break; |
121 | 120 | ||
122 | case HIL_CMD_EXD: | 121 | case HIL_CMD_EXD: |
123 | for (i = 0; i < idx; i++) | 122 | buf = dev->exd; |
124 | kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
125 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
126 | kbd->exd[i] = 0; | ||
127 | break; | 123 | break; |
128 | 124 | ||
129 | case HIL_CMD_RNM: | 125 | case HIL_CMD_RNM: |
130 | for (i = 0; i < idx; i++) | 126 | dev->rnm[HIL_PACKET_MAX_LENGTH] = 0; |
131 | kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | 127 | buf = dev->rnm; |
132 | for (; i < HIL_KBD_MAX_LENGTH + 1; i++) | ||
133 | kbd->rnm[i] = '\0'; | ||
134 | break; | 128 | break; |
135 | 129 | ||
136 | default: | 130 | default: |
137 | /* These occur when device isn't present */ | 131 | /* These occur when device isn't present */ |
138 | if (p == (HIL_ERR_INT | HIL_PKT_CMD)) | 132 | if (p != (HIL_ERR_INT | HIL_PKT_CMD)) { |
139 | break; | 133 | /* Anything else we'd like to know about. */ |
140 | /* Anything else we'd like to know about. */ | 134 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); |
141 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); | 135 | } |
142 | break; | 136 | goto out; |
143 | } | 137 | } |
144 | goto out; | ||
145 | 138 | ||
146 | report: | 139 | for (i = 0; i < idx; i++) |
147 | cnt = 1; | 140 | buf[i] = dev->data[i] & HIL_PKT_DATA_MASK; |
141 | for (; i < HIL_PACKET_MAX_LENGTH; i++) | ||
142 | buf[i] = 0; | ||
143 | out: | ||
144 | complete(&dev->cmd_done); | ||
145 | } | ||
146 | |||
147 | static void hil_dev_handle_kbd_events(struct hil_dev *kbd) | ||
148 | { | ||
149 | struct input_dev *dev = kbd->dev; | ||
150 | int idx = kbd->idx4 / 4; | ||
151 | int i; | ||
152 | |||
148 | switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { | 153 | switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { |
149 | case HIL_POL_CHARTYPE_NONE: | 154 | case HIL_POL_CHARTYPE_NONE: |
150 | break; | 155 | return; |
151 | 156 | ||
152 | case HIL_POL_CHARTYPE_ASCII: | 157 | case HIL_POL_CHARTYPE_ASCII: |
153 | while (cnt < idx - 1) | 158 | for (i = 1; i < idx - 1; i++) |
154 | input_report_key(dev, kbd->data[cnt++] & 0x7f, 1); | 159 | input_report_key(dev, kbd->data[i] & 0x7f, 1); |
155 | break; | 160 | break; |
156 | 161 | ||
157 | case HIL_POL_CHARTYPE_RSVD1: | 162 | case HIL_POL_CHARTYPE_RSVD1: |
158 | case HIL_POL_CHARTYPE_RSVD2: | 163 | case HIL_POL_CHARTYPE_RSVD2: |
159 | case HIL_POL_CHARTYPE_BINARY: | 164 | case HIL_POL_CHARTYPE_BINARY: |
160 | while (cnt < idx - 1) | 165 | for (i = 1; i < idx - 1; i++) |
161 | input_report_key(dev, kbd->data[cnt++], 1); | 166 | input_report_key(dev, kbd->data[i], 1); |
162 | break; | 167 | break; |
163 | 168 | ||
164 | case HIL_POL_CHARTYPE_SET1: | 169 | case HIL_POL_CHARTYPE_SET1: |
165 | while (cnt < idx - 1) { | 170 | for (i = 1; i < idx - 1; i++) { |
166 | unsigned int key; | 171 | unsigned int key = kbd->data[i]; |
167 | int up; | 172 | int up = key & HIL_KBD_SET1_UPBIT; |
168 | key = kbd->data[cnt++]; | 173 | |
169 | up = key & HIL_KBD_SET1_UPBIT; | ||
170 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 174 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
171 | key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; | 175 | key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; |
172 | if (key != KEY_RESERVED) | 176 | input_report_key(dev, key, !up); |
173 | input_report_key(dev, key, !up); | ||
174 | } | 177 | } |
175 | break; | 178 | break; |
176 | 179 | ||
177 | case HIL_POL_CHARTYPE_SET2: | 180 | case HIL_POL_CHARTYPE_SET2: |
178 | while (cnt < idx - 1) { | 181 | for (i = 1; i < idx - 1; i++) { |
179 | unsigned int key; | 182 | unsigned int key = kbd->data[i]; |
180 | int up; | 183 | int up = key & HIL_KBD_SET2_UPBIT; |
181 | key = kbd->data[cnt++]; | 184 | |
182 | up = key & HIL_KBD_SET2_UPBIT; | ||
183 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 185 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
184 | key = key >> HIL_KBD_SET2_SHIFT; | 186 | key = key >> HIL_KBD_SET2_SHIFT; |
185 | if (key != KEY_RESERVED) | 187 | input_report_key(dev, key, !up); |
186 | input_report_key(dev, key, !up); | ||
187 | } | 188 | } |
188 | break; | 189 | break; |
189 | 190 | ||
190 | case HIL_POL_CHARTYPE_SET3: | 191 | case HIL_POL_CHARTYPE_SET3: |
191 | while (cnt < idx - 1) { | 192 | for (i = 1; i < idx - 1; i++) { |
192 | unsigned int key; | 193 | unsigned int key = kbd->data[i]; |
193 | int up; | 194 | int up = key & HIL_KBD_SET3_UPBIT; |
194 | key = kbd->data[cnt++]; | 195 | |
195 | up = key & HIL_KBD_SET3_UPBIT; | ||
196 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 196 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
197 | key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; | 197 | key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; |
198 | if (key != KEY_RESERVED) | 198 | input_report_key(dev, key, !up); |
199 | input_report_key(dev, key, !up); | ||
200 | } | 199 | } |
201 | break; | 200 | break; |
202 | } | 201 | } |
203 | out: | 202 | |
204 | kbd->idx4 = 0; | 203 | input_sync(dev); |
205 | up(&kbd->sem); | ||
206 | } | 204 | } |
207 | 205 | ||
208 | static void hil_kbd_process_err(struct hil_kbd *kbd) | 206 | static void hil_dev_handle_ptr_events(struct hil_dev *ptr) |
207 | { | ||
208 | struct input_dev *dev = ptr->dev; | ||
209 | int idx = ptr->idx4 / 4; | ||
210 | hil_packet p = ptr->data[idx - 1]; | ||
211 | int i, cnt, laxis; | ||
212 | bool absdev, ax16; | ||
213 | |||
214 | if ((p & HIL_CMDCT_POL) != idx - 1) { | ||
215 | printk(KERN_WARNING PREFIX | ||
216 | "Malformed poll packet %x (idx = %i)\n", p, idx); | ||
217 | return; | ||
218 | } | ||
219 | |||
220 | i = (p & HIL_POL_AXIS_ALT) ? 3 : 0; | ||
221 | laxis = (p & HIL_POL_NUM_AXES_MASK) + i; | ||
222 | |||
223 | ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ | ||
224 | absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; | ||
225 | |||
226 | for (cnt = 1; i < laxis; i++) { | ||
227 | unsigned int lo, hi, val; | ||
228 | |||
229 | lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; | ||
230 | hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; | ||
231 | |||
232 | if (absdev) { | ||
233 | val = lo + (hi << 8); | ||
234 | #ifdef TABLET_AUTOADJUST | ||
235 | if (val < dev->absmin[ABS_X + i]) | ||
236 | dev->absmin[ABS_X + i] = val; | ||
237 | if (val > dev->absmax[ABS_X + i]) | ||
238 | dev->absmax[ABS_X + i] = val; | ||
239 | #endif | ||
240 | if (i%3) val = dev->absmax[ABS_X + i] - val; | ||
241 | input_report_abs(dev, ABS_X + i, val); | ||
242 | } else { | ||
243 | val = (int) (((int8_t)lo) | ((int8_t)hi << 8)); | ||
244 | if (i % 3) | ||
245 | val *= -1; | ||
246 | input_report_rel(dev, REL_X + i, val); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | while (cnt < idx - 1) { | ||
251 | unsigned int btn = ptr->data[cnt++]; | ||
252 | int up = btn & 1; | ||
253 | |||
254 | btn &= 0xfe; | ||
255 | if (btn == 0x8e) | ||
256 | continue; /* TODO: proximity == touch? */ | ||
257 | if (btn > 0x8c || btn < 0x80) | ||
258 | continue; | ||
259 | btn = (btn - 0x80) >> 1; | ||
260 | btn = ptr->btnmap[btn]; | ||
261 | input_report_key(dev, btn, !up); | ||
262 | } | ||
263 | |||
264 | input_sync(dev); | ||
265 | } | ||
266 | |||
267 | static void hil_dev_process_err(struct hil_dev *dev) | ||
209 | { | 268 | { |
210 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); | 269 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); |
211 | kbd->idx4 = 0; | 270 | dev->idx4 = 0; |
212 | up(&kbd->sem); | 271 | complete(&dev->cmd_done); /* just in case somebody is waiting */ |
213 | } | 272 | } |
214 | 273 | ||
215 | static irqreturn_t hil_kbd_interrupt(struct serio *serio, | 274 | static irqreturn_t hil_dev_interrupt(struct serio *serio, |
216 | unsigned char data, unsigned int flags) | 275 | unsigned char data, unsigned int flags) |
217 | { | 276 | { |
218 | struct hil_kbd *kbd; | 277 | struct hil_dev *dev; |
219 | hil_packet packet; | 278 | hil_packet packet; |
220 | int idx; | 279 | int idx; |
221 | 280 | ||
222 | kbd = serio_get_drvdata(serio); | 281 | dev = serio_get_drvdata(serio); |
223 | BUG_ON(kbd == NULL); | 282 | BUG_ON(dev == NULL); |
224 | 283 | ||
225 | if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) { | 284 | if (dev->idx4 >= HIL_PACKET_MAX_LENGTH * sizeof(hil_packet)) { |
226 | hil_kbd_process_err(kbd); | 285 | hil_dev_process_err(dev); |
227 | return IRQ_HANDLED; | 286 | goto out; |
228 | } | 287 | } |
229 | idx = kbd->idx4/4; | 288 | |
230 | if (!(kbd->idx4 % 4)) | 289 | idx = dev->idx4 / 4; |
231 | kbd->data[idx] = 0; | 290 | if (!(dev->idx4 % 4)) |
232 | packet = kbd->data[idx]; | 291 | dev->data[idx] = 0; |
233 | packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8); | 292 | packet = dev->data[idx]; |
234 | kbd->data[idx] = packet; | 293 | packet |= ((hil_packet)data) << ((3 - (dev->idx4 % 4)) * 8); |
294 | dev->data[idx] = packet; | ||
235 | 295 | ||
236 | /* Records of N 4-byte hil_packets must terminate with a command. */ | 296 | /* Records of N 4-byte hil_packets must terminate with a command. */ |
237 | if ((++(kbd->idx4)) % 4) | 297 | if ((++dev->idx4 % 4) == 0) { |
238 | return IRQ_HANDLED; | 298 | if ((packet & 0xffff0000) != HIL_ERR_INT) { |
239 | if ((packet & 0xffff0000) != HIL_ERR_INT) { | 299 | hil_dev_process_err(dev); |
240 | hil_kbd_process_err(kbd); | 300 | } else if (packet & HIL_PKT_CMD) { |
241 | return IRQ_HANDLED; | 301 | if (hil_dev_is_command_response(packet)) |
302 | hil_dev_handle_command_response(dev); | ||
303 | else if (dev->is_pointer) | ||
304 | hil_dev_handle_ptr_events(dev); | ||
305 | else | ||
306 | hil_dev_handle_kbd_events(dev); | ||
307 | dev->idx4 = 0; | ||
308 | } | ||
242 | } | 309 | } |
243 | if (packet & HIL_PKT_CMD) | 310 | out: |
244 | hil_kbd_process_record(kbd); | ||
245 | return IRQ_HANDLED; | 311 | return IRQ_HANDLED; |
246 | } | 312 | } |
247 | 313 | ||
248 | static void hil_kbd_disconnect(struct serio *serio) | 314 | static void hil_dev_disconnect(struct serio *serio) |
249 | { | 315 | { |
250 | struct hil_kbd *kbd; | 316 | struct hil_dev *dev = serio_get_drvdata(serio); |
251 | 317 | ||
252 | kbd = serio_get_drvdata(serio); | 318 | BUG_ON(dev == NULL); |
253 | BUG_ON(kbd == NULL); | ||
254 | 319 | ||
255 | serio_close(serio); | 320 | serio_close(serio); |
256 | input_unregister_device(kbd->dev); | 321 | input_unregister_device(dev->dev); |
257 | kfree(kbd); | 322 | serio_set_drvdata(serio, NULL); |
323 | kfree(dev); | ||
324 | } | ||
325 | |||
326 | static void hil_dev_keyboard_setup(struct hil_dev *kbd) | ||
327 | { | ||
328 | struct input_dev *input_dev = kbd->dev; | ||
329 | uint8_t did = kbd->idd[0]; | ||
330 | int i; | ||
331 | |||
332 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
333 | input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | ||
334 | BIT_MASK(LED_SCROLLL); | ||
335 | |||
336 | for (i = 0; i < 128; i++) { | ||
337 | __set_bit(hil_kbd_set1[i], input_dev->keybit); | ||
338 | __set_bit(hil_kbd_set3[i], input_dev->keybit); | ||
339 | } | ||
340 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
341 | |||
342 | input_dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | ||
343 | input_dev->keycodesize = sizeof(hil_kbd_set1[0]); | ||
344 | input_dev->keycode = hil_kbd_set1; | ||
345 | |||
346 | input_dev->name = strlen(kbd->rnm) ? kbd->rnm : "HIL keyboard"; | ||
347 | input_dev->phys = "hpkbd/input0"; | ||
348 | |||
349 | printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", | ||
350 | did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); | ||
258 | } | 351 | } |
259 | 352 | ||
260 | static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) | 353 | static void hil_dev_pointer_setup(struct hil_dev *ptr) |
261 | { | 354 | { |
262 | struct hil_kbd *kbd; | 355 | struct input_dev *input_dev = ptr->dev; |
263 | uint8_t did, *idd; | 356 | uint8_t did = ptr->idd[0]; |
264 | int i; | 357 | uint8_t *idd = ptr->idd + 1; |
358 | unsigned int naxsets = HIL_IDD_NUM_AXSETS(*idd); | ||
359 | unsigned int i, btntype; | ||
360 | const char *txt; | ||
361 | |||
362 | ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); | ||
363 | |||
364 | switch (did & HIL_IDD_DID_TYPE_MASK) { | ||
365 | case HIL_IDD_DID_TYPE_REL: | ||
366 | input_dev->evbit[0] = BIT_MASK(EV_REL); | ||
265 | 367 | ||
266 | kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); | 368 | for (i = 0; i < ptr->naxes; i++) |
267 | if (!kbd) | 369 | __set_bit(REL_X + i, input_dev->relbit); |
268 | return -ENOMEM; | ||
269 | 370 | ||
270 | kbd->dev = input_allocate_device(); | 371 | for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) |
271 | if (!kbd->dev) | 372 | __set_bit(REL_X + i, input_dev->relbit); |
373 | |||
374 | txt = "relative"; | ||
375 | break; | ||
376 | |||
377 | case HIL_IDD_DID_TYPE_ABS: | ||
378 | input_dev->evbit[0] = BIT_MASK(EV_ABS); | ||
379 | |||
380 | for (i = 0; i < ptr->naxes; i++) | ||
381 | input_set_abs_params(input_dev, ABS_X + i, | ||
382 | 0, HIL_IDD_AXIS_MAX(idd, i), 0, 0); | ||
383 | |||
384 | for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) | ||
385 | input_set_abs_params(input_dev, ABS_X + i, | ||
386 | 0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0); | ||
387 | |||
388 | #ifdef TABLET_AUTOADJUST | ||
389 | for (i = 0; i < ABS_MAX; i++) { | ||
390 | int diff = input_dev->absmax[ABS_X + i] / 10; | ||
391 | input_dev->absmin[ABS_X + i] += diff; | ||
392 | input_dev->absmax[ABS_X + i] -= diff; | ||
393 | } | ||
394 | #endif | ||
395 | |||
396 | txt = "absolute"; | ||
397 | break; | ||
398 | |||
399 | default: | ||
400 | BUG(); | ||
401 | } | ||
402 | |||
403 | ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); | ||
404 | if (ptr->nbtn) | ||
405 | input_dev->evbit[0] |= BIT_MASK(EV_KEY); | ||
406 | |||
407 | btntype = BTN_MISC; | ||
408 | if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) | ||
409 | #ifdef TABLET_SIMULATES_MOUSE | ||
410 | btntype = BTN_TOUCH; | ||
411 | #else | ||
412 | btntype = BTN_DIGI; | ||
413 | #endif | ||
414 | if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) | ||
415 | btntype = BTN_TOUCH; | ||
416 | |||
417 | if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) | ||
418 | btntype = BTN_MOUSE; | ||
419 | |||
420 | for (i = 0; i < ptr->nbtn; i++) { | ||
421 | __set_bit(btntype | i, input_dev->keybit); | ||
422 | ptr->btnmap[i] = btntype | i; | ||
423 | } | ||
424 | |||
425 | if (btntype == BTN_MOUSE) { | ||
426 | /* Swap buttons 2 and 3 */ | ||
427 | ptr->btnmap[1] = BTN_MIDDLE; | ||
428 | ptr->btnmap[2] = BTN_RIGHT; | ||
429 | } | ||
430 | |||
431 | input_dev->name = strlen(ptr->rnm) ? ptr->rnm : "HIL pointer device"; | ||
432 | |||
433 | printk(KERN_INFO PREFIX | ||
434 | "HIL pointer device found (did: 0x%02x, axis: %s)\n", | ||
435 | did, txt); | ||
436 | printk(KERN_INFO PREFIX | ||
437 | "HIL pointer has %i buttons and %i sets of %i axes\n", | ||
438 | ptr->nbtn, naxsets, ptr->naxes); | ||
439 | } | ||
440 | |||
441 | static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) | ||
442 | { | ||
443 | struct hil_dev *dev; | ||
444 | struct input_dev *input_dev; | ||
445 | uint8_t did, *idd; | ||
446 | int error; | ||
447 | |||
448 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
449 | input_dev = input_allocate_device(); | ||
450 | if (!dev || !input_dev) { | ||
451 | error = -ENOMEM; | ||
272 | goto bail0; | 452 | goto bail0; |
453 | } | ||
273 | 454 | ||
274 | if (serio_open(serio, drv)) | 455 | dev->serio = serio; |
275 | goto bail1; | 456 | dev->dev = input_dev; |
276 | 457 | ||
277 | serio_set_drvdata(serio, kbd); | 458 | error = serio_open(serio, drv); |
278 | kbd->serio = serio; | 459 | if (error) |
460 | goto bail0; | ||
279 | 461 | ||
280 | init_MUTEX_LOCKED(&kbd->sem); | 462 | serio_set_drvdata(serio, dev); |
281 | 463 | ||
282 | /* Get device info. MLC driver supplies devid/status/etc. */ | 464 | /* Get device info. MLC driver supplies devid/status/etc. */ |
283 | serio->write(serio, 0); | 465 | init_completion(&dev->cmd_done); |
284 | serio->write(serio, 0); | 466 | serio_write(serio, 0); |
285 | serio->write(serio, HIL_PKT_CMD >> 8); | 467 | serio_write(serio, 0); |
286 | serio->write(serio, HIL_CMD_IDD); | 468 | serio_write(serio, HIL_PKT_CMD >> 8); |
287 | down(&kbd->sem); | 469 | serio_write(serio, HIL_CMD_IDD); |
288 | 470 | error = wait_for_completion_killable(&dev->cmd_done); | |
289 | serio->write(serio, 0); | 471 | if (error) |
290 | serio->write(serio, 0); | 472 | goto bail1; |
291 | serio->write(serio, HIL_PKT_CMD >> 8); | 473 | |
292 | serio->write(serio, HIL_CMD_RSC); | 474 | init_completion(&dev->cmd_done); |
293 | down(&kbd->sem); | 475 | serio_write(serio, 0); |
294 | 476 | serio_write(serio, 0); | |
295 | serio->write(serio, 0); | 477 | serio_write(serio, HIL_PKT_CMD >> 8); |
296 | serio->write(serio, 0); | 478 | serio_write(serio, HIL_CMD_RSC); |
297 | serio->write(serio, HIL_PKT_CMD >> 8); | 479 | error = wait_for_completion_killable(&dev->cmd_done); |
298 | serio->write(serio, HIL_CMD_RNM); | 480 | if (error) |
299 | down(&kbd->sem); | 481 | goto bail1; |
300 | 482 | ||
301 | serio->write(serio, 0); | 483 | init_completion(&dev->cmd_done); |
302 | serio->write(serio, 0); | 484 | serio_write(serio, 0); |
303 | serio->write(serio, HIL_PKT_CMD >> 8); | 485 | serio_write(serio, 0); |
304 | serio->write(serio, HIL_CMD_EXD); | 486 | serio_write(serio, HIL_PKT_CMD >> 8); |
305 | down(&kbd->sem); | 487 | serio_write(serio, HIL_CMD_RNM); |
306 | 488 | error = wait_for_completion_killable(&dev->cmd_done); | |
307 | up(&kbd->sem); | 489 | if (error) |
308 | 490 | goto bail1; | |
309 | did = kbd->idd[0]; | 491 | |
310 | idd = kbd->idd + 1; | 492 | init_completion(&dev->cmd_done); |
493 | serio_write(serio, 0); | ||
494 | serio_write(serio, 0); | ||
495 | serio_write(serio, HIL_PKT_CMD >> 8); | ||
496 | serio_write(serio, HIL_CMD_EXD); | ||
497 | error = wait_for_completion_killable(&dev->cmd_done); | ||
498 | if (error) | ||
499 | goto bail1; | ||
500 | |||
501 | did = dev->idd[0]; | ||
502 | idd = dev->idd + 1; | ||
503 | |||
311 | switch (did & HIL_IDD_DID_TYPE_MASK) { | 504 | switch (did & HIL_IDD_DID_TYPE_MASK) { |
312 | case HIL_IDD_DID_TYPE_KB_INTEGRAL: | 505 | case HIL_IDD_DID_TYPE_KB_INTEGRAL: |
313 | case HIL_IDD_DID_TYPE_KB_ITF: | 506 | case HIL_IDD_DID_TYPE_KB_ITF: |
314 | case HIL_IDD_DID_TYPE_KB_RSVD: | 507 | case HIL_IDD_DID_TYPE_KB_RSVD: |
315 | case HIL_IDD_DID_TYPE_CHAR: | 508 | case HIL_IDD_DID_TYPE_CHAR: |
316 | printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", | 509 | if (HIL_IDD_NUM_BUTTONS(idd) || |
317 | did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); | 510 | HIL_IDD_NUM_AXES_PER_SET(*idd)) { |
318 | break; | 511 | printk(KERN_INFO PREFIX |
319 | default: | 512 | "combo devices are not supported.\n"); |
320 | goto bail2; | 513 | goto bail1; |
321 | } | 514 | } |
322 | 515 | ||
323 | if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { | 516 | dev->is_pointer = false; |
324 | printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); | 517 | hil_dev_keyboard_setup(dev); |
325 | goto bail2; | 518 | break; |
326 | } | ||
327 | 519 | ||
328 | kbd->dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 520 | case HIL_IDD_DID_TYPE_REL: |
329 | kbd->dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | 521 | case HIL_IDD_DID_TYPE_ABS: |
330 | BIT_MASK(LED_SCROLLL); | 522 | dev->is_pointer = true; |
331 | kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | 523 | hil_dev_pointer_setup(dev); |
332 | kbd->dev->keycodesize = sizeof(hil_kbd_set1[0]); | 524 | break; |
333 | kbd->dev->keycode = hil_kbd_set1; | ||
334 | kbd->dev->name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; | ||
335 | kbd->dev->phys = "hpkbd/input0"; /* XXX */ | ||
336 | |||
337 | kbd->dev->id.bustype = BUS_HIL; | ||
338 | kbd->dev->id.vendor = PCI_VENDOR_ID_HP; | ||
339 | kbd->dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ | ||
340 | kbd->dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ | ||
341 | kbd->dev->dev.parent = &serio->dev; | ||
342 | 525 | ||
343 | for (i = 0; i < 128; i++) { | 526 | default: |
344 | set_bit(hil_kbd_set1[i], kbd->dev->keybit); | 527 | goto bail1; |
345 | set_bit(hil_kbd_set3[i], kbd->dev->keybit); | ||
346 | } | 528 | } |
347 | clear_bit(0, kbd->dev->keybit); | ||
348 | 529 | ||
349 | input_register_device(kbd->dev); | 530 | input_dev->id.bustype = BUS_HIL; |
350 | printk(KERN_INFO "input: %s, ID: %d\n", | 531 | input_dev->id.vendor = PCI_VENDOR_ID_HP; |
351 | kbd->dev->name, did); | 532 | input_dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ |
533 | input_dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ | ||
534 | input_dev->dev.parent = &serio->dev; | ||
535 | |||
536 | if (!dev->is_pointer) { | ||
537 | serio_write(serio, 0); | ||
538 | serio_write(serio, 0); | ||
539 | serio_write(serio, HIL_PKT_CMD >> 8); | ||
540 | /* Enable Keyswitch Autorepeat 1 */ | ||
541 | serio_write(serio, HIL_CMD_EK1); | ||
542 | /* No need to wait for completion */ | ||
543 | } | ||
352 | 544 | ||
353 | serio->write(serio, 0); | 545 | error = input_register_device(input_dev); |
354 | serio->write(serio, 0); | 546 | if (error) |
355 | serio->write(serio, HIL_PKT_CMD >> 8); | 547 | goto bail1; |
356 | serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */ | ||
357 | down(&kbd->sem); | ||
358 | up(&kbd->sem); | ||
359 | 548 | ||
360 | return 0; | 549 | return 0; |
361 | bail2: | 550 | |
551 | bail1: | ||
362 | serio_close(serio); | 552 | serio_close(serio); |
363 | serio_set_drvdata(serio, NULL); | 553 | serio_set_drvdata(serio, NULL); |
364 | bail1: | ||
365 | input_free_device(kbd->dev); | ||
366 | bail0: | 554 | bail0: |
367 | kfree(kbd); | 555 | input_free_device(input_dev); |
368 | return -EIO; | 556 | kfree(dev); |
557 | return error; | ||
369 | } | 558 | } |
370 | 559 | ||
371 | static struct serio_device_id hil_kbd_ids[] = { | 560 | static struct serio_device_id hil_dev_ids[] = { |
372 | { | 561 | { |
373 | .type = SERIO_HIL_MLC, | 562 | .type = SERIO_HIL_MLC, |
374 | .proto = SERIO_HIL, | 563 | .proto = SERIO_HIL, |
@@ -378,26 +567,26 @@ static struct serio_device_id hil_kbd_ids[] = { | |||
378 | { 0 } | 567 | { 0 } |
379 | }; | 568 | }; |
380 | 569 | ||
381 | static struct serio_driver hil_kbd_serio_drv = { | 570 | static struct serio_driver hil_serio_drv = { |
382 | .driver = { | 571 | .driver = { |
383 | .name = "hil_kbd", | 572 | .name = "hil_dev", |
384 | }, | 573 | }, |
385 | .description = "HP HIL keyboard driver", | 574 | .description = "HP HIL keyboard/mouse/tablet driver", |
386 | .id_table = hil_kbd_ids, | 575 | .id_table = hil_dev_ids, |
387 | .connect = hil_kbd_connect, | 576 | .connect = hil_dev_connect, |
388 | .disconnect = hil_kbd_disconnect, | 577 | .disconnect = hil_dev_disconnect, |
389 | .interrupt = hil_kbd_interrupt | 578 | .interrupt = hil_dev_interrupt |
390 | }; | 579 | }; |
391 | 580 | ||
392 | static int __init hil_kbd_init(void) | 581 | static int __init hil_dev_init(void) |
393 | { | 582 | { |
394 | return serio_register_driver(&hil_kbd_serio_drv); | 583 | return serio_register_driver(&hil_serio_drv); |
395 | } | 584 | } |
396 | 585 | ||
397 | static void __exit hil_kbd_exit(void) | 586 | static void __exit hil_dev_exit(void) |
398 | { | 587 | { |
399 | serio_unregister_driver(&hil_kbd_serio_drv); | 588 | serio_unregister_driver(&hil_serio_drv); |
400 | } | 589 | } |
401 | 590 | ||
402 | module_init(hil_kbd_init); | 591 | module_init(hil_dev_init); |
403 | module_exit(hil_kbd_exit); | 592 | module_exit(hil_dev_exit); |
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 4730ef35c732..f9847e0fb553 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
@@ -525,12 +525,12 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); |
526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); |
527 | if (leds_on != 0) { | 527 | if (leds_on != 0) { |
528 | lk->serio->write (lk->serio, LK_CMD_LED_ON); | 528 | serio_write (lk->serio, LK_CMD_LED_ON); |
529 | lk->serio->write (lk->serio, leds_on); | 529 | serio_write (lk->serio, leds_on); |
530 | } | 530 | } |
531 | if (leds_off != 0) { | 531 | if (leds_off != 0) { |
532 | lk->serio->write (lk->serio, LK_CMD_LED_OFF); | 532 | serio_write (lk->serio, LK_CMD_LED_OFF); |
533 | lk->serio->write (lk->serio, leds_off); | 533 | serio_write (lk->serio, leds_off); |
534 | } | 534 | } |
535 | return 0; | 535 | return 0; |
536 | 536 | ||
@@ -539,20 +539,20 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
539 | case SND_CLICK: | 539 | case SND_CLICK: |
540 | if (value == 0) { | 540 | if (value == 0) { |
541 | DBG ("%s: Deactivating key clicks\n", __func__); | 541 | DBG ("%s: Deactivating key clicks\n", __func__); |
542 | lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 542 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); |
543 | lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 543 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); |
544 | } else { | 544 | } else { |
545 | DBG ("%s: Activating key clicks\n", __func__); | 545 | DBG ("%s: Activating key clicks\n", __func__); |
546 | lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 546 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); |
547 | lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 547 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); |
548 | lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 548 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); |
549 | lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | 549 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); |
550 | } | 550 | } |
551 | return 0; | 551 | return 0; |
552 | 552 | ||
553 | case SND_BELL: | 553 | case SND_BELL: |
554 | if (value != 0) | 554 | if (value != 0) |
555 | lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); | 555 | serio_write (lk->serio, LK_CMD_SOUND_BELL); |
556 | 556 | ||
557 | return 0; | 557 | return 0; |
558 | } | 558 | } |
@@ -579,10 +579,10 @@ lkkbd_reinit (struct work_struct *work) | |||
579 | unsigned char leds_off = 0; | 579 | unsigned char leds_off = 0; |
580 | 580 | ||
581 | /* Ask for ID */ | 581 | /* Ask for ID */ |
582 | lk->serio->write (lk->serio, LK_CMD_REQUEST_ID); | 582 | serio_write (lk->serio, LK_CMD_REQUEST_ID); |
583 | 583 | ||
584 | /* Reset parameters */ | 584 | /* Reset parameters */ |
585 | lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS); | 585 | serio_write (lk->serio, LK_CMD_SET_DEFAULTS); |
586 | 586 | ||
587 | /* Set LEDs */ | 587 | /* Set LEDs */ |
588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); | 588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); |
@@ -590,12 +590,12 @@ lkkbd_reinit (struct work_struct *work) | |||
590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); |
591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); |
592 | if (leds_on != 0) { | 592 | if (leds_on != 0) { |
593 | lk->serio->write (lk->serio, LK_CMD_LED_ON); | 593 | serio_write (lk->serio, LK_CMD_LED_ON); |
594 | lk->serio->write (lk->serio, leds_on); | 594 | serio_write (lk->serio, leds_on); |
595 | } | 595 | } |
596 | if (leds_off != 0) { | 596 | if (leds_off != 0) { |
597 | lk->serio->write (lk->serio, LK_CMD_LED_OFF); | 597 | serio_write (lk->serio, LK_CMD_LED_OFF); |
598 | lk->serio->write (lk->serio, leds_off); | 598 | serio_write (lk->serio, leds_off); |
599 | } | 599 | } |
600 | 600 | ||
601 | /* | 601 | /* |
@@ -603,31 +603,31 @@ lkkbd_reinit (struct work_struct *work) | |||
603 | * only work with a LK401 keyboard and grants access to | 603 | * only work with a LK401 keyboard and grants access to |
604 | * LAlt, RAlt, RCompose and RShift. | 604 | * LAlt, RAlt, RCompose and RShift. |
605 | */ | 605 | */ |
606 | lk->serio->write (lk->serio, LK_CMD_ENABLE_LK401); | 606 | serio_write (lk->serio, LK_CMD_ENABLE_LK401); |
607 | 607 | ||
608 | /* Set all keys to UPDOWN mode */ | 608 | /* Set all keys to UPDOWN mode */ |
609 | for (division = 1; division <= 14; division++) | 609 | for (division = 1; division <= 14; division++) |
610 | lk->serio->write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, | 610 | serio_write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, |
611 | division)); | 611 | division)); |
612 | 612 | ||
613 | /* Enable bell and set volume */ | 613 | /* Enable bell and set volume */ |
614 | lk->serio->write (lk->serio, LK_CMD_ENABLE_BELL); | 614 | serio_write (lk->serio, LK_CMD_ENABLE_BELL); |
615 | lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume)); | 615 | serio_write (lk->serio, volume_to_hw (lk->bell_volume)); |
616 | 616 | ||
617 | /* Enable/disable keyclick (and possibly set volume) */ | 617 | /* Enable/disable keyclick (and possibly set volume) */ |
618 | if (test_bit (SND_CLICK, lk->dev->snd)) { | 618 | if (test_bit (SND_CLICK, lk->dev->snd)) { |
619 | lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 619 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); |
620 | lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 620 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); |
621 | lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 621 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); |
622 | lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | 622 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); |
623 | } else { | 623 | } else { |
624 | lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 624 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); |
625 | lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 625 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); |
626 | } | 626 | } |
627 | 627 | ||
628 | /* Sound the bell if needed */ | 628 | /* Sound the bell if needed */ |
629 | if (test_bit (SND_BELL, lk->dev->snd)) | 629 | if (test_bit (SND_BELL, lk->dev->snd)) |
630 | lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); | 630 | serio_write (lk->serio, LK_CMD_SOUND_BELL); |
631 | } | 631 | } |
632 | 632 | ||
633 | /* | 633 | /* |
@@ -684,8 +684,10 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
684 | input_dev->keycode = lk->keycode; | 684 | input_dev->keycode = lk->keycode; |
685 | input_dev->keycodesize = sizeof (lk_keycode_t); | 685 | input_dev->keycodesize = sizeof (lk_keycode_t); |
686 | input_dev->keycodemax = LK_NUM_KEYCODES; | 686 | input_dev->keycodemax = LK_NUM_KEYCODES; |
687 | |||
687 | for (i = 0; i < LK_NUM_KEYCODES; i++) | 688 | for (i = 0; i < LK_NUM_KEYCODES; i++) |
688 | set_bit (lk->keycode[i], input_dev->keybit); | 689 | __set_bit (lk->keycode[i], input_dev->keybit); |
690 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
689 | 691 | ||
690 | serio_set_drvdata (serio, lk); | 692 | serio_set_drvdata (serio, lk); |
691 | 693 | ||
@@ -697,7 +699,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
697 | if (err) | 699 | if (err) |
698 | goto fail3; | 700 | goto fail3; |
699 | 701 | ||
700 | lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET); | 702 | serio_write (lk->serio, LK_CMD_POWERCYCLE_RESET); |
701 | 703 | ||
702 | return 0; | 704 | return 0; |
703 | 705 | ||
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 0d2fc64a5e1c..c987cc75674c 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/input/matrix_keypad.h> | ||
28 | 29 | ||
29 | #include <asm/mach/arch.h> | 30 | #include <asm/mach/arch.h> |
30 | #include <asm/mach/map.h> | 31 | #include <asm/mach/map.h> |
@@ -107,7 +108,7 @@ struct pxa27x_keypad { | |||
107 | int irq; | 108 | int irq; |
108 | 109 | ||
109 | /* matrix key code map */ | 110 | /* matrix key code map */ |
110 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | 111 | unsigned short matrix_keycodes[MAX_MATRIX_KEY_NUM]; |
111 | 112 | ||
112 | /* state row bits of each column scan */ | 113 | /* state row bits of each column scan */ |
113 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; | 114 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; |
@@ -124,21 +125,21 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | |||
124 | { | 125 | { |
125 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 126 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
126 | struct input_dev *input_dev = keypad->input_dev; | 127 | struct input_dev *input_dev = keypad->input_dev; |
127 | unsigned int *key; | ||
128 | int i; | 128 | int i; |
129 | 129 | ||
130 | key = &pdata->matrix_key_map[0]; | 130 | for (i = 0; i < pdata->matrix_key_map_size; i++) { |
131 | for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { | 131 | unsigned int key = pdata->matrix_key_map[i]; |
132 | int row = ((*key) >> 28) & 0xf; | 132 | unsigned int row = KEY_ROW(key); |
133 | int col = ((*key) >> 24) & 0xf; | 133 | unsigned int col = KEY_COL(key); |
134 | int code = (*key) & 0xffffff; | 134 | unsigned short code = KEY_VAL(key); |
135 | 135 | ||
136 | keypad->matrix_keycodes[(row << 3) + col] = code; | 136 | keypad->matrix_keycodes[(row << 3) + col] = code; |
137 | set_bit(code, input_dev->keybit); | 137 | __set_bit(code, input_dev->keybit); |
138 | } | 138 | } |
139 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
139 | 140 | ||
140 | for (i = 0; i < pdata->direct_key_num; i++) | 141 | for (i = 0; i < pdata->direct_key_num; i++) |
141 | set_bit(pdata->direct_key_map[i], input_dev->keybit); | 142 | __set_bit(pdata->direct_key_map[i], input_dev->keybit); |
142 | 143 | ||
143 | keypad->rotary_up_key[0] = pdata->rotary0_up_key; | 144 | keypad->rotary_up_key[0] = pdata->rotary0_up_key; |
144 | keypad->rotary_up_key[1] = pdata->rotary1_up_key; | 145 | keypad->rotary_up_key[1] = pdata->rotary1_up_key; |
@@ -149,18 +150,18 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | |||
149 | 150 | ||
150 | if (pdata->enable_rotary0) { | 151 | if (pdata->enable_rotary0) { |
151 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { | 152 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { |
152 | set_bit(pdata->rotary0_up_key, input_dev->keybit); | 153 | __set_bit(pdata->rotary0_up_key, input_dev->keybit); |
153 | set_bit(pdata->rotary0_down_key, input_dev->keybit); | 154 | __set_bit(pdata->rotary0_down_key, input_dev->keybit); |
154 | } else | 155 | } else |
155 | set_bit(pdata->rotary0_rel_code, input_dev->relbit); | 156 | __set_bit(pdata->rotary0_rel_code, input_dev->relbit); |
156 | } | 157 | } |
157 | 158 | ||
158 | if (pdata->enable_rotary1) { | 159 | if (pdata->enable_rotary1) { |
159 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { | 160 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { |
160 | set_bit(pdata->rotary1_up_key, input_dev->keybit); | 161 | __set_bit(pdata->rotary1_up_key, input_dev->keybit); |
161 | set_bit(pdata->rotary1_down_key, input_dev->keybit); | 162 | __set_bit(pdata->rotary1_down_key, input_dev->keybit); |
162 | } else | 163 | } else |
163 | set_bit(pdata->rotary1_rel_code, input_dev->relbit); | 164 | __set_bit(pdata->rotary1_rel_code, input_dev->relbit); |
164 | } | 165 | } |
165 | } | 166 | } |
166 | 167 | ||
@@ -388,8 +389,9 @@ static void pxa27x_keypad_close(struct input_dev *dev) | |||
388 | } | 389 | } |
389 | 390 | ||
390 | #ifdef CONFIG_PM | 391 | #ifdef CONFIG_PM |
391 | static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t state) | 392 | static int pxa27x_keypad_suspend(struct device *dev) |
392 | { | 393 | { |
394 | struct platform_device *pdev = to_platform_device(dev); | ||
393 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 395 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
394 | 396 | ||
395 | clk_disable(keypad->clk); | 397 | clk_disable(keypad->clk); |
@@ -400,8 +402,9 @@ static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t stat | |||
400 | return 0; | 402 | return 0; |
401 | } | 403 | } |
402 | 404 | ||
403 | static int pxa27x_keypad_resume(struct platform_device *pdev) | 405 | static int pxa27x_keypad_resume(struct device *dev) |
404 | { | 406 | { |
407 | struct platform_device *pdev = to_platform_device(dev); | ||
405 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 408 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
406 | struct input_dev *input_dev = keypad->input_dev; | 409 | struct input_dev *input_dev = keypad->input_dev; |
407 | 410 | ||
@@ -420,12 +423,12 @@ static int pxa27x_keypad_resume(struct platform_device *pdev) | |||
420 | 423 | ||
421 | return 0; | 424 | return 0; |
422 | } | 425 | } |
423 | #else | ||
424 | #define pxa27x_keypad_suspend NULL | ||
425 | #define pxa27x_keypad_resume NULL | ||
426 | #endif | ||
427 | 426 | ||
428 | #define res_size(res) ((res)->end - (res)->start + 1) | 427 | static const struct dev_pm_ops pxa27x_keypad_pm_ops = { |
428 | .suspend = pxa27x_keypad_suspend, | ||
429 | .resume = pxa27x_keypad_resume, | ||
430 | }; | ||
431 | #endif | ||
429 | 432 | ||
430 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | 433 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) |
431 | { | 434 | { |
@@ -461,14 +464,14 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
461 | goto failed_free; | 464 | goto failed_free; |
462 | } | 465 | } |
463 | 466 | ||
464 | res = request_mem_region(res->start, res_size(res), pdev->name); | 467 | res = request_mem_region(res->start, resource_size(res), pdev->name); |
465 | if (res == NULL) { | 468 | if (res == NULL) { |
466 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | 469 | dev_err(&pdev->dev, "failed to request I/O memory\n"); |
467 | error = -EBUSY; | 470 | error = -EBUSY; |
468 | goto failed_free; | 471 | goto failed_free; |
469 | } | 472 | } |
470 | 473 | ||
471 | keypad->mmio_base = ioremap(res->start, res_size(res)); | 474 | keypad->mmio_base = ioremap(res->start, resource_size(res)); |
472 | if (keypad->mmio_base == NULL) { | 475 | if (keypad->mmio_base == NULL) { |
473 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | 476 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); |
474 | error = -ENXIO; | 477 | error = -ENXIO; |
@@ -540,7 +543,7 @@ failed_put_clk: | |||
540 | failed_free_io: | 543 | failed_free_io: |
541 | iounmap(keypad->mmio_base); | 544 | iounmap(keypad->mmio_base); |
542 | failed_free_mem: | 545 | failed_free_mem: |
543 | release_mem_region(res->start, res_size(res)); | 546 | release_mem_region(res->start, resource_size(res)); |
544 | failed_free: | 547 | failed_free: |
545 | kfree(keypad); | 548 | kfree(keypad); |
546 | return error; | 549 | return error; |
@@ -552,8 +555,6 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | |||
552 | struct resource *res; | 555 | struct resource *res; |
553 | 556 | ||
554 | free_irq(keypad->irq, pdev); | 557 | free_irq(keypad->irq, pdev); |
555 | |||
556 | clk_disable(keypad->clk); | ||
557 | clk_put(keypad->clk); | 558 | clk_put(keypad->clk); |
558 | 559 | ||
559 | input_unregister_device(keypad->input_dev); | 560 | input_unregister_device(keypad->input_dev); |
@@ -562,7 +563,7 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | |||
562 | iounmap(keypad->mmio_base); | 563 | iounmap(keypad->mmio_base); |
563 | 564 | ||
564 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 565 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
565 | release_mem_region(res->start, res_size(res)); | 566 | release_mem_region(res->start, resource_size(res)); |
566 | 567 | ||
567 | platform_set_drvdata(pdev, NULL); | 568 | platform_set_drvdata(pdev, NULL); |
568 | kfree(keypad); | 569 | kfree(keypad); |
@@ -575,11 +576,12 @@ MODULE_ALIAS("platform:pxa27x-keypad"); | |||
575 | static struct platform_driver pxa27x_keypad_driver = { | 576 | static struct platform_driver pxa27x_keypad_driver = { |
576 | .probe = pxa27x_keypad_probe, | 577 | .probe = pxa27x_keypad_probe, |
577 | .remove = __devexit_p(pxa27x_keypad_remove), | 578 | .remove = __devexit_p(pxa27x_keypad_remove), |
578 | .suspend = pxa27x_keypad_suspend, | ||
579 | .resume = pxa27x_keypad_resume, | ||
580 | .driver = { | 579 | .driver = { |
581 | .name = "pxa27x-keypad", | 580 | .name = "pxa27x-keypad", |
582 | .owner = THIS_MODULE, | 581 | .owner = THIS_MODULE, |
582 | #ifdef CONFIG_PM | ||
583 | .pm = &pxa27x_keypad_pm_ops, | ||
584 | #endif | ||
583 | }, | 585 | }, |
584 | }; | 586 | }; |
585 | 587 | ||
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index cea70e6a1031..0714bf2c28fc 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c | |||
@@ -128,7 +128,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
128 | struct resource *res; | 128 | struct resource *res; |
129 | struct input_dev *input; | 129 | struct input_dev *input; |
130 | char clk_name[8]; | 130 | char clk_name[8]; |
131 | int i, k; | 131 | int i; |
132 | int irq, error; | 132 | int irq, error; |
133 | 133 | ||
134 | if (!pdev->dev.platform_data) { | 134 | if (!pdev->dev.platform_data) { |
@@ -195,17 +195,19 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
195 | input->id.product = 0x0001; | 195 | input->id.product = 0x0001; |
196 | input->id.version = 0x0100; | 196 | input->id.version = 0x0100; |
197 | 197 | ||
198 | input->keycode = pdata->keycodes; | ||
199 | input->keycodesize = sizeof(pdata->keycodes[0]); | ||
200 | input->keycodemax = ARRAY_SIZE(pdata->keycodes); | ||
201 | |||
198 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); | 202 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); |
199 | if (error) { | 203 | if (error) { |
200 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 204 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
201 | goto err4; | 205 | goto err4; |
202 | } | 206 | } |
203 | 207 | ||
204 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { | 208 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) |
205 | k = pdata->keycodes[i]; | 209 | __set_bit(pdata->keycodes[i], input->keybit); |
206 | if (k) | 210 | __clear_bit(KEY_RESERVED, input->keybit); |
207 | input_set_capability(input, EV_KEY, k); | ||
208 | } | ||
209 | 211 | ||
210 | error = input_register_device(input); | 212 | error = input_register_device(input); |
211 | if (error) { | 213 | if (error) { |
@@ -221,7 +223,9 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
221 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); | 223 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); |
222 | 224 | ||
223 | device_init_wakeup(&pdev->dev, 1); | 225 | device_init_wakeup(&pdev->dev, 1); |
226 | |||
224 | return 0; | 227 | return 0; |
228 | |||
225 | err5: | 229 | err5: |
226 | free_irq(irq, pdev); | 230 | free_irq(irq, pdev); |
227 | err4: | 231 | err4: |
@@ -252,6 +256,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) | |||
252 | 256 | ||
253 | platform_set_drvdata(pdev, NULL); | 257 | platform_set_drvdata(pdev, NULL); |
254 | kfree(priv); | 258 | kfree(priv); |
259 | |||
255 | return 0; | 260 | return 0; |
256 | } | 261 | } |
257 | 262 | ||
@@ -267,11 +272,12 @@ static int sh_keysc_suspend(struct device *dev) | |||
267 | if (device_may_wakeup(dev)) { | 272 | if (device_may_wakeup(dev)) { |
268 | value |= 0x80; | 273 | value |= 0x80; |
269 | enable_irq_wake(irq); | 274 | enable_irq_wake(irq); |
270 | } | 275 | } else { |
271 | else | ||
272 | value &= ~0x80; | 276 | value &= ~0x80; |
277 | } | ||
273 | 278 | ||
274 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); | 279 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); |
280 | |||
275 | return 0; | 281 | return 0; |
276 | } | 282 | } |
277 | 283 | ||
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index 9fce6d1e29b2..e7aa935a294a 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c | |||
@@ -150,8 +150,8 @@ static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
150 | 150 | ||
151 | case EV_LED: | 151 | case EV_LED: |
152 | 152 | ||
153 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); | 153 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
154 | sunkbd->serio->write(sunkbd->serio, | 154 | serio_write(sunkbd->serio, |
155 | (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) | | 155 | (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) | |
156 | (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led)); | 156 | (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led)); |
157 | return 0; | 157 | return 0; |
@@ -161,11 +161,11 @@ static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
161 | switch (code) { | 161 | switch (code) { |
162 | 162 | ||
163 | case SND_CLICK: | 163 | case SND_CLICK: |
164 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); | 164 | serio_write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); |
165 | return 0; | 165 | return 0; |
166 | 166 | ||
167 | case SND_BELL: | 167 | case SND_BELL: |
168 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); | 168 | serio_write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); |
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | ||
@@ -183,7 +183,7 @@ static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
183 | static int sunkbd_initialize(struct sunkbd *sunkbd) | 183 | static int sunkbd_initialize(struct sunkbd *sunkbd) |
184 | { | 184 | { |
185 | sunkbd->reset = -2; | 185 | sunkbd->reset = -2; |
186 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET); | 186 | serio_write(sunkbd->serio, SUNKBD_CMD_RESET); |
187 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); | 187 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
188 | if (sunkbd->reset < 0) | 188 | if (sunkbd->reset < 0) |
189 | return -1; | 189 | return -1; |
@@ -192,7 +192,7 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) | |||
192 | 192 | ||
193 | if (sunkbd->type == 4) { /* Type 4 keyboard */ | 193 | if (sunkbd->type == 4) { /* Type 4 keyboard */ |
194 | sunkbd->layout = -2; | 194 | sunkbd->layout = -2; |
195 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT); | 195 | serio_write(sunkbd->serio, SUNKBD_CMD_LAYOUT); |
196 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4); | 196 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4); |
197 | if (sunkbd->layout < 0) return -1; | 197 | if (sunkbd->layout < 0) return -1; |
198 | if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5; | 198 | if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5; |
@@ -212,12 +212,14 @@ static void sunkbd_reinit(struct work_struct *work) | |||
212 | 212 | ||
213 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); | 213 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
214 | 214 | ||
215 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); | 215 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
216 | sunkbd->serio->write(sunkbd->serio, | 216 | serio_write(sunkbd->serio, |
217 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | | 217 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | |
218 | (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led)); | 218 | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | |
219 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); | 219 | (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | |
220 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); | 220 | !!test_bit(LED_NUML, sunkbd->dev->led)); |
221 | serio_write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); | ||
222 | serio_write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); | ||
221 | } | 223 | } |
222 | 224 | ||
223 | static void sunkbd_enable(struct sunkbd *sunkbd, int enable) | 225 | static void sunkbd_enable(struct sunkbd *sunkbd, int enable) |
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c new file mode 100644 index 000000000000..b8598ae124ee --- /dev/null +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #include <mach/w90p910_keypad.h> | ||
24 | |||
25 | /* Keypad Interface Control Registers */ | ||
26 | #define KPI_CONF 0x00 | ||
27 | #define KPI_3KCONF 0x04 | ||
28 | #define KPI_LPCONF 0x08 | ||
29 | #define KPI_STATUS 0x0C | ||
30 | |||
31 | #define IS1KEY (0x01 << 16) | ||
32 | #define INTTR (0x01 << 21) | ||
33 | #define KEY0R (0x0f << 3) | ||
34 | #define KEY0C 0x07 | ||
35 | #define DEBOUNCE_BIT 0x08 | ||
36 | #define KSIZE0 (0x01 << 16) | ||
37 | #define KSIZE1 (0x01 << 17) | ||
38 | #define KPSEL (0x01 << 19) | ||
39 | #define ENKP (0x01 << 18) | ||
40 | |||
41 | #define KGET_RAW(n) (((n) & KEY0R) >> 3) | ||
42 | #define KGET_COLUMN(n) ((n) & KEY0C) | ||
43 | |||
44 | #define W90P910_MAX_KEY_NUM (8 * 8) | ||
45 | #define W90P910_ROW_SHIFT 3 | ||
46 | |||
47 | struct w90p910_keypad { | ||
48 | const struct w90p910_keypad_platform_data *pdata; | ||
49 | struct clk *clk; | ||
50 | struct input_dev *input_dev; | ||
51 | void __iomem *mmio_base; | ||
52 | int irq; | ||
53 | unsigned short keymap[W90P910_MAX_KEY_NUM]; | ||
54 | }; | ||
55 | |||
56 | static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, | ||
57 | unsigned int status) | ||
58 | { | ||
59 | struct input_dev *input_dev = keypad->input_dev; | ||
60 | unsigned int row = KGET_RAW(status); | ||
61 | unsigned int col = KGET_COLUMN(status); | ||
62 | unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT); | ||
63 | unsigned int key = keypad->keymap[code]; | ||
64 | |||
65 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
66 | input_report_key(input_dev, key, 1); | ||
67 | input_sync(input_dev); | ||
68 | |||
69 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
70 | input_report_key(input_dev, key, 0); | ||
71 | input_sync(input_dev); | ||
72 | } | ||
73 | |||
74 | static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) | ||
75 | { | ||
76 | struct w90p910_keypad *keypad = dev_id; | ||
77 | unsigned int kstatus, val; | ||
78 | |||
79 | kstatus = __raw_readl(keypad->mmio_base + KPI_STATUS); | ||
80 | |||
81 | val = INTTR | IS1KEY; | ||
82 | |||
83 | if (kstatus & val) | ||
84 | w90p910_keypad_scan_matrix(keypad, kstatus); | ||
85 | |||
86 | return IRQ_HANDLED; | ||
87 | } | ||
88 | |||
89 | static int w90p910_keypad_open(struct input_dev *dev) | ||
90 | { | ||
91 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | ||
92 | const struct w90p910_keypad_platform_data *pdata = keypad->pdata; | ||
93 | unsigned int val, config; | ||
94 | |||
95 | /* Enable unit clock */ | ||
96 | clk_enable(keypad->clk); | ||
97 | |||
98 | val = __raw_readl(keypad->mmio_base + KPI_CONF); | ||
99 | val |= (KPSEL | ENKP); | ||
100 | val &= ~(KSIZE0 | KSIZE1); | ||
101 | |||
102 | config = pdata->prescale | (pdata->debounce << DEBOUNCE_BIT); | ||
103 | |||
104 | val |= config; | ||
105 | |||
106 | __raw_writel(val, keypad->mmio_base + KPI_CONF); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void w90p910_keypad_close(struct input_dev *dev) | ||
112 | { | ||
113 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | ||
114 | |||
115 | /* Disable clock unit */ | ||
116 | clk_disable(keypad->clk); | ||
117 | } | ||
118 | |||
119 | static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | ||
120 | { | ||
121 | const struct w90p910_keypad_platform_data *pdata = | ||
122 | pdev->dev.platform_data; | ||
123 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | ||
124 | struct w90p910_keypad *keypad; | ||
125 | struct input_dev *input_dev; | ||
126 | struct resource *res; | ||
127 | int irq; | ||
128 | int error; | ||
129 | int i; | ||
130 | |||
131 | if (!pdata) { | ||
132 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | |||
136 | irq = platform_get_irq(pdev, 0); | ||
137 | if (irq < 0) { | ||
138 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
139 | return -ENXIO; | ||
140 | } | ||
141 | |||
142 | keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); | ||
143 | input_dev = input_allocate_device(); | ||
144 | if (!keypad || !input_dev) { | ||
145 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
146 | error = -ENOMEM; | ||
147 | goto failed_free; | ||
148 | } | ||
149 | |||
150 | keypad->pdata = pdata; | ||
151 | keypad->input_dev = input_dev; | ||
152 | keypad->irq = irq; | ||
153 | |||
154 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
155 | if (res == NULL) { | ||
156 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
157 | error = -ENXIO; | ||
158 | goto failed_free; | ||
159 | } | ||
160 | |||
161 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
162 | if (res == NULL) { | ||
163 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
164 | error = -EBUSY; | ||
165 | goto failed_free; | ||
166 | } | ||
167 | |||
168 | keypad->mmio_base = ioremap(res->start, resource_size(res)); | ||
169 | if (keypad->mmio_base == NULL) { | ||
170 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
171 | error = -ENXIO; | ||
172 | goto failed_free_res; | ||
173 | } | ||
174 | |||
175 | keypad->clk = clk_get(&pdev->dev, NULL); | ||
176 | if (IS_ERR(keypad->clk)) { | ||
177 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
178 | error = PTR_ERR(keypad->clk); | ||
179 | goto failed_free_io; | ||
180 | } | ||
181 | |||
182 | /* set multi-function pin for w90p910 kpi. */ | ||
183 | mfp_set_groupi(&pdev->dev); | ||
184 | |||
185 | input_dev->name = pdev->name; | ||
186 | input_dev->id.bustype = BUS_HOST; | ||
187 | input_dev->open = w90p910_keypad_open; | ||
188 | input_dev->close = w90p910_keypad_close; | ||
189 | input_dev->dev.parent = &pdev->dev; | ||
190 | |||
191 | input_dev->keycode = keypad->keymap; | ||
192 | input_dev->keycodesize = sizeof(keypad->keymap[0]); | ||
193 | input_dev->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
194 | |||
195 | input_set_drvdata(input_dev, keypad); | ||
196 | |||
197 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
198 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
199 | |||
200 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
201 | unsigned int key = keymap_data->keymap[i]; | ||
202 | unsigned int row = KEY_ROW(key); | ||
203 | unsigned int col = KEY_COL(key); | ||
204 | unsigned short keycode = KEY_VAL(key); | ||
205 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, | ||
206 | W90P910_ROW_SHIFT); | ||
207 | |||
208 | keypad->keymap[scancode] = keycode; | ||
209 | __set_bit(keycode, input_dev->keybit); | ||
210 | } | ||
211 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
212 | |||
213 | |||
214 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, | ||
215 | IRQF_DISABLED, pdev->name, keypad); | ||
216 | if (error) { | ||
217 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
218 | goto failed_put_clk; | ||
219 | } | ||
220 | |||
221 | /* Register the input device */ | ||
222 | error = input_register_device(input_dev); | ||
223 | if (error) { | ||
224 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
225 | goto failed_free_irq; | ||
226 | } | ||
227 | |||
228 | platform_set_drvdata(pdev, keypad); | ||
229 | return 0; | ||
230 | |||
231 | failed_free_irq: | ||
232 | free_irq(irq, pdev); | ||
233 | failed_put_clk: | ||
234 | clk_put(keypad->clk); | ||
235 | failed_free_io: | ||
236 | iounmap(keypad->mmio_base); | ||
237 | failed_free_res: | ||
238 | release_mem_region(res->start, resource_size(res)); | ||
239 | failed_free: | ||
240 | input_free_device(input_dev); | ||
241 | kfree(keypad); | ||
242 | return error; | ||
243 | } | ||
244 | |||
245 | static int __devexit w90p910_keypad_remove(struct platform_device *pdev) | ||
246 | { | ||
247 | struct w90p910_keypad *keypad = platform_get_drvdata(pdev); | ||
248 | struct resource *res; | ||
249 | |||
250 | free_irq(keypad->irq, pdev); | ||
251 | |||
252 | clk_put(keypad->clk); | ||
253 | |||
254 | input_unregister_device(keypad->input_dev); | ||
255 | |||
256 | iounmap(keypad->mmio_base); | ||
257 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
258 | release_mem_region(res->start, resource_size(res)); | ||
259 | |||
260 | platform_set_drvdata(pdev, NULL); | ||
261 | kfree(keypad); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static struct platform_driver w90p910_keypad_driver = { | ||
267 | .probe = w90p910_keypad_probe, | ||
268 | .remove = __devexit_p(w90p910_keypad_remove), | ||
269 | .driver = { | ||
270 | .name = "nuc900-keypad", | ||
271 | .owner = THIS_MODULE, | ||
272 | }, | ||
273 | }; | ||
274 | |||
275 | static int __init w90p910_keypad_init(void) | ||
276 | { | ||
277 | return platform_driver_register(&w90p910_keypad_driver); | ||
278 | } | ||
279 | |||
280 | static void __exit w90p910_keypad_exit(void) | ||
281 | { | ||
282 | platform_driver_unregister(&w90p910_keypad_driver); | ||
283 | } | ||
284 | |||
285 | module_init(w90p910_keypad_init); | ||
286 | module_exit(w90p910_keypad_exit); | ||
287 | |||
288 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
289 | MODULE_DESCRIPTION("w90p910 keypad driver"); | ||
290 | MODULE_LICENSE("GPL"); | ||
291 | MODULE_ALIAS("platform:nuc900-keypad"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 1acfa3a05aad..cbe21bc96b52 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -269,4 +269,14 @@ config INPUT_DM355EVM | |||
269 | 269 | ||
270 | To compile this driver as a module, choose M here: the | 270 | To compile this driver as a module, choose M here: the |
271 | module will be called dm355evm_keys. | 271 | module will be called dm355evm_keys. |
272 | |||
273 | config INPUT_BFIN_ROTARY | ||
274 | tristate "Blackfin Rotary support" | ||
275 | depends on BF54x || BF52x | ||
276 | help | ||
277 | Say Y here if you want to use the Blackfin Rotary. | ||
278 | |||
279 | To compile this driver as a module, choose M here: the | ||
280 | module will be called bfin-rotary. | ||
281 | |||
272 | endif | 282 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 0d979fd4cd57..79c1e9a5ea31 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_INPUT_APANEL) += apanel.o | |||
8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | 8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o |
9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
11 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | ||
11 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 12 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 13 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
13 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o | 14 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o |
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c new file mode 100644 index 000000000000..690f3fafa03b --- /dev/null +++ b/drivers/input/misc/bfin_rotary.c | |||
@@ -0,0 +1,283 @@ | |||
1 | /* | ||
2 | * Rotary counter driver for Analog Devices Blackfin Processors | ||
3 | * | ||
4 | * Copyright 2008-2009 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/version.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/irq.h> | ||
13 | #include <linux/pm.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/input.h> | ||
16 | |||
17 | #include <asm/portmux.h> | ||
18 | #include <asm/bfin_rotary.h> | ||
19 | |||
20 | static const u16 per_cnt[] = { | ||
21 | P_CNT_CUD, | ||
22 | P_CNT_CDG, | ||
23 | P_CNT_CZM, | ||
24 | 0 | ||
25 | }; | ||
26 | |||
27 | struct bfin_rot { | ||
28 | struct input_dev *input; | ||
29 | int irq; | ||
30 | unsigned int up_key; | ||
31 | unsigned int down_key; | ||
32 | unsigned int button_key; | ||
33 | unsigned int rel_code; | ||
34 | unsigned short cnt_config; | ||
35 | unsigned short cnt_imask; | ||
36 | unsigned short cnt_debounce; | ||
37 | }; | ||
38 | |||
39 | static void report_key_event(struct input_dev *input, int keycode) | ||
40 | { | ||
41 | /* simulate a press-n-release */ | ||
42 | input_report_key(input, keycode, 1); | ||
43 | input_sync(input); | ||
44 | input_report_key(input, keycode, 0); | ||
45 | input_sync(input); | ||
46 | } | ||
47 | |||
48 | static void report_rotary_event(struct bfin_rot *rotary, int delta) | ||
49 | { | ||
50 | struct input_dev *input = rotary->input; | ||
51 | |||
52 | if (rotary->up_key) { | ||
53 | report_key_event(input, | ||
54 | delta > 0 ? rotary->up_key : rotary->down_key); | ||
55 | } else { | ||
56 | input_report_rel(input, rotary->rel_code, delta); | ||
57 | input_sync(input); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) | ||
62 | { | ||
63 | struct platform_device *pdev = dev_id; | ||
64 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
65 | int delta; | ||
66 | |||
67 | switch (bfin_read_CNT_STATUS()) { | ||
68 | |||
69 | case ICII: | ||
70 | break; | ||
71 | |||
72 | case UCII: | ||
73 | case DCII: | ||
74 | delta = bfin_read_CNT_COUNTER(); | ||
75 | if (delta) | ||
76 | report_rotary_event(rotary, delta); | ||
77 | break; | ||
78 | |||
79 | case CZMII: | ||
80 | report_key_event(rotary->input, rotary->button_key); | ||
81 | break; | ||
82 | |||
83 | default: | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | bfin_write_CNT_COMMAND(W1LCNT_ZERO); /* Clear COUNTER */ | ||
88 | bfin_write_CNT_STATUS(-1); /* Clear STATUS */ | ||
89 | |||
90 | return IRQ_HANDLED; | ||
91 | } | ||
92 | |||
93 | static int __devinit bfin_rotary_probe(struct platform_device *pdev) | ||
94 | { | ||
95 | struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data; | ||
96 | struct bfin_rot *rotary; | ||
97 | struct input_dev *input; | ||
98 | int error; | ||
99 | |||
100 | /* Basic validation */ | ||
101 | if ((pdata->rotary_up_key && !pdata->rotary_down_key) || | ||
102 | (!pdata->rotary_up_key && pdata->rotary_down_key)) { | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | error = peripheral_request_list(per_cnt, dev_name(&pdev->dev)); | ||
107 | if (error) { | ||
108 | dev_err(&pdev->dev, "requesting peripherals failed\n"); | ||
109 | return error; | ||
110 | } | ||
111 | |||
112 | rotary = kzalloc(sizeof(struct bfin_rot), GFP_KERNEL); | ||
113 | input = input_allocate_device(); | ||
114 | if (!rotary || !input) { | ||
115 | error = -ENOMEM; | ||
116 | goto out1; | ||
117 | } | ||
118 | |||
119 | rotary->input = input; | ||
120 | |||
121 | rotary->up_key = pdata->rotary_up_key; | ||
122 | rotary->down_key = pdata->rotary_down_key; | ||
123 | rotary->button_key = pdata->rotary_button_key; | ||
124 | rotary->rel_code = pdata->rotary_rel_code; | ||
125 | |||
126 | error = rotary->irq = platform_get_irq(pdev, 0); | ||
127 | if (error < 0) | ||
128 | goto out1; | ||
129 | |||
130 | input->name = pdev->name; | ||
131 | input->phys = "bfin-rotary/input0"; | ||
132 | input->dev.parent = &pdev->dev; | ||
133 | |||
134 | input_set_drvdata(input, rotary); | ||
135 | |||
136 | input->id.bustype = BUS_HOST; | ||
137 | input->id.vendor = 0x0001; | ||
138 | input->id.product = 0x0001; | ||
139 | input->id.version = 0x0100; | ||
140 | |||
141 | if (rotary->up_key) { | ||
142 | __set_bit(EV_KEY, input->evbit); | ||
143 | __set_bit(rotary->up_key, input->keybit); | ||
144 | __set_bit(rotary->down_key, input->keybit); | ||
145 | } else { | ||
146 | __set_bit(EV_REL, input->evbit); | ||
147 | __set_bit(rotary->rel_code, input->relbit); | ||
148 | } | ||
149 | |||
150 | if (rotary->button_key) { | ||
151 | __set_bit(EV_KEY, input->evbit); | ||
152 | __set_bit(rotary->button_key, input->keybit); | ||
153 | } | ||
154 | |||
155 | error = request_irq(rotary->irq, bfin_rotary_isr, | ||
156 | 0, dev_name(&pdev->dev), pdev); | ||
157 | if (error) { | ||
158 | dev_err(&pdev->dev, | ||
159 | "unable to claim irq %d; error %d\n", | ||
160 | rotary->irq, error); | ||
161 | goto out1; | ||
162 | } | ||
163 | |||
164 | error = input_register_device(input); | ||
165 | if (error) { | ||
166 | dev_err(&pdev->dev, | ||
167 | "unable to register input device (%d)\n", error); | ||
168 | goto out2; | ||
169 | } | ||
170 | |||
171 | if (pdata->rotary_button_key) | ||
172 | bfin_write_CNT_IMASK(CZMIE); | ||
173 | |||
174 | if (pdata->mode & ROT_DEBE) | ||
175 | bfin_write_CNT_DEBOUNCE(pdata->debounce & DPRESCALE); | ||
176 | |||
177 | if (pdata->mode) | ||
178 | bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | | ||
179 | (pdata->mode & ~CNTE)); | ||
180 | |||
181 | bfin_write_CNT_IMASK(bfin_read_CNT_IMASK() | UCIE | DCIE); | ||
182 | bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | CNTE); | ||
183 | |||
184 | platform_set_drvdata(pdev, rotary); | ||
185 | device_init_wakeup(&pdev->dev, 1); | ||
186 | |||
187 | return 0; | ||
188 | |||
189 | out2: | ||
190 | free_irq(rotary->irq, pdev); | ||
191 | out1: | ||
192 | input_free_device(input); | ||
193 | kfree(rotary); | ||
194 | peripheral_free_list(per_cnt); | ||
195 | |||
196 | return error; | ||
197 | } | ||
198 | |||
199 | static int __devexit bfin_rotary_remove(struct platform_device *pdev) | ||
200 | { | ||
201 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
202 | |||
203 | bfin_write_CNT_CONFIG(0); | ||
204 | bfin_write_CNT_IMASK(0); | ||
205 | |||
206 | free_irq(rotary->irq, pdev); | ||
207 | input_unregister_device(rotary->input); | ||
208 | peripheral_free_list(per_cnt); | ||
209 | |||
210 | kfree(rotary); | ||
211 | platform_set_drvdata(pdev, NULL); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | #ifdef CONFIG_PM | ||
217 | static int bfin_rotary_suspend(struct device *dev) | ||
218 | { | ||
219 | struct platform_device *pdev = to_platform_device(dev); | ||
220 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
221 | |||
222 | rotary->cnt_config = bfin_read_CNT_CONFIG(); | ||
223 | rotary->cnt_imask = bfin_read_CNT_IMASK(); | ||
224 | rotary->cnt_debounce = bfin_read_CNT_DEBOUNCE(); | ||
225 | |||
226 | if (device_may_wakeup(&pdev->dev)) | ||
227 | enable_irq_wake(rotary->irq); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int bfin_rotary_resume(struct device *dev) | ||
233 | { | ||
234 | struct platform_device *pdev = to_platform_device(dev); | ||
235 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
236 | |||
237 | bfin_write_CNT_DEBOUNCE(rotary->cnt_debounce); | ||
238 | bfin_write_CNT_IMASK(rotary->cnt_imask); | ||
239 | bfin_write_CNT_CONFIG(rotary->cnt_config & ~CNTE); | ||
240 | |||
241 | if (device_may_wakeup(&pdev->dev)) | ||
242 | disable_irq_wake(rotary->irq); | ||
243 | |||
244 | if (rotary->cnt_config & CNTE) | ||
245 | bfin_write_CNT_CONFIG(rotary->cnt_config); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static struct dev_pm_ops bfin_rotary_pm_ops = { | ||
251 | .suspend = bfin_rotary_suspend, | ||
252 | .resume = bfin_rotary_resume, | ||
253 | }; | ||
254 | #endif | ||
255 | |||
256 | static struct platform_driver bfin_rotary_device_driver = { | ||
257 | .probe = bfin_rotary_probe, | ||
258 | .remove = __devexit_p(bfin_rotary_remove), | ||
259 | .driver = { | ||
260 | .name = "bfin-rotary", | ||
261 | .owner = THIS_MODULE, | ||
262 | #ifdef CONFIG_PM | ||
263 | .pm = &bfin_rotary_pm_ops, | ||
264 | #endif | ||
265 | }, | ||
266 | }; | ||
267 | |||
268 | static int __init bfin_rotary_init(void) | ||
269 | { | ||
270 | return platform_driver_register(&bfin_rotary_device_driver); | ||
271 | } | ||
272 | module_init(bfin_rotary_init); | ||
273 | |||
274 | static void __exit bfin_rotary_exit(void) | ||
275 | { | ||
276 | platform_driver_unregister(&bfin_rotary_device_driver); | ||
277 | } | ||
278 | module_exit(bfin_rotary_exit); | ||
279 | |||
280 | MODULE_LICENSE("GPL"); | ||
281 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
282 | MODULE_DESCRIPTION("Rotary Counter driver for Blackfin Processors"); | ||
283 | MODULE_ALIAS("platform:bfin-rotary"); | ||
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index d114d3a9e1e9..ee73d7219c92 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
@@ -116,7 +116,7 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | bdev->poll_dev = poll_dev; | 118 | bdev->poll_dev = poll_dev; |
119 | bdev->reg = ioremap(res->start, res->end - res->start + 1); | 119 | bdev->reg = ioremap(res->start, resource_size(res)); |
120 | dev_set_drvdata(&pdev->dev, bdev); | 120 | dev_set_drvdata(&pdev->dev, bdev); |
121 | 121 | ||
122 | error = input_register_polled_device(poll_dev); | 122 | error = input_register_polled_device(poll_dev); |
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index a63315ce4a6c..0918acae584a 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c | |||
@@ -23,30 +23,16 @@ | |||
23 | * pressed, or its autorepeat kicks in, an event is sent. This driver | 23 | * pressed, or its autorepeat kicks in, an event is sent. This driver |
24 | * read those events from the small (32 event) queue and reports them. | 24 | * read those events from the small (32 event) queue and reports them. |
25 | * | 25 | * |
26 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
27 | * in Linux sleep, we need to cons up a kind of threaded IRQ handler | ||
28 | * using a work_struct. The IRQ is active low, but we use it through | ||
29 | * the GPIO controller so we can trigger on falling edges. | ||
30 | * | ||
31 | * Note that physically there can only be one of these devices. | 26 | * Note that physically there can only be one of these devices. |
32 | * | 27 | * |
33 | * This driver was tested with firmware revision A4. | 28 | * This driver was tested with firmware revision A4. |
34 | */ | 29 | */ |
35 | struct dm355evm_keys { | 30 | struct dm355evm_keys { |
36 | struct work_struct work; | ||
37 | struct input_dev *input; | 31 | struct input_dev *input; |
38 | struct device *dev; | 32 | struct device *dev; |
39 | int irq; | 33 | int irq; |
40 | }; | 34 | }; |
41 | 35 | ||
42 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
43 | { | ||
44 | struct dm355evm_keys *keys = _keys; | ||
45 | |||
46 | schedule_work(&keys->work); | ||
47 | return IRQ_HANDLED; | ||
48 | } | ||
49 | |||
50 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ | 36 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ |
51 | static struct { | 37 | static struct { |
52 | u16 event; | 38 | u16 event; |
@@ -110,13 +96,12 @@ static struct { | |||
110 | { 0x3169, KEY_PAUSE, }, | 96 | { 0x3169, KEY_PAUSE, }, |
111 | }; | 97 | }; |
112 | 98 | ||
113 | static void dm355evm_keys_work(struct work_struct *work) | 99 | /* runs in an IRQ thread -- can (and will!) sleep */ |
100 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
114 | { | 101 | { |
115 | struct dm355evm_keys *keys; | 102 | struct dm355evm_keys *keys = _keys; |
116 | int status; | 103 | int status; |
117 | 104 | ||
118 | keys = container_of(work, struct dm355evm_keys, work); | ||
119 | |||
120 | /* For simplicity we ignore INPUT_COUNT and just read | 105 | /* For simplicity we ignore INPUT_COUNT and just read |
121 | * events until we get the "queue empty" indicator. | 106 | * events until we get the "queue empty" indicator. |
122 | * Reading INPUT_LOW decrements the count. | 107 | * Reading INPUT_LOW decrements the count. |
@@ -183,6 +168,19 @@ static void dm355evm_keys_work(struct work_struct *work) | |||
183 | input_report_key(keys->input, keycode, 0); | 168 | input_report_key(keys->input, keycode, 0); |
184 | input_sync(keys->input); | 169 | input_sync(keys->input); |
185 | } | 170 | } |
171 | return IRQ_HANDLED; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
176 | * in Linux sleep, we use a threaded IRQ handler. The IRQ itself is | ||
177 | * active low, but we go through the GPIO controller so we can trigger | ||
178 | * on falling edges and not worry about enabling/disabling the IRQ in | ||
179 | * the keypress handling path. | ||
180 | */ | ||
181 | static irqreturn_t dm355evm_keys_hardirq(int irq, void *_keys) | ||
182 | { | ||
183 | return IRQ_WAKE_THREAD; | ||
186 | } | 184 | } |
187 | 185 | ||
188 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | 186 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) |
@@ -233,7 +231,6 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
233 | 231 | ||
234 | keys->dev = &pdev->dev; | 232 | keys->dev = &pdev->dev; |
235 | keys->input = input; | 233 | keys->input = input; |
236 | INIT_WORK(&keys->work, dm355evm_keys_work); | ||
237 | 234 | ||
238 | /* set up "threaded IRQ handler" */ | 235 | /* set up "threaded IRQ handler" */ |
239 | status = platform_get_irq(pdev, 0); | 236 | status = platform_get_irq(pdev, 0); |
@@ -260,9 +257,10 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
260 | 257 | ||
261 | /* REVISIT: flush the event queue? */ | 258 | /* REVISIT: flush the event queue? */ |
262 | 259 | ||
263 | status = request_irq(keys->irq, dm355evm_keys_irq, | 260 | status = request_threaded_irq(keys->irq, |
264 | IRQF_TRIGGER_FALLING, | 261 | dm355evm_keys_hardirq, dm355evm_keys_irq, |
265 | dev_name(&pdev->dev), keys); | 262 | IRQF_TRIGGER_FALLING, |
263 | dev_name(&pdev->dev), keys); | ||
266 | if (status < 0) | 264 | if (status < 0) |
267 | goto fail1; | 265 | goto fail1; |
268 | 266 | ||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 27ee976eb54c..ebb08cfe2731 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -243,9 +243,9 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | |||
243 | #define FE_UNTESTED 0x80 | 243 | #define FE_UNTESTED 0x80 |
244 | 244 | ||
245 | static struct key_entry *keymap; /* = NULL; Current key map */ | 245 | static struct key_entry *keymap; /* = NULL; Current key map */ |
246 | static int have_wifi; | 246 | static bool have_wifi; |
247 | static int have_bluetooth; | 247 | static bool have_bluetooth; |
248 | static int have_leds; | 248 | static int leds_present; /* bitmask of leds present */ |
249 | 249 | ||
250 | static int __init dmi_matched(const struct dmi_system_id *dmi) | 250 | static int __init dmi_matched(const struct dmi_system_id *dmi) |
251 | { | 251 | { |
@@ -254,11 +254,11 @@ static int __init dmi_matched(const struct dmi_system_id *dmi) | |||
254 | keymap = dmi->driver_data; | 254 | keymap = dmi->driver_data; |
255 | for (key = keymap; key->type != KE_END; key++) { | 255 | for (key = keymap; key->type != KE_END; key++) { |
256 | if (key->type == KE_WIFI) | 256 | if (key->type == KE_WIFI) |
257 | have_wifi = 1; | 257 | have_wifi = true; |
258 | else if (key->type == KE_BLUETOOTH) | 258 | else if (key->type == KE_BLUETOOTH) |
259 | have_bluetooth = 1; | 259 | have_bluetooth = true; |
260 | } | 260 | } |
261 | have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED); | 261 | leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED); |
262 | 262 | ||
263 | return 1; | 263 | return 1; |
264 | } | 264 | } |
@@ -1009,8 +1009,8 @@ static int __init select_keymap(void) | |||
1009 | 1009 | ||
1010 | static struct input_polled_dev *wistron_idev; | 1010 | static struct input_polled_dev *wistron_idev; |
1011 | static unsigned long jiffies_last_press; | 1011 | static unsigned long jiffies_last_press; |
1012 | static int wifi_enabled; | 1012 | static bool wifi_enabled; |
1013 | static int bluetooth_enabled; | 1013 | static bool bluetooth_enabled; |
1014 | 1014 | ||
1015 | static void report_key(struct input_dev *dev, unsigned int keycode) | 1015 | static void report_key(struct input_dev *dev, unsigned int keycode) |
1016 | { | 1016 | { |
@@ -1053,24 +1053,24 @@ static struct led_classdev wistron_wifi_led = { | |||
1053 | 1053 | ||
1054 | static void __devinit wistron_led_init(struct device *parent) | 1054 | static void __devinit wistron_led_init(struct device *parent) |
1055 | { | 1055 | { |
1056 | if (have_leds & FE_WIFI_LED) { | 1056 | if (leds_present & FE_WIFI_LED) { |
1057 | u16 wifi = bios_get_default_setting(WIFI); | 1057 | u16 wifi = bios_get_default_setting(WIFI); |
1058 | if (wifi & 1) { | 1058 | if (wifi & 1) { |
1059 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; | 1059 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; |
1060 | if (led_classdev_register(parent, &wistron_wifi_led)) | 1060 | if (led_classdev_register(parent, &wistron_wifi_led)) |
1061 | have_leds &= ~FE_WIFI_LED; | 1061 | leds_present &= ~FE_WIFI_LED; |
1062 | else | 1062 | else |
1063 | bios_set_state(WIFI, wistron_wifi_led.brightness); | 1063 | bios_set_state(WIFI, wistron_wifi_led.brightness); |
1064 | 1064 | ||
1065 | } else | 1065 | } else |
1066 | have_leds &= ~FE_WIFI_LED; | 1066 | leds_present &= ~FE_WIFI_LED; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | if (have_leds & FE_MAIL_LED) { | 1069 | if (leds_present & FE_MAIL_LED) { |
1070 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ | 1070 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ |
1071 | wistron_mail_led.brightness = LED_OFF; | 1071 | wistron_mail_led.brightness = LED_OFF; |
1072 | if (led_classdev_register(parent, &wistron_mail_led)) | 1072 | if (led_classdev_register(parent, &wistron_mail_led)) |
1073 | have_leds &= ~FE_MAIL_LED; | 1073 | leds_present &= ~FE_MAIL_LED; |
1074 | else | 1074 | else |
1075 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); | 1075 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); |
1076 | } | 1076 | } |
@@ -1078,28 +1078,28 @@ static void __devinit wistron_led_init(struct device *parent) | |||
1078 | 1078 | ||
1079 | static void __devexit wistron_led_remove(void) | 1079 | static void __devexit wistron_led_remove(void) |
1080 | { | 1080 | { |
1081 | if (have_leds & FE_MAIL_LED) | 1081 | if (leds_present & FE_MAIL_LED) |
1082 | led_classdev_unregister(&wistron_mail_led); | 1082 | led_classdev_unregister(&wistron_mail_led); |
1083 | 1083 | ||
1084 | if (have_leds & FE_WIFI_LED) | 1084 | if (leds_present & FE_WIFI_LED) |
1085 | led_classdev_unregister(&wistron_wifi_led); | 1085 | led_classdev_unregister(&wistron_wifi_led); |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | static inline void wistron_led_suspend(void) | 1088 | static inline void wistron_led_suspend(void) |
1089 | { | 1089 | { |
1090 | if (have_leds & FE_MAIL_LED) | 1090 | if (leds_present & FE_MAIL_LED) |
1091 | led_classdev_suspend(&wistron_mail_led); | 1091 | led_classdev_suspend(&wistron_mail_led); |
1092 | 1092 | ||
1093 | if (have_leds & FE_WIFI_LED) | 1093 | if (leds_present & FE_WIFI_LED) |
1094 | led_classdev_suspend(&wistron_wifi_led); | 1094 | led_classdev_suspend(&wistron_wifi_led); |
1095 | } | 1095 | } |
1096 | 1096 | ||
1097 | static inline void wistron_led_resume(void) | 1097 | static inline void wistron_led_resume(void) |
1098 | { | 1098 | { |
1099 | if (have_leds & FE_MAIL_LED) | 1099 | if (leds_present & FE_MAIL_LED) |
1100 | led_classdev_resume(&wistron_mail_led); | 1100 | led_classdev_resume(&wistron_mail_led); |
1101 | 1101 | ||
1102 | if (have_leds & FE_WIFI_LED) | 1102 | if (leds_present & FE_WIFI_LED) |
1103 | led_classdev_resume(&wistron_wifi_led); | 1103 | led_classdev_resume(&wistron_wifi_led); |
1104 | } | 1104 | } |
1105 | 1105 | ||
@@ -1312,7 +1312,7 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1312 | if (have_wifi) { | 1312 | if (have_wifi) { |
1313 | u16 wifi = bios_get_default_setting(WIFI); | 1313 | u16 wifi = bios_get_default_setting(WIFI); |
1314 | if (wifi & 1) | 1314 | if (wifi & 1) |
1315 | wifi_enabled = (wifi & 2) ? 1 : 0; | 1315 | wifi_enabled = wifi & 2; |
1316 | else | 1316 | else |
1317 | have_wifi = 0; | 1317 | have_wifi = 0; |
1318 | 1318 | ||
@@ -1323,15 +1323,16 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1323 | if (have_bluetooth) { | 1323 | if (have_bluetooth) { |
1324 | u16 bt = bios_get_default_setting(BLUETOOTH); | 1324 | u16 bt = bios_get_default_setting(BLUETOOTH); |
1325 | if (bt & 1) | 1325 | if (bt & 1) |
1326 | bluetooth_enabled = (bt & 2) ? 1 : 0; | 1326 | bluetooth_enabled = bt & 2; |
1327 | else | 1327 | else |
1328 | have_bluetooth = 0; | 1328 | have_bluetooth = false; |
1329 | 1329 | ||
1330 | if (have_bluetooth) | 1330 | if (have_bluetooth) |
1331 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1331 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1332 | } | 1332 | } |
1333 | 1333 | ||
1334 | wistron_led_init(&dev->dev); | 1334 | wistron_led_init(&dev->dev); |
1335 | |||
1335 | err = setup_input_dev(); | 1336 | err = setup_input_dev(); |
1336 | if (err) { | 1337 | if (err) { |
1337 | bios_detach(); | 1338 | bios_detach(); |
@@ -1352,7 +1353,7 @@ static int __devexit wistron_remove(struct platform_device *dev) | |||
1352 | } | 1353 | } |
1353 | 1354 | ||
1354 | #ifdef CONFIG_PM | 1355 | #ifdef CONFIG_PM |
1355 | static int wistron_suspend(struct platform_device *dev, pm_message_t state) | 1356 | static int wistron_suspend(struct device *dev) |
1356 | { | 1357 | { |
1357 | if (have_wifi) | 1358 | if (have_wifi) |
1358 | bios_set_state(WIFI, 0); | 1359 | bios_set_state(WIFI, 0); |
@@ -1361,10 +1362,11 @@ static int wistron_suspend(struct platform_device *dev, pm_message_t state) | |||
1361 | bios_set_state(BLUETOOTH, 0); | 1362 | bios_set_state(BLUETOOTH, 0); |
1362 | 1363 | ||
1363 | wistron_led_suspend(); | 1364 | wistron_led_suspend(); |
1365 | |||
1364 | return 0; | 1366 | return 0; |
1365 | } | 1367 | } |
1366 | 1368 | ||
1367 | static int wistron_resume(struct platform_device *dev) | 1369 | static int wistron_resume(struct device *dev) |
1368 | { | 1370 | { |
1369 | if (have_wifi) | 1371 | if (have_wifi) |
1370 | bios_set_state(WIFI, wifi_enabled); | 1372 | bios_set_state(WIFI, wifi_enabled); |
@@ -1373,24 +1375,30 @@ static int wistron_resume(struct platform_device *dev) | |||
1373 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1375 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1374 | 1376 | ||
1375 | wistron_led_resume(); | 1377 | wistron_led_resume(); |
1378 | |||
1376 | poll_bios(true); | 1379 | poll_bios(true); |
1377 | 1380 | ||
1378 | return 0; | 1381 | return 0; |
1379 | } | 1382 | } |
1380 | #else | 1383 | |
1381 | #define wistron_suspend NULL | 1384 | static const struct dev_pm_ops wistron_pm_ops = { |
1382 | #define wistron_resume NULL | 1385 | .suspend = wistron_suspend, |
1386 | .resume = wistron_resume, | ||
1387 | .poweroff = wistron_suspend, | ||
1388 | .restore = wistron_resume, | ||
1389 | }; | ||
1383 | #endif | 1390 | #endif |
1384 | 1391 | ||
1385 | static struct platform_driver wistron_driver = { | 1392 | static struct platform_driver wistron_driver = { |
1386 | .driver = { | 1393 | .driver = { |
1387 | .name = "wistron-bios", | 1394 | .name = "wistron-bios", |
1388 | .owner = THIS_MODULE, | 1395 | .owner = THIS_MODULE, |
1396 | #if CONFIG_PM | ||
1397 | .pm = &wistron_pm_ops, | ||
1398 | #endif | ||
1389 | }, | 1399 | }, |
1390 | .probe = wistron_probe, | 1400 | .probe = wistron_probe, |
1391 | .remove = __devexit_p(wistron_remove), | 1401 | .remove = __devexit_p(wistron_remove), |
1392 | .suspend = wistron_suspend, | ||
1393 | .resume = wistron_resume, | ||
1394 | }; | 1402 | }; |
1395 | 1403 | ||
1396 | static int __init wb_module_init(void) | 1404 | static int __init wb_module_init(void) |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 8a2c5b14c8d8..3feeb3af8abd 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -107,6 +107,14 @@ config MOUSE_PS2_ELANTECH | |||
107 | entries. For further information, | 107 | entries. For further information, |
108 | see <file:Documentation/input/elantech.txt>. | 108 | see <file:Documentation/input/elantech.txt>. |
109 | 109 | ||
110 | config MOUSE_PS2_SENTELIC | ||
111 | bool "Sentelic Finger Sensing Pad PS/2 protocol extension" | ||
112 | depends on MOUSE_PS2 | ||
113 | help | ||
114 | Say Y here if you have a laptop (such as MSI WIND Netbook) | ||
115 | with Sentelic Finger Sensing Pad touchpad. | ||
116 | |||
117 | If unsure, say N. | ||
110 | 118 | ||
111 | config MOUSE_PS2_TOUCHKIT | 119 | config MOUSE_PS2_TOUCHKIT |
112 | bool "eGalax TouchKit PS/2 protocol extension" | 120 | bool "eGalax TouchKit PS/2 protocol extension" |
@@ -262,14 +270,6 @@ config MOUSE_VSXXXAA | |||
262 | described in the source file). This driver also works with the | 270 | described in the source file). This driver also works with the |
263 | digitizer (VSXXX-AB) DEC produced. | 271 | digitizer (VSXXX-AB) DEC produced. |
264 | 272 | ||
265 | config MOUSE_HIL | ||
266 | tristate "HIL pointers (mice etc)." | ||
267 | depends on GSC || HP300 | ||
268 | select HP_SDC | ||
269 | select HIL_MLC | ||
270 | help | ||
271 | Say Y here to support HIL pointers. | ||
272 | |||
273 | config MOUSE_GPIO | 273 | config MOUSE_GPIO |
274 | tristate "GPIO mouse" | 274 | tristate "GPIO mouse" |
275 | depends on GENERIC_GPIO | 275 | depends on GENERIC_GPIO |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 010f265ec152..570c84a4a654 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -9,7 +9,6 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o | |||
9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | 9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o |
10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o | 10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o |
11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | 11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o |
12 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | ||
13 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 12 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
14 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o | 13 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
15 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o | 14 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o |
@@ -28,5 +27,6 @@ psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o | |||
28 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o | 27 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o |
29 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o | 28 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o |
30 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o | 29 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o |
30 | psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o | ||
31 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o | 31 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o |
32 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o | 32 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o |
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index a1ad2f1a7bb3..f5aa035774d9 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -369,12 +369,46 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | |||
369 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, | 369 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, |
370 | hgpk_show_powered, hgpk_set_powered, 0); | 370 | hgpk_show_powered, hgpk_set_powered, 0); |
371 | 371 | ||
372 | static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, | ||
373 | void *data, char *buf) | ||
374 | { | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | |||
378 | static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data, | ||
379 | const char *buf, size_t count) | ||
380 | { | ||
381 | struct hgpk_data *priv = psmouse->private; | ||
382 | unsigned long value; | ||
383 | int err; | ||
384 | |||
385 | err = strict_strtoul(buf, 10, &value); | ||
386 | if (err || value != 1) | ||
387 | return -EINVAL; | ||
388 | |||
389 | /* | ||
390 | * We queue work instead of doing recalibration right here | ||
391 | * to avoid adding locking to to hgpk_force_recalibrate() | ||
392 | * since workqueue provides serialization. | ||
393 | */ | ||
394 | psmouse_queue_work(psmouse, &priv->recalib_wq, 0); | ||
395 | return count; | ||
396 | } | ||
397 | |||
398 | __PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL, | ||
399 | hgpk_trigger_recal_show, hgpk_trigger_recal, 0); | ||
400 | |||
372 | static void hgpk_disconnect(struct psmouse *psmouse) | 401 | static void hgpk_disconnect(struct psmouse *psmouse) |
373 | { | 402 | { |
374 | struct hgpk_data *priv = psmouse->private; | 403 | struct hgpk_data *priv = psmouse->private; |
375 | 404 | ||
376 | device_remove_file(&psmouse->ps2dev.serio->dev, | 405 | device_remove_file(&psmouse->ps2dev.serio->dev, |
377 | &psmouse_attr_powered.dattr); | 406 | &psmouse_attr_powered.dattr); |
407 | |||
408 | if (psmouse->model >= HGPK_MODEL_C) | ||
409 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
410 | &psmouse_attr_recalibrate.dattr); | ||
411 | |||
378 | psmouse_reset(psmouse); | 412 | psmouse_reset(psmouse); |
379 | kfree(priv); | 413 | kfree(priv); |
380 | } | 414 | } |
@@ -423,10 +457,25 @@ static int hgpk_register(struct psmouse *psmouse) | |||
423 | 457 | ||
424 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 458 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
425 | &psmouse_attr_powered.dattr); | 459 | &psmouse_attr_powered.dattr); |
426 | if (err) | 460 | if (err) { |
427 | hgpk_err(psmouse, "Failed to create sysfs attribute\n"); | 461 | hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n"); |
462 | return err; | ||
463 | } | ||
428 | 464 | ||
429 | return err; | 465 | /* C-series touchpads added the recalibrate command */ |
466 | if (psmouse->model >= HGPK_MODEL_C) { | ||
467 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
468 | &psmouse_attr_recalibrate.dattr); | ||
469 | if (err) { | ||
470 | hgpk_err(psmouse, | ||
471 | "Failed creating 'recalibrate' sysfs node\n"); | ||
472 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
473 | &psmouse_attr_powered.dattr); | ||
474 | return err; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | return 0; | ||
430 | } | 479 | } |
431 | 480 | ||
432 | int hgpk_init(struct psmouse *psmouse) | 481 | int hgpk_init(struct psmouse *psmouse) |
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c deleted file mode 100644 index 3263ce083bf0..000000000000 --- a/drivers/input/mouse/hil_ptr.c +++ /dev/null | |||
@@ -1,447 +0,0 @@ | |||
1 | /* | ||
2 | * Generic linux-input device driver for axis-bearing devices | ||
3 | * | ||
4 | * Copyright (c) 2001 Brian S. Julin | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions, and the following disclaimer, | ||
12 | * without modification. | ||
13 | * 2. The name of the author may not be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * Alternatively, this software may be distributed under the terms of the | ||
17 | * GNU General Public License ("GPL"). | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * | ||
29 | * References: | ||
30 | * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #include <linux/hil.h> | ||
35 | #include <linux/input.h> | ||
36 | #include <linux/serio.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/pci_ids.h> | ||
42 | |||
43 | #define PREFIX "HIL PTR: " | ||
44 | #define HIL_GENERIC_NAME "HIL pointer device" | ||
45 | |||
46 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | ||
47 | MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); | ||
48 | MODULE_LICENSE("Dual BSD/GPL"); | ||
49 | MODULE_ALIAS("serio:ty03pr25id0Fex*"); | ||
50 | |||
51 | #define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */ | ||
52 | #undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */ | ||
53 | |||
54 | |||
55 | #define HIL_PTR_MAX_LENGTH 16 | ||
56 | |||
57 | struct hil_ptr { | ||
58 | struct input_dev *dev; | ||
59 | struct serio *serio; | ||
60 | |||
61 | /* Input buffer and index for packets from HIL bus. */ | ||
62 | hil_packet data[HIL_PTR_MAX_LENGTH]; | ||
63 | int idx4; /* four counts per packet */ | ||
64 | |||
65 | /* Raw device info records from HIL bus, see hil.h for fields. */ | ||
66 | char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */ | ||
67 | char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */ | ||
68 | char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */ | ||
69 | char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */ | ||
70 | |||
71 | /* Extra device details not contained in struct input_dev. */ | ||
72 | unsigned int nbtn, naxes; | ||
73 | unsigned int btnmap[7]; | ||
74 | |||
75 | /* Something to sleep around with. */ | ||
76 | struct semaphore sem; | ||
77 | }; | ||
78 | |||
79 | /* Process a complete packet after transfer from the HIL */ | ||
80 | static void hil_ptr_process_record(struct hil_ptr *ptr) | ||
81 | { | ||
82 | struct input_dev *dev = ptr->dev; | ||
83 | hil_packet *data = ptr->data; | ||
84 | hil_packet p; | ||
85 | int idx, i, cnt, laxis; | ||
86 | int ax16, absdev; | ||
87 | |||
88 | idx = ptr->idx4/4; | ||
89 | p = data[idx - 1]; | ||
90 | |||
91 | if ((p & ~HIL_CMDCT_POL) == | ||
92 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) | ||
93 | goto report; | ||
94 | if ((p & ~HIL_CMDCT_RPL) == | ||
95 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) | ||
96 | goto report; | ||
97 | |||
98 | /* Not a poll response. See if we are loading config records. */ | ||
99 | switch (p & HIL_PKT_DATA_MASK) { | ||
100 | case HIL_CMD_IDD: | ||
101 | for (i = 0; i < idx; i++) | ||
102 | ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
103 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
104 | ptr->idd[i] = 0; | ||
105 | break; | ||
106 | |||
107 | case HIL_CMD_RSC: | ||
108 | for (i = 0; i < idx; i++) | ||
109 | ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
110 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
111 | ptr->rsc[i] = 0; | ||
112 | break; | ||
113 | |||
114 | case HIL_CMD_EXD: | ||
115 | for (i = 0; i < idx; i++) | ||
116 | ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
117 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
118 | ptr->exd[i] = 0; | ||
119 | break; | ||
120 | |||
121 | case HIL_CMD_RNM: | ||
122 | for (i = 0; i < idx; i++) | ||
123 | ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
124 | for (; i < HIL_PTR_MAX_LENGTH + 1; i++) | ||
125 | ptr->rnm[i] = 0; | ||
126 | break; | ||
127 | |||
128 | default: | ||
129 | /* These occur when device isn't present */ | ||
130 | if (p == (HIL_ERR_INT | HIL_PKT_CMD)) | ||
131 | break; | ||
132 | /* Anything else we'd like to know about. */ | ||
133 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); | ||
134 | break; | ||
135 | } | ||
136 | goto out; | ||
137 | |||
138 | report: | ||
139 | if ((p & HIL_CMDCT_POL) != idx - 1) { | ||
140 | printk(KERN_WARNING PREFIX | ||
141 | "Malformed poll packet %x (idx = %i)\n", p, idx); | ||
142 | goto out; | ||
143 | } | ||
144 | |||
145 | i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0; | ||
146 | laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK; | ||
147 | laxis += i; | ||
148 | |||
149 | ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ | ||
150 | absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; | ||
151 | |||
152 | for (cnt = 1; i < laxis; i++) { | ||
153 | unsigned int lo,hi,val; | ||
154 | lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; | ||
155 | hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; | ||
156 | if (absdev) { | ||
157 | val = lo + (hi<<8); | ||
158 | #ifdef TABLET_AUTOADJUST | ||
159 | if (val < dev->absmin[ABS_X + i]) | ||
160 | dev->absmin[ABS_X + i] = val; | ||
161 | if (val > dev->absmax[ABS_X + i]) | ||
162 | dev->absmax[ABS_X + i] = val; | ||
163 | #endif | ||
164 | if (i%3) val = dev->absmax[ABS_X + i] - val; | ||
165 | input_report_abs(dev, ABS_X + i, val); | ||
166 | } else { | ||
167 | val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); | ||
168 | if (i%3) | ||
169 | val *= -1; | ||
170 | input_report_rel(dev, REL_X + i, val); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | while (cnt < idx - 1) { | ||
175 | unsigned int btn; | ||
176 | int up; | ||
177 | btn = ptr->data[cnt++]; | ||
178 | up = btn & 1; | ||
179 | btn &= 0xfe; | ||
180 | if (btn == 0x8e) | ||
181 | continue; /* TODO: proximity == touch? */ | ||
182 | else | ||
183 | if ((btn > 0x8c) || (btn < 0x80)) | ||
184 | continue; | ||
185 | btn = (btn - 0x80) >> 1; | ||
186 | btn = ptr->btnmap[btn]; | ||
187 | input_report_key(dev, btn, !up); | ||
188 | } | ||
189 | input_sync(dev); | ||
190 | out: | ||
191 | ptr->idx4 = 0; | ||
192 | up(&ptr->sem); | ||
193 | } | ||
194 | |||
195 | static void hil_ptr_process_err(struct hil_ptr *ptr) | ||
196 | { | ||
197 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); | ||
198 | ptr->idx4 = 0; | ||
199 | up(&ptr->sem); | ||
200 | } | ||
201 | |||
202 | static irqreturn_t hil_ptr_interrupt(struct serio *serio, | ||
203 | unsigned char data, unsigned int flags) | ||
204 | { | ||
205 | struct hil_ptr *ptr; | ||
206 | hil_packet packet; | ||
207 | int idx; | ||
208 | |||
209 | ptr = serio_get_drvdata(serio); | ||
210 | BUG_ON(ptr == NULL); | ||
211 | |||
212 | if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) { | ||
213 | hil_ptr_process_err(ptr); | ||
214 | return IRQ_HANDLED; | ||
215 | } | ||
216 | idx = ptr->idx4/4; | ||
217 | if (!(ptr->idx4 % 4)) | ||
218 | ptr->data[idx] = 0; | ||
219 | packet = ptr->data[idx]; | ||
220 | packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8); | ||
221 | ptr->data[idx] = packet; | ||
222 | |||
223 | /* Records of N 4-byte hil_packets must terminate with a command. */ | ||
224 | if ((++(ptr->idx4)) % 4) | ||
225 | return IRQ_HANDLED; | ||
226 | if ((packet & 0xffff0000) != HIL_ERR_INT) { | ||
227 | hil_ptr_process_err(ptr); | ||
228 | return IRQ_HANDLED; | ||
229 | } | ||
230 | if (packet & HIL_PKT_CMD) | ||
231 | hil_ptr_process_record(ptr); | ||
232 | |||
233 | return IRQ_HANDLED; | ||
234 | } | ||
235 | |||
236 | static void hil_ptr_disconnect(struct serio *serio) | ||
237 | { | ||
238 | struct hil_ptr *ptr; | ||
239 | |||
240 | ptr = serio_get_drvdata(serio); | ||
241 | BUG_ON(ptr == NULL); | ||
242 | |||
243 | serio_close(serio); | ||
244 | input_unregister_device(ptr->dev); | ||
245 | kfree(ptr); | ||
246 | } | ||
247 | |||
248 | static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) | ||
249 | { | ||
250 | struct hil_ptr *ptr; | ||
251 | const char *txt; | ||
252 | unsigned int i, naxsets, btntype; | ||
253 | uint8_t did, *idd; | ||
254 | int error; | ||
255 | |||
256 | ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL); | ||
257 | if (!ptr) | ||
258 | return -ENOMEM; | ||
259 | |||
260 | ptr->dev = input_allocate_device(); | ||
261 | if (!ptr->dev) { | ||
262 | error = -ENOMEM; | ||
263 | goto bail0; | ||
264 | } | ||
265 | |||
266 | error = serio_open(serio, driver); | ||
267 | if (error) | ||
268 | goto bail1; | ||
269 | |||
270 | serio_set_drvdata(serio, ptr); | ||
271 | ptr->serio = serio; | ||
272 | |||
273 | init_MUTEX_LOCKED(&ptr->sem); | ||
274 | |||
275 | /* Get device info. MLC driver supplies devid/status/etc. */ | ||
276 | serio->write(serio, 0); | ||
277 | serio->write(serio, 0); | ||
278 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
279 | serio->write(serio, HIL_CMD_IDD); | ||
280 | down(&ptr->sem); | ||
281 | |||
282 | serio->write(serio, 0); | ||
283 | serio->write(serio, 0); | ||
284 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
285 | serio->write(serio, HIL_CMD_RSC); | ||
286 | down(&ptr->sem); | ||
287 | |||
288 | serio->write(serio, 0); | ||
289 | serio->write(serio, 0); | ||
290 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
291 | serio->write(serio, HIL_CMD_RNM); | ||
292 | down(&ptr->sem); | ||
293 | |||
294 | serio->write(serio, 0); | ||
295 | serio->write(serio, 0); | ||
296 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
297 | serio->write(serio, HIL_CMD_EXD); | ||
298 | down(&ptr->sem); | ||
299 | |||
300 | up(&ptr->sem); | ||
301 | |||
302 | did = ptr->idd[0]; | ||
303 | idd = ptr->idd + 1; | ||
304 | txt = "unknown"; | ||
305 | |||
306 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { | ||
307 | ptr->dev->evbit[0] = BIT_MASK(EV_REL); | ||
308 | txt = "relative"; | ||
309 | } | ||
310 | |||
311 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) { | ||
312 | ptr->dev->evbit[0] = BIT_MASK(EV_ABS); | ||
313 | txt = "absolute"; | ||
314 | } | ||
315 | |||
316 | if (!ptr->dev->evbit[0]) { | ||
317 | error = -ENODEV; | ||
318 | goto bail2; | ||
319 | } | ||
320 | |||
321 | ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); | ||
322 | if (ptr->nbtn) | ||
323 | ptr->dev->evbit[0] |= BIT_MASK(EV_KEY); | ||
324 | |||
325 | naxsets = HIL_IDD_NUM_AXSETS(*idd); | ||
326 | ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); | ||
327 | |||
328 | printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n", | ||
329 | did, txt); | ||
330 | printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", | ||
331 | ptr->nbtn, naxsets, ptr->naxes); | ||
332 | |||
333 | btntype = BTN_MISC; | ||
334 | if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) | ||
335 | #ifdef TABLET_SIMULATES_MOUSE | ||
336 | btntype = BTN_TOUCH; | ||
337 | #else | ||
338 | btntype = BTN_DIGI; | ||
339 | #endif | ||
340 | if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) | ||
341 | btntype = BTN_TOUCH; | ||
342 | |||
343 | if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) | ||
344 | btntype = BTN_MOUSE; | ||
345 | |||
346 | for (i = 0; i < ptr->nbtn; i++) { | ||
347 | set_bit(btntype | i, ptr->dev->keybit); | ||
348 | ptr->btnmap[i] = btntype | i; | ||
349 | } | ||
350 | |||
351 | if (btntype == BTN_MOUSE) { | ||
352 | /* Swap buttons 2 and 3 */ | ||
353 | ptr->btnmap[1] = BTN_MIDDLE; | ||
354 | ptr->btnmap[2] = BTN_RIGHT; | ||
355 | } | ||
356 | |||
357 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { | ||
358 | for (i = 0; i < ptr->naxes; i++) | ||
359 | set_bit(REL_X + i, ptr->dev->relbit); | ||
360 | for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) | ||
361 | set_bit(REL_X + i, ptr->dev->relbit); | ||
362 | } else { | ||
363 | for (i = 0; i < ptr->naxes; i++) { | ||
364 | set_bit(ABS_X + i, ptr->dev->absbit); | ||
365 | ptr->dev->absmin[ABS_X + i] = 0; | ||
366 | ptr->dev->absmax[ABS_X + i] = | ||
367 | HIL_IDD_AXIS_MAX((ptr->idd + 1), i); | ||
368 | } | ||
369 | for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { | ||
370 | set_bit(ABS_X + i, ptr->dev->absbit); | ||
371 | ptr->dev->absmin[ABS_X + i] = 0; | ||
372 | ptr->dev->absmax[ABS_X + i] = | ||
373 | HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3)); | ||
374 | } | ||
375 | #ifdef TABLET_AUTOADJUST | ||
376 | for (i = 0; i < ABS_MAX; i++) { | ||
377 | int diff = ptr->dev->absmax[ABS_X + i] / 10; | ||
378 | ptr->dev->absmin[ABS_X + i] += diff; | ||
379 | ptr->dev->absmax[ABS_X + i] -= diff; | ||
380 | } | ||
381 | #endif | ||
382 | } | ||
383 | |||
384 | ptr->dev->name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; | ||
385 | |||
386 | ptr->dev->id.bustype = BUS_HIL; | ||
387 | ptr->dev->id.vendor = PCI_VENDOR_ID_HP; | ||
388 | ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */ | ||
389 | ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */ | ||
390 | ptr->dev->dev.parent = &serio->dev; | ||
391 | |||
392 | error = input_register_device(ptr->dev); | ||
393 | if (error) { | ||
394 | printk(KERN_INFO PREFIX "Unable to register input device\n"); | ||
395 | goto bail2; | ||
396 | } | ||
397 | |||
398 | printk(KERN_INFO "input: %s (%s), ID: %d\n", | ||
399 | ptr->dev->name, | ||
400 | (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad", | ||
401 | did); | ||
402 | |||
403 | return 0; | ||
404 | |||
405 | bail2: | ||
406 | serio_close(serio); | ||
407 | bail1: | ||
408 | input_free_device(ptr->dev); | ||
409 | bail0: | ||
410 | kfree(ptr); | ||
411 | serio_set_drvdata(serio, NULL); | ||
412 | return error; | ||
413 | } | ||
414 | |||
415 | static struct serio_device_id hil_ptr_ids[] = { | ||
416 | { | ||
417 | .type = SERIO_HIL_MLC, | ||
418 | .proto = SERIO_HIL, | ||
419 | .id = SERIO_ANY, | ||
420 | .extra = SERIO_ANY, | ||
421 | }, | ||
422 | { 0 } | ||
423 | }; | ||
424 | |||
425 | static struct serio_driver hil_ptr_serio_driver = { | ||
426 | .driver = { | ||
427 | .name = "hil_ptr", | ||
428 | }, | ||
429 | .description = "HP HIL mouse/tablet driver", | ||
430 | .id_table = hil_ptr_ids, | ||
431 | .connect = hil_ptr_connect, | ||
432 | .disconnect = hil_ptr_disconnect, | ||
433 | .interrupt = hil_ptr_interrupt | ||
434 | }; | ||
435 | |||
436 | static int __init hil_ptr_init(void) | ||
437 | { | ||
438 | return serio_register_driver(&hil_ptr_serio_driver); | ||
439 | } | ||
440 | |||
441 | static void __exit hil_ptr_exit(void) | ||
442 | { | ||
443 | serio_unregister_driver(&hil_ptr_serio_driver); | ||
444 | } | ||
445 | |||
446 | module_init(hil_ptr_init); | ||
447 | module_exit(hil_ptr_exit); | ||
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b407b355dceb..df318887ca09 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "trackpoint.h" | 30 | #include "trackpoint.h" |
31 | #include "touchkit_ps2.h" | 31 | #include "touchkit_ps2.h" |
32 | #include "elantech.h" | 32 | #include "elantech.h" |
33 | #include "sentelic.h" | ||
33 | 34 | ||
34 | #define DRIVER_DESC "PS/2 mouse driver" | 35 | #define DRIVER_DESC "PS/2 mouse driver" |
35 | 36 | ||
@@ -666,6 +667,20 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
666 | max_proto = PSMOUSE_IMEX; | 667 | max_proto = PSMOUSE_IMEX; |
667 | } | 668 | } |
668 | 669 | ||
670 | /* | ||
671 | * Try Finger Sensing Pad | ||
672 | */ | ||
673 | if (max_proto > PSMOUSE_IMEX) { | ||
674 | if (fsp_detect(psmouse, set_properties) == 0) { | ||
675 | if (!set_properties || fsp_init(psmouse) == 0) | ||
676 | return PSMOUSE_FSP; | ||
677 | /* | ||
678 | * Init failed, try basic relative protocols | ||
679 | */ | ||
680 | max_proto = PSMOUSE_IMEX; | ||
681 | } | ||
682 | } | ||
683 | |||
669 | if (max_proto > PSMOUSE_IMEX) { | 684 | if (max_proto > PSMOUSE_IMEX) { |
670 | if (genius_detect(psmouse, set_properties) == 0) | 685 | if (genius_detect(psmouse, set_properties) == 0) |
671 | return PSMOUSE_GENPS; | 686 | return PSMOUSE_GENPS; |
@@ -813,7 +828,16 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
813 | .detect = elantech_detect, | 828 | .detect = elantech_detect, |
814 | .init = elantech_init, | 829 | .init = elantech_init, |
815 | }, | 830 | }, |
816 | #endif | 831 | #endif |
832 | #ifdef CONFIG_MOUSE_PS2_SENTELIC | ||
833 | { | ||
834 | .type = PSMOUSE_FSP, | ||
835 | .name = "FSPPS/2", | ||
836 | .alias = "fsp", | ||
837 | .detect = fsp_detect, | ||
838 | .init = fsp_init, | ||
839 | }, | ||
840 | #endif | ||
817 | { | 841 | { |
818 | .type = PSMOUSE_CORTRON, | 842 | .type = PSMOUSE_CORTRON, |
819 | .name = "CortronPS/2", | 843 | .name = "CortronPS/2", |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 54ed267894bd..cca1744c2a08 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -91,6 +91,7 @@ enum psmouse_type { | |||
91 | PSMOUSE_CORTRON, | 91 | PSMOUSE_CORTRON, |
92 | PSMOUSE_HGPK, | 92 | PSMOUSE_HGPK, |
93 | PSMOUSE_ELANTECH, | 93 | PSMOUSE_ELANTECH, |
94 | PSMOUSE_FSP, | ||
94 | PSMOUSE_AUTO /* This one should always be last */ | 95 | PSMOUSE_AUTO /* This one should always be last */ |
95 | }; | 96 | }; |
96 | 97 | ||
@@ -116,9 +117,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at | |||
116 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, | 117 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, |
117 | const char *buf, size_t count); | 118 | const char *buf, size_t count); |
118 | 119 | ||
119 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ | 120 | #define __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) \ |
120 | static ssize_t _show(struct psmouse *, void *data, char *); \ | ||
121 | static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ | ||
122 | static struct psmouse_attribute psmouse_attr_##_name = { \ | 121 | static struct psmouse_attribute psmouse_attr_##_name = { \ |
123 | .dattr = { \ | 122 | .dattr = { \ |
124 | .attr = { \ | 123 | .attr = { \ |
@@ -134,7 +133,20 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ | |||
134 | .protect = _protect, \ | 133 | .protect = _protect, \ |
135 | } | 134 | } |
136 | 135 | ||
137 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | 136 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ |
138 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1) | 137 | static ssize_t _show(struct psmouse *, void *, char *); \ |
138 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | ||
139 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) | ||
140 | |||
141 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | ||
142 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1) | ||
143 | |||
144 | #define PSMOUSE_DEFINE_RO_ATTR(_name, _mode, _data, _show) \ | ||
145 | static ssize_t _show(struct psmouse *, void *, char *); \ | ||
146 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, NULL, 1) | ||
147 | |||
148 | #define PSMOUSE_DEFINE_WO_ATTR(_name, _mode, _data, _set) \ | ||
149 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | ||
150 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, 1) | ||
139 | 151 | ||
140 | #endif /* _PSMOUSE_H */ | 152 | #endif /* _PSMOUSE_H */ |
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c new file mode 100644 index 000000000000..97b1e72855a0 --- /dev/null +++ b/drivers/input/mouse/sentelic.c | |||
@@ -0,0 +1,867 @@ | |||
1 | /*- | ||
2 | * Finger Sensing Pad PS/2 mouse driver. | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | ||
5 | * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version 2 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/version.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/ctype.h> | ||
26 | #include <linux/libps2.h> | ||
27 | #include <linux/serio.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | |||
30 | #include "psmouse.h" | ||
31 | #include "sentelic.h" | ||
32 | |||
33 | /* | ||
34 | * Timeout for FSP PS/2 command only (in milliseconds). | ||
35 | */ | ||
36 | #define FSP_CMD_TIMEOUT 200 | ||
37 | #define FSP_CMD_TIMEOUT2 30 | ||
38 | |||
39 | /** Driver version. */ | ||
40 | static const char fsp_drv_ver[] = "1.0.0-K"; | ||
41 | |||
42 | /* | ||
43 | * Make sure that the value being sent to FSP will not conflict with | ||
44 | * possible sample rate values. | ||
45 | */ | ||
46 | static unsigned char fsp_test_swap_cmd(unsigned char reg_val) | ||
47 | { | ||
48 | switch (reg_val) { | ||
49 | case 10: case 20: case 40: case 60: case 80: case 100: case 200: | ||
50 | /* | ||
51 | * The requested value being sent to FSP matched to possible | ||
52 | * sample rates, swap the given value such that the hardware | ||
53 | * wouldn't get confused. | ||
54 | */ | ||
55 | return (reg_val >> 4) | (reg_val << 4); | ||
56 | default: | ||
57 | return reg_val; /* swap isn't necessary */ | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Make sure that the value being sent to FSP will not conflict with certain | ||
63 | * commands. | ||
64 | */ | ||
65 | static unsigned char fsp_test_invert_cmd(unsigned char reg_val) | ||
66 | { | ||
67 | switch (reg_val) { | ||
68 | case 0xe9: case 0xee: case 0xf2: case 0xff: | ||
69 | /* | ||
70 | * The requested value being sent to FSP matched to certain | ||
71 | * commands, inverse the given value such that the hardware | ||
72 | * wouldn't get confused. | ||
73 | */ | ||
74 | return ~reg_val; | ||
75 | default: | ||
76 | return reg_val; /* inversion isn't necessary */ | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | ||
81 | { | ||
82 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
83 | unsigned char param[3]; | ||
84 | unsigned char addr; | ||
85 | int rc = -1; | ||
86 | |||
87 | /* | ||
88 | * We need to shut off the device and switch it into command | ||
89 | * mode so we don't confuse our protocol handler. We don't need | ||
90 | * to do that for writes because sysfs set helper does this for | ||
91 | * us. | ||
92 | */ | ||
93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | ||
94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
95 | mutex_lock(&ps2dev->cmd_mutex); | ||
96 | |||
97 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
98 | goto out; | ||
99 | |||
100 | /* should return 0xfe(request for resending) */ | ||
101 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
102 | /* should return 0xfc(failed) */ | ||
103 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
104 | |||
105 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
106 | goto out; | ||
107 | |||
108 | if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) { | ||
109 | ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2); | ||
110 | } else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) { | ||
111 | /* swapping is required */ | ||
112 | ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2); | ||
113 | /* expect 0xfe */ | ||
114 | } else { | ||
115 | /* swapping isn't necessary */ | ||
116 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
117 | /* expect 0xfe */ | ||
118 | } | ||
119 | /* should return 0xfc(failed) */ | ||
120 | ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT); | ||
121 | |||
122 | if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0) | ||
123 | goto out; | ||
124 | |||
125 | *reg_val = param[2]; | ||
126 | rc = 0; | ||
127 | |||
128 | out: | ||
129 | mutex_unlock(&ps2dev->cmd_mutex); | ||
130 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
131 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
132 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", | ||
133 | reg_addr, *reg_val, rc); | ||
134 | return rc; | ||
135 | } | ||
136 | |||
137 | static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | ||
138 | { | ||
139 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
140 | unsigned char v; | ||
141 | int rc = -1; | ||
142 | |||
143 | mutex_lock(&ps2dev->cmd_mutex); | ||
144 | |||
145 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
146 | goto out; | ||
147 | |||
148 | if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) { | ||
149 | /* inversion is required */ | ||
150 | ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2); | ||
151 | } else { | ||
152 | if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) { | ||
153 | /* swapping is required */ | ||
154 | ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2); | ||
155 | } else { | ||
156 | /* swapping isn't necessary */ | ||
157 | ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2); | ||
158 | } | ||
159 | } | ||
160 | /* write the register address in correct order */ | ||
161 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
162 | |||
163 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
164 | return -1; | ||
165 | |||
166 | if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { | ||
167 | /* inversion is required */ | ||
168 | ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); | ||
169 | } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { | ||
170 | /* swapping is required */ | ||
171 | ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); | ||
172 | } else { | ||
173 | /* swapping isn't necessary */ | ||
174 | ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); | ||
175 | } | ||
176 | |||
177 | /* write the register value in correct order */ | ||
178 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
179 | rc = 0; | ||
180 | |||
181 | out: | ||
182 | mutex_unlock(&ps2dev->cmd_mutex); | ||
183 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", | ||
184 | reg_addr, reg_val, rc); | ||
185 | return rc; | ||
186 | } | ||
187 | |||
188 | /* Enable register clock gating for writing certain registers */ | ||
189 | static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable) | ||
190 | { | ||
191 | int v, nv; | ||
192 | |||
193 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1) | ||
194 | return -1; | ||
195 | |||
196 | if (enable) | ||
197 | nv = v | FSP_BIT_EN_REG_CLK; | ||
198 | else | ||
199 | nv = v & ~FSP_BIT_EN_REG_CLK; | ||
200 | |||
201 | /* only write if necessary */ | ||
202 | if (nv != v) | ||
203 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1) | ||
204 | return -1; | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | ||
210 | { | ||
211 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
212 | unsigned char param[3]; | ||
213 | int rc = -1; | ||
214 | |||
215 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | ||
216 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
217 | mutex_lock(&ps2dev->cmd_mutex); | ||
218 | |||
219 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
220 | goto out; | ||
221 | |||
222 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
223 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
224 | |||
225 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
226 | goto out; | ||
227 | |||
228 | ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2); | ||
229 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
230 | |||
231 | /* get the returned result */ | ||
232 | if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | ||
233 | goto out; | ||
234 | |||
235 | *reg_val = param[2]; | ||
236 | rc = 0; | ||
237 | |||
238 | out: | ||
239 | mutex_unlock(&ps2dev->cmd_mutex); | ||
240 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
241 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
242 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", | ||
243 | *reg_val, rc); | ||
244 | return rc; | ||
245 | } | ||
246 | |||
247 | static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | ||
248 | { | ||
249 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
250 | unsigned char v; | ||
251 | int rc = -1; | ||
252 | |||
253 | mutex_lock(&ps2dev->cmd_mutex); | ||
254 | |||
255 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
256 | goto out; | ||
257 | |||
258 | ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2); | ||
259 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
260 | |||
261 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
262 | return -1; | ||
263 | |||
264 | if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { | ||
265 | ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); | ||
266 | } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { | ||
267 | /* swapping is required */ | ||
268 | ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); | ||
269 | } else { | ||
270 | /* swapping isn't necessary */ | ||
271 | ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); | ||
272 | } | ||
273 | |||
274 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
275 | rc = 0; | ||
276 | |||
277 | out: | ||
278 | mutex_unlock(&ps2dev->cmd_mutex); | ||
279 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", | ||
280 | reg_val, rc); | ||
281 | return rc; | ||
282 | } | ||
283 | |||
284 | static int fsp_get_version(struct psmouse *psmouse, int *version) | ||
285 | { | ||
286 | if (fsp_reg_read(psmouse, FSP_REG_VERSION, version)) | ||
287 | return -EIO; | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int fsp_get_revision(struct psmouse *psmouse, int *rev) | ||
293 | { | ||
294 | if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev)) | ||
295 | return -EIO; | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int fsp_get_buttons(struct psmouse *psmouse, int *btn) | ||
301 | { | ||
302 | static const int buttons[] = { | ||
303 | 0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */ | ||
304 | 0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */ | ||
305 | 0x04, /* Left/Middle/Right & Scroll Up/Down */ | ||
306 | 0x02, /* Left/Middle/Right */ | ||
307 | }; | ||
308 | int val; | ||
309 | |||
310 | if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS1, &val) == -1) | ||
311 | return -EIO; | ||
312 | |||
313 | *btn = buttons[(val & 0x30) >> 4]; | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | /* Enable on-pad command tag output */ | ||
318 | static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) | ||
319 | { | ||
320 | int v, nv; | ||
321 | int res = 0; | ||
322 | |||
323 | if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { | ||
324 | dev_err(&psmouse->ps2dev.serio->dev, "Unable get OPC state.\n"); | ||
325 | return -EIO; | ||
326 | } | ||
327 | |||
328 | if (enable) | ||
329 | nv = v | FSP_BIT_EN_OPC_TAG; | ||
330 | else | ||
331 | nv = v & ~FSP_BIT_EN_OPC_TAG; | ||
332 | |||
333 | /* only write if necessary */ | ||
334 | if (nv != v) { | ||
335 | fsp_reg_write_enable(psmouse, true); | ||
336 | res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv); | ||
337 | fsp_reg_write_enable(psmouse, false); | ||
338 | } | ||
339 | |||
340 | if (res != 0) { | ||
341 | dev_err(&psmouse->ps2dev.serio->dev, | ||
342 | "Unable to enable OPC tag.\n"); | ||
343 | res = -EIO; | ||
344 | } | ||
345 | |||
346 | return res; | ||
347 | } | ||
348 | |||
349 | static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable) | ||
350 | { | ||
351 | struct fsp_data *pad = psmouse->private; | ||
352 | int val; | ||
353 | |||
354 | if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) | ||
355 | return -EIO; | ||
356 | |||
357 | pad->vscroll = enable; | ||
358 | |||
359 | if (enable) | ||
360 | val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE); | ||
361 | else | ||
362 | val &= ~FSP_BIT_FIX_VSCR; | ||
363 | |||
364 | if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) | ||
365 | return -EIO; | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable) | ||
371 | { | ||
372 | struct fsp_data *pad = psmouse->private; | ||
373 | int val, v2; | ||
374 | |||
375 | if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) | ||
376 | return -EIO; | ||
377 | |||
378 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2)) | ||
379 | return -EIO; | ||
380 | |||
381 | pad->hscroll = enable; | ||
382 | |||
383 | if (enable) { | ||
384 | val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE); | ||
385 | v2 |= FSP_BIT_EN_MSID6; | ||
386 | } else { | ||
387 | val &= ~FSP_BIT_FIX_HSCR; | ||
388 | v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8); | ||
389 | } | ||
390 | |||
391 | if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) | ||
392 | return -EIO; | ||
393 | |||
394 | /* reconfigure horizontal scrolling packet output */ | ||
395 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2)) | ||
396 | return -EIO; | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Write device specific initial parameters. | ||
403 | * | ||
404 | * ex: 0xab 0xcd - write oxcd into register 0xab | ||
405 | */ | ||
406 | static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, | ||
407 | const char *buf, size_t count) | ||
408 | { | ||
409 | unsigned long reg, val; | ||
410 | char *rest; | ||
411 | ssize_t retval; | ||
412 | |||
413 | reg = simple_strtoul(buf, &rest, 16); | ||
414 | if (rest == buf || *rest != ' ' || reg > 0xff) | ||
415 | return -EINVAL; | ||
416 | |||
417 | if (strict_strtoul(rest + 1, 16, &val) || val > 0xff) | ||
418 | return -EINVAL; | ||
419 | |||
420 | if (fsp_reg_write_enable(psmouse, true)) | ||
421 | return -EIO; | ||
422 | |||
423 | retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count; | ||
424 | |||
425 | fsp_reg_write_enable(psmouse, false); | ||
426 | |||
427 | return count; | ||
428 | } | ||
429 | |||
430 | PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); | ||
431 | |||
432 | static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse, | ||
433 | void *data, char *buf) | ||
434 | { | ||
435 | struct fsp_data *pad = psmouse->private; | ||
436 | |||
437 | return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val); | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * Read a register from device. | ||
442 | * | ||
443 | * ex: 0xab -- read content from register 0xab | ||
444 | */ | ||
445 | static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data, | ||
446 | const char *buf, size_t count) | ||
447 | { | ||
448 | struct fsp_data *pad = psmouse->private; | ||
449 | unsigned long reg; | ||
450 | int val; | ||
451 | |||
452 | if (strict_strtoul(buf, 16, ®) || reg > 0xff) | ||
453 | return -EINVAL; | ||
454 | |||
455 | if (fsp_reg_read(psmouse, reg, &val)) | ||
456 | return -EIO; | ||
457 | |||
458 | pad->last_reg = reg; | ||
459 | pad->last_val = val; | ||
460 | |||
461 | return count; | ||
462 | } | ||
463 | |||
464 | PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL, | ||
465 | fsp_attr_show_getreg, fsp_attr_set_getreg); | ||
466 | |||
467 | static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse, | ||
468 | void *data, char *buf) | ||
469 | { | ||
470 | int val = 0; | ||
471 | |||
472 | if (fsp_page_reg_read(psmouse, &val)) | ||
473 | return -EIO; | ||
474 | |||
475 | return sprintf(buf, "%02x\n", val); | ||
476 | } | ||
477 | |||
478 | static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data, | ||
479 | const char *buf, size_t count) | ||
480 | { | ||
481 | unsigned long val; | ||
482 | |||
483 | if (strict_strtoul(buf, 16, &val) || val > 0xff) | ||
484 | return -EINVAL; | ||
485 | |||
486 | if (fsp_page_reg_write(psmouse, val)) | ||
487 | return -EIO; | ||
488 | |||
489 | return count; | ||
490 | } | ||
491 | |||
492 | PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL, | ||
493 | fsp_attr_show_pagereg, fsp_attr_set_pagereg); | ||
494 | |||
495 | static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse, | ||
496 | void *data, char *buf) | ||
497 | { | ||
498 | struct fsp_data *pad = psmouse->private; | ||
499 | |||
500 | return sprintf(buf, "%d\n", pad->vscroll); | ||
501 | } | ||
502 | |||
503 | static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data, | ||
504 | const char *buf, size_t count) | ||
505 | { | ||
506 | unsigned long val; | ||
507 | |||
508 | if (strict_strtoul(buf, 10, &val) || val > 1) | ||
509 | return -EINVAL; | ||
510 | |||
511 | fsp_onpad_vscr(psmouse, val); | ||
512 | |||
513 | return count; | ||
514 | } | ||
515 | |||
516 | PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL, | ||
517 | fsp_attr_show_vscroll, fsp_attr_set_vscroll); | ||
518 | |||
519 | static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse, | ||
520 | void *data, char *buf) | ||
521 | { | ||
522 | struct fsp_data *pad = psmouse->private; | ||
523 | |||
524 | return sprintf(buf, "%d\n", pad->hscroll); | ||
525 | } | ||
526 | |||
527 | static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data, | ||
528 | const char *buf, size_t count) | ||
529 | { | ||
530 | unsigned long val; | ||
531 | |||
532 | if (strict_strtoul(buf, 10, &val) || val > 1) | ||
533 | return -EINVAL; | ||
534 | |||
535 | fsp_onpad_hscr(psmouse, val); | ||
536 | |||
537 | return count; | ||
538 | } | ||
539 | |||
540 | PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL, | ||
541 | fsp_attr_show_hscroll, fsp_attr_set_hscroll); | ||
542 | |||
543 | static ssize_t fsp_attr_show_flags(struct psmouse *psmouse, | ||
544 | void *data, char *buf) | ||
545 | { | ||
546 | struct fsp_data *pad = psmouse->private; | ||
547 | |||
548 | return sprintf(buf, "%c\n", | ||
549 | pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c'); | ||
550 | } | ||
551 | |||
552 | static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data, | ||
553 | const char *buf, size_t count) | ||
554 | { | ||
555 | struct fsp_data *pad = psmouse->private; | ||
556 | size_t i; | ||
557 | |||
558 | for (i = 0; i < count; i++) { | ||
559 | switch (buf[i]) { | ||
560 | case 'C': | ||
561 | pad->flags |= FSPDRV_FLAG_EN_OPC; | ||
562 | break; | ||
563 | case 'c': | ||
564 | pad->flags &= ~FSPDRV_FLAG_EN_OPC; | ||
565 | break; | ||
566 | default: | ||
567 | return -EINVAL; | ||
568 | } | ||
569 | } | ||
570 | return count; | ||
571 | } | ||
572 | |||
573 | PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL, | ||
574 | fsp_attr_show_flags, fsp_attr_set_flags); | ||
575 | |||
576 | static ssize_t fsp_attr_show_ver(struct psmouse *psmouse, | ||
577 | void *data, char *buf) | ||
578 | { | ||
579 | return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver); | ||
580 | } | ||
581 | |||
582 | PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver); | ||
583 | |||
584 | static struct attribute *fsp_attributes[] = { | ||
585 | &psmouse_attr_setreg.dattr.attr, | ||
586 | &psmouse_attr_getreg.dattr.attr, | ||
587 | &psmouse_attr_page.dattr.attr, | ||
588 | &psmouse_attr_vscroll.dattr.attr, | ||
589 | &psmouse_attr_hscroll.dattr.attr, | ||
590 | &psmouse_attr_flags.dattr.attr, | ||
591 | &psmouse_attr_ver.dattr.attr, | ||
592 | NULL | ||
593 | }; | ||
594 | |||
595 | static struct attribute_group fsp_attribute_group = { | ||
596 | .attrs = fsp_attributes, | ||
597 | }; | ||
598 | |||
599 | #ifdef FSP_DEBUG | ||
600 | static void fsp_packet_debug(unsigned char packet[]) | ||
601 | { | ||
602 | static unsigned int ps2_packet_cnt; | ||
603 | static unsigned int ps2_last_second; | ||
604 | unsigned int jiffies_msec; | ||
605 | |||
606 | ps2_packet_cnt++; | ||
607 | jiffies_msec = jiffies_to_msecs(jiffies); | ||
608 | printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", | ||
609 | jiffies_msec, packet[0], packet[1], packet[2], packet[3]); | ||
610 | |||
611 | if (jiffies_msec - ps2_last_second > 1000) { | ||
612 | printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt); | ||
613 | ps2_packet_cnt = 0; | ||
614 | ps2_last_second = jiffies_msec; | ||
615 | } | ||
616 | } | ||
617 | #else | ||
618 | static void fsp_packet_debug(unsigned char packet[]) | ||
619 | { | ||
620 | } | ||
621 | #endif | ||
622 | |||
623 | static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | ||
624 | { | ||
625 | struct input_dev *dev = psmouse->dev; | ||
626 | struct fsp_data *ad = psmouse->private; | ||
627 | unsigned char *packet = psmouse->packet; | ||
628 | unsigned char button_status = 0, lscroll = 0, rscroll = 0; | ||
629 | int rel_x, rel_y; | ||
630 | |||
631 | if (psmouse->pktcnt < 4) | ||
632 | return PSMOUSE_GOOD_DATA; | ||
633 | |||
634 | /* | ||
635 | * Full packet accumulated, process it | ||
636 | */ | ||
637 | |||
638 | switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { | ||
639 | case FSP_PKT_TYPE_ABS: | ||
640 | dev_warn(&psmouse->ps2dev.serio->dev, | ||
641 | "Unexpected absolute mode packet, ignored.\n"); | ||
642 | break; | ||
643 | |||
644 | case FSP_PKT_TYPE_NORMAL_OPC: | ||
645 | /* on-pad click, filter it if necessary */ | ||
646 | if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) | ||
647 | packet[0] &= ~BIT(0); | ||
648 | /* fall through */ | ||
649 | |||
650 | case FSP_PKT_TYPE_NORMAL: | ||
651 | /* normal packet */ | ||
652 | /* special packet data translation from on-pad packets */ | ||
653 | if (packet[3] != 0) { | ||
654 | if (packet[3] & BIT(0)) | ||
655 | button_status |= 0x01; /* wheel down */ | ||
656 | if (packet[3] & BIT(1)) | ||
657 | button_status |= 0x0f; /* wheel up */ | ||
658 | if (packet[3] & BIT(2)) | ||
659 | button_status |= BIT(5);/* horizontal left */ | ||
660 | if (packet[3] & BIT(3)) | ||
661 | button_status |= BIT(4);/* horizontal right */ | ||
662 | /* push back to packet queue */ | ||
663 | if (button_status != 0) | ||
664 | packet[3] = button_status; | ||
665 | rscroll = (packet[3] >> 4) & 1; | ||
666 | lscroll = (packet[3] >> 5) & 1; | ||
667 | } | ||
668 | /* | ||
669 | * Processing wheel up/down and extra button events | ||
670 | */ | ||
671 | input_report_rel(dev, REL_WHEEL, | ||
672 | (int)(packet[3] & 8) - (int)(packet[3] & 7)); | ||
673 | input_report_rel(dev, REL_HWHEEL, lscroll - rscroll); | ||
674 | input_report_key(dev, BTN_BACK, lscroll); | ||
675 | input_report_key(dev, BTN_FORWARD, rscroll); | ||
676 | |||
677 | /* | ||
678 | * Standard PS/2 Mouse | ||
679 | */ | ||
680 | input_report_key(dev, BTN_LEFT, packet[0] & 1); | ||
681 | input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1); | ||
682 | input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1); | ||
683 | |||
684 | rel_x = packet[1] ? (int)packet[1] - (int)((packet[0] << 4) & 0x100) : 0; | ||
685 | rel_y = packet[2] ? (int)((packet[0] << 3) & 0x100) - (int)packet[2] : 0; | ||
686 | |||
687 | input_report_rel(dev, REL_X, rel_x); | ||
688 | input_report_rel(dev, REL_Y, rel_y); | ||
689 | break; | ||
690 | } | ||
691 | |||
692 | input_sync(dev); | ||
693 | |||
694 | fsp_packet_debug(packet); | ||
695 | |||
696 | return PSMOUSE_FULL_PACKET; | ||
697 | } | ||
698 | |||
699 | static int fsp_activate_protocol(struct psmouse *psmouse) | ||
700 | { | ||
701 | struct fsp_data *pad = psmouse->private; | ||
702 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
703 | unsigned char param[2]; | ||
704 | int val; | ||
705 | |||
706 | /* | ||
707 | * Standard procedure to enter FSP Intellimouse mode | ||
708 | * (scrolling wheel, 4th and 5th buttons) | ||
709 | */ | ||
710 | param[0] = 200; | ||
711 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
712 | param[0] = 200; | ||
713 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
714 | param[0] = 80; | ||
715 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
716 | |||
717 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); | ||
718 | if (param[0] != 0x04) { | ||
719 | dev_err(&psmouse->ps2dev.serio->dev, | ||
720 | "Unable to enable 4 bytes packet format.\n"); | ||
721 | return -EIO; | ||
722 | } | ||
723 | |||
724 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { | ||
725 | dev_err(&psmouse->ps2dev.serio->dev, | ||
726 | "Unable to read SYSCTL5 register.\n"); | ||
727 | return -EIO; | ||
728 | } | ||
729 | |||
730 | val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); | ||
731 | /* Ensure we are not in absolute mode */ | ||
732 | val &= ~FSP_BIT_EN_PKT_G0; | ||
733 | if (pad->buttons == 0x06) { | ||
734 | /* Left/Middle/Right & Scroll Up/Down/Right/Left */ | ||
735 | val |= FSP_BIT_EN_MSID6; | ||
736 | } | ||
737 | |||
738 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { | ||
739 | dev_err(&psmouse->ps2dev.serio->dev, | ||
740 | "Unable to set up required mode bits.\n"); | ||
741 | return -EIO; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * Enable OPC tags such that driver can tell the difference between | ||
746 | * on-pad and real button click | ||
747 | */ | ||
748 | if (fsp_opc_tag_enable(psmouse, true)) | ||
749 | dev_warn(&psmouse->ps2dev.serio->dev, | ||
750 | "Failed to enable OPC tag mode.\n"); | ||
751 | |||
752 | /* Enable on-pad vertical and horizontal scrolling */ | ||
753 | fsp_onpad_vscr(psmouse, true); | ||
754 | fsp_onpad_hscr(psmouse, true); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | int fsp_detect(struct psmouse *psmouse, int set_properties) | ||
760 | { | ||
761 | int id; | ||
762 | |||
763 | if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id)) | ||
764 | return -EIO; | ||
765 | |||
766 | if (id != 0x01) | ||
767 | return -ENODEV; | ||
768 | |||
769 | if (set_properties) { | ||
770 | psmouse->vendor = "Sentelic"; | ||
771 | psmouse->name = "FingerSensingPad"; | ||
772 | } | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static void fsp_reset(struct psmouse *psmouse) | ||
778 | { | ||
779 | fsp_opc_tag_enable(psmouse, false); | ||
780 | fsp_onpad_vscr(psmouse, false); | ||
781 | fsp_onpad_hscr(psmouse, false); | ||
782 | } | ||
783 | |||
784 | static void fsp_disconnect(struct psmouse *psmouse) | ||
785 | { | ||
786 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | ||
787 | &fsp_attribute_group); | ||
788 | |||
789 | fsp_reset(psmouse); | ||
790 | kfree(psmouse->private); | ||
791 | } | ||
792 | |||
793 | static int fsp_reconnect(struct psmouse *psmouse) | ||
794 | { | ||
795 | int version; | ||
796 | |||
797 | if (fsp_detect(psmouse, 0)) | ||
798 | return -ENODEV; | ||
799 | |||
800 | if (fsp_get_version(psmouse, &version)) | ||
801 | return -ENODEV; | ||
802 | |||
803 | if (fsp_activate_protocol(psmouse)) | ||
804 | return -EIO; | ||
805 | |||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | int fsp_init(struct psmouse *psmouse) | ||
810 | { | ||
811 | struct fsp_data *priv; | ||
812 | int ver, rev, buttons; | ||
813 | int error; | ||
814 | |||
815 | if (fsp_get_version(psmouse, &ver) || | ||
816 | fsp_get_revision(psmouse, &rev) || | ||
817 | fsp_get_buttons(psmouse, &buttons)) { | ||
818 | return -ENODEV; | ||
819 | } | ||
820 | |||
821 | printk(KERN_INFO | ||
822 | "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", | ||
823 | ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); | ||
824 | |||
825 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); | ||
826 | if (!priv) | ||
827 | return -ENOMEM; | ||
828 | |||
829 | priv->ver = ver; | ||
830 | priv->rev = rev; | ||
831 | priv->buttons = buttons; | ||
832 | |||
833 | /* enable on-pad click by default */ | ||
834 | priv->flags |= FSPDRV_FLAG_EN_OPC; | ||
835 | |||
836 | /* Set up various supported input event bits */ | ||
837 | __set_bit(BTN_BACK, psmouse->dev->keybit); | ||
838 | __set_bit(BTN_FORWARD, psmouse->dev->keybit); | ||
839 | __set_bit(REL_WHEEL, psmouse->dev->relbit); | ||
840 | __set_bit(REL_HWHEEL, psmouse->dev->relbit); | ||
841 | |||
842 | psmouse->protocol_handler = fsp_process_byte; | ||
843 | psmouse->disconnect = fsp_disconnect; | ||
844 | psmouse->reconnect = fsp_reconnect; | ||
845 | psmouse->cleanup = fsp_reset; | ||
846 | psmouse->pktsize = 4; | ||
847 | |||
848 | /* set default packet output based on number of buttons we found */ | ||
849 | error = fsp_activate_protocol(psmouse); | ||
850 | if (error) | ||
851 | goto err_out; | ||
852 | |||
853 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, | ||
854 | &fsp_attribute_group); | ||
855 | if (error) { | ||
856 | dev_err(&psmouse->ps2dev.serio->dev, | ||
857 | "Failed to create sysfs attributes (%d)", error); | ||
858 | goto err_out; | ||
859 | } | ||
860 | |||
861 | return 0; | ||
862 | |||
863 | err_out: | ||
864 | kfree(psmouse->private); | ||
865 | psmouse->private = NULL; | ||
866 | return error; | ||
867 | } | ||
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h new file mode 100644 index 000000000000..083559c7282b --- /dev/null +++ b/drivers/input/mouse/sentelic.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /*- | ||
2 | * Finger Sensing Pad PS/2 mouse driver. | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | ||
5 | * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version 2 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __SENTELIC_H | ||
23 | #define __SENTELIC_H | ||
24 | |||
25 | /* Finger-sensing Pad information registers */ | ||
26 | #define FSP_REG_DEVICE_ID 0x00 | ||
27 | #define FSP_REG_VERSION 0x01 | ||
28 | #define FSP_REG_REVISION 0x04 | ||
29 | #define FSP_REG_TMOD_STATUS1 0x0B | ||
30 | #define FSP_BIT_NO_ROTATION BIT(3) | ||
31 | #define FSP_REG_PAGE_CTRL 0x0F | ||
32 | |||
33 | /* Finger-sensing Pad control registers */ | ||
34 | #define FSP_REG_SYSCTL1 0x10 | ||
35 | #define FSP_BIT_EN_REG_CLK BIT(5) | ||
36 | #define FSP_REG_OPC_QDOWN 0x31 | ||
37 | #define FSP_BIT_EN_OPC_TAG BIT(7) | ||
38 | #define FSP_REG_OPTZ_XLO 0x34 | ||
39 | #define FSP_REG_OPTZ_XHI 0x35 | ||
40 | #define FSP_REG_OPTZ_YLO 0x36 | ||
41 | #define FSP_REG_OPTZ_YHI 0x37 | ||
42 | #define FSP_REG_SYSCTL5 0x40 | ||
43 | #define FSP_BIT_90_DEGREE BIT(0) | ||
44 | #define FSP_BIT_EN_MSID6 BIT(1) | ||
45 | #define FSP_BIT_EN_MSID7 BIT(2) | ||
46 | #define FSP_BIT_EN_MSID8 BIT(3) | ||
47 | #define FSP_BIT_EN_AUTO_MSID8 BIT(5) | ||
48 | #define FSP_BIT_EN_PKT_G0 BIT(6) | ||
49 | |||
50 | #define FSP_REG_ONPAD_CTL 0x43 | ||
51 | #define FSP_BIT_ONPAD_ENABLE BIT(0) | ||
52 | #define FSP_BIT_ONPAD_FBBB BIT(1) | ||
53 | #define FSP_BIT_FIX_VSCR BIT(3) | ||
54 | #define FSP_BIT_FIX_HSCR BIT(5) | ||
55 | #define FSP_BIT_DRAG_LOCK BIT(6) | ||
56 | |||
57 | /* Finger-sensing Pad packet formating related definitions */ | ||
58 | |||
59 | /* absolute packet type */ | ||
60 | #define FSP_PKT_TYPE_NORMAL (0x00) | ||
61 | #define FSP_PKT_TYPE_ABS (0x01) | ||
62 | #define FSP_PKT_TYPE_NOTIFY (0x02) | ||
63 | #define FSP_PKT_TYPE_NORMAL_OPC (0x03) | ||
64 | #define FSP_PKT_TYPE_SHIFT (6) | ||
65 | |||
66 | #ifdef __KERNEL__ | ||
67 | |||
68 | struct fsp_data { | ||
69 | unsigned char ver; /* hardware version */ | ||
70 | unsigned char rev; /* hardware revison */ | ||
71 | unsigned char buttons; /* Number of buttons */ | ||
72 | unsigned int flags; | ||
73 | #define FSPDRV_FLAG_EN_OPC (0x001) /* enable on-pad clicking */ | ||
74 | |||
75 | bool vscroll; /* Vertical scroll zone enabled */ | ||
76 | bool hscroll; /* Horizontal scroll zone enabled */ | ||
77 | |||
78 | unsigned char last_reg; /* Last register we requested read from */ | ||
79 | unsigned char last_val; | ||
80 | }; | ||
81 | |||
82 | #ifdef CONFIG_MOUSE_PS2_SENTELIC | ||
83 | extern int fsp_detect(struct psmouse *psmouse, int set_properties); | ||
84 | extern int fsp_init(struct psmouse *psmouse); | ||
85 | #else | ||
86 | inline int fsp_detect(struct psmouse *psmouse, int set_properties) | ||
87 | { | ||
88 | return -ENOSYS; | ||
89 | } | ||
90 | inline int fsp_init(struct psmouse *psmouse) | ||
91 | { | ||
92 | return -ENOSYS; | ||
93 | } | ||
94 | #endif | ||
95 | |||
96 | #endif /* __KERNEL__ */ | ||
97 | |||
98 | #endif /* !__SENTELIC_H */ | ||
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index 404eedd5ffa2..70111443678e 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
@@ -384,11 +384,11 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse) | |||
384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " | 384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " |
385 | "incremental streaming mode and 72 samples/sec\n", | 385 | "incremental streaming mode and 72 samples/sec\n", |
386 | mouse->name, mouse->phys); | 386 | mouse->name, mouse->phys); |
387 | mouse->serio->write (mouse->serio, 'S'); /* Standard format */ | 387 | serio_write (mouse->serio, 'S'); /* Standard format */ |
388 | mdelay (50); | 388 | mdelay (50); |
389 | mouse->serio->write (mouse->serio, 'R'); /* Incremental */ | 389 | serio_write (mouse->serio, 'R'); /* Incremental */ |
390 | mdelay (50); | 390 | mdelay (50); |
391 | mouse->serio->write (mouse->serio, 'L'); /* 72 samples/sec */ | 391 | serio_write (mouse->serio, 'L'); /* 72 samples/sec */ |
392 | } | 392 | } |
393 | 393 | ||
394 | static void | 394 | static void |
@@ -532,7 +532,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) | |||
532 | * Request selftest. Standard packet format and differential | 532 | * Request selftest. Standard packet format and differential |
533 | * mode will be requested after the device ID'ed successfully. | 533 | * mode will be requested after the device ID'ed successfully. |
534 | */ | 534 | */ |
535 | serio->write (serio, 'T'); /* Test */ | 535 | serio_write (serio, 'T'); /* Test */ |
536 | 536 | ||
537 | err = input_register_device (input_dev); | 537 | err = input_register_device (input_dev); |
538 | if (err) | 538 | if (err) |
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index 41fda8c67b1e..a6fb7a3dcc46 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c | |||
@@ -231,7 +231,7 @@ static int __init psif_probe(struct platform_device *pdev) | |||
231 | goto out_free_io; | 231 | goto out_free_io; |
232 | } | 232 | } |
233 | 233 | ||
234 | psif->regs = ioremap(regs->start, regs->end - regs->start + 1); | 234 | psif->regs = ioremap(regs->start, resource_size(regs)); |
235 | if (!psif->regs) { | 235 | if (!psif->regs) { |
236 | ret = -ENOMEM; | 236 | ret = -ENOMEM; |
237 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); | 237 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 582245c497eb..9f5c0506242f 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -923,41 +923,27 @@ static void i8042_dritek_enable(void) | |||
923 | 923 | ||
924 | #ifdef CONFIG_PM | 924 | #ifdef CONFIG_PM |
925 | 925 | ||
926 | static bool i8042_suspended; | ||
927 | |||
928 | /* | 926 | /* |
929 | * Here we try to restore the original BIOS settings. We only want to | 927 | * Here we try to restore the original BIOS settings to avoid |
930 | * do that once, when we really suspend, not when we taking memory | 928 | * upsetting it. |
931 | * snapshot for swsusp (in this case we'll perform required cleanup | ||
932 | * as part of shutdown process). | ||
933 | */ | 929 | */ |
934 | 930 | ||
935 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) | 931 | static int i8042_pm_reset(struct device *dev) |
936 | { | 932 | { |
937 | if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) | 933 | i8042_controller_reset(); |
938 | i8042_controller_reset(); | ||
939 | |||
940 | i8042_suspended = state.event == PM_EVENT_SUSPEND || | ||
941 | state.event == PM_EVENT_FREEZE; | ||
942 | 934 | ||
943 | return 0; | 935 | return 0; |
944 | } | 936 | } |
945 | 937 | ||
946 | |||
947 | /* | 938 | /* |
948 | * Here we try to reset everything back to a state in which suspended | 939 | * Here we try to reset everything back to a state we had |
940 | * before suspending. | ||
949 | */ | 941 | */ |
950 | 942 | ||
951 | static int i8042_resume(struct platform_device *dev) | 943 | static int i8042_pm_restore(struct device *dev) |
952 | { | 944 | { |
953 | int error; | 945 | int error; |
954 | 946 | ||
955 | /* | ||
956 | * Do not bother with restoring state if we haven't suspened yet | ||
957 | */ | ||
958 | if (!i8042_suspended) | ||
959 | return 0; | ||
960 | |||
961 | error = i8042_controller_check(); | 947 | error = i8042_controller_check(); |
962 | if (error) | 948 | if (error) |
963 | return error; | 949 | return error; |
@@ -1001,11 +987,18 @@ static int i8042_resume(struct platform_device *dev) | |||
1001 | if (i8042_ports[I8042_KBD_PORT_NO].serio) | 987 | if (i8042_ports[I8042_KBD_PORT_NO].serio) |
1002 | i8042_enable_kbd_port(); | 988 | i8042_enable_kbd_port(); |
1003 | 989 | ||
1004 | i8042_suspended = false; | ||
1005 | i8042_interrupt(0, NULL); | 990 | i8042_interrupt(0, NULL); |
1006 | 991 | ||
1007 | return 0; | 992 | return 0; |
1008 | } | 993 | } |
994 | |||
995 | static const struct dev_pm_ops i8042_pm_ops = { | ||
996 | .suspend = i8042_pm_reset, | ||
997 | .resume = i8042_pm_restore, | ||
998 | .poweroff = i8042_pm_reset, | ||
999 | .restore = i8042_pm_restore, | ||
1000 | }; | ||
1001 | |||
1009 | #endif /* CONFIG_PM */ | 1002 | #endif /* CONFIG_PM */ |
1010 | 1003 | ||
1011 | /* | 1004 | /* |
@@ -1251,14 +1244,13 @@ static struct platform_driver i8042_driver = { | |||
1251 | .driver = { | 1244 | .driver = { |
1252 | .name = "i8042", | 1245 | .name = "i8042", |
1253 | .owner = THIS_MODULE, | 1246 | .owner = THIS_MODULE, |
1247 | #ifdef CONFIG_PM | ||
1248 | .pm = &i8042_pm_ops, | ||
1249 | #endif | ||
1254 | }, | 1250 | }, |
1255 | .probe = i8042_probe, | 1251 | .probe = i8042_probe, |
1256 | .remove = __devexit_p(i8042_remove), | 1252 | .remove = __devexit_p(i8042_remove), |
1257 | .shutdown = i8042_shutdown, | 1253 | .shutdown = i8042_shutdown, |
1258 | #ifdef CONFIG_PM | ||
1259 | .suspend = i8042_suspend, | ||
1260 | .resume = i8042_resume, | ||
1261 | #endif | ||
1262 | }; | 1254 | }; |
1263 | 1255 | ||
1264 | static int __init i8042_init(void) | 1256 | static int __init i8042_init(void) |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index be5bbbb8ae4e..3a95b508bf27 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -161,7 +161,7 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) | |||
161 | * ps2_command() can only be called from a process context | 161 | * ps2_command() can only be called from a process context |
162 | */ | 162 | */ |
163 | 163 | ||
164 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | 164 | int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) |
165 | { | 165 | { |
166 | int timeout; | 166 | int timeout; |
167 | int send = (command >> 12) & 0xf; | 167 | int send = (command >> 12) & 0xf; |
@@ -179,8 +179,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
179 | return -1; | 179 | return -1; |
180 | } | 180 | } |
181 | 181 | ||
182 | mutex_lock(&ps2dev->cmd_mutex); | ||
183 | |||
184 | serio_pause_rx(ps2dev->serio); | 182 | serio_pause_rx(ps2dev->serio); |
185 | ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; | 183 | ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; |
186 | ps2dev->cmdcnt = receive; | 184 | ps2dev->cmdcnt = receive; |
@@ -231,7 +229,18 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
231 | ps2dev->flags = 0; | 229 | ps2dev->flags = 0; |
232 | serio_continue_rx(ps2dev->serio); | 230 | serio_continue_rx(ps2dev->serio); |
233 | 231 | ||
232 | return rc; | ||
233 | } | ||
234 | EXPORT_SYMBOL(__ps2_command); | ||
235 | |||
236 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | ||
237 | { | ||
238 | int rc; | ||
239 | |||
240 | mutex_lock(&ps2dev->cmd_mutex); | ||
241 | rc = __ps2_command(ps2dev, param, command); | ||
234 | mutex_unlock(&ps2dev->cmd_mutex); | 242 | mutex_unlock(&ps2dev->cmd_mutex); |
243 | |||
235 | return rc; | 244 | return rc; |
236 | } | 245 | } |
237 | EXPORT_SYMBOL(ps2_command); | 246 | EXPORT_SYMBOL(ps2_command); |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index d66f4944f2a0..0236f0d5fd91 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -931,15 +931,11 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
931 | #endif /* CONFIG_HOTPLUG */ | 931 | #endif /* CONFIG_HOTPLUG */ |
932 | 932 | ||
933 | #ifdef CONFIG_PM | 933 | #ifdef CONFIG_PM |
934 | static int serio_suspend(struct device *dev, pm_message_t state) | 934 | static int serio_suspend(struct device *dev) |
935 | { | 935 | { |
936 | struct serio *serio = to_serio_port(dev); | 936 | struct serio *serio = to_serio_port(dev); |
937 | 937 | ||
938 | if (!serio->suspended && state.event == PM_EVENT_SUSPEND) | 938 | serio_cleanup(serio); |
939 | serio_cleanup(serio); | ||
940 | |||
941 | serio->suspended = state.event == PM_EVENT_SUSPEND || | ||
942 | state.event == PM_EVENT_FREEZE; | ||
943 | 939 | ||
944 | return 0; | 940 | return 0; |
945 | } | 941 | } |
@@ -952,13 +948,17 @@ static int serio_resume(struct device *dev) | |||
952 | * Driver reconnect can take a while, so better let kseriod | 948 | * Driver reconnect can take a while, so better let kseriod |
953 | * deal with it. | 949 | * deal with it. |
954 | */ | 950 | */ |
955 | if (serio->suspended) { | 951 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); |
956 | serio->suspended = false; | ||
957 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); | ||
958 | } | ||
959 | 952 | ||
960 | return 0; | 953 | return 0; |
961 | } | 954 | } |
955 | |||
956 | static const struct dev_pm_ops serio_pm_ops = { | ||
957 | .suspend = serio_suspend, | ||
958 | .resume = serio_resume, | ||
959 | .poweroff = serio_suspend, | ||
960 | .restore = serio_resume, | ||
961 | }; | ||
962 | #endif /* CONFIG_PM */ | 962 | #endif /* CONFIG_PM */ |
963 | 963 | ||
964 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ | 964 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ |
@@ -1015,8 +1015,7 @@ static struct bus_type serio_bus = { | |||
1015 | .remove = serio_driver_remove, | 1015 | .remove = serio_driver_remove, |
1016 | .shutdown = serio_shutdown, | 1016 | .shutdown = serio_shutdown, |
1017 | #ifdef CONFIG_PM | 1017 | #ifdef CONFIG_PM |
1018 | .suspend = serio_suspend, | 1018 | .pm = &serio_pm_ops, |
1019 | .resume = serio_resume, | ||
1020 | #endif | 1019 | #endif |
1021 | }; | 1020 | }; |
1022 | 1021 | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 72e2712c7e2a..87a1ae63bcc4 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -366,11 +366,11 @@ config TOUCHSCREEN_WM97XX_ATMEL | |||
366 | be called atmel-wm97xx. | 366 | be called atmel-wm97xx. |
367 | 367 | ||
368 | config TOUCHSCREEN_WM97XX_MAINSTONE | 368 | config TOUCHSCREEN_WM97XX_MAINSTONE |
369 | tristate "WM97xx Mainstone accelerated touch" | 369 | tristate "WM97xx Mainstone/Palm accelerated touch" |
370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA | 370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA |
371 | help | 371 | help |
372 | Say Y here for support for streaming mode with WM97xx touchscreens | 372 | Say Y here for support for streaming mode with WM97xx touchscreens |
373 | on Mainstone systems. | 373 | on Mainstone, Palm Tungsten T5, TX and LifeDrive systems. |
374 | 374 | ||
375 | If unsure, say N. | 375 | If unsure, say N. |
376 | 376 | ||
@@ -406,6 +406,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
406 | - IRTOUCHSYSTEMS/UNITOP | 406 | - IRTOUCHSYSTEMS/UNITOP |
407 | - IdealTEK URTC1000 | 407 | - IdealTEK URTC1000 |
408 | - GoTop Super_Q2/GogoPen/PenPower tablets | 408 | - GoTop Super_Q2/GogoPen/PenPower tablets |
409 | - JASTEC USB Touch Controller/DigiTech DTR-02U | ||
409 | 410 | ||
410 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 411 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
411 | a usage description and the required user-space stuff. | 412 | a usage description and the required user-space stuff. |
@@ -468,6 +469,16 @@ config TOUCHSCREEN_USB_GOTOP | |||
468 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED | 469 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED |
469 | depends on TOUCHSCREEN_USB_COMPOSITE | 470 | depends on TOUCHSCREEN_USB_COMPOSITE |
470 | 471 | ||
472 | config TOUCHSCREEN_USB_JASTEC | ||
473 | default y | ||
474 | bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED | ||
475 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
476 | |||
477 | config TOUCHSCREEN_USB_E2I | ||
478 | default y | ||
479 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" | ||
480 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
481 | |||
471 | config TOUCHSCREEN_TOUCHIT213 | 482 | config TOUCHSCREEN_TOUCHIT213 |
472 | tristate "Sahara TouchIT-213 touchscreen" | 483 | tristate "Sahara TouchIT-213 touchscreen" |
473 | select SERIO | 484 | select SERIO |
@@ -492,6 +503,7 @@ config TOUCHSCREEN_TSC2007 | |||
492 | 503 | ||
493 | config TOUCHSCREEN_W90X900 | 504 | config TOUCHSCREEN_W90X900 |
494 | tristate "W90P910 touchscreen driver" | 505 | tristate "W90P910 touchscreen driver" |
506 | depends on HAVE_CLK | ||
495 | help | 507 | help |
496 | Say Y here if you have a W90P910 based touchscreen. | 508 | Say Y here if you have a W90P910 based touchscreen. |
497 | 509 | ||
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 055969e8be13..9c7fce4d74d0 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -204,14 +204,14 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
204 | goto err_free_dev; | 204 | goto err_free_dev; |
205 | } | 205 | } |
206 | 206 | ||
207 | if (!request_mem_region(res->start, res->end - res->start + 1, | 207 | if (!request_mem_region(res->start, resource_size(res), |
208 | "atmel tsadcc regs")) { | 208 | "atmel tsadcc regs")) { |
209 | dev_err(&pdev->dev, "resources is unavailable.\n"); | 209 | dev_err(&pdev->dev, "resources is unavailable.\n"); |
210 | err = -EBUSY; | 210 | err = -EBUSY; |
211 | goto err_free_dev; | 211 | goto err_free_dev; |
212 | } | 212 | } |
213 | 213 | ||
214 | tsc_base = ioremap(res->start, res->end - res->start + 1); | 214 | tsc_base = ioremap(res->start, resource_size(res)); |
215 | if (!tsc_base) { | 215 | if (!tsc_base) { |
216 | dev_err(&pdev->dev, "failed to map registers.\n"); | 216 | dev_err(&pdev->dev, "failed to map registers.\n"); |
217 | err = -ENOMEM; | 217 | err = -ENOMEM; |
@@ -286,7 +286,7 @@ err_free_irq: | |||
286 | err_unmap_regs: | 286 | err_unmap_regs: |
287 | iounmap(tsc_base); | 287 | iounmap(tsc_base); |
288 | err_release_mem: | 288 | err_release_mem: |
289 | release_mem_region(res->start, res->end - res->start + 1); | 289 | release_mem_region(res->start, resource_size(res)); |
290 | err_free_dev: | 290 | err_free_dev: |
291 | input_free_device(ts_dev->input); | 291 | input_free_device(ts_dev->input); |
292 | err_free_mem: | 292 | err_free_mem: |
@@ -305,7 +305,7 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) | |||
305 | 305 | ||
306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
307 | iounmap(tsc_base); | 307 | iounmap(tsc_base); |
308 | release_mem_region(res->start, res->end - res->start + 1); | 308 | release_mem_region(res->start, resource_size(res)); |
309 | 309 | ||
310 | clk_disable(ts_dev->clk); | 310 | clk_disable(ts_dev->clk); |
311 | clk_put(ts_dev->clk); | 311 | clk_put(ts_dev->clk); |
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 3ab92222a525..9029bd3f34e5 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
34 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
35 | #include <linux/input/eeti_ts.h> | ||
35 | 36 | ||
36 | static int flip_x; | 37 | static int flip_x; |
37 | module_param(flip_x, bool, 0644); | 38 | module_param(flip_x, bool, 0644); |
@@ -46,7 +47,7 @@ struct eeti_ts_priv { | |||
46 | struct input_dev *input; | 47 | struct input_dev *input; |
47 | struct work_struct work; | 48 | struct work_struct work; |
48 | struct mutex mutex; | 49 | struct mutex mutex; |
49 | int irq; | 50 | int irq, irq_active_high; |
50 | }; | 51 | }; |
51 | 52 | ||
52 | #define EETI_TS_BITDEPTH (11) | 53 | #define EETI_TS_BITDEPTH (11) |
@@ -58,6 +59,11 @@ struct eeti_ts_priv { | |||
58 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) | 59 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) |
59 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) | 60 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) |
60 | 61 | ||
62 | static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) | ||
63 | { | ||
64 | return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; | ||
65 | } | ||
66 | |||
61 | static void eeti_ts_read(struct work_struct *work) | 67 | static void eeti_ts_read(struct work_struct *work) |
62 | { | 68 | { |
63 | char buf[6]; | 69 | char buf[6]; |
@@ -67,7 +73,7 @@ static void eeti_ts_read(struct work_struct *work) | |||
67 | 73 | ||
68 | mutex_lock(&priv->mutex); | 74 | mutex_lock(&priv->mutex); |
69 | 75 | ||
70 | while (!gpio_get_value(irq_to_gpio(priv->irq)) && --to) | 76 | while (eeti_ts_irq_active(priv) && --to) |
71 | i2c_master_recv(priv->client, buf, sizeof(buf)); | 77 | i2c_master_recv(priv->client, buf, sizeof(buf)); |
72 | 78 | ||
73 | if (!to) { | 79 | if (!to) { |
@@ -140,8 +146,10 @@ static void eeti_ts_close(struct input_dev *dev) | |||
140 | static int __devinit eeti_ts_probe(struct i2c_client *client, | 146 | static int __devinit eeti_ts_probe(struct i2c_client *client, |
141 | const struct i2c_device_id *idp) | 147 | const struct i2c_device_id *idp) |
142 | { | 148 | { |
149 | struct eeti_ts_platform_data *pdata; | ||
143 | struct eeti_ts_priv *priv; | 150 | struct eeti_ts_priv *priv; |
144 | struct input_dev *input; | 151 | struct input_dev *input; |
152 | unsigned int irq_flags; | ||
145 | int err = -ENOMEM; | 153 | int err = -ENOMEM; |
146 | 154 | ||
147 | /* In contrast to what's described in the datasheet, there seems | 155 | /* In contrast to what's described in the datasheet, there seems |
@@ -180,6 +188,14 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
180 | priv->input = input; | 188 | priv->input = input; |
181 | priv->irq = client->irq; | 189 | priv->irq = client->irq; |
182 | 190 | ||
191 | pdata = client->dev.platform_data; | ||
192 | |||
193 | if (pdata) | ||
194 | priv->irq_active_high = pdata->irq_active_high; | ||
195 | |||
196 | irq_flags = priv->irq_active_high ? | ||
197 | IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; | ||
198 | |||
183 | INIT_WORK(&priv->work, eeti_ts_read); | 199 | INIT_WORK(&priv->work, eeti_ts_read); |
184 | i2c_set_clientdata(client, priv); | 200 | i2c_set_clientdata(client, priv); |
185 | input_set_drvdata(input, priv); | 201 | input_set_drvdata(input, priv); |
@@ -188,7 +204,7 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
188 | if (err) | 204 | if (err) |
189 | goto err1; | 205 | goto err1; |
190 | 206 | ||
191 | err = request_irq(priv->irq, eeti_ts_isr, IRQF_TRIGGER_FALLING, | 207 | err = request_irq(priv->irq, eeti_ts_isr, irq_flags, |
192 | client->name, priv); | 208 | client->name, priv); |
193 | if (err) { | 209 | if (err) { |
194 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | 210 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); |
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 4d3139e2099d..b4d7f63deff1 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -148,9 +148,10 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) | |||
148 | struct h3600_dev *ts = input_get_drvdata(dev); | 148 | struct h3600_dev *ts = input_get_drvdata(dev); |
149 | 149 | ||
150 | /* Must be in this order */ | 150 | /* Must be in this order */ |
151 | ts->serio->write(ts->serio, 1); | 151 | serio_write(ts->serio, 1); |
152 | ts->serio->write(ts->serio, pwr); | 152 | serio_write(ts->serio, pwr); |
153 | ts->serio->write(ts->serio, brightness); | 153 | serio_write(ts->serio, brightness); |
154 | |||
154 | return 0; | 155 | return 0; |
155 | } | 156 | } |
156 | 157 | ||
@@ -262,7 +263,7 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type, | |||
262 | 263 | ||
263 | switch (type) { | 264 | switch (type) { |
264 | case EV_LED: { | 265 | case EV_LED: { |
265 | // ts->serio->write(ts->serio, SOME_CMD); | 266 | // serio_write(ts->serio, SOME_CMD); |
266 | return 0; | 267 | return 0; |
267 | } | 268 | } |
268 | } | 269 | } |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 4cc047a5116e..8fc3b08deb3b 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
@@ -31,9 +31,11 @@ | |||
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/wm97xx.h> | 32 | #include <linux/wm97xx.h> |
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <linux/gpio.h> | ||
35 | |||
34 | #include <mach/regs-ac97.h> | 36 | #include <mach/regs-ac97.h> |
35 | 37 | ||
36 | #define VERSION "0.13" | 38 | #include <asm/mach-types.h> |
37 | 39 | ||
38 | struct continuous { | 40 | struct continuous { |
39 | u16 id; /* codec id */ | 41 | u16 id; /* codec id */ |
@@ -62,6 +64,7 @@ static const struct continuous cinfo[] = { | |||
62 | /* continuous speed index */ | 64 | /* continuous speed index */ |
63 | static int sp_idx; | 65 | static int sp_idx; |
64 | static u16 last, tries; | 66 | static u16 last, tries; |
67 | static int irq; | ||
65 | 68 | ||
66 | /* | 69 | /* |
67 | * Pen sampling frequency (Hz) in continuous mode. | 70 | * Pen sampling frequency (Hz) in continuous mode. |
@@ -171,7 +174,7 @@ up: | |||
171 | 174 | ||
172 | static int wm97xx_acc_startup(struct wm97xx *wm) | 175 | static int wm97xx_acc_startup(struct wm97xx *wm) |
173 | { | 176 | { |
174 | int idx = 0; | 177 | int idx = 0, ret = 0; |
175 | 178 | ||
176 | /* check we have a codec */ | 179 | /* check we have a codec */ |
177 | if (wm->ac97 == NULL) | 180 | if (wm->ac97 == NULL) |
@@ -191,18 +194,40 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
191 | "mainstone accelerated touchscreen driver, %d samples/sec\n", | 194 | "mainstone accelerated touchscreen driver, %d samples/sec\n", |
192 | cinfo[sp_idx].speed); | 195 | cinfo[sp_idx].speed); |
193 | 196 | ||
197 | /* IRQ driven touchscreen is used on Palm hardware */ | ||
198 | if (machine_is_palmt5() || machine_is_palmtx() || machine_is_palmld()) { | ||
199 | pen_int = 1; | ||
200 | irq = 27; | ||
201 | /* There is some obscure mutant of WM9712 interbred with WM9713 | ||
202 | * used on Palm HW */ | ||
203 | wm->variant = WM97xx_WM1613; | ||
204 | } else if (machine_is_mainstone() && pen_int) | ||
205 | irq = 4; | ||
206 | |||
207 | if (irq) { | ||
208 | ret = gpio_request(irq, "Touchscreen IRQ"); | ||
209 | if (ret) | ||
210 | goto out; | ||
211 | |||
212 | ret = gpio_direction_input(irq); | ||
213 | if (ret) { | ||
214 | gpio_free(irq); | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | wm->pen_irq = gpio_to_irq(irq); | ||
219 | set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); | ||
220 | } else /* pen irq not supported */ | ||
221 | pen_int = 0; | ||
222 | |||
194 | /* codec specific irq config */ | 223 | /* codec specific irq config */ |
195 | if (pen_int) { | 224 | if (pen_int) { |
196 | switch (wm->id) { | 225 | switch (wm->id) { |
197 | case WM9705_ID2: | 226 | case WM9705_ID2: |
198 | wm->pen_irq = IRQ_GPIO(4); | ||
199 | set_irq_type(IRQ_GPIO(4), IRQ_TYPE_EDGE_BOTH); | ||
200 | break; | 227 | break; |
201 | case WM9712_ID2: | 228 | case WM9712_ID2: |
202 | case WM9713_ID2: | 229 | case WM9713_ID2: |
203 | /* enable pen down interrupt */ | ||
204 | /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ | 230 | /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ |
205 | wm->pen_irq = MAINSTONE_AC97_IRQ; | ||
206 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | 231 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, |
207 | WM97XX_GPIO_POL_HIGH, | 232 | WM97XX_GPIO_POL_HIGH, |
208 | WM97XX_GPIO_STICKY, | 233 | WM97XX_GPIO_STICKY, |
@@ -220,23 +245,17 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
220 | } | 245 | } |
221 | } | 246 | } |
222 | 247 | ||
223 | return 0; | 248 | out: |
249 | return ret; | ||
224 | } | 250 | } |
225 | 251 | ||
226 | static void wm97xx_acc_shutdown(struct wm97xx *wm) | 252 | static void wm97xx_acc_shutdown(struct wm97xx *wm) |
227 | { | 253 | { |
228 | /* codec specific deconfig */ | 254 | /* codec specific deconfig */ |
229 | if (pen_int) { | 255 | if (pen_int) { |
230 | switch (wm->id & 0xffff) { | 256 | if (irq) |
231 | case WM9705_ID2: | 257 | gpio_free(irq); |
232 | wm->pen_irq = 0; | 258 | wm->pen_irq = 0; |
233 | break; | ||
234 | case WM9712_ID2: | ||
235 | case WM9713_ID2: | ||
236 | /* disable interrupt */ | ||
237 | wm->pen_irq = 0; | ||
238 | break; | ||
239 | } | ||
240 | } | 259 | } |
241 | } | 260 | } |
242 | 261 | ||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 880f58c6a7c4..7ef0d1420d3c 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -21,15 +21,14 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/hrtimer.h> | ||
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/input.h> | 25 | #include <linux/input.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
28 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
29 | #include <linux/i2c/tsc2007.h> | 28 | #include <linux/i2c/tsc2007.h> |
30 | 29 | ||
31 | #define TS_POLL_DELAY (10 * 1000) /* ns delay before the first sample */ | 30 | #define TS_POLL_DELAY 1 /* ms delay between samples */ |
32 | #define TS_POLL_PERIOD (5 * 1000) /* ns delay between samples */ | 31 | #define TS_POLL_PERIOD 1 /* ms delay between samples */ |
33 | 32 | ||
34 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) | 33 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) |
35 | #define TSC2007_MEASURE_AUX (0x2 << 4) | 34 | #define TSC2007_MEASURE_AUX (0x2 << 4) |
@@ -70,17 +69,14 @@ struct ts_event { | |||
70 | struct tsc2007 { | 69 | struct tsc2007 { |
71 | struct input_dev *input; | 70 | struct input_dev *input; |
72 | char phys[32]; | 71 | char phys[32]; |
73 | struct hrtimer timer; | 72 | struct delayed_work work; |
74 | struct ts_event tc; | ||
75 | 73 | ||
76 | struct i2c_client *client; | 74 | struct i2c_client *client; |
77 | 75 | ||
78 | spinlock_t lock; | ||
79 | |||
80 | u16 model; | 76 | u16 model; |
81 | u16 x_plate_ohms; | 77 | u16 x_plate_ohms; |
82 | 78 | ||
83 | unsigned pendown; | 79 | bool pendown; |
84 | int irq; | 80 | int irq; |
85 | 81 | ||
86 | int (*get_pendown_state)(void); | 82 | int (*get_pendown_state)(void); |
@@ -109,52 +105,96 @@ static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd) | |||
109 | return val; | 105 | return val; |
110 | } | 106 | } |
111 | 107 | ||
112 | static void tsc2007_send_event(void *tsc) | 108 | static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc) |
113 | { | 109 | { |
114 | struct tsc2007 *ts = tsc; | 110 | /* y- still on; turn on only y+ (and ADC) */ |
115 | u32 rt; | 111 | tc->y = tsc2007_xfer(tsc, READ_Y); |
116 | u16 x, y, z1, z2; | 112 | |
113 | /* turn y- off, x+ on, then leave in lowpower */ | ||
114 | tc->x = tsc2007_xfer(tsc, READ_X); | ||
115 | |||
116 | /* turn y+ off, x- on; we'll use formula #1 */ | ||
117 | tc->z1 = tsc2007_xfer(tsc, READ_Z1); | ||
118 | tc->z2 = tsc2007_xfer(tsc, READ_Z2); | ||
117 | 119 | ||
118 | x = ts->tc.x; | 120 | /* Prepare for next touch reading - power down ADC, enable PENIRQ */ |
119 | y = ts->tc.y; | 121 | tsc2007_xfer(tsc, PWRDOWN); |
120 | z1 = ts->tc.z1; | 122 | } |
121 | z2 = ts->tc.z2; | 123 | |
124 | static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) | ||
125 | { | ||
126 | u32 rt = 0; | ||
122 | 127 | ||
123 | /* range filtering */ | 128 | /* range filtering */ |
124 | if (x == MAX_12BIT) | 129 | if (tc->x == MAX_12BIT) |
125 | x = 0; | 130 | tc->x = 0; |
126 | 131 | ||
127 | if (likely(x && z1)) { | 132 | if (likely(tc->x && tc->z1)) { |
128 | /* compute touch pressure resistance using equation #1 */ | 133 | /* compute touch pressure resistance using equation #1 */ |
129 | rt = z2; | 134 | rt = tc->z2 - tc->z1; |
130 | rt -= z1; | 135 | rt *= tc->x; |
131 | rt *= x; | 136 | rt *= tsc->x_plate_ohms; |
132 | rt *= ts->x_plate_ohms; | 137 | rt /= tc->z1; |
133 | rt /= z1; | ||
134 | rt = (rt + 2047) >> 12; | 138 | rt = (rt + 2047) >> 12; |
135 | } else | 139 | } |
136 | rt = 0; | 140 | |
141 | return rt; | ||
142 | } | ||
143 | |||
144 | static void tsc2007_send_up_event(struct tsc2007 *tsc) | ||
145 | { | ||
146 | struct input_dev *input = tsc->input; | ||
137 | 147 | ||
138 | /* Sample found inconsistent by debouncing or pressure is beyond | 148 | dev_dbg(&tsc->client->dev, "UP\n"); |
139 | * the maximum. Don't report it to user space, repeat at least | 149 | |
140 | * once more the measurement | 150 | input_report_key(input, BTN_TOUCH, 0); |
151 | input_report_abs(input, ABS_PRESSURE, 0); | ||
152 | input_sync(input); | ||
153 | } | ||
154 | |||
155 | static void tsc2007_work(struct work_struct *work) | ||
156 | { | ||
157 | struct tsc2007 *ts = | ||
158 | container_of(to_delayed_work(work), struct tsc2007, work); | ||
159 | struct ts_event tc; | ||
160 | u32 rt; | ||
161 | |||
162 | /* | ||
163 | * NOTE: We can't rely on the pressure to determine the pen down | ||
164 | * state, even though this controller has a pressure sensor. | ||
165 | * The pressure value can fluctuate for quite a while after | ||
166 | * lifting the pen and in some cases may not even settle at the | ||
167 | * expected value. | ||
168 | * | ||
169 | * The only safe way to check for the pen up condition is in the | ||
170 | * work function by reading the pen signal state (it's a GPIO | ||
171 | * and IRQ). Unfortunately such callback is not always available, | ||
172 | * in that case we have rely on the pressure anyway. | ||
141 | */ | 173 | */ |
174 | if (ts->get_pendown_state) { | ||
175 | if (unlikely(!ts->get_pendown_state())) { | ||
176 | tsc2007_send_up_event(ts); | ||
177 | ts->pendown = false; | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | dev_dbg(&ts->client->dev, "pen is still down\n"); | ||
182 | } | ||
183 | |||
184 | tsc2007_read_values(ts, &tc); | ||
185 | |||
186 | rt = tsc2007_calculate_pressure(ts, &tc); | ||
142 | if (rt > MAX_12BIT) { | 187 | if (rt > MAX_12BIT) { |
188 | /* | ||
189 | * Sample found inconsistent by debouncing or pressure is | ||
190 | * beyond the maximum. Don't report it to user space, | ||
191 | * repeat at least once more the measurement. | ||
192 | */ | ||
143 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | 193 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); |
194 | goto out; | ||
144 | 195 | ||
145 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | ||
146 | HRTIMER_MODE_REL); | ||
147 | return; | ||
148 | } | 196 | } |
149 | 197 | ||
150 | /* NOTE: We can't rely on the pressure to determine the pen down | ||
151 | * state, even this controller has a pressure sensor. The pressure | ||
152 | * value can fluctuate for quite a while after lifting the pen and | ||
153 | * in some cases may not even settle at the expected value. | ||
154 | * | ||
155 | * The only safe way to check for the pen up condition is in the | ||
156 | * timer by reading the pen signal state (it's a GPIO _and_ IRQ). | ||
157 | */ | ||
158 | if (rt) { | 198 | if (rt) { |
159 | struct input_dev *input = ts->input; | 199 | struct input_dev *input = ts->input; |
160 | 200 | ||
@@ -162,102 +202,74 @@ static void tsc2007_send_event(void *tsc) | |||
162 | dev_dbg(&ts->client->dev, "DOWN\n"); | 202 | dev_dbg(&ts->client->dev, "DOWN\n"); |
163 | 203 | ||
164 | input_report_key(input, BTN_TOUCH, 1); | 204 | input_report_key(input, BTN_TOUCH, 1); |
165 | ts->pendown = 1; | 205 | ts->pendown = true; |
166 | } | 206 | } |
167 | 207 | ||
168 | input_report_abs(input, ABS_X, x); | 208 | input_report_abs(input, ABS_X, tc.x); |
169 | input_report_abs(input, ABS_Y, y); | 209 | input_report_abs(input, ABS_Y, tc.y); |
170 | input_report_abs(input, ABS_PRESSURE, rt); | 210 | input_report_abs(input, ABS_PRESSURE, rt); |
171 | 211 | ||
172 | input_sync(input); | 212 | input_sync(input); |
173 | 213 | ||
174 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", | 214 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", |
175 | x, y, rt); | 215 | tc.x, tc.y, rt); |
216 | |||
217 | } else if (!ts->get_pendown_state && ts->pendown) { | ||
218 | /* | ||
219 | * We don't have callback to check pendown state, so we | ||
220 | * have to assume that since pressure reported is 0 the | ||
221 | * pen was lifted up. | ||
222 | */ | ||
223 | tsc2007_send_up_event(ts); | ||
224 | ts->pendown = false; | ||
176 | } | 225 | } |
177 | 226 | ||
178 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 227 | out: |
179 | HRTIMER_MODE_REL); | 228 | if (ts->pendown) |
180 | } | 229 | schedule_delayed_work(&ts->work, |
181 | 230 | msecs_to_jiffies(TS_POLL_PERIOD)); | |
182 | static int tsc2007_read_values(struct tsc2007 *tsc) | 231 | else |
183 | { | ||
184 | /* y- still on; turn on only y+ (and ADC) */ | ||
185 | tsc->tc.y = tsc2007_xfer(tsc, READ_Y); | ||
186 | |||
187 | /* turn y- off, x+ on, then leave in lowpower */ | ||
188 | tsc->tc.x = tsc2007_xfer(tsc, READ_X); | ||
189 | |||
190 | /* turn y+ off, x- on; we'll use formula #1 */ | ||
191 | tsc->tc.z1 = tsc2007_xfer(tsc, READ_Z1); | ||
192 | tsc->tc.z2 = tsc2007_xfer(tsc, READ_Z2); | ||
193 | |||
194 | /* power down */ | ||
195 | tsc2007_xfer(tsc, PWRDOWN); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle) | ||
201 | { | ||
202 | struct tsc2007 *ts = container_of(handle, struct tsc2007, timer); | ||
203 | unsigned long flags; | ||
204 | |||
205 | spin_lock_irqsave(&ts->lock, flags); | ||
206 | |||
207 | if (unlikely(!ts->get_pendown_state() && ts->pendown)) { | ||
208 | struct input_dev *input = ts->input; | ||
209 | |||
210 | dev_dbg(&ts->client->dev, "UP\n"); | ||
211 | |||
212 | input_report_key(input, BTN_TOUCH, 0); | ||
213 | input_report_abs(input, ABS_PRESSURE, 0); | ||
214 | input_sync(input); | ||
215 | |||
216 | ts->pendown = 0; | ||
217 | enable_irq(ts->irq); | 232 | enable_irq(ts->irq); |
218 | } else { | ||
219 | /* pen is still down, continue with the measurement */ | ||
220 | dev_dbg(&ts->client->dev, "pen is still down\n"); | ||
221 | |||
222 | tsc2007_read_values(ts); | ||
223 | tsc2007_send_event(ts); | ||
224 | } | ||
225 | |||
226 | spin_unlock_irqrestore(&ts->lock, flags); | ||
227 | |||
228 | return HRTIMER_NORESTART; | ||
229 | } | 233 | } |
230 | 234 | ||
231 | static irqreturn_t tsc2007_irq(int irq, void *handle) | 235 | static irqreturn_t tsc2007_irq(int irq, void *handle) |
232 | { | 236 | { |
233 | struct tsc2007 *ts = handle; | 237 | struct tsc2007 *ts = handle; |
234 | unsigned long flags; | ||
235 | |||
236 | spin_lock_irqsave(&ts->lock, flags); | ||
237 | 238 | ||
238 | if (likely(ts->get_pendown_state())) { | 239 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) { |
239 | disable_irq_nosync(ts->irq); | 240 | disable_irq_nosync(ts->irq); |
240 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), | 241 | schedule_delayed_work(&ts->work, |
241 | HRTIMER_MODE_REL); | 242 | msecs_to_jiffies(TS_POLL_DELAY)); |
242 | } | 243 | } |
243 | 244 | ||
244 | if (ts->clear_penirq) | 245 | if (ts->clear_penirq) |
245 | ts->clear_penirq(); | 246 | ts->clear_penirq(); |
246 | 247 | ||
247 | spin_unlock_irqrestore(&ts->lock, flags); | ||
248 | |||
249 | return IRQ_HANDLED; | 248 | return IRQ_HANDLED; |
250 | } | 249 | } |
251 | 250 | ||
252 | static int tsc2007_probe(struct i2c_client *client, | 251 | static void tsc2007_free_irq(struct tsc2007 *ts) |
253 | const struct i2c_device_id *id) | 252 | { |
253 | free_irq(ts->irq, ts); | ||
254 | if (cancel_delayed_work_sync(&ts->work)) { | ||
255 | /* | ||
256 | * Work was pending, therefore we need to enable | ||
257 | * IRQ here to balance the disable_irq() done in the | ||
258 | * interrupt handler. | ||
259 | */ | ||
260 | enable_irq(ts->irq); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | static int __devinit tsc2007_probe(struct i2c_client *client, | ||
265 | const struct i2c_device_id *id) | ||
254 | { | 266 | { |
255 | struct tsc2007 *ts; | 267 | struct tsc2007 *ts; |
256 | struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data; | 268 | struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data; |
257 | struct input_dev *input_dev; | 269 | struct input_dev *input_dev; |
258 | int err; | 270 | int err; |
259 | 271 | ||
260 | if (!pdata || !pdata->get_pendown_state) { | 272 | if (!pdata) { |
261 | dev_err(&client->dev, "platform data is required!\n"); | 273 | dev_err(&client->dev, "platform data is required!\n"); |
262 | return -EINVAL; | 274 | return -EINVAL; |
263 | } | 275 | } |
@@ -274,22 +286,15 @@ static int tsc2007_probe(struct i2c_client *client, | |||
274 | } | 286 | } |
275 | 287 | ||
276 | ts->client = client; | 288 | ts->client = client; |
277 | i2c_set_clientdata(client, ts); | 289 | ts->irq = client->irq; |
278 | |||
279 | ts->input = input_dev; | 290 | ts->input = input_dev; |
280 | 291 | INIT_DELAYED_WORK(&ts->work, tsc2007_work); | |
281 | hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
282 | ts->timer.function = tsc2007_timer; | ||
283 | |||
284 | spin_lock_init(&ts->lock); | ||
285 | 292 | ||
286 | ts->model = pdata->model; | 293 | ts->model = pdata->model; |
287 | ts->x_plate_ohms = pdata->x_plate_ohms; | 294 | ts->x_plate_ohms = pdata->x_plate_ohms; |
288 | ts->get_pendown_state = pdata->get_pendown_state; | 295 | ts->get_pendown_state = pdata->get_pendown_state; |
289 | ts->clear_penirq = pdata->clear_penirq; | 296 | ts->clear_penirq = pdata->clear_penirq; |
290 | 297 | ||
291 | pdata->init_platform_hw(); | ||
292 | |||
293 | snprintf(ts->phys, sizeof(ts->phys), | 298 | snprintf(ts->phys, sizeof(ts->phys), |
294 | "%s/input0", dev_name(&client->dev)); | 299 | "%s/input0", dev_name(&client->dev)); |
295 | 300 | ||
@@ -304,9 +309,8 @@ static int tsc2007_probe(struct i2c_client *client, | |||
304 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | 309 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); |
305 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | 310 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); |
306 | 311 | ||
307 | tsc2007_read_values(ts); | 312 | if (pdata->init_platform_hw) |
308 | 313 | pdata->init_platform_hw(); | |
309 | ts->irq = client->irq; | ||
310 | 314 | ||
311 | err = request_irq(ts->irq, tsc2007_irq, 0, | 315 | err = request_irq(ts->irq, tsc2007_irq, 0, |
312 | client->dev.driver->name, ts); | 316 | client->dev.driver->name, ts); |
@@ -315,33 +319,39 @@ static int tsc2007_probe(struct i2c_client *client, | |||
315 | goto err_free_mem; | 319 | goto err_free_mem; |
316 | } | 320 | } |
317 | 321 | ||
322 | /* Prepare for touch readings - power down ADC and enable PENIRQ */ | ||
323 | err = tsc2007_xfer(ts, PWRDOWN); | ||
324 | if (err < 0) | ||
325 | goto err_free_irq; | ||
326 | |||
318 | err = input_register_device(input_dev); | 327 | err = input_register_device(input_dev); |
319 | if (err) | 328 | if (err) |
320 | goto err_free_irq; | 329 | goto err_free_irq; |
321 | 330 | ||
322 | dev_info(&client->dev, "registered with irq (%d)\n", ts->irq); | 331 | i2c_set_clientdata(client, ts); |
323 | 332 | ||
324 | return 0; | 333 | return 0; |
325 | 334 | ||
326 | err_free_irq: | 335 | err_free_irq: |
327 | free_irq(ts->irq, ts); | 336 | tsc2007_free_irq(ts); |
328 | hrtimer_cancel(&ts->timer); | 337 | if (pdata->exit_platform_hw) |
338 | pdata->exit_platform_hw(); | ||
329 | err_free_mem: | 339 | err_free_mem: |
330 | input_free_device(input_dev); | 340 | input_free_device(input_dev); |
331 | kfree(ts); | 341 | kfree(ts); |
332 | return err; | 342 | return err; |
333 | } | 343 | } |
334 | 344 | ||
335 | static int tsc2007_remove(struct i2c_client *client) | 345 | static int __devexit tsc2007_remove(struct i2c_client *client) |
336 | { | 346 | { |
337 | struct tsc2007 *ts = i2c_get_clientdata(client); | 347 | struct tsc2007 *ts = i2c_get_clientdata(client); |
338 | struct tsc2007_platform_data *pdata; | 348 | struct tsc2007_platform_data *pdata = client->dev.platform_data; |
339 | 349 | ||
340 | pdata = client->dev.platform_data; | 350 | tsc2007_free_irq(ts); |
341 | pdata->exit_platform_hw(); | 351 | |
352 | if (pdata->exit_platform_hw) | ||
353 | pdata->exit_platform_hw(); | ||
342 | 354 | ||
343 | free_irq(ts->irq, ts); | ||
344 | hrtimer_cancel(&ts->timer); | ||
345 | input_unregister_device(ts->input); | 355 | input_unregister_device(ts->input); |
346 | kfree(ts); | 356 | kfree(ts); |
347 | 357 | ||
@@ -362,7 +372,7 @@ static struct i2c_driver tsc2007_driver = { | |||
362 | }, | 372 | }, |
363 | .id_table = tsc2007_idtable, | 373 | .id_table = tsc2007_idtable, |
364 | .probe = tsc2007_probe, | 374 | .probe = tsc2007_probe, |
365 | .remove = tsc2007_remove, | 375 | .remove = __devexit_p(tsc2007_remove), |
366 | }; | 376 | }; |
367 | 377 | ||
368 | static int __init tsc2007_init(void) | 378 | static int __init tsc2007_init(void) |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 3a7a58222f83..095f84b1f56e 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -128,9 +128,10 @@ static inline unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb) | |||
128 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); | 128 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); |
129 | } | 129 | } |
130 | 130 | ||
131 | static inline int ucb1400_ts_pen_down(struct snd_ac97 *ac97) | 131 | static inline int ucb1400_ts_pen_up(struct snd_ac97 *ac97) |
132 | { | 132 | { |
133 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); | 133 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); |
134 | |||
134 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); | 135 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); |
135 | } | 136 | } |
136 | 137 | ||
@@ -209,7 +210,7 @@ static int ucb1400_ts_thread(void *_ucb) | |||
209 | 210 | ||
210 | msleep(10); | 211 | msleep(10); |
211 | 212 | ||
212 | if (ucb1400_ts_pen_down(ucb->ac97)) { | 213 | if (ucb1400_ts_pen_up(ucb->ac97)) { |
213 | ucb1400_ts_irq_enable(ucb->ac97); | 214 | ucb1400_ts_irq_enable(ucb->ac97); |
214 | 215 | ||
215 | /* | 216 | /* |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index fb7cb9bdfbd5..68ece5801a58 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * - IdealTEK URTC1000 | 13 | * - IdealTEK URTC1000 |
14 | * - General Touch | 14 | * - General Touch |
15 | * - GoTop Super_Q2/GogoPen/PenPower tablets | 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets |
16 | * - JASTEC USB touch controller/DigiTech DTR-02U | ||
16 | * | 17 | * |
17 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 18 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
18 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 19 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
@@ -118,6 +119,8 @@ enum { | |||
118 | DEVTYPE_IDEALTEK, | 119 | DEVTYPE_IDEALTEK, |
119 | DEVTYPE_GENERAL_TOUCH, | 120 | DEVTYPE_GENERAL_TOUCH, |
120 | DEVTYPE_GOTOP, | 121 | DEVTYPE_GOTOP, |
122 | DEVTYPE_JASTEC, | ||
123 | DEVTYPE_E2I, | ||
121 | }; | 124 | }; |
122 | 125 | ||
123 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 126 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
@@ -191,11 +194,51 @@ static struct usb_device_id usbtouch_devices[] = { | |||
191 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, | 194 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, |
192 | #endif | 195 | #endif |
193 | 196 | ||
197 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
198 | {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, | ||
199 | #endif | ||
200 | |||
201 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
202 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, | ||
203 | #endif | ||
194 | {} | 204 | {} |
195 | }; | 205 | }; |
196 | 206 | ||
197 | 207 | ||
198 | /***************************************************************************** | 208 | /***************************************************************************** |
209 | * e2i Part | ||
210 | */ | ||
211 | |||
212 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
213 | static int e2i_init(struct usbtouch_usb *usbtouch) | ||
214 | { | ||
215 | int ret; | ||
216 | |||
217 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | ||
218 | 0x01, 0x02, 0x0000, 0x0081, | ||
219 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
220 | |||
221 | dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", | ||
222 | __func__, ret); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
227 | { | ||
228 | int tmp = (pkt[0] << 8) | pkt[1]; | ||
229 | dev->x = (pkt[2] << 8) | pkt[3]; | ||
230 | dev->y = (pkt[4] << 8) | pkt[5]; | ||
231 | |||
232 | tmp = tmp - 0xA000; | ||
233 | dev->touch = (tmp > 0); | ||
234 | dev->press = (tmp > 0 ? tmp : 0); | ||
235 | |||
236 | return 1; | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | |||
241 | /***************************************************************************** | ||
199 | * eGalax part | 242 | * eGalax part |
200 | */ | 243 | */ |
201 | 244 | ||
@@ -559,6 +602,21 @@ static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
559 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; | 602 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; |
560 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; | 603 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; |
561 | dev->touch = pkt[0] & 0x01; | 604 | dev->touch = pkt[0] & 0x01; |
605 | |||
606 | return 1; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | /***************************************************************************** | ||
611 | * JASTEC Part | ||
612 | */ | ||
613 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
614 | static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
615 | { | ||
616 | dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); | ||
617 | dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); | ||
618 | dev->touch = (pkt[0] & 0x40) >> 6; | ||
619 | |||
562 | return 1; | 620 | return 1; |
563 | } | 621 | } |
564 | #endif | 622 | #endif |
@@ -702,6 +760,29 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
702 | .read_data = gotop_read_data, | 760 | .read_data = gotop_read_data, |
703 | }, | 761 | }, |
704 | #endif | 762 | #endif |
763 | |||
764 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
765 | [DEVTYPE_JASTEC] = { | ||
766 | .min_xc = 0x0, | ||
767 | .max_xc = 0x0fff, | ||
768 | .min_yc = 0x0, | ||
769 | .max_yc = 0x0fff, | ||
770 | .rept_size = 4, | ||
771 | .read_data = jastec_read_data, | ||
772 | }, | ||
773 | #endif | ||
774 | |||
775 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
776 | [DEVTYPE_E2I] = { | ||
777 | .min_xc = 0x0, | ||
778 | .max_xc = 0x7fff, | ||
779 | .min_yc = 0x0, | ||
780 | .max_yc = 0x7fff, | ||
781 | .rept_size = 6, | ||
782 | .init = e2i_init, | ||
783 | .read_data = e2i_read_data, | ||
784 | }, | ||
785 | #endif | ||
705 | }; | 786 | }; |
706 | 787 | ||
707 | 788 | ||
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 6071f5882572..dc4c9d6b67c7 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/clk.h> | ||
16 | #include <linux/input.h> | 17 | #include <linux/input.h> |
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | 19 | ||
@@ -47,8 +48,8 @@ enum ts_state { | |||
47 | struct w90p910_ts { | 48 | struct w90p910_ts { |
48 | struct input_dev *input; | 49 | struct input_dev *input; |
49 | struct timer_list timer; | 50 | struct timer_list timer; |
51 | struct clk *clk; | ||
50 | int irq_num; | 52 | int irq_num; |
51 | void __iomem *clocken; | ||
52 | void __iomem *ts_reg; | 53 | void __iomem *ts_reg; |
53 | spinlock_t lock; | 54 | spinlock_t lock; |
54 | enum ts_state state; | 55 | enum ts_state state; |
@@ -166,8 +167,7 @@ static int w90p910_open(struct input_dev *dev) | |||
166 | unsigned long val; | 167 | unsigned long val; |
167 | 168 | ||
168 | /* enable the ADC clock */ | 169 | /* enable the ADC clock */ |
169 | val = __raw_readl(w90p910_ts->clocken); | 170 | clk_enable(w90p910_ts->clk); |
170 | __raw_writel(val | ADC_CLK_EN, w90p910_ts->clocken); | ||
171 | 171 | ||
172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); | 172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); |
173 | msleep(1); | 173 | msleep(1); |
@@ -211,8 +211,7 @@ static void w90p910_close(struct input_dev *dev) | |||
211 | del_timer_sync(&w90p910_ts->timer); | 211 | del_timer_sync(&w90p910_ts->timer); |
212 | 212 | ||
213 | /* stop the ADC clock */ | 213 | /* stop the ADC clock */ |
214 | val = __raw_readl(w90p910_ts->clocken); | 214 | clk_disable(w90p910_ts->clk); |
215 | __raw_writel(val & ~ADC_CLK_EN, w90p910_ts->clocken); | ||
216 | } | 215 | } |
217 | 216 | ||
218 | static int __devinit w90x900ts_probe(struct platform_device *pdev) | 217 | static int __devinit w90x900ts_probe(struct platform_device *pdev) |
@@ -241,26 +240,24 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
241 | goto fail1; | 240 | goto fail1; |
242 | } | 241 | } |
243 | 242 | ||
244 | if (!request_mem_region(res->start, res->end - res->start + 1, | 243 | if (!request_mem_region(res->start, resource_size(res), |
245 | pdev->name)) { | 244 | pdev->name)) { |
246 | err = -EBUSY; | 245 | err = -EBUSY; |
247 | goto fail1; | 246 | goto fail1; |
248 | } | 247 | } |
249 | 248 | ||
250 | w90p910_ts->ts_reg = ioremap(res->start, res->end - res->start + 1); | 249 | w90p910_ts->ts_reg = ioremap(res->start, resource_size(res)); |
251 | if (!w90p910_ts->ts_reg) { | 250 | if (!w90p910_ts->ts_reg) { |
252 | err = -ENOMEM; | 251 | err = -ENOMEM; |
253 | goto fail2; | 252 | goto fail2; |
254 | } | 253 | } |
255 | 254 | ||
256 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 255 | w90p910_ts->clk = clk_get(&pdev->dev, NULL); |
257 | if (!res) { | 256 | if (IS_ERR(w90p910_ts->clk)) { |
258 | err = -ENXIO; | 257 | err = PTR_ERR(w90p910_ts->clk); |
259 | goto fail3; | 258 | goto fail3; |
260 | } | 259 | } |
261 | 260 | ||
262 | w90p910_ts->clocken = (void __iomem *)res->start; | ||
263 | |||
264 | input_dev->name = "W90P910 TouchScreen"; | 261 | input_dev->name = "W90P910 TouchScreen"; |
265 | input_dev->phys = "w90p910ts/event0"; | 262 | input_dev->phys = "w90p910ts/event0"; |
266 | input_dev->id.bustype = BUS_HOST; | 263 | input_dev->id.bustype = BUS_HOST; |
@@ -283,20 +280,21 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
283 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, | 280 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, |
284 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { | 281 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { |
285 | err = -EBUSY; | 282 | err = -EBUSY; |
286 | goto fail3; | 283 | goto fail4; |
287 | } | 284 | } |
288 | 285 | ||
289 | err = input_register_device(w90p910_ts->input); | 286 | err = input_register_device(w90p910_ts->input); |
290 | if (err) | 287 | if (err) |
291 | goto fail4; | 288 | goto fail5; |
292 | 289 | ||
293 | platform_set_drvdata(pdev, w90p910_ts); | 290 | platform_set_drvdata(pdev, w90p910_ts); |
294 | 291 | ||
295 | return 0; | 292 | return 0; |
296 | 293 | ||
297 | fail4: free_irq(w90p910_ts->irq_num, w90p910_ts); | 294 | fail5: free_irq(w90p910_ts->irq_num, w90p910_ts); |
295 | fail4: clk_put(w90p910_ts->clk); | ||
298 | fail3: iounmap(w90p910_ts->ts_reg); | 296 | fail3: iounmap(w90p910_ts->ts_reg); |
299 | fail2: release_mem_region(res->start, res->end - res->start + 1); | 297 | fail2: release_mem_region(res->start, resource_size(res)); |
300 | fail1: input_free_device(input_dev); | 298 | fail1: input_free_device(input_dev); |
301 | kfree(w90p910_ts); | 299 | kfree(w90p910_ts); |
302 | return err; | 300 | return err; |
@@ -311,8 +309,10 @@ static int __devexit w90x900ts_remove(struct platform_device *pdev) | |||
311 | del_timer_sync(&w90p910_ts->timer); | 309 | del_timer_sync(&w90p910_ts->timer); |
312 | iounmap(w90p910_ts->ts_reg); | 310 | iounmap(w90p910_ts->ts_reg); |
313 | 311 | ||
312 | clk_put(w90p910_ts->clk); | ||
313 | |||
314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
315 | release_mem_region(res->start, res->end - res->start + 1); | 315 | release_mem_region(res->start, resource_size(res)); |
316 | 316 | ||
317 | input_unregister_device(w90p910_ts->input); | 317 | input_unregister_device(w90p910_ts->input); |
318 | kfree(w90p910_ts); | 318 | kfree(w90p910_ts); |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 2957d48e0045..252eb11fe9db 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -204,7 +204,7 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, | |||
204 | else | 204 | else |
205 | reg &= ~gpio; | 205 | reg &= ~gpio; |
206 | 206 | ||
207 | if (wm->id == WM9712_ID2) | 207 | if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) |
208 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); | 208 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); |
209 | else | 209 | else |
210 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); | 210 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); |
@@ -307,7 +307,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) | |||
307 | WM97XX_GPIO_13); | 307 | WM97XX_GPIO_13); |
308 | } | 308 | } |
309 | 309 | ||
310 | if (wm->id == WM9712_ID2) | 310 | if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) |
311 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & | 311 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & |
312 | ~WM97XX_GPIO_13) << 1); | 312 | ~WM97XX_GPIO_13) << 1); |
313 | else | 313 | else |
@@ -582,6 +582,8 @@ static int wm97xx_probe(struct device *dev) | |||
582 | 582 | ||
583 | wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); | 583 | wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); |
584 | 584 | ||
585 | wm->variant = WM97xx_GENERIC; | ||
586 | |||
585 | dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); | 587 | dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); |
586 | 588 | ||
587 | switch (wm->id & 0xff) { | 589 | switch (wm->id & 0xff) { |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index f99bc7f089f1..a7eb7277b106 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -575,7 +575,7 @@ static void pci_pm_complete(struct device *dev) | |||
575 | static int pci_pm_suspend(struct device *dev) | 575 | static int pci_pm_suspend(struct device *dev) |
576 | { | 576 | { |
577 | struct pci_dev *pci_dev = to_pci_dev(dev); | 577 | struct pci_dev *pci_dev = to_pci_dev(dev); |
578 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 578 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
579 | 579 | ||
580 | if (pci_has_legacy_pm_support(pci_dev)) | 580 | if (pci_has_legacy_pm_support(pci_dev)) |
581 | return pci_legacy_suspend(dev, PMSG_SUSPEND); | 581 | return pci_legacy_suspend(dev, PMSG_SUSPEND); |
@@ -613,7 +613,7 @@ static int pci_pm_suspend(struct device *dev) | |||
613 | static int pci_pm_suspend_noirq(struct device *dev) | 613 | static int pci_pm_suspend_noirq(struct device *dev) |
614 | { | 614 | { |
615 | struct pci_dev *pci_dev = to_pci_dev(dev); | 615 | struct pci_dev *pci_dev = to_pci_dev(dev); |
616 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 616 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
617 | 617 | ||
618 | if (pci_has_legacy_pm_support(pci_dev)) | 618 | if (pci_has_legacy_pm_support(pci_dev)) |
619 | return pci_legacy_suspend_late(dev, PMSG_SUSPEND); | 619 | return pci_legacy_suspend_late(dev, PMSG_SUSPEND); |
@@ -672,7 +672,7 @@ static int pci_pm_resume_noirq(struct device *dev) | |||
672 | static int pci_pm_resume(struct device *dev) | 672 | static int pci_pm_resume(struct device *dev) |
673 | { | 673 | { |
674 | struct pci_dev *pci_dev = to_pci_dev(dev); | 674 | struct pci_dev *pci_dev = to_pci_dev(dev); |
675 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 675 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
676 | int error = 0; | 676 | int error = 0; |
677 | 677 | ||
678 | /* | 678 | /* |
@@ -711,7 +711,7 @@ static int pci_pm_resume(struct device *dev) | |||
711 | static int pci_pm_freeze(struct device *dev) | 711 | static int pci_pm_freeze(struct device *dev) |
712 | { | 712 | { |
713 | struct pci_dev *pci_dev = to_pci_dev(dev); | 713 | struct pci_dev *pci_dev = to_pci_dev(dev); |
714 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 714 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
715 | 715 | ||
716 | if (pci_has_legacy_pm_support(pci_dev)) | 716 | if (pci_has_legacy_pm_support(pci_dev)) |
717 | return pci_legacy_suspend(dev, PMSG_FREEZE); | 717 | return pci_legacy_suspend(dev, PMSG_FREEZE); |
@@ -780,7 +780,7 @@ static int pci_pm_thaw_noirq(struct device *dev) | |||
780 | static int pci_pm_thaw(struct device *dev) | 780 | static int pci_pm_thaw(struct device *dev) |
781 | { | 781 | { |
782 | struct pci_dev *pci_dev = to_pci_dev(dev); | 782 | struct pci_dev *pci_dev = to_pci_dev(dev); |
783 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 783 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
784 | int error = 0; | 784 | int error = 0; |
785 | 785 | ||
786 | if (pci_has_legacy_pm_support(pci_dev)) | 786 | if (pci_has_legacy_pm_support(pci_dev)) |
@@ -799,7 +799,7 @@ static int pci_pm_thaw(struct device *dev) | |||
799 | static int pci_pm_poweroff(struct device *dev) | 799 | static int pci_pm_poweroff(struct device *dev) |
800 | { | 800 | { |
801 | struct pci_dev *pci_dev = to_pci_dev(dev); | 801 | struct pci_dev *pci_dev = to_pci_dev(dev); |
802 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 802 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
803 | 803 | ||
804 | if (pci_has_legacy_pm_support(pci_dev)) | 804 | if (pci_has_legacy_pm_support(pci_dev)) |
805 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); | 805 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); |
@@ -872,7 +872,7 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
872 | static int pci_pm_restore(struct device *dev) | 872 | static int pci_pm_restore(struct device *dev) |
873 | { | 873 | { |
874 | struct pci_dev *pci_dev = to_pci_dev(dev); | 874 | struct pci_dev *pci_dev = to_pci_dev(dev); |
875 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 875 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
876 | int error = 0; | 876 | int error = 0; |
877 | 877 | ||
878 | /* | 878 | /* |
@@ -910,7 +910,7 @@ static int pci_pm_restore(struct device *dev) | |||
910 | 910 | ||
911 | #endif /* !CONFIG_HIBERNATION */ | 911 | #endif /* !CONFIG_HIBERNATION */ |
912 | 912 | ||
913 | struct dev_pm_ops pci_dev_pm_ops = { | 913 | const struct dev_pm_ops pci_dev_pm_ops = { |
914 | .prepare = pci_pm_prepare, | 914 | .prepare = pci_pm_prepare, |
915 | .complete = pci_pm_complete, | 915 | .complete = pci_pm_complete, |
916 | .suspend = pci_pm_suspend, | 916 | .suspend = pci_pm_suspend, |