diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-03-17 22:40:50 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-03-17 22:40:50 -0400 |
commit | 688d794c4c3f8b08c814381ee2edd3ede5856056 (patch) | |
tree | ef680add71e2a9588d07d8b594edbc1b5cd127d7 /drivers/input | |
parent | 16142655269aaf580488e074eabfdcf0fb4e3687 (diff) | |
parent | a937536b868b8369b98967929045f1df54234323 (diff) |
Merge tag 'v3.9-rc3' into next
Merge with mainline to bring in module_platform_driver_probe() and
devm_ioremap_resource().
Diffstat (limited to 'drivers/input')
39 files changed, 993 insertions, 631 deletions
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index 53eaf89f2db5..71db1930573f 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c | |||
@@ -252,7 +252,7 @@ void input_mt_sync_frame(struct input_dev *dev) | |||
252 | 252 | ||
253 | if (mt->flags & INPUT_MT_DROP_UNUSED) { | 253 | if (mt->flags & INPUT_MT_DROP_UNUSED) { |
254 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { | 254 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { |
255 | if (s->frame == mt->frame) | 255 | if (input_mt_is_used(mt, s)) |
256 | continue; | 256 | continue; |
257 | input_mt_slot(dev, s - mt->slots); | 257 | input_mt_slot(dev, s - mt->slots); |
258 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); | 258 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); |
diff --git a/drivers/input/input.c b/drivers/input/input.c index ce01332f7b3a..c04469928925 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -1785,12 +1785,13 @@ static void devm_input_device_release(struct device *dev, void *res) | |||
1785 | * its driver (or binding fails). Once managed input device is allocated, | 1785 | * its driver (or binding fails). Once managed input device is allocated, |
1786 | * it is ready to be set up and registered in the same fashion as regular | 1786 | * it is ready to be set up and registered in the same fashion as regular |
1787 | * input device. There are no special devm_input_device_[un]register() | 1787 | * input device. There are no special devm_input_device_[un]register() |
1788 | * variants, regular ones work with both managed and unmanaged devices. | 1788 | * variants, regular ones work with both managed and unmanaged devices, |
1789 | * should you need them. In most cases however, managed input device need | ||
1790 | * not be explicitly unregistered or freed. | ||
1789 | * | 1791 | * |
1790 | * NOTE: the owner device is set up as parent of input device and users | 1792 | * NOTE: the owner device is set up as parent of input device and users |
1791 | * should not override it. | 1793 | * should not override it. |
1792 | */ | 1794 | */ |
1793 | |||
1794 | struct input_dev *devm_input_allocate_device(struct device *dev) | 1795 | struct input_dev *devm_input_allocate_device(struct device *dev) |
1795 | { | 1796 | { |
1796 | struct input_dev *input; | 1797 | struct input_dev *input; |
@@ -2004,6 +2005,17 @@ static void devm_input_device_unregister(struct device *dev, void *res) | |||
2004 | * Once device has been successfully registered it can be unregistered | 2005 | * Once device has been successfully registered it can be unregistered |
2005 | * with input_unregister_device(); input_free_device() should not be | 2006 | * with input_unregister_device(); input_free_device() should not be |
2006 | * called in this case. | 2007 | * called in this case. |
2008 | * | ||
2009 | * Note that this function is also used to register managed input devices | ||
2010 | * (ones allocated with devm_input_allocate_device()). Such managed input | ||
2011 | * devices need not be explicitly unregistered or freed, their tear down | ||
2012 | * is controlled by the devres infrastructure. It is also worth noting | ||
2013 | * that tear down of managed input devices is internally a 2-step process: | ||
2014 | * registered managed input device is first unregistered, but stays in | ||
2015 | * memory and can still handle input_event() calls (although events will | ||
2016 | * not be delivered anywhere). The freeing of managed input device will | ||
2017 | * happen later, when devres stack is unwound to the point where device | ||
2018 | * allocation was made. | ||
2007 | */ | 2019 | */ |
2008 | int input_register_device(struct input_dev *dev) | 2020 | int input_register_device(struct input_dev *dev) |
2009 | { | 2021 | { |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 358cd7ee905b..7cd74e29cbc8 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -162,7 +162,7 @@ static unsigned int get_time_pit(void) | |||
162 | #define GET_TIME(x) do { x = get_cycles(); } while (0) | 162 | #define GET_TIME(x) do { x = get_cycles(); } while (0) |
163 | #define DELTA(x,y) ((y)-(x)) | 163 | #define DELTA(x,y) ((y)-(x)) |
164 | #define TIME_NAME "PCC" | 164 | #define TIME_NAME "PCC" |
165 | #elif defined(CONFIG_MN10300) | 165 | #elif defined(CONFIG_MN10300) || defined(CONFIG_TILE) |
166 | #define GET_TIME(x) do { x = get_cycles(); } while (0) | 166 | #define GET_TIME(x) do { x = get_cycles(); } while (0) |
167 | #define DELTA(x, y) ((x) - (y)) | 167 | #define DELTA(x, y) ((x) - (y)) |
168 | #define TIME_NAME "TSC" | 168 | #define TIME_NAME "TSC" |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 83811e45d633..d6cbfe9df218 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -118,11 +118,12 @@ static const struct xpad_device { | |||
118 | u8 xtype; | 118 | u8 xtype; |
119 | } xpad_device[] = { | 119 | } xpad_device[] = { |
120 | { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, | 120 | { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, |
121 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, | ||
122 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, | 121 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, |
123 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, | 122 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, |
123 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, | ||
124 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, | ||
125 | { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, | ||
124 | { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, | 126 | { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, |
125 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, | ||
126 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, | 127 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, |
127 | { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, | 128 | { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, |
128 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, | 129 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, |
@@ -136,9 +137,12 @@ static const struct xpad_device { | |||
136 | { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 137 | { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
137 | { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX }, | 138 | { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX }, |
138 | { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, | 139 | { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, |
140 | { 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", XTYPE_XBOX360 }, | ||
139 | { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, | 141 | { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, |
140 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 142 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
143 | { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 }, | ||
141 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, | 144 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, |
145 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, | ||
142 | { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, | 146 | { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, |
143 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, | 147 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, |
144 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, | 148 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, |
@@ -148,24 +152,28 @@ static const struct xpad_device { | |||
148 | { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, | 152 | { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, |
149 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, | 153 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, |
150 | { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, | 154 | { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, |
151 | { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, | 155 | { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
152 | { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, | 156 | { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, |
157 | { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, | ||
153 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, | 158 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, |
159 | { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, | ||
160 | { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, | ||
154 | { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, | 161 | { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, |
155 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, | 162 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, |
156 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, | 163 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, |
157 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | ||
158 | { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | 164 | { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
159 | { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | 165 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
160 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, | 166 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, |
161 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 167 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
162 | { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, | 168 | { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, |
163 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, | 169 | { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
164 | { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, | 170 | { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, |
165 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | 171 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
166 | { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, | 172 | { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, |
167 | { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, | 173 | { 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 }, |
168 | { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | 174 | { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, |
175 | { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, | ||
176 | { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, | ||
169 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, | 177 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, |
170 | { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } | 178 | { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } |
171 | }; | 179 | }; |
@@ -235,7 +243,7 @@ static const signed short xpad_abs_triggers[] = { | |||
235 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ | 243 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ |
236 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } | 244 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } |
237 | 245 | ||
238 | static struct usb_device_id xpad_table [] = { | 246 | static struct usb_device_id xpad_table[] = { |
239 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ | 247 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ |
240 | XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ | 248 | XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ |
241 | XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ | 249 | XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ |
@@ -248,10 +256,11 @@ static struct usb_device_id xpad_table [] = { | |||
248 | XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ | 256 | XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ |
249 | XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ | 257 | XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ |
250 | XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ | 258 | XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ |
259 | XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ | ||
251 | { } | 260 | { } |
252 | }; | 261 | }; |
253 | 262 | ||
254 | MODULE_DEVICE_TABLE (usb, xpad_table); | 263 | MODULE_DEVICE_TABLE(usb, xpad_table); |
255 | 264 | ||
256 | struct usb_xpad { | 265 | struct usb_xpad { |
257 | struct input_dev *dev; /* input device interface */ | 266 | struct input_dev *dev; /* input device interface */ |
@@ -783,7 +792,7 @@ static int xpad_open(struct input_dev *dev) | |||
783 | struct usb_xpad *xpad = input_get_drvdata(dev); | 792 | struct usb_xpad *xpad = input_get_drvdata(dev); |
784 | 793 | ||
785 | /* URB was submitted in probe */ | 794 | /* URB was submitted in probe */ |
786 | if(xpad->xtype == XTYPE_XBOX360W) | 795 | if (xpad->xtype == XTYPE_XBOX360W) |
787 | return 0; | 796 | return 0; |
788 | 797 | ||
789 | xpad->irq_in->dev = xpad->udev; | 798 | xpad->irq_in->dev = xpad->udev; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 992137cf3a64..ac0500667000 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -409,7 +409,7 @@ config KEYBOARD_NEWTON | |||
409 | 409 | ||
410 | config KEYBOARD_NOMADIK | 410 | config KEYBOARD_NOMADIK |
411 | tristate "ST-Ericsson Nomadik SKE keyboard" | 411 | tristate "ST-Ericsson Nomadik SKE keyboard" |
412 | depends on PLAT_NOMADIK | 412 | depends on (ARCH_NOMADIK || ARCH_U8500) |
413 | select INPUT_MATRIXKMAP | 413 | select INPUT_MATRIXKMAP |
414 | help | 414 | help |
415 | Say Y here if you want to use a keypad provided on the SKE controller | 415 | Say Y here if you want to use a keypad provided on the SKE controller |
@@ -554,6 +554,7 @@ config KEYBOARD_OMAP | |||
554 | 554 | ||
555 | config KEYBOARD_OMAP4 | 555 | config KEYBOARD_OMAP4 |
556 | tristate "TI OMAP4+ keypad support" | 556 | tristate "TI OMAP4+ keypad support" |
557 | depends on ARCH_OMAP2PLUS | ||
557 | select INPUT_MATRIXKMAP | 558 | select INPUT_MATRIXKMAP |
558 | help | 559 | help |
559 | Say Y here if you want to use the OMAP4+ keypad. | 560 | Say Y here if you want to use the OMAP4+ keypad. |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index d327f5a2bb0e..b29ca651a395 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -602,6 +602,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) | |||
602 | 602 | ||
603 | i = 0; | 603 | i = 0; |
604 | for_each_child_of_node(node, pp) { | 604 | for_each_child_of_node(node, pp) { |
605 | int gpio; | ||
605 | enum of_gpio_flags flags; | 606 | enum of_gpio_flags flags; |
606 | 607 | ||
607 | if (!of_find_property(pp, "gpios", NULL)) { | 608 | if (!of_find_property(pp, "gpios", NULL)) { |
@@ -610,9 +611,19 @@ gpio_keys_get_devtree_pdata(struct device *dev) | |||
610 | continue; | 611 | continue; |
611 | } | 612 | } |
612 | 613 | ||
614 | gpio = of_get_gpio_flags(pp, 0, &flags); | ||
615 | if (gpio < 0) { | ||
616 | error = gpio; | ||
617 | if (error != -EPROBE_DEFER) | ||
618 | dev_err(dev, | ||
619 | "Failed to get gpio flags, error: %d\n", | ||
620 | error); | ||
621 | goto err_free_pdata; | ||
622 | } | ||
623 | |||
613 | button = &pdata->buttons[i++]; | 624 | button = &pdata->buttons[i++]; |
614 | 625 | ||
615 | button->gpio = of_get_gpio_flags(pp, 0, &flags); | 626 | button->gpio = gpio; |
616 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | 627 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; |
617 | 628 | ||
618 | if (of_property_read_u32(pp, "linux,code", &button->code)) { | 629 | if (of_property_read_u32(pp, "linux,code", &button->code)) { |
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index f686fd970553..21147164874d 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c | |||
@@ -135,6 +135,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct | |||
135 | 135 | ||
136 | i = 0; | 136 | i = 0; |
137 | for_each_child_of_node(node, pp) { | 137 | for_each_child_of_node(node, pp) { |
138 | int gpio; | ||
138 | enum of_gpio_flags flags; | 139 | enum of_gpio_flags flags; |
139 | 140 | ||
140 | if (!of_find_property(pp, "gpios", NULL)) { | 141 | if (!of_find_property(pp, "gpios", NULL)) { |
@@ -143,9 +144,19 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct | |||
143 | continue; | 144 | continue; |
144 | } | 145 | } |
145 | 146 | ||
147 | gpio = of_get_gpio_flags(pp, 0, &flags); | ||
148 | if (gpio < 0) { | ||
149 | error = gpio; | ||
150 | if (error != -EPROBE_DEFER) | ||
151 | dev_err(dev, | ||
152 | "Failed to get gpio flags, error: %d\n", | ||
153 | error); | ||
154 | goto err_free_pdata; | ||
155 | } | ||
156 | |||
146 | button = &pdata->buttons[i++]; | 157 | button = &pdata->buttons[i++]; |
147 | 158 | ||
148 | button->gpio = of_get_gpio_flags(pp, 0, &flags); | 159 | button->gpio = gpio; |
149 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | 160 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; |
150 | 161 | ||
151 | if (of_property_read_u32(pp, "linux,code", &button->code)) { | 162 | if (of_property_read_u32(pp, "linux,code", &button->code)) { |
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 93c812662134..0de23f41b2d3 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c | |||
@@ -398,7 +398,7 @@ static irqreturn_t lm8323_irq(int irq, void *_lm) | |||
398 | lm8323_configure(lm); | 398 | lm8323_configure(lm); |
399 | } | 399 | } |
400 | for (i = 0; i < LM8323_NUM_PWMS; i++) { | 400 | for (i = 0; i < LM8323_NUM_PWMS; i++) { |
401 | if (ints & (1 << (INT_PWM1 + i))) { | 401 | if (ints & (INT_PWM1 << i)) { |
402 | dev_vdbg(&lm->client->dev, | 402 | dev_vdbg(&lm->client->dev, |
403 | "pwm%d engine completed\n", i); | 403 | "pwm%d engine completed\n", i); |
404 | pwm_done(&lm->pwm[i]); | 404 | pwm_done(&lm->pwm[i]); |
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index f4ff0dda7597..71d77192ac1e 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -403,7 +403,7 @@ matrix_keypad_parse_dt(struct device *dev) | |||
403 | struct matrix_keypad_platform_data *pdata; | 403 | struct matrix_keypad_platform_data *pdata; |
404 | struct device_node *np = dev->of_node; | 404 | struct device_node *np = dev->of_node; |
405 | unsigned int *gpios; | 405 | unsigned int *gpios; |
406 | int i; | 406 | int i, nrow, ncol; |
407 | 407 | ||
408 | if (!np) { | 408 | if (!np) { |
409 | dev_err(dev, "device lacks DT data\n"); | 409 | dev_err(dev, "device lacks DT data\n"); |
@@ -416,9 +416,9 @@ matrix_keypad_parse_dt(struct device *dev) | |||
416 | return ERR_PTR(-ENOMEM); | 416 | return ERR_PTR(-ENOMEM); |
417 | } | 417 | } |
418 | 418 | ||
419 | pdata->num_row_gpios = of_gpio_named_count(np, "row-gpios"); | 419 | pdata->num_row_gpios = nrow = of_gpio_named_count(np, "row-gpios"); |
420 | pdata->num_col_gpios = of_gpio_named_count(np, "col-gpios"); | 420 | pdata->num_col_gpios = ncol = of_gpio_named_count(np, "col-gpios"); |
421 | if (!pdata->num_row_gpios || !pdata->num_col_gpios) { | 421 | if (nrow <= 0 || ncol <= 0) { |
422 | dev_err(dev, "number of keypad rows/columns not specified\n"); | 422 | dev_err(dev, "number of keypad rows/columns not specified\n"); |
423 | return ERR_PTR(-EINVAL); | 423 | return ERR_PTR(-EINVAL); |
424 | } | 424 | } |
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 695d237417d6..cb1e8f614631 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c | |||
@@ -228,11 +228,9 @@ static int spear_kbd_probe(struct platform_device *pdev) | |||
228 | kbd->suspended_rate = pdata->suspended_rate; | 228 | kbd->suspended_rate = pdata->suspended_rate; |
229 | } | 229 | } |
230 | 230 | ||
231 | kbd->io_base = devm_request_and_ioremap(&pdev->dev, res); | 231 | kbd->io_base = devm_ioremap_resource(&pdev->dev, res); |
232 | if (!kbd->io_base) { | 232 | if (IS_ERR(kbd->io_base)) |
233 | dev_err(&pdev->dev, "request-ioremap failed for kbd_region\n"); | 233 | return PTR_ERR(kbd->io_base); |
234 | return -ENOMEM; | ||
235 | } | ||
236 | 234 | ||
237 | kbd->clk = devm_clk_get(&pdev->dev, NULL); | 235 | kbd->clk = devm_clk_get(&pdev->dev, NULL); |
238 | if (IS_ERR(kbd->clk)) | 236 | if (IS_ERR(kbd->clk)) |
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 2fb0d76a04c4..208de7cbb7fa 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c | |||
@@ -70,8 +70,6 @@ | |||
70 | #define TC3589x_EVT_INT_CLR 0x2 | 70 | #define TC3589x_EVT_INT_CLR 0x2 |
71 | #define TC3589x_KBD_INT_CLR 0x1 | 71 | #define TC3589x_KBD_INT_CLR 0x1 |
72 | 72 | ||
73 | #define TC3589x_KBD_KEYMAP_SIZE 64 | ||
74 | |||
75 | /** | 73 | /** |
76 | * struct tc_keypad - data structure used by keypad driver | 74 | * struct tc_keypad - data structure used by keypad driver |
77 | * @tc3589x: pointer to tc35893 | 75 | * @tc3589x: pointer to tc35893 |
@@ -88,7 +86,7 @@ struct tc_keypad { | |||
88 | const struct tc3589x_keypad_platform_data *board; | 86 | const struct tc3589x_keypad_platform_data *board; |
89 | unsigned int krow; | 87 | unsigned int krow; |
90 | unsigned int kcol; | 88 | unsigned int kcol; |
91 | unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE]; | 89 | unsigned short *keymap; |
92 | bool keypad_stopped; | 90 | bool keypad_stopped; |
93 | }; | 91 | }; |
94 | 92 | ||
@@ -338,12 +336,14 @@ static int tc3589x_keypad_probe(struct platform_device *pdev) | |||
338 | 336 | ||
339 | error = matrix_keypad_build_keymap(plat->keymap_data, NULL, | 337 | error = matrix_keypad_build_keymap(plat->keymap_data, NULL, |
340 | TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, | 338 | TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, |
341 | keypad->keymap, input); | 339 | NULL, input); |
342 | if (error) { | 340 | if (error) { |
343 | dev_err(&pdev->dev, "Failed to build keymap\n"); | 341 | dev_err(&pdev->dev, "Failed to build keymap\n"); |
344 | goto err_free_mem; | 342 | goto err_free_mem; |
345 | } | 343 | } |
346 | 344 | ||
345 | keypad->keymap = input->keycode; | ||
346 | |||
347 | input_set_capability(input, EV_MSC, MSC_SCAN); | 347 | input_set_capability(input, EV_MSC, MSC_SCAN); |
348 | if (!plat->no_autorepeat) | 348 | if (!plat->no_autorepeat) |
349 | __set_bit(EV_REP, input->evbit); | 349 | __set_bit(EV_REP, input->evbit); |
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 50e9c5e195e1..a34cc6714e5b 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c | |||
@@ -384,7 +384,7 @@ static const struct i2c_device_id tca8418_id[] = { | |||
384 | MODULE_DEVICE_TABLE(i2c, tca8418_id); | 384 | MODULE_DEVICE_TABLE(i2c, tca8418_id); |
385 | 385 | ||
386 | #ifdef CONFIG_OF | 386 | #ifdef CONFIG_OF |
387 | static const struct of_device_id tca8418_dt_ids[] __devinitconst = { | 387 | static const struct of_device_id tca8418_dt_ids[] = { |
388 | { .compatible = "ti,tca8418", }, | 388 | { .compatible = "ti,tca8418", }, |
389 | { } | 389 | { } |
390 | }; | 390 | }; |
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index d89e7d392d1e..0e138ebcc768 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/input/matrix_keypad.h> | 32 | #include <linux/input/matrix_keypad.h> |
33 | #include <mach/clk.h> | 33 | #include <linux/clk/tegra.h> |
34 | 34 | ||
35 | #define KBC_MAX_GPIO 24 | 35 | #define KBC_MAX_GPIO 24 |
36 | #define KBC_MAX_KPENT 8 | 36 | #define KBC_MAX_KPENT 8 |
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c index 419cb6b88e2a..3ae496ea5fe6 100644 --- a/drivers/input/matrix-keymap.c +++ b/drivers/input/matrix-keymap.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/export.h> | 26 | #include <linux/export.h> |
27 | #include <linux/module.h> | ||
27 | #include <linux/input/matrix_keypad.h> | 28 | #include <linux/input/matrix_keypad.h> |
28 | 29 | ||
29 | static bool matrix_keypad_map_key(struct input_dev *input_dev, | 30 | static bool matrix_keypad_map_key(struct input_dev *input_dev, |
@@ -182,3 +183,5 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, | |||
182 | return 0; | 183 | return 0; |
183 | } | 184 | } |
184 | EXPORT_SYMBOL(matrix_keypad_build_keymap); | 185 | EXPORT_SYMBOL(matrix_keypad_build_keymap); |
186 | |||
187 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 3ec8887ce451..af80928a46b4 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -72,6 +72,16 @@ config INPUT_AD714X_SPI | |||
72 | To compile this driver as a module, choose M here: the | 72 | To compile this driver as a module, choose M here: the |
73 | module will be called ad714x-spi. | 73 | module will be called ad714x-spi. |
74 | 74 | ||
75 | config INPUT_ARIZONA_HAPTICS | ||
76 | tristate "Arizona haptics support" | ||
77 | depends on MFD_ARIZONA && SND_SOC | ||
78 | select INPUT_FF_MEMLESS | ||
79 | help | ||
80 | Say Y to enable support for the haptics module in Arizona CODECs. | ||
81 | |||
82 | To compile this driver as a module, choose M here: the | ||
83 | module will be called arizona-haptics. | ||
84 | |||
75 | config INPUT_BMA150 | 85 | config INPUT_BMA150 |
76 | tristate "BMA150/SMB380 acceleration sensor support" | 86 | tristate "BMA150/SMB380 acceleration sensor support" |
77 | depends on I2C | 87 | depends on I2C |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index d6873433ba71..d7fc17f11d77 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o | |||
14 | obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o | 14 | obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o |
15 | obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o | 15 | obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o |
16 | obj-$(CONFIG_INPUT_APANEL) += apanel.o | 16 | obj-$(CONFIG_INPUT_APANEL) += apanel.o |
17 | obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o | ||
17 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 18 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
18 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 19 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
19 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | 20 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o |
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c new file mode 100644 index 000000000000..7a04f54ef961 --- /dev/null +++ b/drivers/input/misc/arizona-haptics.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * Arizona haptics driver | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/slab.h> | ||
17 | |||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dapm.h> | ||
20 | |||
21 | #include <linux/mfd/arizona/core.h> | ||
22 | #include <linux/mfd/arizona/pdata.h> | ||
23 | #include <linux/mfd/arizona/registers.h> | ||
24 | |||
25 | struct arizona_haptics { | ||
26 | struct arizona *arizona; | ||
27 | struct input_dev *input_dev; | ||
28 | struct work_struct work; | ||
29 | |||
30 | struct mutex mutex; | ||
31 | u8 intensity; | ||
32 | }; | ||
33 | |||
34 | static void arizona_haptics_work(struct work_struct *work) | ||
35 | { | ||
36 | struct arizona_haptics *haptics = container_of(work, | ||
37 | struct arizona_haptics, | ||
38 | work); | ||
39 | struct arizona *arizona = haptics->arizona; | ||
40 | struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex; | ||
41 | int ret; | ||
42 | |||
43 | if (!haptics->arizona->dapm) { | ||
44 | dev_err(arizona->dev, "No DAPM context\n"); | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | if (haptics->intensity) { | ||
49 | ret = regmap_update_bits(arizona->regmap, | ||
50 | ARIZONA_HAPTICS_PHASE_2_INTENSITY, | ||
51 | ARIZONA_PHASE2_INTENSITY_MASK, | ||
52 | haptics->intensity); | ||
53 | if (ret != 0) { | ||
54 | dev_err(arizona->dev, "Failed to set intensity: %d\n", | ||
55 | ret); | ||
56 | return; | ||
57 | } | ||
58 | |||
59 | /* This enable sequence will be a noop if already enabled */ | ||
60 | ret = regmap_update_bits(arizona->regmap, | ||
61 | ARIZONA_HAPTICS_CONTROL_1, | ||
62 | ARIZONA_HAP_CTRL_MASK, | ||
63 | 1 << ARIZONA_HAP_CTRL_SHIFT); | ||
64 | if (ret != 0) { | ||
65 | dev_err(arizona->dev, "Failed to start haptics: %d\n", | ||
66 | ret); | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
71 | |||
72 | ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS"); | ||
73 | if (ret != 0) { | ||
74 | dev_err(arizona->dev, "Failed to start HAPTICS: %d\n", | ||
75 | ret); | ||
76 | mutex_unlock(dapm_mutex); | ||
77 | return; | ||
78 | } | ||
79 | |||
80 | ret = snd_soc_dapm_sync(arizona->dapm); | ||
81 | if (ret != 0) { | ||
82 | dev_err(arizona->dev, "Failed to sync DAPM: %d\n", | ||
83 | ret); | ||
84 | mutex_unlock(dapm_mutex); | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | mutex_unlock(dapm_mutex); | ||
89 | |||
90 | } else { | ||
91 | /* This disable sequence will be a noop if already enabled */ | ||
92 | mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
93 | |||
94 | ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS"); | ||
95 | if (ret != 0) { | ||
96 | dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n", | ||
97 | ret); | ||
98 | mutex_unlock(dapm_mutex); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | ret = snd_soc_dapm_sync(arizona->dapm); | ||
103 | if (ret != 0) { | ||
104 | dev_err(arizona->dev, "Failed to sync DAPM: %d\n", | ||
105 | ret); | ||
106 | mutex_unlock(dapm_mutex); | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | mutex_unlock(dapm_mutex); | ||
111 | |||
112 | ret = regmap_update_bits(arizona->regmap, | ||
113 | ARIZONA_HAPTICS_CONTROL_1, | ||
114 | ARIZONA_HAP_CTRL_MASK, | ||
115 | 1 << ARIZONA_HAP_CTRL_SHIFT); | ||
116 | if (ret != 0) { | ||
117 | dev_err(arizona->dev, "Failed to stop haptics: %d\n", | ||
118 | ret); | ||
119 | return; | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static int arizona_haptics_play(struct input_dev *input, void *data, | ||
125 | struct ff_effect *effect) | ||
126 | { | ||
127 | struct arizona_haptics *haptics = input_get_drvdata(input); | ||
128 | struct arizona *arizona = haptics->arizona; | ||
129 | |||
130 | if (!arizona->dapm) { | ||
131 | dev_err(arizona->dev, "No DAPM context\n"); | ||
132 | return -EBUSY; | ||
133 | } | ||
134 | |||
135 | if (effect->u.rumble.strong_magnitude) { | ||
136 | /* Scale the magnitude into the range the device supports */ | ||
137 | if (arizona->pdata.hap_act) { | ||
138 | haptics->intensity = | ||
139 | effect->u.rumble.strong_magnitude >> 9; | ||
140 | if (effect->direction < 0x8000) | ||
141 | haptics->intensity += 0x7f; | ||
142 | } else { | ||
143 | haptics->intensity = | ||
144 | effect->u.rumble.strong_magnitude >> 8; | ||
145 | } | ||
146 | } else { | ||
147 | haptics->intensity = 0; | ||
148 | } | ||
149 | |||
150 | schedule_work(&haptics->work); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static void arizona_haptics_close(struct input_dev *input) | ||
156 | { | ||
157 | struct arizona_haptics *haptics = input_get_drvdata(input); | ||
158 | struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex; | ||
159 | |||
160 | cancel_work_sync(&haptics->work); | ||
161 | |||
162 | mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
163 | |||
164 | if (haptics->arizona->dapm) | ||
165 | snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS"); | ||
166 | |||
167 | mutex_unlock(dapm_mutex); | ||
168 | } | ||
169 | |||
170 | static int arizona_haptics_probe(struct platform_device *pdev) | ||
171 | { | ||
172 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | ||
173 | struct arizona_haptics *haptics; | ||
174 | int ret; | ||
175 | |||
176 | haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL); | ||
177 | if (!haptics) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | haptics->arizona = arizona; | ||
181 | |||
182 | ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1, | ||
183 | ARIZONA_HAP_ACT, arizona->pdata.hap_act); | ||
184 | if (ret != 0) { | ||
185 | dev_err(arizona->dev, "Failed to set haptics actuator: %d\n", | ||
186 | ret); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | INIT_WORK(&haptics->work, arizona_haptics_work); | ||
191 | |||
192 | haptics->input_dev = input_allocate_device(); | ||
193 | if (haptics->input_dev == NULL) { | ||
194 | dev_err(arizona->dev, "Failed to allocate input device\n"); | ||
195 | return -ENOMEM; | ||
196 | } | ||
197 | |||
198 | input_set_drvdata(haptics->input_dev, haptics); | ||
199 | |||
200 | haptics->input_dev->name = "arizona:haptics"; | ||
201 | haptics->input_dev->dev.parent = pdev->dev.parent; | ||
202 | haptics->input_dev->close = arizona_haptics_close; | ||
203 | __set_bit(FF_RUMBLE, haptics->input_dev->ffbit); | ||
204 | |||
205 | ret = input_ff_create_memless(haptics->input_dev, NULL, | ||
206 | arizona_haptics_play); | ||
207 | if (ret < 0) { | ||
208 | dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n", | ||
209 | ret); | ||
210 | goto err_ialloc; | ||
211 | } | ||
212 | |||
213 | ret = input_register_device(haptics->input_dev); | ||
214 | if (ret < 0) { | ||
215 | dev_err(arizona->dev, "couldn't register input device: %d\n", | ||
216 | ret); | ||
217 | goto err_iff; | ||
218 | } | ||
219 | |||
220 | platform_set_drvdata(pdev, haptics); | ||
221 | |||
222 | return 0; | ||
223 | |||
224 | err_iff: | ||
225 | if (haptics->input_dev) | ||
226 | input_ff_destroy(haptics->input_dev); | ||
227 | err_ialloc: | ||
228 | input_free_device(haptics->input_dev); | ||
229 | |||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | static int arizona_haptics_remove(struct platform_device *pdev) | ||
234 | { | ||
235 | struct arizona_haptics *haptics = platform_get_drvdata(pdev); | ||
236 | |||
237 | input_unregister_device(haptics->input_dev); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static struct platform_driver arizona_haptics_driver = { | ||
243 | .probe = arizona_haptics_probe, | ||
244 | .remove = arizona_haptics_remove, | ||
245 | .driver = { | ||
246 | .name = "arizona-haptics", | ||
247 | .owner = THIS_MODULE, | ||
248 | }, | ||
249 | }; | ||
250 | module_platform_driver(arizona_haptics_driver); | ||
251 | |||
252 | MODULE_ALIAS("platform:arizona-haptics"); | ||
253 | MODULE_DESCRIPTION("Arizona haptics driver"); | ||
254 | MODULE_LICENSE("GPL"); | ||
255 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 26f13131639a..5d4402365a52 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c | |||
@@ -121,7 +121,7 @@ static int atlas_acpi_button_add(struct acpi_device *device) | |||
121 | return err; | 121 | return err; |
122 | } | 122 | } |
123 | 123 | ||
124 | static int atlas_acpi_button_remove(struct acpi_device *device, int type) | 124 | static int atlas_acpi_button_remove(struct acpi_device *device) |
125 | { | 125 | { |
126 | acpi_status status; | 126 | acpi_status status; |
127 | 127 | ||
diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c index 630c1ce4980a..020569a499f2 100644 --- a/drivers/input/misc/da9052_onkey.c +++ b/drivers/input/misc/da9052_onkey.c | |||
@@ -24,7 +24,6 @@ struct da9052_onkey { | |||
24 | struct da9052 *da9052; | 24 | struct da9052 *da9052; |
25 | struct input_dev *input; | 25 | struct input_dev *input; |
26 | struct delayed_work work; | 26 | struct delayed_work work; |
27 | unsigned int irq; | ||
28 | }; | 27 | }; |
29 | 28 | ||
30 | static void da9052_onkey_query(struct da9052_onkey *onkey) | 29 | static void da9052_onkey_query(struct da9052_onkey *onkey) |
@@ -76,7 +75,6 @@ static int da9052_onkey_probe(struct platform_device *pdev) | |||
76 | struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent); | 75 | struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent); |
77 | struct da9052_onkey *onkey; | 76 | struct da9052_onkey *onkey; |
78 | struct input_dev *input_dev; | 77 | struct input_dev *input_dev; |
79 | int irq; | ||
80 | int error; | 78 | int error; |
81 | 79 | ||
82 | if (!da9052) { | 80 | if (!da9052) { |
@@ -84,13 +82,6 @@ static int da9052_onkey_probe(struct platform_device *pdev) | |||
84 | return -EINVAL; | 82 | return -EINVAL; |
85 | } | 83 | } |
86 | 84 | ||
87 | irq = platform_get_irq_byname(pdev, "ONKEY"); | ||
88 | if (irq < 0) { | ||
89 | dev_err(&pdev->dev, | ||
90 | "Failed to get an IRQ for input device, %d\n", irq); | ||
91 | return -EINVAL; | ||
92 | } | ||
93 | |||
94 | onkey = kzalloc(sizeof(*onkey), GFP_KERNEL); | 85 | onkey = kzalloc(sizeof(*onkey), GFP_KERNEL); |
95 | input_dev = input_allocate_device(); | 86 | input_dev = input_allocate_device(); |
96 | if (!onkey || !input_dev) { | 87 | if (!onkey || !input_dev) { |
@@ -101,7 +92,6 @@ static int da9052_onkey_probe(struct platform_device *pdev) | |||
101 | 92 | ||
102 | onkey->input = input_dev; | 93 | onkey->input = input_dev; |
103 | onkey->da9052 = da9052; | 94 | onkey->da9052 = da9052; |
104 | onkey->irq = irq; | ||
105 | INIT_DELAYED_WORK(&onkey->work, da9052_onkey_work); | 95 | INIT_DELAYED_WORK(&onkey->work, da9052_onkey_work); |
106 | 96 | ||
107 | input_dev->name = "da9052-onkey"; | 97 | input_dev->name = "da9052-onkey"; |
@@ -111,13 +101,11 @@ static int da9052_onkey_probe(struct platform_device *pdev) | |||
111 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | 101 | input_dev->evbit[0] = BIT_MASK(EV_KEY); |
112 | __set_bit(KEY_POWER, input_dev->keybit); | 102 | __set_bit(KEY_POWER, input_dev->keybit); |
113 | 103 | ||
114 | error = request_threaded_irq(onkey->irq, NULL, da9052_onkey_irq, | 104 | error = da9052_request_irq(onkey->da9052, DA9052_IRQ_NONKEY, "ONKEY", |
115 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 105 | da9052_onkey_irq, onkey); |
116 | "ONKEY", onkey); | ||
117 | if (error < 0) { | 106 | if (error < 0) { |
118 | dev_err(onkey->da9052->dev, | 107 | dev_err(onkey->da9052->dev, |
119 | "Failed to register ONKEY IRQ %d, error = %d\n", | 108 | "Failed to register ONKEY IRQ: %d\n", error); |
120 | onkey->irq, error); | ||
121 | goto err_free_mem; | 109 | goto err_free_mem; |
122 | } | 110 | } |
123 | 111 | ||
@@ -132,7 +120,7 @@ static int da9052_onkey_probe(struct platform_device *pdev) | |||
132 | return 0; | 120 | return 0; |
133 | 121 | ||
134 | err_free_irq: | 122 | err_free_irq: |
135 | free_irq(onkey->irq, onkey); | 123 | da9052_free_irq(onkey->da9052, DA9052_IRQ_NONKEY, onkey); |
136 | cancel_delayed_work_sync(&onkey->work); | 124 | cancel_delayed_work_sync(&onkey->work); |
137 | err_free_mem: | 125 | err_free_mem: |
138 | input_free_device(input_dev); | 126 | input_free_device(input_dev); |
@@ -145,7 +133,7 @@ static int da9052_onkey_remove(struct platform_device *pdev) | |||
145 | { | 133 | { |
146 | struct da9052_onkey *onkey = platform_get_drvdata(pdev); | 134 | struct da9052_onkey *onkey = platform_get_drvdata(pdev); |
147 | 135 | ||
148 | free_irq(onkey->irq, onkey); | 136 | da9052_free_irq(onkey->da9052, DA9052_IRQ_NONKEY, onkey); |
149 | cancel_delayed_work_sync(&onkey->work); | 137 | cancel_delayed_work_sync(&onkey->work); |
150 | 138 | ||
151 | input_unregister_device(onkey->input); | 139 | input_unregister_device(onkey->input); |
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index 0b4f54265f62..2e3334b8f82d 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c | |||
@@ -109,7 +109,9 @@ static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm) | |||
109 | 109 | ||
110 | if (hp_sdc_enqueue_transaction(&t)) return -1; | 110 | if (hp_sdc_enqueue_transaction(&t)) return -1; |
111 | 111 | ||
112 | down_interruptible(&tsem); /* Put ourselves to sleep for results. */ | 112 | /* Put ourselves to sleep for results. */ |
113 | if (WARN_ON(down_interruptible(&tsem))) | ||
114 | return -1; | ||
113 | 115 | ||
114 | /* Check for nonpresence of BBRTC */ | 116 | /* Check for nonpresence of BBRTC */ |
115 | if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] | | 117 | if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] | |
@@ -176,11 +178,16 @@ static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg) | |||
176 | t.seq = tseq; | 178 | t.seq = tseq; |
177 | t.act.semaphore = &i8042tregs; | 179 | t.act.semaphore = &i8042tregs; |
178 | 180 | ||
179 | down_interruptible(&i8042tregs); /* Sleep if output regs in use. */ | 181 | /* Sleep if output regs in use. */ |
182 | if (WARN_ON(down_interruptible(&i8042tregs))) | ||
183 | return -1; | ||
180 | 184 | ||
181 | if (hp_sdc_enqueue_transaction(&t)) return -1; | 185 | if (hp_sdc_enqueue_transaction(&t)) return -1; |
182 | 186 | ||
183 | down_interruptible(&i8042tregs); /* Sleep until results come back. */ | 187 | /* Sleep until results come back. */ |
188 | if (WARN_ON(down_interruptible(&i8042tregs))) | ||
189 | return -1; | ||
190 | |||
184 | up(&i8042tregs); | 191 | up(&i8042tregs); |
185 | 192 | ||
186 | return (tseq[5] | | 193 | return (tseq[5] | |
@@ -276,6 +283,7 @@ static inline int hp_sdc_rtc_read_ct(struct timeval *res) { | |||
276 | } | 283 | } |
277 | 284 | ||
278 | 285 | ||
286 | #if 0 /* not used yet */ | ||
279 | /* Set the i8042 real-time clock */ | 287 | /* Set the i8042 real-time clock */ |
280 | static int hp_sdc_rtc_set_rt (struct timeval *setto) | 288 | static int hp_sdc_rtc_set_rt (struct timeval *setto) |
281 | { | 289 | { |
@@ -386,6 +394,7 @@ static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd) | |||
386 | } | 394 | } |
387 | return 0; | 395 | return 0; |
388 | } | 396 | } |
397 | #endif | ||
389 | 398 | ||
390 | static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, | 399 | static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, |
391 | size_t count, loff_t *ppos) { | 400 | size_t count, loff_t *ppos) { |
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c index 369a39de4ff3..f9179b2585a9 100644 --- a/drivers/input/misc/max8925_onkey.c +++ b/drivers/input/misc/max8925_onkey.c | |||
@@ -100,9 +100,6 @@ static int max8925_onkey_probe(struct platform_device *pdev) | |||
100 | input->dev.parent = &pdev->dev; | 100 | input->dev.parent = &pdev->dev; |
101 | input_set_capability(input, EV_KEY, KEY_POWER); | 101 | input_set_capability(input, EV_KEY, KEY_POWER); |
102 | 102 | ||
103 | irq[0] += chip->irq_base; | ||
104 | irq[1] += chip->irq_base; | ||
105 | |||
106 | error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler, | 103 | error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler, |
107 | IRQF_ONESHOT, "onkey-down", info); | 104 | IRQF_ONESHOT, "onkey-down", info); |
108 | if (error < 0) { | 105 | if (error < 0) { |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7b99fc7c9438..0238e0e14335 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) | |||
490 | f->y_map |= (p[5] & 0x20) << 6; | 490 | f->y_map |= (p[5] & 0x20) << 6; |
491 | } | 491 | } |
492 | 492 | ||
493 | static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) | ||
494 | { | ||
495 | f->first_mp = !!(p[0] & 0x02); | ||
496 | f->is_mp = !!(p[0] & 0x20); | ||
497 | |||
498 | f->fingers = ((p[0] & 0x6) >> 1 | | ||
499 | (p[0] & 0x10) >> 2); | ||
500 | f->x_map = ((p[2] & 0x60) >> 5) | | ||
501 | ((p[4] & 0x7f) << 2) | | ||
502 | ((p[5] & 0x7f) << 9) | | ||
503 | ((p[3] & 0x07) << 16) | | ||
504 | ((p[3] & 0x70) << 15) | | ||
505 | ((p[0] & 0x01) << 22); | ||
506 | f->y_map = (p[1] & 0x7f) | | ||
507 | ((p[2] & 0x1f) << 7); | ||
508 | |||
509 | f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); | ||
510 | f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); | ||
511 | f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; | ||
512 | |||
513 | alps_decode_buttons_v3(f, p); | ||
514 | } | ||
515 | |||
493 | static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) | 516 | static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) |
494 | { | 517 | { |
495 | struct alps_data *priv = psmouse->private; | 518 | struct alps_data *priv = psmouse->private; |
@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
874 | } | 897 | } |
875 | 898 | ||
876 | /* Bytes 2 - pktsize should have 0 in the highest bit */ | 899 | /* Bytes 2 - pktsize should have 0 in the highest bit */ |
877 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && | 900 | if (priv->proto_version != ALPS_PROTO_V5 && |
901 | psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && | ||
878 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { | 902 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { |
879 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 903 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
880 | psmouse->pktcnt - 1, | 904 | psmouse->pktcnt - 1, |
@@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, | |||
994 | return 0; | 1018 | return 0; |
995 | } | 1019 | } |
996 | 1020 | ||
997 | static int alps_enter_command_mode(struct psmouse *psmouse, | 1021 | static int alps_enter_command_mode(struct psmouse *psmouse) |
998 | unsigned char *resp) | ||
999 | { | 1022 | { |
1000 | unsigned char param[4]; | 1023 | unsigned char param[4]; |
1001 | 1024 | ||
@@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse, | |||
1004 | return -1; | 1027 | return -1; |
1005 | } | 1028 | } |
1006 | 1029 | ||
1007 | if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { | 1030 | if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) && |
1031 | param[0] != 0x73) { | ||
1008 | psmouse_dbg(psmouse, | 1032 | psmouse_dbg(psmouse, |
1009 | "unknown response while entering command mode\n"); | 1033 | "unknown response while entering command mode\n"); |
1010 | return -1; | 1034 | return -1; |
1011 | } | 1035 | } |
1012 | |||
1013 | if (resp) | ||
1014 | *resp = param[2]; | ||
1015 | return 0; | 1036 | return 0; |
1016 | } | 1037 | } |
1017 | 1038 | ||
@@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse, | |||
1176 | { | 1197 | { |
1177 | int reg_val, ret = -1; | 1198 | int reg_val, ret = -1; |
1178 | 1199 | ||
1179 | if (alps_enter_command_mode(psmouse, NULL)) | 1200 | if (alps_enter_command_mode(psmouse)) |
1180 | return -1; | 1201 | return -1; |
1181 | 1202 | ||
1182 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); | 1203 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); |
@@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) | |||
1216 | { | 1237 | { |
1217 | int ret = -EIO, reg_val; | 1238 | int ret = -EIO, reg_val; |
1218 | 1239 | ||
1219 | if (alps_enter_command_mode(psmouse, NULL)) | 1240 | if (alps_enter_command_mode(psmouse)) |
1220 | goto error; | 1241 | goto error; |
1221 | 1242 | ||
1222 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); | 1243 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); |
@@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) | |||
1279 | * supported by this driver. If bit 1 isn't set the packet | 1300 | * supported by this driver. If bit 1 isn't set the packet |
1280 | * format is different. | 1301 | * format is different. |
1281 | */ | 1302 | */ |
1282 | if (alps_enter_command_mode(psmouse, NULL) || | 1303 | if (alps_enter_command_mode(psmouse) || |
1283 | alps_command_mode_write_reg(psmouse, | 1304 | alps_command_mode_write_reg(psmouse, |
1284 | reg_base + 0x08, 0x82) || | 1305 | reg_base + 0x08, 0x82) || |
1285 | alps_exit_command_mode(psmouse)) | 1306 | alps_exit_command_mode(psmouse)) |
@@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) | |||
1306 | alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) | 1327 | alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) |
1307 | goto error; | 1328 | goto error; |
1308 | 1329 | ||
1309 | if (alps_enter_command_mode(psmouse, NULL) || | 1330 | if (alps_enter_command_mode(psmouse) || |
1310 | alps_absolute_mode_v3(psmouse)) { | 1331 | alps_absolute_mode_v3(psmouse)) { |
1311 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); | 1332 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); |
1312 | goto error; | 1333 | goto error; |
@@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) | |||
1381 | priv->flags &= ~ALPS_DUALPOINT; | 1402 | priv->flags &= ~ALPS_DUALPOINT; |
1382 | } | 1403 | } |
1383 | 1404 | ||
1384 | if (alps_enter_command_mode(psmouse, NULL) || | 1405 | if (alps_enter_command_mode(psmouse) || |
1385 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || | 1406 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || |
1386 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) | 1407 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) |
1387 | goto error; | 1408 | goto error; |
@@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) | |||
1431 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1452 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1432 | unsigned char param[4]; | 1453 | unsigned char param[4]; |
1433 | 1454 | ||
1434 | if (alps_enter_command_mode(psmouse, NULL)) | 1455 | if (alps_enter_command_mode(psmouse)) |
1435 | goto error; | 1456 | goto error; |
1436 | 1457 | ||
1437 | if (alps_absolute_mode_v4(psmouse)) { | 1458 | if (alps_absolute_mode_v4(psmouse)) { |
@@ -1499,6 +1520,23 @@ error: | |||
1499 | return -1; | 1520 | return -1; |
1500 | } | 1521 | } |
1501 | 1522 | ||
1523 | static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) | ||
1524 | { | ||
1525 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
1526 | unsigned char param[2]; | ||
1527 | |||
1528 | /* This is dolphin "v1" as empirically defined by florin9doi */ | ||
1529 | param[0] = 0x64; | ||
1530 | param[1] = 0x28; | ||
1531 | |||
1532 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
1533 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | ||
1534 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) | ||
1535 | return -1; | ||
1536 | |||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1502 | static void alps_set_defaults(struct alps_data *priv) | 1540 | static void alps_set_defaults(struct alps_data *priv) |
1503 | { | 1541 | { |
1504 | priv->byte0 = 0x8f; | 1542 | priv->byte0 = 0x8f; |
@@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv) | |||
1532 | priv->nibble_commands = alps_v4_nibble_commands; | 1570 | priv->nibble_commands = alps_v4_nibble_commands; |
1533 | priv->addr_command = PSMOUSE_CMD_DISABLE; | 1571 | priv->addr_command = PSMOUSE_CMD_DISABLE; |
1534 | break; | 1572 | break; |
1573 | case ALPS_PROTO_V5: | ||
1574 | priv->hw_init = alps_hw_init_dolphin_v1; | ||
1575 | priv->process_packet = alps_process_packet_v3; | ||
1576 | priv->decode_fields = alps_decode_dolphin; | ||
1577 | priv->set_abs_params = alps_set_abs_params_mt; | ||
1578 | priv->nibble_commands = alps_v3_nibble_commands; | ||
1579 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | ||
1580 | priv->byte0 = 0xc8; | ||
1581 | priv->mask0 = 0xc8; | ||
1582 | priv->flags = 0; | ||
1583 | priv->x_max = 1360; | ||
1584 | priv->y_max = 660; | ||
1585 | priv->x_bits = 23; | ||
1586 | priv->y_bits = 12; | ||
1587 | break; | ||
1535 | } | 1588 | } |
1536 | } | 1589 | } |
1537 | 1590 | ||
@@ -1592,6 +1645,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
1592 | 1645 | ||
1593 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { | 1646 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { |
1594 | return 0; | 1647 | return 0; |
1648 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && | ||
1649 | ec[0] == 0x73 && ec[1] == 0x01) { | ||
1650 | priv->proto_version = ALPS_PROTO_V5; | ||
1651 | alps_set_defaults(priv); | ||
1652 | |||
1653 | return 0; | ||
1595 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { | 1654 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { |
1596 | priv->proto_version = ALPS_PROTO_V3; | 1655 | priv->proto_version = ALPS_PROTO_V3; |
1597 | alps_set_defaults(priv); | 1656 | alps_set_defaults(priv); |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 970480551b6e..eee59853b9ce 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define ALPS_PROTO_V2 2 | 16 | #define ALPS_PROTO_V2 2 |
17 | #define ALPS_PROTO_V3 3 | 17 | #define ALPS_PROTO_V3 3 |
18 | #define ALPS_PROTO_V4 4 | 18 | #define ALPS_PROTO_V4 4 |
19 | #define ALPS_PROTO_V5 5 | ||
19 | 20 | ||
20 | /** | 21 | /** |
21 | * struct alps_model_info - touchpad ID table | 22 | * struct alps_model_info - touchpad ID table |
diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index 1673dc6c8092..f51765fff054 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c | |||
@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse) | |||
236 | cytp->fw_version = param[2] & FW_VERSION_MASX; | 236 | cytp->fw_version = param[2] & FW_VERSION_MASX; |
237 | cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; | 237 | cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; |
238 | 238 | ||
239 | /* | ||
240 | * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to | ||
241 | * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594. | ||
242 | */ | ||
243 | if (cytp->fw_version >= 11) | ||
244 | cytp->tp_metrics_supported = 0; | ||
245 | |||
239 | psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); | 246 | psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); |
240 | psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", | 247 | psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", |
241 | cytp->tp_metrics_supported); | 248 | cytp->tp_metrics_supported); |
@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) | |||
258 | cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; | 265 | cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; |
259 | cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; | 266 | cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; |
260 | 267 | ||
268 | if (!cytp->tp_metrics_supported) | ||
269 | return 0; | ||
270 | |||
261 | memset(param, 0, sizeof(param)); | 271 | memset(param, 0, sizeof(param)); |
262 | if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { | 272 | if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { |
263 | /* Update trackpad parameters. */ | 273 | /* Update trackpad parameters. */ |
@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) | |||
315 | 325 | ||
316 | static int cypress_query_hardware(struct psmouse *psmouse) | 326 | static int cypress_query_hardware(struct psmouse *psmouse) |
317 | { | 327 | { |
318 | struct cytp_data *cytp = psmouse->private; | ||
319 | int ret; | 328 | int ret; |
320 | 329 | ||
321 | ret = cypress_read_fw_version(psmouse); | 330 | ret = cypress_read_fw_version(psmouse); |
322 | if (ret) | 331 | if (ret) |
323 | return ret; | 332 | return ret; |
324 | 333 | ||
325 | if (cytp->tp_metrics_supported) { | 334 | ret = cypress_read_tp_metrics(psmouse); |
326 | ret = cypress_read_tp_metrics(psmouse); | 335 | if (ret) |
327 | if (ret) | 336 | return ret; |
328 | return ret; | ||
329 | } | ||
330 | 337 | ||
331 | return 0; | 338 | return 0; |
332 | } | 339 | } |
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index e582922bacf7..cc7e0d4a8f93 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
@@ -791,7 +791,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | |||
791 | fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); | 791 | fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); |
792 | fsp_set_slot(dev, 1, false, 0, 0); | 792 | fsp_set_slot(dev, 1, false, 0, 0); |
793 | } | 793 | } |
794 | if (fgrs > 0) { | 794 | if (fgrs == 1 || (fgrs == 2 && !(packet[0] & FSP_PB0_MFMC_FGR2))) { |
795 | input_report_abs(dev, ABS_X, abs_x); | 795 | input_report_abs(dev, ABS_X, abs_x); |
796 | input_report_abs(dev, ABS_Y, abs_y); | 796 | input_report_abs(dev, ABS_Y, abs_y); |
797 | } | 797 | } |
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index dbb170916dd1..aebfe3ecb945 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
@@ -22,7 +22,7 @@ config SERIO_I8042 | |||
22 | tristate "i8042 PC Keyboard controller" if EXPERT || !X86 | 22 | tristate "i8042 PC Keyboard controller" if EXPERT || !X86 |
23 | default y | 23 | default y |
24 | depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ | 24 | depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ |
25 | (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN | 25 | (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390 |
26 | help | 26 | help |
27 | i8042 is the chip over which the standard AT keyboard and PS/2 | 27 | i8042 is the chip over which the standard AT keyboard and PS/2 |
28 | mouse are connected to the computer. If you use these devices, | 28 | mouse are connected to the computer. If you use these devices, |
@@ -36,6 +36,7 @@ config SERIO_I8042 | |||
36 | config SERIO_SERPORT | 36 | config SERIO_SERPORT |
37 | tristate "Serial port line discipline" | 37 | tristate "Serial port line discipline" |
38 | default y | 38 | default y |
39 | depends on TTY | ||
39 | help | 40 | help |
40 | Say Y here if you plan to use an input device (mouse, joystick, | 41 | Say Y here if you plan to use an input device (mouse, joystick, |
41 | tablet, 6dof) that communicates over the RS232 serial (COM) port. | 42 | tablet, 6dof) that communicates over the RS232 serial (COM) port. |
diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c index b571eb3e4efc..c52e3e589f72 100644 --- a/drivers/input/serio/arc_ps2.c +++ b/drivers/input/serio/arc_ps2.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Driver is originally developed by Pavel Sokolov <psokolov@synopsys.com> | 8 | * Driver is originally developed by Pavel Sokolov <psokolov@synopsys.com> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/err.h> | ||
11 | #include <linux/module.h> | 12 | #include <linux/module.h> |
12 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
13 | #include <linux/input.h> | 14 | #include <linux/input.h> |
@@ -206,9 +207,9 @@ static int arc_ps2_probe(struct platform_device *pdev) | |||
206 | return -ENOMEM; | 207 | return -ENOMEM; |
207 | } | 208 | } |
208 | 209 | ||
209 | arc_ps2->addr = devm_request_and_ioremap(&pdev->dev, res); | 210 | arc_ps2->addr = devm_ioremap_resource(&pdev->dev, res); |
210 | if (!arc_ps2->addr) | 211 | if (IS_ERR(arc_ps2->addr)) |
211 | return -EBUSY; | 212 | return PTR_ERR(arc_ps2->addr); |
212 | 213 | ||
213 | dev_info(&pdev->dev, "irq = %d, address = 0x%p, ports = %i\n", | 214 | dev_info(&pdev->dev, "irq = %d, address = 0x%p, ports = %i\n", |
214 | irq, arc_ps2->addr, ARC_PS2_PORTS); | 215 | irq, arc_ps2->addr, ARC_PS2_PORTS); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index d6cc77a53c7e..5f306f79da0c 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -921,6 +921,7 @@ static int __init i8042_platform_init(void) | |||
921 | int retval; | 921 | int retval; |
922 | 922 | ||
923 | #ifdef CONFIG_X86 | 923 | #ifdef CONFIG_X86 |
924 | u8 a20_on = 0xdf; | ||
924 | /* Just return if pre-detection shows no i8042 controller exist */ | 925 | /* Just return if pre-detection shows no i8042 controller exist */ |
925 | if (!x86_platform.i8042_detect()) | 926 | if (!x86_platform.i8042_detect()) |
926 | return -ENODEV; | 927 | return -ENODEV; |
@@ -960,6 +961,14 @@ static int __init i8042_platform_init(void) | |||
960 | 961 | ||
961 | if (dmi_check_system(i8042_dmi_dritek_table)) | 962 | if (dmi_check_system(i8042_dmi_dritek_table)) |
962 | i8042_dritek = true; | 963 | i8042_dritek = true; |
964 | |||
965 | /* | ||
966 | * A20 was already enabled during early kernel init. But some buggy | ||
967 | * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to | ||
968 | * resume from S3. So we do it here and hope that nothing breaks. | ||
969 | */ | ||
970 | i8042_command(&a20_on, 0x10d1); | ||
971 | i8042_command(NULL, 0x00ff); /* Null command for SMM firmware */ | ||
963 | #endif /* CONFIG_X86 */ | 972 | #endif /* CONFIG_X86 */ |
964 | 973 | ||
965 | return retval; | 974 | return retval; |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index f92d34f45a1c..aaf23aeae2ea 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -553,10 +553,10 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int | |||
553 | if (!rep_data) | 553 | if (!rep_data) |
554 | return error; | 554 | return error; |
555 | 555 | ||
556 | rep_data[0] = report_id; | ||
557 | rep_data[1] = mode; | ||
558 | |||
559 | do { | 556 | do { |
557 | rep_data[0] = report_id; | ||
558 | rep_data[1] = mode; | ||
559 | |||
560 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, | 560 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, |
561 | report_id, rep_data, length, 1); | 561 | report_id, rep_data, length, 1); |
562 | if (error >= 0) | 562 | if (error >= 0) |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index ad11ec543623..1daa97913b7d 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -2017,6 +2017,9 @@ static const struct wacom_features wacom_features_0x100 = | |||
2017 | static const struct wacom_features wacom_features_0x101 = | 2017 | static const struct wacom_features wacom_features_0x101 = |
2018 | { "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, | 2018 | { "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, |
2019 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2019 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
2020 | static const struct wacom_features wacom_features_0x10D = | ||
2021 | { "Wacom ISDv4 10D", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, | ||
2022 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
2020 | static const struct wacom_features wacom_features_0x4001 = | 2023 | static const struct wacom_features wacom_features_0x4001 = |
2021 | { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, | 2024 | { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, |
2022 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2025 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
@@ -2036,7 +2039,8 @@ static const struct wacom_features wacom_features_0xD1 = | |||
2036 | .touch_max = 2 }; | 2039 | .touch_max = 2 }; |
2037 | static const struct wacom_features wacom_features_0xD2 = | 2040 | static const struct wacom_features wacom_features_0xD2 = |
2038 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 2041 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
2039 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2042 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
2043 | .touch_max = 2 }; | ||
2040 | static const struct wacom_features wacom_features_0xD3 = | 2044 | static const struct wacom_features wacom_features_0xD3 = |
2041 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, | 2045 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, |
2042 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, | 2046 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
@@ -2200,6 +2204,7 @@ const struct usb_device_id wacom_ids[] = { | |||
2200 | { USB_DEVICE_WACOM(0xEF) }, | 2204 | { USB_DEVICE_WACOM(0xEF) }, |
2201 | { USB_DEVICE_WACOM(0x100) }, | 2205 | { USB_DEVICE_WACOM(0x100) }, |
2202 | { USB_DEVICE_WACOM(0x101) }, | 2206 | { USB_DEVICE_WACOM(0x101) }, |
2207 | { USB_DEVICE_WACOM(0x10D) }, | ||
2203 | { USB_DEVICE_WACOM(0x4001) }, | 2208 | { USB_DEVICE_WACOM(0x4001) }, |
2204 | { USB_DEVICE_WACOM(0x47) }, | 2209 | { USB_DEVICE_WACOM(0x47) }, |
2205 | { USB_DEVICE_WACOM(0xF4) }, | 2210 | { USB_DEVICE_WACOM(0xF4) }, |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 9a647ee1136a..f9a5fd89bc02 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -517,9 +517,9 @@ config TOUCHSCREEN_TOUCHWIN | |||
517 | To compile this driver as a module, choose M here: the | 517 | To compile this driver as a module, choose M here: the |
518 | module will be called touchwin. | 518 | module will be called touchwin. |
519 | 519 | ||
520 | config TOUCHSCREEN_TI_TSCADC | 520 | config TOUCHSCREEN_TI_AM335X_TSC |
521 | tristate "TI Touchscreen Interface" | 521 | tristate "TI Touchscreen Interface" |
522 | depends on ARCH_OMAP2PLUS | 522 | depends on MFD_TI_AM335X_TSCADC |
523 | help | 523 | help |
524 | Say Y here if you have 4/5/8 wire touchscreen controller | 524 | Say Y here if you have 4/5/8 wire touchscreen controller |
525 | to be connected to the ADC controller on your TI AM335x SoC. | 525 | to be connected to the ADC controller on your TI AM335x SoC. |
@@ -527,7 +527,7 @@ config TOUCHSCREEN_TI_TSCADC | |||
527 | If unsure, say N. | 527 | If unsure, say N. |
528 | 528 | ||
529 | To compile this driver as a module, choose M here: the | 529 | To compile this driver as a module, choose M here: the |
530 | module will be called ti_tscadc. | 530 | module will be called ti_am335x_tsc. |
531 | 531 | ||
532 | config TOUCHSCREEN_ATMEL_TSADCC | 532 | config TOUCHSCREEN_ATMEL_TSADCC |
533 | tristate "Atmel Touchscreen Interface" | 533 | tristate "Atmel Touchscreen Interface" |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 5f949c0bf82f..6bfbeab67c9f 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -51,7 +51,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o | |||
51 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 51 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
52 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o | 52 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o |
53 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 53 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
54 | obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o | 54 | obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o |
55 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | 55 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o |
56 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 56 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
57 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 57 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 4f702b3ec1a3..434c3df250ca 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -236,7 +236,12 @@ static void __ads7846_disable(struct ads7846 *ts) | |||
236 | /* Must be called with ts->lock held */ | 236 | /* Must be called with ts->lock held */ |
237 | static void __ads7846_enable(struct ads7846 *ts) | 237 | static void __ads7846_enable(struct ads7846 *ts) |
238 | { | 238 | { |
239 | regulator_enable(ts->reg); | 239 | int error; |
240 | |||
241 | error = regulator_enable(ts->reg); | ||
242 | if (error != 0) | ||
243 | dev_err(&ts->spi->dev, "Failed to enable supply: %d\n", error); | ||
244 | |||
240 | ads7846_restart(ts); | 245 | ads7846_restart(ts); |
241 | } | 246 | } |
242 | 247 | ||
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index d04f810cb1dd..59aa24002c7b 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -176,11 +176,17 @@ | |||
176 | /* Define for MXT_GEN_COMMAND_T6 */ | 176 | /* Define for MXT_GEN_COMMAND_T6 */ |
177 | #define MXT_BOOT_VALUE 0xa5 | 177 | #define MXT_BOOT_VALUE 0xa5 |
178 | #define MXT_BACKUP_VALUE 0x55 | 178 | #define MXT_BACKUP_VALUE 0x55 |
179 | #define MXT_BACKUP_TIME 25 /* msec */ | 179 | #define MXT_BACKUP_TIME 50 /* msec */ |
180 | #define MXT_RESET_TIME 65 /* msec */ | 180 | #define MXT_RESET_TIME 200 /* msec */ |
181 | 181 | ||
182 | #define MXT_FWRESET_TIME 175 /* msec */ | 182 | #define MXT_FWRESET_TIME 175 /* msec */ |
183 | 183 | ||
184 | /* MXT_SPT_GPIOPWM_T19 field */ | ||
185 | #define MXT_GPIO0_MASK 0x04 | ||
186 | #define MXT_GPIO1_MASK 0x08 | ||
187 | #define MXT_GPIO2_MASK 0x10 | ||
188 | #define MXT_GPIO3_MASK 0x20 | ||
189 | |||
184 | /* Command to unlock bootloader */ | 190 | /* Command to unlock bootloader */ |
185 | #define MXT_UNLOCK_CMD_MSB 0xaa | 191 | #define MXT_UNLOCK_CMD_MSB 0xaa |
186 | #define MXT_UNLOCK_CMD_LSB 0xdc | 192 | #define MXT_UNLOCK_CMD_LSB 0xdc |
@@ -212,6 +218,8 @@ | |||
212 | /* Touchscreen absolute values */ | 218 | /* Touchscreen absolute values */ |
213 | #define MXT_MAX_AREA 0xff | 219 | #define MXT_MAX_AREA 0xff |
214 | 220 | ||
221 | #define MXT_PIXELS_PER_MM 20 | ||
222 | |||
215 | struct mxt_info { | 223 | struct mxt_info { |
216 | u8 family_id; | 224 | u8 family_id; |
217 | u8 variant_id; | 225 | u8 variant_id; |
@@ -243,6 +251,8 @@ struct mxt_data { | |||
243 | const struct mxt_platform_data *pdata; | 251 | const struct mxt_platform_data *pdata; |
244 | struct mxt_object *object_table; | 252 | struct mxt_object *object_table; |
245 | struct mxt_info info; | 253 | struct mxt_info info; |
254 | bool is_tp; | ||
255 | |||
246 | unsigned int irq; | 256 | unsigned int irq; |
247 | unsigned int max_x; | 257 | unsigned int max_x; |
248 | unsigned int max_y; | 258 | unsigned int max_y; |
@@ -251,6 +261,7 @@ struct mxt_data { | |||
251 | u8 T6_reportid; | 261 | u8 T6_reportid; |
252 | u8 T9_reportid_min; | 262 | u8 T9_reportid_min; |
253 | u8 T9_reportid_max; | 263 | u8 T9_reportid_max; |
264 | u8 T19_reportid; | ||
254 | }; | 265 | }; |
255 | 266 | ||
256 | static bool mxt_object_readable(unsigned int type) | 267 | static bool mxt_object_readable(unsigned int type) |
@@ -502,6 +513,21 @@ static int mxt_write_object(struct mxt_data *data, | |||
502 | return mxt_write_reg(data->client, reg + offset, val); | 513 | return mxt_write_reg(data->client, reg + offset, val); |
503 | } | 514 | } |
504 | 515 | ||
516 | static void mxt_input_button(struct mxt_data *data, struct mxt_message *message) | ||
517 | { | ||
518 | struct input_dev *input = data->input_dev; | ||
519 | bool button; | ||
520 | int i; | ||
521 | |||
522 | /* Active-low switch */ | ||
523 | for (i = 0; i < MXT_NUM_GPIO; i++) { | ||
524 | if (data->pdata->key_map[i] == KEY_RESERVED) | ||
525 | continue; | ||
526 | button = !(message->message[0] & MXT_GPIO0_MASK << i); | ||
527 | input_report_key(input, data->pdata->key_map[i], button); | ||
528 | } | ||
529 | } | ||
530 | |||
505 | static void mxt_input_touchevent(struct mxt_data *data, | 531 | static void mxt_input_touchevent(struct mxt_data *data, |
506 | struct mxt_message *message, int id) | 532 | struct mxt_message *message, int id) |
507 | { | 533 | { |
@@ -585,6 +611,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) | |||
585 | int id = reportid - data->T9_reportid_min; | 611 | int id = reportid - data->T9_reportid_min; |
586 | mxt_input_touchevent(data, &message, id); | 612 | mxt_input_touchevent(data, &message, id); |
587 | update_input = true; | 613 | update_input = true; |
614 | } else if (message.reportid == data->T19_reportid) { | ||
615 | mxt_input_button(data, &message); | ||
616 | update_input = true; | ||
588 | } else { | 617 | } else { |
589 | mxt_dump_message(dev, &message); | 618 | mxt_dump_message(dev, &message); |
590 | } | 619 | } |
@@ -764,6 +793,9 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
764 | data->T9_reportid_min = min_id; | 793 | data->T9_reportid_min = min_id; |
765 | data->T9_reportid_max = max_id; | 794 | data->T9_reportid_max = max_id; |
766 | break; | 795 | break; |
796 | case MXT_SPT_GPIOPWM_T19: | ||
797 | data->T19_reportid = min_id; | ||
798 | break; | ||
767 | } | 799 | } |
768 | } | 800 | } |
769 | 801 | ||
@@ -777,7 +809,7 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
777 | data->T6_reportid = 0; | 809 | data->T6_reportid = 0; |
778 | data->T9_reportid_min = 0; | 810 | data->T9_reportid_min = 0; |
779 | data->T9_reportid_max = 0; | 811 | data->T9_reportid_max = 0; |
780 | 812 | data->T19_reportid = 0; | |
781 | } | 813 | } |
782 | 814 | ||
783 | static int mxt_initialize(struct mxt_data *data) | 815 | static int mxt_initialize(struct mxt_data *data) |
@@ -1115,9 +1147,13 @@ static int mxt_probe(struct i2c_client *client, | |||
1115 | goto err_free_mem; | 1147 | goto err_free_mem; |
1116 | } | 1148 | } |
1117 | 1149 | ||
1118 | input_dev->name = "Atmel maXTouch Touchscreen"; | 1150 | data->is_tp = pdata && pdata->is_tp; |
1151 | |||
1152 | input_dev->name = (data->is_tp) ? "Atmel maXTouch Touchpad" : | ||
1153 | "Atmel maXTouch Touchscreen"; | ||
1119 | snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", | 1154 | snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", |
1120 | client->adapter->nr, client->addr); | 1155 | client->adapter->nr, client->addr); |
1156 | |||
1121 | input_dev->phys = data->phys; | 1157 | input_dev->phys = data->phys; |
1122 | 1158 | ||
1123 | input_dev->id.bustype = BUS_I2C; | 1159 | input_dev->id.bustype = BUS_I2C; |
@@ -1140,6 +1176,29 @@ static int mxt_probe(struct i2c_client *client, | |||
1140 | __set_bit(EV_KEY, input_dev->evbit); | 1176 | __set_bit(EV_KEY, input_dev->evbit); |
1141 | __set_bit(BTN_TOUCH, input_dev->keybit); | 1177 | __set_bit(BTN_TOUCH, input_dev->keybit); |
1142 | 1178 | ||
1179 | if (data->is_tp) { | ||
1180 | int i; | ||
1181 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
1182 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | ||
1183 | |||
1184 | for (i = 0; i < MXT_NUM_GPIO; i++) | ||
1185 | if (pdata->key_map[i] != KEY_RESERVED) | ||
1186 | __set_bit(pdata->key_map[i], input_dev->keybit); | ||
1187 | |||
1188 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
1189 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
1190 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
1191 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | ||
1192 | __set_bit(BTN_TOOL_QUINTTAP, input_dev->keybit); | ||
1193 | |||
1194 | input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); | ||
1195 | input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); | ||
1196 | input_abs_set_res(input_dev, ABS_MT_POSITION_X, | ||
1197 | MXT_PIXELS_PER_MM); | ||
1198 | input_abs_set_res(input_dev, ABS_MT_POSITION_Y, | ||
1199 | MXT_PIXELS_PER_MM); | ||
1200 | } | ||
1201 | |||
1143 | /* For single touch */ | 1202 | /* For single touch */ |
1144 | input_set_abs_params(input_dev, ABS_X, | 1203 | input_set_abs_params(input_dev, ABS_X, |
1145 | 0, data->max_x, 0, 0); | 1204 | 0, data->max_x, 0, 0); |
@@ -1258,6 +1317,7 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); | |||
1258 | static const struct i2c_device_id mxt_id[] = { | 1317 | static const struct i2c_device_id mxt_id[] = { |
1259 | { "qt602240_ts", 0 }, | 1318 | { "qt602240_ts", 0 }, |
1260 | { "atmel_mxt_ts", 0 }, | 1319 | { "atmel_mxt_ts", 0 }, |
1320 | { "atmel_mxt_tp", 0 }, | ||
1261 | { "mXT224", 0 }, | 1321 | { "mXT224", 0 }, |
1262 | { } | 1322 | { } |
1263 | }; | 1323 | }; |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 55092d1c5cb9..95f6785a94b0 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <mach/board.h> | 25 | #include <linux/platform_data/atmel.h> |
26 | #include <mach/cpu.h> | 26 | #include <mach/cpu.h> |
27 | 27 | ||
28 | /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ | 28 | /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ |
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c index 303966ffe1e8..8f561e22bdd4 100644 --- a/drivers/input/touchscreen/da9052_tsi.c +++ b/drivers/input/touchscreen/da9052_tsi.c | |||
@@ -27,8 +27,6 @@ struct da9052_tsi { | |||
27 | struct input_dev *dev; | 27 | struct input_dev *dev; |
28 | struct delayed_work ts_pen_work; | 28 | struct delayed_work ts_pen_work; |
29 | struct mutex mutex; | 29 | struct mutex mutex; |
30 | unsigned int irq_pendwn; | ||
31 | unsigned int irq_datardy; | ||
32 | bool stopped; | 30 | bool stopped; |
33 | bool adc_on; | 31 | bool adc_on; |
34 | }; | 32 | }; |
@@ -45,8 +43,8 @@ static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data) | |||
45 | 43 | ||
46 | if (!tsi->stopped) { | 44 | if (!tsi->stopped) { |
47 | /* Mask PEN_DOWN event and unmask TSI_READY event */ | 45 | /* Mask PEN_DOWN event and unmask TSI_READY event */ |
48 | disable_irq_nosync(tsi->irq_pendwn); | 46 | da9052_disable_irq_nosync(tsi->da9052, DA9052_IRQ_PENDOWN); |
49 | enable_irq(tsi->irq_datardy); | 47 | da9052_enable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); |
50 | 48 | ||
51 | da9052_ts_adc_toggle(tsi, true); | 49 | da9052_ts_adc_toggle(tsi, true); |
52 | 50 | ||
@@ -137,8 +135,8 @@ static void da9052_ts_pen_work(struct work_struct *work) | |||
137 | return; | 135 | return; |
138 | 136 | ||
139 | /* Mask TSI_READY event and unmask PEN_DOWN event */ | 137 | /* Mask TSI_READY event and unmask PEN_DOWN event */ |
140 | disable_irq(tsi->irq_datardy); | 138 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); |
141 | enable_irq(tsi->irq_pendwn); | 139 | da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); |
142 | } | 140 | } |
143 | } | 141 | } |
144 | } | 142 | } |
@@ -197,7 +195,7 @@ static int da9052_ts_input_open(struct input_dev *input_dev) | |||
197 | mb(); | 195 | mb(); |
198 | 196 | ||
199 | /* Unmask PEN_DOWN event */ | 197 | /* Unmask PEN_DOWN event */ |
200 | enable_irq(tsi->irq_pendwn); | 198 | da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); |
201 | 199 | ||
202 | /* Enable Pen Detect Circuit */ | 200 | /* Enable Pen Detect Circuit */ |
203 | return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, | 201 | return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, |
@@ -210,11 +208,11 @@ static void da9052_ts_input_close(struct input_dev *input_dev) | |||
210 | 208 | ||
211 | tsi->stopped = true; | 209 | tsi->stopped = true; |
212 | mb(); | 210 | mb(); |
213 | disable_irq(tsi->irq_pendwn); | 211 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); |
214 | cancel_delayed_work_sync(&tsi->ts_pen_work); | 212 | cancel_delayed_work_sync(&tsi->ts_pen_work); |
215 | 213 | ||
216 | if (tsi->adc_on) { | 214 | if (tsi->adc_on) { |
217 | disable_irq(tsi->irq_datardy); | 215 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); |
218 | da9052_ts_adc_toggle(tsi, false); | 216 | da9052_ts_adc_toggle(tsi, false); |
219 | 217 | ||
220 | /* | 218 | /* |
@@ -222,7 +220,7 @@ static void da9052_ts_input_close(struct input_dev *input_dev) | |||
222 | * twice and we need to enable it to keep enable/disable | 220 | * twice and we need to enable it to keep enable/disable |
223 | * counter balanced. IRQ is still off though. | 221 | * counter balanced. IRQ is still off though. |
224 | */ | 222 | */ |
225 | enable_irq(tsi->irq_pendwn); | 223 | da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); |
226 | } | 224 | } |
227 | 225 | ||
228 | /* Disable Pen Detect Circuit */ | 226 | /* Disable Pen Detect Circuit */ |
@@ -234,21 +232,12 @@ static int da9052_ts_probe(struct platform_device *pdev) | |||
234 | struct da9052 *da9052; | 232 | struct da9052 *da9052; |
235 | struct da9052_tsi *tsi; | 233 | struct da9052_tsi *tsi; |
236 | struct input_dev *input_dev; | 234 | struct input_dev *input_dev; |
237 | int irq_pendwn; | ||
238 | int irq_datardy; | ||
239 | int error; | 235 | int error; |
240 | 236 | ||
241 | da9052 = dev_get_drvdata(pdev->dev.parent); | 237 | da9052 = dev_get_drvdata(pdev->dev.parent); |
242 | if (!da9052) | 238 | if (!da9052) |
243 | return -EINVAL; | 239 | return -EINVAL; |
244 | 240 | ||
245 | irq_pendwn = platform_get_irq_byname(pdev, "PENDWN"); | ||
246 | irq_datardy = platform_get_irq_byname(pdev, "TSIRDY"); | ||
247 | if (irq_pendwn < 0 || irq_datardy < 0) { | ||
248 | dev_err(da9052->dev, "Unable to determine device interrupts\n"); | ||
249 | return -ENXIO; | ||
250 | } | ||
251 | |||
252 | tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); | 241 | tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); |
253 | input_dev = input_allocate_device(); | 242 | input_dev = input_allocate_device(); |
254 | if (!tsi || !input_dev) { | 243 | if (!tsi || !input_dev) { |
@@ -258,8 +247,6 @@ static int da9052_ts_probe(struct platform_device *pdev) | |||
258 | 247 | ||
259 | tsi->da9052 = da9052; | 248 | tsi->da9052 = da9052; |
260 | tsi->dev = input_dev; | 249 | tsi->dev = input_dev; |
261 | tsi->irq_pendwn = da9052->irq_base + irq_pendwn; | ||
262 | tsi->irq_datardy = da9052->irq_base + irq_datardy; | ||
263 | tsi->stopped = true; | 250 | tsi->stopped = true; |
264 | INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work); | 251 | INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work); |
265 | 252 | ||
@@ -287,31 +274,25 @@ static int da9052_ts_probe(struct platform_device *pdev) | |||
287 | /* Disable ADC */ | 274 | /* Disable ADC */ |
288 | da9052_ts_adc_toggle(tsi, false); | 275 | da9052_ts_adc_toggle(tsi, false); |
289 | 276 | ||
290 | error = request_threaded_irq(tsi->irq_pendwn, | 277 | error = da9052_request_irq(tsi->da9052, DA9052_IRQ_PENDOWN, |
291 | NULL, da9052_ts_pendwn_irq, | 278 | "pendown-irq", da9052_ts_pendwn_irq, tsi); |
292 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
293 | "PENDWN", tsi); | ||
294 | if (error) { | 279 | if (error) { |
295 | dev_err(tsi->da9052->dev, | 280 | dev_err(tsi->da9052->dev, |
296 | "Failed to register PENDWN IRQ %d, error = %d\n", | 281 | "Failed to register PENDWN IRQ: %d\n", error); |
297 | tsi->irq_pendwn, error); | ||
298 | goto err_free_mem; | 282 | goto err_free_mem; |
299 | } | 283 | } |
300 | 284 | ||
301 | error = request_threaded_irq(tsi->irq_datardy, | 285 | error = da9052_request_irq(tsi->da9052, DA9052_IRQ_TSIREADY, |
302 | NULL, da9052_ts_datardy_irq, | 286 | "tsiready-irq", da9052_ts_datardy_irq, tsi); |
303 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
304 | "TSIRDY", tsi); | ||
305 | if (error) { | 287 | if (error) { |
306 | dev_err(tsi->da9052->dev, | 288 | dev_err(tsi->da9052->dev, |
307 | "Failed to register TSIRDY IRQ %d, error = %d\n", | 289 | "Failed to register TSIRDY IRQ :%d\n", error); |
308 | tsi->irq_datardy, error); | ||
309 | goto err_free_pendwn_irq; | 290 | goto err_free_pendwn_irq; |
310 | } | 291 | } |
311 | 292 | ||
312 | /* Mask PEN_DOWN and TSI_READY events */ | 293 | /* Mask PEN_DOWN and TSI_READY events */ |
313 | disable_irq(tsi->irq_pendwn); | 294 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); |
314 | disable_irq(tsi->irq_datardy); | 295 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); |
315 | 296 | ||
316 | error = da9052_configure_tsi(tsi); | 297 | error = da9052_configure_tsi(tsi); |
317 | if (error) | 298 | if (error) |
@@ -326,9 +307,9 @@ static int da9052_ts_probe(struct platform_device *pdev) | |||
326 | return 0; | 307 | return 0; |
327 | 308 | ||
328 | err_free_datardy_irq: | 309 | err_free_datardy_irq: |
329 | free_irq(tsi->irq_datardy, tsi); | 310 | da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi); |
330 | err_free_pendwn_irq: | 311 | err_free_pendwn_irq: |
331 | free_irq(tsi->irq_pendwn, tsi); | 312 | da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi); |
332 | err_free_mem: | 313 | err_free_mem: |
333 | kfree(tsi); | 314 | kfree(tsi); |
334 | input_free_device(input_dev); | 315 | input_free_device(input_dev); |
@@ -342,8 +323,8 @@ static int da9052_ts_remove(struct platform_device *pdev) | |||
342 | 323 | ||
343 | da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19); | 324 | da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19); |
344 | 325 | ||
345 | free_irq(tsi->irq_pendwn, tsi); | 326 | da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi); |
346 | free_irq(tsi->irq_datardy, tsi); | 327 | da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi); |
347 | 328 | ||
348 | input_unregister_device(tsi->dev); | 329 | input_unregister_device(tsi->dev); |
349 | kfree(tsi); | 330 | kfree(tsi); |
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 4a29ddf6bf1e..1443532fe6c4 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c | |||
@@ -314,15 +314,27 @@ static int mms114_start(struct mms114_data *data) | |||
314 | struct i2c_client *client = data->client; | 314 | struct i2c_client *client = data->client; |
315 | int error; | 315 | int error; |
316 | 316 | ||
317 | if (data->core_reg) | 317 | error = regulator_enable(data->core_reg); |
318 | regulator_enable(data->core_reg); | 318 | if (error) { |
319 | if (data->io_reg) | 319 | dev_err(&client->dev, "Failed to enable avdd: %d\n", error); |
320 | regulator_enable(data->io_reg); | 320 | return error; |
321 | } | ||
322 | |||
323 | error = regulator_enable(data->io_reg); | ||
324 | if (error) { | ||
325 | dev_err(&client->dev, "Failed to enable vdd: %d\n", error); | ||
326 | regulator_disable(data->core_reg); | ||
327 | return error; | ||
328 | } | ||
329 | |||
321 | mdelay(MMS114_POWERON_DELAY); | 330 | mdelay(MMS114_POWERON_DELAY); |
322 | 331 | ||
323 | error = mms114_setup_regs(data); | 332 | error = mms114_setup_regs(data); |
324 | if (error < 0) | 333 | if (error < 0) { |
334 | regulator_disable(data->io_reg); | ||
335 | regulator_disable(data->core_reg); | ||
325 | return error; | 336 | return error; |
337 | } | ||
326 | 338 | ||
327 | if (data->pdata->cfg_pin) | 339 | if (data->pdata->cfg_pin) |
328 | data->pdata->cfg_pin(true); | 340 | data->pdata->cfg_pin(true); |
@@ -335,16 +347,20 @@ static int mms114_start(struct mms114_data *data) | |||
335 | static void mms114_stop(struct mms114_data *data) | 347 | static void mms114_stop(struct mms114_data *data) |
336 | { | 348 | { |
337 | struct i2c_client *client = data->client; | 349 | struct i2c_client *client = data->client; |
350 | int error; | ||
338 | 351 | ||
339 | disable_irq(client->irq); | 352 | disable_irq(client->irq); |
340 | 353 | ||
341 | if (data->pdata->cfg_pin) | 354 | if (data->pdata->cfg_pin) |
342 | data->pdata->cfg_pin(false); | 355 | data->pdata->cfg_pin(false); |
343 | 356 | ||
344 | if (data->io_reg) | 357 | error = regulator_disable(data->io_reg); |
345 | regulator_disable(data->io_reg); | 358 | if (error) |
346 | if (data->core_reg) | 359 | dev_warn(&client->dev, "Failed to disable vdd: %d\n", error); |
347 | regulator_disable(data->core_reg); | 360 | |
361 | error = regulator_disable(data->core_reg); | ||
362 | if (error) | ||
363 | dev_warn(&client->dev, "Failed to disable avdd: %d\n", error); | ||
348 | } | 364 | } |
349 | 365 | ||
350 | static int mms114_input_open(struct input_dev *dev) | 366 | static int mms114_input_open(struct input_dev *dev) |
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c new file mode 100644 index 000000000000..51e7b87827a4 --- /dev/null +++ b/drivers/input/touchscreen/ti_am335x_tsc.c | |||
@@ -0,0 +1,398 @@ | |||
1 | /* | ||
2 | * TI Touch Screen driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/input/ti_am335x_tsc.h> | ||
28 | #include <linux/delay.h> | ||
29 | |||
30 | #include <linux/mfd/ti_am335x_tscadc.h> | ||
31 | |||
32 | #define ADCFSM_STEPID 0x10 | ||
33 | #define SEQ_SETTLE 275 | ||
34 | #define MAX_12BIT ((1 << 12) - 1) | ||
35 | |||
36 | struct titsc { | ||
37 | struct input_dev *input; | ||
38 | struct ti_tscadc_dev *mfd_tscadc; | ||
39 | unsigned int irq; | ||
40 | unsigned int wires; | ||
41 | unsigned int x_plate_resistance; | ||
42 | bool pen_down; | ||
43 | int steps_to_configure; | ||
44 | }; | ||
45 | |||
46 | static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) | ||
47 | { | ||
48 | return readl(ts->mfd_tscadc->tscadc_base + reg); | ||
49 | } | ||
50 | |||
51 | static void titsc_writel(struct titsc *tsc, unsigned int reg, | ||
52 | unsigned int val) | ||
53 | { | ||
54 | writel(val, tsc->mfd_tscadc->tscadc_base + reg); | ||
55 | } | ||
56 | |||
57 | static void titsc_step_config(struct titsc *ts_dev) | ||
58 | { | ||
59 | unsigned int config; | ||
60 | int i, total_steps; | ||
61 | |||
62 | /* Configure the Step registers */ | ||
63 | total_steps = 2 * ts_dev->steps_to_configure; | ||
64 | |||
65 | config = STEPCONFIG_MODE_HWSYNC | | ||
66 | STEPCONFIG_AVG_16 | STEPCONFIG_XPP; | ||
67 | switch (ts_dev->wires) { | ||
68 | case 4: | ||
69 | config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; | ||
70 | break; | ||
71 | case 5: | ||
72 | config |= STEPCONFIG_YNN | | ||
73 | STEPCONFIG_INP_AN4 | STEPCONFIG_XNN | | ||
74 | STEPCONFIG_YPP; | ||
75 | break; | ||
76 | case 8: | ||
77 | config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; | ||
78 | break; | ||
79 | } | ||
80 | |||
81 | for (i = 1; i <= ts_dev->steps_to_configure; i++) { | ||
82 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
83 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
84 | } | ||
85 | |||
86 | config = 0; | ||
87 | config = STEPCONFIG_MODE_HWSYNC | | ||
88 | STEPCONFIG_AVG_16 | STEPCONFIG_YNN | | ||
89 | STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; | ||
90 | switch (ts_dev->wires) { | ||
91 | case 4: | ||
92 | config |= STEPCONFIG_YPP; | ||
93 | break; | ||
94 | case 5: | ||
95 | config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 | | ||
96 | STEPCONFIG_XNP | STEPCONFIG_YPN; | ||
97 | break; | ||
98 | case 8: | ||
99 | config |= STEPCONFIG_YPP; | ||
100 | break; | ||
101 | } | ||
102 | |||
103 | for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { | ||
104 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
105 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
106 | } | ||
107 | |||
108 | config = 0; | ||
109 | /* Charge step configuration */ | ||
110 | config = STEPCONFIG_XPP | STEPCONFIG_YNN | | ||
111 | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | | ||
112 | STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1; | ||
113 | |||
114 | titsc_writel(ts_dev, REG_CHARGECONFIG, config); | ||
115 | titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); | ||
116 | |||
117 | config = 0; | ||
118 | /* Configure to calculate pressure */ | ||
119 | config = STEPCONFIG_MODE_HWSYNC | | ||
120 | STEPCONFIG_AVG_16 | STEPCONFIG_YPP | | ||
121 | STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM; | ||
122 | titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); | ||
123 | titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), | ||
124 | STEPCONFIG_OPENDLY); | ||
125 | |||
126 | config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1; | ||
127 | titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); | ||
128 | titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), | ||
129 | STEPCONFIG_OPENDLY); | ||
130 | |||
131 | titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); | ||
132 | } | ||
133 | |||
134 | static void titsc_read_coordinates(struct titsc *ts_dev, | ||
135 | unsigned int *x, unsigned int *y) | ||
136 | { | ||
137 | unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); | ||
138 | unsigned int prev_val_x = ~0, prev_val_y = ~0; | ||
139 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; | ||
140 | unsigned int read, diff; | ||
141 | unsigned int i, channel; | ||
142 | |||
143 | /* | ||
144 | * Delta filter is used to remove large variations in sampled | ||
145 | * values from ADC. The filter tries to predict where the next | ||
146 | * coordinate could be. This is done by taking a previous | ||
147 | * coordinate and subtracting it form current one. Further the | ||
148 | * algorithm compares the difference with that of a present value, | ||
149 | * if true the value is reported to the sub system. | ||
150 | */ | ||
151 | for (i = 0; i < fifocount - 1; i++) { | ||
152 | read = titsc_readl(ts_dev, REG_FIFO0); | ||
153 | channel = read & 0xf0000; | ||
154 | channel = channel >> 0x10; | ||
155 | if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { | ||
156 | read &= 0xfff; | ||
157 | diff = abs(read - prev_val_x); | ||
158 | if (diff < prev_diff_x) { | ||
159 | prev_diff_x = diff; | ||
160 | *x = read; | ||
161 | } | ||
162 | prev_val_x = read; | ||
163 | } | ||
164 | |||
165 | read = titsc_readl(ts_dev, REG_FIFO1); | ||
166 | channel = read & 0xf0000; | ||
167 | channel = channel >> 0x10; | ||
168 | if ((channel >= ts_dev->steps_to_configure) && | ||
169 | (channel < (2 * ts_dev->steps_to_configure - 1))) { | ||
170 | read &= 0xfff; | ||
171 | diff = abs(read - prev_val_y); | ||
172 | if (diff < prev_diff_y) { | ||
173 | prev_diff_y = diff; | ||
174 | *y = read; | ||
175 | } | ||
176 | prev_val_y = read; | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | static irqreturn_t titsc_irq(int irq, void *dev) | ||
182 | { | ||
183 | struct titsc *ts_dev = dev; | ||
184 | struct input_dev *input_dev = ts_dev->input; | ||
185 | unsigned int status, irqclr = 0; | ||
186 | unsigned int x = 0, y = 0; | ||
187 | unsigned int z1, z2, z; | ||
188 | unsigned int fsm; | ||
189 | unsigned int fifo1count, fifo0count; | ||
190 | int i; | ||
191 | |||
192 | status = titsc_readl(ts_dev, REG_IRQSTATUS); | ||
193 | if (status & IRQENB_FIFO0THRES) { | ||
194 | titsc_read_coordinates(ts_dev, &x, &y); | ||
195 | |||
196 | z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; | ||
197 | z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
198 | |||
199 | fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT); | ||
200 | for (i = 0; i < fifo1count; i++) | ||
201 | titsc_readl(ts_dev, REG_FIFO1); | ||
202 | |||
203 | fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT); | ||
204 | for (i = 0; i < fifo0count; i++) | ||
205 | titsc_readl(ts_dev, REG_FIFO0); | ||
206 | |||
207 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { | ||
208 | /* | ||
209 | * Calculate pressure using formula | ||
210 | * Resistance(touch) = x plate resistance * | ||
211 | * x postion/4096 * ((z2 / z1) - 1) | ||
212 | */ | ||
213 | z = z2 - z1; | ||
214 | z *= x; | ||
215 | z *= ts_dev->x_plate_resistance; | ||
216 | z /= z1; | ||
217 | z = (z + 2047) >> 12; | ||
218 | |||
219 | if (z <= MAX_12BIT) { | ||
220 | input_report_abs(input_dev, ABS_X, x); | ||
221 | input_report_abs(input_dev, ABS_Y, y); | ||
222 | input_report_abs(input_dev, ABS_PRESSURE, z); | ||
223 | input_report_key(input_dev, BTN_TOUCH, 1); | ||
224 | input_sync(input_dev); | ||
225 | } | ||
226 | } | ||
227 | irqclr |= IRQENB_FIFO0THRES; | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * Time for sequencer to settle, to read | ||
232 | * correct state of the sequencer. | ||
233 | */ | ||
234 | udelay(SEQ_SETTLE); | ||
235 | |||
236 | status = titsc_readl(ts_dev, REG_RAWIRQSTATUS); | ||
237 | if (status & IRQENB_PENUP) { | ||
238 | /* Pen up event */ | ||
239 | fsm = titsc_readl(ts_dev, REG_ADCFSM); | ||
240 | if (fsm == ADCFSM_STEPID) { | ||
241 | ts_dev->pen_down = false; | ||
242 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
243 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
244 | input_sync(input_dev); | ||
245 | } else { | ||
246 | ts_dev->pen_down = true; | ||
247 | } | ||
248 | irqclr |= IRQENB_PENUP; | ||
249 | } | ||
250 | |||
251 | titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); | ||
252 | |||
253 | titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); | ||
254 | return IRQ_HANDLED; | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * The functions for inserting/removing driver as a module. | ||
259 | */ | ||
260 | |||
261 | static int titsc_probe(struct platform_device *pdev) | ||
262 | { | ||
263 | struct titsc *ts_dev; | ||
264 | struct input_dev *input_dev; | ||
265 | struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; | ||
266 | struct mfd_tscadc_board *pdata; | ||
267 | int err; | ||
268 | |||
269 | pdata = tscadc_dev->dev->platform_data; | ||
270 | |||
271 | if (!pdata) { | ||
272 | dev_err(&pdev->dev, "Could not find platform data\n"); | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | |||
276 | /* Allocate memory for device */ | ||
277 | ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); | ||
278 | input_dev = input_allocate_device(); | ||
279 | if (!ts_dev || !input_dev) { | ||
280 | dev_err(&pdev->dev, "failed to allocate memory.\n"); | ||
281 | err = -ENOMEM; | ||
282 | goto err_free_mem; | ||
283 | } | ||
284 | |||
285 | tscadc_dev->tsc = ts_dev; | ||
286 | ts_dev->mfd_tscadc = tscadc_dev; | ||
287 | ts_dev->input = input_dev; | ||
288 | ts_dev->irq = tscadc_dev->irq; | ||
289 | ts_dev->wires = pdata->tsc_init->wires; | ||
290 | ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; | ||
291 | ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; | ||
292 | |||
293 | err = request_irq(ts_dev->irq, titsc_irq, | ||
294 | 0, pdev->dev.driver->name, ts_dev); | ||
295 | if (err) { | ||
296 | dev_err(&pdev->dev, "failed to allocate irq.\n"); | ||
297 | goto err_free_mem; | ||
298 | } | ||
299 | |||
300 | titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); | ||
301 | titsc_step_config(ts_dev); | ||
302 | titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); | ||
303 | |||
304 | input_dev->name = "ti-tsc"; | ||
305 | input_dev->dev.parent = &pdev->dev; | ||
306 | |||
307 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
308 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
309 | |||
310 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); | ||
311 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | ||
312 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | ||
313 | |||
314 | /* register to the input system */ | ||
315 | err = input_register_device(input_dev); | ||
316 | if (err) | ||
317 | goto err_free_irq; | ||
318 | |||
319 | platform_set_drvdata(pdev, ts_dev); | ||
320 | return 0; | ||
321 | |||
322 | err_free_irq: | ||
323 | free_irq(ts_dev->irq, ts_dev); | ||
324 | err_free_mem: | ||
325 | input_free_device(input_dev); | ||
326 | kfree(ts_dev); | ||
327 | return err; | ||
328 | } | ||
329 | |||
330 | static int titsc_remove(struct platform_device *pdev) | ||
331 | { | ||
332 | struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; | ||
333 | struct titsc *ts_dev = tscadc_dev->tsc; | ||
334 | |||
335 | free_irq(ts_dev->irq, ts_dev); | ||
336 | |||
337 | input_unregister_device(ts_dev->input); | ||
338 | |||
339 | platform_set_drvdata(pdev, NULL); | ||
340 | kfree(ts_dev); | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | #ifdef CONFIG_PM | ||
345 | static int titsc_suspend(struct device *dev) | ||
346 | { | ||
347 | struct ti_tscadc_dev *tscadc_dev = dev->platform_data; | ||
348 | struct titsc *ts_dev = tscadc_dev->tsc; | ||
349 | unsigned int idle; | ||
350 | |||
351 | if (device_may_wakeup(tscadc_dev->dev)) { | ||
352 | idle = titsc_readl(ts_dev, REG_IRQENABLE); | ||
353 | titsc_writel(ts_dev, REG_IRQENABLE, | ||
354 | (idle | IRQENB_HW_PEN)); | ||
355 | titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB); | ||
356 | } | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int titsc_resume(struct device *dev) | ||
361 | { | ||
362 | struct ti_tscadc_dev *tscadc_dev = dev->platform_data; | ||
363 | struct titsc *ts_dev = tscadc_dev->tsc; | ||
364 | |||
365 | if (device_may_wakeup(tscadc_dev->dev)) { | ||
366 | titsc_writel(ts_dev, REG_IRQWAKEUP, | ||
367 | 0x00); | ||
368 | titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); | ||
369 | } | ||
370 | titsc_step_config(ts_dev); | ||
371 | titsc_writel(ts_dev, REG_FIFO0THR, | ||
372 | ts_dev->steps_to_configure); | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static const struct dev_pm_ops titsc_pm_ops = { | ||
377 | .suspend = titsc_suspend, | ||
378 | .resume = titsc_resume, | ||
379 | }; | ||
380 | #define TITSC_PM_OPS (&titsc_pm_ops) | ||
381 | #else | ||
382 | #define TITSC_PM_OPS NULL | ||
383 | #endif | ||
384 | |||
385 | static struct platform_driver ti_tsc_driver = { | ||
386 | .probe = titsc_probe, | ||
387 | .remove = titsc_remove, | ||
388 | .driver = { | ||
389 | .name = "tsc", | ||
390 | .owner = THIS_MODULE, | ||
391 | .pm = TITSC_PM_OPS, | ||
392 | }, | ||
393 | }; | ||
394 | module_platform_driver(ti_tsc_driver); | ||
395 | |||
396 | MODULE_DESCRIPTION("TI touchscreen controller driver"); | ||
397 | MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); | ||
398 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c deleted file mode 100644 index bcedf2e7468c..000000000000 --- a/drivers/input/touchscreen/ti_tscadc.c +++ /dev/null | |||
@@ -1,486 +0,0 @@ | |||
1 | /* | ||
2 | * TI Touch Screen driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/input/ti_tscadc.h> | ||
28 | #include <linux/delay.h> | ||
29 | |||
30 | #define REG_IRQEOI 0x020 | ||
31 | #define REG_RAWIRQSTATUS 0x024 | ||
32 | #define REG_IRQSTATUS 0x028 | ||
33 | #define REG_IRQENABLE 0x02C | ||
34 | #define REG_IRQWAKEUP 0x034 | ||
35 | #define REG_CTRL 0x040 | ||
36 | #define REG_ADCFSM 0x044 | ||
37 | #define REG_CLKDIV 0x04C | ||
38 | #define REG_SE 0x054 | ||
39 | #define REG_IDLECONFIG 0x058 | ||
40 | #define REG_CHARGECONFIG 0x05C | ||
41 | #define REG_CHARGEDELAY 0x060 | ||
42 | #define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8)) | ||
43 | #define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8)) | ||
44 | #define REG_STEPCONFIG13 0x0C4 | ||
45 | #define REG_STEPDELAY13 0x0C8 | ||
46 | #define REG_STEPCONFIG14 0x0CC | ||
47 | #define REG_STEPDELAY14 0x0D0 | ||
48 | #define REG_FIFO0CNT 0xE4 | ||
49 | #define REG_FIFO1THR 0xF4 | ||
50 | #define REG_FIFO0 0x100 | ||
51 | #define REG_FIFO1 0x200 | ||
52 | |||
53 | /* Register Bitfields */ | ||
54 | #define IRQWKUP_ENB BIT(0) | ||
55 | #define STPENB_STEPENB 0x7FFF | ||
56 | #define IRQENB_FIFO1THRES BIT(5) | ||
57 | #define IRQENB_PENUP BIT(9) | ||
58 | #define STEPCONFIG_MODE_HWSYNC 0x2 | ||
59 | #define STEPCONFIG_SAMPLES_AVG (1 << 4) | ||
60 | #define STEPCONFIG_XPP (1 << 5) | ||
61 | #define STEPCONFIG_XNN (1 << 6) | ||
62 | #define STEPCONFIG_YPP (1 << 7) | ||
63 | #define STEPCONFIG_YNN (1 << 8) | ||
64 | #define STEPCONFIG_XNP (1 << 9) | ||
65 | #define STEPCONFIG_YPN (1 << 10) | ||
66 | #define STEPCONFIG_INM (1 << 18) | ||
67 | #define STEPCONFIG_INP (1 << 20) | ||
68 | #define STEPCONFIG_INP_5 (1 << 21) | ||
69 | #define STEPCONFIG_FIFO1 (1 << 26) | ||
70 | #define STEPCONFIG_OPENDLY 0xff | ||
71 | #define STEPCONFIG_Z1 (3 << 19) | ||
72 | #define STEPIDLE_INP (1 << 22) | ||
73 | #define STEPCHARGE_RFP (1 << 12) | ||
74 | #define STEPCHARGE_INM (1 << 15) | ||
75 | #define STEPCHARGE_INP (1 << 19) | ||
76 | #define STEPCHARGE_RFM (1 << 23) | ||
77 | #define STEPCHARGE_DELAY 0x1 | ||
78 | #define CNTRLREG_TSCSSENB (1 << 0) | ||
79 | #define CNTRLREG_STEPID (1 << 1) | ||
80 | #define CNTRLREG_STEPCONFIGWRT (1 << 2) | ||
81 | #define CNTRLREG_4WIRE (1 << 5) | ||
82 | #define CNTRLREG_5WIRE (1 << 6) | ||
83 | #define CNTRLREG_8WIRE (3 << 5) | ||
84 | #define CNTRLREG_TSCENB (1 << 7) | ||
85 | #define ADCFSM_STEPID 0x10 | ||
86 | |||
87 | #define SEQ_SETTLE 275 | ||
88 | #define ADC_CLK 3000000 | ||
89 | #define MAX_12BIT ((1 << 12) - 1) | ||
90 | #define TSCADC_DELTA_X 15 | ||
91 | #define TSCADC_DELTA_Y 15 | ||
92 | |||
93 | struct tscadc { | ||
94 | struct input_dev *input; | ||
95 | struct clk *tsc_ick; | ||
96 | void __iomem *tsc_base; | ||
97 | unsigned int irq; | ||
98 | unsigned int wires; | ||
99 | unsigned int x_plate_resistance; | ||
100 | bool pen_down; | ||
101 | }; | ||
102 | |||
103 | static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg) | ||
104 | { | ||
105 | return readl(ts->tsc_base + reg); | ||
106 | } | ||
107 | |||
108 | static void tscadc_writel(struct tscadc *tsc, unsigned int reg, | ||
109 | unsigned int val) | ||
110 | { | ||
111 | writel(val, tsc->tsc_base + reg); | ||
112 | } | ||
113 | |||
114 | static void tscadc_step_config(struct tscadc *ts_dev) | ||
115 | { | ||
116 | unsigned int config; | ||
117 | int i; | ||
118 | |||
119 | /* Configure the Step registers */ | ||
120 | |||
121 | config = STEPCONFIG_MODE_HWSYNC | | ||
122 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP; | ||
123 | switch (ts_dev->wires) { | ||
124 | case 4: | ||
125 | config |= STEPCONFIG_INP | STEPCONFIG_XNN; | ||
126 | break; | ||
127 | case 5: | ||
128 | config |= STEPCONFIG_YNN | | ||
129 | STEPCONFIG_INP_5 | STEPCONFIG_XNN | | ||
130 | STEPCONFIG_YPP; | ||
131 | break; | ||
132 | case 8: | ||
133 | config |= STEPCONFIG_INP | STEPCONFIG_XNN; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | for (i = 1; i < 7; i++) { | ||
138 | tscadc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
139 | tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
140 | } | ||
141 | |||
142 | config = 0; | ||
143 | config = STEPCONFIG_MODE_HWSYNC | | ||
144 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN | | ||
145 | STEPCONFIG_INM | STEPCONFIG_FIFO1; | ||
146 | switch (ts_dev->wires) { | ||
147 | case 4: | ||
148 | config |= STEPCONFIG_YPP; | ||
149 | break; | ||
150 | case 5: | ||
151 | config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 | | ||
152 | STEPCONFIG_XNP | STEPCONFIG_YPN; | ||
153 | break; | ||
154 | case 8: | ||
155 | config |= STEPCONFIG_YPP; | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | for (i = 7; i < 13; i++) { | ||
160 | tscadc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
161 | tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
162 | } | ||
163 | |||
164 | config = 0; | ||
165 | /* Charge step configuration */ | ||
166 | config = STEPCONFIG_XPP | STEPCONFIG_YNN | | ||
167 | STEPCHARGE_RFP | STEPCHARGE_RFM | | ||
168 | STEPCHARGE_INM | STEPCHARGE_INP; | ||
169 | |||
170 | tscadc_writel(ts_dev, REG_CHARGECONFIG, config); | ||
171 | tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY); | ||
172 | |||
173 | config = 0; | ||
174 | /* Configure to calculate pressure */ | ||
175 | config = STEPCONFIG_MODE_HWSYNC | | ||
176 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP | | ||
177 | STEPCONFIG_XNN | STEPCONFIG_INM; | ||
178 | tscadc_writel(ts_dev, REG_STEPCONFIG13, config); | ||
179 | tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY); | ||
180 | |||
181 | config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1; | ||
182 | tscadc_writel(ts_dev, REG_STEPCONFIG14, config); | ||
183 | tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY); | ||
184 | |||
185 | tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB); | ||
186 | } | ||
187 | |||
188 | static void tscadc_idle_config(struct tscadc *ts_config) | ||
189 | { | ||
190 | unsigned int idleconfig; | ||
191 | |||
192 | idleconfig = STEPCONFIG_YNN | | ||
193 | STEPCONFIG_INM | | ||
194 | STEPCONFIG_YPN | STEPIDLE_INP; | ||
195 | tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig); | ||
196 | } | ||
197 | |||
198 | static void tscadc_read_coordinates(struct tscadc *ts_dev, | ||
199 | unsigned int *x, unsigned int *y) | ||
200 | { | ||
201 | unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT); | ||
202 | unsigned int prev_val_x = ~0, prev_val_y = ~0; | ||
203 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; | ||
204 | unsigned int read, diff; | ||
205 | unsigned int i; | ||
206 | |||
207 | /* | ||
208 | * Delta filter is used to remove large variations in sampled | ||
209 | * values from ADC. The filter tries to predict where the next | ||
210 | * coordinate could be. This is done by taking a previous | ||
211 | * coordinate and subtracting it form current one. Further the | ||
212 | * algorithm compares the difference with that of a present value, | ||
213 | * if true the value is reported to the sub system. | ||
214 | */ | ||
215 | for (i = 0; i < fifocount - 1; i++) { | ||
216 | read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff; | ||
217 | diff = abs(read - prev_val_x); | ||
218 | if (diff < prev_diff_x) { | ||
219 | prev_diff_x = diff; | ||
220 | *x = read; | ||
221 | } | ||
222 | prev_val_x = read; | ||
223 | |||
224 | read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
225 | diff = abs(read - prev_val_y); | ||
226 | if (diff < prev_diff_y) { | ||
227 | prev_diff_y = diff; | ||
228 | *y = read; | ||
229 | } | ||
230 | prev_val_y = read; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static irqreturn_t tscadc_irq(int irq, void *dev) | ||
235 | { | ||
236 | struct tscadc *ts_dev = dev; | ||
237 | struct input_dev *input_dev = ts_dev->input; | ||
238 | unsigned int status, irqclr = 0; | ||
239 | unsigned int x = 0, y = 0; | ||
240 | unsigned int z1, z2, z; | ||
241 | unsigned int fsm; | ||
242 | |||
243 | status = tscadc_readl(ts_dev, REG_IRQSTATUS); | ||
244 | if (status & IRQENB_FIFO1THRES) { | ||
245 | tscadc_read_coordinates(ts_dev, &x, &y); | ||
246 | |||
247 | z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff; | ||
248 | z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
249 | |||
250 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { | ||
251 | /* | ||
252 | * Calculate pressure using formula | ||
253 | * Resistance(touch) = x plate resistance * | ||
254 | * x postion/4096 * ((z2 / z1) - 1) | ||
255 | */ | ||
256 | z = z2 - z1; | ||
257 | z *= x; | ||
258 | z *= ts_dev->x_plate_resistance; | ||
259 | z /= z1; | ||
260 | z = (z + 2047) >> 12; | ||
261 | |||
262 | if (z <= MAX_12BIT) { | ||
263 | input_report_abs(input_dev, ABS_X, x); | ||
264 | input_report_abs(input_dev, ABS_Y, y); | ||
265 | input_report_abs(input_dev, ABS_PRESSURE, z); | ||
266 | input_report_key(input_dev, BTN_TOUCH, 1); | ||
267 | input_sync(input_dev); | ||
268 | } | ||
269 | } | ||
270 | irqclr |= IRQENB_FIFO1THRES; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * Time for sequencer to settle, to read | ||
275 | * correct state of the sequencer. | ||
276 | */ | ||
277 | udelay(SEQ_SETTLE); | ||
278 | |||
279 | status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS); | ||
280 | if (status & IRQENB_PENUP) { | ||
281 | /* Pen up event */ | ||
282 | fsm = tscadc_readl(ts_dev, REG_ADCFSM); | ||
283 | if (fsm == ADCFSM_STEPID) { | ||
284 | ts_dev->pen_down = false; | ||
285 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
286 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
287 | input_sync(input_dev); | ||
288 | } else { | ||
289 | ts_dev->pen_down = true; | ||
290 | } | ||
291 | irqclr |= IRQENB_PENUP; | ||
292 | } | ||
293 | |||
294 | tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr); | ||
295 | /* check pending interrupts */ | ||
296 | tscadc_writel(ts_dev, REG_IRQEOI, 0x0); | ||
297 | |||
298 | tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB); | ||
299 | return IRQ_HANDLED; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * The functions for inserting/removing driver as a module. | ||
304 | */ | ||
305 | |||
306 | static int tscadc_probe(struct platform_device *pdev) | ||
307 | { | ||
308 | const struct tsc_data *pdata = pdev->dev.platform_data; | ||
309 | struct resource *res; | ||
310 | struct tscadc *ts_dev; | ||
311 | struct input_dev *input_dev; | ||
312 | struct clk *clk; | ||
313 | int err; | ||
314 | int clk_value, ctrl, irq; | ||
315 | |||
316 | if (!pdata) { | ||
317 | dev_err(&pdev->dev, "missing platform data.\n"); | ||
318 | return -EINVAL; | ||
319 | } | ||
320 | |||
321 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
322 | if (!res) { | ||
323 | dev_err(&pdev->dev, "no memory resource defined.\n"); | ||
324 | return -EINVAL; | ||
325 | } | ||
326 | |||
327 | irq = platform_get_irq(pdev, 0); | ||
328 | if (irq < 0) { | ||
329 | dev_err(&pdev->dev, "no irq ID is specified.\n"); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
333 | /* Allocate memory for device */ | ||
334 | ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL); | ||
335 | input_dev = input_allocate_device(); | ||
336 | if (!ts_dev || !input_dev) { | ||
337 | dev_err(&pdev->dev, "failed to allocate memory.\n"); | ||
338 | err = -ENOMEM; | ||
339 | goto err_free_mem; | ||
340 | } | ||
341 | |||
342 | ts_dev->input = input_dev; | ||
343 | ts_dev->irq = irq; | ||
344 | ts_dev->wires = pdata->wires; | ||
345 | ts_dev->x_plate_resistance = pdata->x_plate_resistance; | ||
346 | |||
347 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
348 | if (!res) { | ||
349 | dev_err(&pdev->dev, "failed to reserve registers.\n"); | ||
350 | err = -EBUSY; | ||
351 | goto err_free_mem; | ||
352 | } | ||
353 | |||
354 | ts_dev->tsc_base = ioremap(res->start, resource_size(res)); | ||
355 | if (!ts_dev->tsc_base) { | ||
356 | dev_err(&pdev->dev, "failed to map registers.\n"); | ||
357 | err = -ENOMEM; | ||
358 | goto err_release_mem_region; | ||
359 | } | ||
360 | |||
361 | err = request_irq(ts_dev->irq, tscadc_irq, | ||
362 | 0, pdev->dev.driver->name, ts_dev); | ||
363 | if (err) { | ||
364 | dev_err(&pdev->dev, "failed to allocate irq.\n"); | ||
365 | goto err_unmap_regs; | ||
366 | } | ||
367 | |||
368 | ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick"); | ||
369 | if (IS_ERR(ts_dev->tsc_ick)) { | ||
370 | dev_err(&pdev->dev, "failed to get TSC ick\n"); | ||
371 | goto err_free_irq; | ||
372 | } | ||
373 | clk_enable(ts_dev->tsc_ick); | ||
374 | |||
375 | clk = clk_get(&pdev->dev, "adc_tsc_fck"); | ||
376 | if (IS_ERR(clk)) { | ||
377 | dev_err(&pdev->dev, "failed to get TSC fck\n"); | ||
378 | err = PTR_ERR(clk); | ||
379 | goto err_disable_clk; | ||
380 | } | ||
381 | |||
382 | clk_value = clk_get_rate(clk) / ADC_CLK; | ||
383 | clk_put(clk); | ||
384 | |||
385 | if (clk_value < 7) { | ||
386 | dev_err(&pdev->dev, "clock input less than min clock requirement\n"); | ||
387 | goto err_disable_clk; | ||
388 | } | ||
389 | /* CLKDIV needs to be configured to the value minus 1 */ | ||
390 | tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1); | ||
391 | |||
392 | /* Enable wake-up of the SoC using touchscreen */ | ||
393 | tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB); | ||
394 | |||
395 | ctrl = CNTRLREG_STEPCONFIGWRT | | ||
396 | CNTRLREG_TSCENB | | ||
397 | CNTRLREG_STEPID; | ||
398 | switch (ts_dev->wires) { | ||
399 | case 4: | ||
400 | ctrl |= CNTRLREG_4WIRE; | ||
401 | break; | ||
402 | case 5: | ||
403 | ctrl |= CNTRLREG_5WIRE; | ||
404 | break; | ||
405 | case 8: | ||
406 | ctrl |= CNTRLREG_8WIRE; | ||
407 | break; | ||
408 | } | ||
409 | tscadc_writel(ts_dev, REG_CTRL, ctrl); | ||
410 | |||
411 | tscadc_idle_config(ts_dev); | ||
412 | tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES); | ||
413 | tscadc_step_config(ts_dev); | ||
414 | tscadc_writel(ts_dev, REG_FIFO1THR, 6); | ||
415 | |||
416 | ctrl |= CNTRLREG_TSCSSENB; | ||
417 | tscadc_writel(ts_dev, REG_CTRL, ctrl); | ||
418 | |||
419 | input_dev->name = "ti-tsc-adc"; | ||
420 | input_dev->dev.parent = &pdev->dev; | ||
421 | |||
422 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
423 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
424 | |||
425 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); | ||
426 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | ||
427 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | ||
428 | |||
429 | /* register to the input system */ | ||
430 | err = input_register_device(input_dev); | ||
431 | if (err) | ||
432 | goto err_disable_clk; | ||
433 | |||
434 | platform_set_drvdata(pdev, ts_dev); | ||
435 | return 0; | ||
436 | |||
437 | err_disable_clk: | ||
438 | clk_disable(ts_dev->tsc_ick); | ||
439 | clk_put(ts_dev->tsc_ick); | ||
440 | err_free_irq: | ||
441 | free_irq(ts_dev->irq, ts_dev); | ||
442 | err_unmap_regs: | ||
443 | iounmap(ts_dev->tsc_base); | ||
444 | err_release_mem_region: | ||
445 | release_mem_region(res->start, resource_size(res)); | ||
446 | err_free_mem: | ||
447 | input_free_device(input_dev); | ||
448 | kfree(ts_dev); | ||
449 | return err; | ||
450 | } | ||
451 | |||
452 | static int __devexit tscadc_remove(struct platform_device *pdev) | ||
453 | { | ||
454 | struct tscadc *ts_dev = platform_get_drvdata(pdev); | ||
455 | struct resource *res; | ||
456 | |||
457 | free_irq(ts_dev->irq, ts_dev); | ||
458 | |||
459 | input_unregister_device(ts_dev->input); | ||
460 | |||
461 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
462 | iounmap(ts_dev->tsc_base); | ||
463 | release_mem_region(res->start, resource_size(res)); | ||
464 | |||
465 | clk_disable(ts_dev->tsc_ick); | ||
466 | clk_put(ts_dev->tsc_ick); | ||
467 | |||
468 | kfree(ts_dev); | ||
469 | |||
470 | platform_set_drvdata(pdev, NULL); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static struct platform_driver ti_tsc_driver = { | ||
475 | .probe = tscadc_probe, | ||
476 | .remove = __devexit_p(tscadc_remove), | ||
477 | .driver = { | ||
478 | .name = "tsc", | ||
479 | .owner = THIS_MODULE, | ||
480 | }, | ||
481 | }; | ||
482 | module_platform_driver(ti_tsc_driver); | ||
483 | |||
484 | MODULE_DESCRIPTION("TI touchscreen controller driver"); | ||
485 | MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); | ||
486 | MODULE_LICENSE("GPL"); | ||