Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:
"A few new haptic/button drivers, a rudimentary support for laptops
using FocalTech touchpads; xpad driver will bind to more devices, and
a few other driver fixes."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: soc_button_array - convert to platform bus
Input: palmas-pwrbutton - fix typo in the license string
Input: palmas-pwrbutton - use IRQF_ONESHOT
Input: psmouse - add support for detecting FocalTech PS/2 touchpads
Input: psmouse - add psmouse_matches_pnp_id helper function
Input: joystick - use ktime for measuring timing
Input: add haptic driver on max77693
Input: introduce palmas-pwrbutton
Input: add support for the DRV2667 haptic driver
Input: xpad - sync device IDs with xboxdrv
Input: xpad - add VID/PID for Razer Sabertooth
Input: cros_ec_keyb - optimize ghosting algorithm
Input: drv260x - fix binding document
Input: drv260x - add check for ERM mode and LRA Libraries
Input: drv260x - remove unused defines
Input: drv260x - add TI drv260x haptics driver

+2468 -109
+50
Documentation/devicetree/bindings/input/ti,drv260x.txt
··· 1 + * Texas Instruments - drv260x Haptics driver family 2 + 3 + Required properties: 4 + - compatible - One of: 5 + "ti,drv2604" - DRV2604 6 + "ti,drv2605" - DRV2605 7 + "ti,drv2605l" - DRV2605L 8 + - reg - I2C slave address 9 + - vbat-supply - Required supply regulator 10 + - mode - Power up mode of the chip (defined in include/dt-bindings/input/ti-drv260x.h) 11 + DRV260X_LRA_MODE - Linear Resonance Actuator mode (Piezoelectric) 12 + DRV260X_LRA_NO_CAL_MODE - This is a LRA Mode but there is no calibration 13 + sequence during init. And the device is configured for real 14 + time playback mode (RTP mode). 15 + DRV260X_ERM_MODE - Eccentric Rotating Mass mode (Rotary vibrator) 16 + - library-sel - These are ROM based waveforms pre-programmed into the IC. 17 + This should be set to set the library to use at power up. 18 + (defined in include/dt-bindings/input/ti-drv260x.h) 19 + DRV260X_LIB_EMPTY - Do not use a pre-programmed library 20 + DRV260X_ERM_LIB_A - Pre-programmed Library 21 + DRV260X_ERM_LIB_B - Pre-programmed Library 22 + DRV260X_ERM_LIB_C - Pre-programmed Library 23 + DRV260X_ERM_LIB_D - Pre-programmed Library 24 + DRV260X_ERM_LIB_E - Pre-programmed Library 25 + DRV260X_ERM_LIB_F - Pre-programmed Library 26 + DRV260X_LIB_LRA - Pre-programmed LRA Library 27 + 28 + Optional properties: 29 + - enable-gpio - gpio pin to enable/disable the device. 30 + - vib-rated-mv - The rated voltage of the actuator in millivolts. 31 + If this is not set then the value will be defaulted to 32 + 3.2 v. 33 + - vib-overdrive-mv - The overdrive voltage of the actuator in millivolts. 34 + If this is not set then the value will be defaulted to 35 + 3.2 v. 36 + Example: 37 + 38 + haptics: haptics@5a { 39 + compatible = "ti,drv2605l"; 40 + reg = <0x5a>; 41 + vbat-supply = <&vbat>; 42 + enable-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>; 43 + mode = <DRV260X_LRA_MODE>; 44 + library-sel = <DRV260X_LIB_LRA>; 45 + vib-rated-mv = <3200>; 46 + vib-overdriver-mv = <3200>; 47 + } 48 + 49 + For more product information please see the link below: 50 + http://www.ti.com/product/drv2605
+17
Documentation/devicetree/bindings/input/ti,drv2667.txt
··· 1 + * Texas Instruments - drv2667 Haptics driver 2 + 3 + Required properties: 4 + - compatible - "ti,drv2667" - DRV2667 5 + - reg - I2C slave address 6 + - vbat-supply - Required supply regulator 7 + 8 + Example: 9 + 10 + haptics: haptics@59 { 11 + compatible = "ti,drv2667"; 12 + reg = <0x59>; 13 + vbat-supply = <&vbat>; 14 + }; 15 + 16 + For more product information please see the link below: 17 + http://www.ti.com/product/drv2667
+36
Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.txt
··· 1 + Texas Instruments Palmas family power button module 2 + 3 + This module is part of the Palmas family of PMICs. For more details 4 + about the whole chip see: 5 + Documentation/devicetree/bindings/mfd/palmas.txt. 6 + 7 + This module provides a simple power button event via an Interrupt. 8 + 9 + Required properties: 10 + - compatible: should be one of the following 11 + - "ti,palmas-pwrbutton": For Palmas compatible power on button 12 + - interrupt-parent: Parent interrupt device, must be handle of palmas node. 13 + - interrupts: Interrupt number of power button submodule on device. 14 + 15 + Optional Properties: 16 + 17 + - ti,palmas-long-press-seconds: Duration in seconds which the power 18 + button should be kept pressed for Palmas to power off automatically. 19 + NOTE: This depends on OTP support and POWERHOLD signal configuration 20 + on platform. Valid values are 6, 8, 10 and 12. 21 + - ti,palmas-pwron-debounce-milli-seconds: Duration in milliseconds 22 + which the power button should be kept pressed for Palmas to register 23 + a press for debouncing purposes. NOTE: This depends on specific 24 + Palmas variation capability. Valid values are 15, 100, 500 and 1000. 25 + 26 + Example: 27 + 28 + &palmas { 29 + palmas_pwr_button: pwrbutton { 30 + compatible = "ti,palmas-pwrbutton"; 31 + interrupt-parent = <&tps659038>; 32 + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; 33 + ti,palmas-long-press-seconds = <12>; 34 + ti,palmas-pwron-debounce-milli-seconds = <15>; 35 + }; 36 + };
-2
drivers/acpi/acpi_pnp.c
··· 15 15 #include <linux/ctype.h> 16 16 17 17 static const struct acpi_device_id acpi_pnp_device_ids[] = { 18 - /* soc_button_array */ 19 - {"PNP0C40"}, 20 18 /* pata_isapnp */ 21 19 {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */ 22 20 /* floppy */
+40 -1
drivers/input/gameport/gameport.c
··· 23 23 #include <linux/workqueue.h> 24 24 #include <linux/sched.h> /* HZ */ 25 25 #include <linux/mutex.h> 26 + #include <linux/timekeeping.h> 26 27 27 28 /*#include <asm/io.h>*/ 28 29 29 30 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 30 31 MODULE_DESCRIPTION("Generic gameport layer"); 31 32 MODULE_LICENSE("GPL"); 33 + 34 + static bool use_ktime = true; 35 + module_param(use_ktime, bool, 0400); 36 + MODULE_PARM_DESC(use_ktime, "Use ktime for measuring I/O speed"); 32 37 33 38 /* 34 39 * gameport_mutex protects entire gameport subsystem and is taken ··· 80 75 */ 81 76 82 77 static int gameport_measure_speed(struct gameport *gameport) 78 + { 79 + unsigned int i, t, tx; 80 + u64 t1, t2, t3; 81 + unsigned long flags; 82 + 83 + if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) 84 + return 0; 85 + 86 + tx = ~0; 87 + 88 + for (i = 0; i < 50; i++) { 89 + local_irq_save(flags); 90 + t1 = ktime_get_ns(); 91 + for (t = 0; t < 50; t++) 92 + gameport_read(gameport); 93 + t2 = ktime_get_ns(); 94 + t3 = ktime_get_ns(); 95 + local_irq_restore(flags); 96 + udelay(i * 10); 97 + t = (t2 - t1) - (t3 - t2); 98 + if (t < tx) 99 + tx = t; 100 + } 101 + 102 + gameport_close(gameport); 103 + t = 1000000 * 50; 104 + if (tx) 105 + t /= tx; 106 + return t; 107 + } 108 + 109 + static int old_gameport_measure_speed(struct gameport *gameport) 83 110 { 84 111 #if defined(__i386__) 85 112 ··· 558 521 if (gameport->parent) 559 522 gameport->parent->child = gameport; 560 523 561 - gameport->speed = gameport_measure_speed(gameport); 524 + gameport->speed = use_ktime ? 525 + gameport_measure_speed(gameport) : 526 + old_gameport_measure_speed(gameport); 562 527 563 528 list_add_tail(&gameport->node, &gameport_list); 564 529
+52 -19
drivers/input/joystick/analog.c
··· 36 36 #include <linux/gameport.h> 37 37 #include <linux/jiffies.h> 38 38 #include <linux/timex.h> 39 + #include <linux/timekeeping.h> 39 40 40 41 #define DRIVER_DESC "Analog joystick and gamepad driver" 41 42 42 43 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 43 44 MODULE_DESCRIPTION(DRIVER_DESC); 44 45 MODULE_LICENSE("GPL"); 46 + 47 + static bool use_ktime = true; 48 + module_param(use_ktime, bool, 0400); 49 + MODULE_PARM_DESC(use_ktime, "Use ktime for measuring I/O speed"); 45 50 46 51 /* 47 52 * Option parsing. ··· 176 171 #warning Precise timer not defined for this architecture. 177 172 #endif 178 173 174 + static inline u64 get_time(void) 175 + { 176 + if (use_ktime) { 177 + return ktime_get_ns(); 178 + } else { 179 + unsigned int x; 180 + GET_TIME(x); 181 + return x; 182 + } 183 + } 184 + 185 + static inline unsigned int delta(u64 x, u64 y) 186 + { 187 + if (use_ktime) 188 + return y - x; 189 + else 190 + return DELTA((unsigned int)x, (unsigned int)y); 191 + } 192 + 179 193 /* 180 194 * analog_decode() decodes analog joystick data and reports input events. 181 195 */ ··· 250 226 static int analog_cooked_read(struct analog_port *port) 251 227 { 252 228 struct gameport *gameport = port->gameport; 253 - unsigned int time[4], start, loop, now, loopout, timeout; 229 + u64 time[4], start, loop, now; 230 + unsigned int loopout, timeout; 254 231 unsigned char data[4], this, last; 255 232 unsigned long flags; 256 233 int i, j; ··· 261 236 262 237 local_irq_save(flags); 263 238 gameport_trigger(gameport); 264 - GET_TIME(now); 239 + now = get_time(); 265 240 local_irq_restore(flags); 266 241 267 242 start = now; ··· 274 249 275 250 local_irq_disable(); 276 251 this = gameport_read(gameport) & port->mask; 277 - GET_TIME(now); 252 + now = get_time(); 278 253 local_irq_restore(flags); 279 254 280 - if ((last ^ this) && (DELTA(loop, now) < loopout)) { 255 + if ((last ^ this) && (delta(loop, now) < loopout)) { 281 256 data[i] = last ^ this; 282 257 time[i] = now; 283 258 i++; 284 259 } 285 260 286 - } while (this && (i < 4) && (DELTA(start, now) < timeout)); 261 + } while (this && (i < 4) && (delta(start, now) < timeout)); 287 262 288 263 this <<= 4; 289 264 ··· 291 266 this |= data[i]; 292 267 for (j = 0; j < 4; j++) 293 268 if (data[i] & (1 << j)) 294 - port->axes[j] = (DELTA(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop; 269 + port->axes[j] = (delta(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop; 295 270 } 296 271 297 272 return -(this != port->mask); ··· 390 365 static void analog_calibrate_timer(struct analog_port *port) 391 366 { 392 367 struct gameport *gameport = port->gameport; 393 - unsigned int i, t, tx, t1, t2, t3; 368 + unsigned int i, t, tx; 369 + u64 t1, t2, t3; 394 370 unsigned long flags; 395 371 396 - local_irq_save(flags); 397 - GET_TIME(t1); 372 + if (use_ktime) { 373 + port->speed = 1000000; 374 + } else { 375 + local_irq_save(flags); 376 + t1 = get_time(); 398 377 #ifdef FAKE_TIME 399 - analog_faketime += 830; 378 + analog_faketime += 830; 400 379 #endif 401 - mdelay(1); 402 - GET_TIME(t2); 403 - GET_TIME(t3); 404 - local_irq_restore(flags); 380 + mdelay(1); 381 + t2 = get_time(); 382 + t3 = get_time(); 383 + local_irq_restore(flags); 405 384 406 - port->speed = DELTA(t1, t2) - DELTA(t2, t3); 385 + port->speed = delta(t1, t2) - delta(t2, t3); 386 + } 407 387 408 388 tx = ~0; 409 389 410 390 for (i = 0; i < 50; i++) { 411 391 local_irq_save(flags); 412 - GET_TIME(t1); 413 - for (t = 0; t < 50; t++) { gameport_read(gameport); GET_TIME(t2); } 414 - GET_TIME(t3); 392 + t1 = get_time(); 393 + for (t = 0; t < 50; t++) { 394 + gameport_read(gameport); 395 + t2 = get_time(); 396 + } 397 + t3 = get_time(); 415 398 local_irq_restore(flags); 416 399 udelay(i); 417 - t = DELTA(t1, t2) - DELTA(t2, t3); 400 + t = delta(t1, t2) - delta(t2, t3); 418 401 if (t < tx) tx = t; 419 402 } 420 403
+34
drivers/input/joystick/xpad.c
··· 126 126 { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, 127 127 { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, 128 128 { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, 129 + { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 }, 129 130 { 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 }, 131 + { 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 }, 130 132 { 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 }, 131 133 { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, 132 134 { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, ··· 142 140 { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, 143 141 { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX }, 144 142 { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, 143 + { 0x0738, 0x4718, "Mad Catz Street Fighter IV FightStick SE", 0, XTYPE_XBOX360 }, 144 + { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, 145 145 { 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, 146 146 { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, 147 + { 0x0738, 0x4740, "Mad Catz Beat Pad", 0, XTYPE_XBOX360 }, 147 148 { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, 149 + { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2", 0, XTYPE_XBOX360 }, 148 150 { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 }, 151 + { 0x0738, 0xcb02, "Saitek Cyborg Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, 152 + { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, 153 + { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 }, 149 154 { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, 150 155 { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, 151 156 { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, ··· 165 156 { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, 166 157 { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, 167 158 { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, 159 + { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, 168 160 { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, 169 161 { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, 162 + { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, 163 + { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 }, 164 + { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 }, 170 165 { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, 166 + { 0x0e8f, 0x3008, "Generic xbox control (dealextreme)", 0, XTYPE_XBOX }, 167 + { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick", 0, XTYPE_XBOX360 }, 171 168 { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, 172 169 { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, 173 170 { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, 174 171 { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, 175 172 { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, 176 173 { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, 174 + { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, 177 175 { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, 178 176 { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, 179 177 { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, 180 178 { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, 179 + { 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 }, 180 + { 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 }, 181 + { 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, 182 + { 0x15e4, 0x3f10, "Batarang Xbox 360 controller", 0, XTYPE_XBOX360 }, 183 + { 0x162e, 0xbeef, "Joytech Neo-Se Take2", 0, XTYPE_XBOX360 }, 181 184 { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 }, 182 185 { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 }, 186 + { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 }, 183 187 { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, 184 188 { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, 185 189 { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, 190 + { 0x1bad, 0xf023, "MLG Pro Circuit Controller (Xbox)", 0, XTYPE_XBOX360 }, 186 191 { 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 }, 192 + { 0x1bad, 0xf038, "Street Fighter IV FightStick TE", 0, XTYPE_XBOX360 }, 193 + { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 }, 187 194 { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, 188 195 { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, 196 + { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", 0, XTYPE_XBOX360 }, 189 197 { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, 198 + { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, 199 + { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 }, 200 + { 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA", 0, XTYPE_XBOX360 }, 201 + { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 }, 202 + { 0x24c6, 0x5b02, "Thrustmaster, Inc. GPX Controller", 0, XTYPE_XBOX360 }, 190 203 { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, 191 204 { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } 192 205 }; ··· 305 274 XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ 306 275 XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ 307 276 XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ 277 + XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */ 278 + XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */ 279 + XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */ 308 280 { } 309 281 }; 310 282
+49 -43
drivers/input/keyboard/cros_ec_keyb.c
··· 22 22 */ 23 23 24 24 #include <linux/module.h> 25 + #include <linux/bitops.h> 25 26 #include <linux/i2c.h> 26 27 #include <linux/input.h> 27 28 #include <linux/interrupt.h> ··· 39 38 * @row_shift: log2 or number of rows, rounded up 40 39 * @keymap_data: Matrix keymap data used to convert to keyscan values 41 40 * @ghost_filter: true to enable the matrix key-ghosting filter 41 + * @valid_keys: bitmap of existing keys for each matrix column 42 42 * @old_kb_state: bitmap of keys pressed last scan 43 43 * @dev: Device pointer 44 44 * @idev: Input device ··· 51 49 int row_shift; 52 50 const struct matrix_keymap_data *keymap_data; 53 51 bool ghost_filter; 52 + uint8_t *valid_keys; 54 53 uint8_t *old_kb_state; 55 54 56 55 struct device *dev; ··· 60 57 }; 61 58 62 59 63 - static bool cros_ec_keyb_row_has_ghosting(struct cros_ec_keyb *ckdev, 64 - uint8_t *buf, int row) 65 - { 66 - int pressed_in_row = 0; 67 - int row_has_teeth = 0; 68 - int col, mask; 69 - 70 - mask = 1 << row; 71 - for (col = 0; col < ckdev->cols; col++) { 72 - if (buf[col] & mask) { 73 - pressed_in_row++; 74 - row_has_teeth |= buf[col] & ~mask; 75 - if (pressed_in_row > 1 && row_has_teeth) { 76 - /* ghosting */ 77 - dev_dbg(ckdev->dev, 78 - "ghost found at: r%d c%d, pressed %d, teeth 0x%x\n", 79 - row, col, pressed_in_row, 80 - row_has_teeth); 81 - return true; 82 - } 83 - } 84 - } 85 - 86 - return false; 87 - } 88 - 89 60 /* 90 61 * Returns true when there is at least one combination of pressed keys that 91 62 * results in ghosting. 92 63 */ 93 64 static bool cros_ec_keyb_has_ghosting(struct cros_ec_keyb *ckdev, uint8_t *buf) 94 65 { 95 - int row; 66 + int col1, col2, buf1, buf2; 67 + struct device *dev = ckdev->dev; 68 + uint8_t *valid_keys = ckdev->valid_keys; 96 69 97 70 /* 98 71 * Ghosting happens if for any pressed key X there are other keys ··· 82 103 * 83 104 * In this case only X, Y, and Z are pressed, but g appears to be 84 105 * pressed too (see Wikipedia). 85 - * 86 - * We can detect ghosting in a single pass (*) over the keyboard state 87 - * by maintaining two arrays. pressed_in_row counts how many pressed 88 - * keys we have found in a row. row_has_teeth is true if any of the 89 - * pressed keys for this row has other pressed keys in its column. If 90 - * at any point of the scan we find that a row has multiple pressed 91 - * keys, and at least one of them is at the intersection with a column 92 - * with multiple pressed keys, we're sure there is ghosting. 93 - * Conversely, if there is ghosting, we will detect such situation for 94 - * at least one key during the pass. 95 - * 96 - * (*) This looks linear in the number of keys, but it's not. We can 97 - * cheat because the number of rows is small. 98 106 */ 99 - for (row = 0; row < ckdev->rows; row++) 100 - if (cros_ec_keyb_row_has_ghosting(ckdev, buf, row)) 101 - return true; 107 + for (col1 = 0; col1 < ckdev->cols; col1++) { 108 + buf1 = buf[col1] & valid_keys[col1]; 109 + for (col2 = col1 + 1; col2 < ckdev->cols; col2++) { 110 + buf2 = buf[col2] & valid_keys[col2]; 111 + if (hweight8(buf1 & buf2) > 1) { 112 + dev_dbg(dev, "ghost found at: B[%02d]:0x%02x & B[%02d]:0x%02x", 113 + col1, buf1, col2, buf2); 114 + return true; 115 + } 116 + } 117 + } 102 118 103 119 return false; 104 120 } 121 + 105 122 106 123 /* 107 124 * Compares the new keyboard state to the old one and produces key ··· 197 222 free_irq(ec->irq, ckdev); 198 223 } 199 224 225 + /* 226 + * Walks keycodes flipping bit in buffer COLUMNS deep where bit is ROW. Used by 227 + * ghosting logic to ignore NULL or virtual keys. 228 + */ 229 + static void cros_ec_keyb_compute_valid_keys(struct cros_ec_keyb *ckdev) 230 + { 231 + int row, col; 232 + int row_shift = ckdev->row_shift; 233 + unsigned short *keymap = ckdev->idev->keycode; 234 + unsigned short code; 235 + 236 + BUG_ON(ckdev->idev->keycodesize != sizeof(*keymap)); 237 + 238 + for (col = 0; col < ckdev->cols; col++) { 239 + for (row = 0; row < ckdev->rows; row++) { 240 + code = keymap[MATRIX_SCAN_CODE(row, col, row_shift)]; 241 + if (code && (code != KEY_BATTERY)) 242 + ckdev->valid_keys[col] |= 1 << row; 243 + } 244 + dev_dbg(ckdev->dev, "valid_keys[%02d] = 0x%02x\n", 245 + col, ckdev->valid_keys[col]); 246 + } 247 + } 248 + 200 249 static int cros_ec_keyb_probe(struct platform_device *pdev) 201 250 { 202 251 struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); ··· 241 242 &ckdev->cols); 242 243 if (err) 243 244 return err; 245 + 246 + ckdev->valid_keys = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL); 247 + if (!ckdev->valid_keys) 248 + return -ENOMEM; 249 + 244 250 ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL); 245 251 if (!ckdev->old_kb_state) 246 252 return -ENOMEM; ··· 289 285 input_set_capability(idev, EV_MSC, MSC_SCAN); 290 286 input_set_drvdata(idev, ckdev); 291 287 ckdev->idev = idev; 288 + cros_ec_keyb_compute_valid_keys(ckdev); 289 + 292 290 err = input_register_device(ckdev->idev); 293 291 if (err) { 294 292 dev_err(dev, "cannot register input device\n");
+43
drivers/input/misc/Kconfig
··· 144 144 tristate "M68k Beeper support" 145 145 depends on M68K 146 146 147 + config INPUT_MAX77693_HAPTIC 148 + tristate "MAXIM MAX77693 haptic controller support" 149 + depends on MFD_MAX77693 && PWM 150 + select INPUT_FF_MEMLESS 151 + help 152 + This option enables support for the haptic controller on 153 + MAXIM MAX77693 chip. 154 + 155 + To compile this driver as module, choose M here: the 156 + module will be called max77693-haptic. 157 + 147 158 config INPUT_MAX8925_ONKEY 148 159 tristate "MAX8925 ONKEY support" 149 160 depends on MFD_MAX8925 ··· 462 451 Say Y here if you want to support the built-in real time clock 463 452 of the HP SDC controller. 464 453 454 + config INPUT_PALMAS_PWRBUTTON 455 + tristate "Palmas Power button Driver" 456 + depends on MFD_PALMAS 457 + help 458 + Say Y here if you want to enable power key reporting via the 459 + Palmas family of PMICs. 460 + 461 + To compile this driver as a module, choose M here. The module will 462 + be called palmas_pwrbutton. 463 + 465 464 config INPUT_PCF50633_PMU 466 465 tristate "PCF50633 PMU events" 467 466 depends on MFD_PCF50633 ··· 696 675 697 676 To compile this driver as a module, choose M here: the 698 677 module will be called soc_button_array. 678 + 679 + config INPUT_DRV260X_HAPTICS 680 + tristate "TI DRV260X haptics support" 681 + depends on INPUT && I2C && GPIOLIB 682 + select INPUT_FF_MEMLESS 683 + select REGMAP_I2C 684 + help 685 + Say Y to enable support for the TI DRV260X haptics driver. 686 + 687 + To compile this driver as a module, choose M here: the 688 + module will be called drv260x-haptics. 689 + 690 + config INPUT_DRV2667_HAPTICS 691 + tristate "TI DRV2667 haptics support" 692 + depends on INPUT && I2C 693 + select INPUT_FF_MEMLESS 694 + select REGMAP_I2C 695 + help 696 + Say Y to enable support for the TI DRV2667 haptics driver. 697 + 698 + To compile this driver as a module, choose M here: the 699 + module will be called drv260x-haptics. 699 700 700 701 endif
+4
drivers/input/misc/Makefile
··· 26 26 obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o 27 27 obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o 28 28 obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o 29 + obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o 30 + obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o 29 31 obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o 30 32 obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o 31 33 obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o ··· 37 35 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o 38 36 obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o 39 37 obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o 38 + obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o 40 39 obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o 41 40 obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o 42 41 obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o 43 42 obj-$(CONFIG_INPUT_MMA8450) += mma8450.o 44 43 obj-$(CONFIG_INPUT_MPU3050) += mpu3050.o 44 + obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o 45 45 obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o 46 46 obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o 47 47 obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
+741
drivers/input/misc/drv260x.c
··· 1 + /* 2 + * DRV260X haptics driver family 3 + * 4 + * Author: Dan Murphy <dmurphy@ti.com> 5 + * 6 + * Copyright: (C) 2014 Texas Instruments, Inc. 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 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + */ 17 + 18 + #include <linux/i2c.h> 19 + #include <linux/input.h> 20 + #include <linux/module.h> 21 + #include <linux/of_gpio.h> 22 + #include <linux/platform_device.h> 23 + #include <linux/regmap.h> 24 + #include <linux/slab.h> 25 + #include <linux/delay.h> 26 + #include <linux/gpio/consumer.h> 27 + #include <linux/regulator/consumer.h> 28 + 29 + #include <dt-bindings/input/ti-drv260x.h> 30 + #include <linux/platform_data/drv260x-pdata.h> 31 + 32 + #define DRV260X_STATUS 0x0 33 + #define DRV260X_MODE 0x1 34 + #define DRV260X_RT_PB_IN 0x2 35 + #define DRV260X_LIB_SEL 0x3 36 + #define DRV260X_WV_SEQ_1 0x4 37 + #define DRV260X_WV_SEQ_2 0x5 38 + #define DRV260X_WV_SEQ_3 0x6 39 + #define DRV260X_WV_SEQ_4 0x7 40 + #define DRV260X_WV_SEQ_5 0x8 41 + #define DRV260X_WV_SEQ_6 0x9 42 + #define DRV260X_WV_SEQ_7 0xa 43 + #define DRV260X_WV_SEQ_8 0xb 44 + #define DRV260X_GO 0xc 45 + #define DRV260X_OVERDRIVE_OFF 0xd 46 + #define DRV260X_SUSTAIN_P_OFF 0xe 47 + #define DRV260X_SUSTAIN_N_OFF 0xf 48 + #define DRV260X_BRAKE_OFF 0x10 49 + #define DRV260X_A_TO_V_CTRL 0x11 50 + #define DRV260X_A_TO_V_MIN_INPUT 0x12 51 + #define DRV260X_A_TO_V_MAX_INPUT 0x13 52 + #define DRV260X_A_TO_V_MIN_OUT 0x14 53 + #define DRV260X_A_TO_V_MAX_OUT 0x15 54 + #define DRV260X_RATED_VOLT 0x16 55 + #define DRV260X_OD_CLAMP_VOLT 0x17 56 + #define DRV260X_CAL_COMP 0x18 57 + #define DRV260X_CAL_BACK_EMF 0x19 58 + #define DRV260X_FEEDBACK_CTRL 0x1a 59 + #define DRV260X_CTRL1 0x1b 60 + #define DRV260X_CTRL2 0x1c 61 + #define DRV260X_CTRL3 0x1d 62 + #define DRV260X_CTRL4 0x1e 63 + #define DRV260X_CTRL5 0x1f 64 + #define DRV260X_LRA_LOOP_PERIOD 0x20 65 + #define DRV260X_VBAT_MON 0x21 66 + #define DRV260X_LRA_RES_PERIOD 0x22 67 + #define DRV260X_MAX_REG 0x23 68 + 69 + #define DRV260X_GO_BIT 0x01 70 + 71 + /* Library Selection */ 72 + #define DRV260X_LIB_SEL_MASK 0x07 73 + #define DRV260X_LIB_SEL_RAM 0x0 74 + #define DRV260X_LIB_SEL_OD 0x1 75 + #define DRV260X_LIB_SEL_40_60 0x2 76 + #define DRV260X_LIB_SEL_60_80 0x3 77 + #define DRV260X_LIB_SEL_100_140 0x4 78 + #define DRV260X_LIB_SEL_140_PLUS 0x5 79 + 80 + #define DRV260X_LIB_SEL_HIZ_MASK 0x10 81 + #define DRV260X_LIB_SEL_HIZ_EN 0x01 82 + #define DRV260X_LIB_SEL_HIZ_DIS 0 83 + 84 + /* Mode register */ 85 + #define DRV260X_STANDBY (1 << 6) 86 + #define DRV260X_STANDBY_MASK 0x40 87 + #define DRV260X_INTERNAL_TRIGGER 0x00 88 + #define DRV260X_EXT_TRIGGER_EDGE 0x01 89 + #define DRV260X_EXT_TRIGGER_LEVEL 0x02 90 + #define DRV260X_PWM_ANALOG_IN 0x03 91 + #define DRV260X_AUDIOHAPTIC 0x04 92 + #define DRV260X_RT_PLAYBACK 0x05 93 + #define DRV260X_DIAGNOSTICS 0x06 94 + #define DRV260X_AUTO_CAL 0x07 95 + 96 + /* Audio to Haptics Control */ 97 + #define DRV260X_AUDIO_HAPTICS_PEAK_10MS (0 << 2) 98 + #define DRV260X_AUDIO_HAPTICS_PEAK_20MS (1 << 2) 99 + #define DRV260X_AUDIO_HAPTICS_PEAK_30MS (2 << 2) 100 + #define DRV260X_AUDIO_HAPTICS_PEAK_40MS (3 << 2) 101 + 102 + #define DRV260X_AUDIO_HAPTICS_FILTER_100HZ 0x00 103 + #define DRV260X_AUDIO_HAPTICS_FILTER_125HZ 0x01 104 + #define DRV260X_AUDIO_HAPTICS_FILTER_150HZ 0x02 105 + #define DRV260X_AUDIO_HAPTICS_FILTER_200HZ 0x03 106 + 107 + /* Min/Max Input/Output Voltages */ 108 + #define DRV260X_AUDIO_HAPTICS_MIN_IN_VOLT 0x19 109 + #define DRV260X_AUDIO_HAPTICS_MAX_IN_VOLT 0x64 110 + #define DRV260X_AUDIO_HAPTICS_MIN_OUT_VOLT 0x19 111 + #define DRV260X_AUDIO_HAPTICS_MAX_OUT_VOLT 0xFF 112 + 113 + /* Feedback register */ 114 + #define DRV260X_FB_REG_ERM_MODE 0x7f 115 + #define DRV260X_FB_REG_LRA_MODE (1 << 7) 116 + 117 + #define DRV260X_BRAKE_FACTOR_MASK 0x1f 118 + #define DRV260X_BRAKE_FACTOR_2X (1 << 0) 119 + #define DRV260X_BRAKE_FACTOR_3X (2 << 4) 120 + #define DRV260X_BRAKE_FACTOR_4X (3 << 4) 121 + #define DRV260X_BRAKE_FACTOR_6X (4 << 4) 122 + #define DRV260X_BRAKE_FACTOR_8X (5 << 4) 123 + #define DRV260X_BRAKE_FACTOR_16 (6 << 4) 124 + #define DRV260X_BRAKE_FACTOR_DIS (7 << 4) 125 + 126 + #define DRV260X_LOOP_GAIN_LOW 0xf3 127 + #define DRV260X_LOOP_GAIN_MED (1 << 2) 128 + #define DRV260X_LOOP_GAIN_HIGH (2 << 2) 129 + #define DRV260X_LOOP_GAIN_VERY_HIGH (3 << 2) 130 + 131 + #define DRV260X_BEMF_GAIN_0 0xfc 132 + #define DRV260X_BEMF_GAIN_1 (1 << 0) 133 + #define DRV260X_BEMF_GAIN_2 (2 << 0) 134 + #define DRV260X_BEMF_GAIN_3 (3 << 0) 135 + 136 + /* Control 1 register */ 137 + #define DRV260X_AC_CPLE_EN (1 << 5) 138 + #define DRV260X_STARTUP_BOOST (1 << 7) 139 + 140 + /* Control 2 register */ 141 + 142 + #define DRV260X_IDISS_TIME_45 0 143 + #define DRV260X_IDISS_TIME_75 (1 << 0) 144 + #define DRV260X_IDISS_TIME_150 (1 << 1) 145 + #define DRV260X_IDISS_TIME_225 0x03 146 + 147 + #define DRV260X_BLANK_TIME_45 (0 << 2) 148 + #define DRV260X_BLANK_TIME_75 (1 << 2) 149 + #define DRV260X_BLANK_TIME_150 (2 << 2) 150 + #define DRV260X_BLANK_TIME_225 (3 << 2) 151 + 152 + #define DRV260X_SAMP_TIME_150 (0 << 4) 153 + #define DRV260X_SAMP_TIME_200 (1 << 4) 154 + #define DRV260X_SAMP_TIME_250 (2 << 4) 155 + #define DRV260X_SAMP_TIME_300 (3 << 4) 156 + 157 + #define DRV260X_BRAKE_STABILIZER (1 << 6) 158 + #define DRV260X_UNIDIR_IN (0 << 7) 159 + #define DRV260X_BIDIR_IN (1 << 7) 160 + 161 + /* Control 3 Register */ 162 + #define DRV260X_LRA_OPEN_LOOP (1 << 0) 163 + #define DRV260X_ANANLOG_IN (1 << 1) 164 + #define DRV260X_LRA_DRV_MODE (1 << 2) 165 + #define DRV260X_RTP_UNSIGNED_DATA (1 << 3) 166 + #define DRV260X_SUPPLY_COMP_DIS (1 << 4) 167 + #define DRV260X_ERM_OPEN_LOOP (1 << 5) 168 + #define DRV260X_NG_THRESH_0 (0 << 6) 169 + #define DRV260X_NG_THRESH_2 (1 << 6) 170 + #define DRV260X_NG_THRESH_4 (2 << 6) 171 + #define DRV260X_NG_THRESH_8 (3 << 6) 172 + 173 + /* Control 4 Register */ 174 + #define DRV260X_AUTOCAL_TIME_150MS (0 << 4) 175 + #define DRV260X_AUTOCAL_TIME_250MS (1 << 4) 176 + #define DRV260X_AUTOCAL_TIME_500MS (2 << 4) 177 + #define DRV260X_AUTOCAL_TIME_1000MS (3 << 4) 178 + 179 + /** 180 + * struct drv260x_data - 181 + * @input_dev - Pointer to the input device 182 + * @client - Pointer to the I2C client 183 + * @regmap - Register map of the device 184 + * @work - Work item used to off load the enable/disable of the vibration 185 + * @enable_gpio - Pointer to the gpio used for enable/disabling 186 + * @regulator - Pointer to the regulator for the IC 187 + * @magnitude - Magnitude of the vibration event 188 + * @mode - The operating mode of the IC (LRA_NO_CAL, ERM or LRA) 189 + * @library - The vibration library to be used 190 + * @rated_voltage - The rated_voltage of the actuator 191 + * @overdriver_voltage - The over drive voltage of the actuator 192 + **/ 193 + struct drv260x_data { 194 + struct input_dev *input_dev; 195 + struct i2c_client *client; 196 + struct regmap *regmap; 197 + struct work_struct work; 198 + struct gpio_desc *enable_gpio; 199 + struct regulator *regulator; 200 + u32 magnitude; 201 + u32 mode; 202 + u32 library; 203 + int rated_voltage; 204 + int overdrive_voltage; 205 + }; 206 + 207 + static struct reg_default drv260x_reg_defs[] = { 208 + { DRV260X_STATUS, 0xe0 }, 209 + { DRV260X_MODE, 0x40 }, 210 + { DRV260X_RT_PB_IN, 0x00 }, 211 + { DRV260X_LIB_SEL, 0x00 }, 212 + { DRV260X_WV_SEQ_1, 0x01 }, 213 + { DRV260X_WV_SEQ_2, 0x00 }, 214 + { DRV260X_WV_SEQ_3, 0x00 }, 215 + { DRV260X_WV_SEQ_4, 0x00 }, 216 + { DRV260X_WV_SEQ_5, 0x00 }, 217 + { DRV260X_WV_SEQ_6, 0x00 }, 218 + { DRV260X_WV_SEQ_7, 0x00 }, 219 + { DRV260X_WV_SEQ_8, 0x00 }, 220 + { DRV260X_GO, 0x00 }, 221 + { DRV260X_OVERDRIVE_OFF, 0x00 }, 222 + { DRV260X_SUSTAIN_P_OFF, 0x00 }, 223 + { DRV260X_SUSTAIN_N_OFF, 0x00 }, 224 + { DRV260X_BRAKE_OFF, 0x00 }, 225 + { DRV260X_A_TO_V_CTRL, 0x05 }, 226 + { DRV260X_A_TO_V_MIN_INPUT, 0x19 }, 227 + { DRV260X_A_TO_V_MAX_INPUT, 0xff }, 228 + { DRV260X_A_TO_V_MIN_OUT, 0x19 }, 229 + { DRV260X_A_TO_V_MAX_OUT, 0xff }, 230 + { DRV260X_RATED_VOLT, 0x3e }, 231 + { DRV260X_OD_CLAMP_VOLT, 0x8c }, 232 + { DRV260X_CAL_COMP, 0x0c }, 233 + { DRV260X_CAL_BACK_EMF, 0x6c }, 234 + { DRV260X_FEEDBACK_CTRL, 0x36 }, 235 + { DRV260X_CTRL1, 0x93 }, 236 + { DRV260X_CTRL2, 0xfa }, 237 + { DRV260X_CTRL3, 0xa0 }, 238 + { DRV260X_CTRL4, 0x20 }, 239 + { DRV260X_CTRL5, 0x80 }, 240 + { DRV260X_LRA_LOOP_PERIOD, 0x33 }, 241 + { DRV260X_VBAT_MON, 0x00 }, 242 + { DRV260X_LRA_RES_PERIOD, 0x00 }, 243 + }; 244 + 245 + #define DRV260X_DEF_RATED_VOLT 0x90 246 + #define DRV260X_DEF_OD_CLAMP_VOLT 0x90 247 + 248 + /** 249 + * Rated and Overdriver Voltages: 250 + * Calculated using the formula r = v * 255 / 5.6 251 + * where r is what will be written to the register 252 + * and v is the rated or overdriver voltage of the actuator 253 + **/ 254 + static int drv260x_calculate_voltage(unsigned int voltage) 255 + { 256 + return (voltage * 255 / 5600); 257 + } 258 + 259 + static void drv260x_worker(struct work_struct *work) 260 + { 261 + struct drv260x_data *haptics = container_of(work, struct drv260x_data, work); 262 + int error; 263 + 264 + gpiod_set_value(haptics->enable_gpio, 1); 265 + /* Data sheet says to wait 250us before trying to communicate */ 266 + udelay(250); 267 + 268 + error = regmap_write(haptics->regmap, 269 + DRV260X_MODE, DRV260X_RT_PLAYBACK); 270 + if (error) { 271 + dev_err(&haptics->client->dev, 272 + "Failed to write set mode: %d\n", error); 273 + } else { 274 + error = regmap_write(haptics->regmap, 275 + DRV260X_RT_PB_IN, haptics->magnitude); 276 + if (error) 277 + dev_err(&haptics->client->dev, 278 + "Failed to set magnitude: %d\n", error); 279 + } 280 + } 281 + 282 + static int drv260x_haptics_play(struct input_dev *input, void *data, 283 + struct ff_effect *effect) 284 + { 285 + struct drv260x_data *haptics = input_get_drvdata(input); 286 + 287 + haptics->mode = DRV260X_LRA_NO_CAL_MODE; 288 + 289 + if (effect->u.rumble.strong_magnitude > 0) 290 + haptics->magnitude = effect->u.rumble.strong_magnitude; 291 + else if (effect->u.rumble.weak_magnitude > 0) 292 + haptics->magnitude = effect->u.rumble.weak_magnitude; 293 + else 294 + haptics->magnitude = 0; 295 + 296 + schedule_work(&haptics->work); 297 + 298 + return 0; 299 + } 300 + 301 + static void drv260x_close(struct input_dev *input) 302 + { 303 + struct drv260x_data *haptics = input_get_drvdata(input); 304 + int error; 305 + 306 + cancel_work_sync(&haptics->work); 307 + 308 + error = regmap_write(haptics->regmap, DRV260X_MODE, DRV260X_STANDBY); 309 + if (error) 310 + dev_err(&haptics->client->dev, 311 + "Failed to enter standby mode: %d\n", error); 312 + 313 + gpiod_set_value(haptics->enable_gpio, 0); 314 + } 315 + 316 + static const struct reg_default drv260x_lra_cal_regs[] = { 317 + { DRV260X_MODE, DRV260X_AUTO_CAL }, 318 + { DRV260X_CTRL3, DRV260X_NG_THRESH_2 }, 319 + { DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE | 320 + DRV260X_BRAKE_FACTOR_4X | DRV260X_LOOP_GAIN_HIGH }, 321 + }; 322 + 323 + static const struct reg_default drv260x_lra_init_regs[] = { 324 + { DRV260X_MODE, DRV260X_RT_PLAYBACK }, 325 + { DRV260X_A_TO_V_CTRL, DRV260X_AUDIO_HAPTICS_PEAK_20MS | 326 + DRV260X_AUDIO_HAPTICS_FILTER_125HZ }, 327 + { DRV260X_A_TO_V_MIN_INPUT, DRV260X_AUDIO_HAPTICS_MIN_IN_VOLT }, 328 + { DRV260X_A_TO_V_MAX_INPUT, DRV260X_AUDIO_HAPTICS_MAX_IN_VOLT }, 329 + { DRV260X_A_TO_V_MIN_OUT, DRV260X_AUDIO_HAPTICS_MIN_OUT_VOLT }, 330 + { DRV260X_A_TO_V_MAX_OUT, DRV260X_AUDIO_HAPTICS_MAX_OUT_VOLT }, 331 + { DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE | 332 + DRV260X_BRAKE_FACTOR_2X | DRV260X_LOOP_GAIN_MED | 333 + DRV260X_BEMF_GAIN_3 }, 334 + { DRV260X_CTRL1, DRV260X_STARTUP_BOOST }, 335 + { DRV260X_CTRL2, DRV260X_SAMP_TIME_250 }, 336 + { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_ANANLOG_IN }, 337 + { DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS }, 338 + }; 339 + 340 + static const struct reg_default drv260x_erm_cal_regs[] = { 341 + { DRV260X_MODE, DRV260X_AUTO_CAL }, 342 + { DRV260X_A_TO_V_MIN_INPUT, DRV260X_AUDIO_HAPTICS_MIN_IN_VOLT }, 343 + { DRV260X_A_TO_V_MAX_INPUT, DRV260X_AUDIO_HAPTICS_MAX_IN_VOLT }, 344 + { DRV260X_A_TO_V_MIN_OUT, DRV260X_AUDIO_HAPTICS_MIN_OUT_VOLT }, 345 + { DRV260X_A_TO_V_MAX_OUT, DRV260X_AUDIO_HAPTICS_MAX_OUT_VOLT }, 346 + { DRV260X_FEEDBACK_CTRL, DRV260X_BRAKE_FACTOR_3X | 347 + DRV260X_LOOP_GAIN_MED | DRV260X_BEMF_GAIN_2 }, 348 + { DRV260X_CTRL1, DRV260X_STARTUP_BOOST }, 349 + { DRV260X_CTRL2, DRV260X_SAMP_TIME_250 | DRV260X_BLANK_TIME_75 | 350 + DRV260X_IDISS_TIME_75 }, 351 + { DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_ERM_OPEN_LOOP }, 352 + { DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS }, 353 + }; 354 + 355 + static int drv260x_init(struct drv260x_data *haptics) 356 + { 357 + int error; 358 + unsigned int cal_buf; 359 + 360 + error = regmap_write(haptics->regmap, 361 + DRV260X_RATED_VOLT, haptics->rated_voltage); 362 + if (error) { 363 + dev_err(&haptics->client->dev, 364 + "Failed to write DRV260X_RATED_VOLT register: %d\n", 365 + error); 366 + return error; 367 + } 368 + 369 + error = regmap_write(haptics->regmap, 370 + DRV260X_OD_CLAMP_VOLT, haptics->overdrive_voltage); 371 + if (error) { 372 + dev_err(&haptics->client->dev, 373 + "Failed to write DRV260X_OD_CLAMP_VOLT register: %d\n", 374 + error); 375 + return error; 376 + } 377 + 378 + switch (haptics->mode) { 379 + case DRV260X_LRA_MODE: 380 + error = regmap_register_patch(haptics->regmap, 381 + drv260x_lra_cal_regs, 382 + ARRAY_SIZE(drv260x_lra_cal_regs)); 383 + if (error) { 384 + dev_err(&haptics->client->dev, 385 + "Failed to write LRA calibration registers: %d\n", 386 + error); 387 + return error; 388 + } 389 + 390 + break; 391 + 392 + case DRV260X_ERM_MODE: 393 + error = regmap_register_patch(haptics->regmap, 394 + drv260x_erm_cal_regs, 395 + ARRAY_SIZE(drv260x_erm_cal_regs)); 396 + if (error) { 397 + dev_err(&haptics->client->dev, 398 + "Failed to write ERM calibration registers: %d\n", 399 + error); 400 + return error; 401 + } 402 + 403 + error = regmap_update_bits(haptics->regmap, DRV260X_LIB_SEL, 404 + DRV260X_LIB_SEL_MASK, 405 + haptics->library); 406 + if (error) { 407 + dev_err(&haptics->client->dev, 408 + "Failed to write DRV260X_LIB_SEL register: %d\n", 409 + error); 410 + return error; 411 + } 412 + 413 + break; 414 + 415 + default: 416 + error = regmap_register_patch(haptics->regmap, 417 + drv260x_lra_init_regs, 418 + ARRAY_SIZE(drv260x_lra_init_regs)); 419 + if (error) { 420 + dev_err(&haptics->client->dev, 421 + "Failed to write LRA init registers: %d\n", 422 + error); 423 + return error; 424 + } 425 + 426 + error = regmap_update_bits(haptics->regmap, DRV260X_LIB_SEL, 427 + DRV260X_LIB_SEL_MASK, 428 + haptics->library); 429 + if (error) { 430 + dev_err(&haptics->client->dev, 431 + "Failed to write DRV260X_LIB_SEL register: %d\n", 432 + error); 433 + return error; 434 + } 435 + 436 + /* No need to set GO bit here */ 437 + return 0; 438 + } 439 + 440 + error = regmap_write(haptics->regmap, DRV260X_GO, DRV260X_GO_BIT); 441 + if (error) { 442 + dev_err(&haptics->client->dev, 443 + "Failed to write GO register: %d\n", 444 + error); 445 + return error; 446 + } 447 + 448 + do { 449 + error = regmap_read(haptics->regmap, DRV260X_GO, &cal_buf); 450 + if (error) { 451 + dev_err(&haptics->client->dev, 452 + "Failed to read GO register: %d\n", 453 + error); 454 + return error; 455 + } 456 + } while (cal_buf == DRV260X_GO_BIT); 457 + 458 + return 0; 459 + } 460 + 461 + static const struct regmap_config drv260x_regmap_config = { 462 + .reg_bits = 8, 463 + .val_bits = 8, 464 + 465 + .max_register = DRV260X_MAX_REG, 466 + .reg_defaults = drv260x_reg_defs, 467 + .num_reg_defaults = ARRAY_SIZE(drv260x_reg_defs), 468 + .cache_type = REGCACHE_NONE, 469 + }; 470 + 471 + #ifdef CONFIG_OF 472 + static int drv260x_parse_dt(struct device *dev, 473 + struct drv260x_data *haptics) 474 + { 475 + struct device_node *np = dev->of_node; 476 + unsigned int voltage; 477 + int error; 478 + 479 + error = of_property_read_u32(np, "mode", &haptics->mode); 480 + if (error) { 481 + dev_err(dev, "%s: No entry for mode\n", __func__); 482 + return error; 483 + } 484 + 485 + error = of_property_read_u32(np, "library-sel", &haptics->library); 486 + if (error) { 487 + dev_err(dev, "%s: No entry for library selection\n", 488 + __func__); 489 + return error; 490 + } 491 + 492 + error = of_property_read_u32(np, "vib-rated-mv", &voltage); 493 + if (!error) 494 + haptics->rated_voltage = drv260x_calculate_voltage(voltage); 495 + 496 + 497 + error = of_property_read_u32(np, "vib-overdrive-mv", &voltage); 498 + if (!error) 499 + haptics->overdrive_voltage = drv260x_calculate_voltage(voltage); 500 + 501 + return 0; 502 + } 503 + #else 504 + static inline int drv260x_parse_dt(struct device *dev, 505 + struct drv260x_data *haptics) 506 + { 507 + dev_err(dev, "no platform data defined\n"); 508 + 509 + return -EINVAL; 510 + } 511 + #endif 512 + 513 + static int drv260x_probe(struct i2c_client *client, 514 + const struct i2c_device_id *id) 515 + { 516 + const struct drv260x_platform_data *pdata = dev_get_platdata(&client->dev); 517 + struct drv260x_data *haptics; 518 + int error; 519 + 520 + haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL); 521 + if (!haptics) 522 + return -ENOMEM; 523 + 524 + haptics->rated_voltage = DRV260X_DEF_OD_CLAMP_VOLT; 525 + haptics->rated_voltage = DRV260X_DEF_RATED_VOLT; 526 + 527 + if (pdata) { 528 + haptics->mode = pdata->mode; 529 + haptics->library = pdata->library_selection; 530 + if (pdata->vib_overdrive_voltage) 531 + haptics->overdrive_voltage = drv260x_calculate_voltage(pdata->vib_overdrive_voltage); 532 + if (pdata->vib_rated_voltage) 533 + haptics->rated_voltage = drv260x_calculate_voltage(pdata->vib_rated_voltage); 534 + } else if (client->dev.of_node) { 535 + error = drv260x_parse_dt(&client->dev, haptics); 536 + if (error) 537 + return error; 538 + } else { 539 + dev_err(&client->dev, "Platform data not set\n"); 540 + return -ENODEV; 541 + } 542 + 543 + 544 + if (haptics->mode < DRV260X_LRA_MODE || 545 + haptics->mode > DRV260X_ERM_MODE) { 546 + dev_err(&client->dev, 547 + "Vibrator mode is invalid: %i\n", 548 + haptics->mode); 549 + return -EINVAL; 550 + } 551 + 552 + if (haptics->library < DRV260X_LIB_EMPTY || 553 + haptics->library > DRV260X_ERM_LIB_F) { 554 + dev_err(&client->dev, 555 + "Library value is invalid: %i\n", haptics->library); 556 + return -EINVAL; 557 + } 558 + 559 + if (haptics->mode == DRV260X_LRA_MODE && 560 + haptics->library != DRV260X_LIB_EMPTY && 561 + haptics->library != DRV260X_LIB_LRA) { 562 + dev_err(&client->dev, 563 + "LRA Mode with ERM Library mismatch\n"); 564 + return -EINVAL; 565 + } 566 + 567 + if (haptics->mode == DRV260X_ERM_MODE && 568 + (haptics->library == DRV260X_LIB_EMPTY || 569 + haptics->library == DRV260X_LIB_LRA)) { 570 + dev_err(&client->dev, 571 + "ERM Mode with LRA Library mismatch\n"); 572 + return -EINVAL; 573 + } 574 + 575 + haptics->regulator = devm_regulator_get(&client->dev, "vbat"); 576 + if (IS_ERR(haptics->regulator)) { 577 + error = PTR_ERR(haptics->regulator); 578 + dev_err(&client->dev, 579 + "unable to get regulator, error: %d\n", error); 580 + return error; 581 + } 582 + 583 + haptics->enable_gpio = devm_gpiod_get(&client->dev, "enable"); 584 + if (IS_ERR(haptics->enable_gpio)) { 585 + error = PTR_ERR(haptics->enable_gpio); 586 + if (error != -ENOENT && error != -ENOSYS) 587 + return error; 588 + haptics->enable_gpio = NULL; 589 + } else { 590 + gpiod_direction_output(haptics->enable_gpio, 1); 591 + } 592 + 593 + haptics->input_dev = devm_input_allocate_device(&client->dev); 594 + if (!haptics->input_dev) { 595 + dev_err(&client->dev, "Failed to allocate input device\n"); 596 + return -ENOMEM; 597 + } 598 + 599 + haptics->input_dev->name = "drv260x:haptics"; 600 + haptics->input_dev->dev.parent = client->dev.parent; 601 + haptics->input_dev->close = drv260x_close; 602 + input_set_drvdata(haptics->input_dev, haptics); 603 + input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE); 604 + 605 + error = input_ff_create_memless(haptics->input_dev, NULL, 606 + drv260x_haptics_play); 607 + if (error) { 608 + dev_err(&client->dev, "input_ff_create() failed: %d\n", 609 + error); 610 + return error; 611 + } 612 + 613 + INIT_WORK(&haptics->work, drv260x_worker); 614 + 615 + haptics->client = client; 616 + i2c_set_clientdata(client, haptics); 617 + 618 + haptics->regmap = devm_regmap_init_i2c(client, &drv260x_regmap_config); 619 + if (IS_ERR(haptics->regmap)) { 620 + error = PTR_ERR(haptics->regmap); 621 + dev_err(&client->dev, "Failed to allocate register map: %d\n", 622 + error); 623 + return error; 624 + } 625 + 626 + error = drv260x_init(haptics); 627 + if (error) { 628 + dev_err(&client->dev, "Device init failed: %d\n", error); 629 + return error; 630 + } 631 + 632 + error = input_register_device(haptics->input_dev); 633 + if (error) { 634 + dev_err(&client->dev, "couldn't register input device: %d\n", 635 + error); 636 + return error; 637 + } 638 + 639 + return 0; 640 + } 641 + 642 + #ifdef CONFIG_PM_SLEEP 643 + static int drv260x_suspend(struct device *dev) 644 + { 645 + struct drv260x_data *haptics = dev_get_drvdata(dev); 646 + int ret = 0; 647 + 648 + mutex_lock(&haptics->input_dev->mutex); 649 + 650 + if (haptics->input_dev->users) { 651 + ret = regmap_update_bits(haptics->regmap, 652 + DRV260X_MODE, 653 + DRV260X_STANDBY_MASK, 654 + DRV260X_STANDBY); 655 + if (ret) { 656 + dev_err(dev, "Failed to set standby mode\n"); 657 + goto out; 658 + } 659 + 660 + gpiod_set_value(haptics->enable_gpio, 0); 661 + 662 + ret = regulator_disable(haptics->regulator); 663 + if (ret) { 664 + dev_err(dev, "Failed to disable regulator\n"); 665 + regmap_update_bits(haptics->regmap, 666 + DRV260X_MODE, 667 + DRV260X_STANDBY_MASK, 0); 668 + } 669 + } 670 + out: 671 + mutex_unlock(&haptics->input_dev->mutex); 672 + return ret; 673 + } 674 + 675 + static int drv260x_resume(struct device *dev) 676 + { 677 + struct drv260x_data *haptics = dev_get_drvdata(dev); 678 + int ret = 0; 679 + 680 + mutex_lock(&haptics->input_dev->mutex); 681 + 682 + if (haptics->input_dev->users) { 683 + ret = regulator_enable(haptics->regulator); 684 + if (ret) { 685 + dev_err(dev, "Failed to enable regulator\n"); 686 + goto out; 687 + } 688 + 689 + ret = regmap_update_bits(haptics->regmap, 690 + DRV260X_MODE, 691 + DRV260X_STANDBY_MASK, 0); 692 + if (ret) { 693 + dev_err(dev, "Failed to unset standby mode\n"); 694 + regulator_disable(haptics->regulator); 695 + goto out; 696 + } 697 + 698 + gpiod_set_value(haptics->enable_gpio, 1); 699 + } 700 + 701 + out: 702 + mutex_unlock(&haptics->input_dev->mutex); 703 + return ret; 704 + } 705 + #endif 706 + 707 + static SIMPLE_DEV_PM_OPS(drv260x_pm_ops, drv260x_suspend, drv260x_resume); 708 + 709 + static const struct i2c_device_id drv260x_id[] = { 710 + { "drv2605l", 0 }, 711 + { } 712 + }; 713 + MODULE_DEVICE_TABLE(i2c, drv260x_id); 714 + 715 + #ifdef CONFIG_OF 716 + static const struct of_device_id drv260x_of_match[] = { 717 + { .compatible = "ti,drv2604", }, 718 + { .compatible = "ti,drv2604l", }, 719 + { .compatible = "ti,drv2605", }, 720 + { .compatible = "ti,drv2605l", }, 721 + { } 722 + }; 723 + MODULE_DEVICE_TABLE(of, drv260x_of_match); 724 + #endif 725 + 726 + static struct i2c_driver drv260x_driver = { 727 + .probe = drv260x_probe, 728 + .driver = { 729 + .name = "drv260x-haptics", 730 + .owner = THIS_MODULE, 731 + .of_match_table = of_match_ptr(drv260x_of_match), 732 + .pm = &drv260x_pm_ops, 733 + }, 734 + .id_table = drv260x_id, 735 + }; 736 + module_i2c_driver(drv260x_driver); 737 + 738 + MODULE_ALIAS("platform:drv260x-haptics"); 739 + MODULE_DESCRIPTION("TI DRV260x haptics driver"); 740 + MODULE_LICENSE("GPL"); 741 + MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
+500
drivers/input/misc/drv2667.c
··· 1 + /* 2 + * DRV2667 haptics driver family 3 + * 4 + * Author: Dan Murphy <dmurphy@ti.com> 5 + * 6 + * Copyright: (C) 2014 Texas Instruments, Inc. 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 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + */ 17 + 18 + #include <linux/i2c.h> 19 + #include <linux/input.h> 20 + #include <linux/module.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/regmap.h> 23 + #include <linux/slab.h> 24 + #include <linux/delay.h> 25 + #include <linux/regulator/consumer.h> 26 + 27 + /* Contol registers */ 28 + #define DRV2667_STATUS 0x00 29 + #define DRV2667_CTRL_1 0x01 30 + #define DRV2667_CTRL_2 0x02 31 + /* Waveform sequencer */ 32 + #define DRV2667_WV_SEQ_0 0x03 33 + #define DRV2667_WV_SEQ_1 0x04 34 + #define DRV2667_WV_SEQ_2 0x05 35 + #define DRV2667_WV_SEQ_3 0x06 36 + #define DRV2667_WV_SEQ_4 0x07 37 + #define DRV2667_WV_SEQ_5 0x08 38 + #define DRV2667_WV_SEQ_6 0x09 39 + #define DRV2667_WV_SEQ_7 0x0A 40 + #define DRV2667_FIFO 0x0B 41 + #define DRV2667_PAGE 0xFF 42 + #define DRV2667_MAX_REG DRV2667_PAGE 43 + 44 + #define DRV2667_PAGE_0 0x00 45 + #define DRV2667_PAGE_1 0x01 46 + #define DRV2667_PAGE_2 0x02 47 + #define DRV2667_PAGE_3 0x03 48 + #define DRV2667_PAGE_4 0x04 49 + #define DRV2667_PAGE_5 0x05 50 + #define DRV2667_PAGE_6 0x06 51 + #define DRV2667_PAGE_7 0x07 52 + #define DRV2667_PAGE_8 0x08 53 + 54 + /* RAM fields */ 55 + #define DRV2667_RAM_HDR_SZ 0x0 56 + /* RAM Header addresses */ 57 + #define DRV2667_RAM_START_HI 0x01 58 + #define DRV2667_RAM_START_LO 0x02 59 + #define DRV2667_RAM_STOP_HI 0x03 60 + #define DRV2667_RAM_STOP_LO 0x04 61 + #define DRV2667_RAM_REPEAT_CT 0x05 62 + /* RAM data addresses */ 63 + #define DRV2667_RAM_AMP 0x06 64 + #define DRV2667_RAM_FREQ 0x07 65 + #define DRV2667_RAM_DURATION 0x08 66 + #define DRV2667_RAM_ENVELOPE 0x09 67 + 68 + /* Control 1 Register */ 69 + #define DRV2667_25_VPP_GAIN 0x00 70 + #define DRV2667_50_VPP_GAIN 0x01 71 + #define DRV2667_75_VPP_GAIN 0x02 72 + #define DRV2667_100_VPP_GAIN 0x03 73 + #define DRV2667_DIGITAL_IN 0xfc 74 + #define DRV2667_ANALOG_IN (1 << 2) 75 + 76 + /* Control 2 Register */ 77 + #define DRV2667_GO (1 << 0) 78 + #define DRV2667_STANDBY (1 << 6) 79 + #define DRV2667_DEV_RST (1 << 7) 80 + 81 + /* RAM Envelope settings */ 82 + #define DRV2667_NO_ENV 0x00 83 + #define DRV2667_32_MS_ENV 0x01 84 + #define DRV2667_64_MS_ENV 0x02 85 + #define DRV2667_96_MS_ENV 0x03 86 + #define DRV2667_128_MS_ENV 0x04 87 + #define DRV2667_160_MS_ENV 0x05 88 + #define DRV2667_192_MS_ENV 0x06 89 + #define DRV2667_224_MS_ENV 0x07 90 + #define DRV2667_256_MS_ENV 0x08 91 + #define DRV2667_512_MS_ENV 0x09 92 + #define DRV2667_768_MS_ENV 0x0a 93 + #define DRV2667_1024_MS_ENV 0x0b 94 + #define DRV2667_1280_MS_ENV 0x0c 95 + #define DRV2667_1536_MS_ENV 0x0d 96 + #define DRV2667_1792_MS_ENV 0x0e 97 + #define DRV2667_2048_MS_ENV 0x0f 98 + 99 + /** 100 + * struct drv2667_data - 101 + * @input_dev - Pointer to the input device 102 + * @client - Pointer to the I2C client 103 + * @regmap - Register map of the device 104 + * @work - Work item used to off load the enable/disable of the vibration 105 + * @regulator - Pointer to the regulator for the IC 106 + * @magnitude - Magnitude of the vibration event 107 + **/ 108 + struct drv2667_data { 109 + struct input_dev *input_dev; 110 + struct i2c_client *client; 111 + struct regmap *regmap; 112 + struct work_struct work; 113 + struct regulator *regulator; 114 + u32 page; 115 + u32 magnitude; 116 + u32 frequency; 117 + }; 118 + 119 + static struct reg_default drv2667_reg_defs[] = { 120 + { DRV2667_STATUS, 0x02 }, 121 + { DRV2667_CTRL_1, 0x28 }, 122 + { DRV2667_CTRL_2, 0x40 }, 123 + { DRV2667_WV_SEQ_0, 0x00 }, 124 + { DRV2667_WV_SEQ_1, 0x00 }, 125 + { DRV2667_WV_SEQ_2, 0x00 }, 126 + { DRV2667_WV_SEQ_3, 0x00 }, 127 + { DRV2667_WV_SEQ_4, 0x00 }, 128 + { DRV2667_WV_SEQ_5, 0x00 }, 129 + { DRV2667_WV_SEQ_6, 0x00 }, 130 + { DRV2667_WV_SEQ_7, 0x00 }, 131 + { DRV2667_FIFO, 0x00 }, 132 + { DRV2667_PAGE, 0x00 }, 133 + }; 134 + 135 + static int drv2667_set_waveform_freq(struct drv2667_data *haptics) 136 + { 137 + unsigned int read_buf; 138 + int freq; 139 + int error; 140 + 141 + /* Per the data sheet: 142 + * Sinusoid Frequency (Hz) = 7.8125 x Frequency 143 + */ 144 + freq = (haptics->frequency * 1000) / 78125; 145 + if (freq <= 0) { 146 + dev_err(&haptics->client->dev, 147 + "ERROR: Frequency calculated to %i\n", freq); 148 + return -EINVAL; 149 + } 150 + 151 + error = regmap_read(haptics->regmap, DRV2667_PAGE, &read_buf); 152 + if (error) { 153 + dev_err(&haptics->client->dev, 154 + "Failed to read the page number: %d\n", error); 155 + return -EIO; 156 + } 157 + 158 + if (read_buf == DRV2667_PAGE_0 || 159 + haptics->page != read_buf) { 160 + error = regmap_write(haptics->regmap, 161 + DRV2667_PAGE, haptics->page); 162 + if (error) { 163 + dev_err(&haptics->client->dev, 164 + "Failed to set the page: %d\n", error); 165 + return -EIO; 166 + } 167 + } 168 + 169 + error = regmap_write(haptics->regmap, DRV2667_RAM_FREQ, freq); 170 + if (error) 171 + dev_err(&haptics->client->dev, 172 + "Failed to set the frequency: %d\n", error); 173 + 174 + /* Reset back to original page */ 175 + if (read_buf == DRV2667_PAGE_0 || 176 + haptics->page != read_buf) { 177 + error = regmap_write(haptics->regmap, DRV2667_PAGE, read_buf); 178 + if (error) { 179 + dev_err(&haptics->client->dev, 180 + "Failed to set the page: %d\n", error); 181 + return -EIO; 182 + } 183 + } 184 + 185 + return error; 186 + } 187 + 188 + static void drv2667_worker(struct work_struct *work) 189 + { 190 + struct drv2667_data *haptics = container_of(work, struct drv2667_data, work); 191 + int error; 192 + 193 + if (haptics->magnitude) { 194 + error = regmap_write(haptics->regmap, 195 + DRV2667_PAGE, haptics->page); 196 + if (error) { 197 + dev_err(&haptics->client->dev, 198 + "Failed to set the page: %d\n", error); 199 + return; 200 + } 201 + 202 + error = regmap_write(haptics->regmap, DRV2667_RAM_AMP, 203 + haptics->magnitude); 204 + if (error) { 205 + dev_err(&haptics->client->dev, 206 + "Failed to set the amplitude: %d\n", error); 207 + return; 208 + } 209 + 210 + error = regmap_write(haptics->regmap, 211 + DRV2667_PAGE, DRV2667_PAGE_0); 212 + if (error) { 213 + dev_err(&haptics->client->dev, 214 + "Failed to set the page: %d\n", error); 215 + return; 216 + } 217 + 218 + error = regmap_write(haptics->regmap, 219 + DRV2667_CTRL_2, DRV2667_GO); 220 + if (error) { 221 + dev_err(&haptics->client->dev, 222 + "Failed to set the GO bit: %d\n", error); 223 + } 224 + } else { 225 + error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, 226 + DRV2667_GO, 0); 227 + if (error) { 228 + dev_err(&haptics->client->dev, 229 + "Failed to unset the GO bit: %d\n", error); 230 + } 231 + } 232 + } 233 + 234 + static int drv2667_haptics_play(struct input_dev *input, void *data, 235 + struct ff_effect *effect) 236 + { 237 + struct drv2667_data *haptics = input_get_drvdata(input); 238 + 239 + if (effect->u.rumble.strong_magnitude > 0) 240 + haptics->magnitude = effect->u.rumble.strong_magnitude; 241 + else if (effect->u.rumble.weak_magnitude > 0) 242 + haptics->magnitude = effect->u.rumble.weak_magnitude; 243 + else 244 + haptics->magnitude = 0; 245 + 246 + schedule_work(&haptics->work); 247 + 248 + return 0; 249 + } 250 + 251 + static void drv2667_close(struct input_dev *input) 252 + { 253 + struct drv2667_data *haptics = input_get_drvdata(input); 254 + int error; 255 + 256 + cancel_work_sync(&haptics->work); 257 + 258 + error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, 259 + DRV2667_STANDBY, 1); 260 + if (error) 261 + dev_err(&haptics->client->dev, 262 + "Failed to enter standby mode: %d\n", error); 263 + } 264 + 265 + static const struct reg_default drv2667_init_regs[] = { 266 + { DRV2667_CTRL_2, 0 }, 267 + { DRV2667_CTRL_1, DRV2667_25_VPP_GAIN }, 268 + { DRV2667_WV_SEQ_0, 1 }, 269 + { DRV2667_WV_SEQ_1, 0 } 270 + }; 271 + 272 + static const struct reg_default drv2667_page1_init[] = { 273 + { DRV2667_RAM_HDR_SZ, 0x05 }, 274 + { DRV2667_RAM_START_HI, 0x80 }, 275 + { DRV2667_RAM_START_LO, 0x06 }, 276 + { DRV2667_RAM_STOP_HI, 0x00 }, 277 + { DRV2667_RAM_STOP_LO, 0x09 }, 278 + { DRV2667_RAM_REPEAT_CT, 0 }, 279 + { DRV2667_RAM_DURATION, 0x05 }, 280 + { DRV2667_RAM_ENVELOPE, DRV2667_NO_ENV }, 281 + { DRV2667_RAM_AMP, 0x60 }, 282 + }; 283 + 284 + static int drv2667_init(struct drv2667_data *haptics) 285 + { 286 + int error; 287 + 288 + /* Set default haptic frequency to 195Hz on Page 1*/ 289 + haptics->frequency = 195; 290 + haptics->page = DRV2667_PAGE_1; 291 + 292 + error = regmap_register_patch(haptics->regmap, 293 + drv2667_init_regs, 294 + ARRAY_SIZE(drv2667_init_regs)); 295 + if (error) { 296 + dev_err(&haptics->client->dev, 297 + "Failed to write init registers: %d\n", 298 + error); 299 + return error; 300 + } 301 + 302 + error = regmap_write(haptics->regmap, DRV2667_PAGE, haptics->page); 303 + if (error) { 304 + dev_err(&haptics->client->dev, "Failed to set page: %d\n", 305 + error); 306 + goto error_out; 307 + } 308 + 309 + error = drv2667_set_waveform_freq(haptics); 310 + if (error) 311 + goto error_page; 312 + 313 + error = regmap_register_patch(haptics->regmap, 314 + drv2667_page1_init, 315 + ARRAY_SIZE(drv2667_page1_init)); 316 + if (error) { 317 + dev_err(&haptics->client->dev, 318 + "Failed to write page registers: %d\n", 319 + error); 320 + return error; 321 + } 322 + 323 + error = regmap_write(haptics->regmap, DRV2667_PAGE, DRV2667_PAGE_0); 324 + return error; 325 + 326 + error_page: 327 + regmap_write(haptics->regmap, DRV2667_PAGE, DRV2667_PAGE_0); 328 + error_out: 329 + return error; 330 + } 331 + 332 + static const struct regmap_config drv2667_regmap_config = { 333 + .reg_bits = 8, 334 + .val_bits = 8, 335 + 336 + .max_register = DRV2667_MAX_REG, 337 + .reg_defaults = drv2667_reg_defs, 338 + .num_reg_defaults = ARRAY_SIZE(drv2667_reg_defs), 339 + .cache_type = REGCACHE_NONE, 340 + }; 341 + 342 + static int drv2667_probe(struct i2c_client *client, 343 + const struct i2c_device_id *id) 344 + { 345 + struct drv2667_data *haptics; 346 + int error; 347 + 348 + haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL); 349 + if (!haptics) 350 + return -ENOMEM; 351 + 352 + haptics->regulator = devm_regulator_get(&client->dev, "vbat"); 353 + if (IS_ERR(haptics->regulator)) { 354 + error = PTR_ERR(haptics->regulator); 355 + dev_err(&client->dev, 356 + "unable to get regulator, error: %d\n", error); 357 + return error; 358 + } 359 + 360 + haptics->input_dev = devm_input_allocate_device(&client->dev); 361 + if (!haptics->input_dev) { 362 + dev_err(&client->dev, "Failed to allocate input device\n"); 363 + return -ENOMEM; 364 + } 365 + 366 + haptics->input_dev->name = "drv2667:haptics"; 367 + haptics->input_dev->dev.parent = client->dev.parent; 368 + haptics->input_dev->close = drv2667_close; 369 + input_set_drvdata(haptics->input_dev, haptics); 370 + input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE); 371 + 372 + error = input_ff_create_memless(haptics->input_dev, NULL, 373 + drv2667_haptics_play); 374 + if (error) { 375 + dev_err(&client->dev, "input_ff_create() failed: %d\n", 376 + error); 377 + return error; 378 + } 379 + 380 + INIT_WORK(&haptics->work, drv2667_worker); 381 + 382 + haptics->client = client; 383 + i2c_set_clientdata(client, haptics); 384 + 385 + haptics->regmap = devm_regmap_init_i2c(client, &drv2667_regmap_config); 386 + if (IS_ERR(haptics->regmap)) { 387 + error = PTR_ERR(haptics->regmap); 388 + dev_err(&client->dev, "Failed to allocate register map: %d\n", 389 + error); 390 + return error; 391 + } 392 + 393 + error = drv2667_init(haptics); 394 + if (error) { 395 + dev_err(&client->dev, "Device init failed: %d\n", error); 396 + return error; 397 + } 398 + 399 + error = input_register_device(haptics->input_dev); 400 + if (error) { 401 + dev_err(&client->dev, "couldn't register input device: %d\n", 402 + error); 403 + return error; 404 + } 405 + 406 + return 0; 407 + } 408 + 409 + #ifdef CONFIG_PM_SLEEP 410 + static int drv2667_suspend(struct device *dev) 411 + { 412 + struct drv2667_data *haptics = dev_get_drvdata(dev); 413 + int ret = 0; 414 + 415 + mutex_lock(&haptics->input_dev->mutex); 416 + 417 + if (haptics->input_dev->users) { 418 + ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, 419 + DRV2667_STANDBY, 1); 420 + if (ret) { 421 + dev_err(dev, "Failed to set standby mode\n"); 422 + regulator_disable(haptics->regulator); 423 + goto out; 424 + } 425 + 426 + ret = regulator_disable(haptics->regulator); 427 + if (ret) { 428 + dev_err(dev, "Failed to disable regulator\n"); 429 + regmap_update_bits(haptics->regmap, 430 + DRV2667_CTRL_2, 431 + DRV2667_STANDBY, 0); 432 + } 433 + } 434 + out: 435 + mutex_unlock(&haptics->input_dev->mutex); 436 + return ret; 437 + } 438 + 439 + static int drv2667_resume(struct device *dev) 440 + { 441 + struct drv2667_data *haptics = dev_get_drvdata(dev); 442 + int ret = 0; 443 + 444 + mutex_lock(&haptics->input_dev->mutex); 445 + 446 + if (haptics->input_dev->users) { 447 + ret = regulator_enable(haptics->regulator); 448 + if (ret) { 449 + dev_err(dev, "Failed to enable regulator\n"); 450 + goto out; 451 + } 452 + 453 + ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, 454 + DRV2667_STANDBY, 0); 455 + if (ret) { 456 + dev_err(dev, "Failed to unset standby mode\n"); 457 + regulator_disable(haptics->regulator); 458 + goto out; 459 + } 460 + 461 + } 462 + 463 + out: 464 + mutex_unlock(&haptics->input_dev->mutex); 465 + return ret; 466 + } 467 + #endif 468 + 469 + static SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume); 470 + 471 + static const struct i2c_device_id drv2667_id[] = { 472 + { "drv2667", 0 }, 473 + { } 474 + }; 475 + MODULE_DEVICE_TABLE(i2c, drv2667_id); 476 + 477 + #ifdef CONFIG_OF 478 + static const struct of_device_id drv2667_of_match[] = { 479 + { .compatible = "ti,drv2667", }, 480 + { } 481 + }; 482 + MODULE_DEVICE_TABLE(of, drv2667_of_match); 483 + #endif 484 + 485 + static struct i2c_driver drv2667_driver = { 486 + .probe = drv2667_probe, 487 + .driver = { 488 + .name = "drv2667-haptics", 489 + .owner = THIS_MODULE, 490 + .of_match_table = of_match_ptr(drv2667_of_match), 491 + .pm = &drv2667_pm_ops, 492 + }, 493 + .id_table = drv2667_id, 494 + }; 495 + module_i2c_driver(drv2667_driver); 496 + 497 + MODULE_ALIAS("platform:drv2667-haptics"); 498 + MODULE_DESCRIPTION("TI DRV2667 haptics driver"); 499 + MODULE_LICENSE("GPL"); 500 + MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
+357
drivers/input/misc/max77693-haptic.c
··· 1 + /* 2 + * MAXIM MAX77693 Haptic device driver 3 + * 4 + * Copyright (C) 2014 Samsung Electronics 5 + * Jaewon Kim <jaewon02.kim@samsung.com> 6 + * 7 + * This program is not provided / owned by Maxim Integrated Products. 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation; either version 2 of the License, or 12 + * (at your option) any later version. 13 + */ 14 + 15 + #include <linux/err.h> 16 + #include <linux/init.h> 17 + #include <linux/i2c.h> 18 + #include <linux/regmap.h> 19 + #include <linux/input.h> 20 + #include <linux/module.h> 21 + #include <linux/platform_device.h> 22 + #include <linux/pwm.h> 23 + #include <linux/slab.h> 24 + #include <linux/workqueue.h> 25 + #include <linux/regulator/consumer.h> 26 + #include <linux/mfd/max77693.h> 27 + #include <linux/mfd/max77693-private.h> 28 + 29 + #define MAX_MAGNITUDE_SHIFT 16 30 + 31 + enum max77693_haptic_motor_type { 32 + MAX77693_HAPTIC_ERM = 0, 33 + MAX77693_HAPTIC_LRA, 34 + }; 35 + 36 + enum max77693_haptic_pulse_mode { 37 + MAX77693_HAPTIC_EXTERNAL_MODE = 0, 38 + MAX77693_HAPTIC_INTERNAL_MODE, 39 + }; 40 + 41 + enum max77693_haptic_pwm_divisor { 42 + MAX77693_HAPTIC_PWM_DIVISOR_32 = 0, 43 + MAX77693_HAPTIC_PWM_DIVISOR_64, 44 + MAX77693_HAPTIC_PWM_DIVISOR_128, 45 + MAX77693_HAPTIC_PWM_DIVISOR_256, 46 + }; 47 + 48 + struct max77693_haptic { 49 + struct regmap *regmap_pmic; 50 + struct regmap *regmap_haptic; 51 + struct device *dev; 52 + struct input_dev *input_dev; 53 + struct pwm_device *pwm_dev; 54 + struct regulator *motor_reg; 55 + 56 + bool enabled; 57 + bool suspend_state; 58 + unsigned int magnitude; 59 + unsigned int pwm_duty; 60 + enum max77693_haptic_motor_type type; 61 + enum max77693_haptic_pulse_mode mode; 62 + enum max77693_haptic_pwm_divisor pwm_divisor; 63 + 64 + struct work_struct work; 65 + }; 66 + 67 + static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic) 68 + { 69 + int delta = (haptic->pwm_dev->period + haptic->pwm_duty) / 2; 70 + int error; 71 + 72 + error = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period); 73 + if (error) { 74 + dev_err(haptic->dev, "failed to configure pwm: %d\n", error); 75 + return error; 76 + } 77 + 78 + return 0; 79 + } 80 + 81 + static int max77693_haptic_configure(struct max77693_haptic *haptic, 82 + bool enable) 83 + { 84 + unsigned int value; 85 + int error; 86 + 87 + value = ((haptic->type << MAX77693_CONFIG2_MODE) | 88 + (enable << MAX77693_CONFIG2_MEN) | 89 + (haptic->mode << MAX77693_CONFIG2_HTYP) | 90 + (haptic->pwm_divisor)); 91 + 92 + error = regmap_write(haptic->regmap_haptic, 93 + MAX77693_HAPTIC_REG_CONFIG2, value); 94 + if (error) { 95 + dev_err(haptic->dev, 96 + "failed to update haptic config: %d\n", error); 97 + return error; 98 + } 99 + 100 + return 0; 101 + } 102 + 103 + static int max77693_haptic_lowsys(struct max77693_haptic *haptic, bool enable) 104 + { 105 + int error; 106 + 107 + error = regmap_update_bits(haptic->regmap_pmic, 108 + MAX77693_PMIC_REG_LSCNFG, 109 + MAX77693_PMIC_LOW_SYS_MASK, 110 + enable << MAX77693_PMIC_LOW_SYS_SHIFT); 111 + if (error) { 112 + dev_err(haptic->dev, "cannot update pmic regmap: %d\n", error); 113 + return error; 114 + } 115 + 116 + return 0; 117 + } 118 + 119 + static void max77693_haptic_enable(struct max77693_haptic *haptic) 120 + { 121 + int error; 122 + 123 + if (haptic->enabled) 124 + return; 125 + 126 + error = pwm_enable(haptic->pwm_dev); 127 + if (error) { 128 + dev_err(haptic->dev, 129 + "failed to enable haptic pwm device: %d\n", error); 130 + return; 131 + } 132 + 133 + error = max77693_haptic_lowsys(haptic, true); 134 + if (error) 135 + goto err_enable_lowsys; 136 + 137 + error = max77693_haptic_configure(haptic, true); 138 + if (error) 139 + goto err_enable_config; 140 + 141 + haptic->enabled = true; 142 + 143 + return; 144 + 145 + err_enable_config: 146 + max77693_haptic_lowsys(haptic, false); 147 + err_enable_lowsys: 148 + pwm_disable(haptic->pwm_dev); 149 + } 150 + 151 + static void max77693_haptic_disable(struct max77693_haptic *haptic) 152 + { 153 + int error; 154 + 155 + if (haptic->enabled) 156 + return; 157 + 158 + error = max77693_haptic_configure(haptic, false); 159 + if (error) 160 + return; 161 + 162 + error = max77693_haptic_lowsys(haptic, false); 163 + if (error) 164 + goto err_disable_lowsys; 165 + 166 + pwm_disable(haptic->pwm_dev); 167 + haptic->enabled = false; 168 + 169 + return; 170 + 171 + err_disable_lowsys: 172 + max77693_haptic_configure(haptic, true); 173 + } 174 + 175 + static void max77693_haptic_play_work(struct work_struct *work) 176 + { 177 + struct max77693_haptic *haptic = 178 + container_of(work, struct max77693_haptic, work); 179 + int error; 180 + 181 + error = max77693_haptic_set_duty_cycle(haptic); 182 + if (error) { 183 + dev_err(haptic->dev, "failed to set duty cycle: %d\n", error); 184 + return; 185 + } 186 + 187 + if (haptic->magnitude) 188 + max77693_haptic_enable(haptic); 189 + else 190 + max77693_haptic_disable(haptic); 191 + } 192 + 193 + static int max77693_haptic_play_effect(struct input_dev *dev, void *data, 194 + struct ff_effect *effect) 195 + { 196 + struct max77693_haptic *haptic = input_get_drvdata(dev); 197 + uint64_t period_mag_multi; 198 + 199 + haptic->magnitude = effect->u.rumble.strong_magnitude; 200 + if (!haptic->magnitude) 201 + haptic->magnitude = effect->u.rumble.weak_magnitude; 202 + 203 + /* 204 + * The magnitude comes from force-feedback interface. 205 + * The formula to convert magnitude to pwm_duty as follows: 206 + * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF) 207 + */ 208 + period_mag_multi = (int64_t)(haptic->pwm_dev->period * 209 + haptic->magnitude); 210 + haptic->pwm_duty = (unsigned int)(period_mag_multi >> 211 + MAX_MAGNITUDE_SHIFT); 212 + 213 + schedule_work(&haptic->work); 214 + 215 + return 0; 216 + } 217 + 218 + static int max77693_haptic_open(struct input_dev *dev) 219 + { 220 + struct max77693_haptic *haptic = input_get_drvdata(dev); 221 + int error; 222 + 223 + error = regulator_enable(haptic->motor_reg); 224 + if (error) { 225 + dev_err(haptic->dev, 226 + "failed to enable regulator: %d\n", error); 227 + return error; 228 + } 229 + 230 + return 0; 231 + } 232 + 233 + static void max77693_haptic_close(struct input_dev *dev) 234 + { 235 + struct max77693_haptic *haptic = input_get_drvdata(dev); 236 + int error; 237 + 238 + cancel_work_sync(&haptic->work); 239 + max77693_haptic_disable(haptic); 240 + 241 + error = regulator_disable(haptic->motor_reg); 242 + if (error) 243 + dev_err(haptic->dev, 244 + "failed to disable regulator: %d\n", error); 245 + } 246 + 247 + static int max77693_haptic_probe(struct platform_device *pdev) 248 + { 249 + struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); 250 + struct max77693_haptic *haptic; 251 + int error; 252 + 253 + haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL); 254 + if (!haptic) 255 + return -ENOMEM; 256 + 257 + haptic->regmap_pmic = max77693->regmap; 258 + haptic->regmap_haptic = max77693->regmap_haptic; 259 + haptic->dev = &pdev->dev; 260 + haptic->type = MAX77693_HAPTIC_LRA; 261 + haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE; 262 + haptic->pwm_divisor = MAX77693_HAPTIC_PWM_DIVISOR_128; 263 + haptic->suspend_state = false; 264 + 265 + INIT_WORK(&haptic->work, max77693_haptic_play_work); 266 + 267 + /* Get pwm and regulatot for haptic device */ 268 + haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL); 269 + if (IS_ERR(haptic->pwm_dev)) { 270 + dev_err(&pdev->dev, "failed to get pwm device\n"); 271 + return PTR_ERR(haptic->pwm_dev); 272 + } 273 + 274 + haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic"); 275 + if (IS_ERR(haptic->motor_reg)) { 276 + dev_err(&pdev->dev, "failed to get regulator\n"); 277 + return PTR_ERR(haptic->motor_reg); 278 + } 279 + 280 + /* Initialize input device for haptic device */ 281 + haptic->input_dev = devm_input_allocate_device(&pdev->dev); 282 + if (!haptic->input_dev) { 283 + dev_err(&pdev->dev, "failed to allocate input device\n"); 284 + return -ENOMEM; 285 + } 286 + 287 + haptic->input_dev->name = "max77693-haptic"; 288 + haptic->input_dev->id.version = 1; 289 + haptic->input_dev->dev.parent = &pdev->dev; 290 + haptic->input_dev->open = max77693_haptic_open; 291 + haptic->input_dev->close = max77693_haptic_close; 292 + input_set_drvdata(haptic->input_dev, haptic); 293 + input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE); 294 + 295 + error = input_ff_create_memless(haptic->input_dev, NULL, 296 + max77693_haptic_play_effect); 297 + if (error) { 298 + dev_err(&pdev->dev, "failed to create force-feedback\n"); 299 + return error; 300 + } 301 + 302 + error = input_register_device(haptic->input_dev); 303 + if (error) { 304 + dev_err(&pdev->dev, "failed to register input device\n"); 305 + return error; 306 + } 307 + 308 + platform_set_drvdata(pdev, haptic); 309 + 310 + return 0; 311 + } 312 + 313 + #ifdef CONFIG_PM_SLEEP 314 + static int max77693_haptic_suspend(struct device *dev) 315 + { 316 + struct platform_device *pdev = to_platform_device(dev); 317 + struct max77693_haptic *haptic = platform_get_drvdata(pdev); 318 + 319 + if (haptic->enabled) { 320 + max77693_haptic_disable(haptic); 321 + haptic->suspend_state = true; 322 + } 323 + 324 + return 0; 325 + } 326 + 327 + static int max77693_haptic_resume(struct device *dev) 328 + { 329 + struct platform_device *pdev = to_platform_device(dev); 330 + struct max77693_haptic *haptic = platform_get_drvdata(pdev); 331 + 332 + if (haptic->suspend_state) { 333 + max77693_haptic_enable(haptic); 334 + haptic->suspend_state = false; 335 + } 336 + 337 + return 0; 338 + } 339 + #endif 340 + 341 + static SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops, 342 + max77693_haptic_suspend, max77693_haptic_resume); 343 + 344 + static struct platform_driver max77693_haptic_driver = { 345 + .driver = { 346 + .name = "max77693-haptic", 347 + .owner = THIS_MODULE, 348 + .pm = &max77693_haptic_pm_ops, 349 + }, 350 + .probe = max77693_haptic_probe, 351 + }; 352 + module_platform_driver(max77693_haptic_driver); 353 + 354 + MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); 355 + MODULE_DESCRIPTION("MAXIM MAX77693 Haptic driver"); 356 + MODULE_ALIAS("platform:max77693-haptic"); 357 + MODULE_LICENSE("GPL");
+332
drivers/input/misc/palmas-pwrbutton.c
··· 1 + /* 2 + * Texas Instruments' Palmas Power Button Input Driver 3 + * 4 + * Copyright (C) 2012-2014 Texas Instruments Incorporated - http://www.ti.com/ 5 + * Girish S Ghongdemath 6 + * Nishanth Menon 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 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any 13 + * kind, whether express or implied; without even the implied warranty 14 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + */ 17 + 18 + #include <linux/init.h> 19 + #include <linux/input.h> 20 + #include <linux/interrupt.h> 21 + #include <linux/kernel.h> 22 + #include <linux/mfd/palmas.h> 23 + #include <linux/module.h> 24 + #include <linux/of.h> 25 + #include <linux/platform_device.h> 26 + #include <linux/slab.h> 27 + 28 + #define PALMAS_LPK_TIME_MASK 0x0c 29 + #define PALMAS_PWRON_DEBOUNCE_MASK 0x03 30 + #define PALMAS_PWR_KEY_Q_TIME_MS 20 31 + 32 + /** 33 + * struct palmas_pwron - Palmas power on data 34 + * @palmas: pointer to palmas device 35 + * @input_dev: pointer to input device 36 + * @input_work: work for detecting release of key 37 + * @irq: irq that we are hooked on to 38 + */ 39 + struct palmas_pwron { 40 + struct palmas *palmas; 41 + struct input_dev *input_dev; 42 + struct delayed_work input_work; 43 + int irq; 44 + }; 45 + 46 + /** 47 + * struct palmas_pwron_config - configuration of palmas power on 48 + * @long_press_time_val: value for long press h/w shutdown event 49 + * @pwron_debounce_val: value for debounce of power button 50 + */ 51 + struct palmas_pwron_config { 52 + u8 long_press_time_val; 53 + u8 pwron_debounce_val; 54 + }; 55 + 56 + /** 57 + * palmas_power_button_work() - Detects the button release event 58 + * @work: work item to detect button release 59 + */ 60 + static void palmas_power_button_work(struct work_struct *work) 61 + { 62 + struct palmas_pwron *pwron = container_of(work, 63 + struct palmas_pwron, 64 + input_work.work); 65 + struct input_dev *input_dev = pwron->input_dev; 66 + unsigned int reg; 67 + int error; 68 + 69 + error = palmas_read(pwron->palmas, PALMAS_INTERRUPT_BASE, 70 + PALMAS_INT1_LINE_STATE, &reg); 71 + if (error) { 72 + dev_err(input_dev->dev.parent, 73 + "Cannot read palmas PWRON status: %d\n", error); 74 + } else if (reg & BIT(1)) { 75 + /* The button is released, report event. */ 76 + input_report_key(input_dev, KEY_POWER, 0); 77 + input_sync(input_dev); 78 + } else { 79 + /* The button is still depressed, keep checking. */ 80 + schedule_delayed_work(&pwron->input_work, 81 + msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS)); 82 + } 83 + } 84 + 85 + /** 86 + * pwron_irq() - button press isr 87 + * @irq: irq 88 + * @palmas_pwron: pwron struct 89 + * 90 + * Return: IRQ_HANDLED 91 + */ 92 + static irqreturn_t pwron_irq(int irq, void *palmas_pwron) 93 + { 94 + struct palmas_pwron *pwron = palmas_pwron; 95 + struct input_dev *input_dev = pwron->input_dev; 96 + 97 + input_report_key(input_dev, KEY_POWER, 1); 98 + pm_wakeup_event(input_dev->dev.parent, 0); 99 + input_sync(input_dev); 100 + 101 + mod_delayed_work(system_wq, &pwron->input_work, 102 + msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS)); 103 + 104 + return IRQ_HANDLED; 105 + } 106 + 107 + /** 108 + * palmas_pwron_params_ofinit() - device tree parameter parser 109 + * @dev: palmas button device 110 + * @config: configuration params that this fills up 111 + */ 112 + static void palmas_pwron_params_ofinit(struct device *dev, 113 + struct palmas_pwron_config *config) 114 + { 115 + struct device_node *np; 116 + u32 val; 117 + int i, error; 118 + u8 lpk_times[] = { 6, 8, 10, 12 }; 119 + int pwr_on_deb_ms[] = { 15, 100, 500, 1000 }; 120 + 121 + memset(config, 0, sizeof(*config)); 122 + 123 + /* Default config parameters */ 124 + config->long_press_time_val = ARRAY_SIZE(lpk_times) - 1; 125 + 126 + np = dev->of_node; 127 + if (!np) 128 + return; 129 + 130 + error = of_property_read_u32(np, "ti,palmas-long-press-seconds", &val); 131 + if (!error) { 132 + for (i = 0; i < ARRAY_SIZE(lpk_times); i++) { 133 + if (val <= lpk_times[i]) { 134 + config->long_press_time_val = i; 135 + break; 136 + } 137 + } 138 + } 139 + 140 + error = of_property_read_u32(np, 141 + "ti,palmas-pwron-debounce-milli-seconds", 142 + &val); 143 + if (!error) { 144 + for (i = 0; i < ARRAY_SIZE(pwr_on_deb_ms); i++) { 145 + if (val <= pwr_on_deb_ms[i]) { 146 + config->pwron_debounce_val = i; 147 + break; 148 + } 149 + } 150 + } 151 + 152 + dev_info(dev, "h/w controlled shutdown duration=%d seconds\n", 153 + lpk_times[config->long_press_time_val]); 154 + } 155 + 156 + /** 157 + * palmas_pwron_probe() - probe 158 + * @pdev: platform device for the button 159 + * 160 + * Return: 0 for successful probe else appropriate error 161 + */ 162 + static int palmas_pwron_probe(struct platform_device *pdev) 163 + { 164 + struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); 165 + struct device *dev = &pdev->dev; 166 + struct input_dev *input_dev; 167 + struct palmas_pwron *pwron; 168 + struct palmas_pwron_config config; 169 + int val; 170 + int error; 171 + 172 + palmas_pwron_params_ofinit(dev, &config); 173 + 174 + pwron = kzalloc(sizeof(*pwron), GFP_KERNEL); 175 + if (!pwron) 176 + return -ENOMEM; 177 + 178 + input_dev = input_allocate_device(); 179 + if (!input_dev) { 180 + dev_err(dev, "Can't allocate power button\n"); 181 + error = -ENOMEM; 182 + goto err_free_mem; 183 + } 184 + 185 + input_dev->name = "palmas_pwron"; 186 + input_dev->phys = "palmas_pwron/input0"; 187 + input_dev->dev.parent = dev; 188 + 189 + input_set_capability(input_dev, EV_KEY, KEY_POWER); 190 + 191 + /* 192 + * Setup default hardware shutdown option (long key press) 193 + * and debounce. 194 + */ 195 + val = config.long_press_time_val << __ffs(PALMAS_LPK_TIME_MASK); 196 + val |= config.pwron_debounce_val << __ffs(PALMAS_PWRON_DEBOUNCE_MASK); 197 + error = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE, 198 + PALMAS_LONG_PRESS_KEY, 199 + PALMAS_LPK_TIME_MASK | 200 + PALMAS_PWRON_DEBOUNCE_MASK, 201 + val); 202 + if (error) { 203 + dev_err(dev, "LONG_PRESS_KEY_UPDATE failed: %d\n", error); 204 + goto err_free_input; 205 + } 206 + 207 + pwron->palmas = palmas; 208 + pwron->input_dev = input_dev; 209 + 210 + INIT_DELAYED_WORK(&pwron->input_work, palmas_power_button_work); 211 + 212 + pwron->irq = platform_get_irq(pdev, 0); 213 + error = request_threaded_irq(pwron->irq, NULL, pwron_irq, 214 + IRQF_TRIGGER_HIGH | 215 + IRQF_TRIGGER_LOW | 216 + IRQF_ONESHOT, 217 + dev_name(dev), pwron); 218 + if (error) { 219 + dev_err(dev, "Can't get IRQ for pwron: %d\n", error); 220 + goto err_free_input; 221 + } 222 + 223 + error = input_register_device(input_dev); 224 + if (error) { 225 + dev_err(dev, "Can't register power button: %d\n", error); 226 + goto err_free_irq; 227 + } 228 + 229 + platform_set_drvdata(pdev, pwron); 230 + device_init_wakeup(dev, true); 231 + 232 + return 0; 233 + 234 + err_free_irq: 235 + cancel_delayed_work_sync(&pwron->input_work); 236 + free_irq(pwron->irq, pwron); 237 + err_free_input: 238 + input_free_device(input_dev); 239 + err_free_mem: 240 + kfree(pwron); 241 + return error; 242 + } 243 + 244 + /** 245 + * palmas_pwron_remove() - Cleanup on removal 246 + * @pdev: platform device for the button 247 + * 248 + * Return: 0 249 + */ 250 + static int palmas_pwron_remove(struct platform_device *pdev) 251 + { 252 + struct palmas_pwron *pwron = platform_get_drvdata(pdev); 253 + 254 + free_irq(pwron->irq, pwron); 255 + cancel_delayed_work_sync(&pwron->input_work); 256 + 257 + input_unregister_device(pwron->input_dev); 258 + kfree(pwron); 259 + 260 + return 0; 261 + } 262 + 263 + #ifdef CONFIG_PM_SLEEP 264 + /** 265 + * palmas_pwron_suspend() - suspend handler 266 + * @dev: power button device 267 + * 268 + * Cancel all pending work items for the power button, setup irq for wakeup 269 + * 270 + * Return: 0 271 + */ 272 + static int palmas_pwron_suspend(struct device *dev) 273 + { 274 + struct platform_device *pdev = to_platform_device(dev); 275 + struct palmas_pwron *pwron = platform_get_drvdata(pdev); 276 + 277 + cancel_delayed_work_sync(&pwron->input_work); 278 + 279 + if (device_may_wakeup(dev)) 280 + enable_irq_wake(pwron->irq); 281 + 282 + return 0; 283 + } 284 + 285 + /** 286 + * palmas_pwron_resume() - resume handler 287 + * @dev: power button device 288 + * 289 + * Just disable the wakeup capability of irq here. 290 + * 291 + * Return: 0 292 + */ 293 + static int palmas_pwron_resume(struct device *dev) 294 + { 295 + struct platform_device *pdev = to_platform_device(dev); 296 + struct palmas_pwron *pwron = platform_get_drvdata(pdev); 297 + 298 + if (device_may_wakeup(dev)) 299 + disable_irq_wake(pwron->irq); 300 + 301 + return 0; 302 + } 303 + #endif 304 + 305 + static SIMPLE_DEV_PM_OPS(palmas_pwron_pm, 306 + palmas_pwron_suspend, palmas_pwron_resume); 307 + 308 + #ifdef CONFIG_OF 309 + static struct of_device_id of_palmas_pwr_match[] = { 310 + { .compatible = "ti,palmas-pwrbutton" }, 311 + { }, 312 + }; 313 + 314 + MODULE_DEVICE_TABLE(of, of_palmas_pwr_match); 315 + #endif 316 + 317 + static struct platform_driver palmas_pwron_driver = { 318 + .probe = palmas_pwron_probe, 319 + .remove = palmas_pwron_remove, 320 + .driver = { 321 + .name = "palmas_pwrbutton", 322 + .owner = THIS_MODULE, 323 + .of_match_table = of_match_ptr(of_palmas_pwr_match), 324 + .pm = &palmas_pwron_pm, 325 + }, 326 + }; 327 + module_platform_driver(palmas_pwron_driver); 328 + 329 + MODULE_ALIAS("platform:palmas-pwrbutton"); 330 + MODULE_DESCRIPTION("Palmas Power Button"); 331 + MODULE_LICENSE("GPL v2"); 332 + MODULE_AUTHOR("Texas Instruments Inc.");
+31 -29
drivers/input/misc/soc_button_array.c
··· 18 18 #include <linux/gpio/consumer.h> 19 19 #include <linux/gpio_keys.h> 20 20 #include <linux/platform_device.h> 21 - #include <linux/pnp.h> 21 + #include <linux/acpi.h> 22 22 23 23 /* 24 24 * Definition of buttons on the tablet. The ACPI index of each button ··· 67 67 } 68 68 69 69 static struct platform_device * 70 - soc_button_device_create(struct pnp_dev *pdev, 70 + soc_button_device_create(struct platform_device *pdev, 71 71 const struct soc_button_info *button_info, 72 72 bool autorepeat) 73 73 { ··· 138 138 return ERR_PTR(error); 139 139 } 140 140 141 - static void soc_button_remove(struct pnp_dev *pdev) 141 + static int soc_button_remove(struct platform_device *pdev) 142 142 { 143 - struct soc_button_data *priv = pnp_get_drvdata(pdev); 143 + struct soc_button_data *priv = platform_get_drvdata(pdev); 144 + 144 145 int i; 145 146 146 147 for (i = 0; i < BUTTON_TYPES; i++) 147 148 if (priv->children[i]) 148 149 platform_device_unregister(priv->children[i]); 150 + 151 + return 0; 149 152 } 150 153 151 - static int soc_button_pnp_probe(struct pnp_dev *pdev, 152 - const struct pnp_device_id *id) 154 + static int soc_button_probe(struct platform_device *pdev) 153 155 { 154 - const struct soc_button_info *button_info = (void *)id->driver_data; 156 + struct device *dev = &pdev->dev; 157 + const struct acpi_device_id *id; 158 + struct soc_button_info *button_info; 155 159 struct soc_button_data *priv; 156 160 struct platform_device *pd; 157 161 int i; 158 162 int error; 159 163 164 + id = acpi_match_device(dev->driver->acpi_match_table, dev); 165 + if (!id) 166 + return -ENODEV; 167 + 168 + button_info = (struct soc_button_info *)id->driver_data; 169 + 160 170 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 161 171 if (!priv) 162 172 return -ENOMEM; 163 173 164 - pnp_set_drvdata(pdev, priv); 174 + platform_set_drvdata(pdev, priv); 165 175 166 176 for (i = 0; i < BUTTON_TYPES; i++) { 167 177 pd = soc_button_device_create(pdev, button_info, i == 0); ··· 202 192 { } 203 193 }; 204 194 205 - static const struct pnp_device_id soc_button_pnp_match[] = { 206 - { .id = "PNP0C40", .driver_data = (long)soc_button_PNP0C40 }, 207 - { .id = "" } 195 + static const struct acpi_device_id soc_button_acpi_match[] = { 196 + { "PNP0C40", (unsigned long)soc_button_PNP0C40 }, 197 + { } 208 198 }; 209 - MODULE_DEVICE_TABLE(pnp, soc_button_pnp_match); 210 199 211 - static struct pnp_driver soc_button_pnp_driver = { 212 - .name = KBUILD_MODNAME, 213 - .id_table = soc_button_pnp_match, 214 - .probe = soc_button_pnp_probe, 200 + MODULE_DEVICE_TABLE(acpi, soc_button_acpi_match); 201 + 202 + static struct platform_driver soc_button_driver = { 203 + .probe = soc_button_probe, 215 204 .remove = soc_button_remove, 205 + .driver = { 206 + .name = KBUILD_MODNAME, 207 + .owner = THIS_MODULE, 208 + .acpi_match_table = ACPI_PTR(soc_button_acpi_match), 209 + }, 216 210 }; 217 - 218 - static int __init soc_button_init(void) 219 - { 220 - return pnp_register_driver(&soc_button_pnp_driver); 221 - } 222 - 223 - static void __exit soc_button_exit(void) 224 - { 225 - pnp_unregister_driver(&soc_button_pnp_driver); 226 - } 227 - 228 - module_init(soc_button_init); 229 - module_exit(soc_button_exit); 211 + module_platform_driver(soc_button_driver); 230 212 231 213 MODULE_LICENSE("GPL");
+1 -1
drivers/input/mouse/Makefile
··· 23 23 obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o 24 24 obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o 25 25 26 - psmouse-objs := psmouse-base.o synaptics.o 26 + psmouse-objs := psmouse-base.o synaptics.o focaltech.o 27 27 28 28 psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o 29 29 psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o
+52
drivers/input/mouse/focaltech.c
··· 1 + /* 2 + * Focaltech TouchPad PS/2 mouse driver 3 + * 4 + * Copyright (c) 2014 Red Hat Inc. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * Red Hat authors: 12 + * 13 + * Hans de Goede <hdegoede@redhat.com> 14 + */ 15 + 16 + /* 17 + * The Focaltech PS/2 touchpad protocol is unknown. This drivers deals with 18 + * detection only, to avoid further detection attempts confusing the touchpad 19 + * this way it at least works in PS/2 mouse compatibility mode. 20 + */ 21 + 22 + #include <linux/device.h> 23 + #include <linux/libps2.h> 24 + #include "psmouse.h" 25 + 26 + static const char * const focaltech_pnp_ids[] = { 27 + "FLT0101", 28 + "FLT0102", 29 + "FLT0103", 30 + NULL 31 + }; 32 + 33 + int focaltech_detect(struct psmouse *psmouse, bool set_properties) 34 + { 35 + if (!psmouse_matches_pnp_id(psmouse, focaltech_pnp_ids)) 36 + return -ENODEV; 37 + 38 + if (set_properties) { 39 + psmouse->vendor = "FocalTech"; 40 + psmouse->name = "FocalTech Touchpad in mouse emulation mode"; 41 + } 42 + 43 + return 0; 44 + } 45 + 46 + int focaltech_init(struct psmouse *psmouse) 47 + { 48 + ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); 49 + psmouse_reset(psmouse); 50 + 51 + return 0; 52 + }
+22
drivers/input/mouse/focaltech.h
··· 1 + /* 2 + * Focaltech TouchPad PS/2 mouse driver 3 + * 4 + * Copyright (c) 2014 Red Hat Inc. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * Red Hat authors: 12 + * 13 + * Hans de Goede <hdegoede@redhat.com> 14 + */ 15 + 16 + #ifndef _FOCALTECH_H 17 + #define _FOCALTECH_H 18 + 19 + int focaltech_detect(struct psmouse *psmouse, bool set_properties); 20 + int focaltech_init(struct psmouse *psmouse); 21 + 22 + #endif
+30
drivers/input/mouse/psmouse-base.c
··· 35 35 #include "elantech.h" 36 36 #include "sentelic.h" 37 37 #include "cypress_ps2.h" 38 + #include "focaltech.h" 38 39 39 40 #define DRIVER_DESC "PS/2 mouse driver" 40 41 ··· 463 462 PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); 464 463 } 465 464 465 + /* 466 + * psmouse_matches_pnp_id - check if psmouse matches one of the passed in ids. 467 + */ 468 + bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]) 469 + { 470 + int i; 471 + 472 + if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) 473 + for (i = 0; ids[i]; i++) 474 + if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i])) 475 + return true; 476 + 477 + return false; 478 + } 466 479 467 480 /* 468 481 * Genius NetMouse magic init. ··· 722 707 unsigned int max_proto, bool set_properties) 723 708 { 724 709 bool synaptics_hardware = false; 710 + 711 + /* Always check for focaltech, this is safe as it uses pnp-id matching */ 712 + if (psmouse_do_detect(focaltech_detect, psmouse, set_properties) == 0) { 713 + if (!set_properties || focaltech_init(psmouse) == 0) { 714 + /* 715 + * Not supported yet, use bare protocol. 716 + * Note that we need to also restrict 717 + * psmouse_max_proto so that psmouse_initialize() 718 + * does not try to reset rate and resolution, 719 + * because even that upsets the device. 720 + */ 721 + psmouse_max_proto = PSMOUSE_PS2; 722 + return PSMOUSE_PS2; 723 + } 724 + } 725 725 726 726 /* 727 727 * We always check for lifebook because it does not disturb mouse
+1
drivers/input/mouse/psmouse.h
··· 108 108 psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse); 109 109 int psmouse_activate(struct psmouse *psmouse); 110 110 int psmouse_deactivate(struct psmouse *psmouse); 111 + bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]); 111 112 112 113 struct psmouse_attribute { 113 114 struct device_attribute dattr;
+3 -14
drivers/input/mouse/synaptics.c
··· 185 185 NULL 186 186 }; 187 187 188 - static bool matches_pnp_id(struct psmouse *psmouse, const char * const ids[]) 189 - { 190 - int i; 191 - 192 - if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) 193 - for (i = 0; ids[i]; i++) 194 - if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i])) 195 - return true; 196 - 197 - return false; 198 - } 199 - 200 188 /***************************************************************************** 201 189 * Synaptics communications functions 202 190 ****************************************************************************/ ··· 350 362 } 351 363 352 364 for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) { 353 - if (matches_pnp_id(psmouse, min_max_pnpid_table[i].pnp_ids)) { 365 + if (psmouse_matches_pnp_id(psmouse, 366 + min_max_pnpid_table[i].pnp_ids)) { 354 367 priv->x_min = min_max_pnpid_table[i].x_min; 355 368 priv->x_max = min_max_pnpid_table[i].x_max; 356 369 priv->y_min = min_max_pnpid_table[i].y_min; ··· 1481 1492 1482 1493 if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { 1483 1494 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); 1484 - if (matches_pnp_id(psmouse, topbuttonpad_pnp_ids)) 1495 + if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids)) 1485 1496 __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit); 1486 1497 /* Clickpads report only left button */ 1487 1498 __clear_bit(BTN_RIGHT, dev->keybit);
+36
include/dt-bindings/input/ti-drv260x.h
··· 1 + /* 2 + * DRV260X haptics driver family 3 + * 4 + * Author: Dan Murphy <dmurphy@ti.com> 5 + * 6 + * Copyright: (C) 2014 Texas Instruments, Inc. 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 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + */ 17 + 18 + #ifndef _DT_BINDINGS_TI_DRV260X_H 19 + #define _DT_BINDINGS_TI_DRV260X_H 20 + 21 + /* Calibration Types */ 22 + #define DRV260X_LRA_MODE 0x00 23 + #define DRV260X_LRA_NO_CAL_MODE 0x01 24 + #define DRV260X_ERM_MODE 0x02 25 + 26 + /* Library Selection */ 27 + #define DRV260X_LIB_EMPTY 0x00 28 + #define DRV260X_ERM_LIB_A 0x01 29 + #define DRV260X_ERM_LIB_B 0x02 30 + #define DRV260X_ERM_LIB_C 0x03 31 + #define DRV260X_ERM_LIB_D 0x04 32 + #define DRV260X_ERM_LIB_E 0x05 33 + #define DRV260X_LIB_LRA 0x06 34 + #define DRV260X_ERM_LIB_F 0x07 35 + 36 + #endif
+9
include/linux/mfd/max77693-private.h
··· 251 251 MAX77693_HAPTIC_REG_END, 252 252 }; 253 253 254 + /* max77693-pmic LSCNFG configuraton register */ 255 + #define MAX77693_PMIC_LOW_SYS_MASK 0x80 256 + #define MAX77693_PMIC_LOW_SYS_SHIFT 7 257 + 258 + /* max77693-haptic configuration register */ 259 + #define MAX77693_CONFIG2_MODE 7 260 + #define MAX77693_CONFIG2_MEN 6 261 + #define MAX77693_CONFIG2_HTYP 5 262 + 254 263 enum max77693_irq_source { 255 264 LED_INT = 0, 256 265 TOPSYS_INT,
+28
include/linux/platform_data/drv260x-pdata.h
··· 1 + /* 2 + * Platform data for DRV260X haptics driver family 3 + * 4 + * Author: Dan Murphy <dmurphy@ti.com> 5 + * 6 + * Copyright: (C) 2014 Texas Instruments, Inc. 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 + * This program is distributed in the hope that it will be useful, but 13 + * WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + */ 17 + 18 + #ifndef _LINUX_DRV260X_PDATA_H 19 + #define _LINUX_DRV260X_PDATA_H 20 + 21 + struct drv260x_platform_data { 22 + u32 library_selection; 23 + u32 mode; 24 + u32 vib_rated_voltage; 25 + u32 vib_overdrive_voltage; 26 + }; 27 + 28 + #endif