diff options
105 files changed, 4793 insertions, 512 deletions
diff --git a/Documentation/devicetree/bindings/input/pxa27x-keypad.txt b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt new file mode 100644 index 000000000000..f8674f7e5ea5 --- /dev/null +++ b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt | |||
@@ -0,0 +1,60 @@ | |||
1 | * Marvell PXA Keypad controller | ||
2 | |||
3 | Required Properties | ||
4 | - compatible : should be "marvell,pxa27x-keypad" | ||
5 | - reg : Address and length of the register set for the device | ||
6 | - interrupts : The interrupt for the keypad controller | ||
7 | - marvell,debounce-interval : How long time the key will be | ||
8 | recognized when it is pressed. It is a u32 value, and bit[31:16] | ||
9 | is debounce interval for direct key and bit[15:0] is debounce | ||
10 | interval for matrix key. The value is in binary number of 2ms | ||
11 | |||
12 | Optional Properties For Matrix Keyes | ||
13 | Please refer to matrix-keymap.txt | ||
14 | |||
15 | Optional Properties for Direct Keyes | ||
16 | - marvell,direct-key-count : How many direct keyes are used. | ||
17 | - marvell,direct-key-mask : The mask indicates which keyes | ||
18 | are used. If bit[X] of the mask is set, the direct key X | ||
19 | is used. | ||
20 | - marvell,direct-key-low-active : Direct key status register | ||
21 | tells the level of pins that connects to the direct keyes. | ||
22 | When this property is set, it means that when the pin level | ||
23 | is low, the key is pressed(active). | ||
24 | - marvell,direct-key-map : It is a u16 array. Each item indicates | ||
25 | the linux key-code for the direct key. | ||
26 | |||
27 | Optional Properties For Rotary | ||
28 | - marvell,rotary0 : It is a u32 value. Bit[31:16] is the | ||
29 | linux key-code for rotary up. Bit[15:0] is the linux key-code | ||
30 | for rotary down. It is for rotary 0. | ||
31 | - marvell,rotary1 : Same as marvell,rotary0. It is for rotary 1. | ||
32 | - marvell,rotary-rel-key : When rotary is used for relative axes | ||
33 | in the device, the value indicates the key-code for relative | ||
34 | axes measurement in the device. It is a u32 value. Bit[31:16] | ||
35 | is for rotary 1, and Bit[15:0] is for rotary 0. | ||
36 | |||
37 | Examples: | ||
38 | keypad: keypad@d4012000 { | ||
39 | keypad,num-rows = <3>; | ||
40 | keypad,num-columns = <5>; | ||
41 | linux,keymap = <0x0000000e /* KEY_BACKSPACE */ | ||
42 | 0x0001006b /* KEY_END */ | ||
43 | 0x00020061 /* KEY_RIGHTCTRL */ | ||
44 | 0x0003000b /* KEY_0 */ | ||
45 | 0x00040002 /* KEY_1 */ | ||
46 | 0x0100008b /* KEY_MENU */ | ||
47 | 0x01010066 /* KEY_HOME */ | ||
48 | 0x010200e7 /* KEY_SEND */ | ||
49 | 0x01030009 /* KEY_8 */ | ||
50 | 0x0104000a /* KEY_9 */ | ||
51 | 0x02000160 /* KEY_OK */ | ||
52 | 0x02010003 /* KEY_2 */ | ||
53 | 0x02020004 /* KEY_3 */ | ||
54 | 0x02030005 /* KEY_4 */ | ||
55 | 0x02040006>; /* KEY_5 */ | ||
56 | marvell,rotary0 = <0x006c0067>; /* KEY_UP & KEY_DOWN */ | ||
57 | marvell,direct-key-count = <1>; | ||
58 | marvell,direct-key-map = <0x001c>; | ||
59 | marvell,debounce-interval = <0x001e001e>; | ||
60 | }; | ||
diff --git a/Documentation/devicetree/bindings/input/samsung-keypad.txt b/Documentation/devicetree/bindings/input/samsung-keypad.txt index ce3e394c0e64..942d071baaa5 100644 --- a/Documentation/devicetree/bindings/input/samsung-keypad.txt +++ b/Documentation/devicetree/bindings/input/samsung-keypad.txt | |||
@@ -25,14 +25,6 @@ Required Board Specific Properties: | |||
25 | - samsung,keypad-num-columns: Number of column lines connected to the | 25 | - samsung,keypad-num-columns: Number of column lines connected to the |
26 | keypad controller. | 26 | keypad controller. |
27 | 27 | ||
28 | - row-gpios: List of gpios used as row lines. The gpio specifier for | ||
29 | this property depends on the gpio controller to which these row lines | ||
30 | are connected. | ||
31 | |||
32 | - col-gpios: List of gpios used as column lines. The gpio specifier for | ||
33 | this property depends on the gpio controller to which these column | ||
34 | lines are connected. | ||
35 | |||
36 | - Keys represented as child nodes: Each key connected to the keypad | 28 | - Keys represented as child nodes: Each key connected to the keypad |
37 | controller is represented as a child node to the keypad controller | 29 | controller is represented as a child node to the keypad controller |
38 | device node and should include the following properties. | 30 | device node and should include the following properties. |
@@ -41,6 +33,9 @@ Required Board Specific Properties: | |||
41 | - linux,code: the key-code to be reported when the key is pressed | 33 | - linux,code: the key-code to be reported when the key is pressed |
42 | and released. | 34 | and released. |
43 | 35 | ||
36 | - pinctrl-0: Should specify pin control groups used for this controller. | ||
37 | - pinctrl-names: Should contain only one value - "default". | ||
38 | |||
44 | Optional Properties specific to linux: | 39 | Optional Properties specific to linux: |
45 | - linux,keypad-no-autorepeat: do no enable autorepeat feature. | 40 | - linux,keypad-no-autorepeat: do no enable autorepeat feature. |
46 | - linux,keypad-wakeup: use any event on keypad as wakeup event. | 41 | - linux,keypad-wakeup: use any event on keypad as wakeup event. |
@@ -56,17 +51,8 @@ Example: | |||
56 | linux,input-no-autorepeat; | 51 | linux,input-no-autorepeat; |
57 | linux,input-wakeup; | 52 | linux,input-wakeup; |
58 | 53 | ||
59 | row-gpios = <&gpx2 0 3 3 0 | 54 | pinctrl-names = "default"; |
60 | &gpx2 1 3 3 0>; | 55 | pinctrl-0 = <&keypad_rows &keypad_columns>; |
61 | |||
62 | col-gpios = <&gpx1 0 3 0 0 | ||
63 | &gpx1 1 3 0 0 | ||
64 | &gpx1 2 3 0 0 | ||
65 | &gpx1 3 3 0 0 | ||
66 | &gpx1 4 3 0 0 | ||
67 | &gpx1 5 3 0 0 | ||
68 | &gpx1 6 3 0 0 | ||
69 | &gpx1 7 3 0 0>; | ||
70 | 56 | ||
71 | key_1 { | 57 | key_1 { |
72 | keypad,row = <0>; | 58 | keypad,row = <0>; |
diff --git a/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt b/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt new file mode 100644 index 000000000000..513d94d6e899 --- /dev/null +++ b/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt | |||
@@ -0,0 +1,60 @@ | |||
1 | TI-NSPIRE Keypad | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Compatible property value should be "ti,nspire-keypad". | ||
5 | |||
6 | - reg: Physical base address of the peripheral and length of memory mapped | ||
7 | region. | ||
8 | |||
9 | - interrupts: The interrupt number for the peripheral. | ||
10 | |||
11 | - scan-interval: How often to scan in us. Based on a APB speed of 33MHz, the | ||
12 | maximum and minimum delay time is ~2000us and ~500us respectively | ||
13 | |||
14 | - row-delay: How long to wait before scanning each row. | ||
15 | |||
16 | - clocks: The clock this peripheral is attached to. | ||
17 | |||
18 | - linux,keymap: The keymap to use | ||
19 | (see Documentation/devicetree/bindings/input/matrix-keymap.txt) | ||
20 | |||
21 | Optional properties: | ||
22 | - active-low: Specify that the keypad is active low (i.e. logical low signifies | ||
23 | a key press). | ||
24 | |||
25 | Example: | ||
26 | |||
27 | input { | ||
28 | compatible = "ti,nspire-keypad"; | ||
29 | reg = <0x900E0000 0x1000>; | ||
30 | interrupts = <16>; | ||
31 | |||
32 | scan-interval = <1000>; | ||
33 | row-delay = <200>; | ||
34 | |||
35 | clocks = <&apb_pclk>; | ||
36 | |||
37 | linux,keymap = < | ||
38 | 0x0000001c 0x0001001c 0x00040039 | ||
39 | 0x0005002c 0x00060015 0x0007000b | ||
40 | 0x0008000f 0x0100002d 0x01010011 | ||
41 | 0x0102002f 0x01030004 0x01040016 | ||
42 | 0x01050014 0x0106001f 0x01070002 | ||
43 | 0x010a006a 0x02000013 0x02010010 | ||
44 | 0x02020019 0x02030007 0x02040018 | ||
45 | 0x02050031 0x02060032 0x02070005 | ||
46 | 0x02080028 0x0209006c 0x03000026 | ||
47 | 0x03010025 0x03020024 0x0303000a | ||
48 | 0x03040017 0x03050023 0x03060022 | ||
49 | 0x03070008 0x03080035 0x03090069 | ||
50 | 0x04000021 0x04010012 0x04020020 | ||
51 | 0x0404002e 0x04050030 0x0406001e | ||
52 | 0x0407000d 0x04080037 0x04090067 | ||
53 | 0x05010038 0x0502000c 0x0503001b | ||
54 | 0x05040034 0x0505001a 0x05060006 | ||
55 | 0x05080027 0x0509000e 0x050a006f | ||
56 | 0x0600002b 0x0602004e 0x06030068 | ||
57 | 0x06040003 0x0605006d 0x06060009 | ||
58 | 0x06070001 0x0609000f 0x0708002a | ||
59 | 0x0709001d 0x070a0033 >; | ||
60 | }; | ||
diff --git a/Documentation/devicetree/bindings/serio/olpc,ap-sp.txt b/Documentation/devicetree/bindings/serio/olpc,ap-sp.txt new file mode 100644 index 000000000000..0e72183f52bc --- /dev/null +++ b/Documentation/devicetree/bindings/serio/olpc,ap-sp.txt | |||
@@ -0,0 +1,13 @@ | |||
1 | OLPC AP-SP serio interface | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "olpc,ap-sp" | ||
5 | - reg : base address and length of SoC's WTM registers | ||
6 | - interrupts : SP-AP interrupt | ||
7 | |||
8 | Example: | ||
9 | ap-sp@d4290000 { | ||
10 | compatible = "olpc,ap-sp"; | ||
11 | reg = <0xd4290000 0x1000>; | ||
12 | interrupts = <40>; | ||
13 | } | ||
diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt index 2c179613f81b..de139b18184a 100644 --- a/Documentation/input/multi-touch-protocol.txt +++ b/Documentation/input/multi-touch-protocol.txt | |||
@@ -80,6 +80,8 @@ Userspace can detect that a driver can report more total contacts than slots | |||
80 | by noting that the largest supported BTN_TOOL_*TAP event is larger than the | 80 | by noting that the largest supported BTN_TOOL_*TAP event is larger than the |
81 | total number of type B slots reported in the absinfo for the ABS_MT_SLOT axis. | 81 | total number of type B slots reported in the absinfo for the ABS_MT_SLOT axis. |
82 | 82 | ||
83 | The minimum value of the ABS_MT_SLOT axis must be 0. | ||
84 | |||
83 | Protocol Example A | 85 | Protocol Example A |
84 | ------------------ | 86 | ------------------ |
85 | 87 | ||
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 8a24b6c6339f..bea6793a7ede 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c | |||
@@ -985,7 +985,6 @@ static struct regulator_init_data tps65070_regulator_data[] = { | |||
985 | static struct touchscreen_init_data tps6507x_touchscreen_data = { | 985 | static struct touchscreen_init_data tps6507x_touchscreen_data = { |
986 | .poll_period = 30, /* ms between touch samples */ | 986 | .poll_period = 30, /* ms between touch samples */ |
987 | .min_pressure = 0x30, /* minimum pressure to trigger touch */ | 987 | .min_pressure = 0x30, /* minimum pressure to trigger touch */ |
988 | .vref = 0, /* turn off vref when not using A/D */ | ||
989 | .vendor = 0, /* /sys/class/input/input?/id/vendor */ | 988 | .vendor = 0, /* /sys/class/input/input?/id/vendor */ |
990 | .product = 65070, /* /sys/class/input/input?/id/product */ | 989 | .product = 65070, /* /sys/class/input/input?/id/product */ |
991 | .version = 0x100, /* /sys/class/input/input?/id/version */ | 990 | .version = 0x100, /* /sys/class/input/input?/id/version */ |
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index 5b660ec09ef5..0c002099c3a3 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c | |||
@@ -210,7 +210,7 @@ struct pxa168fb_mach_info aspenite_lcd_info = { | |||
210 | .invert_pixclock = 0, | 210 | .invert_pixclock = 0, |
211 | }; | 211 | }; |
212 | 212 | ||
213 | static unsigned int aspenite_matrix_key_map[] = { | 213 | static const unsigned int aspenite_matrix_key_map[] = { |
214 | KEY(0, 6, KEY_UP), /* SW 4 */ | 214 | KEY(0, 6, KEY_UP), /* SW 4 */ |
215 | KEY(0, 7, KEY_DOWN), /* SW 5 */ | 215 | KEY(0, 7, KEY_DOWN), /* SW 5 */ |
216 | KEY(1, 6, KEY_LEFT), /* SW 6 */ | 216 | KEY(1, 6, KEY_LEFT), /* SW 6 */ |
@@ -219,11 +219,15 @@ static unsigned int aspenite_matrix_key_map[] = { | |||
219 | KEY(4, 7, KEY_ESC), /* SW 9 */ | 219 | KEY(4, 7, KEY_ESC), /* SW 9 */ |
220 | }; | 220 | }; |
221 | 221 | ||
222 | static struct matrix_keymap_data aspenite_matrix_keymap_data = { | ||
223 | .keymap = aspenite_matrix_key_map, | ||
224 | .keymap_size = ARRAY_SIZE(aspenite_matrix_key_map), | ||
225 | }; | ||
226 | |||
222 | static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = { | 227 | static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = { |
223 | .matrix_key_rows = 5, | 228 | .matrix_key_rows = 5, |
224 | .matrix_key_cols = 8, | 229 | .matrix_key_cols = 8, |
225 | .matrix_key_map = aspenite_matrix_key_map, | 230 | .matrix_keymap_data = &aspenite_matrix_keymap_data, |
226 | .matrix_key_map_size = ARRAY_SIZE(aspenite_matrix_key_map), | ||
227 | .debounce_interval = 30, | 231 | .debounce_interval = 30, |
228 | }; | 232 | }; |
229 | 233 | ||
diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c index e4d95b4c6bb2..6aa53fb29d26 100644 --- a/arch/arm/mach-mmp/teton_bga.c +++ b/arch/arm/mach-mmp/teton_bga.c | |||
@@ -61,11 +61,15 @@ static unsigned int teton_bga_matrix_key_map[] = { | |||
61 | KEY(1, 7, KEY_RIGHT), | 61 | KEY(1, 7, KEY_RIGHT), |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static struct matrix_keymap_data teton_bga_matrix_keymap_data = { | ||
65 | .keymap = teton_bga_matrix_key_map, | ||
66 | .keymap_size = ARRAY_SIZE(teton_bga_matrix_key_map), | ||
67 | }; | ||
68 | |||
64 | static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = { | 69 | static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = { |
65 | .matrix_key_rows = 2, | 70 | .matrix_key_rows = 2, |
66 | .matrix_key_cols = 8, | 71 | .matrix_key_cols = 8, |
67 | .matrix_key_map = teton_bga_matrix_key_map, | 72 | .matrix_keymap_data = &teton_bga_matrix_keymap_data, |
68 | .matrix_key_map_size = ARRAY_SIZE(teton_bga_matrix_key_map), | ||
69 | .debounce_interval = 30, | 73 | .debounce_interval = 30, |
70 | }; | 74 | }; |
71 | 75 | ||
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 446563a7d1ad..f6726bb4eb95 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c | |||
@@ -833,21 +833,25 @@ static inline void em_x270_init_ac97(void) {} | |||
833 | #endif | 833 | #endif |
834 | 834 | ||
835 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 835 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
836 | static unsigned int em_x270_module_matrix_keys[] = { | 836 | static const unsigned int em_x270_module_matrix_keys[] = { |
837 | KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B), | 837 | KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B), |
838 | KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT), | 838 | KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT), |
839 | KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D), | 839 | KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D), |
840 | }; | 840 | }; |
841 | 841 | ||
842 | static struct matrix_keymap_data em_x270_matrix_keymap_data = { | ||
843 | .keymap = em_x270_module_matrix_keys, | ||
844 | .keymap_size = ARRAY_SIZE(em_x270_module_matrix_keys), | ||
845 | }; | ||
846 | |||
842 | struct pxa27x_keypad_platform_data em_x270_module_keypad_info = { | 847 | struct pxa27x_keypad_platform_data em_x270_module_keypad_info = { |
843 | /* code map for the matrix keys */ | 848 | /* code map for the matrix keys */ |
844 | .matrix_key_rows = 3, | 849 | .matrix_key_rows = 3, |
845 | .matrix_key_cols = 3, | 850 | .matrix_key_cols = 3, |
846 | .matrix_key_map = em_x270_module_matrix_keys, | 851 | .matrix_keymap_data = &em_x270_matrix_keymap_data, |
847 | .matrix_key_map_size = ARRAY_SIZE(em_x270_module_matrix_keys), | ||
848 | }; | 852 | }; |
849 | 853 | ||
850 | static unsigned int em_x270_exeda_matrix_keys[] = { | 854 | static const unsigned int em_x270_exeda_matrix_keys[] = { |
851 | KEY(0, 0, KEY_RIGHTSHIFT), KEY(0, 1, KEY_RIGHTCTRL), | 855 | KEY(0, 0, KEY_RIGHTSHIFT), KEY(0, 1, KEY_RIGHTCTRL), |
852 | KEY(0, 2, KEY_RIGHTALT), KEY(0, 3, KEY_SPACE), | 856 | KEY(0, 2, KEY_RIGHTALT), KEY(0, 3, KEY_SPACE), |
853 | KEY(0, 4, KEY_LEFTALT), KEY(0, 5, KEY_LEFTCTRL), | 857 | KEY(0, 4, KEY_LEFTALT), KEY(0, 5, KEY_LEFTCTRL), |
@@ -889,12 +893,16 @@ static unsigned int em_x270_exeda_matrix_keys[] = { | |||
889 | KEY(7, 6, 0), KEY(7, 7, 0), | 893 | KEY(7, 6, 0), KEY(7, 7, 0), |
890 | }; | 894 | }; |
891 | 895 | ||
896 | static struct matrix_keymap_data em_x270_exeda_matrix_keymap_data = { | ||
897 | .keymap = em_x270_exeda_matrix_keys, | ||
898 | .keymap_size = ARRAY_SIZE(em_x270_exeda_matrix_keys), | ||
899 | }; | ||
900 | |||
892 | struct pxa27x_keypad_platform_data em_x270_exeda_keypad_info = { | 901 | struct pxa27x_keypad_platform_data em_x270_exeda_keypad_info = { |
893 | /* code map for the matrix keys */ | 902 | /* code map for the matrix keys */ |
894 | .matrix_key_rows = 8, | 903 | .matrix_key_rows = 8, |
895 | .matrix_key_cols = 8, | 904 | .matrix_key_cols = 8, |
896 | .matrix_key_map = em_x270_exeda_matrix_keys, | 905 | .matrix_keymap_data = &em_x270_exeda_matrix_keymap_data, |
897 | .matrix_key_map_size = ARRAY_SIZE(em_x270_exeda_matrix_keys), | ||
898 | }; | 906 | }; |
899 | 907 | ||
900 | static void __init em_x270_init_keypad(void) | 908 | static void __init em_x270_init_keypad(void) |
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c index dca10709be8f..fe2eb8394dff 100644 --- a/arch/arm/mach-pxa/ezx.c +++ b/arch/arm/mach-pxa/ezx.c | |||
@@ -392,7 +392,7 @@ static unsigned long e6_pin_config[] __initdata = { | |||
392 | 392 | ||
393 | /* KEYPAD */ | 393 | /* KEYPAD */ |
394 | #ifdef CONFIG_MACH_EZX_A780 | 394 | #ifdef CONFIG_MACH_EZX_A780 |
395 | static unsigned int a780_key_map[] = { | 395 | static const unsigned int a780_key_map[] = { |
396 | KEY(0, 0, KEY_SEND), | 396 | KEY(0, 0, KEY_SEND), |
397 | KEY(0, 1, KEY_BACK), | 397 | KEY(0, 1, KEY_BACK), |
398 | KEY(0, 2, KEY_END), | 398 | KEY(0, 2, KEY_END), |
@@ -424,11 +424,15 @@ static unsigned int a780_key_map[] = { | |||
424 | KEY(4, 4, KEY_DOWN), | 424 | KEY(4, 4, KEY_DOWN), |
425 | }; | 425 | }; |
426 | 426 | ||
427 | static struct matrix_keymap_data a780_matrix_keymap_data = { | ||
428 | .keymap = a780_key_map, | ||
429 | .keymap_size = ARRAY_SIZE(a780_key_map), | ||
430 | }; | ||
431 | |||
427 | static struct pxa27x_keypad_platform_data a780_keypad_platform_data = { | 432 | static struct pxa27x_keypad_platform_data a780_keypad_platform_data = { |
428 | .matrix_key_rows = 5, | 433 | .matrix_key_rows = 5, |
429 | .matrix_key_cols = 5, | 434 | .matrix_key_cols = 5, |
430 | .matrix_key_map = a780_key_map, | 435 | .matrix_keymap_data = &a780_matrix_keymap_data, |
431 | .matrix_key_map_size = ARRAY_SIZE(a780_key_map), | ||
432 | 436 | ||
433 | .direct_key_map = { KEY_CAMERA }, | 437 | .direct_key_map = { KEY_CAMERA }, |
434 | .direct_key_num = 1, | 438 | .direct_key_num = 1, |
@@ -438,7 +442,7 @@ static struct pxa27x_keypad_platform_data a780_keypad_platform_data = { | |||
438 | #endif /* CONFIG_MACH_EZX_A780 */ | 442 | #endif /* CONFIG_MACH_EZX_A780 */ |
439 | 443 | ||
440 | #ifdef CONFIG_MACH_EZX_E680 | 444 | #ifdef CONFIG_MACH_EZX_E680 |
441 | static unsigned int e680_key_map[] = { | 445 | static const unsigned int e680_key_map[] = { |
442 | KEY(0, 0, KEY_UP), | 446 | KEY(0, 0, KEY_UP), |
443 | KEY(0, 1, KEY_RIGHT), | 447 | KEY(0, 1, KEY_RIGHT), |
444 | KEY(0, 2, KEY_RESERVED), | 448 | KEY(0, 2, KEY_RESERVED), |
@@ -455,11 +459,15 @@ static unsigned int e680_key_map[] = { | |||
455 | KEY(2, 3, KEY_KPENTER), | 459 | KEY(2, 3, KEY_KPENTER), |
456 | }; | 460 | }; |
457 | 461 | ||
462 | static struct matrix_keymap_data e680_matrix_keymap_data = { | ||
463 | .keymap = e680_key_map, | ||
464 | .keymap_size = ARRAY_SIZE(e680_key_map), | ||
465 | }; | ||
466 | |||
458 | static struct pxa27x_keypad_platform_data e680_keypad_platform_data = { | 467 | static struct pxa27x_keypad_platform_data e680_keypad_platform_data = { |
459 | .matrix_key_rows = 3, | 468 | .matrix_key_rows = 3, |
460 | .matrix_key_cols = 4, | 469 | .matrix_key_cols = 4, |
461 | .matrix_key_map = e680_key_map, | 470 | .matrix_keymap_data = &e680_matrix_keymap_data, |
462 | .matrix_key_map_size = ARRAY_SIZE(e680_key_map), | ||
463 | 471 | ||
464 | .direct_key_map = { | 472 | .direct_key_map = { |
465 | KEY_CAMERA, | 473 | KEY_CAMERA, |
@@ -476,7 +484,7 @@ static struct pxa27x_keypad_platform_data e680_keypad_platform_data = { | |||
476 | #endif /* CONFIG_MACH_EZX_E680 */ | 484 | #endif /* CONFIG_MACH_EZX_E680 */ |
477 | 485 | ||
478 | #ifdef CONFIG_MACH_EZX_A1200 | 486 | #ifdef CONFIG_MACH_EZX_A1200 |
479 | static unsigned int a1200_key_map[] = { | 487 | static const unsigned int a1200_key_map[] = { |
480 | KEY(0, 0, KEY_RESERVED), | 488 | KEY(0, 0, KEY_RESERVED), |
481 | KEY(0, 1, KEY_RIGHT), | 489 | KEY(0, 1, KEY_RIGHT), |
482 | KEY(0, 2, KEY_PAGEDOWN), | 490 | KEY(0, 2, KEY_PAGEDOWN), |
@@ -513,18 +521,22 @@ static unsigned int a1200_key_map[] = { | |||
513 | KEY(4, 5, KEY_RESERVED), | 521 | KEY(4, 5, KEY_RESERVED), |
514 | }; | 522 | }; |
515 | 523 | ||
524 | static struct matrix_keymap_data a1200_matrix_keymap_data = { | ||
525 | .keymap = a1200_key_map, | ||
526 | .keymap_size = ARRAY_SIZE(a1200_key_map), | ||
527 | }; | ||
528 | |||
516 | static struct pxa27x_keypad_platform_data a1200_keypad_platform_data = { | 529 | static struct pxa27x_keypad_platform_data a1200_keypad_platform_data = { |
517 | .matrix_key_rows = 5, | 530 | .matrix_key_rows = 5, |
518 | .matrix_key_cols = 6, | 531 | .matrix_key_cols = 6, |
519 | .matrix_key_map = a1200_key_map, | 532 | .matrix_keymap_data = &a1200_matrix_keymap_data, |
520 | .matrix_key_map_size = ARRAY_SIZE(a1200_key_map), | ||
521 | 533 | ||
522 | .debounce_interval = 30, | 534 | .debounce_interval = 30, |
523 | }; | 535 | }; |
524 | #endif /* CONFIG_MACH_EZX_A1200 */ | 536 | #endif /* CONFIG_MACH_EZX_A1200 */ |
525 | 537 | ||
526 | #ifdef CONFIG_MACH_EZX_E6 | 538 | #ifdef CONFIG_MACH_EZX_E6 |
527 | static unsigned int e6_key_map[] = { | 539 | static const unsigned int e6_key_map[] = { |
528 | KEY(0, 0, KEY_RESERVED), | 540 | KEY(0, 0, KEY_RESERVED), |
529 | KEY(0, 1, KEY_RIGHT), | 541 | KEY(0, 1, KEY_RIGHT), |
530 | KEY(0, 2, KEY_PAGEDOWN), | 542 | KEY(0, 2, KEY_PAGEDOWN), |
@@ -561,18 +573,22 @@ static unsigned int e6_key_map[] = { | |||
561 | KEY(4, 5, KEY_PREVIOUSSONG), | 573 | KEY(4, 5, KEY_PREVIOUSSONG), |
562 | }; | 574 | }; |
563 | 575 | ||
576 | static struct matrix_keymap_data e6_keymap_data = { | ||
577 | .keymap = e6_key_map, | ||
578 | .keymap_size = ARRAY_SIZE(e6_key_map), | ||
579 | }; | ||
580 | |||
564 | static struct pxa27x_keypad_platform_data e6_keypad_platform_data = { | 581 | static struct pxa27x_keypad_platform_data e6_keypad_platform_data = { |
565 | .matrix_key_rows = 5, | 582 | .matrix_key_rows = 5, |
566 | .matrix_key_cols = 6, | 583 | .matrix_key_cols = 6, |
567 | .matrix_key_map = e6_key_map, | 584 | .matrix_keymap_data = &e6_keymap_data, |
568 | .matrix_key_map_size = ARRAY_SIZE(e6_key_map), | ||
569 | 585 | ||
570 | .debounce_interval = 30, | 586 | .debounce_interval = 30, |
571 | }; | 587 | }; |
572 | #endif /* CONFIG_MACH_EZX_E6 */ | 588 | #endif /* CONFIG_MACH_EZX_E6 */ |
573 | 589 | ||
574 | #ifdef CONFIG_MACH_EZX_A910 | 590 | #ifdef CONFIG_MACH_EZX_A910 |
575 | static unsigned int a910_key_map[] = { | 591 | static const unsigned int a910_key_map[] = { |
576 | KEY(0, 0, KEY_NUMERIC_6), | 592 | KEY(0, 0, KEY_NUMERIC_6), |
577 | KEY(0, 1, KEY_RIGHT), | 593 | KEY(0, 1, KEY_RIGHT), |
578 | KEY(0, 2, KEY_PAGEDOWN), | 594 | KEY(0, 2, KEY_PAGEDOWN), |
@@ -609,18 +625,22 @@ static unsigned int a910_key_map[] = { | |||
609 | KEY(4, 5, KEY_RESERVED), | 625 | KEY(4, 5, KEY_RESERVED), |
610 | }; | 626 | }; |
611 | 627 | ||
628 | static struct matrix_keymap_data a910_matrix_keymap_data = { | ||
629 | .keymap = a910_key_map, | ||
630 | .keymap_size = ARRAY_SIZE(a910_key_map), | ||
631 | }; | ||
632 | |||
612 | static struct pxa27x_keypad_platform_data a910_keypad_platform_data = { | 633 | static struct pxa27x_keypad_platform_data a910_keypad_platform_data = { |
613 | .matrix_key_rows = 5, | 634 | .matrix_key_rows = 5, |
614 | .matrix_key_cols = 6, | 635 | .matrix_key_cols = 6, |
615 | .matrix_key_map = a910_key_map, | 636 | .matrix_keymap_data = &a910_matrix_keymap_data, |
616 | .matrix_key_map_size = ARRAY_SIZE(a910_key_map), | ||
617 | 637 | ||
618 | .debounce_interval = 30, | 638 | .debounce_interval = 30, |
619 | }; | 639 | }; |
620 | #endif /* CONFIG_MACH_EZX_A910 */ | 640 | #endif /* CONFIG_MACH_EZX_A910 */ |
621 | 641 | ||
622 | #ifdef CONFIG_MACH_EZX_E2 | 642 | #ifdef CONFIG_MACH_EZX_E2 |
623 | static unsigned int e2_key_map[] = { | 643 | static const unsigned int e2_key_map[] = { |
624 | KEY(0, 0, KEY_NUMERIC_6), | 644 | KEY(0, 0, KEY_NUMERIC_6), |
625 | KEY(0, 1, KEY_RIGHT), | 645 | KEY(0, 1, KEY_RIGHT), |
626 | KEY(0, 2, KEY_NUMERIC_9), | 646 | KEY(0, 2, KEY_NUMERIC_9), |
@@ -657,11 +677,15 @@ static unsigned int e2_key_map[] = { | |||
657 | KEY(4, 5, KEY_RESERVED), | 677 | KEY(4, 5, KEY_RESERVED), |
658 | }; | 678 | }; |
659 | 679 | ||
680 | static struct matrix_keymap_data e2_matrix_keymap_data = { | ||
681 | .keymap = e2_key_map, | ||
682 | .keymap_size = ARRAY_SIZE(e2_key_map), | ||
683 | }; | ||
684 | |||
660 | static struct pxa27x_keypad_platform_data e2_keypad_platform_data = { | 685 | static struct pxa27x_keypad_platform_data e2_keypad_platform_data = { |
661 | .matrix_key_rows = 5, | 686 | .matrix_key_rows = 5, |
662 | .matrix_key_cols = 6, | 687 | .matrix_key_cols = 6, |
663 | .matrix_key_map = e2_key_map, | 688 | .matrix_keymap_data = &e2_matrix_keymap_data, |
664 | .matrix_key_map_size = ARRAY_SIZE(e2_key_map), | ||
665 | 689 | ||
666 | .debounce_interval = 30, | 690 | .debounce_interval = 30, |
667 | }; | 691 | }; |
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index e848c4607baf..5d665588c7eb 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c | |||
@@ -222,7 +222,7 @@ static inline void littleton_init_spi(void) {} | |||
222 | #endif | 222 | #endif |
223 | 223 | ||
224 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 224 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
225 | static unsigned int littleton_matrix_key_map[] = { | 225 | static const unsigned int littleton_matrix_key_map[] = { |
226 | /* KEY(row, col, key_code) */ | 226 | /* KEY(row, col, key_code) */ |
227 | KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3), | 227 | KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3), |
228 | KEY(0, 1, KEY_4), KEY(1, 1, KEY_5), KEY(2, 1, KEY_6), KEY(0, 2, KEY_7), | 228 | KEY(0, 1, KEY_4), KEY(1, 1, KEY_5), KEY(2, 1, KEY_6), KEY(0, 2, KEY_7), |
@@ -249,11 +249,15 @@ static unsigned int littleton_matrix_key_map[] = { | |||
249 | KEY(3, 1, KEY_F23), /* soft2 */ | 249 | KEY(3, 1, KEY_F23), /* soft2 */ |
250 | }; | 250 | }; |
251 | 251 | ||
252 | static struct matrix_keymap_data littleton_matrix_keymap_data = { | ||
253 | .keymap = littleton_matrix_key_map, | ||
254 | .keymap_size = ARRAY_SIZE(littleton_matrix_key_map), | ||
255 | }; | ||
256 | |||
252 | static struct pxa27x_keypad_platform_data littleton_keypad_info = { | 257 | static struct pxa27x_keypad_platform_data littleton_keypad_info = { |
253 | .matrix_key_rows = 6, | 258 | .matrix_key_rows = 6, |
254 | .matrix_key_cols = 5, | 259 | .matrix_key_cols = 5, |
255 | .matrix_key_map = littleton_matrix_key_map, | 260 | .matrix_keymap_data = &littleton_matrix_keymap_data, |
256 | .matrix_key_map_size = ARRAY_SIZE(littleton_matrix_key_map), | ||
257 | 261 | ||
258 | .enable_rotary0 = 1, | 262 | .enable_rotary0 = 1, |
259 | .rotary0_up_key = KEY_UP, | 263 | .rotary0_up_key = KEY_UP, |
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 7a12c1ba90ff..d2c652318376 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c | |||
@@ -498,7 +498,7 @@ static struct pxaohci_platform_data mainstone_ohci_platform_data = { | |||
498 | }; | 498 | }; |
499 | 499 | ||
500 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 500 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
501 | static unsigned int mainstone_matrix_keys[] = { | 501 | static const unsigned int mainstone_matrix_keys[] = { |
502 | KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C), | 502 | KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C), |
503 | KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F), | 503 | KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F), |
504 | KEY(0, 1, KEY_G), KEY(1, 1, KEY_H), KEY(2, 1, KEY_I), | 504 | KEY(0, 1, KEY_G), KEY(1, 1, KEY_H), KEY(2, 1, KEY_I), |
@@ -527,11 +527,15 @@ static unsigned int mainstone_matrix_keys[] = { | |||
527 | KEY(4, 6, KEY_SELECT), | 527 | KEY(4, 6, KEY_SELECT), |
528 | }; | 528 | }; |
529 | 529 | ||
530 | static struct matrix_keymap_data mainstone_matrix_keymap_data = { | ||
531 | .keymap = mainstone_matrix_keys, | ||
532 | .keymap_size = ARRAY_SIZE(mainstone_matrix_keys), | ||
533 | }; | ||
534 | |||
530 | struct pxa27x_keypad_platform_data mainstone_keypad_info = { | 535 | struct pxa27x_keypad_platform_data mainstone_keypad_info = { |
531 | .matrix_key_rows = 6, | 536 | .matrix_key_rows = 6, |
532 | .matrix_key_cols = 7, | 537 | .matrix_key_cols = 7, |
533 | .matrix_key_map = mainstone_matrix_keys, | 538 | .matrix_keymap_data = &mainstone_matrix_keymap_data, |
534 | .matrix_key_map_size = ARRAY_SIZE(mainstone_matrix_keys), | ||
535 | 539 | ||
536 | .enable_rotary0 = 1, | 540 | .enable_rotary0 = 1, |
537 | .rotary0_up_key = KEY_UP, | 541 | .rotary0_up_key = KEY_UP, |
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index f8979b943cbf..654b0ac84dea 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c | |||
@@ -222,7 +222,7 @@ static struct pxafb_mach_info mioa701_pxafb_info = { | |||
222 | /* | 222 | /* |
223 | * Keyboard configuration | 223 | * Keyboard configuration |
224 | */ | 224 | */ |
225 | static unsigned int mioa701_matrix_keys[] = { | 225 | static const unsigned int mioa701_matrix_keys[] = { |
226 | KEY(0, 0, KEY_UP), | 226 | KEY(0, 0, KEY_UP), |
227 | KEY(0, 1, KEY_RIGHT), | 227 | KEY(0, 1, KEY_RIGHT), |
228 | KEY(0, 2, KEY_MEDIA), | 228 | KEY(0, 2, KEY_MEDIA), |
@@ -233,11 +233,16 @@ static unsigned int mioa701_matrix_keys[] = { | |||
233 | KEY(2, 1, KEY_PHONE), /* Phone Green key */ | 233 | KEY(2, 1, KEY_PHONE), /* Phone Green key */ |
234 | KEY(2, 2, KEY_CAMERA) /* Camera key */ | 234 | KEY(2, 2, KEY_CAMERA) /* Camera key */ |
235 | }; | 235 | }; |
236 | |||
237 | static struct matrix_keymap_data mioa701_matrix_keymap_data = { | ||
238 | .keymap = mioa701_matrix_keys, | ||
239 | .keymap_size = ARRAY_SIZE(mioa701_matrix_keys), | ||
240 | }; | ||
241 | |||
236 | static struct pxa27x_keypad_platform_data mioa701_keypad_info = { | 242 | static struct pxa27x_keypad_platform_data mioa701_keypad_info = { |
237 | .matrix_key_rows = 3, | 243 | .matrix_key_rows = 3, |
238 | .matrix_key_cols = 3, | 244 | .matrix_key_cols = 3, |
239 | .matrix_key_map = mioa701_matrix_keys, | 245 | .matrix_keymap_data = &mioa701_matrix_keymap_data, |
240 | .matrix_key_map_size = ARRAY_SIZE(mioa701_matrix_keys), | ||
241 | }; | 246 | }; |
242 | 247 | ||
243 | /* | 248 | /* |
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c index 909b713e5789..cf210b11ffcc 100644 --- a/arch/arm/mach-pxa/palmld.c +++ b/arch/arm/mach-pxa/palmld.c | |||
@@ -173,7 +173,7 @@ static inline void palmld_nor_init(void) {} | |||
173 | * GPIO keyboard | 173 | * GPIO keyboard |
174 | ******************************************************************************/ | 174 | ******************************************************************************/ |
175 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 175 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
176 | static unsigned int palmld_matrix_keys[] = { | 176 | static const unsigned int palmld_matrix_keys[] = { |
177 | KEY(0, 1, KEY_F2), | 177 | KEY(0, 1, KEY_F2), |
178 | KEY(0, 2, KEY_UP), | 178 | KEY(0, 2, KEY_UP), |
179 | 179 | ||
@@ -190,11 +190,15 @@ static unsigned int palmld_matrix_keys[] = { | |||
190 | KEY(3, 2, KEY_LEFT), | 190 | KEY(3, 2, KEY_LEFT), |
191 | }; | 191 | }; |
192 | 192 | ||
193 | static struct matrix_keymap_data palmld_matrix_keymap_data = { | ||
194 | .keymap = palmld_matrix_keys, | ||
195 | .keymap_size = ARRAY_SIZE(palmld_matrix_keys), | ||
196 | }; | ||
197 | |||
193 | static struct pxa27x_keypad_platform_data palmld_keypad_platform_data = { | 198 | static struct pxa27x_keypad_platform_data palmld_keypad_platform_data = { |
194 | .matrix_key_rows = 4, | 199 | .matrix_key_rows = 4, |
195 | .matrix_key_cols = 3, | 200 | .matrix_key_cols = 3, |
196 | .matrix_key_map = palmld_matrix_keys, | 201 | .matrix_keymap_data = &palmld_matrix_keymap_data, |
197 | .matrix_key_map_size = ARRAY_SIZE(palmld_matrix_keys), | ||
198 | 202 | ||
199 | .debounce_interval = 30, | 203 | .debounce_interval = 30, |
200 | }; | 204 | }; |
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c index 5033fd07968f..3ed9b029428b 100644 --- a/arch/arm/mach-pxa/palmt5.c +++ b/arch/arm/mach-pxa/palmt5.c | |||
@@ -108,7 +108,7 @@ static unsigned long palmt5_pin_config[] __initdata = { | |||
108 | * GPIO keyboard | 108 | * GPIO keyboard |
109 | ******************************************************************************/ | 109 | ******************************************************************************/ |
110 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 110 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
111 | static unsigned int palmt5_matrix_keys[] = { | 111 | static const unsigned int palmt5_matrix_keys[] = { |
112 | KEY(0, 0, KEY_POWER), | 112 | KEY(0, 0, KEY_POWER), |
113 | KEY(0, 1, KEY_F1), | 113 | KEY(0, 1, KEY_F1), |
114 | KEY(0, 2, KEY_ENTER), | 114 | KEY(0, 2, KEY_ENTER), |
@@ -124,11 +124,15 @@ static unsigned int palmt5_matrix_keys[] = { | |||
124 | KEY(3, 2, KEY_LEFT), | 124 | KEY(3, 2, KEY_LEFT), |
125 | }; | 125 | }; |
126 | 126 | ||
127 | static struct matrix_keymap_data palmt5_matrix_keymap_data = { | ||
128 | .keymap = palmt5_matrix_keys, | ||
129 | .keymap_size = ARRAY_SIZE(palmt5_matrix_keys), | ||
130 | }; | ||
131 | |||
127 | static struct pxa27x_keypad_platform_data palmt5_keypad_platform_data = { | 132 | static struct pxa27x_keypad_platform_data palmt5_keypad_platform_data = { |
128 | .matrix_key_rows = 4, | 133 | .matrix_key_rows = 4, |
129 | .matrix_key_cols = 3, | 134 | .matrix_key_cols = 3, |
130 | .matrix_key_map = palmt5_matrix_keys, | 135 | .matrix_keymap_data = &palmt5_matrix_keymap_data, |
131 | .matrix_key_map_size = ARRAY_SIZE(palmt5_matrix_keys), | ||
132 | 136 | ||
133 | .debounce_interval = 30, | 137 | .debounce_interval = 30, |
134 | }; | 138 | }; |
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c index d82a50b4a803..d8b937c870de 100644 --- a/arch/arm/mach-pxa/palmtreo.c +++ b/arch/arm/mach-pxa/palmtreo.c | |||
@@ -168,7 +168,7 @@ static unsigned long centro685_pin_config[] __initdata = { | |||
168 | * GPIO keyboard | 168 | * GPIO keyboard |
169 | ******************************************************************************/ | 169 | ******************************************************************************/ |
170 | #if IS_ENABLED(CONFIG_KEYBOARD_PXA27x) | 170 | #if IS_ENABLED(CONFIG_KEYBOARD_PXA27x) |
171 | static unsigned int treo680_matrix_keys[] = { | 171 | static const unsigned int treo680_matrix_keys[] = { |
172 | KEY(0, 0, KEY_F8), /* Red/Off/Power */ | 172 | KEY(0, 0, KEY_F8), /* Red/Off/Power */ |
173 | KEY(0, 1, KEY_LEFT), | 173 | KEY(0, 1, KEY_LEFT), |
174 | KEY(0, 2, KEY_LEFTCTRL), /* Alternate */ | 174 | KEY(0, 2, KEY_LEFTCTRL), /* Alternate */ |
@@ -227,7 +227,7 @@ static unsigned int treo680_matrix_keys[] = { | |||
227 | KEY(7, 5, KEY_I), | 227 | KEY(7, 5, KEY_I), |
228 | }; | 228 | }; |
229 | 229 | ||
230 | static unsigned int centro_matrix_keys[] = { | 230 | static const unsigned int centro_matrix_keys[] = { |
231 | KEY(0, 0, KEY_F9), /* Home */ | 231 | KEY(0, 0, KEY_F9), /* Home */ |
232 | KEY(0, 1, KEY_LEFT), | 232 | KEY(0, 1, KEY_LEFT), |
233 | KEY(0, 2, KEY_LEFTCTRL), /* Alternate */ | 233 | KEY(0, 2, KEY_LEFTCTRL), /* Alternate */ |
@@ -286,11 +286,20 @@ static unsigned int centro_matrix_keys[] = { | |||
286 | KEY(7, 5, KEY_I), | 286 | KEY(7, 5, KEY_I), |
287 | }; | 287 | }; |
288 | 288 | ||
289 | static struct matrix_keymap_data treo680_matrix_keymap_data = { | ||
290 | .keymap = treo680_matrix_keys, | ||
291 | .keymap_size = ARRAY_SIZE(treo680_matrix_keys), | ||
292 | }; | ||
293 | |||
294 | static struct matrix_keymap_data centro_matrix_keymap_data = { | ||
295 | .keymap = centro_matrix_keys, | ||
296 | .keymap_size = ARRAY_SIZE(centro_matrix_keys), | ||
297 | }; | ||
298 | |||
289 | static struct pxa27x_keypad_platform_data treo680_keypad_pdata = { | 299 | static struct pxa27x_keypad_platform_data treo680_keypad_pdata = { |
290 | .matrix_key_rows = 8, | 300 | .matrix_key_rows = 8, |
291 | .matrix_key_cols = 7, | 301 | .matrix_key_cols = 7, |
292 | .matrix_key_map = treo680_matrix_keys, | 302 | .matrix_keymap_data = &treo680_matrix_keymap_data, |
293 | .matrix_key_map_size = ARRAY_SIZE(treo680_matrix_keys), | ||
294 | .direct_key_map = { KEY_CONNECT }, | 303 | .direct_key_map = { KEY_CONNECT }, |
295 | .direct_key_num = 1, | 304 | .direct_key_num = 1, |
296 | 305 | ||
@@ -301,10 +310,8 @@ static void __init palmtreo_kpc_init(void) | |||
301 | { | 310 | { |
302 | static struct pxa27x_keypad_platform_data *data = &treo680_keypad_pdata; | 311 | static struct pxa27x_keypad_platform_data *data = &treo680_keypad_pdata; |
303 | 312 | ||
304 | if (machine_is_centro()) { | 313 | if (machine_is_centro()) |
305 | data->matrix_key_map = centro_matrix_keys; | 314 | data->matrix_keymap_data = ¢ro_matrix_keymap_data; |
306 | data->matrix_key_map_size = ARRAY_SIZE(centro_matrix_keys); | ||
307 | } | ||
308 | 315 | ||
309 | pxa_set_keypad_info(&treo680_keypad_pdata); | 316 | pxa_set_keypad_info(&treo680_keypad_pdata); |
310 | } | 317 | } |
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index 627c93a7364c..83f830dd8ad8 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c | |||
@@ -176,7 +176,7 @@ static inline void palmtx_nor_init(void) {} | |||
176 | * GPIO keyboard | 176 | * GPIO keyboard |
177 | ******************************************************************************/ | 177 | ******************************************************************************/ |
178 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 178 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
179 | static unsigned int palmtx_matrix_keys[] = { | 179 | static const unsigned int palmtx_matrix_keys[] = { |
180 | KEY(0, 0, KEY_POWER), | 180 | KEY(0, 0, KEY_POWER), |
181 | KEY(0, 1, KEY_F1), | 181 | KEY(0, 1, KEY_F1), |
182 | KEY(0, 2, KEY_ENTER), | 182 | KEY(0, 2, KEY_ENTER), |
@@ -192,11 +192,15 @@ static unsigned int palmtx_matrix_keys[] = { | |||
192 | KEY(3, 2, KEY_LEFT), | 192 | KEY(3, 2, KEY_LEFT), |
193 | }; | 193 | }; |
194 | 194 | ||
195 | static struct matrix_keymap_data palmtx_matrix_keymap_data = { | ||
196 | .keymap = palmtx_matrix_keys, | ||
197 | .keymap_size = ARRAY_SIZE(palmtx_matrix_keys), | ||
198 | }; | ||
199 | |||
195 | static struct pxa27x_keypad_platform_data palmtx_keypad_platform_data = { | 200 | static struct pxa27x_keypad_platform_data palmtx_keypad_platform_data = { |
196 | .matrix_key_rows = 4, | 201 | .matrix_key_rows = 4, |
197 | .matrix_key_cols = 3, | 202 | .matrix_key_cols = 3, |
198 | .matrix_key_map = palmtx_matrix_keys, | 203 | .matrix_keymap_data = &palmtx_matrix_keymap_data, |
199 | .matrix_key_map_size = ARRAY_SIZE(palmtx_matrix_keys), | ||
200 | 204 | ||
201 | .debounce_interval = 30, | 205 | .debounce_interval = 30, |
202 | }; | 206 | }; |
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index 18b7fcd98592..1a35ddf218da 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c | |||
@@ -140,7 +140,7 @@ static unsigned long palmz72_pin_config[] __initdata = { | |||
140 | * GPIO keyboard | 140 | * GPIO keyboard |
141 | ******************************************************************************/ | 141 | ******************************************************************************/ |
142 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 142 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
143 | static unsigned int palmz72_matrix_keys[] = { | 143 | static const unsigned int palmz72_matrix_keys[] = { |
144 | KEY(0, 0, KEY_POWER), | 144 | KEY(0, 0, KEY_POWER), |
145 | KEY(0, 1, KEY_F1), | 145 | KEY(0, 1, KEY_F1), |
146 | KEY(0, 2, KEY_ENTER), | 146 | KEY(0, 2, KEY_ENTER), |
@@ -156,11 +156,15 @@ static unsigned int palmz72_matrix_keys[] = { | |||
156 | KEY(3, 2, KEY_LEFT), | 156 | KEY(3, 2, KEY_LEFT), |
157 | }; | 157 | }; |
158 | 158 | ||
159 | static struct matrix_keymap_data almz72_matrix_keymap_data = { | ||
160 | .keymap = palmz72_matrix_keys, | ||
161 | .keymap_size = ARRAY_SIZE(palmz72_matrix_keys), | ||
162 | }; | ||
163 | |||
159 | static struct pxa27x_keypad_platform_data palmz72_keypad_platform_data = { | 164 | static struct pxa27x_keypad_platform_data palmz72_keypad_platform_data = { |
160 | .matrix_key_rows = 4, | 165 | .matrix_key_rows = 4, |
161 | .matrix_key_cols = 3, | 166 | .matrix_key_cols = 3, |
162 | .matrix_key_map = palmz72_matrix_keys, | 167 | .matrix_keymap_data = &almz72_matrix_keymap_data, |
163 | .matrix_key_map_size = ARRAY_SIZE(palmz72_matrix_keys), | ||
164 | 168 | ||
165 | .debounce_interval = 30, | 169 | .debounce_interval = 30, |
166 | }; | 170 | }; |
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c index f55979c09a5f..4680efe55345 100644 --- a/arch/arm/mach-pxa/tavorevb.c +++ b/arch/arm/mach-pxa/tavorevb.c | |||
@@ -106,7 +106,7 @@ static struct platform_device smc91x_device = { | |||
106 | }; | 106 | }; |
107 | 107 | ||
108 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 108 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
109 | static unsigned int tavorevb_matrix_key_map[] = { | 109 | static const unsigned int tavorevb_matrix_key_map[] = { |
110 | /* KEY(row, col, key_code) */ | 110 | /* KEY(row, col, key_code) */ |
111 | KEY(0, 4, KEY_A), KEY(0, 5, KEY_B), KEY(0, 6, KEY_C), | 111 | KEY(0, 4, KEY_A), KEY(0, 5, KEY_B), KEY(0, 6, KEY_C), |
112 | KEY(1, 4, KEY_E), KEY(1, 5, KEY_F), KEY(1, 6, KEY_G), | 112 | KEY(1, 4, KEY_E), KEY(1, 5, KEY_F), KEY(1, 6, KEY_G), |
@@ -147,11 +147,15 @@ static unsigned int tavorevb_matrix_key_map[] = { | |||
147 | KEY(3, 3, KEY_F23), /* soft2 */ | 147 | KEY(3, 3, KEY_F23), /* soft2 */ |
148 | }; | 148 | }; |
149 | 149 | ||
150 | static struct matrix_keymap_data tavorevb_matrix_keymap_data = { | ||
151 | .keymap = tavorevb_matrix_key_map, | ||
152 | .keymap_size = ARRAY_SIZE(tavorevb_matrix_key_map), | ||
153 | }; | ||
154 | |||
150 | static struct pxa27x_keypad_platform_data tavorevb_keypad_info = { | 155 | static struct pxa27x_keypad_platform_data tavorevb_keypad_info = { |
151 | .matrix_key_rows = 7, | 156 | .matrix_key_rows = 7, |
152 | .matrix_key_cols = 7, | 157 | .matrix_key_cols = 7, |
153 | .matrix_key_map = tavorevb_matrix_key_map, | 158 | .matrix_keymap_data = &tavorevb_matrix_keymap_data, |
154 | .matrix_key_map_size = ARRAY_SIZE(tavorevb_matrix_key_map), | ||
155 | .debounce_interval = 30, | 159 | .debounce_interval = 30, |
156 | }; | 160 | }; |
157 | 161 | ||
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index 989903a7e467..2513d8f4931f 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c | |||
@@ -345,7 +345,7 @@ static inline void z2_leds_init(void) {} | |||
345 | * GPIO keyboard | 345 | * GPIO keyboard |
346 | ******************************************************************************/ | 346 | ******************************************************************************/ |
347 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 347 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
348 | static unsigned int z2_matrix_keys[] = { | 348 | static const unsigned int z2_matrix_keys[] = { |
349 | KEY(0, 0, KEY_OPTION), | 349 | KEY(0, 0, KEY_OPTION), |
350 | KEY(1, 0, KEY_UP), | 350 | KEY(1, 0, KEY_UP), |
351 | KEY(2, 0, KEY_DOWN), | 351 | KEY(2, 0, KEY_DOWN), |
@@ -405,11 +405,15 @@ static unsigned int z2_matrix_keys[] = { | |||
405 | KEY(5, 7, KEY_DOT), | 405 | KEY(5, 7, KEY_DOT), |
406 | }; | 406 | }; |
407 | 407 | ||
408 | static struct matrix_keymap_data z2_matrix_keymap_data = { | ||
409 | .keymap = z2_matrix_keys, | ||
410 | .keymap_size = ARRAY_SIZE(z2_matrix_keys), | ||
411 | }; | ||
412 | |||
408 | static struct pxa27x_keypad_platform_data z2_keypad_platform_data = { | 413 | static struct pxa27x_keypad_platform_data z2_keypad_platform_data = { |
409 | .matrix_key_rows = 7, | 414 | .matrix_key_rows = 7, |
410 | .matrix_key_cols = 8, | 415 | .matrix_key_cols = 8, |
411 | .matrix_key_map = z2_matrix_keys, | 416 | .matrix_keymap_data = &z2_matrix_keymap_data, |
412 | .matrix_key_map_size = ARRAY_SIZE(z2_matrix_keys), | ||
413 | 417 | ||
414 | .debounce_interval = 30, | 418 | .debounce_interval = 30, |
415 | }; | 419 | }; |
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index 1f00d650ac27..36cf7cf95ec1 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c | |||
@@ -263,7 +263,7 @@ static inline void zylonite_init_mmc(void) {} | |||
263 | #endif | 263 | #endif |
264 | 264 | ||
265 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) | 265 | #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) |
266 | static unsigned int zylonite_matrix_key_map[] = { | 266 | static const unsigned int zylonite_matrix_key_map[] = { |
267 | /* KEY(row, col, key_code) */ | 267 | /* KEY(row, col, key_code) */ |
268 | KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D), | 268 | KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D), |
269 | KEY(1, 0, KEY_E), KEY(1, 1, KEY_F), KEY(1, 2, KEY_G), KEY(1, 5, KEY_H), | 269 | KEY(1, 0, KEY_E), KEY(1, 1, KEY_F), KEY(1, 2, KEY_G), KEY(1, 5, KEY_H), |
@@ -306,11 +306,15 @@ static unsigned int zylonite_matrix_key_map[] = { | |||
306 | KEY(0, 3, KEY_AUX), /* contact */ | 306 | KEY(0, 3, KEY_AUX), /* contact */ |
307 | }; | 307 | }; |
308 | 308 | ||
309 | static struct matrix_keymap_data zylonite_matrix_keymap_data = { | ||
310 | .keymap = zylonite_matrix_key_map, | ||
311 | .keymap_size = ARRAY_SIZE(zylonite_matrix_key_map), | ||
312 | }; | ||
313 | |||
309 | static struct pxa27x_keypad_platform_data zylonite_keypad_info = { | 314 | static struct pxa27x_keypad_platform_data zylonite_keypad_info = { |
310 | .matrix_key_rows = 8, | 315 | .matrix_key_rows = 8, |
311 | .matrix_key_cols = 8, | 316 | .matrix_key_cols = 8, |
312 | .matrix_key_map = zylonite_matrix_key_map, | 317 | .matrix_keymap_data = &zylonite_matrix_keymap_data, |
313 | .matrix_key_map_size = ARRAY_SIZE(zylonite_matrix_key_map), | ||
314 | 318 | ||
315 | .enable_rotary0 = 1, | 319 | .enable_rotary0 = 1, |
316 | .rotary0_up_key = KEY_UP, | 320 | .rotary0_up_key = KEY_UP, |
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index feae88b53fcd..c7710b5c69af 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c | |||
@@ -524,6 +524,12 @@ static const struct hid_device_id apple_devices[] = { | |||
524 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | 524 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, |
525 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), | 525 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), |
526 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | 526 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, |
527 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI), | ||
528 | .driver_data = APPLE_HAS_FN }, | ||
529 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO), | ||
530 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
531 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS), | ||
532 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
527 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), | 533 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), |
528 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, | 534 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, |
529 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), | 535 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e39dac68063c..36668d1aca8f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1547,6 +1547,9 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1547 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, | 1547 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, |
1548 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, | 1548 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, |
1549 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, | 1549 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, |
1550 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) }, | ||
1551 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) }, | ||
1552 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) }, | ||
1550 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, | 1553 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, |
1551 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, | 1554 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, |
1552 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, | 1555 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, |
@@ -2189,6 +2192,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
2189 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, | 2192 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, |
2190 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, | 2193 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, |
2191 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, | 2194 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, |
2195 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) }, | ||
2196 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) }, | ||
2197 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) }, | ||
2192 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 2198 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
2193 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 2199 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
2194 | { } | 2200 | { } |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c5aea29f164f..ffe4c7ae3340 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -135,6 +135,9 @@ | |||
135 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b | 135 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b |
136 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 | 136 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 |
137 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 | 137 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 |
138 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0291 | ||
139 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0292 | ||
140 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0293 | ||
138 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | 141 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a |
139 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | 142 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b |
140 | #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 | 143 | #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index f0f8928b3c8a..d2b34fbbc42e 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -52,6 +52,82 @@ struct evdev_client { | |||
52 | struct input_event buffer[]; | 52 | struct input_event buffer[]; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* flush queued events of type @type, caller must hold client->buffer_lock */ | ||
56 | static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) | ||
57 | { | ||
58 | unsigned int i, head, num; | ||
59 | unsigned int mask = client->bufsize - 1; | ||
60 | bool is_report; | ||
61 | struct input_event *ev; | ||
62 | |||
63 | BUG_ON(type == EV_SYN); | ||
64 | |||
65 | head = client->tail; | ||
66 | client->packet_head = client->tail; | ||
67 | |||
68 | /* init to 1 so a leading SYN_REPORT will not be dropped */ | ||
69 | num = 1; | ||
70 | |||
71 | for (i = client->tail; i != client->head; i = (i + 1) & mask) { | ||
72 | ev = &client->buffer[i]; | ||
73 | is_report = ev->type == EV_SYN && ev->code == SYN_REPORT; | ||
74 | |||
75 | if (ev->type == type) { | ||
76 | /* drop matched entry */ | ||
77 | continue; | ||
78 | } else if (is_report && !num) { | ||
79 | /* drop empty SYN_REPORT groups */ | ||
80 | continue; | ||
81 | } else if (head != i) { | ||
82 | /* move entry to fill the gap */ | ||
83 | client->buffer[head].time = ev->time; | ||
84 | client->buffer[head].type = ev->type; | ||
85 | client->buffer[head].code = ev->code; | ||
86 | client->buffer[head].value = ev->value; | ||
87 | } | ||
88 | |||
89 | num++; | ||
90 | head = (head + 1) & mask; | ||
91 | |||
92 | if (is_report) { | ||
93 | num = 0; | ||
94 | client->packet_head = head; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | client->head = head; | ||
99 | } | ||
100 | |||
101 | /* queue SYN_DROPPED event */ | ||
102 | static void evdev_queue_syn_dropped(struct evdev_client *client) | ||
103 | { | ||
104 | unsigned long flags; | ||
105 | struct input_event ev; | ||
106 | ktime_t time; | ||
107 | |||
108 | time = ktime_get(); | ||
109 | if (client->clkid != CLOCK_MONOTONIC) | ||
110 | time = ktime_sub(time, ktime_get_monotonic_offset()); | ||
111 | |||
112 | ev.time = ktime_to_timeval(time); | ||
113 | ev.type = EV_SYN; | ||
114 | ev.code = SYN_DROPPED; | ||
115 | ev.value = 0; | ||
116 | |||
117 | spin_lock_irqsave(&client->buffer_lock, flags); | ||
118 | |||
119 | client->buffer[client->head++] = ev; | ||
120 | client->head &= client->bufsize - 1; | ||
121 | |||
122 | if (unlikely(client->head == client->tail)) { | ||
123 | /* drop queue but keep our SYN_DROPPED event */ | ||
124 | client->tail = (client->head - 1) & (client->bufsize - 1); | ||
125 | client->packet_head = client->tail; | ||
126 | } | ||
127 | |||
128 | spin_unlock_irqrestore(&client->buffer_lock, flags); | ||
129 | } | ||
130 | |||
55 | static void __pass_event(struct evdev_client *client, | 131 | static void __pass_event(struct evdev_client *client, |
56 | const struct input_event *event) | 132 | const struct input_event *event) |
57 | { | 133 | { |
@@ -650,6 +726,51 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) | |||
650 | return input_set_keycode(dev, &ke); | 726 | return input_set_keycode(dev, &ke); |
651 | } | 727 | } |
652 | 728 | ||
729 | /* | ||
730 | * If we transfer state to the user, we should flush all pending events | ||
731 | * of the same type from the client's queue. Otherwise, they might end up | ||
732 | * with duplicate events, which can screw up client's state tracking. | ||
733 | * If bits_to_user fails after flushing the queue, we queue a SYN_DROPPED | ||
734 | * event so user-space will notice missing events. | ||
735 | * | ||
736 | * LOCKING: | ||
737 | * We need to take event_lock before buffer_lock to avoid dead-locks. But we | ||
738 | * need the even_lock only to guarantee consistent state. We can safely release | ||
739 | * it while flushing the queue. This allows input-core to handle filters while | ||
740 | * we flush the queue. | ||
741 | */ | ||
742 | static int evdev_handle_get_val(struct evdev_client *client, | ||
743 | struct input_dev *dev, unsigned int type, | ||
744 | unsigned long *bits, unsigned int max, | ||
745 | unsigned int size, void __user *p, int compat) | ||
746 | { | ||
747 | int ret; | ||
748 | unsigned long *mem; | ||
749 | |||
750 | mem = kmalloc(sizeof(unsigned long) * max, GFP_KERNEL); | ||
751 | if (!mem) | ||
752 | return -ENOMEM; | ||
753 | |||
754 | spin_lock_irq(&dev->event_lock); | ||
755 | spin_lock(&client->buffer_lock); | ||
756 | |||
757 | memcpy(mem, bits, sizeof(unsigned long) * max); | ||
758 | |||
759 | spin_unlock(&dev->event_lock); | ||
760 | |||
761 | __evdev_flush_queue(client, type); | ||
762 | |||
763 | spin_unlock_irq(&client->buffer_lock); | ||
764 | |||
765 | ret = bits_to_user(mem, max, size, p, compat); | ||
766 | if (ret < 0) | ||
767 | evdev_queue_syn_dropped(client); | ||
768 | |||
769 | kfree(mem); | ||
770 | |||
771 | return ret; | ||
772 | } | ||
773 | |||
653 | static int evdev_handle_mt_request(struct input_dev *dev, | 774 | static int evdev_handle_mt_request(struct input_dev *dev, |
654 | unsigned int size, | 775 | unsigned int size, |
655 | int __user *ip) | 776 | int __user *ip) |
@@ -771,16 +892,20 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
771 | return evdev_handle_mt_request(dev, size, ip); | 892 | return evdev_handle_mt_request(dev, size, ip); |
772 | 893 | ||
773 | case EVIOCGKEY(0): | 894 | case EVIOCGKEY(0): |
774 | return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); | 895 | return evdev_handle_get_val(client, dev, EV_KEY, dev->key, |
896 | KEY_MAX, size, p, compat_mode); | ||
775 | 897 | ||
776 | case EVIOCGLED(0): | 898 | case EVIOCGLED(0): |
777 | return bits_to_user(dev->led, LED_MAX, size, p, compat_mode); | 899 | return evdev_handle_get_val(client, dev, EV_LED, dev->led, |
900 | LED_MAX, size, p, compat_mode); | ||
778 | 901 | ||
779 | case EVIOCGSND(0): | 902 | case EVIOCGSND(0): |
780 | return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode); | 903 | return evdev_handle_get_val(client, dev, EV_SND, dev->snd, |
904 | SND_MAX, size, p, compat_mode); | ||
781 | 905 | ||
782 | case EVIOCGSW(0): | 906 | case EVIOCGSW(0): |
783 | return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode); | 907 | return evdev_handle_get_val(client, dev, EV_SW, dev->sw, |
908 | SW_MAX, size, p, compat_mode); | ||
784 | 909 | ||
785 | case EVIOCGNAME(0): | 910 | case EVIOCGNAME(0): |
786 | return str_to_user(dev->name, size, p); | 911 | return str_to_user(dev->name, size, p); |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 7ac9c9818d55..269d4c3658cb 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -418,6 +418,16 @@ config KEYBOARD_NOMADIK | |||
418 | To compile this driver as a module, choose M here: the | 418 | To compile this driver as a module, choose M here: the |
419 | module will be called nmk-ske-keypad. | 419 | module will be called nmk-ske-keypad. |
420 | 420 | ||
421 | config KEYBOARD_NSPIRE | ||
422 | tristate "TI-NSPIRE built-in keyboard" | ||
423 | depends on ARCH_NSPIRE && OF | ||
424 | select INPUT_MATRIXKMAP | ||
425 | help | ||
426 | Say Y here if you want to use the built-in keypad on TI-NSPIRE. | ||
427 | |||
428 | To compile this driver as a module, choose M here: the | ||
429 | module will be called nspire-keypad. | ||
430 | |||
421 | config KEYBOARD_TEGRA | 431 | config KEYBOARD_TEGRA |
422 | tristate "NVIDIA Tegra internal matrix keyboard controller support" | 432 | tristate "NVIDIA Tegra internal matrix keyboard controller support" |
423 | depends on ARCH_TEGRA && OF | 433 | depends on ARCH_TEGRA && OF |
@@ -442,6 +452,7 @@ config KEYBOARD_OPENCORES | |||
442 | config KEYBOARD_PXA27x | 452 | config KEYBOARD_PXA27x |
443 | tristate "PXA27x/PXA3xx keypad support" | 453 | tristate "PXA27x/PXA3xx keypad support" |
444 | depends on PXA27x || PXA3xx || ARCH_MMP | 454 | depends on PXA27x || PXA3xx || ARCH_MMP |
455 | select INPUT_MATRIXKMAP | ||
445 | help | 456 | help |
446 | Enable support for PXA27x/PXA3xx keypad controller. | 457 | Enable support for PXA27x/PXA3xx keypad controller. |
447 | 458 | ||
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 0c43e8cf8d0e..a699b6172303 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o | |||
36 | obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o | 36 | obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o |
37 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 37 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
38 | obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o | 38 | obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o |
39 | obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o | ||
39 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 40 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
40 | obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o | 41 | obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o |
41 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o | 42 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o |
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index ba0b36f7daea..096d6067ae1f 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c | |||
@@ -246,7 +246,6 @@ static int __exit amikbd_remove(struct platform_device *pdev) | |||
246 | { | 246 | { |
247 | struct input_dev *dev = platform_get_drvdata(pdev); | 247 | struct input_dev *dev = platform_get_drvdata(pdev); |
248 | 248 | ||
249 | platform_set_drvdata(pdev, NULL); | ||
250 | free_irq(IRQ_AMIGA_CIAA_SP, dev); | 249 | free_irq(IRQ_AMIGA_CIAA_SP, dev); |
251 | input_unregister_device(dev); | 250 | input_unregister_device(dev); |
252 | return 0; | 251 | return 0; |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 20b9fa91fb9e..fc88fb48d70d 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -326,7 +326,6 @@ out0: | |||
326 | kfree(bf54x_kpad->keycode); | 326 | kfree(bf54x_kpad->keycode); |
327 | out: | 327 | out: |
328 | kfree(bf54x_kpad); | 328 | kfree(bf54x_kpad); |
329 | platform_set_drvdata(pdev, NULL); | ||
330 | 329 | ||
331 | return error; | 330 | return error; |
332 | } | 331 | } |
@@ -346,7 +345,6 @@ static int bfin_kpad_remove(struct platform_device *pdev) | |||
346 | 345 | ||
347 | kfree(bf54x_kpad->keycode); | 346 | kfree(bf54x_kpad->keycode); |
348 | kfree(bf54x_kpad); | 347 | kfree(bf54x_kpad); |
349 | platform_set_drvdata(pdev, NULL); | ||
350 | 348 | ||
351 | return 0; | 349 | return 0; |
352 | } | 350 | } |
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index 829753702b62..d15977a8361e 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c | |||
@@ -314,8 +314,6 @@ static int davinci_ks_remove(struct platform_device *pdev) | |||
314 | iounmap(davinci_ks->base); | 314 | iounmap(davinci_ks->base); |
315 | release_mem_region(davinci_ks->pbase, davinci_ks->base_size); | 315 | release_mem_region(davinci_ks->pbase, davinci_ks->base_size); |
316 | 316 | ||
317 | platform_set_drvdata(pdev, NULL); | ||
318 | |||
319 | kfree(davinci_ks); | 317 | kfree(davinci_ks); |
320 | 318 | ||
321 | return 0; | 319 | return 0; |
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 9857e8fd0987..47206bdba411 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c | |||
@@ -329,8 +329,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) | |||
329 | return 0; | 329 | return 0; |
330 | 330 | ||
331 | failed_free_irq: | 331 | failed_free_irq: |
332 | free_irq(keypad->irq, pdev); | 332 | free_irq(keypad->irq, keypad); |
333 | platform_set_drvdata(pdev, NULL); | ||
334 | failed_free_dev: | 333 | failed_free_dev: |
335 | input_free_device(input_dev); | 334 | input_free_device(input_dev); |
336 | failed_put_clk: | 335 | failed_put_clk: |
@@ -351,9 +350,7 @@ static int ep93xx_keypad_remove(struct platform_device *pdev) | |||
351 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | 350 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); |
352 | struct resource *res; | 351 | struct resource *res; |
353 | 352 | ||
354 | free_irq(keypad->irq, pdev); | 353 | free_irq(keypad->irq, keypad); |
355 | |||
356 | platform_set_drvdata(pdev, NULL); | ||
357 | 354 | ||
358 | if (keypad->enabled) | 355 | if (keypad->enabled) |
359 | clk_disable(keypad->clk); | 356 | clk_disable(keypad->clk); |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index b29ca651a395..440ce32462ba 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -767,7 +767,6 @@ static int gpio_keys_probe(struct platform_device *pdev) | |||
767 | while (--i >= 0) | 767 | while (--i >= 0) |
768 | gpio_remove_key(&ddata->data[i]); | 768 | gpio_remove_key(&ddata->data[i]); |
769 | 769 | ||
770 | platform_set_drvdata(pdev, NULL); | ||
771 | fail1: | 770 | fail1: |
772 | input_free_device(input); | 771 | input_free_device(input); |
773 | kfree(ddata); | 772 | kfree(ddata); |
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 21147164874d..cd5ed9e22168 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c | |||
@@ -324,7 +324,6 @@ err_free_gpio: | |||
324 | 324 | ||
325 | err_free_bdev: | 325 | err_free_bdev: |
326 | kfree(bdev); | 326 | kfree(bdev); |
327 | platform_set_drvdata(pdev, NULL); | ||
328 | 327 | ||
329 | err_free_pdata: | 328 | err_free_pdata: |
330 | /* If we have no platform_data, we allocated pdata dynamically. */ | 329 | /* If we have no platform_data, we allocated pdata dynamically. */ |
@@ -355,7 +354,6 @@ static int gpio_keys_polled_remove(struct platform_device *pdev) | |||
355 | kfree(pdata); | 354 | kfree(pdata); |
356 | 355 | ||
357 | kfree(bdev); | 356 | kfree(bdev); |
358 | platform_set_drvdata(pdev, NULL); | ||
359 | 357 | ||
360 | return 0; | 358 | return 0; |
361 | } | 359 | } |
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 74e75a6e8deb..a2a034c25f0b 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c | |||
@@ -233,7 +233,6 @@ static int jornada680kbd_probe(struct platform_device *pdev) | |||
233 | failed: | 233 | failed: |
234 | printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", | 234 | printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", |
235 | error); | 235 | error); |
236 | platform_set_drvdata(pdev, NULL); | ||
237 | input_free_polled_device(poll_dev); | 236 | input_free_polled_device(poll_dev); |
238 | kfree(jornadakbd); | 237 | kfree(jornadakbd); |
239 | return error; | 238 | return error; |
@@ -244,7 +243,6 @@ static int jornada680kbd_remove(struct platform_device *pdev) | |||
244 | { | 243 | { |
245 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | 244 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); |
246 | 245 | ||
247 | platform_set_drvdata(pdev, NULL); | ||
248 | input_unregister_polled_device(jornadakbd->poll_dev); | 246 | input_unregister_polled_device(jornadakbd->poll_dev); |
249 | input_free_polled_device(jornadakbd->poll_dev); | 247 | input_free_polled_device(jornadakbd->poll_dev); |
250 | kfree(jornadakbd); | 248 | kfree(jornadakbd); |
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 5ceef636df2f..b0ad457ca9d8 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c | |||
@@ -146,7 +146,6 @@ static int jornada720_kbd_probe(struct platform_device *pdev) | |||
146 | fail2: /* IRQ, DEVICE, MEMORY */ | 146 | fail2: /* IRQ, DEVICE, MEMORY */ |
147 | free_irq(IRQ_GPIO0, pdev); | 147 | free_irq(IRQ_GPIO0, pdev); |
148 | fail1: /* DEVICE, MEMORY */ | 148 | fail1: /* DEVICE, MEMORY */ |
149 | platform_set_drvdata(pdev, NULL); | ||
150 | input_free_device(input_dev); | 149 | input_free_device(input_dev); |
151 | kfree(jornadakbd); | 150 | kfree(jornadakbd); |
152 | return err; | 151 | return err; |
@@ -157,7 +156,6 @@ static int jornada720_kbd_remove(struct platform_device *pdev) | |||
157 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | 156 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); |
158 | 157 | ||
159 | free_irq(IRQ_GPIO0, pdev); | 158 | free_irq(IRQ_GPIO0, pdev); |
160 | platform_set_drvdata(pdev, NULL); | ||
161 | input_unregister_device(jornadakbd->input); | 159 | input_unregister_device(jornadakbd->input); |
162 | kfree(jornadakbd); | 160 | kfree(jornadakbd); |
163 | 161 | ||
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 71d77192ac1e..90ff73ace424 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -549,8 +549,6 @@ static int matrix_keypad_remove(struct platform_device *pdev) | |||
549 | input_unregister_device(keypad->input_dev); | 549 | input_unregister_device(keypad->input_dev); |
550 | kfree(keypad); | 550 | kfree(keypad); |
551 | 551 | ||
552 | platform_set_drvdata(pdev, NULL); | ||
553 | |||
554 | return 0; | 552 | return 0; |
555 | } | 553 | } |
556 | 554 | ||
diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c new file mode 100644 index 000000000000..e0a1339e40e6 --- /dev/null +++ b/drivers/input/keyboard/nspire-keypad.c | |||
@@ -0,0 +1,283 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2, as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/input/matrix_keypad.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | |||
20 | #define KEYPAD_SCAN_MODE 0x00 | ||
21 | #define KEYPAD_CNTL 0x04 | ||
22 | #define KEYPAD_INT 0x08 | ||
23 | #define KEYPAD_INTMSK 0x0C | ||
24 | |||
25 | #define KEYPAD_DATA 0x10 | ||
26 | #define KEYPAD_GPIO 0x30 | ||
27 | |||
28 | #define KEYPAD_UNKNOWN_INT 0x40 | ||
29 | #define KEYPAD_UNKNOWN_INT_STS 0x44 | ||
30 | |||
31 | #define KEYPAD_BITMASK_COLS 11 | ||
32 | #define KEYPAD_BITMASK_ROWS 8 | ||
33 | |||
34 | struct nspire_keypad { | ||
35 | void __iomem *reg_base; | ||
36 | u32 int_mask; | ||
37 | |||
38 | struct input_dev *input; | ||
39 | struct clk *clk; | ||
40 | |||
41 | struct matrix_keymap_data *keymap; | ||
42 | int row_shift; | ||
43 | |||
44 | /* Maximum delay estimated assuming 33MHz APB */ | ||
45 | u32 scan_interval; /* In microseconds (~2000us max) */ | ||
46 | u32 row_delay; /* In microseconds (~500us max) */ | ||
47 | |||
48 | u16 state[KEYPAD_BITMASK_ROWS]; | ||
49 | |||
50 | bool active_low; | ||
51 | }; | ||
52 | |||
53 | static irqreturn_t nspire_keypad_irq(int irq, void *dev_id) | ||
54 | { | ||
55 | struct nspire_keypad *keypad = dev_id; | ||
56 | struct input_dev *input = keypad->input; | ||
57 | unsigned short *keymap = input->keycode; | ||
58 | unsigned int code; | ||
59 | int row, col; | ||
60 | u32 int_sts; | ||
61 | u16 state[8]; | ||
62 | u16 bits, changed; | ||
63 | |||
64 | int_sts = readl(keypad->reg_base + KEYPAD_INT) & keypad->int_mask; | ||
65 | if (!int_sts) | ||
66 | return IRQ_NONE; | ||
67 | |||
68 | memcpy_fromio(state, keypad->reg_base + KEYPAD_DATA, sizeof(state)); | ||
69 | |||
70 | for (row = 0; row < KEYPAD_BITMASK_ROWS; row++) { | ||
71 | bits = state[row]; | ||
72 | if (keypad->active_low) | ||
73 | bits = ~bits; | ||
74 | |||
75 | changed = bits ^ keypad->state[row]; | ||
76 | if (!changed) | ||
77 | continue; | ||
78 | |||
79 | keypad->state[row] = bits; | ||
80 | |||
81 | for (col = 0; col < KEYPAD_BITMASK_COLS; col++) { | ||
82 | if (!(changed & (1U << col))) | ||
83 | continue; | ||
84 | |||
85 | code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); | ||
86 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
87 | input_report_key(input, keymap[code], | ||
88 | bits & (1U << col)); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | input_sync(input); | ||
93 | |||
94 | writel(0x3, keypad->reg_base + KEYPAD_INT); | ||
95 | |||
96 | return IRQ_HANDLED; | ||
97 | } | ||
98 | |||
99 | static int nspire_keypad_chip_init(struct nspire_keypad *keypad) | ||
100 | { | ||
101 | unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles; | ||
102 | |||
103 | cycles_per_us = (clk_get_rate(keypad->clk) / 1000000); | ||
104 | if (cycles_per_us == 0) | ||
105 | cycles_per_us = 1; | ||
106 | |||
107 | delay_cycles = cycles_per_us * keypad->scan_interval; | ||
108 | WARN_ON(delay_cycles >= (1 << 16)); /* Overflow */ | ||
109 | delay_cycles &= 0xffff; | ||
110 | |||
111 | row_delay_cycles = cycles_per_us * keypad->row_delay; | ||
112 | WARN_ON(row_delay_cycles >= (1 << 14)); /* Overflow */ | ||
113 | row_delay_cycles &= 0x3fff; | ||
114 | |||
115 | val |= 3 << 0; /* Set scan mode to 3 (continuous scan) */ | ||
116 | val |= row_delay_cycles << 2; /* Delay between scanning each row */ | ||
117 | val |= delay_cycles << 16; /* Delay between scans */ | ||
118 | writel(val, keypad->reg_base + KEYPAD_SCAN_MODE); | ||
119 | |||
120 | val = (KEYPAD_BITMASK_ROWS & 0xff) | (KEYPAD_BITMASK_COLS & 0xff)<<8; | ||
121 | writel(val, keypad->reg_base + KEYPAD_CNTL); | ||
122 | |||
123 | /* Enable interrupts */ | ||
124 | keypad->int_mask = 1 << 1; | ||
125 | writel(keypad->int_mask, keypad->reg_base + 0xc); | ||
126 | |||
127 | /* Disable GPIO interrupts to prevent hanging on touchpad */ | ||
128 | /* Possibly used to detect touchpad events */ | ||
129 | writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT); | ||
130 | /* Acknowledge existing interrupts */ | ||
131 | writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int nspire_keypad_open(struct input_dev *input) | ||
137 | { | ||
138 | struct nspire_keypad *keypad = input_get_drvdata(input); | ||
139 | int error; | ||
140 | |||
141 | error = clk_prepare_enable(keypad->clk); | ||
142 | if (error) | ||
143 | return error; | ||
144 | |||
145 | error = nspire_keypad_chip_init(keypad); | ||
146 | if (error) | ||
147 | return error; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static void nspire_keypad_close(struct input_dev *input) | ||
153 | { | ||
154 | struct nspire_keypad *keypad = input_get_drvdata(input); | ||
155 | |||
156 | clk_disable_unprepare(keypad->clk); | ||
157 | } | ||
158 | |||
159 | static int nspire_keypad_probe(struct platform_device *pdev) | ||
160 | { | ||
161 | const struct device_node *of_node = pdev->dev.of_node; | ||
162 | struct nspire_keypad *keypad; | ||
163 | struct input_dev *input; | ||
164 | struct resource *res; | ||
165 | int irq; | ||
166 | int error; | ||
167 | |||
168 | irq = platform_get_irq(pdev, 0); | ||
169 | if (irq < 0) { | ||
170 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | |||
174 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
175 | if (!res) { | ||
176 | dev_err(&pdev->dev, "missing platform resources\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | keypad = devm_kzalloc(&pdev->dev, sizeof(struct nspire_keypad), | ||
181 | GFP_KERNEL); | ||
182 | if (!keypad) { | ||
183 | dev_err(&pdev->dev, "failed to allocate keypad memory\n"); | ||
184 | return -ENOMEM; | ||
185 | } | ||
186 | |||
187 | keypad->row_shift = get_count_order(KEYPAD_BITMASK_COLS); | ||
188 | |||
189 | error = of_property_read_u32(of_node, "scan-interval", | ||
190 | &keypad->scan_interval); | ||
191 | if (error) { | ||
192 | dev_err(&pdev->dev, "failed to get scan-interval\n"); | ||
193 | return error; | ||
194 | } | ||
195 | |||
196 | error = of_property_read_u32(of_node, "row-delay", | ||
197 | &keypad->row_delay); | ||
198 | if (error) { | ||
199 | dev_err(&pdev->dev, "failed to get row-delay\n"); | ||
200 | return error; | ||
201 | } | ||
202 | |||
203 | keypad->active_low = of_property_read_bool(of_node, "active-low"); | ||
204 | |||
205 | keypad->clk = devm_clk_get(&pdev->dev, NULL); | ||
206 | if (IS_ERR(keypad->clk)) { | ||
207 | dev_err(&pdev->dev, "unable to get clock\n"); | ||
208 | return PTR_ERR(keypad->clk); | ||
209 | } | ||
210 | |||
211 | keypad->reg_base = devm_ioremap_resource(&pdev->dev, res); | ||
212 | if (IS_ERR(keypad->reg_base)) | ||
213 | return PTR_ERR(keypad->reg_base); | ||
214 | |||
215 | keypad->input = input = devm_input_allocate_device(&pdev->dev); | ||
216 | if (!input) { | ||
217 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
218 | return -ENOMEM; | ||
219 | } | ||
220 | |||
221 | input_set_drvdata(input, keypad); | ||
222 | |||
223 | input->id.bustype = BUS_HOST; | ||
224 | input->name = "nspire-keypad"; | ||
225 | input->open = nspire_keypad_open; | ||
226 | input->close = nspire_keypad_close; | ||
227 | |||
228 | __set_bit(EV_KEY, input->evbit); | ||
229 | __set_bit(EV_REP, input->evbit); | ||
230 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
231 | |||
232 | error = matrix_keypad_build_keymap(NULL, NULL, | ||
233 | KEYPAD_BITMASK_ROWS, | ||
234 | KEYPAD_BITMASK_COLS, | ||
235 | NULL, input); | ||
236 | if (error) { | ||
237 | dev_err(&pdev->dev, "building keymap failed\n"); | ||
238 | return error; | ||
239 | } | ||
240 | |||
241 | error = devm_request_irq(&pdev->dev, irq, nspire_keypad_irq, 0, | ||
242 | "nspire_keypad", keypad); | ||
243 | if (error) { | ||
244 | dev_err(&pdev->dev, "allocate irq %d failed\n", irq); | ||
245 | return error; | ||
246 | } | ||
247 | |||
248 | error = input_register_device(input); | ||
249 | if (error) { | ||
250 | dev_err(&pdev->dev, | ||
251 | "unable to register input device: %d\n", error); | ||
252 | return error; | ||
253 | } | ||
254 | |||
255 | platform_set_drvdata(pdev, keypad); | ||
256 | |||
257 | dev_dbg(&pdev->dev, | ||
258 | "TI-NSPIRE keypad at %pR (scan_interval=%uus, row_delay=%uus%s)\n", | ||
259 | res, keypad->row_delay, keypad->scan_interval, | ||
260 | keypad->active_low ? ", active_low" : ""); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static const struct of_device_id nspire_keypad_dt_match[] = { | ||
266 | { .compatible = "ti,nspire-keypad" }, | ||
267 | { }, | ||
268 | }; | ||
269 | MODULE_DEVICE_TABLE(of, nspire_keypad_dt_match); | ||
270 | |||
271 | static struct platform_driver nspire_keypad_driver = { | ||
272 | .driver = { | ||
273 | .name = "nspire-keypad", | ||
274 | .owner = THIS_MODULE, | ||
275 | .of_match_table = of_match_ptr(nspire_keypad_dt_match), | ||
276 | }, | ||
277 | .probe = nspire_keypad_probe, | ||
278 | }; | ||
279 | |||
280 | module_platform_driver(nspire_keypad_driver); | ||
281 | |||
282 | MODULE_LICENSE("GPL"); | ||
283 | MODULE_DESCRIPTION("TI-NSPIRE Keypad Driver"); | ||
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 1b289092f4e3..f4aa53a1fd69 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c | |||
@@ -419,8 +419,6 @@ static int omap4_keypad_remove(struct platform_device *pdev) | |||
419 | kfree(keypad_data->keymap); | 419 | kfree(keypad_data->keymap); |
420 | kfree(keypad_data); | 420 | kfree(keypad_data); |
421 | 421 | ||
422 | platform_set_drvdata(pdev, NULL); | ||
423 | |||
424 | return 0; | 422 | return 0; |
425 | } | 423 | } |
426 | 424 | ||
diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index 7ac5f174c6f7..7b9b44158ad1 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c | |||
@@ -151,8 +151,6 @@ static int opencores_kbd_remove(struct platform_device *pdev) | |||
151 | input_unregister_device(opencores_kbd->input); | 151 | input_unregister_device(opencores_kbd->input); |
152 | kfree(opencores_kbd); | 152 | kfree(opencores_kbd); |
153 | 153 | ||
154 | platform_set_drvdata(pdev, NULL); | ||
155 | |||
156 | return 0; | 154 | return 0; |
157 | } | 155 | } |
158 | 156 | ||
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 74339e139d43..2c9f19ac35ea 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c | |||
@@ -707,7 +707,6 @@ err_gpio_config: | |||
707 | err_get_irq: | 707 | err_get_irq: |
708 | input_free_device(kp->input); | 708 | input_free_device(kp->input); |
709 | err_alloc_device: | 709 | err_alloc_device: |
710 | platform_set_drvdata(pdev, NULL); | ||
711 | kfree(kp); | 710 | kfree(kp); |
712 | return rc; | 711 | return rc; |
713 | } | 712 | } |
@@ -722,7 +721,6 @@ static int pmic8xxx_kp_remove(struct platform_device *pdev) | |||
722 | input_unregister_device(kp->input); | 721 | input_unregister_device(kp->input); |
723 | kfree(kp); | 722 | kfree(kp); |
724 | 723 | ||
725 | platform_set_drvdata(pdev, NULL); | ||
726 | return 0; | 724 | return 0; |
727 | } | 725 | } |
728 | 726 | ||
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 5330d8fbf6c0..134c3b404a54 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -100,7 +100,7 @@ | |||
100 | #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM) | 100 | #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM) |
101 | 101 | ||
102 | struct pxa27x_keypad { | 102 | struct pxa27x_keypad { |
103 | struct pxa27x_keypad_platform_data *pdata; | 103 | const struct pxa27x_keypad_platform_data *pdata; |
104 | 104 | ||
105 | struct clk *clk; | 105 | struct clk *clk; |
106 | struct input_dev *input_dev; | 106 | struct input_dev *input_dev; |
@@ -118,25 +118,254 @@ struct pxa27x_keypad { | |||
118 | unsigned int direct_key_mask; | 118 | unsigned int direct_key_mask; |
119 | }; | 119 | }; |
120 | 120 | ||
121 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | 121 | #ifdef CONFIG_OF |
122 | static int pxa27x_keypad_matrix_key_parse_dt(struct pxa27x_keypad *keypad, | ||
123 | struct pxa27x_keypad_platform_data *pdata) | ||
122 | { | 124 | { |
123 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
124 | struct input_dev *input_dev = keypad->input_dev; | 125 | struct input_dev *input_dev = keypad->input_dev; |
125 | unsigned short keycode; | 126 | struct device *dev = input_dev->dev.parent; |
127 | u32 rows, cols; | ||
128 | int error; | ||
129 | |||
130 | error = matrix_keypad_parse_of_params(dev, &rows, &cols); | ||
131 | if (error) | ||
132 | return error; | ||
133 | |||
134 | if (rows > MAX_MATRIX_KEY_ROWS || cols > MAX_MATRIX_KEY_COLS) { | ||
135 | dev_err(dev, "rows or cols exceeds maximum value\n"); | ||
136 | return -EINVAL; | ||
137 | } | ||
138 | |||
139 | pdata->matrix_key_rows = rows; | ||
140 | pdata->matrix_key_cols = cols; | ||
141 | |||
142 | error = matrix_keypad_build_keymap(NULL, NULL, | ||
143 | pdata->matrix_key_rows, | ||
144 | pdata->matrix_key_cols, | ||
145 | keypad->keycodes, input_dev); | ||
146 | if (error) | ||
147 | return error; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int pxa27x_keypad_direct_key_parse_dt(struct pxa27x_keypad *keypad, | ||
153 | struct pxa27x_keypad_platform_data *pdata) | ||
154 | { | ||
155 | struct input_dev *input_dev = keypad->input_dev; | ||
156 | struct device *dev = input_dev->dev.parent; | ||
157 | struct device_node *np = dev->of_node; | ||
158 | const __be16 *prop; | ||
159 | unsigned short code; | ||
160 | unsigned int proplen, size; | ||
126 | int i; | 161 | int i; |
162 | int error; | ||
127 | 163 | ||
128 | for (i = 0; i < pdata->matrix_key_map_size; i++) { | 164 | error = of_property_read_u32(np, "marvell,direct-key-count", |
129 | unsigned int key = pdata->matrix_key_map[i]; | 165 | &pdata->direct_key_num); |
130 | unsigned int row = KEY_ROW(key); | 166 | if (error) { |
131 | unsigned int col = KEY_COL(key); | 167 | /* |
132 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, | 168 | * If do not have marvel,direct-key-count defined, |
133 | MATRIX_ROW_SHIFT); | 169 | * it means direct key is not supported. |
170 | */ | ||
171 | return error == -EINVAL ? 0 : error; | ||
172 | } | ||
134 | 173 | ||
135 | keycode = KEY_VAL(key); | 174 | error = of_property_read_u32(np, "marvell,direct-key-mask", |
136 | keypad->keycodes[scancode] = keycode; | 175 | &pdata->direct_key_mask); |
137 | __set_bit(keycode, input_dev->keybit); | 176 | if (error) { |
177 | if (error != -EINVAL) | ||
178 | return error; | ||
179 | |||
180 | /* | ||
181 | * If marvell,direct-key-mask is not defined, driver will use | ||
182 | * default value. Default value is set when configure the keypad. | ||
183 | */ | ||
184 | pdata->direct_key_mask = 0; | ||
185 | } | ||
186 | |||
187 | pdata->direct_key_low_active = of_property_read_bool(np, | ||
188 | "marvell,direct-key-low-active"); | ||
189 | |||
190 | prop = of_get_property(np, "marvell,direct-key-map", &proplen); | ||
191 | if (!prop) | ||
192 | return -EINVAL; | ||
193 | |||
194 | if (proplen % sizeof(u16)) | ||
195 | return -EINVAL; | ||
196 | |||
197 | size = proplen / sizeof(u16); | ||
198 | |||
199 | /* Only MAX_DIRECT_KEY_NUM is accepted.*/ | ||
200 | if (size > MAX_DIRECT_KEY_NUM) | ||
201 | return -EINVAL; | ||
202 | |||
203 | for (i = 0; i < size; i++) { | ||
204 | code = be16_to_cpup(prop + i); | ||
205 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = code; | ||
206 | __set_bit(code, input_dev->keybit); | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int pxa27x_keypad_rotary_parse_dt(struct pxa27x_keypad *keypad, | ||
213 | struct pxa27x_keypad_platform_data *pdata) | ||
214 | { | ||
215 | const __be32 *prop; | ||
216 | int i, relkey_ret; | ||
217 | unsigned int code, proplen; | ||
218 | const char *rotaryname[2] = { | ||
219 | "marvell,rotary0", "marvell,rotary1"}; | ||
220 | const char relkeyname[] = {"marvell,rotary-rel-key"}; | ||
221 | struct input_dev *input_dev = keypad->input_dev; | ||
222 | struct device *dev = input_dev->dev.parent; | ||
223 | struct device_node *np = dev->of_node; | ||
224 | |||
225 | relkey_ret = of_property_read_u32(np, relkeyname, &code); | ||
226 | /* if can read correct rotary key-code, we do not need this. */ | ||
227 | if (relkey_ret == 0) { | ||
228 | unsigned short relcode; | ||
229 | |||
230 | /* rotary0 taks lower half, rotary1 taks upper half. */ | ||
231 | relcode = code & 0xffff; | ||
232 | pdata->rotary0_rel_code = (code & 0xffff); | ||
233 | __set_bit(relcode, input_dev->relbit); | ||
234 | |||
235 | relcode = code >> 16; | ||
236 | pdata->rotary1_rel_code = relcode; | ||
237 | __set_bit(relcode, input_dev->relbit); | ||
238 | } | ||
239 | |||
240 | for (i = 0; i < 2; i++) { | ||
241 | prop = of_get_property(np, rotaryname[i], &proplen); | ||
242 | /* | ||
243 | * If the prop is not set, it means keypad does not need | ||
244 | * initialize the rotaryX. | ||
245 | */ | ||
246 | if (!prop) | ||
247 | continue; | ||
248 | |||
249 | code = be32_to_cpup(prop); | ||
250 | /* | ||
251 | * Not all up/down key code are valid. | ||
252 | * Now we depends on direct-rel-code. | ||
253 | */ | ||
254 | if ((!(code & 0xffff) || !(code >> 16)) && relkey_ret) { | ||
255 | return relkey_ret; | ||
256 | } else { | ||
257 | unsigned int n = MAX_MATRIX_KEY_NUM + (i << 1); | ||
258 | unsigned short keycode; | ||
259 | |||
260 | keycode = code & 0xffff; | ||
261 | keypad->keycodes[n] = keycode; | ||
262 | __set_bit(keycode, input_dev->keybit); | ||
263 | |||
264 | keycode = code >> 16; | ||
265 | keypad->keycodes[n + 1] = keycode; | ||
266 | __set_bit(keycode, input_dev->keybit); | ||
267 | |||
268 | if (i == 0) | ||
269 | pdata->rotary0_rel_code = -1; | ||
270 | else | ||
271 | pdata->rotary1_rel_code = -1; | ||
272 | } | ||
273 | if (i == 0) | ||
274 | pdata->enable_rotary0 = 1; | ||
275 | else | ||
276 | pdata->enable_rotary1 = 1; | ||
277 | } | ||
278 | |||
279 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
280 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad) | ||
286 | { | ||
287 | struct input_dev *input_dev = keypad->input_dev; | ||
288 | struct device *dev = input_dev->dev.parent; | ||
289 | struct device_node *np = dev->of_node; | ||
290 | struct pxa27x_keypad_platform_data *pdata; | ||
291 | int error; | ||
292 | |||
293 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
294 | if (!pdata) { | ||
295 | dev_err(dev, "failed to allocate memory for pdata\n"); | ||
296 | return -ENOMEM; | ||
297 | } | ||
298 | |||
299 | error = pxa27x_keypad_matrix_key_parse_dt(keypad, pdata); | ||
300 | if (error) { | ||
301 | dev_err(dev, "failed to parse matrix key\n"); | ||
302 | return error; | ||
303 | } | ||
304 | |||
305 | error = pxa27x_keypad_direct_key_parse_dt(keypad, pdata); | ||
306 | if (error) { | ||
307 | dev_err(dev, "failed to parse direct key\n"); | ||
308 | return error; | ||
309 | } | ||
310 | |||
311 | error = pxa27x_keypad_rotary_parse_dt(keypad, pdata); | ||
312 | if (error) { | ||
313 | dev_err(dev, "failed to parse rotary key\n"); | ||
314 | return error; | ||
315 | } | ||
316 | |||
317 | error = of_property_read_u32(np, "marvell,debounce-interval", | ||
318 | &pdata->debounce_interval); | ||
319 | if (error) { | ||
320 | dev_err(dev, "failed to parse debpunce-interval\n"); | ||
321 | return error; | ||
138 | } | 322 | } |
139 | 323 | ||
324 | /* | ||
325 | * The keycodes may not only includes matrix key but also the direct | ||
326 | * key or rotary key. | ||
327 | */ | ||
328 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
329 | |||
330 | keypad->pdata = pdata; | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | #else | ||
335 | |||
336 | static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad) | ||
337 | { | ||
338 | dev_info(keypad->input_dev->dev.parent, "missing platform data\n"); | ||
339 | |||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | #endif | ||
344 | |||
345 | static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | ||
346 | { | ||
347 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
348 | struct input_dev *input_dev = keypad->input_dev; | ||
349 | const struct matrix_keymap_data *keymap_data = | ||
350 | pdata ? pdata->matrix_keymap_data : NULL; | ||
351 | unsigned short keycode; | ||
352 | int i; | ||
353 | int error; | ||
354 | |||
355 | error = matrix_keypad_build_keymap(keymap_data, NULL, | ||
356 | pdata->matrix_key_rows, | ||
357 | pdata->matrix_key_cols, | ||
358 | keypad->keycodes, input_dev); | ||
359 | if (error) | ||
360 | return error; | ||
361 | |||
362 | /* | ||
363 | * The keycodes may not only include matrix keys but also the direct | ||
364 | * or rotary keys. | ||
365 | */ | ||
366 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
367 | |||
368 | /* For direct keys. */ | ||
140 | for (i = 0; i < pdata->direct_key_num; i++) { | 369 | for (i = 0; i < pdata->direct_key_num; i++) { |
141 | keycode = pdata->direct_key_map[i]; | 370 | keycode = pdata->direct_key_map[i]; |
142 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode; | 371 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode; |
@@ -178,11 +407,13 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | |||
178 | } | 407 | } |
179 | 408 | ||
180 | __clear_bit(KEY_RESERVED, input_dev->keybit); | 409 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
410 | |||
411 | return 0; | ||
181 | } | 412 | } |
182 | 413 | ||
183 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | 414 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) |
184 | { | 415 | { |
185 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 416 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
186 | struct input_dev *input_dev = keypad->input_dev; | 417 | struct input_dev *input_dev = keypad->input_dev; |
187 | int row, col, num_keys_pressed = 0; | 418 | int row, col, num_keys_pressed = 0; |
188 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; | 419 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; |
@@ -284,7 +515,7 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta) | |||
284 | 515 | ||
285 | static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | 516 | static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) |
286 | { | 517 | { |
287 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 518 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
288 | uint32_t kprec; | 519 | uint32_t kprec; |
289 | 520 | ||
290 | /* read and reset to default count value */ | 521 | /* read and reset to default count value */ |
@@ -300,7 +531,7 @@ static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | |||
300 | 531 | ||
301 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | 532 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) |
302 | { | 533 | { |
303 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 534 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
304 | struct input_dev *input_dev = keypad->input_dev; | 535 | struct input_dev *input_dev = keypad->input_dev; |
305 | unsigned int new_state; | 536 | unsigned int new_state; |
306 | uint32_t kpdk, bits_changed; | 537 | uint32_t kpdk, bits_changed; |
@@ -340,7 +571,7 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
340 | 571 | ||
341 | static void clear_wakeup_event(struct pxa27x_keypad *keypad) | 572 | static void clear_wakeup_event(struct pxa27x_keypad *keypad) |
342 | { | 573 | { |
343 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 574 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
344 | 575 | ||
345 | if (pdata->clear_wakeup_event) | 576 | if (pdata->clear_wakeup_event) |
346 | (pdata->clear_wakeup_event)(); | 577 | (pdata->clear_wakeup_event)(); |
@@ -364,7 +595,7 @@ static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) | |||
364 | 595 | ||
365 | static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) | 596 | static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) |
366 | { | 597 | { |
367 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 598 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
368 | unsigned int mask = 0, direct_key_num = 0; | 599 | unsigned int mask = 0, direct_key_num = 0; |
369 | unsigned long kpc = 0; | 600 | unsigned long kpc = 0; |
370 | 601 | ||
@@ -431,7 +662,7 @@ static void pxa27x_keypad_close(struct input_dev *dev) | |||
431 | clk_disable_unprepare(keypad->clk); | 662 | clk_disable_unprepare(keypad->clk); |
432 | } | 663 | } |
433 | 664 | ||
434 | #ifdef CONFIG_PM | 665 | #ifdef CONFIG_PM_SLEEP |
435 | static int pxa27x_keypad_suspend(struct device *dev) | 666 | static int pxa27x_keypad_suspend(struct device *dev) |
436 | { | 667 | { |
437 | struct platform_device *pdev = to_platform_device(dev); | 668 | struct platform_device *pdev = to_platform_device(dev); |
@@ -475,25 +706,25 @@ static int pxa27x_keypad_resume(struct device *dev) | |||
475 | 706 | ||
476 | return 0; | 707 | return 0; |
477 | } | 708 | } |
478 | |||
479 | static const struct dev_pm_ops pxa27x_keypad_pm_ops = { | ||
480 | .suspend = pxa27x_keypad_suspend, | ||
481 | .resume = pxa27x_keypad_resume, | ||
482 | }; | ||
483 | #endif | 709 | #endif |
484 | 710 | ||
711 | static SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops, | ||
712 | pxa27x_keypad_suspend, pxa27x_keypad_resume); | ||
713 | |||
714 | |||
485 | static int pxa27x_keypad_probe(struct platform_device *pdev) | 715 | static int pxa27x_keypad_probe(struct platform_device *pdev) |
486 | { | 716 | { |
487 | struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data; | 717 | const struct pxa27x_keypad_platform_data *pdata = |
718 | dev_get_platdata(&pdev->dev); | ||
719 | struct device_node *np = pdev->dev.of_node; | ||
488 | struct pxa27x_keypad *keypad; | 720 | struct pxa27x_keypad *keypad; |
489 | struct input_dev *input_dev; | 721 | struct input_dev *input_dev; |
490 | struct resource *res; | 722 | struct resource *res; |
491 | int irq, error; | 723 | int irq, error; |
492 | 724 | ||
493 | if (pdata == NULL) { | 725 | /* Driver need build keycode from device tree or pdata */ |
494 | dev_err(&pdev->dev, "no platform data defined\n"); | 726 | if (!np && !pdata) |
495 | return -EINVAL; | 727 | return -EINVAL; |
496 | } | ||
497 | 728 | ||
498 | irq = platform_get_irq(pdev, 0); | 729 | irq = platform_get_irq(pdev, 0); |
499 | if (irq < 0) { | 730 | if (irq < 0) { |
@@ -555,7 +786,14 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) | |||
555 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 786 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
556 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 787 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
557 | 788 | ||
558 | pxa27x_keypad_build_keycode(keypad); | 789 | if (pdata) |
790 | error = pxa27x_keypad_build_keycode(keypad); | ||
791 | else | ||
792 | error = pxa27x_keypad_build_keycode_from_dt(keypad); | ||
793 | if (error) { | ||
794 | dev_err(&pdev->dev, "failed to build keycode\n"); | ||
795 | goto failed_put_clk; | ||
796 | } | ||
559 | 797 | ||
560 | if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || | 798 | if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || |
561 | (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { | 799 | (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { |
@@ -582,7 +820,7 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) | |||
582 | return 0; | 820 | return 0; |
583 | 821 | ||
584 | failed_free_irq: | 822 | failed_free_irq: |
585 | free_irq(irq, pdev); | 823 | free_irq(irq, keypad); |
586 | failed_put_clk: | 824 | failed_put_clk: |
587 | clk_put(keypad->clk); | 825 | clk_put(keypad->clk); |
588 | failed_free_io: | 826 | failed_free_io: |
@@ -600,7 +838,7 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) | |||
600 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 838 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
601 | struct resource *res; | 839 | struct resource *res; |
602 | 840 | ||
603 | free_irq(keypad->irq, pdev); | 841 | free_irq(keypad->irq, keypad); |
604 | clk_put(keypad->clk); | 842 | clk_put(keypad->clk); |
605 | 843 | ||
606 | input_unregister_device(keypad->input_dev); | 844 | input_unregister_device(keypad->input_dev); |
@@ -609,7 +847,6 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) | |||
609 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 847 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
610 | release_mem_region(res->start, resource_size(res)); | 848 | release_mem_region(res->start, resource_size(res)); |
611 | 849 | ||
612 | platform_set_drvdata(pdev, NULL); | ||
613 | kfree(keypad); | 850 | kfree(keypad); |
614 | 851 | ||
615 | return 0; | 852 | return 0; |
@@ -618,15 +855,22 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) | |||
618 | /* work with hotplug and coldplug */ | 855 | /* work with hotplug and coldplug */ |
619 | MODULE_ALIAS("platform:pxa27x-keypad"); | 856 | MODULE_ALIAS("platform:pxa27x-keypad"); |
620 | 857 | ||
858 | #ifdef CONFIG_OF | ||
859 | static const struct of_device_id pxa27x_keypad_dt_match[] = { | ||
860 | { .compatible = "marvell,pxa27x-keypad" }, | ||
861 | {}, | ||
862 | }; | ||
863 | MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match); | ||
864 | #endif | ||
865 | |||
621 | static struct platform_driver pxa27x_keypad_driver = { | 866 | static struct platform_driver pxa27x_keypad_driver = { |
622 | .probe = pxa27x_keypad_probe, | 867 | .probe = pxa27x_keypad_probe, |
623 | .remove = pxa27x_keypad_remove, | 868 | .remove = pxa27x_keypad_remove, |
624 | .driver = { | 869 | .driver = { |
625 | .name = "pxa27x-keypad", | 870 | .name = "pxa27x-keypad", |
871 | .of_match_table = of_match_ptr(pxa27x_keypad_dt_match), | ||
626 | .owner = THIS_MODULE, | 872 | .owner = THIS_MODULE, |
627 | #ifdef CONFIG_PM | ||
628 | .pm = &pxa27x_keypad_pm_ops, | 873 | .pm = &pxa27x_keypad_pm_ops, |
629 | #endif | ||
630 | }, | 874 | }, |
631 | }; | 875 | }; |
632 | module_platform_driver(pxa27x_keypad_driver); | 876 | module_platform_driver(pxa27x_keypad_driver); |
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index bcad95be73aa..248cdcf95296 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c | |||
@@ -181,7 +181,6 @@ static int pxa930_rotary_remove(struct platform_device *pdev) | |||
181 | free_irq(platform_get_irq(pdev, 0), r); | 181 | free_irq(platform_get_irq(pdev, 0), r); |
182 | input_unregister_device(r->input_dev); | 182 | input_unregister_device(r->input_dev); |
183 | iounmap(r->mmio_base); | 183 | iounmap(r->mmio_base); |
184 | platform_set_drvdata(pdev, NULL); | ||
185 | kfree(r); | 184 | kfree(r); |
186 | 185 | ||
187 | return 0; | 186 | return 0; |
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 22e357b51024..ac43a486c775 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/pm_runtime.h> | 24 | #include <linux/pm_runtime.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
27 | #include <linux/of_gpio.h> | ||
28 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
29 | #include <linux/input/samsung-keypad.h> | 28 | #include <linux/input/samsung-keypad.h> |
30 | 29 | ||
@@ -79,10 +78,6 @@ struct samsung_keypad { | |||
79 | unsigned int rows; | 78 | unsigned int rows; |
80 | unsigned int cols; | 79 | unsigned int cols; |
81 | unsigned int row_state[SAMSUNG_MAX_COLS]; | 80 | unsigned int row_state[SAMSUNG_MAX_COLS]; |
82 | #ifdef CONFIG_OF | ||
83 | int row_gpios[SAMSUNG_MAX_ROWS]; | ||
84 | int col_gpios[SAMSUNG_MAX_COLS]; | ||
85 | #endif | ||
86 | unsigned short keycodes[]; | 81 | unsigned short keycodes[]; |
87 | }; | 82 | }; |
88 | 83 | ||
@@ -304,45 +299,6 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( | |||
304 | 299 | ||
305 | return pdata; | 300 | return pdata; |
306 | } | 301 | } |
307 | |||
308 | static void samsung_keypad_parse_dt_gpio(struct device *dev, | ||
309 | struct samsung_keypad *keypad) | ||
310 | { | ||
311 | struct device_node *np = dev->of_node; | ||
312 | int gpio, error, row, col; | ||
313 | |||
314 | for (row = 0; row < keypad->rows; row++) { | ||
315 | gpio = of_get_named_gpio(np, "row-gpios", row); | ||
316 | keypad->row_gpios[row] = gpio; | ||
317 | if (!gpio_is_valid(gpio)) { | ||
318 | dev_err(dev, "keypad row[%d]: invalid gpio %d\n", | ||
319 | row, gpio); | ||
320 | continue; | ||
321 | } | ||
322 | |||
323 | error = devm_gpio_request(dev, gpio, "keypad-row"); | ||
324 | if (error) | ||
325 | dev_err(dev, | ||
326 | "keypad row[%d] gpio request failed: %d\n", | ||
327 | row, error); | ||
328 | } | ||
329 | |||
330 | for (col = 0; col < keypad->cols; col++) { | ||
331 | gpio = of_get_named_gpio(np, "col-gpios", col); | ||
332 | keypad->col_gpios[col] = gpio; | ||
333 | if (!gpio_is_valid(gpio)) { | ||
334 | dev_err(dev, "keypad column[%d]: invalid gpio %d\n", | ||
335 | col, gpio); | ||
336 | continue; | ||
337 | } | ||
338 | |||
339 | error = devm_gpio_request(dev, gpio, "keypad-col"); | ||
340 | if (error) | ||
341 | dev_err(dev, | ||
342 | "keypad column[%d] gpio request failed: %d\n", | ||
343 | col, error); | ||
344 | } | ||
345 | } | ||
346 | #else | 302 | #else |
347 | static | 303 | static |
348 | struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) | 304 | struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) |
@@ -424,15 +380,11 @@ static int samsung_keypad_probe(struct platform_device *pdev) | |||
424 | keypad->stopped = true; | 380 | keypad->stopped = true; |
425 | init_waitqueue_head(&keypad->wait); | 381 | init_waitqueue_head(&keypad->wait); |
426 | 382 | ||
427 | if (pdev->dev.of_node) { | 383 | if (pdev->dev.of_node) |
428 | #ifdef CONFIG_OF | ||
429 | samsung_keypad_parse_dt_gpio(&pdev->dev, keypad); | ||
430 | keypad->type = of_device_is_compatible(pdev->dev.of_node, | 384 | keypad->type = of_device_is_compatible(pdev->dev.of_node, |
431 | "samsung,s5pv210-keypad"); | 385 | "samsung,s5pv210-keypad"); |
432 | #endif | 386 | else |
433 | } else { | ||
434 | keypad->type = platform_get_device_id(pdev)->driver_data; | 387 | keypad->type = platform_get_device_id(pdev)->driver_data; |
435 | } | ||
436 | 388 | ||
437 | input_dev->name = pdev->name; | 389 | input_dev->name = pdev->name; |
438 | input_dev->id.bustype = BUS_HOST; | 390 | input_dev->id.bustype = BUS_HOST; |
@@ -487,7 +439,6 @@ static int samsung_keypad_probe(struct platform_device *pdev) | |||
487 | err_disable_runtime_pm: | 439 | err_disable_runtime_pm: |
488 | pm_runtime_disable(&pdev->dev); | 440 | pm_runtime_disable(&pdev->dev); |
489 | device_init_wakeup(&pdev->dev, 0); | 441 | device_init_wakeup(&pdev->dev, 0); |
490 | platform_set_drvdata(pdev, NULL); | ||
491 | err_unprepare_clk: | 442 | err_unprepare_clk: |
492 | clk_unprepare(keypad->clk); | 443 | clk_unprepare(keypad->clk); |
493 | return error; | 444 | return error; |
@@ -499,7 +450,6 @@ static int samsung_keypad_remove(struct platform_device *pdev) | |||
499 | 450 | ||
500 | pm_runtime_disable(&pdev->dev); | 451 | pm_runtime_disable(&pdev->dev); |
501 | device_init_wakeup(&pdev->dev, 0); | 452 | device_init_wakeup(&pdev->dev, 0); |
502 | platform_set_drvdata(pdev, NULL); | ||
503 | 453 | ||
504 | input_unregister_device(keypad->input_dev); | 454 | input_unregister_device(keypad->input_dev); |
505 | 455 | ||
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index fdb9eb2df380..fe0e498d2479 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c | |||
@@ -266,7 +266,6 @@ static int sh_keysc_probe(struct platform_device *pdev) | |||
266 | err2: | 266 | err2: |
267 | iounmap(priv->iomem_base); | 267 | iounmap(priv->iomem_base); |
268 | err1: | 268 | err1: |
269 | platform_set_drvdata(pdev, NULL); | ||
270 | kfree(priv); | 269 | kfree(priv); |
271 | err0: | 270 | err0: |
272 | return error; | 271 | return error; |
@@ -285,7 +284,6 @@ static int sh_keysc_remove(struct platform_device *pdev) | |||
285 | pm_runtime_put_sync(&pdev->dev); | 284 | pm_runtime_put_sync(&pdev->dev); |
286 | pm_runtime_disable(&pdev->dev); | 285 | pm_runtime_disable(&pdev->dev); |
287 | 286 | ||
288 | platform_set_drvdata(pdev, NULL); | ||
289 | kfree(priv); | 287 | kfree(priv); |
290 | 288 | ||
291 | return 0; | 289 | return 0; |
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index cb1e8f614631..7111124b5362 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c | |||
@@ -290,7 +290,6 @@ static int spear_kbd_remove(struct platform_device *pdev) | |||
290 | clk_unprepare(kbd->clk); | 290 | clk_unprepare(kbd->clk); |
291 | 291 | ||
292 | device_init_wakeup(&pdev->dev, 0); | 292 | device_init_wakeup(&pdev->dev, 0); |
293 | platform_set_drvdata(pdev, NULL); | ||
294 | 293 | ||
295 | return 0; | 294 | return 0; |
296 | } | 295 | } |
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index ee1635011292..5f7b427dd7ed 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c | |||
@@ -296,7 +296,6 @@ error_clk: | |||
296 | error_map: | 296 | error_map: |
297 | release_mem_region(kp->res->start, resource_size(kp->res)); | 297 | release_mem_region(kp->res->start, resource_size(kp->res)); |
298 | error_res: | 298 | error_res: |
299 | platform_set_drvdata(pdev, NULL); | ||
300 | kfree(kp); | 299 | kfree(kp); |
301 | return error; | 300 | return error; |
302 | } | 301 | } |
@@ -311,7 +310,6 @@ static int keypad_remove(struct platform_device *pdev) | |||
311 | clk_put(kp->clk); | 310 | clk_put(kp->clk); |
312 | iounmap(kp->regs); | 311 | iounmap(kp->regs); |
313 | release_mem_region(kp->res->start, resource_size(kp->res)); | 312 | release_mem_region(kp->res->start, resource_size(kp->res)); |
314 | platform_set_drvdata(pdev, NULL); | ||
315 | kfree(kp); | 313 | kfree(kp); |
316 | 314 | ||
317 | return 0; | 315 | return 0; |
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 04f84fd57173..d2d178c84ea7 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
@@ -422,7 +422,7 @@ static int twl4030_kp_probe(struct platform_device *pdev) | |||
422 | err3: | 422 | err3: |
423 | /* mask all events - we don't care about the result */ | 423 | /* mask all events - we don't care about the result */ |
424 | (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); | 424 | (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); |
425 | free_irq(kp->irq, NULL); | 425 | free_irq(kp->irq, kp); |
426 | err2: | 426 | err2: |
427 | input_unregister_device(input); | 427 | input_unregister_device(input); |
428 | input = NULL; | 428 | input = NULL; |
@@ -438,7 +438,6 @@ static int twl4030_kp_remove(struct platform_device *pdev) | |||
438 | 438 | ||
439 | free_irq(kp->irq, kp); | 439 | free_irq(kp->irq, kp); |
440 | input_unregister_device(kp->input); | 440 | input_unregister_device(kp->input); |
441 | platform_set_drvdata(pdev, NULL); | ||
442 | kfree(kp); | 441 | kfree(kp); |
443 | 442 | ||
444 | return 0; | 443 | return 0; |
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index ee163bee8cce..7b039162a3f8 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
@@ -221,7 +221,7 @@ static int w90p910_keypad_probe(struct platform_device *pdev) | |||
221 | return 0; | 221 | return 0; |
222 | 222 | ||
223 | failed_free_irq: | 223 | failed_free_irq: |
224 | free_irq(irq, pdev); | 224 | free_irq(irq, keypad); |
225 | failed_put_clk: | 225 | failed_put_clk: |
226 | clk_put(keypad->clk); | 226 | clk_put(keypad->clk); |
227 | failed_free_io: | 227 | failed_free_io: |
@@ -239,7 +239,7 @@ static int w90p910_keypad_remove(struct platform_device *pdev) | |||
239 | struct w90p910_keypad *keypad = platform_get_drvdata(pdev); | 239 | struct w90p910_keypad *keypad = platform_get_drvdata(pdev); |
240 | struct resource *res; | 240 | struct resource *res; |
241 | 241 | ||
242 | free_irq(keypad->irq, pdev); | 242 | free_irq(keypad->irq, keypad); |
243 | 243 | ||
244 | clk_put(keypad->clk); | 244 | clk_put(keypad->clk); |
245 | 245 | ||
@@ -249,7 +249,6 @@ static int w90p910_keypad_remove(struct platform_device *pdev) | |||
249 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 249 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
250 | release_mem_region(res->start, resource_size(res)); | 250 | release_mem_region(res->start, resource_size(res)); |
251 | 251 | ||
252 | platform_set_drvdata(pdev, NULL); | ||
253 | kfree(keypad); | 252 | kfree(keypad); |
254 | 253 | ||
255 | return 0; | 254 | return 0; |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index bb698e1f9e42..0b541cdf9b8e 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -637,4 +637,14 @@ config INPUT_XEN_KBDDEV_FRONTEND | |||
637 | To compile this driver as a module, choose M here: the | 637 | To compile this driver as a module, choose M here: the |
638 | module will be called xen-kbdfront. | 638 | module will be called xen-kbdfront. |
639 | 639 | ||
640 | config INPUT_SIRFSOC_ONKEY | ||
641 | bool "CSR SiRFSoC power on/off/suspend key support" | ||
642 | depends on ARCH_SIRF && OF | ||
643 | default y | ||
644 | help | ||
645 | Say Y here if you want to support for the SiRFSoC power on/off/suspend key | ||
646 | in Linux, after you press the onkey, system will suspend. | ||
647 | |||
648 | If unsure, say N. | ||
649 | |||
640 | endif | 650 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index d7fc17f11d77..829de43a2427 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -51,6 +51,7 @@ obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o | |||
51 | obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o | 51 | obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o |
52 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o | 52 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o |
53 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | 53 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o |
54 | obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o | ||
54 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 55 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o |
55 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o | 56 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o |
56 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o | 57 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o |
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c index 2f090b46e716..f2fbdd88ed20 100644 --- a/drivers/input/misc/ab8500-ponkey.c +++ b/drivers/input/misc/ab8500-ponkey.c | |||
@@ -127,8 +127,6 @@ static int ab8500_ponkey_remove(struct platform_device *pdev) | |||
127 | input_unregister_device(ponkey->idev); | 127 | input_unregister_device(ponkey->idev); |
128 | kfree(ponkey); | 128 | kfree(ponkey); |
129 | 129 | ||
130 | platform_set_drvdata(pdev, NULL); | ||
131 | |||
132 | return 0; | 130 | return 0; |
133 | } | 131 | } |
134 | 132 | ||
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index a6666e142a91..cd139cb17e32 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c | |||
@@ -208,7 +208,6 @@ static int bfin_rotary_remove(struct platform_device *pdev) | |||
208 | peripheral_free_list(per_cnt); | 208 | peripheral_free_list(per_cnt); |
209 | 209 | ||
210 | kfree(rotary); | 210 | kfree(rotary); |
211 | platform_set_drvdata(pdev, NULL); | ||
212 | 211 | ||
213 | return 0; | 212 | return 0; |
214 | } | 213 | } |
diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c index da05cca8b562..714c68369134 100644 --- a/drivers/input/misc/gpio_tilt_polled.c +++ b/drivers/input/misc/gpio_tilt_polled.c | |||
@@ -184,8 +184,6 @@ static int gpio_tilt_polled_remove(struct platform_device *pdev) | |||
184 | struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev); | 184 | struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev); |
185 | const struct gpio_tilt_platform_data *pdata = tdev->pdata; | 185 | const struct gpio_tilt_platform_data *pdata = tdev->pdata; |
186 | 186 | ||
187 | platform_set_drvdata(pdev, NULL); | ||
188 | |||
189 | input_unregister_polled_device(tdev->poll_dev); | 187 | input_unregister_polled_device(tdev->poll_dev); |
190 | input_free_polled_device(tdev->poll_dev); | 188 | input_free_polled_device(tdev->poll_dev); |
191 | 189 | ||
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index 6ab3decc86e6..f34beb228d36 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c | |||
@@ -125,7 +125,7 @@ static int ixp4xx_spkr_probe(struct platform_device *dev) | |||
125 | return 0; | 125 | return 0; |
126 | 126 | ||
127 | err_free_irq: | 127 | err_free_irq: |
128 | free_irq(IRQ_IXP4XX_TIMER2, dev); | 128 | free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id); |
129 | err_free_device: | 129 | err_free_device: |
130 | input_free_device(input_dev); | 130 | input_free_device(input_dev); |
131 | 131 | ||
@@ -138,13 +138,12 @@ static int ixp4xx_spkr_remove(struct platform_device *dev) | |||
138 | unsigned int pin = (unsigned int) input_get_drvdata(input_dev); | 138 | unsigned int pin = (unsigned int) input_get_drvdata(input_dev); |
139 | 139 | ||
140 | input_unregister_device(input_dev); | 140 | input_unregister_device(input_dev); |
141 | platform_set_drvdata(dev, NULL); | ||
142 | 141 | ||
143 | /* turn the speaker off */ | 142 | /* turn the speaker off */ |
144 | disable_irq(IRQ_IXP4XX_TIMER2); | 143 | disable_irq(IRQ_IXP4XX_TIMER2); |
145 | ixp4xx_spkr_control(pin, 0); | 144 | ixp4xx_spkr_control(pin, 0); |
146 | 145 | ||
147 | free_irq(IRQ_IXP4XX_TIMER2, dev); | 146 | free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id); |
148 | 147 | ||
149 | return 0; | 148 | return 0; |
150 | } | 149 | } |
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c index b40ee4b47f4f..def21dc84522 100644 --- a/drivers/input/misc/m68kspkr.c +++ b/drivers/input/misc/m68kspkr.c | |||
@@ -85,7 +85,6 @@ static int m68kspkr_remove(struct platform_device *dev) | |||
85 | struct input_dev *input_dev = platform_get_drvdata(dev); | 85 | struct input_dev *input_dev = platform_get_drvdata(dev); |
86 | 86 | ||
87 | input_unregister_device(input_dev); | 87 | input_unregister_device(input_dev); |
88 | platform_set_drvdata(dev, NULL); | ||
89 | /* turn off the speaker */ | 88 | /* turn off the speaker */ |
90 | m68kspkr_event(NULL, EV_SND, SND_BELL, 0); | 89 | m68kspkr_event(NULL, EV_SND, SND_BELL, 0); |
91 | 90 | ||
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c index f9179b2585a9..eef41cfc054d 100644 --- a/drivers/input/misc/max8925_onkey.c +++ b/drivers/input/misc/max8925_onkey.c | |||
@@ -148,8 +148,6 @@ static int max8925_onkey_remove(struct platform_device *pdev) | |||
148 | input_unregister_device(info->idev); | 148 | input_unregister_device(info->idev); |
149 | kfree(info); | 149 | kfree(info); |
150 | 150 | ||
151 | platform_set_drvdata(pdev, NULL); | ||
152 | |||
153 | return 0; | 151 | return 0; |
154 | } | 152 | } |
155 | 153 | ||
diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c index 0906ca593d5f..d0277a7b1579 100644 --- a/drivers/input/misc/mc13783-pwrbutton.c +++ b/drivers/input/misc/mc13783-pwrbutton.c | |||
@@ -250,7 +250,6 @@ static int mc13783_pwrbutton_remove(struct platform_device *pdev) | |||
250 | 250 | ||
251 | input_unregister_device(priv->pwr); | 251 | input_unregister_device(priv->pwr); |
252 | kfree(priv); | 252 | kfree(priv); |
253 | platform_set_drvdata(pdev, NULL); | ||
254 | 253 | ||
255 | return 0; | 254 | return 0; |
256 | } | 255 | } |
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 199db78acc4f..7288b267613d 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
@@ -100,7 +100,6 @@ static int pcspkr_remove(struct platform_device *dev) | |||
100 | struct input_dev *pcspkr_dev = platform_get_drvdata(dev); | 100 | struct input_dev *pcspkr_dev = platform_get_drvdata(dev); |
101 | 101 | ||
102 | input_unregister_device(pcspkr_dev); | 102 | input_unregister_device(pcspkr_dev); |
103 | platform_set_drvdata(dev, NULL); | ||
104 | /* turn off the speaker */ | 103 | /* turn off the speaker */ |
105 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); | 104 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); |
106 | 105 | ||
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index a9da65e41c5b..ec086f6f3cc3 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c | |||
@@ -249,8 +249,6 @@ static int pm8xxx_vib_remove(struct platform_device *pdev) | |||
249 | input_unregister_device(vib->vib_input_dev); | 249 | input_unregister_device(vib->vib_input_dev); |
250 | kfree(vib); | 250 | kfree(vib); |
251 | 251 | ||
252 | platform_set_drvdata(pdev, NULL); | ||
253 | |||
254 | return 0; | 252 | return 0; |
255 | } | 253 | } |
256 | 254 | ||
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index 4b811be73974..b49b738aa9c6 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c | |||
@@ -175,9 +175,8 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
175 | return 0; | 175 | return 0; |
176 | 176 | ||
177 | free_press_irq: | 177 | free_press_irq: |
178 | free_irq(key_press_irq, NULL); | 178 | free_irq(key_press_irq, pwrkey); |
179 | unreg_input_dev: | 179 | unreg_input_dev: |
180 | platform_set_drvdata(pdev, NULL); | ||
181 | input_unregister_device(pwr); | 180 | input_unregister_device(pwr); |
182 | pwr = NULL; | 181 | pwr = NULL; |
183 | free_input_dev: | 182 | free_input_dev: |
@@ -198,7 +197,6 @@ static int pmic8xxx_pwrkey_remove(struct platform_device *pdev) | |||
198 | free_irq(key_press_irq, pwrkey); | 197 | free_irq(key_press_irq, pwrkey); |
199 | free_irq(key_release_irq, pwrkey); | 198 | free_irq(key_release_irq, pwrkey); |
200 | input_unregister_device(pwrkey->pwr); | 199 | input_unregister_device(pwrkey->pwr); |
201 | platform_set_drvdata(pdev, NULL); | ||
202 | kfree(pwrkey); | 200 | kfree(pwrkey); |
203 | 201 | ||
204 | return 0; | 202 | return 0; |
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index 0808868461de..a37f0c909aba 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c | |||
@@ -133,7 +133,6 @@ static int pwm_beeper_remove(struct platform_device *pdev) | |||
133 | { | 133 | { |
134 | struct pwm_beeper *beeper = platform_get_drvdata(pdev); | 134 | struct pwm_beeper *beeper = platform_get_drvdata(pdev); |
135 | 135 | ||
136 | platform_set_drvdata(pdev, NULL); | ||
137 | input_unregister_device(beeper->input); | 136 | input_unregister_device(beeper->input); |
138 | 137 | ||
139 | pwm_disable(beeper->pwm); | 138 | pwm_disable(beeper->pwm); |
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index aff47b2c38ff..5b1aff825138 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
@@ -317,8 +317,6 @@ static int rotary_encoder_remove(struct platform_device *pdev) | |||
317 | if (!dev_get_platdata(&pdev->dev)) | 317 | if (!dev_get_platdata(&pdev->dev)) |
318 | kfree(pdata); | 318 | kfree(pdata); |
319 | 319 | ||
320 | platform_set_drvdata(pdev, NULL); | ||
321 | |||
322 | return 0; | 320 | return 0; |
323 | } | 321 | } |
324 | 322 | ||
diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index ad6415ceaf5f..95cf299ef9a3 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c | |||
@@ -128,7 +128,7 @@ static int sgi_buttons_probe(struct platform_device *pdev) | |||
128 | __clear_bit(KEY_RESERVED, input->keybit); | 128 | __clear_bit(KEY_RESERVED, input->keybit); |
129 | 129 | ||
130 | bdev->poll_dev = poll_dev; | 130 | bdev->poll_dev = poll_dev; |
131 | dev_set_drvdata(&pdev->dev, bdev); | 131 | platform_set_drvdata(pdev, bdev); |
132 | 132 | ||
133 | error = input_register_polled_device(poll_dev); | 133 | error = input_register_polled_device(poll_dev); |
134 | if (error) | 134 | if (error) |
@@ -139,19 +139,16 @@ static int sgi_buttons_probe(struct platform_device *pdev) | |||
139 | err_free_mem: | 139 | err_free_mem: |
140 | input_free_polled_device(poll_dev); | 140 | input_free_polled_device(poll_dev); |
141 | kfree(bdev); | 141 | kfree(bdev); |
142 | dev_set_drvdata(&pdev->dev, NULL); | ||
143 | return error; | 142 | return error; |
144 | } | 143 | } |
145 | 144 | ||
146 | static int sgi_buttons_remove(struct platform_device *pdev) | 145 | static int sgi_buttons_remove(struct platform_device *pdev) |
147 | { | 146 | { |
148 | struct device *dev = &pdev->dev; | 147 | struct buttons_dev *bdev = platform_get_drvdata(pdev); |
149 | struct buttons_dev *bdev = dev_get_drvdata(dev); | ||
150 | 148 | ||
151 | input_unregister_polled_device(bdev->poll_dev); | 149 | input_unregister_polled_device(bdev->poll_dev); |
152 | input_free_polled_device(bdev->poll_dev); | 150 | input_free_polled_device(bdev->poll_dev); |
153 | kfree(bdev); | 151 | kfree(bdev); |
154 | dev_set_drvdata(dev, NULL); | ||
155 | 152 | ||
156 | return 0; | 153 | return 0; |
157 | } | 154 | } |
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c new file mode 100644 index 000000000000..0621c367049a --- /dev/null +++ b/drivers/input/misc/sirfsoc-onkey.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Power key driver for SiRF PrimaII | ||
3 | * | ||
4 | * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/rtc/sirfsoc_rtciobrg.h> | ||
16 | #include <linux/of.h> | ||
17 | |||
18 | struct sirfsoc_pwrc_drvdata { | ||
19 | u32 pwrc_base; | ||
20 | struct input_dev *input; | ||
21 | }; | ||
22 | |||
23 | #define PWRC_ON_KEY_BIT (1 << 0) | ||
24 | |||
25 | #define PWRC_INT_STATUS 0xc | ||
26 | #define PWRC_INT_MASK 0x10 | ||
27 | |||
28 | static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) | ||
29 | { | ||
30 | struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_id; | ||
31 | u32 int_status; | ||
32 | |||
33 | int_status = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + | ||
34 | PWRC_INT_STATUS); | ||
35 | sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, | ||
36 | pwrcdrv->pwrc_base + PWRC_INT_STATUS); | ||
37 | |||
38 | /* | ||
39 | * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c | ||
40 | * to queue a SUSPEND APM event | ||
41 | */ | ||
42 | input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1); | ||
43 | input_sync(pwrcdrv->input); | ||
44 | |||
45 | /* | ||
46 | * Todo: report KEY_POWER event for Android platforms, Android PowerManager | ||
47 | * will handle the suspend and powerdown/hibernation | ||
48 | */ | ||
49 | |||
50 | return IRQ_HANDLED; | ||
51 | } | ||
52 | |||
53 | static const struct of_device_id sirfsoc_pwrc_of_match[] = { | ||
54 | { .compatible = "sirf,prima2-pwrc" }, | ||
55 | {}, | ||
56 | } | ||
57 | MODULE_DEVICE_TABLE(of, sirfsoc_pwrc_of_match); | ||
58 | |||
59 | static int sirfsoc_pwrc_probe(struct platform_device *pdev) | ||
60 | { | ||
61 | struct device_node *np = pdev->dev.of_node; | ||
62 | struct sirfsoc_pwrc_drvdata *pwrcdrv; | ||
63 | int irq; | ||
64 | int error; | ||
65 | |||
66 | pwrcdrv = devm_kzalloc(&pdev->dev, sizeof(struct sirfsoc_pwrc_drvdata), | ||
67 | GFP_KERNEL); | ||
68 | if (!pwrcdrv) { | ||
69 | dev_info(&pdev->dev, "Not enough memory for the device data\n"); | ||
70 | return -ENOMEM; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * we can't use of_iomap because pwrc is not mapped in memory, | ||
75 | * the so-called base address is only offset in rtciobrg | ||
76 | */ | ||
77 | error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); | ||
78 | if (error) { | ||
79 | dev_err(&pdev->dev, | ||
80 | "unable to find base address of pwrc node in dtb\n"); | ||
81 | return error; | ||
82 | } | ||
83 | |||
84 | pwrcdrv->input = devm_input_allocate_device(&pdev->dev); | ||
85 | if (!pwrcdrv->input) | ||
86 | return -ENOMEM; | ||
87 | |||
88 | pwrcdrv->input->name = "sirfsoc pwrckey"; | ||
89 | pwrcdrv->input->phys = "pwrc/input0"; | ||
90 | pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR); | ||
91 | |||
92 | irq = platform_get_irq(pdev, 0); | ||
93 | error = devm_request_irq(&pdev->dev, irq, | ||
94 | sirfsoc_pwrc_isr, IRQF_SHARED, | ||
95 | "sirfsoc_pwrc_int", pwrcdrv); | ||
96 | if (error) { | ||
97 | dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", | ||
98 | irq, error); | ||
99 | return error; | ||
100 | } | ||
101 | |||
102 | sirfsoc_rtc_iobrg_writel( | ||
103 | sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) | | ||
104 | PWRC_ON_KEY_BIT, | ||
105 | pwrcdrv->pwrc_base + PWRC_INT_MASK); | ||
106 | |||
107 | error = input_register_device(pwrcdrv->input); | ||
108 | if (error) { | ||
109 | dev_err(&pdev->dev, | ||
110 | "unable to register input device, error: %d\n", | ||
111 | error); | ||
112 | return error; | ||
113 | } | ||
114 | |||
115 | platform_set_drvdata(pdev, pwrcdrv); | ||
116 | device_init_wakeup(&pdev->dev, 1); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int sirfsoc_pwrc_remove(struct platform_device *pdev) | ||
122 | { | ||
123 | device_init_wakeup(&pdev->dev, 0); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | #ifdef CONFIG_PM_SLEEP | ||
129 | static int pwrc_resume(struct device *dev) | ||
130 | { | ||
131 | struct platform_device *pdev = to_platform_device(dev); | ||
132 | struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev); | ||
133 | |||
134 | /* | ||
135 | * Do not mask pwrc interrupt as we want pwrc work as a wakeup source | ||
136 | * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c | ||
137 | */ | ||
138 | sirfsoc_rtc_iobrg_writel( | ||
139 | sirfsoc_rtc_iobrg_readl( | ||
140 | pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT, | ||
141 | pwrcdrv->pwrc_base + PWRC_INT_MASK); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | #endif | ||
146 | |||
147 | static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume); | ||
148 | |||
149 | static struct platform_driver sirfsoc_pwrc_driver = { | ||
150 | .probe = sirfsoc_pwrc_probe, | ||
151 | .remove = sirfsoc_pwrc_remove, | ||
152 | .driver = { | ||
153 | .name = "sirfsoc-pwrc", | ||
154 | .owner = THIS_MODULE, | ||
155 | .pm = &sirfsoc_pwrc_pm_ops, | ||
156 | .of_match_table = of_match_ptr(sirfsoc_pwrc_of_match), | ||
157 | } | ||
158 | }; | ||
159 | |||
160 | module_platform_driver(sirfsoc_pwrc_driver); | ||
161 | |||
162 | MODULE_LICENSE("GPLv2"); | ||
163 | MODULE_AUTHOR("Binghua Duan <Binghua.Duan@csr.com>, Xianglong Du <Xianglong.Du@csr.com>"); | ||
164 | MODULE_DESCRIPTION("CSR Prima2 PWRC Driver"); | ||
165 | MODULE_ALIAS("platform:sirfsoc-pwrc"); | ||
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index a53586a7fbdb..65fd3150919b 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c | |||
@@ -175,7 +175,7 @@ static int sparcspkr_probe(struct device *dev) | |||
175 | 175 | ||
176 | static void sparcspkr_shutdown(struct platform_device *dev) | 176 | static void sparcspkr_shutdown(struct platform_device *dev) |
177 | { | 177 | { |
178 | struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); | 178 | struct sparcspkr_state *state = platform_get_drvdata(dev); |
179 | struct input_dev *input_dev = state->input_dev; | 179 | struct input_dev *input_dev = state->input_dev; |
180 | 180 | ||
181 | /* turn off the speaker */ | 181 | /* turn off the speaker */ |
@@ -211,7 +211,7 @@ static int bbc_beep_probe(struct platform_device *op) | |||
211 | if (!info->regs) | 211 | if (!info->regs) |
212 | goto out_free; | 212 | goto out_free; |
213 | 213 | ||
214 | dev_set_drvdata(&op->dev, state); | 214 | platform_set_drvdata(op, state); |
215 | 215 | ||
216 | err = sparcspkr_probe(&op->dev); | 216 | err = sparcspkr_probe(&op->dev); |
217 | if (err) | 217 | if (err) |
@@ -220,7 +220,6 @@ static int bbc_beep_probe(struct platform_device *op) | |||
220 | return 0; | 220 | return 0; |
221 | 221 | ||
222 | out_clear_drvdata: | 222 | out_clear_drvdata: |
223 | dev_set_drvdata(&op->dev, NULL); | ||
224 | of_iounmap(&op->resource[0], info->regs, 6); | 223 | of_iounmap(&op->resource[0], info->regs, 6); |
225 | 224 | ||
226 | out_free: | 225 | out_free: |
@@ -231,7 +230,7 @@ out_err: | |||
231 | 230 | ||
232 | static int bbc_remove(struct platform_device *op) | 231 | static int bbc_remove(struct platform_device *op) |
233 | { | 232 | { |
234 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); | 233 | struct sparcspkr_state *state = platform_get_drvdata(op); |
235 | struct input_dev *input_dev = state->input_dev; | 234 | struct input_dev *input_dev = state->input_dev; |
236 | struct bbc_beep_info *info = &state->u.bbc; | 235 | struct bbc_beep_info *info = &state->u.bbc; |
237 | 236 | ||
@@ -242,7 +241,6 @@ static int bbc_remove(struct platform_device *op) | |||
242 | 241 | ||
243 | of_iounmap(&op->resource[0], info->regs, 6); | 242 | of_iounmap(&op->resource[0], info->regs, 6); |
244 | 243 | ||
245 | dev_set_drvdata(&op->dev, NULL); | ||
246 | kfree(state); | 244 | kfree(state); |
247 | 245 | ||
248 | return 0; | 246 | return 0; |
@@ -290,7 +288,7 @@ static int grover_beep_probe(struct platform_device *op) | |||
290 | if (!info->enable_reg) | 288 | if (!info->enable_reg) |
291 | goto out_unmap_freq_regs; | 289 | goto out_unmap_freq_regs; |
292 | 290 | ||
293 | dev_set_drvdata(&op->dev, state); | 291 | platform_set_drvdata(op, state); |
294 | 292 | ||
295 | err = sparcspkr_probe(&op->dev); | 293 | err = sparcspkr_probe(&op->dev); |
296 | if (err) | 294 | if (err) |
@@ -299,7 +297,6 @@ static int grover_beep_probe(struct platform_device *op) | |||
299 | return 0; | 297 | return 0; |
300 | 298 | ||
301 | out_clear_drvdata: | 299 | out_clear_drvdata: |
302 | dev_set_drvdata(&op->dev, NULL); | ||
303 | of_iounmap(&op->resource[3], info->enable_reg, 1); | 300 | of_iounmap(&op->resource[3], info->enable_reg, 1); |
304 | 301 | ||
305 | out_unmap_freq_regs: | 302 | out_unmap_freq_regs: |
@@ -312,7 +309,7 @@ out_err: | |||
312 | 309 | ||
313 | static int grover_remove(struct platform_device *op) | 310 | static int grover_remove(struct platform_device *op) |
314 | { | 311 | { |
315 | struct sparcspkr_state *state = dev_get_drvdata(&op->dev); | 312 | struct sparcspkr_state *state = platform_get_drvdata(op); |
316 | struct grover_beep_info *info = &state->u.grover; | 313 | struct grover_beep_info *info = &state->u.grover; |
317 | struct input_dev *input_dev = state->input_dev; | 314 | struct input_dev *input_dev = state->input_dev; |
318 | 315 | ||
@@ -324,7 +321,6 @@ static int grover_remove(struct platform_device *op) | |||
324 | of_iounmap(&op->resource[3], info->enable_reg, 1); | 321 | of_iounmap(&op->resource[3], info->enable_reg, 1); |
325 | of_iounmap(&op->resource[2], info->freq_regs, 2); | 322 | of_iounmap(&op->resource[2], info->freq_regs, 2); |
326 | 323 | ||
327 | dev_set_drvdata(&op->dev, NULL); | ||
328 | kfree(state); | 324 | kfree(state); |
329 | 325 | ||
330 | return 0; | 326 | return 0; |
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index b55d5af217a7..62ec52b2e347 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c | |||
@@ -133,7 +133,6 @@ static int __exit amimouse_remove(struct platform_device *pdev) | |||
133 | { | 133 | { |
134 | struct input_dev *dev = platform_get_drvdata(pdev); | 134 | struct input_dev *dev = platform_get_drvdata(pdev); |
135 | 135 | ||
136 | platform_set_drvdata(pdev, NULL); | ||
137 | input_unregister_device(dev); | 136 | input_unregister_device(dev); |
138 | return 0; | 137 | return 0; |
139 | } | 138 | } |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2baff1b79a55..4ef4d5e198ae 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -88,6 +88,10 @@ | |||
88 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 | 88 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 |
89 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a | 89 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a |
90 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b | 90 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b |
91 | /* MacbookAir6,2 (unibody, June 2013) */ | ||
92 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0291 | ||
93 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0292 | ||
94 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0293 | ||
91 | 95 | ||
92 | #define BCM5974_DEVICE(prod) { \ | 96 | #define BCM5974_DEVICE(prod) { \ |
93 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ | 97 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ |
@@ -145,6 +149,10 @@ static const struct usb_device_id bcm5974_table[] = { | |||
145 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), | 149 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), |
146 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), | 150 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), |
147 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), | 151 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), |
152 | /* MacbookAir6,2 */ | ||
153 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI), | ||
154 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ISO), | ||
155 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_JIS), | ||
148 | /* Terminating entry */ | 156 | /* Terminating entry */ |
149 | {} | 157 | {} |
150 | }; | 158 | }; |
@@ -172,15 +180,18 @@ struct bt_data { | |||
172 | /* trackpad header types */ | 180 | /* trackpad header types */ |
173 | enum tp_type { | 181 | enum tp_type { |
174 | TYPE1, /* plain trackpad */ | 182 | TYPE1, /* plain trackpad */ |
175 | TYPE2 /* button integrated in trackpad */ | 183 | TYPE2, /* button integrated in trackpad */ |
184 | TYPE3 /* additional header fields since June 2013 */ | ||
176 | }; | 185 | }; |
177 | 186 | ||
178 | /* trackpad finger data offsets, le16-aligned */ | 187 | /* trackpad finger data offsets, le16-aligned */ |
179 | #define FINGER_TYPE1 (13 * sizeof(__le16)) | 188 | #define FINGER_TYPE1 (13 * sizeof(__le16)) |
180 | #define FINGER_TYPE2 (15 * sizeof(__le16)) | 189 | #define FINGER_TYPE2 (15 * sizeof(__le16)) |
190 | #define FINGER_TYPE3 (19 * sizeof(__le16)) | ||
181 | 191 | ||
182 | /* trackpad button data offsets */ | 192 | /* trackpad button data offsets */ |
183 | #define BUTTON_TYPE2 15 | 193 | #define BUTTON_TYPE2 15 |
194 | #define BUTTON_TYPE3 23 | ||
184 | 195 | ||
185 | /* list of device capability bits */ | 196 | /* list of device capability bits */ |
186 | #define HAS_INTEGRATED_BUTTON 1 | 197 | #define HAS_INTEGRATED_BUTTON 1 |
@@ -400,6 +411,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { | |||
400 | { SN_COORD, -150, 6730 }, | 411 | { SN_COORD, -150, 6730 }, |
401 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } | 412 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } |
402 | }, | 413 | }, |
414 | { | ||
415 | USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI, | ||
416 | USB_DEVICE_ID_APPLE_WELLSPRING8_ISO, | ||
417 | USB_DEVICE_ID_APPLE_WELLSPRING8_JIS, | ||
418 | HAS_INTEGRATED_BUTTON, | ||
419 | 0, sizeof(struct bt_data), | ||
420 | 0x83, TYPE3, FINGER_TYPE3, FINGER_TYPE3 + SIZEOF_ALL_FINGERS, | ||
421 | { SN_PRESSURE, 0, 300 }, | ||
422 | { SN_WIDTH, 0, 2048 }, | ||
423 | { SN_COORD, -4620, 5140 }, | ||
424 | { SN_COORD, -150, 6600 }, | ||
425 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } | ||
426 | }, | ||
403 | {} | 427 | {} |
404 | }; | 428 | }; |
405 | 429 | ||
@@ -557,6 +581,9 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
557 | input_report_key(input, BTN_LEFT, ibt); | 581 | input_report_key(input, BTN_LEFT, ibt); |
558 | } | 582 | } |
559 | 583 | ||
584 | if (c->tp_type == TYPE3) | ||
585 | input_report_key(input, BTN_LEFT, dev->tp_data[BUTTON_TYPE3]); | ||
586 | |||
560 | input_sync(input); | 587 | input_sync(input); |
561 | 588 | ||
562 | return 0; | 589 | return 0; |
@@ -572,9 +599,14 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
572 | 599 | ||
573 | static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) | 600 | static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) |
574 | { | 601 | { |
575 | char *data = kmalloc(8, GFP_KERNEL); | ||
576 | int retval = 0, size; | 602 | int retval = 0, size; |
603 | char *data; | ||
604 | |||
605 | /* Type 3 does not require a mode switch */ | ||
606 | if (dev->cfg.tp_type == TYPE3) | ||
607 | return 0; | ||
577 | 608 | ||
609 | data = kmalloc(8, GFP_KERNEL); | ||
578 | if (!data) { | 610 | if (!data) { |
579 | dev_err(&dev->intf->dev, "out of memory\n"); | 611 | dev_err(&dev->intf->dev, "out of memory\n"); |
580 | retval = -ENOMEM; | 612 | retval = -ENOMEM; |
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 532eaca4cc56..6b44413f54e3 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c | |||
@@ -138,7 +138,6 @@ static int gpio_mouse_probe(struct platform_device *pdev) | |||
138 | 138 | ||
139 | out_free_polldev: | 139 | out_free_polldev: |
140 | input_free_polled_device(input_poll); | 140 | input_free_polled_device(input_poll); |
141 | platform_set_drvdata(pdev, NULL); | ||
142 | 141 | ||
143 | out_free_gpios: | 142 | out_free_gpios: |
144 | while (--i >= 0) { | 143 | while (--i >= 0) { |
@@ -165,8 +164,6 @@ static int gpio_mouse_remove(struct platform_device *pdev) | |||
165 | gpio_free(pin); | 164 | gpio_free(pin); |
166 | } | 165 | } |
167 | 166 | ||
168 | platform_set_drvdata(pdev, NULL); | ||
169 | |||
170 | return 0; | 167 | return 0; |
171 | } | 168 | } |
172 | 169 | ||
diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c index 8e1b98ea5648..0b8d33591dee 100644 --- a/drivers/input/mouse/navpoint.c +++ b/drivers/input/mouse/navpoint.c | |||
@@ -287,7 +287,7 @@ static int navpoint_probe(struct platform_device *pdev) | |||
287 | return 0; | 287 | return 0; |
288 | 288 | ||
289 | err_free_irq: | 289 | err_free_irq: |
290 | free_irq(ssp->irq, &pdev->dev); | 290 | free_irq(ssp->irq, navpoint); |
291 | err_free_mem: | 291 | err_free_mem: |
292 | input_free_device(input); | 292 | input_free_device(input); |
293 | kfree(navpoint); | 293 | kfree(navpoint); |
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 1bda828f4b55..94c17c28d268 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
@@ -256,4 +256,14 @@ config SERIO_APBPS2 | |||
256 | To compile this driver as a module, choose M here: the module will | 256 | To compile this driver as a module, choose M here: the module will |
257 | be called apbps2. | 257 | be called apbps2. |
258 | 258 | ||
259 | config SERIO_OLPC_APSP | ||
260 | tristate "OLPC AP-SP input support" | ||
261 | depends on OF | ||
262 | help | ||
263 | Say Y here if you want support for the keyboard and touchpad included | ||
264 | in the OLPC XO-1.75 and XO-4 laptops. | ||
265 | |||
266 | To compile this driver as a module, choose M here: the module will | ||
267 | be called olpc_apsp. | ||
268 | |||
259 | endif | 269 | endif |
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 8edb36c2cdb4..12298b1c0e71 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile | |||
@@ -27,3 +27,4 @@ obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o | |||
27 | obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o | 27 | obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o |
28 | obj-$(CONFIG_SERIO_ARC_PS2) += arc_ps2.o | 28 | obj-$(CONFIG_SERIO_ARC_PS2) += arc_ps2.o |
29 | obj-$(CONFIG_SERIO_APBPS2) += apbps2.o | 29 | obj-$(CONFIG_SERIO_APBPS2) += apbps2.o |
30 | obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o | ||
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index 479ce5fe8955..a0a2657e31ff 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c | |||
@@ -163,7 +163,6 @@ static int altera_ps2_remove(struct platform_device *pdev) | |||
163 | { | 163 | { |
164 | struct ps2if *ps2if = platform_get_drvdata(pdev); | 164 | struct ps2if *ps2if = platform_get_drvdata(pdev); |
165 | 165 | ||
166 | platform_set_drvdata(pdev, NULL); | ||
167 | serio_unregister_port(ps2if->io); | 166 | serio_unregister_port(ps2if->io); |
168 | free_irq(ps2if->irq, ps2if); | 167 | free_irq(ps2if->irq, ps2if); |
169 | iounmap(ps2if->base); | 168 | iounmap(ps2if->base); |
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index 190ce35af7df..3290b287ac4b 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c | |||
@@ -314,8 +314,6 @@ static int __exit psif_remove(struct platform_device *pdev) | |||
314 | clk_put(psif->pclk); | 314 | clk_put(psif->pclk); |
315 | kfree(psif); | 315 | kfree(psif); |
316 | 316 | ||
317 | platform_set_drvdata(pdev, NULL); | ||
318 | |||
319 | return 0; | 317 | return 0; |
320 | } | 318 | } |
321 | 319 | ||
diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c new file mode 100644 index 000000000000..818aa466b5d2 --- /dev/null +++ b/drivers/input/serio/olpc_apsp.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /* | ||
2 | * OLPC serio driver for multiplexed input from Marvell MMP security processor | ||
3 | * | ||
4 | * Copyright (C) 2011-2013 One Laptop Per Child | ||
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 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/serio.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/delay.h> | ||
27 | |||
28 | /* | ||
29 | * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller. | ||
30 | * Instead, the OLPC firmware runs a bit-banging PS/2 implementation on an | ||
31 | * otherwise-unused slow processor which is included in the Marvell MMP2/MMP3 | ||
32 | * SoC, known as the "Security Processor" (SP) or "Wireless Trusted Module" | ||
33 | * (WTM). This firmware then reports its results via the WTM registers, | ||
34 | * which we read from the Application Processor (AP, i.e. main CPU) in this | ||
35 | * driver. | ||
36 | * | ||
37 | * On the hardware side we have a PS/2 mouse and an AT keyboard, the data | ||
38 | * is multiplexed through this system. We create a serio port for each one, | ||
39 | * and demultiplex the data accordingly. | ||
40 | */ | ||
41 | |||
42 | /* WTM register offsets */ | ||
43 | #define SECURE_PROCESSOR_COMMAND 0x40 | ||
44 | #define COMMAND_RETURN_STATUS 0x80 | ||
45 | #define COMMAND_FIFO_STATUS 0xc4 | ||
46 | #define PJ_RST_INTERRUPT 0xc8 | ||
47 | #define PJ_INTERRUPT_MASK 0xcc | ||
48 | |||
49 | /* | ||
50 | * The upper byte of SECURE_PROCESSOR_COMMAND and COMMAND_RETURN_STATUS is | ||
51 | * used to identify which port (device) is being talked to. The lower byte | ||
52 | * is the data being sent/received. | ||
53 | */ | ||
54 | #define PORT_MASK 0xff00 | ||
55 | #define DATA_MASK 0x00ff | ||
56 | #define PORT_SHIFT 8 | ||
57 | #define KEYBOARD_PORT 0 | ||
58 | #define TOUCHPAD_PORT 1 | ||
59 | |||
60 | /* COMMAND_FIFO_STATUS */ | ||
61 | #define CMD_CNTR_MASK 0x7 /* Number of pending/unprocessed commands */ | ||
62 | #define MAX_PENDING_CMDS 4 /* from device specs */ | ||
63 | |||
64 | /* PJ_RST_INTERRUPT */ | ||
65 | #define SP_COMMAND_COMPLETE_RESET 0x1 | ||
66 | |||
67 | /* PJ_INTERRUPT_MASK */ | ||
68 | #define INT_0 (1 << 0) | ||
69 | |||
70 | /* COMMAND_FIFO_STATUS */ | ||
71 | #define CMD_STS_MASK 0x100 | ||
72 | |||
73 | struct olpc_apsp { | ||
74 | struct device *dev; | ||
75 | struct serio *kbio; | ||
76 | struct serio *padio; | ||
77 | void __iomem *base; | ||
78 | int open_count; | ||
79 | int irq; | ||
80 | }; | ||
81 | |||
82 | static int olpc_apsp_write(struct serio *port, unsigned char val) | ||
83 | { | ||
84 | struct olpc_apsp *priv = port->port_data; | ||
85 | unsigned int i; | ||
86 | u32 which = 0; | ||
87 | |||
88 | if (port == priv->padio) | ||
89 | which = TOUCHPAD_PORT << PORT_SHIFT; | ||
90 | else | ||
91 | which = KEYBOARD_PORT << PORT_SHIFT; | ||
92 | |||
93 | dev_dbg(priv->dev, "olpc_apsp_write which=%x val=%x\n", which, val); | ||
94 | for (i = 0; i < 50; i++) { | ||
95 | u32 sts = readl(priv->base + COMMAND_FIFO_STATUS); | ||
96 | if ((sts & CMD_CNTR_MASK) < MAX_PENDING_CMDS) { | ||
97 | writel(which | val, | ||
98 | priv->base + SECURE_PROCESSOR_COMMAND); | ||
99 | return 0; | ||
100 | } | ||
101 | /* SP busy. This has not been seen in practice. */ | ||
102 | mdelay(1); | ||
103 | } | ||
104 | |||
105 | dev_dbg(priv->dev, "olpc_apsp_write timeout, status=%x\n", | ||
106 | readl(priv->base + COMMAND_FIFO_STATUS)); | ||
107 | |||
108 | return -ETIMEDOUT; | ||
109 | } | ||
110 | |||
111 | static irqreturn_t olpc_apsp_rx(int irq, void *dev_id) | ||
112 | { | ||
113 | struct olpc_apsp *priv = dev_id; | ||
114 | unsigned int w, tmp; | ||
115 | struct serio *serio; | ||
116 | |||
117 | /* | ||
118 | * Write 1 to PJ_RST_INTERRUPT to acknowledge and clear the interrupt | ||
119 | * Write 0xff00 to SECURE_PROCESSOR_COMMAND. | ||
120 | */ | ||
121 | tmp = readl(priv->base + PJ_RST_INTERRUPT); | ||
122 | if (!(tmp & SP_COMMAND_COMPLETE_RESET)) { | ||
123 | dev_warn(priv->dev, "spurious interrupt?\n"); | ||
124 | return IRQ_NONE; | ||
125 | } | ||
126 | |||
127 | w = readl(priv->base + COMMAND_RETURN_STATUS); | ||
128 | dev_dbg(priv->dev, "olpc_apsp_rx %x\n", w); | ||
129 | |||
130 | if (w >> PORT_SHIFT == KEYBOARD_PORT) | ||
131 | serio = priv->kbio; | ||
132 | else | ||
133 | serio = priv->padio; | ||
134 | |||
135 | serio_interrupt(serio, w & DATA_MASK, 0); | ||
136 | |||
137 | /* Ack and clear interrupt */ | ||
138 | writel(tmp | SP_COMMAND_COMPLETE_RESET, priv->base + PJ_RST_INTERRUPT); | ||
139 | writel(PORT_MASK, priv->base + SECURE_PROCESSOR_COMMAND); | ||
140 | |||
141 | pm_wakeup_event(priv->dev, 1000); | ||
142 | return IRQ_HANDLED; | ||
143 | } | ||
144 | |||
145 | static int olpc_apsp_open(struct serio *port) | ||
146 | { | ||
147 | struct olpc_apsp *priv = port->port_data; | ||
148 | unsigned int tmp; | ||
149 | |||
150 | if (priv->open_count++ == 0) { | ||
151 | /* Enable interrupt 0 by clearing its bit */ | ||
152 | tmp = readl(priv->base + PJ_INTERRUPT_MASK); | ||
153 | writel(tmp & ~INT_0, priv->base + PJ_INTERRUPT_MASK); | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static void olpc_apsp_close(struct serio *port) | ||
160 | { | ||
161 | struct olpc_apsp *priv = port->port_data; | ||
162 | unsigned int tmp; | ||
163 | |||
164 | if (--priv->open_count == 0) { | ||
165 | /* Disable interrupt 0 */ | ||
166 | tmp = readl(priv->base + PJ_INTERRUPT_MASK); | ||
167 | writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static int olpc_apsp_probe(struct platform_device *pdev) | ||
172 | { | ||
173 | struct serio *kb_serio, *pad_serio; | ||
174 | struct olpc_apsp *priv; | ||
175 | struct resource *res; | ||
176 | struct device_node *np; | ||
177 | unsigned long l; | ||
178 | int error; | ||
179 | |||
180 | priv = devm_kzalloc(&pdev->dev, sizeof(struct olpc_apsp), GFP_KERNEL); | ||
181 | if (!priv) | ||
182 | return -ENOMEM; | ||
183 | |||
184 | np = pdev->dev.of_node; | ||
185 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
186 | if (!res) | ||
187 | return -ENOENT; | ||
188 | |||
189 | priv->base = devm_ioremap_resource(&pdev->dev, res); | ||
190 | if (IS_ERR(priv->base)) { | ||
191 | dev_err(&pdev->dev, "Failed to map WTM registers\n"); | ||
192 | return PTR_ERR(priv->base); | ||
193 | } | ||
194 | |||
195 | priv->irq = platform_get_irq(pdev, 0); | ||
196 | if (priv->irq < 0) | ||
197 | return priv->irq; | ||
198 | |||
199 | l = readl(priv->base + COMMAND_FIFO_STATUS); | ||
200 | if (!(l & CMD_STS_MASK)) { | ||
201 | dev_err(&pdev->dev, "SP cannot accept commands.\n"); | ||
202 | return -EIO; | ||
203 | } | ||
204 | |||
205 | /* KEYBOARD */ | ||
206 | kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | ||
207 | if (!kb_serio) | ||
208 | return -ENOMEM; | ||
209 | kb_serio->id.type = SERIO_8042_XL; | ||
210 | kb_serio->write = olpc_apsp_write; | ||
211 | kb_serio->open = olpc_apsp_open; | ||
212 | kb_serio->close = olpc_apsp_close; | ||
213 | kb_serio->port_data = priv; | ||
214 | kb_serio->dev.parent = &pdev->dev; | ||
215 | strlcpy(kb_serio->name, "sp keyboard", sizeof(kb_serio->name)); | ||
216 | strlcpy(kb_serio->phys, "sp/serio0", sizeof(kb_serio->phys)); | ||
217 | priv->kbio = kb_serio; | ||
218 | serio_register_port(kb_serio); | ||
219 | |||
220 | /* TOUCHPAD */ | ||
221 | pad_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | ||
222 | if (!pad_serio) { | ||
223 | error = -ENOMEM; | ||
224 | goto err_pad; | ||
225 | } | ||
226 | pad_serio->id.type = SERIO_8042; | ||
227 | pad_serio->write = olpc_apsp_write; | ||
228 | pad_serio->open = olpc_apsp_open; | ||
229 | pad_serio->close = olpc_apsp_close; | ||
230 | pad_serio->port_data = priv; | ||
231 | pad_serio->dev.parent = &pdev->dev; | ||
232 | strlcpy(pad_serio->name, "sp touchpad", sizeof(pad_serio->name)); | ||
233 | strlcpy(pad_serio->phys, "sp/serio1", sizeof(pad_serio->phys)); | ||
234 | priv->padio = pad_serio; | ||
235 | serio_register_port(pad_serio); | ||
236 | |||
237 | error = request_irq(priv->irq, olpc_apsp_rx, 0, "olpc-apsp", priv); | ||
238 | if (error) { | ||
239 | dev_err(&pdev->dev, "Failed to request IRQ\n"); | ||
240 | goto err_irq; | ||
241 | } | ||
242 | |||
243 | priv->dev = &pdev->dev; | ||
244 | device_init_wakeup(priv->dev, 1); | ||
245 | platform_set_drvdata(pdev, priv); | ||
246 | |||
247 | dev_dbg(&pdev->dev, "probed successfully.\n"); | ||
248 | return 0; | ||
249 | |||
250 | err_irq: | ||
251 | serio_unregister_port(pad_serio); | ||
252 | err_pad: | ||
253 | serio_unregister_port(kb_serio); | ||
254 | return error; | ||
255 | } | ||
256 | |||
257 | static int olpc_apsp_remove(struct platform_device *pdev) | ||
258 | { | ||
259 | struct olpc_apsp *priv = platform_get_drvdata(pdev); | ||
260 | |||
261 | free_irq(priv->irq, priv); | ||
262 | |||
263 | serio_unregister_port(priv->kbio); | ||
264 | serio_unregister_port(priv->padio); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static struct of_device_id olpc_apsp_dt_ids[] = { | ||
270 | { .compatible = "olpc,ap-sp", }, | ||
271 | {} | ||
272 | }; | ||
273 | MODULE_DEVICE_TABLE(of, olpc_apsp_dt_ids); | ||
274 | |||
275 | static struct platform_driver olpc_apsp_driver = { | ||
276 | .probe = olpc_apsp_probe, | ||
277 | .remove = olpc_apsp_remove, | ||
278 | .driver = { | ||
279 | .name = "olpc-apsp", | ||
280 | .owner = THIS_MODULE, | ||
281 | .of_match_table = olpc_apsp_dt_ids, | ||
282 | }, | ||
283 | }; | ||
284 | |||
285 | MODULE_DESCRIPTION("OLPC AP-SP serio driver"); | ||
286 | MODULE_LICENSE("GPL"); | ||
287 | module_platform_driver(olpc_apsp_driver); | ||
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 436a3433f8e5..7a65a1bc5226 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c | |||
@@ -181,7 +181,6 @@ static int q40kbd_remove(struct platform_device *pdev) | |||
181 | free_irq(Q40_IRQ_KEYBOARD, q40kbd); | 181 | free_irq(Q40_IRQ_KEYBOARD, q40kbd); |
182 | kfree(q40kbd); | 182 | kfree(q40kbd); |
183 | 183 | ||
184 | platform_set_drvdata(pdev, NULL); | ||
185 | return 0; | 184 | return 0; |
186 | } | 185 | } |
187 | 186 | ||
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 17be85948ffd..4b7662a17ae9 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
@@ -349,8 +349,6 @@ static int xps2_of_remove(struct platform_device *of_dev) | |||
349 | 349 | ||
350 | kfree(drvdata); | 350 | kfree(drvdata); |
351 | 351 | ||
352 | platform_set_drvdata(of_dev, NULL); | ||
353 | |||
354 | return 0; | 352 | return 0; |
355 | } | 353 | } |
356 | 354 | ||
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index c7068942ebe8..f7de14a268bf 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c | |||
@@ -237,7 +237,7 @@ static int pm860x_touch_probe(struct platform_device *pdev) | |||
237 | touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); | 237 | touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); |
238 | if (touch == NULL) | 238 | if (touch == NULL) |
239 | return -ENOMEM; | 239 | return -ENOMEM; |
240 | dev_set_drvdata(&pdev->dev, touch); | 240 | platform_set_drvdata(pdev, touch); |
241 | 241 | ||
242 | touch->idev = input_allocate_device(); | 242 | touch->idev = input_allocate_device(); |
243 | if (touch->idev == NULL) { | 243 | if (touch->idev == NULL) { |
@@ -299,7 +299,6 @@ static int pm860x_touch_remove(struct platform_device *pdev) | |||
299 | 299 | ||
300 | input_unregister_device(touch->idev); | 300 | input_unregister_device(touch->idev); |
301 | free_irq(touch->irq, touch); | 301 | free_irq(touch->irq, touch); |
302 | platform_set_drvdata(pdev, NULL); | ||
303 | kfree(touch); | 302 | kfree(touch); |
304 | return 0; | 303 | return 0; |
305 | } | 304 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index f9a5fd89bc02..3b9758b5f4d7 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -167,6 +167,36 @@ config TOUCHSCREEN_CYTTSP_SPI | |||
167 | To compile this driver as a module, choose M here: the | 167 | To compile this driver as a module, choose M here: the |
168 | module will be called cyttsp_spi. | 168 | module will be called cyttsp_spi. |
169 | 169 | ||
170 | config TOUCHSCREEN_CYTTSP4_CORE | ||
171 | tristate "Cypress TrueTouch Gen4 Touchscreen Driver" | ||
172 | help | ||
173 | Core driver for Cypress TrueTouch(tm) Standard Product | ||
174 | Generation4 touchscreen controllers. | ||
175 | |||
176 | Say Y here if you have a Cypress Gen4 touchscreen. | ||
177 | |||
178 | If unsure, say N. | ||
179 | |||
180 | To compile this driver as a module, choose M here. | ||
181 | |||
182 | config TOUCHSCREEN_CYTTSP4_I2C | ||
183 | tristate "support I2C bus connection" | ||
184 | depends on TOUCHSCREEN_CYTTSP4_CORE && I2C | ||
185 | help | ||
186 | Say Y here if the touchscreen is connected via I2C bus. | ||
187 | |||
188 | To compile this driver as a module, choose M here: the | ||
189 | module will be called cyttsp4_i2c. | ||
190 | |||
191 | config TOUCHSCREEN_CYTTSP4_SPI | ||
192 | tristate "support SPI bus connection" | ||
193 | depends on TOUCHSCREEN_CYTTSP4_CORE && SPI_MASTER | ||
194 | help | ||
195 | Say Y here if the touchscreen is connected via SPI bus. | ||
196 | |||
197 | To compile this driver as a module, choose M here: the | ||
198 | module will be called cyttsp4_spi. | ||
199 | |||
170 | config TOUCHSCREEN_DA9034 | 200 | config TOUCHSCREEN_DA9034 |
171 | tristate "Touchscreen support for Dialog Semiconductor DA9034" | 201 | tristate "Touchscreen support for Dialog Semiconductor DA9034" |
172 | depends on PMIC_DA903X | 202 | depends on PMIC_DA903X |
@@ -879,6 +909,7 @@ config TOUCHSCREEN_STMPE | |||
879 | config TOUCHSCREEN_TPS6507X | 909 | config TOUCHSCREEN_TPS6507X |
880 | tristate "TPS6507x based touchscreens" | 910 | tristate "TPS6507x based touchscreens" |
881 | depends on I2C | 911 | depends on I2C |
912 | select INPUT_POLLDEV | ||
882 | help | 913 | help |
883 | Say Y here if you have a TPS6507x based touchscreen | 914 | Say Y here if you have a TPS6507x based touchscreen |
884 | controller. | 915 | controller. |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 6bfbeab67c9f..f5216c1bf53e 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -18,8 +18,11 @@ obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o | |||
18 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o |
19 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o | 19 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o |
20 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o | 20 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o |
21 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o | 21 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o |
22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o | 22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o |
23 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o | ||
24 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o | ||
25 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o | ||
23 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o | 26 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o |
24 | obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o | 27 | obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o |
25 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | 28 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index 2c1e46b7e45b..268a35e55d7f 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c | |||
@@ -372,7 +372,6 @@ static int __init atmel_wm97xx_probe(struct platform_device *pdev) | |||
372 | err_irq: | 372 | err_irq: |
373 | free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); | 373 | free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); |
374 | err: | 374 | err: |
375 | platform_set_drvdata(pdev, NULL); | ||
376 | kfree(atmel_wm97xx); | 375 | kfree(atmel_wm97xx); |
377 | return ret; | 376 | return ret; |
378 | } | 377 | } |
@@ -386,7 +385,6 @@ static int __exit atmel_wm97xx_remove(struct platform_device *pdev) | |||
386 | free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); | 385 | free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx); |
387 | del_timer_sync(&atmel_wm97xx->pen_timer); | 386 | del_timer_sync(&atmel_wm97xx->pen_timer); |
388 | wm97xx_unregister_mach_ops(wm); | 387 | wm97xx_unregister_mach_ops(wm); |
389 | platform_set_drvdata(pdev, NULL); | ||
390 | kfree(atmel_wm97xx); | 388 | kfree(atmel_wm97xx); |
391 | 389 | ||
392 | return 0; | 390 | return 0; |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 95f6785a94b0..bddabc595077 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -183,10 +183,13 @@ static int atmel_tsadcc_probe(struct platform_device *pdev) | |||
183 | struct input_dev *input_dev; | 183 | struct input_dev *input_dev; |
184 | struct resource *res; | 184 | struct resource *res; |
185 | struct at91_tsadcc_data *pdata = pdev->dev.platform_data; | 185 | struct at91_tsadcc_data *pdata = pdev->dev.platform_data; |
186 | int err = 0; | 186 | int err; |
187 | unsigned int prsc; | 187 | unsigned int prsc; |
188 | unsigned int reg; | 188 | unsigned int reg; |
189 | 189 | ||
190 | if (!pdata) | ||
191 | return -EINVAL; | ||
192 | |||
190 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 193 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
191 | if (!res) { | 194 | if (!res) { |
192 | dev_err(&pdev->dev, "no mmio resource defined.\n"); | 195 | dev_err(&pdev->dev, "no mmio resource defined.\n"); |
@@ -265,9 +268,6 @@ static int atmel_tsadcc_probe(struct platform_device *pdev) | |||
265 | prsc = clk_get_rate(ts_dev->clk); | 268 | prsc = clk_get_rate(ts_dev->clk); |
266 | dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); | 269 | dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); |
267 | 270 | ||
268 | if (!pdata) | ||
269 | goto err_fail; | ||
270 | |||
271 | if (!pdata->adc_clock) | 271 | if (!pdata->adc_clock) |
272 | pdata->adc_clock = ADC_DEFAULT_CLOCK; | 272 | pdata->adc_clock = ADC_DEFAULT_CLOCK; |
273 | 273 | ||
@@ -325,7 +325,7 @@ err_free_mem: | |||
325 | 325 | ||
326 | static int atmel_tsadcc_remove(struct platform_device *pdev) | 326 | static int atmel_tsadcc_remove(struct platform_device *pdev) |
327 | { | 327 | { |
328 | struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev); | 328 | struct atmel_tsadcc *ts_dev = platform_get_drvdata(pdev); |
329 | struct resource *res; | 329 | struct resource *res; |
330 | 330 | ||
331 | free_irq(ts_dev->irq, ts_dev); | 331 | free_irq(ts_dev->irq, ts_dev); |
diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c new file mode 100644 index 000000000000..edcf7993034b --- /dev/null +++ b/drivers/input/touchscreen/cyttsp4_core.c | |||
@@ -0,0 +1,2166 @@ | |||
1 | /* | ||
2 | * cyttsp4_core.c | ||
3 | * Cypress TrueTouch(TM) Standard Product V4 Core driver module. | ||
4 | * For use with Cypress Txx4xx parts. | ||
5 | * Supported parts include: | ||
6 | * TMA4XX | ||
7 | * TMA1036 | ||
8 | * | ||
9 | * Copyright (C) 2012 Cypress Semiconductor | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2, and only version 2, as published by the | ||
14 | * Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include "cyttsp4_core.h" | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/input/mt.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/pm_runtime.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/slab.h> | ||
33 | |||
34 | /* Timeout in ms. */ | ||
35 | #define CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT 500 | ||
36 | #define CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT 5000 | ||
37 | #define CY_CORE_MODE_CHANGE_TIMEOUT 1000 | ||
38 | #define CY_CORE_RESET_AND_WAIT_TIMEOUT 500 | ||
39 | #define CY_CORE_WAKEUP_TIMEOUT 500 | ||
40 | |||
41 | #define CY_CORE_STARTUP_RETRY_COUNT 3 | ||
42 | |||
43 | static const u8 ldr_exit[] = { | ||
44 | 0xFF, 0x01, 0x3B, 0x00, 0x00, 0x4F, 0x6D, 0x17 | ||
45 | }; | ||
46 | |||
47 | static const u8 ldr_err_app[] = { | ||
48 | 0x01, 0x02, 0x00, 0x00, 0x55, 0xDD, 0x17 | ||
49 | }; | ||
50 | |||
51 | static inline size_t merge_bytes(u8 high, u8 low) | ||
52 | { | ||
53 | return (high << 8) + low; | ||
54 | } | ||
55 | |||
56 | #ifdef VERBOSE_DEBUG | ||
57 | static void cyttsp4_pr_buf(struct device *dev, u8 *pr_buf, u8 *dptr, int size, | ||
58 | const char *data_name) | ||
59 | { | ||
60 | int i, k; | ||
61 | const char fmt[] = "%02X "; | ||
62 | int max; | ||
63 | |||
64 | if (!size) | ||
65 | return; | ||
66 | |||
67 | max = (CY_MAX_PRBUF_SIZE - 1) - sizeof(CY_PR_TRUNCATED); | ||
68 | |||
69 | pr_buf[0] = 0; | ||
70 | for (i = k = 0; i < size && k < max; i++, k += 3) | ||
71 | scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, dptr[i]); | ||
72 | |||
73 | dev_vdbg(dev, "%s: %s[0..%d]=%s%s\n", __func__, data_name, size - 1, | ||
74 | pr_buf, size <= max ? "" : CY_PR_TRUNCATED); | ||
75 | } | ||
76 | #else | ||
77 | #define cyttsp4_pr_buf(dev, pr_buf, dptr, size, data_name) do { } while (0) | ||
78 | #endif | ||
79 | |||
80 | static int cyttsp4_load_status_regs(struct cyttsp4 *cd) | ||
81 | { | ||
82 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
83 | struct device *dev = cd->dev; | ||
84 | int rc; | ||
85 | |||
86 | rc = cyttsp4_adap_read(cd, CY_REG_BASE, si->si_ofs.mode_size, | ||
87 | si->xy_mode); | ||
88 | if (rc < 0) | ||
89 | dev_err(dev, "%s: fail read mode regs r=%d\n", | ||
90 | __func__, rc); | ||
91 | else | ||
92 | cyttsp4_pr_buf(dev, cd->pr_buf, si->xy_mode, | ||
93 | si->si_ofs.mode_size, "xy_mode"); | ||
94 | |||
95 | return rc; | ||
96 | } | ||
97 | |||
98 | static int cyttsp4_handshake(struct cyttsp4 *cd, u8 mode) | ||
99 | { | ||
100 | u8 cmd = mode ^ CY_HST_TOGGLE; | ||
101 | int rc; | ||
102 | |||
103 | /* | ||
104 | * Mode change issued, handshaking now will cause endless mode change | ||
105 | * requests, for sync mode modechange will do same with handshake | ||
106 | * */ | ||
107 | if (mode & CY_HST_MODE_CHANGE) | ||
108 | return 0; | ||
109 | |||
110 | rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(cmd), &cmd); | ||
111 | if (rc < 0) | ||
112 | dev_err(cd->dev, "%s: bus write fail on handshake (ret=%d)\n", | ||
113 | __func__, rc); | ||
114 | |||
115 | return rc; | ||
116 | } | ||
117 | |||
118 | static int cyttsp4_hw_soft_reset(struct cyttsp4 *cd) | ||
119 | { | ||
120 | u8 cmd = CY_HST_RESET; | ||
121 | int rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(cmd), &cmd); | ||
122 | if (rc < 0) { | ||
123 | dev_err(cd->dev, "%s: FAILED to execute SOFT reset\n", | ||
124 | __func__); | ||
125 | return rc; | ||
126 | } | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int cyttsp4_hw_hard_reset(struct cyttsp4 *cd) | ||
131 | { | ||
132 | if (cd->cpdata->xres) { | ||
133 | cd->cpdata->xres(cd->cpdata, cd->dev); | ||
134 | dev_dbg(cd->dev, "%s: execute HARD reset\n", __func__); | ||
135 | return 0; | ||
136 | } | ||
137 | dev_err(cd->dev, "%s: FAILED to execute HARD reset\n", __func__); | ||
138 | return -ENOSYS; | ||
139 | } | ||
140 | |||
141 | static int cyttsp4_hw_reset(struct cyttsp4 *cd) | ||
142 | { | ||
143 | int rc = cyttsp4_hw_hard_reset(cd); | ||
144 | if (rc == -ENOSYS) | ||
145 | rc = cyttsp4_hw_soft_reset(cd); | ||
146 | return rc; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Gets number of bits for a touch filed as parameter, | ||
151 | * sets maximum value for field which is used as bit mask | ||
152 | * and returns number of bytes required for that field | ||
153 | */ | ||
154 | static int cyttsp4_bits_2_bytes(unsigned int nbits, size_t *max) | ||
155 | { | ||
156 | *max = 1UL << nbits; | ||
157 | return (nbits + 7) / 8; | ||
158 | } | ||
159 | |||
160 | static int cyttsp4_si_data_offsets(struct cyttsp4 *cd) | ||
161 | { | ||
162 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
163 | int rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(si->si_data), | ||
164 | &si->si_data); | ||
165 | if (rc < 0) { | ||
166 | dev_err(cd->dev, "%s: fail read sysinfo data offsets r=%d\n", | ||
167 | __func__, rc); | ||
168 | return rc; | ||
169 | } | ||
170 | |||
171 | /* Print sysinfo data offsets */ | ||
172 | cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)&si->si_data, | ||
173 | sizeof(si->si_data), "sysinfo_data_offsets"); | ||
174 | |||
175 | /* convert sysinfo data offset bytes into integers */ | ||
176 | |||
177 | si->si_ofs.map_sz = merge_bytes(si->si_data.map_szh, | ||
178 | si->si_data.map_szl); | ||
179 | si->si_ofs.map_sz = merge_bytes(si->si_data.map_szh, | ||
180 | si->si_data.map_szl); | ||
181 | si->si_ofs.cydata_ofs = merge_bytes(si->si_data.cydata_ofsh, | ||
182 | si->si_data.cydata_ofsl); | ||
183 | si->si_ofs.test_ofs = merge_bytes(si->si_data.test_ofsh, | ||
184 | si->si_data.test_ofsl); | ||
185 | si->si_ofs.pcfg_ofs = merge_bytes(si->si_data.pcfg_ofsh, | ||
186 | si->si_data.pcfg_ofsl); | ||
187 | si->si_ofs.opcfg_ofs = merge_bytes(si->si_data.opcfg_ofsh, | ||
188 | si->si_data.opcfg_ofsl); | ||
189 | si->si_ofs.ddata_ofs = merge_bytes(si->si_data.ddata_ofsh, | ||
190 | si->si_data.ddata_ofsl); | ||
191 | si->si_ofs.mdata_ofs = merge_bytes(si->si_data.mdata_ofsh, | ||
192 | si->si_data.mdata_ofsl); | ||
193 | return rc; | ||
194 | } | ||
195 | |||
196 | static int cyttsp4_si_get_cydata(struct cyttsp4 *cd) | ||
197 | { | ||
198 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
199 | int read_offset; | ||
200 | int mfgid_sz, calc_mfgid_sz; | ||
201 | void *p; | ||
202 | int rc; | ||
203 | |||
204 | si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs; | ||
205 | dev_dbg(cd->dev, "%s: cydata size: %Zd\n", __func__, | ||
206 | si->si_ofs.cydata_size); | ||
207 | |||
208 | p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL); | ||
209 | if (p == NULL) { | ||
210 | dev_err(cd->dev, "%s: fail alloc cydata memory\n", __func__); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | si->si_ptrs.cydata = p; | ||
214 | |||
215 | read_offset = si->si_ofs.cydata_ofs; | ||
216 | |||
217 | /* Read the CYDA registers up to MFGID field */ | ||
218 | rc = cyttsp4_adap_read(cd, read_offset, | ||
219 | offsetof(struct cyttsp4_cydata, mfgid_sz) | ||
220 | + sizeof(si->si_ptrs.cydata->mfgid_sz), | ||
221 | si->si_ptrs.cydata); | ||
222 | if (rc < 0) { | ||
223 | dev_err(cd->dev, "%s: fail read cydata r=%d\n", | ||
224 | __func__, rc); | ||
225 | return rc; | ||
226 | } | ||
227 | |||
228 | /* Check MFGID size */ | ||
229 | mfgid_sz = si->si_ptrs.cydata->mfgid_sz; | ||
230 | calc_mfgid_sz = si->si_ofs.cydata_size - sizeof(struct cyttsp4_cydata); | ||
231 | if (mfgid_sz != calc_mfgid_sz) { | ||
232 | dev_err(cd->dev, "%s: mismatch in MFGID size, reported:%d calculated:%d\n", | ||
233 | __func__, mfgid_sz, calc_mfgid_sz); | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | |||
237 | read_offset += offsetof(struct cyttsp4_cydata, mfgid_sz) | ||
238 | + sizeof(si->si_ptrs.cydata->mfgid_sz); | ||
239 | |||
240 | /* Read the CYDA registers for MFGID field */ | ||
241 | rc = cyttsp4_adap_read(cd, read_offset, si->si_ptrs.cydata->mfgid_sz, | ||
242 | si->si_ptrs.cydata->mfg_id); | ||
243 | if (rc < 0) { | ||
244 | dev_err(cd->dev, "%s: fail read cydata r=%d\n", | ||
245 | __func__, rc); | ||
246 | return rc; | ||
247 | } | ||
248 | |||
249 | read_offset += si->si_ptrs.cydata->mfgid_sz; | ||
250 | |||
251 | /* Read the rest of the CYDA registers */ | ||
252 | rc = cyttsp4_adap_read(cd, read_offset, | ||
253 | sizeof(struct cyttsp4_cydata) | ||
254 | - offsetof(struct cyttsp4_cydata, cyito_idh), | ||
255 | &si->si_ptrs.cydata->cyito_idh); | ||
256 | if (rc < 0) { | ||
257 | dev_err(cd->dev, "%s: fail read cydata r=%d\n", | ||
258 | __func__, rc); | ||
259 | return rc; | ||
260 | } | ||
261 | |||
262 | cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.cydata, | ||
263 | si->si_ofs.cydata_size, "sysinfo_cydata"); | ||
264 | return rc; | ||
265 | } | ||
266 | |||
267 | static int cyttsp4_si_get_test_data(struct cyttsp4 *cd) | ||
268 | { | ||
269 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
270 | void *p; | ||
271 | int rc; | ||
272 | |||
273 | si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs; | ||
274 | |||
275 | p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL); | ||
276 | if (p == NULL) { | ||
277 | dev_err(cd->dev, "%s: fail alloc test memory\n", __func__); | ||
278 | return -ENOMEM; | ||
279 | } | ||
280 | si->si_ptrs.test = p; | ||
281 | |||
282 | rc = cyttsp4_adap_read(cd, si->si_ofs.test_ofs, si->si_ofs.test_size, | ||
283 | si->si_ptrs.test); | ||
284 | if (rc < 0) { | ||
285 | dev_err(cd->dev, "%s: fail read test data r=%d\n", | ||
286 | __func__, rc); | ||
287 | return rc; | ||
288 | } | ||
289 | |||
290 | cyttsp4_pr_buf(cd->dev, cd->pr_buf, | ||
291 | (u8 *)si->si_ptrs.test, si->si_ofs.test_size, | ||
292 | "sysinfo_test_data"); | ||
293 | if (si->si_ptrs.test->post_codel & | ||
294 | CY_POST_CODEL_WDG_RST) | ||
295 | dev_info(cd->dev, "%s: %s codel=%02X\n", | ||
296 | __func__, "Reset was a WATCHDOG RESET", | ||
297 | si->si_ptrs.test->post_codel); | ||
298 | |||
299 | if (!(si->si_ptrs.test->post_codel & | ||
300 | CY_POST_CODEL_CFG_DATA_CRC_FAIL)) | ||
301 | dev_info(cd->dev, "%s: %s codel=%02X\n", __func__, | ||
302 | "Config Data CRC FAIL", | ||
303 | si->si_ptrs.test->post_codel); | ||
304 | |||
305 | if (!(si->si_ptrs.test->post_codel & | ||
306 | CY_POST_CODEL_PANEL_TEST_FAIL)) | ||
307 | dev_info(cd->dev, "%s: %s codel=%02X\n", | ||
308 | __func__, "PANEL TEST FAIL", | ||
309 | si->si_ptrs.test->post_codel); | ||
310 | |||
311 | dev_info(cd->dev, "%s: SCANNING is %s codel=%02X\n", | ||
312 | __func__, si->si_ptrs.test->post_codel & 0x08 ? | ||
313 | "ENABLED" : "DISABLED", | ||
314 | si->si_ptrs.test->post_codel); | ||
315 | return rc; | ||
316 | } | ||
317 | |||
318 | static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd) | ||
319 | { | ||
320 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
321 | void *p; | ||
322 | int rc; | ||
323 | |||
324 | si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs; | ||
325 | |||
326 | p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL); | ||
327 | if (p == NULL) { | ||
328 | rc = -ENOMEM; | ||
329 | dev_err(cd->dev, "%s: fail alloc pcfg memory r=%d\n", | ||
330 | __func__, rc); | ||
331 | return rc; | ||
332 | } | ||
333 | si->si_ptrs.pcfg = p; | ||
334 | |||
335 | rc = cyttsp4_adap_read(cd, si->si_ofs.pcfg_ofs, si->si_ofs.pcfg_size, | ||
336 | si->si_ptrs.pcfg); | ||
337 | if (rc < 0) { | ||
338 | dev_err(cd->dev, "%s: fail read pcfg data r=%d\n", | ||
339 | __func__, rc); | ||
340 | return rc; | ||
341 | } | ||
342 | |||
343 | si->si_ofs.max_x = merge_bytes((si->si_ptrs.pcfg->res_xh | ||
344 | & CY_PCFG_RESOLUTION_X_MASK), si->si_ptrs.pcfg->res_xl); | ||
345 | si->si_ofs.x_origin = !!(si->si_ptrs.pcfg->res_xh | ||
346 | & CY_PCFG_ORIGIN_X_MASK); | ||
347 | si->si_ofs.max_y = merge_bytes((si->si_ptrs.pcfg->res_yh | ||
348 | & CY_PCFG_RESOLUTION_Y_MASK), si->si_ptrs.pcfg->res_yl); | ||
349 | si->si_ofs.y_origin = !!(si->si_ptrs.pcfg->res_yh | ||
350 | & CY_PCFG_ORIGIN_Y_MASK); | ||
351 | si->si_ofs.max_p = merge_bytes(si->si_ptrs.pcfg->max_zh, | ||
352 | si->si_ptrs.pcfg->max_zl); | ||
353 | |||
354 | cyttsp4_pr_buf(cd->dev, cd->pr_buf, | ||
355 | (u8 *)si->si_ptrs.pcfg, | ||
356 | si->si_ofs.pcfg_size, "sysinfo_pcfg_data"); | ||
357 | return rc; | ||
358 | } | ||
359 | |||
360 | static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) | ||
361 | { | ||
362 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
363 | struct cyttsp4_tch_abs_params *tch; | ||
364 | struct cyttsp4_tch_rec_params *tch_old, *tch_new; | ||
365 | enum cyttsp4_tch_abs abs; | ||
366 | int i; | ||
367 | void *p; | ||
368 | int rc; | ||
369 | |||
370 | si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs; | ||
371 | |||
372 | p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL); | ||
373 | if (p == NULL) { | ||
374 | dev_err(cd->dev, "%s: fail alloc opcfg memory\n", __func__); | ||
375 | rc = -ENOMEM; | ||
376 | goto cyttsp4_si_get_opcfg_data_exit; | ||
377 | } | ||
378 | si->si_ptrs.opcfg = p; | ||
379 | |||
380 | rc = cyttsp4_adap_read(cd, si->si_ofs.opcfg_ofs, si->si_ofs.opcfg_size, | ||
381 | si->si_ptrs.opcfg); | ||
382 | if (rc < 0) { | ||
383 | dev_err(cd->dev, "%s: fail read opcfg data r=%d\n", | ||
384 | __func__, rc); | ||
385 | goto cyttsp4_si_get_opcfg_data_exit; | ||
386 | } | ||
387 | si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs; | ||
388 | si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs; | ||
389 | si->si_ofs.rep_sz = (si->si_ptrs.opcfg->rep_szh * 256) + | ||
390 | si->si_ptrs.opcfg->rep_szl; | ||
391 | si->si_ofs.num_btns = si->si_ptrs.opcfg->num_btns; | ||
392 | si->si_ofs.num_btn_regs = (si->si_ofs.num_btns + | ||
393 | CY_NUM_BTN_PER_REG - 1) / CY_NUM_BTN_PER_REG; | ||
394 | si->si_ofs.tt_stat_ofs = si->si_ptrs.opcfg->tt_stat_ofs; | ||
395 | si->si_ofs.obj_cfg0 = si->si_ptrs.opcfg->obj_cfg0; | ||
396 | si->si_ofs.max_tchs = si->si_ptrs.opcfg->max_tchs & | ||
397 | CY_BYTE_OFS_MASK; | ||
398 | si->si_ofs.tch_rec_size = si->si_ptrs.opcfg->tch_rec_size & | ||
399 | CY_BYTE_OFS_MASK; | ||
400 | |||
401 | /* Get the old touch fields */ | ||
402 | for (abs = CY_TCH_X; abs < CY_NUM_TCH_FIELDS; abs++) { | ||
403 | tch = &si->si_ofs.tch_abs[abs]; | ||
404 | tch_old = &si->si_ptrs.opcfg->tch_rec_old[abs]; | ||
405 | |||
406 | tch->ofs = tch_old->loc & CY_BYTE_OFS_MASK; | ||
407 | tch->size = cyttsp4_bits_2_bytes(tch_old->size, | ||
408 | &tch->max); | ||
409 | tch->bofs = (tch_old->loc & CY_BOFS_MASK) >> CY_BOFS_SHIFT; | ||
410 | } | ||
411 | |||
412 | /* button fields */ | ||
413 | si->si_ofs.btn_rec_size = si->si_ptrs.opcfg->btn_rec_size; | ||
414 | si->si_ofs.btn_diff_ofs = si->si_ptrs.opcfg->btn_diff_ofs; | ||
415 | si->si_ofs.btn_diff_size = si->si_ptrs.opcfg->btn_diff_size; | ||
416 | |||
417 | if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) { | ||
418 | /* Get the extended touch fields */ | ||
419 | for (i = 0; i < CY_NUM_EXT_TCH_FIELDS; abs++, i++) { | ||
420 | tch = &si->si_ofs.tch_abs[abs]; | ||
421 | tch_new = &si->si_ptrs.opcfg->tch_rec_new[i]; | ||
422 | |||
423 | tch->ofs = tch_new->loc & CY_BYTE_OFS_MASK; | ||
424 | tch->size = cyttsp4_bits_2_bytes(tch_new->size, | ||
425 | &tch->max); | ||
426 | tch->bofs = (tch_new->loc & CY_BOFS_MASK) >> CY_BOFS_SHIFT; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | for (abs = 0; abs < CY_TCH_NUM_ABS; abs++) { | ||
431 | dev_dbg(cd->dev, "%s: tch_rec_%s\n", __func__, | ||
432 | cyttsp4_tch_abs_string[abs]); | ||
433 | dev_dbg(cd->dev, "%s: ofs =%2Zd\n", __func__, | ||
434 | si->si_ofs.tch_abs[abs].ofs); | ||
435 | dev_dbg(cd->dev, "%s: siz =%2Zd\n", __func__, | ||
436 | si->si_ofs.tch_abs[abs].size); | ||
437 | dev_dbg(cd->dev, "%s: max =%2Zd\n", __func__, | ||
438 | si->si_ofs.tch_abs[abs].max); | ||
439 | dev_dbg(cd->dev, "%s: bofs=%2Zd\n", __func__, | ||
440 | si->si_ofs.tch_abs[abs].bofs); | ||
441 | } | ||
442 | |||
443 | si->si_ofs.mode_size = si->si_ofs.tt_stat_ofs + 1; | ||
444 | si->si_ofs.data_size = si->si_ofs.max_tchs * | ||
445 | si->si_ptrs.opcfg->tch_rec_size; | ||
446 | |||
447 | cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg, | ||
448 | si->si_ofs.opcfg_size, "sysinfo_opcfg_data"); | ||
449 | |||
450 | cyttsp4_si_get_opcfg_data_exit: | ||
451 | return rc; | ||
452 | } | ||
453 | |||
454 | static int cyttsp4_si_get_ddata(struct cyttsp4 *cd) | ||
455 | { | ||
456 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
457 | void *p; | ||
458 | int rc; | ||
459 | |||
460 | si->si_ofs.ddata_size = si->si_ofs.mdata_ofs - si->si_ofs.ddata_ofs; | ||
461 | |||
462 | p = krealloc(si->si_ptrs.ddata, si->si_ofs.ddata_size, GFP_KERNEL); | ||
463 | if (p == NULL) { | ||
464 | dev_err(cd->dev, "%s: fail alloc ddata memory\n", __func__); | ||
465 | return -ENOMEM; | ||
466 | } | ||
467 | si->si_ptrs.ddata = p; | ||
468 | |||
469 | rc = cyttsp4_adap_read(cd, si->si_ofs.ddata_ofs, si->si_ofs.ddata_size, | ||
470 | si->si_ptrs.ddata); | ||
471 | if (rc < 0) | ||
472 | dev_err(cd->dev, "%s: fail read ddata data r=%d\n", | ||
473 | __func__, rc); | ||
474 | else | ||
475 | cyttsp4_pr_buf(cd->dev, cd->pr_buf, | ||
476 | (u8 *)si->si_ptrs.ddata, | ||
477 | si->si_ofs.ddata_size, "sysinfo_ddata"); | ||
478 | return rc; | ||
479 | } | ||
480 | |||
481 | static int cyttsp4_si_get_mdata(struct cyttsp4 *cd) | ||
482 | { | ||
483 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
484 | void *p; | ||
485 | int rc; | ||
486 | |||
487 | si->si_ofs.mdata_size = si->si_ofs.map_sz - si->si_ofs.mdata_ofs; | ||
488 | |||
489 | p = krealloc(si->si_ptrs.mdata, si->si_ofs.mdata_size, GFP_KERNEL); | ||
490 | if (p == NULL) { | ||
491 | dev_err(cd->dev, "%s: fail alloc mdata memory\n", __func__); | ||
492 | return -ENOMEM; | ||
493 | } | ||
494 | si->si_ptrs.mdata = p; | ||
495 | |||
496 | rc = cyttsp4_adap_read(cd, si->si_ofs.mdata_ofs, si->si_ofs.mdata_size, | ||
497 | si->si_ptrs.mdata); | ||
498 | if (rc < 0) | ||
499 | dev_err(cd->dev, "%s: fail read mdata data r=%d\n", | ||
500 | __func__, rc); | ||
501 | else | ||
502 | cyttsp4_pr_buf(cd->dev, cd->pr_buf, | ||
503 | (u8 *)si->si_ptrs.mdata, | ||
504 | si->si_ofs.mdata_size, "sysinfo_mdata"); | ||
505 | return rc; | ||
506 | } | ||
507 | |||
508 | static int cyttsp4_si_get_btn_data(struct cyttsp4 *cd) | ||
509 | { | ||
510 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
511 | int btn; | ||
512 | int num_defined_keys; | ||
513 | u16 *key_table; | ||
514 | void *p; | ||
515 | int rc = 0; | ||
516 | |||
517 | if (si->si_ofs.num_btns) { | ||
518 | si->si_ofs.btn_keys_size = si->si_ofs.num_btns * | ||
519 | sizeof(struct cyttsp4_btn); | ||
520 | |||
521 | p = krealloc(si->btn, si->si_ofs.btn_keys_size, | ||
522 | GFP_KERNEL|__GFP_ZERO); | ||
523 | if (p == NULL) { | ||
524 | dev_err(cd->dev, "%s: %s\n", __func__, | ||
525 | "fail alloc btn_keys memory"); | ||
526 | return -ENOMEM; | ||
527 | } | ||
528 | si->btn = p; | ||
529 | |||
530 | if (cd->cpdata->sett[CY_IC_GRPNUM_BTN_KEYS] == NULL) | ||
531 | num_defined_keys = 0; | ||
532 | else if (cd->cpdata->sett[CY_IC_GRPNUM_BTN_KEYS]->data == NULL) | ||
533 | num_defined_keys = 0; | ||
534 | else | ||
535 | num_defined_keys = cd->cpdata->sett | ||
536 | [CY_IC_GRPNUM_BTN_KEYS]->size; | ||
537 | |||
538 | for (btn = 0; btn < si->si_ofs.num_btns && | ||
539 | btn < num_defined_keys; btn++) { | ||
540 | key_table = (u16 *)cd->cpdata->sett | ||
541 | [CY_IC_GRPNUM_BTN_KEYS]->data; | ||
542 | si->btn[btn].key_code = key_table[btn]; | ||
543 | si->btn[btn].state = CY_BTN_RELEASED; | ||
544 | si->btn[btn].enabled = true; | ||
545 | } | ||
546 | for (; btn < si->si_ofs.num_btns; btn++) { | ||
547 | si->btn[btn].key_code = KEY_RESERVED; | ||
548 | si->btn[btn].state = CY_BTN_RELEASED; | ||
549 | si->btn[btn].enabled = true; | ||
550 | } | ||
551 | |||
552 | return rc; | ||
553 | } | ||
554 | |||
555 | si->si_ofs.btn_keys_size = 0; | ||
556 | kfree(si->btn); | ||
557 | si->btn = NULL; | ||
558 | return rc; | ||
559 | } | ||
560 | |||
561 | static int cyttsp4_si_get_op_data_ptrs(struct cyttsp4 *cd) | ||
562 | { | ||
563 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
564 | void *p; | ||
565 | |||
566 | p = krealloc(si->xy_mode, si->si_ofs.mode_size, GFP_KERNEL|__GFP_ZERO); | ||
567 | if (p == NULL) | ||
568 | return -ENOMEM; | ||
569 | si->xy_mode = p; | ||
570 | |||
571 | p = krealloc(si->xy_data, si->si_ofs.data_size, GFP_KERNEL|__GFP_ZERO); | ||
572 | if (p == NULL) | ||
573 | return -ENOMEM; | ||
574 | si->xy_data = p; | ||
575 | |||
576 | p = krealloc(si->btn_rec_data, | ||
577 | si->si_ofs.btn_rec_size * si->si_ofs.num_btns, | ||
578 | GFP_KERNEL|__GFP_ZERO); | ||
579 | if (p == NULL) | ||
580 | return -ENOMEM; | ||
581 | si->btn_rec_data = p; | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static void cyttsp4_si_put_log_data(struct cyttsp4 *cd) | ||
587 | { | ||
588 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
589 | dev_dbg(cd->dev, "%s: cydata_ofs =%4Zd siz=%4Zd\n", __func__, | ||
590 | si->si_ofs.cydata_ofs, si->si_ofs.cydata_size); | ||
591 | dev_dbg(cd->dev, "%s: test_ofs =%4Zd siz=%4Zd\n", __func__, | ||
592 | si->si_ofs.test_ofs, si->si_ofs.test_size); | ||
593 | dev_dbg(cd->dev, "%s: pcfg_ofs =%4Zd siz=%4Zd\n", __func__, | ||
594 | si->si_ofs.pcfg_ofs, si->si_ofs.pcfg_size); | ||
595 | dev_dbg(cd->dev, "%s: opcfg_ofs =%4Zd siz=%4Zd\n", __func__, | ||
596 | si->si_ofs.opcfg_ofs, si->si_ofs.opcfg_size); | ||
597 | dev_dbg(cd->dev, "%s: ddata_ofs =%4Zd siz=%4Zd\n", __func__, | ||
598 | si->si_ofs.ddata_ofs, si->si_ofs.ddata_size); | ||
599 | dev_dbg(cd->dev, "%s: mdata_ofs =%4Zd siz=%4Zd\n", __func__, | ||
600 | si->si_ofs.mdata_ofs, si->si_ofs.mdata_size); | ||
601 | |||
602 | dev_dbg(cd->dev, "%s: cmd_ofs =%4Zd\n", __func__, | ||
603 | si->si_ofs.cmd_ofs); | ||
604 | dev_dbg(cd->dev, "%s: rep_ofs =%4Zd\n", __func__, | ||
605 | si->si_ofs.rep_ofs); | ||
606 | dev_dbg(cd->dev, "%s: rep_sz =%4Zd\n", __func__, | ||
607 | si->si_ofs.rep_sz); | ||
608 | dev_dbg(cd->dev, "%s: num_btns =%4Zd\n", __func__, | ||
609 | si->si_ofs.num_btns); | ||
610 | dev_dbg(cd->dev, "%s: num_btn_regs =%4Zd\n", __func__, | ||
611 | si->si_ofs.num_btn_regs); | ||
612 | dev_dbg(cd->dev, "%s: tt_stat_ofs =%4Zd\n", __func__, | ||
613 | si->si_ofs.tt_stat_ofs); | ||
614 | dev_dbg(cd->dev, "%s: tch_rec_size =%4Zd\n", __func__, | ||
615 | si->si_ofs.tch_rec_size); | ||
616 | dev_dbg(cd->dev, "%s: max_tchs =%4Zd\n", __func__, | ||
617 | si->si_ofs.max_tchs); | ||
618 | dev_dbg(cd->dev, "%s: mode_size =%4Zd\n", __func__, | ||
619 | si->si_ofs.mode_size); | ||
620 | dev_dbg(cd->dev, "%s: data_size =%4Zd\n", __func__, | ||
621 | si->si_ofs.data_size); | ||
622 | dev_dbg(cd->dev, "%s: map_sz =%4Zd\n", __func__, | ||
623 | si->si_ofs.map_sz); | ||
624 | |||
625 | dev_dbg(cd->dev, "%s: btn_rec_size =%2Zd\n", __func__, | ||
626 | si->si_ofs.btn_rec_size); | ||
627 | dev_dbg(cd->dev, "%s: btn_diff_ofs =%2Zd\n", __func__, | ||
628 | si->si_ofs.btn_diff_ofs); | ||
629 | dev_dbg(cd->dev, "%s: btn_diff_size =%2Zd\n", __func__, | ||
630 | si->si_ofs.btn_diff_size); | ||
631 | |||
632 | dev_dbg(cd->dev, "%s: max_x = 0x%04ZX (%Zd)\n", __func__, | ||
633 | si->si_ofs.max_x, si->si_ofs.max_x); | ||
634 | dev_dbg(cd->dev, "%s: x_origin = %Zd (%s)\n", __func__, | ||
635 | si->si_ofs.x_origin, | ||
636 | si->si_ofs.x_origin == CY_NORMAL_ORIGIN ? | ||
637 | "left corner" : "right corner"); | ||
638 | dev_dbg(cd->dev, "%s: max_y = 0x%04ZX (%Zd)\n", __func__, | ||
639 | si->si_ofs.max_y, si->si_ofs.max_y); | ||
640 | dev_dbg(cd->dev, "%s: y_origin = %Zd (%s)\n", __func__, | ||
641 | si->si_ofs.y_origin, | ||
642 | si->si_ofs.y_origin == CY_NORMAL_ORIGIN ? | ||
643 | "upper corner" : "lower corner"); | ||
644 | dev_dbg(cd->dev, "%s: max_p = 0x%04ZX (%Zd)\n", __func__, | ||
645 | si->si_ofs.max_p, si->si_ofs.max_p); | ||
646 | |||
647 | dev_dbg(cd->dev, "%s: xy_mode=%p xy_data=%p\n", __func__, | ||
648 | si->xy_mode, si->xy_data); | ||
649 | } | ||
650 | |||
651 | static int cyttsp4_get_sysinfo_regs(struct cyttsp4 *cd) | ||
652 | { | ||
653 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
654 | int rc; | ||
655 | |||
656 | rc = cyttsp4_si_data_offsets(cd); | ||
657 | if (rc < 0) | ||
658 | return rc; | ||
659 | |||
660 | rc = cyttsp4_si_get_cydata(cd); | ||
661 | if (rc < 0) | ||
662 | return rc; | ||
663 | |||
664 | rc = cyttsp4_si_get_test_data(cd); | ||
665 | if (rc < 0) | ||
666 | return rc; | ||
667 | |||
668 | rc = cyttsp4_si_get_pcfg_data(cd); | ||
669 | if (rc < 0) | ||
670 | return rc; | ||
671 | |||
672 | rc = cyttsp4_si_get_opcfg_data(cd); | ||
673 | if (rc < 0) | ||
674 | return rc; | ||
675 | |||
676 | rc = cyttsp4_si_get_ddata(cd); | ||
677 | if (rc < 0) | ||
678 | return rc; | ||
679 | |||
680 | rc = cyttsp4_si_get_mdata(cd); | ||
681 | if (rc < 0) | ||
682 | return rc; | ||
683 | |||
684 | rc = cyttsp4_si_get_btn_data(cd); | ||
685 | if (rc < 0) | ||
686 | return rc; | ||
687 | |||
688 | rc = cyttsp4_si_get_op_data_ptrs(cd); | ||
689 | if (rc < 0) { | ||
690 | dev_err(cd->dev, "%s: failed to get_op_data\n", | ||
691 | __func__); | ||
692 | return rc; | ||
693 | } | ||
694 | |||
695 | cyttsp4_si_put_log_data(cd); | ||
696 | |||
697 | /* provide flow control handshake */ | ||
698 | rc = cyttsp4_handshake(cd, si->si_data.hst_mode); | ||
699 | if (rc < 0) | ||
700 | dev_err(cd->dev, "%s: handshake fail on sysinfo reg\n", | ||
701 | __func__); | ||
702 | |||
703 | si->ready = true; | ||
704 | return rc; | ||
705 | } | ||
706 | |||
707 | static void cyttsp4_queue_startup_(struct cyttsp4 *cd) | ||
708 | { | ||
709 | if (cd->startup_state == STARTUP_NONE) { | ||
710 | cd->startup_state = STARTUP_QUEUED; | ||
711 | schedule_work(&cd->startup_work); | ||
712 | dev_dbg(cd->dev, "%s: cyttsp4_startup queued\n", __func__); | ||
713 | } else { | ||
714 | dev_dbg(cd->dev, "%s: startup_state = %d\n", __func__, | ||
715 | cd->startup_state); | ||
716 | } | ||
717 | } | ||
718 | |||
719 | static void cyttsp4_report_slot_liftoff(struct cyttsp4_mt_data *md, | ||
720 | int max_slots) | ||
721 | { | ||
722 | int t; | ||
723 | |||
724 | if (md->num_prv_tch == 0) | ||
725 | return; | ||
726 | |||
727 | for (t = 0; t < max_slots; t++) { | ||
728 | input_mt_slot(md->input, t); | ||
729 | input_mt_report_slot_state(md->input, | ||
730 | MT_TOOL_FINGER, false); | ||
731 | } | ||
732 | } | ||
733 | |||
734 | static void cyttsp4_lift_all(struct cyttsp4_mt_data *md) | ||
735 | { | ||
736 | if (!md->si) | ||
737 | return; | ||
738 | |||
739 | if (md->num_prv_tch != 0) { | ||
740 | cyttsp4_report_slot_liftoff(md, | ||
741 | md->si->si_ofs.tch_abs[CY_TCH_T].max); | ||
742 | input_sync(md->input); | ||
743 | md->num_prv_tch = 0; | ||
744 | } | ||
745 | } | ||
746 | |||
747 | static void cyttsp4_get_touch_axis(struct cyttsp4_mt_data *md, | ||
748 | int *axis, int size, int max, u8 *xy_data, int bofs) | ||
749 | { | ||
750 | int nbyte; | ||
751 | int next; | ||
752 | |||
753 | for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) { | ||
754 | dev_vdbg(&md->input->dev, | ||
755 | "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" | ||
756 | " xy_data[%d]=%02X(%d) bofs=%d\n", | ||
757 | __func__, *axis, *axis, size, max, xy_data, next, | ||
758 | xy_data[next], xy_data[next], bofs); | ||
759 | *axis = (*axis * 256) + (xy_data[next] >> bofs); | ||
760 | next++; | ||
761 | } | ||
762 | |||
763 | *axis &= max - 1; | ||
764 | |||
765 | dev_vdbg(&md->input->dev, | ||
766 | "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" | ||
767 | " xy_data[%d]=%02X(%d)\n", | ||
768 | __func__, *axis, *axis, size, max, xy_data, next, | ||
769 | xy_data[next], xy_data[next]); | ||
770 | } | ||
771 | |||
772 | static void cyttsp4_get_touch(struct cyttsp4_mt_data *md, | ||
773 | struct cyttsp4_touch *touch, u8 *xy_data) | ||
774 | { | ||
775 | struct device *dev = &md->input->dev; | ||
776 | struct cyttsp4_sysinfo *si = md->si; | ||
777 | enum cyttsp4_tch_abs abs; | ||
778 | int tmp; | ||
779 | bool flipped; | ||
780 | |||
781 | for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) { | ||
782 | cyttsp4_get_touch_axis(md, &touch->abs[abs], | ||
783 | si->si_ofs.tch_abs[abs].size, | ||
784 | si->si_ofs.tch_abs[abs].max, | ||
785 | xy_data + si->si_ofs.tch_abs[abs].ofs, | ||
786 | si->si_ofs.tch_abs[abs].bofs); | ||
787 | dev_vdbg(dev, "%s: get %s=%04X(%d)\n", __func__, | ||
788 | cyttsp4_tch_abs_string[abs], | ||
789 | touch->abs[abs], touch->abs[abs]); | ||
790 | } | ||
791 | |||
792 | if (md->pdata->flags & CY_FLAG_FLIP) { | ||
793 | tmp = touch->abs[CY_TCH_X]; | ||
794 | touch->abs[CY_TCH_X] = touch->abs[CY_TCH_Y]; | ||
795 | touch->abs[CY_TCH_Y] = tmp; | ||
796 | flipped = true; | ||
797 | } else | ||
798 | flipped = false; | ||
799 | |||
800 | if (md->pdata->flags & CY_FLAG_INV_X) { | ||
801 | if (flipped) | ||
802 | touch->abs[CY_TCH_X] = md->si->si_ofs.max_y - | ||
803 | touch->abs[CY_TCH_X]; | ||
804 | else | ||
805 | touch->abs[CY_TCH_X] = md->si->si_ofs.max_x - | ||
806 | touch->abs[CY_TCH_X]; | ||
807 | } | ||
808 | if (md->pdata->flags & CY_FLAG_INV_Y) { | ||
809 | if (flipped) | ||
810 | touch->abs[CY_TCH_Y] = md->si->si_ofs.max_x - | ||
811 | touch->abs[CY_TCH_Y]; | ||
812 | else | ||
813 | touch->abs[CY_TCH_Y] = md->si->si_ofs.max_y - | ||
814 | touch->abs[CY_TCH_Y]; | ||
815 | } | ||
816 | |||
817 | dev_vdbg(dev, "%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n", | ||
818 | __func__, flipped ? "true" : "false", | ||
819 | md->pdata->flags & CY_FLAG_INV_X ? "true" : "false", | ||
820 | md->pdata->flags & CY_FLAG_INV_Y ? "true" : "false", | ||
821 | touch->abs[CY_TCH_X], touch->abs[CY_TCH_X], | ||
822 | touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]); | ||
823 | } | ||
824 | |||
825 | static void cyttsp4_final_sync(struct input_dev *input, int max_slots, int *ids) | ||
826 | { | ||
827 | int t; | ||
828 | |||
829 | for (t = 0; t < max_slots; t++) { | ||
830 | if (ids[t]) | ||
831 | continue; | ||
832 | input_mt_slot(input, t); | ||
833 | input_mt_report_slot_state(input, MT_TOOL_FINGER, false); | ||
834 | } | ||
835 | |||
836 | input_sync(input); | ||
837 | } | ||
838 | |||
839 | static void cyttsp4_get_mt_touches(struct cyttsp4_mt_data *md, int num_cur_tch) | ||
840 | { | ||
841 | struct device *dev = &md->input->dev; | ||
842 | struct cyttsp4_sysinfo *si = md->si; | ||
843 | struct cyttsp4_touch tch; | ||
844 | int sig; | ||
845 | int i, j, t = 0; | ||
846 | int ids[max(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)]; | ||
847 | |||
848 | memset(ids, 0, si->si_ofs.tch_abs[CY_TCH_T].max * sizeof(int)); | ||
849 | for (i = 0; i < num_cur_tch; i++) { | ||
850 | cyttsp4_get_touch(md, &tch, si->xy_data + | ||
851 | (i * si->si_ofs.tch_rec_size)); | ||
852 | if ((tch.abs[CY_TCH_T] < md->pdata->frmwrk->abs | ||
853 | [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]) || | ||
854 | (tch.abs[CY_TCH_T] > md->pdata->frmwrk->abs | ||
855 | [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MAX_OST])) { | ||
856 | dev_err(dev, "%s: tch=%d -> bad trk_id=%d max_id=%d\n", | ||
857 | __func__, i, tch.abs[CY_TCH_T], | ||
858 | md->pdata->frmwrk->abs[(CY_ABS_ID_OST * | ||
859 | CY_NUM_ABS_SET) + CY_MAX_OST]); | ||
860 | continue; | ||
861 | } | ||
862 | |||
863 | /* use 0 based track id's */ | ||
864 | sig = md->pdata->frmwrk->abs | ||
865 | [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + 0]; | ||
866 | if (sig != CY_IGNORE_VALUE) { | ||
867 | t = tch.abs[CY_TCH_T] - md->pdata->frmwrk->abs | ||
868 | [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]; | ||
869 | if (tch.abs[CY_TCH_E] == CY_EV_LIFTOFF) { | ||
870 | dev_dbg(dev, "%s: t=%d e=%d lift-off\n", | ||
871 | __func__, t, tch.abs[CY_TCH_E]); | ||
872 | goto cyttsp4_get_mt_touches_pr_tch; | ||
873 | } | ||
874 | input_mt_slot(md->input, t); | ||
875 | input_mt_report_slot_state(md->input, MT_TOOL_FINGER, | ||
876 | true); | ||
877 | ids[t] = true; | ||
878 | } | ||
879 | |||
880 | /* all devices: position and pressure fields */ | ||
881 | for (j = 0; j <= CY_ABS_W_OST; j++) { | ||
882 | sig = md->pdata->frmwrk->abs[((CY_ABS_X_OST + j) * | ||
883 | CY_NUM_ABS_SET) + 0]; | ||
884 | if (sig != CY_IGNORE_VALUE) | ||
885 | input_report_abs(md->input, sig, | ||
886 | tch.abs[CY_TCH_X + j]); | ||
887 | } | ||
888 | if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) { | ||
889 | /* | ||
890 | * TMA400 size and orientation fields: | ||
891 | * if pressure is non-zero and major touch | ||
892 | * signal is zero, then set major and minor touch | ||
893 | * signals to minimum non-zero value | ||
894 | */ | ||
895 | if (tch.abs[CY_TCH_P] > 0 && tch.abs[CY_TCH_MAJ] == 0) | ||
896 | tch.abs[CY_TCH_MAJ] = tch.abs[CY_TCH_MIN] = 1; | ||
897 | |||
898 | /* Get the extended touch fields */ | ||
899 | for (j = 0; j < CY_NUM_EXT_TCH_FIELDS; j++) { | ||
900 | sig = md->pdata->frmwrk->abs | ||
901 | [((CY_ABS_MAJ_OST + j) * | ||
902 | CY_NUM_ABS_SET) + 0]; | ||
903 | if (sig != CY_IGNORE_VALUE) | ||
904 | input_report_abs(md->input, sig, | ||
905 | tch.abs[CY_TCH_MAJ + j]); | ||
906 | } | ||
907 | } | ||
908 | |||
909 | cyttsp4_get_mt_touches_pr_tch: | ||
910 | if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) | ||
911 | dev_dbg(dev, | ||
912 | "%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d\n", | ||
913 | __func__, t, | ||
914 | tch.abs[CY_TCH_X], | ||
915 | tch.abs[CY_TCH_Y], | ||
916 | tch.abs[CY_TCH_P], | ||
917 | tch.abs[CY_TCH_MAJ], | ||
918 | tch.abs[CY_TCH_MIN], | ||
919 | tch.abs[CY_TCH_OR], | ||
920 | tch.abs[CY_TCH_E]); | ||
921 | else | ||
922 | dev_dbg(dev, | ||
923 | "%s: t=%d x=%d y=%d z=%d e=%d\n", __func__, | ||
924 | t, | ||
925 | tch.abs[CY_TCH_X], | ||
926 | tch.abs[CY_TCH_Y], | ||
927 | tch.abs[CY_TCH_P], | ||
928 | tch.abs[CY_TCH_E]); | ||
929 | } | ||
930 | |||
931 | cyttsp4_final_sync(md->input, si->si_ofs.tch_abs[CY_TCH_T].max, ids); | ||
932 | |||
933 | md->num_prv_tch = num_cur_tch; | ||
934 | |||
935 | return; | ||
936 | } | ||
937 | |||
938 | /* read xy_data for all current touches */ | ||
939 | static int cyttsp4_xy_worker(struct cyttsp4 *cd) | ||
940 | { | ||
941 | struct cyttsp4_mt_data *md = &cd->md; | ||
942 | struct device *dev = &md->input->dev; | ||
943 | struct cyttsp4_sysinfo *si = md->si; | ||
944 | u8 num_cur_tch; | ||
945 | u8 hst_mode; | ||
946 | u8 rep_len; | ||
947 | u8 rep_stat; | ||
948 | u8 tt_stat; | ||
949 | int rc = 0; | ||
950 | |||
951 | /* | ||
952 | * Get event data from cyttsp4 device. | ||
953 | * The event data includes all data | ||
954 | * for all active touches. | ||
955 | * Event data also includes button data | ||
956 | */ | ||
957 | /* | ||
958 | * Use 2 reads: | ||
959 | * 1st read to get mode + button bytes + touch count (core) | ||
960 | * 2nd read (optional) to get touch 1 - touch n data | ||
961 | */ | ||
962 | hst_mode = si->xy_mode[CY_REG_BASE]; | ||
963 | rep_len = si->xy_mode[si->si_ofs.rep_ofs]; | ||
964 | rep_stat = si->xy_mode[si->si_ofs.rep_ofs + 1]; | ||
965 | tt_stat = si->xy_mode[si->si_ofs.tt_stat_ofs]; | ||
966 | dev_vdbg(dev, "%s: %s%02X %s%d %s%02X %s%02X\n", __func__, | ||
967 | "hst_mode=", hst_mode, "rep_len=", rep_len, | ||
968 | "rep_stat=", rep_stat, "tt_stat=", tt_stat); | ||
969 | |||
970 | num_cur_tch = GET_NUM_TOUCHES(tt_stat); | ||
971 | dev_vdbg(dev, "%s: num_cur_tch=%d\n", __func__, num_cur_tch); | ||
972 | |||
973 | if (rep_len == 0 && num_cur_tch > 0) { | ||
974 | dev_err(dev, "%s: report length error rep_len=%d num_tch=%d\n", | ||
975 | __func__, rep_len, num_cur_tch); | ||
976 | goto cyttsp4_xy_worker_exit; | ||
977 | } | ||
978 | |||
979 | /* read touches */ | ||
980 | if (num_cur_tch > 0) { | ||
981 | rc = cyttsp4_adap_read(cd, si->si_ofs.tt_stat_ofs + 1, | ||
982 | num_cur_tch * si->si_ofs.tch_rec_size, | ||
983 | si->xy_data); | ||
984 | if (rc < 0) { | ||
985 | dev_err(dev, "%s: read fail on touch regs r=%d\n", | ||
986 | __func__, rc); | ||
987 | goto cyttsp4_xy_worker_exit; | ||
988 | } | ||
989 | } | ||
990 | |||
991 | /* print xy data */ | ||
992 | cyttsp4_pr_buf(dev, cd->pr_buf, si->xy_data, num_cur_tch * | ||
993 | si->si_ofs.tch_rec_size, "xy_data"); | ||
994 | |||
995 | /* check any error conditions */ | ||
996 | if (IS_BAD_PKT(rep_stat)) { | ||
997 | dev_dbg(dev, "%s: Invalid buffer detected\n", __func__); | ||
998 | rc = 0; | ||
999 | goto cyttsp4_xy_worker_exit; | ||
1000 | } | ||
1001 | |||
1002 | if (IS_LARGE_AREA(tt_stat)) | ||
1003 | dev_dbg(dev, "%s: Large area detected\n", __func__); | ||
1004 | |||
1005 | if (num_cur_tch > si->si_ofs.max_tchs) { | ||
1006 | dev_err(dev, "%s: too many tch; set to max tch (n=%d c=%Zd)\n", | ||
1007 | __func__, num_cur_tch, si->si_ofs.max_tchs); | ||
1008 | num_cur_tch = si->si_ofs.max_tchs; | ||
1009 | } | ||
1010 | |||
1011 | /* extract xy_data for all currently reported touches */ | ||
1012 | dev_vdbg(dev, "%s: extract data num_cur_tch=%d\n", __func__, | ||
1013 | num_cur_tch); | ||
1014 | if (num_cur_tch) | ||
1015 | cyttsp4_get_mt_touches(md, num_cur_tch); | ||
1016 | else | ||
1017 | cyttsp4_lift_all(md); | ||
1018 | |||
1019 | rc = 0; | ||
1020 | |||
1021 | cyttsp4_xy_worker_exit: | ||
1022 | return rc; | ||
1023 | } | ||
1024 | |||
1025 | static int cyttsp4_mt_attention(struct cyttsp4 *cd) | ||
1026 | { | ||
1027 | struct device *dev = cd->dev; | ||
1028 | struct cyttsp4_mt_data *md = &cd->md; | ||
1029 | int rc = 0; | ||
1030 | |||
1031 | if (!md->si) | ||
1032 | return 0; | ||
1033 | |||
1034 | mutex_lock(&md->report_lock); | ||
1035 | if (!md->is_suspended) { | ||
1036 | /* core handles handshake */ | ||
1037 | rc = cyttsp4_xy_worker(cd); | ||
1038 | } else { | ||
1039 | dev_vdbg(dev, "%s: Ignoring report while suspended\n", | ||
1040 | __func__); | ||
1041 | } | ||
1042 | mutex_unlock(&md->report_lock); | ||
1043 | if (rc < 0) | ||
1044 | dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc); | ||
1045 | |||
1046 | return rc; | ||
1047 | } | ||
1048 | |||
1049 | static irqreturn_t cyttsp4_irq(int irq, void *handle) | ||
1050 | { | ||
1051 | struct cyttsp4 *cd = handle; | ||
1052 | struct device *dev = cd->dev; | ||
1053 | enum cyttsp4_mode cur_mode; | ||
1054 | u8 cmd_ofs = cd->sysinfo.si_ofs.cmd_ofs; | ||
1055 | u8 mode[3]; | ||
1056 | int rc; | ||
1057 | |||
1058 | /* | ||
1059 | * Check whether this IRQ should be ignored (external) | ||
1060 | * This should be the very first thing to check since | ||
1061 | * ignore_irq may be set for a very short period of time | ||
1062 | */ | ||
1063 | if (atomic_read(&cd->ignore_irq)) { | ||
1064 | dev_vdbg(dev, "%s: Ignoring IRQ\n", __func__); | ||
1065 | return IRQ_HANDLED; | ||
1066 | } | ||
1067 | |||
1068 | dev_dbg(dev, "%s int:0x%x\n", __func__, cd->int_status); | ||
1069 | |||
1070 | mutex_lock(&cd->system_lock); | ||
1071 | |||
1072 | /* Just to debug */ | ||
1073 | if (cd->sleep_state == SS_SLEEP_ON || cd->sleep_state == SS_SLEEPING) | ||
1074 | dev_vdbg(dev, "%s: Received IRQ while in sleep\n", __func__); | ||
1075 | |||
1076 | rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), mode); | ||
1077 | if (rc) { | ||
1078 | dev_err(cd->dev, "%s: Fail read adapter r=%d\n", __func__, rc); | ||
1079 | goto cyttsp4_irq_exit; | ||
1080 | } | ||
1081 | dev_vdbg(dev, "%s mode[0-2]:0x%X 0x%X 0x%X\n", __func__, | ||
1082 | mode[0], mode[1], mode[2]); | ||
1083 | |||
1084 | if (IS_BOOTLOADER(mode[0], mode[1])) { | ||
1085 | cur_mode = CY_MODE_BOOTLOADER; | ||
1086 | dev_vdbg(dev, "%s: bl running\n", __func__); | ||
1087 | if (cd->mode == CY_MODE_BOOTLOADER) { | ||
1088 | /* Signal bootloader heartbeat heard */ | ||
1089 | wake_up(&cd->wait_q); | ||
1090 | goto cyttsp4_irq_exit; | ||
1091 | } | ||
1092 | |||
1093 | /* switch to bootloader */ | ||
1094 | dev_dbg(dev, "%s: restart switch to bl m=%d -> m=%d\n", | ||
1095 | __func__, cd->mode, cur_mode); | ||
1096 | |||
1097 | /* catch operation->bl glitch */ | ||
1098 | if (cd->mode != CY_MODE_UNKNOWN) { | ||
1099 | /* Incase startup_state do not let startup_() */ | ||
1100 | cd->mode = CY_MODE_UNKNOWN; | ||
1101 | cyttsp4_queue_startup_(cd); | ||
1102 | goto cyttsp4_irq_exit; | ||
1103 | } | ||
1104 | |||
1105 | /* | ||
1106 | * do not wake thread on this switch since | ||
1107 | * it is possible to get an early heartbeat | ||
1108 | * prior to performing the reset | ||
1109 | */ | ||
1110 | cd->mode = cur_mode; | ||
1111 | |||
1112 | goto cyttsp4_irq_exit; | ||
1113 | } | ||
1114 | |||
1115 | switch (mode[0] & CY_HST_MODE) { | ||
1116 | case CY_HST_OPERATE: | ||
1117 | cur_mode = CY_MODE_OPERATIONAL; | ||
1118 | dev_vdbg(dev, "%s: operational\n", __func__); | ||
1119 | break; | ||
1120 | case CY_HST_CAT: | ||
1121 | cur_mode = CY_MODE_CAT; | ||
1122 | dev_vdbg(dev, "%s: CaT\n", __func__); | ||
1123 | break; | ||
1124 | case CY_HST_SYSINFO: | ||
1125 | cur_mode = CY_MODE_SYSINFO; | ||
1126 | dev_vdbg(dev, "%s: sysinfo\n", __func__); | ||
1127 | break; | ||
1128 | default: | ||
1129 | cur_mode = CY_MODE_UNKNOWN; | ||
1130 | dev_err(dev, "%s: unknown HST mode 0x%02X\n", __func__, | ||
1131 | mode[0]); | ||
1132 | break; | ||
1133 | } | ||
1134 | |||
1135 | /* Check whether this IRQ should be ignored (internal) */ | ||
1136 | if (cd->int_status & CY_INT_IGNORE) { | ||
1137 | dev_vdbg(dev, "%s: Ignoring IRQ\n", __func__); | ||
1138 | goto cyttsp4_irq_exit; | ||
1139 | } | ||
1140 | |||
1141 | /* Check for wake up interrupt */ | ||
1142 | if (cd->int_status & CY_INT_AWAKE) { | ||
1143 | cd->int_status &= ~CY_INT_AWAKE; | ||
1144 | wake_up(&cd->wait_q); | ||
1145 | dev_vdbg(dev, "%s: Received wake up interrupt\n", __func__); | ||
1146 | goto cyttsp4_irq_handshake; | ||
1147 | } | ||
1148 | |||
1149 | /* Expecting mode change interrupt */ | ||
1150 | if ((cd->int_status & CY_INT_MODE_CHANGE) | ||
1151 | && (mode[0] & CY_HST_MODE_CHANGE) == 0) { | ||
1152 | cd->int_status &= ~CY_INT_MODE_CHANGE; | ||
1153 | dev_dbg(dev, "%s: finish mode switch m=%d -> m=%d\n", | ||
1154 | __func__, cd->mode, cur_mode); | ||
1155 | cd->mode = cur_mode; | ||
1156 | wake_up(&cd->wait_q); | ||
1157 | goto cyttsp4_irq_handshake; | ||
1158 | } | ||
1159 | |||
1160 | /* compare current core mode to current device mode */ | ||
1161 | dev_vdbg(dev, "%s: cd->mode=%d cur_mode=%d\n", | ||
1162 | __func__, cd->mode, cur_mode); | ||
1163 | if ((mode[0] & CY_HST_MODE_CHANGE) == 0 && cd->mode != cur_mode) { | ||
1164 | /* Unexpected mode change occurred */ | ||
1165 | dev_err(dev, "%s %d->%d 0x%x\n", __func__, cd->mode, | ||
1166 | cur_mode, cd->int_status); | ||
1167 | dev_dbg(dev, "%s: Unexpected mode change, startup\n", | ||
1168 | __func__); | ||
1169 | cyttsp4_queue_startup_(cd); | ||
1170 | goto cyttsp4_irq_exit; | ||
1171 | } | ||
1172 | |||
1173 | /* Expecting command complete interrupt */ | ||
1174 | dev_vdbg(dev, "%s: command byte:0x%x\n", __func__, mode[cmd_ofs]); | ||
1175 | if ((cd->int_status & CY_INT_EXEC_CMD) | ||
1176 | && mode[cmd_ofs] & CY_CMD_COMPLETE) { | ||
1177 | cd->int_status &= ~CY_INT_EXEC_CMD; | ||
1178 | dev_vdbg(dev, "%s: Received command complete interrupt\n", | ||
1179 | __func__); | ||
1180 | wake_up(&cd->wait_q); | ||
1181 | /* | ||
1182 | * It is possible to receive a single interrupt for | ||
1183 | * command complete and touch/button status report. | ||
1184 | * Continue processing for a possible status report. | ||
1185 | */ | ||
1186 | } | ||
1187 | |||
1188 | /* This should be status report, read status regs */ | ||
1189 | if (cd->mode == CY_MODE_OPERATIONAL) { | ||
1190 | dev_vdbg(dev, "%s: Read status registers\n", __func__); | ||
1191 | rc = cyttsp4_load_status_regs(cd); | ||
1192 | if (rc < 0) | ||
1193 | dev_err(dev, "%s: fail read mode regs r=%d\n", | ||
1194 | __func__, rc); | ||
1195 | } | ||
1196 | |||
1197 | cyttsp4_mt_attention(cd); | ||
1198 | |||
1199 | cyttsp4_irq_handshake: | ||
1200 | /* handshake the event */ | ||
1201 | dev_vdbg(dev, "%s: Handshake mode=0x%02X r=%d\n", | ||
1202 | __func__, mode[0], rc); | ||
1203 | rc = cyttsp4_handshake(cd, mode[0]); | ||
1204 | if (rc < 0) | ||
1205 | dev_err(dev, "%s: Fail handshake mode=0x%02X r=%d\n", | ||
1206 | __func__, mode[0], rc); | ||
1207 | |||
1208 | /* | ||
1209 | * a non-zero udelay period is required for using | ||
1210 | * IRQF_TRIGGER_LOW in order to delay until the | ||
1211 | * device completes isr deassert | ||
1212 | */ | ||
1213 | udelay(cd->cpdata->level_irq_udelay); | ||
1214 | |||
1215 | cyttsp4_irq_exit: | ||
1216 | mutex_unlock(&cd->system_lock); | ||
1217 | return IRQ_HANDLED; | ||
1218 | } | ||
1219 | |||
1220 | static void cyttsp4_start_wd_timer(struct cyttsp4 *cd) | ||
1221 | { | ||
1222 | if (!CY_WATCHDOG_TIMEOUT) | ||
1223 | return; | ||
1224 | |||
1225 | mod_timer(&cd->watchdog_timer, jiffies + | ||
1226 | msecs_to_jiffies(CY_WATCHDOG_TIMEOUT)); | ||
1227 | } | ||
1228 | |||
1229 | static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd) | ||
1230 | { | ||
1231 | if (!CY_WATCHDOG_TIMEOUT) | ||
1232 | return; | ||
1233 | |||
1234 | /* | ||
1235 | * Ensure we wait until the watchdog timer | ||
1236 | * running on a different CPU finishes | ||
1237 | */ | ||
1238 | del_timer_sync(&cd->watchdog_timer); | ||
1239 | cancel_work_sync(&cd->watchdog_work); | ||
1240 | del_timer_sync(&cd->watchdog_timer); | ||
1241 | } | ||
1242 | |||
1243 | static void cyttsp4_watchdog_timer(unsigned long handle) | ||
1244 | { | ||
1245 | struct cyttsp4 *cd = (struct cyttsp4 *)handle; | ||
1246 | |||
1247 | dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__); | ||
1248 | |||
1249 | if (!cd) | ||
1250 | return; | ||
1251 | |||
1252 | if (!work_pending(&cd->watchdog_work)) | ||
1253 | schedule_work(&cd->watchdog_work); | ||
1254 | |||
1255 | return; | ||
1256 | } | ||
1257 | |||
1258 | static int cyttsp4_request_exclusive(struct cyttsp4 *cd, void *ownptr, | ||
1259 | int timeout_ms) | ||
1260 | { | ||
1261 | int t = msecs_to_jiffies(timeout_ms); | ||
1262 | bool with_timeout = (timeout_ms != 0); | ||
1263 | |||
1264 | mutex_lock(&cd->system_lock); | ||
1265 | if (!cd->exclusive_dev && cd->exclusive_waits == 0) { | ||
1266 | cd->exclusive_dev = ownptr; | ||
1267 | goto exit; | ||
1268 | } | ||
1269 | |||
1270 | cd->exclusive_waits++; | ||
1271 | wait: | ||
1272 | mutex_unlock(&cd->system_lock); | ||
1273 | if (with_timeout) { | ||
1274 | t = wait_event_timeout(cd->wait_q, !cd->exclusive_dev, t); | ||
1275 | if (IS_TMO(t)) { | ||
1276 | dev_err(cd->dev, "%s: tmo waiting exclusive access\n", | ||
1277 | __func__); | ||
1278 | mutex_lock(&cd->system_lock); | ||
1279 | cd->exclusive_waits--; | ||
1280 | mutex_unlock(&cd->system_lock); | ||
1281 | return -ETIME; | ||
1282 | } | ||
1283 | } else { | ||
1284 | wait_event(cd->wait_q, !cd->exclusive_dev); | ||
1285 | } | ||
1286 | mutex_lock(&cd->system_lock); | ||
1287 | if (cd->exclusive_dev) | ||
1288 | goto wait; | ||
1289 | cd->exclusive_dev = ownptr; | ||
1290 | cd->exclusive_waits--; | ||
1291 | exit: | ||
1292 | mutex_unlock(&cd->system_lock); | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1297 | /* | ||
1298 | * returns error if was not owned | ||
1299 | */ | ||
1300 | static int cyttsp4_release_exclusive(struct cyttsp4 *cd, void *ownptr) | ||
1301 | { | ||
1302 | mutex_lock(&cd->system_lock); | ||
1303 | if (cd->exclusive_dev != ownptr) { | ||
1304 | mutex_unlock(&cd->system_lock); | ||
1305 | return -EINVAL; | ||
1306 | } | ||
1307 | |||
1308 | dev_vdbg(cd->dev, "%s: exclusive_dev %p freed\n", | ||
1309 | __func__, cd->exclusive_dev); | ||
1310 | cd->exclusive_dev = NULL; | ||
1311 | wake_up(&cd->wait_q); | ||
1312 | mutex_unlock(&cd->system_lock); | ||
1313 | return 0; | ||
1314 | } | ||
1315 | |||
1316 | static int cyttsp4_wait_bl_heartbeat(struct cyttsp4 *cd) | ||
1317 | { | ||
1318 | long t; | ||
1319 | int rc = 0; | ||
1320 | |||
1321 | /* wait heartbeat */ | ||
1322 | dev_vdbg(cd->dev, "%s: wait heartbeat...\n", __func__); | ||
1323 | t = wait_event_timeout(cd->wait_q, cd->mode == CY_MODE_BOOTLOADER, | ||
1324 | msecs_to_jiffies(CY_CORE_RESET_AND_WAIT_TIMEOUT)); | ||
1325 | if (IS_TMO(t)) { | ||
1326 | dev_err(cd->dev, "%s: tmo waiting bl heartbeat cd->mode=%d\n", | ||
1327 | __func__, cd->mode); | ||
1328 | rc = -ETIME; | ||
1329 | } | ||
1330 | |||
1331 | return rc; | ||
1332 | } | ||
1333 | |||
1334 | static int cyttsp4_wait_sysinfo_mode(struct cyttsp4 *cd) | ||
1335 | { | ||
1336 | long t; | ||
1337 | |||
1338 | dev_vdbg(cd->dev, "%s: wait sysinfo...\n", __func__); | ||
1339 | |||
1340 | t = wait_event_timeout(cd->wait_q, cd->mode == CY_MODE_SYSINFO, | ||
1341 | msecs_to_jiffies(CY_CORE_MODE_CHANGE_TIMEOUT)); | ||
1342 | if (IS_TMO(t)) { | ||
1343 | dev_err(cd->dev, "%s: tmo waiting exit bl cd->mode=%d\n", | ||
1344 | __func__, cd->mode); | ||
1345 | mutex_lock(&cd->system_lock); | ||
1346 | cd->int_status &= ~CY_INT_MODE_CHANGE; | ||
1347 | mutex_unlock(&cd->system_lock); | ||
1348 | return -ETIME; | ||
1349 | } | ||
1350 | |||
1351 | return 0; | ||
1352 | } | ||
1353 | |||
1354 | static int cyttsp4_reset_and_wait(struct cyttsp4 *cd) | ||
1355 | { | ||
1356 | int rc; | ||
1357 | |||
1358 | /* reset hardware */ | ||
1359 | mutex_lock(&cd->system_lock); | ||
1360 | dev_dbg(cd->dev, "%s: reset hw...\n", __func__); | ||
1361 | rc = cyttsp4_hw_reset(cd); | ||
1362 | cd->mode = CY_MODE_UNKNOWN; | ||
1363 | mutex_unlock(&cd->system_lock); | ||
1364 | if (rc < 0) { | ||
1365 | dev_err(cd->dev, "%s:Fail hw reset r=%d\n", __func__, rc); | ||
1366 | return rc; | ||
1367 | } | ||
1368 | |||
1369 | return cyttsp4_wait_bl_heartbeat(cd); | ||
1370 | } | ||
1371 | |||
1372 | /* | ||
1373 | * returns err if refused or timeout; block until mode change complete | ||
1374 | * bit is set (mode change interrupt) | ||
1375 | */ | ||
1376 | static int cyttsp4_set_mode(struct cyttsp4 *cd, int new_mode) | ||
1377 | { | ||
1378 | u8 new_dev_mode; | ||
1379 | u8 mode; | ||
1380 | long t; | ||
1381 | int rc; | ||
1382 | |||
1383 | switch (new_mode) { | ||
1384 | case CY_MODE_OPERATIONAL: | ||
1385 | new_dev_mode = CY_HST_OPERATE; | ||
1386 | break; | ||
1387 | case CY_MODE_SYSINFO: | ||
1388 | new_dev_mode = CY_HST_SYSINFO; | ||
1389 | break; | ||
1390 | case CY_MODE_CAT: | ||
1391 | new_dev_mode = CY_HST_CAT; | ||
1392 | break; | ||
1393 | default: | ||
1394 | dev_err(cd->dev, "%s: invalid mode: %02X(%d)\n", | ||
1395 | __func__, new_mode, new_mode); | ||
1396 | return -EINVAL; | ||
1397 | } | ||
1398 | |||
1399 | /* change mode */ | ||
1400 | dev_dbg(cd->dev, "%s: %s=%p new_dev_mode=%02X new_mode=%d\n", | ||
1401 | __func__, "have exclusive", cd->exclusive_dev, | ||
1402 | new_dev_mode, new_mode); | ||
1403 | |||
1404 | mutex_lock(&cd->system_lock); | ||
1405 | rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); | ||
1406 | if (rc < 0) { | ||
1407 | mutex_unlock(&cd->system_lock); | ||
1408 | dev_err(cd->dev, "%s: Fail read mode r=%d\n", | ||
1409 | __func__, rc); | ||
1410 | goto exit; | ||
1411 | } | ||
1412 | |||
1413 | /* Clear device mode bits and set to new mode */ | ||
1414 | mode &= ~CY_HST_MODE; | ||
1415 | mode |= new_dev_mode | CY_HST_MODE_CHANGE; | ||
1416 | |||
1417 | cd->int_status |= CY_INT_MODE_CHANGE; | ||
1418 | rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(mode), &mode); | ||
1419 | mutex_unlock(&cd->system_lock); | ||
1420 | if (rc < 0) { | ||
1421 | dev_err(cd->dev, "%s: Fail write mode change r=%d\n", | ||
1422 | __func__, rc); | ||
1423 | goto exit; | ||
1424 | } | ||
1425 | |||
1426 | /* wait for mode change done interrupt */ | ||
1427 | t = wait_event_timeout(cd->wait_q, | ||
1428 | (cd->int_status & CY_INT_MODE_CHANGE) == 0, | ||
1429 | msecs_to_jiffies(CY_CORE_MODE_CHANGE_TIMEOUT)); | ||
1430 | dev_dbg(cd->dev, "%s: back from wait t=%ld cd->mode=%d\n", | ||
1431 | __func__, t, cd->mode); | ||
1432 | |||
1433 | if (IS_TMO(t)) { | ||
1434 | dev_err(cd->dev, "%s: %s\n", __func__, | ||
1435 | "tmo waiting mode change"); | ||
1436 | mutex_lock(&cd->system_lock); | ||
1437 | cd->int_status &= ~CY_INT_MODE_CHANGE; | ||
1438 | mutex_unlock(&cd->system_lock); | ||
1439 | rc = -EINVAL; | ||
1440 | } | ||
1441 | |||
1442 | exit: | ||
1443 | return rc; | ||
1444 | } | ||
1445 | |||
1446 | static void cyttsp4_watchdog_work(struct work_struct *work) | ||
1447 | { | ||
1448 | struct cyttsp4 *cd = | ||
1449 | container_of(work, struct cyttsp4, watchdog_work); | ||
1450 | u8 *mode; | ||
1451 | int retval; | ||
1452 | |||
1453 | mutex_lock(&cd->system_lock); | ||
1454 | retval = cyttsp4_load_status_regs(cd); | ||
1455 | if (retval < 0) { | ||
1456 | dev_err(cd->dev, | ||
1457 | "%s: failed to access device in watchdog timer r=%d\n", | ||
1458 | __func__, retval); | ||
1459 | cyttsp4_queue_startup_(cd); | ||
1460 | goto cyttsp4_timer_watchdog_exit_error; | ||
1461 | } | ||
1462 | mode = &cd->sysinfo.xy_mode[CY_REG_BASE]; | ||
1463 | if (IS_BOOTLOADER(mode[0], mode[1])) { | ||
1464 | dev_err(cd->dev, | ||
1465 | "%s: device found in bootloader mode when operational mode\n", | ||
1466 | __func__); | ||
1467 | cyttsp4_queue_startup_(cd); | ||
1468 | goto cyttsp4_timer_watchdog_exit_error; | ||
1469 | } | ||
1470 | |||
1471 | cyttsp4_start_wd_timer(cd); | ||
1472 | cyttsp4_timer_watchdog_exit_error: | ||
1473 | mutex_unlock(&cd->system_lock); | ||
1474 | return; | ||
1475 | } | ||
1476 | |||
1477 | static int cyttsp4_core_sleep_(struct cyttsp4 *cd) | ||
1478 | { | ||
1479 | enum cyttsp4_sleep_state ss = SS_SLEEP_ON; | ||
1480 | enum cyttsp4_int_state int_status = CY_INT_IGNORE; | ||
1481 | int rc = 0; | ||
1482 | u8 mode[2]; | ||
1483 | |||
1484 | /* Already in sleep mode? */ | ||
1485 | mutex_lock(&cd->system_lock); | ||
1486 | if (cd->sleep_state == SS_SLEEP_ON) { | ||
1487 | mutex_unlock(&cd->system_lock); | ||
1488 | return 0; | ||
1489 | } | ||
1490 | cd->sleep_state = SS_SLEEPING; | ||
1491 | mutex_unlock(&cd->system_lock); | ||
1492 | |||
1493 | cyttsp4_stop_wd_timer(cd); | ||
1494 | |||
1495 | /* Wait until currently running IRQ handler exits and disable IRQ */ | ||
1496 | disable_irq(cd->irq); | ||
1497 | |||
1498 | dev_vdbg(cd->dev, "%s: write DEEP SLEEP...\n", __func__); | ||
1499 | mutex_lock(&cd->system_lock); | ||
1500 | rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); | ||
1501 | if (rc) { | ||
1502 | mutex_unlock(&cd->system_lock); | ||
1503 | dev_err(cd->dev, "%s: Fail read adapter r=%d\n", __func__, rc); | ||
1504 | goto error; | ||
1505 | } | ||
1506 | |||
1507 | if (IS_BOOTLOADER(mode[0], mode[1])) { | ||
1508 | mutex_unlock(&cd->system_lock); | ||
1509 | dev_err(cd->dev, "%s: Device in BOOTLADER mode.\n", __func__); | ||
1510 | rc = -EINVAL; | ||
1511 | goto error; | ||
1512 | } | ||
1513 | |||
1514 | mode[0] |= CY_HST_SLEEP; | ||
1515 | rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(mode[0]), &mode[0]); | ||
1516 | mutex_unlock(&cd->system_lock); | ||
1517 | if (rc) { | ||
1518 | dev_err(cd->dev, "%s: Fail write adapter r=%d\n", __func__, rc); | ||
1519 | goto error; | ||
1520 | } | ||
1521 | dev_vdbg(cd->dev, "%s: write DEEP SLEEP succeeded\n", __func__); | ||
1522 | |||
1523 | if (cd->cpdata->power) { | ||
1524 | dev_dbg(cd->dev, "%s: Power down HW\n", __func__); | ||
1525 | rc = cd->cpdata->power(cd->cpdata, 0, cd->dev, &cd->ignore_irq); | ||
1526 | } else { | ||
1527 | dev_dbg(cd->dev, "%s: No power function\n", __func__); | ||
1528 | rc = 0; | ||
1529 | } | ||
1530 | if (rc < 0) { | ||
1531 | dev_err(cd->dev, "%s: HW Power down fails r=%d\n", | ||
1532 | __func__, rc); | ||
1533 | goto error; | ||
1534 | } | ||
1535 | |||
1536 | /* Give time to FW to sleep */ | ||
1537 | msleep(50); | ||
1538 | |||
1539 | goto exit; | ||
1540 | |||
1541 | error: | ||
1542 | ss = SS_SLEEP_OFF; | ||
1543 | int_status = CY_INT_NONE; | ||
1544 | cyttsp4_start_wd_timer(cd); | ||
1545 | |||
1546 | exit: | ||
1547 | mutex_lock(&cd->system_lock); | ||
1548 | cd->sleep_state = ss; | ||
1549 | cd->int_status |= int_status; | ||
1550 | mutex_unlock(&cd->system_lock); | ||
1551 | enable_irq(cd->irq); | ||
1552 | return rc; | ||
1553 | } | ||
1554 | |||
1555 | static int cyttsp4_core_sleep(struct cyttsp4 *cd) | ||
1556 | { | ||
1557 | int rc; | ||
1558 | |||
1559 | rc = cyttsp4_request_exclusive(cd, cd->dev, | ||
1560 | CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT); | ||
1561 | if (rc < 0) { | ||
1562 | dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", | ||
1563 | __func__, cd->exclusive_dev, cd->dev); | ||
1564 | return 0; | ||
1565 | } | ||
1566 | |||
1567 | rc = cyttsp4_core_sleep_(cd); | ||
1568 | |||
1569 | if (cyttsp4_release_exclusive(cd, cd->dev) < 0) | ||
1570 | dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); | ||
1571 | else | ||
1572 | dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); | ||
1573 | |||
1574 | return rc; | ||
1575 | } | ||
1576 | |||
1577 | static int cyttsp4_core_wake_(struct cyttsp4 *cd) | ||
1578 | { | ||
1579 | struct device *dev = cd->dev; | ||
1580 | int rc; | ||
1581 | u8 mode; | ||
1582 | int t; | ||
1583 | |||
1584 | /* Already woken? */ | ||
1585 | mutex_lock(&cd->system_lock); | ||
1586 | if (cd->sleep_state == SS_SLEEP_OFF) { | ||
1587 | mutex_unlock(&cd->system_lock); | ||
1588 | return 0; | ||
1589 | } | ||
1590 | cd->int_status &= ~CY_INT_IGNORE; | ||
1591 | cd->int_status |= CY_INT_AWAKE; | ||
1592 | cd->sleep_state = SS_WAKING; | ||
1593 | |||
1594 | if (cd->cpdata->power) { | ||
1595 | dev_dbg(dev, "%s: Power up HW\n", __func__); | ||
1596 | rc = cd->cpdata->power(cd->cpdata, 1, dev, &cd->ignore_irq); | ||
1597 | } else { | ||
1598 | dev_dbg(dev, "%s: No power function\n", __func__); | ||
1599 | rc = -ENOSYS; | ||
1600 | } | ||
1601 | if (rc < 0) { | ||
1602 | dev_err(dev, "%s: HW Power up fails r=%d\n", | ||
1603 | __func__, rc); | ||
1604 | |||
1605 | /* Initiate a read transaction to wake up */ | ||
1606 | cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); | ||
1607 | } else | ||
1608 | dev_vdbg(cd->dev, "%s: HW power up succeeds\n", | ||
1609 | __func__); | ||
1610 | mutex_unlock(&cd->system_lock); | ||
1611 | |||
1612 | t = wait_event_timeout(cd->wait_q, | ||
1613 | (cd->int_status & CY_INT_AWAKE) == 0, | ||
1614 | msecs_to_jiffies(CY_CORE_WAKEUP_TIMEOUT)); | ||
1615 | if (IS_TMO(t)) { | ||
1616 | dev_err(dev, "%s: TMO waiting for wakeup\n", __func__); | ||
1617 | mutex_lock(&cd->system_lock); | ||
1618 | cd->int_status &= ~CY_INT_AWAKE; | ||
1619 | /* Try starting up */ | ||
1620 | cyttsp4_queue_startup_(cd); | ||
1621 | mutex_unlock(&cd->system_lock); | ||
1622 | } | ||
1623 | |||
1624 | mutex_lock(&cd->system_lock); | ||
1625 | cd->sleep_state = SS_SLEEP_OFF; | ||
1626 | mutex_unlock(&cd->system_lock); | ||
1627 | |||
1628 | cyttsp4_start_wd_timer(cd); | ||
1629 | |||
1630 | return 0; | ||
1631 | } | ||
1632 | |||
1633 | static int cyttsp4_core_wake(struct cyttsp4 *cd) | ||
1634 | { | ||
1635 | int rc; | ||
1636 | |||
1637 | rc = cyttsp4_request_exclusive(cd, cd->dev, | ||
1638 | CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT); | ||
1639 | if (rc < 0) { | ||
1640 | dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", | ||
1641 | __func__, cd->exclusive_dev, cd->dev); | ||
1642 | return 0; | ||
1643 | } | ||
1644 | |||
1645 | rc = cyttsp4_core_wake_(cd); | ||
1646 | |||
1647 | if (cyttsp4_release_exclusive(cd, cd->dev) < 0) | ||
1648 | dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); | ||
1649 | else | ||
1650 | dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); | ||
1651 | |||
1652 | return rc; | ||
1653 | } | ||
1654 | |||
1655 | static int cyttsp4_startup_(struct cyttsp4 *cd) | ||
1656 | { | ||
1657 | int retry = CY_CORE_STARTUP_RETRY_COUNT; | ||
1658 | int rc; | ||
1659 | |||
1660 | cyttsp4_stop_wd_timer(cd); | ||
1661 | |||
1662 | reset: | ||
1663 | if (retry != CY_CORE_STARTUP_RETRY_COUNT) | ||
1664 | dev_dbg(cd->dev, "%s: Retry %d\n", __func__, | ||
1665 | CY_CORE_STARTUP_RETRY_COUNT - retry); | ||
1666 | |||
1667 | /* reset hardware and wait for heartbeat */ | ||
1668 | rc = cyttsp4_reset_and_wait(cd); | ||
1669 | if (rc < 0) { | ||
1670 | dev_err(cd->dev, "%s: Error on h/w reset r=%d\n", __func__, rc); | ||
1671 | if (retry--) | ||
1672 | goto reset; | ||
1673 | goto exit; | ||
1674 | } | ||
1675 | |||
1676 | /* exit bl into sysinfo mode */ | ||
1677 | dev_vdbg(cd->dev, "%s: write exit ldr...\n", __func__); | ||
1678 | mutex_lock(&cd->system_lock); | ||
1679 | cd->int_status &= ~CY_INT_IGNORE; | ||
1680 | cd->int_status |= CY_INT_MODE_CHANGE; | ||
1681 | |||
1682 | rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(ldr_exit), | ||
1683 | (u8 *)ldr_exit); | ||
1684 | mutex_unlock(&cd->system_lock); | ||
1685 | if (rc < 0) { | ||
1686 | dev_err(cd->dev, "%s: Fail write r=%d\n", __func__, rc); | ||
1687 | if (retry--) | ||
1688 | goto reset; | ||
1689 | goto exit; | ||
1690 | } | ||
1691 | |||
1692 | rc = cyttsp4_wait_sysinfo_mode(cd); | ||
1693 | if (rc < 0) { | ||
1694 | u8 buf[sizeof(ldr_err_app)]; | ||
1695 | int rc1; | ||
1696 | |||
1697 | /* Check for invalid/corrupted touch application */ | ||
1698 | rc1 = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(ldr_err_app), | ||
1699 | buf); | ||
1700 | if (rc1) { | ||
1701 | dev_err(cd->dev, "%s: Fail read r=%d\n", __func__, rc1); | ||
1702 | } else if (!memcmp(buf, ldr_err_app, sizeof(ldr_err_app))) { | ||
1703 | dev_err(cd->dev, "%s: Error launching touch application\n", | ||
1704 | __func__); | ||
1705 | mutex_lock(&cd->system_lock); | ||
1706 | cd->invalid_touch_app = true; | ||
1707 | mutex_unlock(&cd->system_lock); | ||
1708 | goto exit_no_wd; | ||
1709 | } | ||
1710 | |||
1711 | if (retry--) | ||
1712 | goto reset; | ||
1713 | goto exit; | ||
1714 | } | ||
1715 | |||
1716 | mutex_lock(&cd->system_lock); | ||
1717 | cd->invalid_touch_app = false; | ||
1718 | mutex_unlock(&cd->system_lock); | ||
1719 | |||
1720 | /* read sysinfo data */ | ||
1721 | dev_vdbg(cd->dev, "%s: get sysinfo regs..\n", __func__); | ||
1722 | rc = cyttsp4_get_sysinfo_regs(cd); | ||
1723 | if (rc < 0) { | ||
1724 | dev_err(cd->dev, "%s: failed to get sysinfo regs rc=%d\n", | ||
1725 | __func__, rc); | ||
1726 | if (retry--) | ||
1727 | goto reset; | ||
1728 | goto exit; | ||
1729 | } | ||
1730 | |||
1731 | rc = cyttsp4_set_mode(cd, CY_MODE_OPERATIONAL); | ||
1732 | if (rc < 0) { | ||
1733 | dev_err(cd->dev, "%s: failed to set mode to operational rc=%d\n", | ||
1734 | __func__, rc); | ||
1735 | if (retry--) | ||
1736 | goto reset; | ||
1737 | goto exit; | ||
1738 | } | ||
1739 | |||
1740 | cyttsp4_lift_all(&cd->md); | ||
1741 | |||
1742 | /* restore to sleep if was suspended */ | ||
1743 | mutex_lock(&cd->system_lock); | ||
1744 | if (cd->sleep_state == SS_SLEEP_ON) { | ||
1745 | cd->sleep_state = SS_SLEEP_OFF; | ||
1746 | mutex_unlock(&cd->system_lock); | ||
1747 | cyttsp4_core_sleep_(cd); | ||
1748 | goto exit_no_wd; | ||
1749 | } | ||
1750 | mutex_unlock(&cd->system_lock); | ||
1751 | |||
1752 | exit: | ||
1753 | cyttsp4_start_wd_timer(cd); | ||
1754 | exit_no_wd: | ||
1755 | return rc; | ||
1756 | } | ||
1757 | |||
1758 | static int cyttsp4_startup(struct cyttsp4 *cd) | ||
1759 | { | ||
1760 | int rc; | ||
1761 | |||
1762 | mutex_lock(&cd->system_lock); | ||
1763 | cd->startup_state = STARTUP_RUNNING; | ||
1764 | mutex_unlock(&cd->system_lock); | ||
1765 | |||
1766 | rc = cyttsp4_request_exclusive(cd, cd->dev, | ||
1767 | CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT); | ||
1768 | if (rc < 0) { | ||
1769 | dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", | ||
1770 | __func__, cd->exclusive_dev, cd->dev); | ||
1771 | goto exit; | ||
1772 | } | ||
1773 | |||
1774 | rc = cyttsp4_startup_(cd); | ||
1775 | |||
1776 | if (cyttsp4_release_exclusive(cd, cd->dev) < 0) | ||
1777 | /* Don't return fail code, mode is already changed. */ | ||
1778 | dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); | ||
1779 | else | ||
1780 | dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); | ||
1781 | |||
1782 | exit: | ||
1783 | mutex_lock(&cd->system_lock); | ||
1784 | cd->startup_state = STARTUP_NONE; | ||
1785 | mutex_unlock(&cd->system_lock); | ||
1786 | |||
1787 | /* Wake the waiters for end of startup */ | ||
1788 | wake_up(&cd->wait_q); | ||
1789 | |||
1790 | return rc; | ||
1791 | } | ||
1792 | |||
1793 | static void cyttsp4_startup_work_function(struct work_struct *work) | ||
1794 | { | ||
1795 | struct cyttsp4 *cd = container_of(work, struct cyttsp4, startup_work); | ||
1796 | int rc; | ||
1797 | |||
1798 | rc = cyttsp4_startup(cd); | ||
1799 | if (rc < 0) | ||
1800 | dev_err(cd->dev, "%s: Fail queued startup r=%d\n", | ||
1801 | __func__, rc); | ||
1802 | } | ||
1803 | |||
1804 | static void cyttsp4_free_si_ptrs(struct cyttsp4 *cd) | ||
1805 | { | ||
1806 | struct cyttsp4_sysinfo *si = &cd->sysinfo; | ||
1807 | |||
1808 | if (!si) | ||
1809 | return; | ||
1810 | |||
1811 | kfree(si->si_ptrs.cydata); | ||
1812 | kfree(si->si_ptrs.test); | ||
1813 | kfree(si->si_ptrs.pcfg); | ||
1814 | kfree(si->si_ptrs.opcfg); | ||
1815 | kfree(si->si_ptrs.ddata); | ||
1816 | kfree(si->si_ptrs.mdata); | ||
1817 | kfree(si->btn); | ||
1818 | kfree(si->xy_mode); | ||
1819 | kfree(si->xy_data); | ||
1820 | kfree(si->btn_rec_data); | ||
1821 | } | ||
1822 | |||
1823 | #if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME) | ||
1824 | static int cyttsp4_core_suspend(struct device *dev) | ||
1825 | { | ||
1826 | struct cyttsp4 *cd = dev_get_drvdata(dev); | ||
1827 | struct cyttsp4_mt_data *md = &cd->md; | ||
1828 | int rc; | ||
1829 | |||
1830 | md->is_suspended = true; | ||
1831 | |||
1832 | rc = cyttsp4_core_sleep(cd); | ||
1833 | if (rc < 0) { | ||
1834 | dev_err(dev, "%s: Error on sleep\n", __func__); | ||
1835 | return -EAGAIN; | ||
1836 | } | ||
1837 | return 0; | ||
1838 | } | ||
1839 | |||
1840 | static int cyttsp4_core_resume(struct device *dev) | ||
1841 | { | ||
1842 | struct cyttsp4 *cd = dev_get_drvdata(dev); | ||
1843 | struct cyttsp4_mt_data *md = &cd->md; | ||
1844 | int rc; | ||
1845 | |||
1846 | md->is_suspended = false; | ||
1847 | |||
1848 | rc = cyttsp4_core_wake(cd); | ||
1849 | if (rc < 0) { | ||
1850 | dev_err(dev, "%s: Error on wake\n", __func__); | ||
1851 | return -EAGAIN; | ||
1852 | } | ||
1853 | |||
1854 | return 0; | ||
1855 | } | ||
1856 | #endif | ||
1857 | |||
1858 | const struct dev_pm_ops cyttsp4_pm_ops = { | ||
1859 | SET_SYSTEM_SLEEP_PM_OPS(cyttsp4_core_suspend, cyttsp4_core_resume) | ||
1860 | SET_RUNTIME_PM_OPS(cyttsp4_core_suspend, cyttsp4_core_resume, NULL) | ||
1861 | }; | ||
1862 | EXPORT_SYMBOL_GPL(cyttsp4_pm_ops); | ||
1863 | |||
1864 | static int cyttsp4_mt_open(struct input_dev *input) | ||
1865 | { | ||
1866 | pm_runtime_get(input->dev.parent); | ||
1867 | return 0; | ||
1868 | } | ||
1869 | |||
1870 | static void cyttsp4_mt_close(struct input_dev *input) | ||
1871 | { | ||
1872 | struct cyttsp4_mt_data *md = input_get_drvdata(input); | ||
1873 | mutex_lock(&md->report_lock); | ||
1874 | if (!md->is_suspended) | ||
1875 | pm_runtime_put(input->dev.parent); | ||
1876 | mutex_unlock(&md->report_lock); | ||
1877 | } | ||
1878 | |||
1879 | |||
1880 | static int cyttsp4_setup_input_device(struct cyttsp4 *cd) | ||
1881 | { | ||
1882 | struct device *dev = cd->dev; | ||
1883 | struct cyttsp4_mt_data *md = &cd->md; | ||
1884 | int signal = CY_IGNORE_VALUE; | ||
1885 | int max_x, max_y, max_p, min, max; | ||
1886 | int max_x_tmp, max_y_tmp; | ||
1887 | int i; | ||
1888 | int rc; | ||
1889 | |||
1890 | dev_vdbg(dev, "%s: Initialize event signals\n", __func__); | ||
1891 | __set_bit(EV_ABS, md->input->evbit); | ||
1892 | __set_bit(EV_REL, md->input->evbit); | ||
1893 | __set_bit(EV_KEY, md->input->evbit); | ||
1894 | |||
1895 | max_x_tmp = md->si->si_ofs.max_x; | ||
1896 | max_y_tmp = md->si->si_ofs.max_y; | ||
1897 | |||
1898 | /* get maximum values from the sysinfo data */ | ||
1899 | if (md->pdata->flags & CY_FLAG_FLIP) { | ||
1900 | max_x = max_y_tmp - 1; | ||
1901 | max_y = max_x_tmp - 1; | ||
1902 | } else { | ||
1903 | max_x = max_x_tmp - 1; | ||
1904 | max_y = max_y_tmp - 1; | ||
1905 | } | ||
1906 | max_p = md->si->si_ofs.max_p; | ||
1907 | |||
1908 | /* set event signal capabilities */ | ||
1909 | for (i = 0; i < (md->pdata->frmwrk->size / CY_NUM_ABS_SET); i++) { | ||
1910 | signal = md->pdata->frmwrk->abs | ||
1911 | [(i * CY_NUM_ABS_SET) + CY_SIGNAL_OST]; | ||
1912 | if (signal != CY_IGNORE_VALUE) { | ||
1913 | __set_bit(signal, md->input->absbit); | ||
1914 | min = md->pdata->frmwrk->abs | ||
1915 | [(i * CY_NUM_ABS_SET) + CY_MIN_OST]; | ||
1916 | max = md->pdata->frmwrk->abs | ||
1917 | [(i * CY_NUM_ABS_SET) + CY_MAX_OST]; | ||
1918 | if (i == CY_ABS_ID_OST) { | ||
1919 | /* shift track ids down to start at 0 */ | ||
1920 | max = max - min; | ||
1921 | min = min - min; | ||
1922 | } else if (i == CY_ABS_X_OST) | ||
1923 | max = max_x; | ||
1924 | else if (i == CY_ABS_Y_OST) | ||
1925 | max = max_y; | ||
1926 | else if (i == CY_ABS_P_OST) | ||
1927 | max = max_p; | ||
1928 | input_set_abs_params(md->input, signal, min, max, | ||
1929 | md->pdata->frmwrk->abs | ||
1930 | [(i * CY_NUM_ABS_SET) + CY_FUZZ_OST], | ||
1931 | md->pdata->frmwrk->abs | ||
1932 | [(i * CY_NUM_ABS_SET) + CY_FLAT_OST]); | ||
1933 | dev_dbg(dev, "%s: register signal=%02X min=%d max=%d\n", | ||
1934 | __func__, signal, min, max); | ||
1935 | if ((i == CY_ABS_ID_OST) && | ||
1936 | (md->si->si_ofs.tch_rec_size < | ||
1937 | CY_TMA4XX_TCH_REC_SIZE)) | ||
1938 | break; | ||
1939 | } | ||
1940 | } | ||
1941 | |||
1942 | input_mt_init_slots(md->input, md->si->si_ofs.tch_abs[CY_TCH_T].max, | ||
1943 | INPUT_MT_DIRECT); | ||
1944 | rc = input_register_device(md->input); | ||
1945 | if (rc < 0) | ||
1946 | dev_err(dev, "%s: Error, failed register input device r=%d\n", | ||
1947 | __func__, rc); | ||
1948 | return rc; | ||
1949 | } | ||
1950 | |||
1951 | static int cyttsp4_mt_probe(struct cyttsp4 *cd) | ||
1952 | { | ||
1953 | struct device *dev = cd->dev; | ||
1954 | struct cyttsp4_mt_data *md = &cd->md; | ||
1955 | struct cyttsp4_mt_platform_data *pdata = cd->pdata->mt_pdata; | ||
1956 | int rc = 0; | ||
1957 | |||
1958 | mutex_init(&md->report_lock); | ||
1959 | md->pdata = pdata; | ||
1960 | /* Create the input device and register it. */ | ||
1961 | dev_vdbg(dev, "%s: Create the input device and register it\n", | ||
1962 | __func__); | ||
1963 | md->input = input_allocate_device(); | ||
1964 | if (md->input == NULL) { | ||
1965 | dev_err(dev, "%s: Error, failed to allocate input device\n", | ||
1966 | __func__); | ||
1967 | rc = -ENOSYS; | ||
1968 | goto error_alloc_failed; | ||
1969 | } | ||
1970 | |||
1971 | md->input->name = pdata->inp_dev_name; | ||
1972 | scnprintf(md->phys, sizeof(md->phys)-1, "%s", dev_name(dev)); | ||
1973 | md->input->phys = md->phys; | ||
1974 | md->input->id.bustype = cd->bus_ops->bustype; | ||
1975 | md->input->dev.parent = dev; | ||
1976 | md->input->open = cyttsp4_mt_open; | ||
1977 | md->input->close = cyttsp4_mt_close; | ||
1978 | input_set_drvdata(md->input, md); | ||
1979 | |||
1980 | /* get sysinfo */ | ||
1981 | md->si = &cd->sysinfo; | ||
1982 | if (!md->si) { | ||
1983 | dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n", | ||
1984 | __func__, md->si); | ||
1985 | goto error_get_sysinfo; | ||
1986 | } | ||
1987 | |||
1988 | rc = cyttsp4_setup_input_device(cd); | ||
1989 | if (rc) | ||
1990 | goto error_init_input; | ||
1991 | |||
1992 | return 0; | ||
1993 | |||
1994 | error_init_input: | ||
1995 | input_free_device(md->input); | ||
1996 | error_get_sysinfo: | ||
1997 | input_set_drvdata(md->input, NULL); | ||
1998 | error_alloc_failed: | ||
1999 | dev_err(dev, "%s failed.\n", __func__); | ||
2000 | return rc; | ||
2001 | } | ||
2002 | |||
2003 | struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, | ||
2004 | struct device *dev, u16 irq, size_t xfer_buf_size) | ||
2005 | { | ||
2006 | struct cyttsp4 *cd; | ||
2007 | struct cyttsp4_platform_data *pdata = dev_get_platdata(dev); | ||
2008 | unsigned long irq_flags; | ||
2009 | int rc = 0; | ||
2010 | |||
2011 | if (!pdata || !pdata->core_pdata || !pdata->mt_pdata) { | ||
2012 | dev_err(dev, "%s: Missing platform data\n", __func__); | ||
2013 | rc = -ENODEV; | ||
2014 | goto error_no_pdata; | ||
2015 | } | ||
2016 | |||
2017 | cd = kzalloc(sizeof(*cd), GFP_KERNEL); | ||
2018 | if (!cd) { | ||
2019 | dev_err(dev, "%s: Error, kzalloc\n", __func__); | ||
2020 | rc = -ENOMEM; | ||
2021 | goto error_alloc_data; | ||
2022 | } | ||
2023 | |||
2024 | cd->xfer_buf = kzalloc(xfer_buf_size, GFP_KERNEL); | ||
2025 | if (!cd->xfer_buf) { | ||
2026 | dev_err(dev, "%s: Error, kzalloc\n", __func__); | ||
2027 | rc = -ENOMEM; | ||
2028 | goto error_free_cd; | ||
2029 | } | ||
2030 | |||
2031 | /* Initialize device info */ | ||
2032 | cd->dev = dev; | ||
2033 | cd->pdata = pdata; | ||
2034 | cd->cpdata = pdata->core_pdata; | ||
2035 | cd->bus_ops = ops; | ||
2036 | |||
2037 | /* Initialize mutexes and spinlocks */ | ||
2038 | mutex_init(&cd->system_lock); | ||
2039 | mutex_init(&cd->adap_lock); | ||
2040 | |||
2041 | /* Initialize wait queue */ | ||
2042 | init_waitqueue_head(&cd->wait_q); | ||
2043 | |||
2044 | /* Initialize works */ | ||
2045 | INIT_WORK(&cd->startup_work, cyttsp4_startup_work_function); | ||
2046 | INIT_WORK(&cd->watchdog_work, cyttsp4_watchdog_work); | ||
2047 | |||
2048 | /* Initialize IRQ */ | ||
2049 | cd->irq = gpio_to_irq(cd->cpdata->irq_gpio); | ||
2050 | if (cd->irq < 0) { | ||
2051 | rc = -EINVAL; | ||
2052 | goto error_free_xfer; | ||
2053 | } | ||
2054 | |||
2055 | dev_set_drvdata(dev, cd); | ||
2056 | |||
2057 | /* Call platform init function */ | ||
2058 | if (cd->cpdata->init) { | ||
2059 | dev_dbg(cd->dev, "%s: Init HW\n", __func__); | ||
2060 | rc = cd->cpdata->init(cd->cpdata, 1, cd->dev); | ||
2061 | } else { | ||
2062 | dev_dbg(cd->dev, "%s: No HW INIT function\n", __func__); | ||
2063 | rc = 0; | ||
2064 | } | ||
2065 | if (rc < 0) | ||
2066 | dev_err(cd->dev, "%s: HW Init fail r=%d\n", __func__, rc); | ||
2067 | |||
2068 | dev_dbg(dev, "%s: initialize threaded irq=%d\n", __func__, cd->irq); | ||
2069 | if (cd->cpdata->level_irq_udelay > 0) | ||
2070 | /* use level triggered interrupts */ | ||
2071 | irq_flags = IRQF_TRIGGER_LOW | IRQF_ONESHOT; | ||
2072 | else | ||
2073 | /* use edge triggered interrupts */ | ||
2074 | irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; | ||
2075 | |||
2076 | rc = request_threaded_irq(cd->irq, NULL, cyttsp4_irq, irq_flags, | ||
2077 | dev_name(dev), cd); | ||
2078 | if (rc < 0) { | ||
2079 | dev_err(dev, "%s: Error, could not request irq\n", __func__); | ||
2080 | goto error_request_irq; | ||
2081 | } | ||
2082 | |||
2083 | /* Setup watchdog timer */ | ||
2084 | setup_timer(&cd->watchdog_timer, cyttsp4_watchdog_timer, | ||
2085 | (unsigned long)cd); | ||
2086 | |||
2087 | /* | ||
2088 | * call startup directly to ensure that the device | ||
2089 | * is tested before leaving the probe | ||
2090 | */ | ||
2091 | rc = cyttsp4_startup(cd); | ||
2092 | |||
2093 | /* Do not fail probe if startup fails but the device is detected */ | ||
2094 | if (rc < 0 && cd->mode == CY_MODE_UNKNOWN) { | ||
2095 | dev_err(cd->dev, "%s: Fail initial startup r=%d\n", | ||
2096 | __func__, rc); | ||
2097 | goto error_startup; | ||
2098 | } | ||
2099 | |||
2100 | rc = cyttsp4_mt_probe(cd); | ||
2101 | if (rc < 0) { | ||
2102 | dev_err(dev, "%s: Error, fail mt probe\n", __func__); | ||
2103 | goto error_startup; | ||
2104 | } | ||
2105 | |||
2106 | pm_runtime_enable(dev); | ||
2107 | |||
2108 | return cd; | ||
2109 | |||
2110 | error_startup: | ||
2111 | cancel_work_sync(&cd->startup_work); | ||
2112 | cyttsp4_stop_wd_timer(cd); | ||
2113 | pm_runtime_disable(dev); | ||
2114 | cyttsp4_free_si_ptrs(cd); | ||
2115 | free_irq(cd->irq, cd); | ||
2116 | error_request_irq: | ||
2117 | if (cd->cpdata->init) | ||
2118 | cd->cpdata->init(cd->cpdata, 0, dev); | ||
2119 | dev_set_drvdata(dev, NULL); | ||
2120 | error_free_xfer: | ||
2121 | kfree(cd->xfer_buf); | ||
2122 | error_free_cd: | ||
2123 | kfree(cd); | ||
2124 | error_alloc_data: | ||
2125 | error_no_pdata: | ||
2126 | dev_err(dev, "%s failed.\n", __func__); | ||
2127 | return ERR_PTR(rc); | ||
2128 | } | ||
2129 | EXPORT_SYMBOL_GPL(cyttsp4_probe); | ||
2130 | |||
2131 | static void cyttsp4_mt_release(struct cyttsp4_mt_data *md) | ||
2132 | { | ||
2133 | input_unregister_device(md->input); | ||
2134 | input_set_drvdata(md->input, NULL); | ||
2135 | } | ||
2136 | |||
2137 | int cyttsp4_remove(struct cyttsp4 *cd) | ||
2138 | { | ||
2139 | struct device *dev = cd->dev; | ||
2140 | |||
2141 | cyttsp4_mt_release(&cd->md); | ||
2142 | |||
2143 | /* | ||
2144 | * Suspend the device before freeing the startup_work and stopping | ||
2145 | * the watchdog since sleep function restarts watchdog on failure | ||
2146 | */ | ||
2147 | pm_runtime_suspend(dev); | ||
2148 | pm_runtime_disable(dev); | ||
2149 | |||
2150 | cancel_work_sync(&cd->startup_work); | ||
2151 | |||
2152 | cyttsp4_stop_wd_timer(cd); | ||
2153 | |||
2154 | free_irq(cd->irq, cd); | ||
2155 | if (cd->cpdata->init) | ||
2156 | cd->cpdata->init(cd->cpdata, 0, dev); | ||
2157 | dev_set_drvdata(dev, NULL); | ||
2158 | cyttsp4_free_si_ptrs(cd); | ||
2159 | kfree(cd); | ||
2160 | return 0; | ||
2161 | } | ||
2162 | EXPORT_SYMBOL_GPL(cyttsp4_remove); | ||
2163 | |||
2164 | MODULE_LICENSE("GPL"); | ||
2165 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen core driver"); | ||
2166 | MODULE_AUTHOR("Cypress"); | ||
diff --git a/drivers/input/touchscreen/cyttsp4_core.h b/drivers/input/touchscreen/cyttsp4_core.h new file mode 100644 index 000000000000..86a254354136 --- /dev/null +++ b/drivers/input/touchscreen/cyttsp4_core.h | |||
@@ -0,0 +1,472 @@ | |||
1 | /* | ||
2 | * cyttsp4_core.h | ||
3 | * Cypress TrueTouch(TM) Standard Product V4 Core driver module. | ||
4 | * For use with Cypress Txx4xx parts. | ||
5 | * Supported parts include: | ||
6 | * TMA4XX | ||
7 | * TMA1036 | ||
8 | * | ||
9 | * Copyright (C) 2012 Cypress Semiconductor | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2, and only version 2, as published by the | ||
14 | * Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef _LINUX_CYTTSP4_CORE_H | ||
26 | #define _LINUX_CYTTSP4_CORE_H | ||
27 | |||
28 | #include <linux/device.h> | ||
29 | #include <linux/err.h> | ||
30 | #include <linux/input.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/limits.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/stringify.h> | ||
35 | #include <linux/types.h> | ||
36 | #include <linux/platform_data/cyttsp4.h> | ||
37 | |||
38 | #define CY_REG_BASE 0x00 | ||
39 | |||
40 | #define CY_POST_CODEL_WDG_RST 0x01 | ||
41 | #define CY_POST_CODEL_CFG_DATA_CRC_FAIL 0x02 | ||
42 | #define CY_POST_CODEL_PANEL_TEST_FAIL 0x04 | ||
43 | |||
44 | #define CY_NUM_BTN_PER_REG 4 | ||
45 | |||
46 | /* touch record system information offset masks and shifts */ | ||
47 | #define CY_BYTE_OFS_MASK 0x1F | ||
48 | #define CY_BOFS_MASK 0xE0 | ||
49 | #define CY_BOFS_SHIFT 5 | ||
50 | |||
51 | #define CY_TMA1036_TCH_REC_SIZE 6 | ||
52 | #define CY_TMA4XX_TCH_REC_SIZE 9 | ||
53 | #define CY_TMA1036_MAX_TCH 0x0E | ||
54 | #define CY_TMA4XX_MAX_TCH 0x1E | ||
55 | |||
56 | #define CY_NORMAL_ORIGIN 0 /* upper, left corner */ | ||
57 | #define CY_INVERT_ORIGIN 1 /* lower, right corner */ | ||
58 | |||
59 | /* helpers */ | ||
60 | #define GET_NUM_TOUCHES(x) ((x) & 0x1F) | ||
61 | #define IS_LARGE_AREA(x) ((x) & 0x20) | ||
62 | #define IS_BAD_PKT(x) ((x) & 0x20) | ||
63 | #define IS_BOOTLOADER(hst_mode, reset_detect) \ | ||
64 | ((hst_mode) & 0x01 || (reset_detect) != 0) | ||
65 | #define IS_TMO(t) ((t) == 0) | ||
66 | |||
67 | |||
68 | enum cyttsp_cmd_bits { | ||
69 | CY_CMD_COMPLETE = (1 << 6), | ||
70 | }; | ||
71 | |||
72 | /* Timeout in ms. */ | ||
73 | #define CY_WATCHDOG_TIMEOUT 1000 | ||
74 | |||
75 | #define CY_MAX_PRINT_SIZE 512 | ||
76 | #ifdef VERBOSE_DEBUG | ||
77 | #define CY_MAX_PRBUF_SIZE PIPE_BUF | ||
78 | #define CY_PR_TRUNCATED " truncated..." | ||
79 | #endif | ||
80 | |||
81 | enum cyttsp4_ic_grpnum { | ||
82 | CY_IC_GRPNUM_RESERVED, | ||
83 | CY_IC_GRPNUM_CMD_REGS, | ||
84 | CY_IC_GRPNUM_TCH_REP, | ||
85 | CY_IC_GRPNUM_DATA_REC, | ||
86 | CY_IC_GRPNUM_TEST_REC, | ||
87 | CY_IC_GRPNUM_PCFG_REC, | ||
88 | CY_IC_GRPNUM_TCH_PARM_VAL, | ||
89 | CY_IC_GRPNUM_TCH_PARM_SIZE, | ||
90 | CY_IC_GRPNUM_RESERVED1, | ||
91 | CY_IC_GRPNUM_RESERVED2, | ||
92 | CY_IC_GRPNUM_OPCFG_REC, | ||
93 | CY_IC_GRPNUM_DDATA_REC, | ||
94 | CY_IC_GRPNUM_MDATA_REC, | ||
95 | CY_IC_GRPNUM_TEST_REGS, | ||
96 | CY_IC_GRPNUM_BTN_KEYS, | ||
97 | CY_IC_GRPNUM_TTHE_REGS, | ||
98 | CY_IC_GRPNUM_NUM | ||
99 | }; | ||
100 | |||
101 | enum cyttsp4_int_state { | ||
102 | CY_INT_NONE, | ||
103 | CY_INT_IGNORE = (1 << 0), | ||
104 | CY_INT_MODE_CHANGE = (1 << 1), | ||
105 | CY_INT_EXEC_CMD = (1 << 2), | ||
106 | CY_INT_AWAKE = (1 << 3), | ||
107 | }; | ||
108 | |||
109 | enum cyttsp4_mode { | ||
110 | CY_MODE_UNKNOWN, | ||
111 | CY_MODE_BOOTLOADER = (1 << 1), | ||
112 | CY_MODE_OPERATIONAL = (1 << 2), | ||
113 | CY_MODE_SYSINFO = (1 << 3), | ||
114 | CY_MODE_CAT = (1 << 4), | ||
115 | CY_MODE_STARTUP = (1 << 5), | ||
116 | CY_MODE_LOADER = (1 << 6), | ||
117 | CY_MODE_CHANGE_MODE = (1 << 7), | ||
118 | CY_MODE_CHANGED = (1 << 8), | ||
119 | CY_MODE_CMD_COMPLETE = (1 << 9), | ||
120 | }; | ||
121 | |||
122 | enum cyttsp4_sleep_state { | ||
123 | SS_SLEEP_OFF, | ||
124 | SS_SLEEP_ON, | ||
125 | SS_SLEEPING, | ||
126 | SS_WAKING, | ||
127 | }; | ||
128 | |||
129 | enum cyttsp4_startup_state { | ||
130 | STARTUP_NONE, | ||
131 | STARTUP_QUEUED, | ||
132 | STARTUP_RUNNING, | ||
133 | }; | ||
134 | |||
135 | #define CY_NUM_REVCTRL 8 | ||
136 | struct cyttsp4_cydata { | ||
137 | u8 ttpidh; | ||
138 | u8 ttpidl; | ||
139 | u8 fw_ver_major; | ||
140 | u8 fw_ver_minor; | ||
141 | u8 revctrl[CY_NUM_REVCTRL]; | ||
142 | u8 blver_major; | ||
143 | u8 blver_minor; | ||
144 | u8 jtag_si_id3; | ||
145 | u8 jtag_si_id2; | ||
146 | u8 jtag_si_id1; | ||
147 | u8 jtag_si_id0; | ||
148 | u8 mfgid_sz; | ||
149 | u8 cyito_idh; | ||
150 | u8 cyito_idl; | ||
151 | u8 cyito_verh; | ||
152 | u8 cyito_verl; | ||
153 | u8 ttsp_ver_major; | ||
154 | u8 ttsp_ver_minor; | ||
155 | u8 device_info; | ||
156 | u8 mfg_id[]; | ||
157 | } __packed; | ||
158 | |||
159 | struct cyttsp4_test { | ||
160 | u8 post_codeh; | ||
161 | u8 post_codel; | ||
162 | } __packed; | ||
163 | |||
164 | struct cyttsp4_pcfg { | ||
165 | u8 electrodes_x; | ||
166 | u8 electrodes_y; | ||
167 | u8 len_xh; | ||
168 | u8 len_xl; | ||
169 | u8 len_yh; | ||
170 | u8 len_yl; | ||
171 | u8 res_xh; | ||
172 | u8 res_xl; | ||
173 | u8 res_yh; | ||
174 | u8 res_yl; | ||
175 | u8 max_zh; | ||
176 | u8 max_zl; | ||
177 | u8 panel_info0; | ||
178 | } __packed; | ||
179 | |||
180 | struct cyttsp4_tch_rec_params { | ||
181 | u8 loc; | ||
182 | u8 size; | ||
183 | } __packed; | ||
184 | |||
185 | #define CY_NUM_TCH_FIELDS 7 | ||
186 | #define CY_NUM_EXT_TCH_FIELDS 3 | ||
187 | struct cyttsp4_opcfg { | ||
188 | u8 cmd_ofs; | ||
189 | u8 rep_ofs; | ||
190 | u8 rep_szh; | ||
191 | u8 rep_szl; | ||
192 | u8 num_btns; | ||
193 | u8 tt_stat_ofs; | ||
194 | u8 obj_cfg0; | ||
195 | u8 max_tchs; | ||
196 | u8 tch_rec_size; | ||
197 | struct cyttsp4_tch_rec_params tch_rec_old[CY_NUM_TCH_FIELDS]; | ||
198 | u8 btn_rec_size; /* btn record size (in bytes) */ | ||
199 | u8 btn_diff_ofs; /* btn data loc, diff counts */ | ||
200 | u8 btn_diff_size; /* btn size of diff counts (in bits) */ | ||
201 | struct cyttsp4_tch_rec_params tch_rec_new[CY_NUM_EXT_TCH_FIELDS]; | ||
202 | } __packed; | ||
203 | |||
204 | struct cyttsp4_sysinfo_ptr { | ||
205 | struct cyttsp4_cydata *cydata; | ||
206 | struct cyttsp4_test *test; | ||
207 | struct cyttsp4_pcfg *pcfg; | ||
208 | struct cyttsp4_opcfg *opcfg; | ||
209 | struct cyttsp4_ddata *ddata; | ||
210 | struct cyttsp4_mdata *mdata; | ||
211 | } __packed; | ||
212 | |||
213 | struct cyttsp4_sysinfo_data { | ||
214 | u8 hst_mode; | ||
215 | u8 reserved; | ||
216 | u8 map_szh; | ||
217 | u8 map_szl; | ||
218 | u8 cydata_ofsh; | ||
219 | u8 cydata_ofsl; | ||
220 | u8 test_ofsh; | ||
221 | u8 test_ofsl; | ||
222 | u8 pcfg_ofsh; | ||
223 | u8 pcfg_ofsl; | ||
224 | u8 opcfg_ofsh; | ||
225 | u8 opcfg_ofsl; | ||
226 | u8 ddata_ofsh; | ||
227 | u8 ddata_ofsl; | ||
228 | u8 mdata_ofsh; | ||
229 | u8 mdata_ofsl; | ||
230 | } __packed; | ||
231 | |||
232 | enum cyttsp4_tch_abs { /* for ordering within the extracted touch data array */ | ||
233 | CY_TCH_X, /* X */ | ||
234 | CY_TCH_Y, /* Y */ | ||
235 | CY_TCH_P, /* P (Z) */ | ||
236 | CY_TCH_T, /* TOUCH ID */ | ||
237 | CY_TCH_E, /* EVENT ID */ | ||
238 | CY_TCH_O, /* OBJECT ID */ | ||
239 | CY_TCH_W, /* SIZE */ | ||
240 | CY_TCH_MAJ, /* TOUCH_MAJOR */ | ||
241 | CY_TCH_MIN, /* TOUCH_MINOR */ | ||
242 | CY_TCH_OR, /* ORIENTATION */ | ||
243 | CY_TCH_NUM_ABS | ||
244 | }; | ||
245 | |||
246 | static const char * const cyttsp4_tch_abs_string[] = { | ||
247 | [CY_TCH_X] = "X", | ||
248 | [CY_TCH_Y] = "Y", | ||
249 | [CY_TCH_P] = "P", | ||
250 | [CY_TCH_T] = "T", | ||
251 | [CY_TCH_E] = "E", | ||
252 | [CY_TCH_O] = "O", | ||
253 | [CY_TCH_W] = "W", | ||
254 | [CY_TCH_MAJ] = "MAJ", | ||
255 | [CY_TCH_MIN] = "MIN", | ||
256 | [CY_TCH_OR] = "OR", | ||
257 | [CY_TCH_NUM_ABS] = "INVALID" | ||
258 | }; | ||
259 | |||
260 | struct cyttsp4_touch { | ||
261 | int abs[CY_TCH_NUM_ABS]; | ||
262 | }; | ||
263 | |||
264 | struct cyttsp4_tch_abs_params { | ||
265 | size_t ofs; /* abs byte offset */ | ||
266 | size_t size; /* size in bits */ | ||
267 | size_t max; /* max value */ | ||
268 | size_t bofs; /* bit offset */ | ||
269 | }; | ||
270 | |||
271 | struct cyttsp4_sysinfo_ofs { | ||
272 | size_t chip_type; | ||
273 | size_t cmd_ofs; | ||
274 | size_t rep_ofs; | ||
275 | size_t rep_sz; | ||
276 | size_t num_btns; | ||
277 | size_t num_btn_regs; /* ceil(num_btns/4) */ | ||
278 | size_t tt_stat_ofs; | ||
279 | size_t tch_rec_size; | ||
280 | size_t obj_cfg0; | ||
281 | size_t max_tchs; | ||
282 | size_t mode_size; | ||
283 | size_t data_size; | ||
284 | size_t map_sz; | ||
285 | size_t max_x; | ||
286 | size_t x_origin; /* left or right corner */ | ||
287 | size_t max_y; | ||
288 | size_t y_origin; /* upper or lower corner */ | ||
289 | size_t max_p; | ||
290 | size_t cydata_ofs; | ||
291 | size_t test_ofs; | ||
292 | size_t pcfg_ofs; | ||
293 | size_t opcfg_ofs; | ||
294 | size_t ddata_ofs; | ||
295 | size_t mdata_ofs; | ||
296 | size_t cydata_size; | ||
297 | size_t test_size; | ||
298 | size_t pcfg_size; | ||
299 | size_t opcfg_size; | ||
300 | size_t ddata_size; | ||
301 | size_t mdata_size; | ||
302 | size_t btn_keys_size; | ||
303 | struct cyttsp4_tch_abs_params tch_abs[CY_TCH_NUM_ABS]; | ||
304 | size_t btn_rec_size; /* btn record size (in bytes) */ | ||
305 | size_t btn_diff_ofs;/* btn data loc ,diff counts, (Op-Mode byte ofs) */ | ||
306 | size_t btn_diff_size;/* btn size of diff counts (in bits) */ | ||
307 | }; | ||
308 | |||
309 | enum cyttsp4_btn_state { | ||
310 | CY_BTN_RELEASED, | ||
311 | CY_BTN_PRESSED, | ||
312 | CY_BTN_NUM_STATE | ||
313 | }; | ||
314 | |||
315 | struct cyttsp4_btn { | ||
316 | bool enabled; | ||
317 | int state; /* CY_BTN_PRESSED, CY_BTN_RELEASED */ | ||
318 | int key_code; | ||
319 | }; | ||
320 | |||
321 | struct cyttsp4_sysinfo { | ||
322 | bool ready; | ||
323 | struct cyttsp4_sysinfo_data si_data; | ||
324 | struct cyttsp4_sysinfo_ptr si_ptrs; | ||
325 | struct cyttsp4_sysinfo_ofs si_ofs; | ||
326 | struct cyttsp4_btn *btn; /* button states */ | ||
327 | u8 *btn_rec_data; /* button diff count data */ | ||
328 | u8 *xy_mode; /* operational mode and status regs */ | ||
329 | u8 *xy_data; /* operational touch regs */ | ||
330 | }; | ||
331 | |||
332 | struct cyttsp4_mt_data { | ||
333 | struct cyttsp4_mt_platform_data *pdata; | ||
334 | struct cyttsp4_sysinfo *si; | ||
335 | struct input_dev *input; | ||
336 | struct mutex report_lock; | ||
337 | bool is_suspended; | ||
338 | char phys[NAME_MAX]; | ||
339 | int num_prv_tch; | ||
340 | }; | ||
341 | |||
342 | struct cyttsp4 { | ||
343 | struct device *dev; | ||
344 | struct mutex system_lock; | ||
345 | struct mutex adap_lock; | ||
346 | enum cyttsp4_mode mode; | ||
347 | enum cyttsp4_sleep_state sleep_state; | ||
348 | enum cyttsp4_startup_state startup_state; | ||
349 | int int_status; | ||
350 | wait_queue_head_t wait_q; | ||
351 | int irq; | ||
352 | struct work_struct startup_work; | ||
353 | struct work_struct watchdog_work; | ||
354 | struct timer_list watchdog_timer; | ||
355 | struct cyttsp4_sysinfo sysinfo; | ||
356 | void *exclusive_dev; | ||
357 | int exclusive_waits; | ||
358 | atomic_t ignore_irq; | ||
359 | bool invalid_touch_app; | ||
360 | struct cyttsp4_mt_data md; | ||
361 | struct cyttsp4_platform_data *pdata; | ||
362 | struct cyttsp4_core_platform_data *cpdata; | ||
363 | const struct cyttsp4_bus_ops *bus_ops; | ||
364 | u8 *xfer_buf; | ||
365 | #ifdef VERBOSE_DEBUG | ||
366 | u8 pr_buf[CY_MAX_PRBUF_SIZE]; | ||
367 | #endif | ||
368 | }; | ||
369 | |||
370 | struct cyttsp4_bus_ops { | ||
371 | u16 bustype; | ||
372 | int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length, | ||
373 | const void *values); | ||
374 | int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length, | ||
375 | void *values); | ||
376 | }; | ||
377 | |||
378 | enum cyttsp4_hst_mode_bits { | ||
379 | CY_HST_TOGGLE = (1 << 7), | ||
380 | CY_HST_MODE_CHANGE = (1 << 3), | ||
381 | CY_HST_MODE = (7 << 4), | ||
382 | CY_HST_OPERATE = (0 << 4), | ||
383 | CY_HST_SYSINFO = (1 << 4), | ||
384 | CY_HST_CAT = (2 << 4), | ||
385 | CY_HST_LOWPOW = (1 << 2), | ||
386 | CY_HST_SLEEP = (1 << 1), | ||
387 | CY_HST_RESET = (1 << 0), | ||
388 | }; | ||
389 | |||
390 | /* abs settings */ | ||
391 | #define CY_IGNORE_VALUE 0xFFFF | ||
392 | |||
393 | /* abs signal capabilities offsets in the frameworks array */ | ||
394 | enum cyttsp4_sig_caps { | ||
395 | CY_SIGNAL_OST, | ||
396 | CY_MIN_OST, | ||
397 | CY_MAX_OST, | ||
398 | CY_FUZZ_OST, | ||
399 | CY_FLAT_OST, | ||
400 | CY_NUM_ABS_SET /* number of signal capability fields */ | ||
401 | }; | ||
402 | |||
403 | /* abs axis signal offsets in the framworks array */ | ||
404 | enum cyttsp4_sig_ost { | ||
405 | CY_ABS_X_OST, | ||
406 | CY_ABS_Y_OST, | ||
407 | CY_ABS_P_OST, | ||
408 | CY_ABS_W_OST, | ||
409 | CY_ABS_ID_OST, | ||
410 | CY_ABS_MAJ_OST, | ||
411 | CY_ABS_MIN_OST, | ||
412 | CY_ABS_OR_OST, | ||
413 | CY_NUM_ABS_OST /* number of abs signals */ | ||
414 | }; | ||
415 | |||
416 | enum cyttsp4_flags { | ||
417 | CY_FLAG_NONE = 0x00, | ||
418 | CY_FLAG_HOVER = 0x04, | ||
419 | CY_FLAG_FLIP = 0x08, | ||
420 | CY_FLAG_INV_X = 0x10, | ||
421 | CY_FLAG_INV_Y = 0x20, | ||
422 | CY_FLAG_VKEYS = 0x40, | ||
423 | }; | ||
424 | |||
425 | enum cyttsp4_object_id { | ||
426 | CY_OBJ_STANDARD_FINGER, | ||
427 | CY_OBJ_LARGE_OBJECT, | ||
428 | CY_OBJ_STYLUS, | ||
429 | CY_OBJ_HOVER, | ||
430 | }; | ||
431 | |||
432 | enum cyttsp4_event_id { | ||
433 | CY_EV_NO_EVENT, | ||
434 | CY_EV_TOUCHDOWN, | ||
435 | CY_EV_MOVE, /* significant displacement (> act dist) */ | ||
436 | CY_EV_LIFTOFF, /* record reports last position */ | ||
437 | }; | ||
438 | |||
439 | /* x-axis resolution of panel in pixels */ | ||
440 | #define CY_PCFG_RESOLUTION_X_MASK 0x7F | ||
441 | |||
442 | /* y-axis resolution of panel in pixels */ | ||
443 | #define CY_PCFG_RESOLUTION_Y_MASK 0x7F | ||
444 | |||
445 | /* x-axis, 0:origin is on left side of panel, 1: right */ | ||
446 | #define CY_PCFG_ORIGIN_X_MASK 0x80 | ||
447 | |||
448 | /* y-axis, 0:origin is on top side of panel, 1: bottom */ | ||
449 | #define CY_PCFG_ORIGIN_Y_MASK 0x80 | ||
450 | |||
451 | static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u8 addr, int size, | ||
452 | void *buf) | ||
453 | { | ||
454 | return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf); | ||
455 | } | ||
456 | |||
457 | static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size, | ||
458 | const void *buf) | ||
459 | { | ||
460 | return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf); | ||
461 | } | ||
462 | |||
463 | extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, | ||
464 | struct device *dev, u16 irq, size_t xfer_buf_size); | ||
465 | extern int cyttsp4_remove(struct cyttsp4 *ts); | ||
466 | int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr, | ||
467 | u8 length, const void *values); | ||
468 | int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr, | ||
469 | u8 length, void *values); | ||
470 | extern const struct dev_pm_ops cyttsp4_pm_ops; | ||
471 | |||
472 | #endif /* _LINUX_CYTTSP4_CORE_H */ | ||
diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c new file mode 100644 index 000000000000..8e2012c79058 --- /dev/null +++ b/drivers/input/touchscreen/cyttsp4_i2c.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * cyttsp_i2c.c | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. | ||
4 | * For use with Cypress Txx4xx parts. | ||
5 | * Supported parts include: | ||
6 | * TMA4XX | ||
7 | * TMA1036 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * Copyright (C) 2013 Cypress Semiconductor | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * version 2, and only version 2, as published by the | ||
16 | * Free Software Foundation. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include "cyttsp4_core.h" | ||
28 | |||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/input.h> | ||
31 | |||
32 | #define CYTTSP4_I2C_DATA_SIZE (3 * 256) | ||
33 | |||
34 | static const struct cyttsp4_bus_ops cyttsp4_i2c_bus_ops = { | ||
35 | .bustype = BUS_I2C, | ||
36 | .write = cyttsp_i2c_write_block_data, | ||
37 | .read = cyttsp_i2c_read_block_data, | ||
38 | }; | ||
39 | |||
40 | static int cyttsp4_i2c_probe(struct i2c_client *client, | ||
41 | const struct i2c_device_id *id) | ||
42 | { | ||
43 | struct cyttsp4 *ts; | ||
44 | |||
45 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
46 | dev_err(&client->dev, "I2C functionality not Supported\n"); | ||
47 | return -EIO; | ||
48 | } | ||
49 | |||
50 | ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq, | ||
51 | CYTTSP4_I2C_DATA_SIZE); | ||
52 | |||
53 | if (IS_ERR(ts)) | ||
54 | return PTR_ERR(ts); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int cyttsp4_i2c_remove(struct i2c_client *client) | ||
60 | { | ||
61 | struct cyttsp4 *ts = i2c_get_clientdata(client); | ||
62 | |||
63 | cyttsp4_remove(ts); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static const struct i2c_device_id cyttsp4_i2c_id[] = { | ||
69 | { CYTTSP4_I2C_NAME, 0 }, | ||
70 | { } | ||
71 | }; | ||
72 | MODULE_DEVICE_TABLE(i2c, cyttsp4_i2c_id); | ||
73 | |||
74 | static struct i2c_driver cyttsp4_i2c_driver = { | ||
75 | .driver = { | ||
76 | .name = CYTTSP4_I2C_NAME, | ||
77 | .owner = THIS_MODULE, | ||
78 | .pm = &cyttsp4_pm_ops, | ||
79 | }, | ||
80 | .probe = cyttsp4_i2c_probe, | ||
81 | .remove = cyttsp4_i2c_remove, | ||
82 | .id_table = cyttsp4_i2c_id, | ||
83 | }; | ||
84 | |||
85 | module_i2c_driver(cyttsp4_i2c_driver); | ||
86 | |||
87 | MODULE_LICENSE("GPL"); | ||
88 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); | ||
89 | MODULE_AUTHOR("Cypress"); | ||
90 | MODULE_ALIAS("i2c:cyttsp4"); | ||
diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c new file mode 100644 index 000000000000..f8f891bead34 --- /dev/null +++ b/drivers/input/touchscreen/cyttsp4_spi.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * Source for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. | ||
4 | * For use with Cypress Txx4xx parts. | ||
5 | * Supported parts include: | ||
6 | * TMA4XX | ||
7 | * TMA1036 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * Copyright (C) 2013 Cypress Semiconductor | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * version 2, and only version 2, as published by the | ||
16 | * Free Software Foundation. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include "cyttsp4_core.h" | ||
28 | |||
29 | #include <linux/delay.h> | ||
30 | #include <linux/input.h> | ||
31 | #include <linux/spi/spi.h> | ||
32 | |||
33 | #define CY_SPI_WR_OP 0x00 /* r/~w */ | ||
34 | #define CY_SPI_RD_OP 0x01 | ||
35 | #define CY_SPI_BITS_PER_WORD 8 | ||
36 | #define CY_SPI_A8_BIT 0x02 | ||
37 | #define CY_SPI_WR_HEADER_BYTES 2 | ||
38 | #define CY_SPI_RD_HEADER_BYTES 1 | ||
39 | #define CY_SPI_CMD_BYTES 2 | ||
40 | #define CY_SPI_SYNC_BYTE 0 | ||
41 | #define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */ | ||
42 | #define CY_SPI_DATA_SIZE (2 * 256) | ||
43 | |||
44 | #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) | ||
45 | |||
46 | static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, | ||
47 | u8 op, u8 reg, u8 *buf, int length) | ||
48 | { | ||
49 | struct spi_device *spi = to_spi_device(dev); | ||
50 | struct spi_message msg; | ||
51 | struct spi_transfer xfer[2]; | ||
52 | u8 *wr_buf = &xfer_buf[0]; | ||
53 | u8 rd_buf[CY_SPI_CMD_BYTES]; | ||
54 | int retval; | ||
55 | int i; | ||
56 | |||
57 | if (length > CY_SPI_DATA_SIZE) { | ||
58 | dev_err(dev, "%s: length %d is too big.\n", | ||
59 | __func__, length); | ||
60 | return -EINVAL; | ||
61 | } | ||
62 | |||
63 | memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); | ||
64 | memset(rd_buf, 0, CY_SPI_CMD_BYTES); | ||
65 | |||
66 | if (reg > 255) | ||
67 | wr_buf[0] = op + CY_SPI_A8_BIT; | ||
68 | else | ||
69 | wr_buf[0] = op; | ||
70 | if (op == CY_SPI_WR_OP) | ||
71 | wr_buf[1] = reg % 256; | ||
72 | if (op == CY_SPI_WR_OP && length > 0) | ||
73 | memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); | ||
74 | |||
75 | memset(xfer, 0, sizeof(xfer)); | ||
76 | spi_message_init(&msg); | ||
77 | |||
78 | /* | ||
79 | We set both TX and RX buffers because Cypress TTSP | ||
80 | requires full duplex operation. | ||
81 | */ | ||
82 | xfer[0].tx_buf = wr_buf; | ||
83 | xfer[0].rx_buf = rd_buf; | ||
84 | switch (op) { | ||
85 | case CY_SPI_WR_OP: | ||
86 | xfer[0].len = length + CY_SPI_CMD_BYTES; | ||
87 | spi_message_add_tail(&xfer[0], &msg); | ||
88 | break; | ||
89 | |||
90 | case CY_SPI_RD_OP: | ||
91 | xfer[0].len = CY_SPI_RD_HEADER_BYTES; | ||
92 | spi_message_add_tail(&xfer[0], &msg); | ||
93 | |||
94 | xfer[1].rx_buf = buf; | ||
95 | xfer[1].len = length; | ||
96 | spi_message_add_tail(&xfer[1], &msg); | ||
97 | break; | ||
98 | |||
99 | default: | ||
100 | dev_err(dev, "%s: bad operation code=%d\n", __func__, op); | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | retval = spi_sync(spi, &msg); | ||
105 | if (retval < 0) { | ||
106 | dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n", | ||
107 | __func__, retval, xfer[1].len, op); | ||
108 | |||
109 | /* | ||
110 | * do not return here since was a bad ACK sequence | ||
111 | * let the following ACK check handle any errors and | ||
112 | * allow silent retries | ||
113 | */ | ||
114 | } | ||
115 | |||
116 | if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) { | ||
117 | dev_dbg(dev, "%s: operation %d failed\n", __func__, op); | ||
118 | |||
119 | for (i = 0; i < CY_SPI_CMD_BYTES; i++) | ||
120 | dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n", | ||
121 | __func__, i, rd_buf[i]); | ||
122 | for (i = 0; i < length; i++) | ||
123 | dev_dbg(dev, "%s: test buf[%d]:0x%02x\n", | ||
124 | __func__, i, buf[i]); | ||
125 | |||
126 | return -EIO; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, | ||
133 | u8 addr, u8 length, void *data) | ||
134 | { | ||
135 | int rc; | ||
136 | |||
137 | rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0); | ||
138 | if (rc) | ||
139 | return rc; | ||
140 | else | ||
141 | return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data, | ||
142 | length); | ||
143 | } | ||
144 | |||
145 | static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, | ||
146 | u8 addr, u8 length, const void *data) | ||
147 | { | ||
148 | return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, | ||
149 | length); | ||
150 | } | ||
151 | |||
152 | static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = { | ||
153 | .bustype = BUS_SPI, | ||
154 | .write = cyttsp_spi_write_block_data, | ||
155 | .read = cyttsp_spi_read_block_data, | ||
156 | }; | ||
157 | |||
158 | static int cyttsp4_spi_probe(struct spi_device *spi) | ||
159 | { | ||
160 | struct cyttsp4 *ts; | ||
161 | int error; | ||
162 | |||
163 | /* Set up SPI*/ | ||
164 | spi->bits_per_word = CY_SPI_BITS_PER_WORD; | ||
165 | spi->mode = SPI_MODE_0; | ||
166 | error = spi_setup(spi); | ||
167 | if (error < 0) { | ||
168 | dev_err(&spi->dev, "%s: SPI setup error %d\n", | ||
169 | __func__, error); | ||
170 | return error; | ||
171 | } | ||
172 | |||
173 | ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, | ||
174 | CY_SPI_DATA_BUF_SIZE); | ||
175 | |||
176 | if (IS_ERR(ts)) | ||
177 | return PTR_ERR(ts); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int cyttsp4_spi_remove(struct spi_device *spi) | ||
183 | { | ||
184 | struct cyttsp4 *ts = spi_get_drvdata(spi); | ||
185 | cyttsp4_remove(ts); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static struct spi_driver cyttsp4_spi_driver = { | ||
191 | .driver = { | ||
192 | .name = CYTTSP4_SPI_NAME, | ||
193 | .owner = THIS_MODULE, | ||
194 | .pm = &cyttsp4_pm_ops, | ||
195 | }, | ||
196 | .probe = cyttsp4_spi_probe, | ||
197 | .remove = cyttsp4_spi_remove, | ||
198 | }; | ||
199 | |||
200 | module_spi_driver(cyttsp4_spi_driver); | ||
201 | |||
202 | MODULE_LICENSE("GPL"); | ||
203 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); | ||
204 | MODULE_AUTHOR("Cypress"); | ||
205 | MODULE_ALIAS("spi:cyttsp4"); | ||
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index ae89d2609ab0..d53e0b72a407 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c | |||
@@ -84,7 +84,8 @@ static int ttsp_read_block_data(struct cyttsp *ts, u8 command, | |||
84 | int tries; | 84 | int tries; |
85 | 85 | ||
86 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { | 86 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { |
87 | error = ts->bus_ops->read(ts, command, length, buf); | 87 | error = ts->bus_ops->read(ts->dev, ts->xfer_buf, command, |
88 | length, buf); | ||
88 | if (!error) | 89 | if (!error) |
89 | return 0; | 90 | return 0; |
90 | 91 | ||
@@ -101,7 +102,8 @@ static int ttsp_write_block_data(struct cyttsp *ts, u8 command, | |||
101 | int tries; | 102 | int tries; |
102 | 103 | ||
103 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { | 104 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { |
104 | error = ts->bus_ops->write(ts, command, length, buf); | 105 | error = ts->bus_ops->write(ts->dev, ts->xfer_buf, command, |
106 | length, buf); | ||
105 | if (!error) | 107 | if (!error) |
106 | return 0; | 108 | return 0; |
107 | 109 | ||
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index f1ebde369f86..0cf564a79fb5 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h | |||
@@ -112,9 +112,10 @@ struct cyttsp; | |||
112 | 112 | ||
113 | struct cyttsp_bus_ops { | 113 | struct cyttsp_bus_ops { |
114 | u16 bustype; | 114 | u16 bustype; |
115 | int (*write)(struct cyttsp *ts, | 115 | int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length, |
116 | u8 addr, u8 length, const void *values); | 116 | const void *values); |
117 | int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values); | 117 | int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length, |
118 | void *values); | ||
118 | }; | 119 | }; |
119 | 120 | ||
120 | enum cyttsp_state { | 121 | enum cyttsp_state { |
@@ -144,6 +145,10 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, | |||
144 | struct device *dev, int irq, size_t xfer_buf_size); | 145 | struct device *dev, int irq, size_t xfer_buf_size); |
145 | void cyttsp_remove(struct cyttsp *ts); | 146 | void cyttsp_remove(struct cyttsp *ts); |
146 | 147 | ||
148 | int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr, | ||
149 | u8 length, const void *values); | ||
150 | int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr, | ||
151 | u8 length, void *values); | ||
147 | extern const struct dev_pm_ops cyttsp_pm_ops; | 152 | extern const struct dev_pm_ops cyttsp_pm_ops; |
148 | 153 | ||
149 | #endif /* __CYTTSP_CORE_H__ */ | 154 | #endif /* __CYTTSP_CORE_H__ */ |
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 4dbdf44b8fc5..63104a86a9bd 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Source for: | 2 | * cyttsp_i2c.c |
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. | 3 | * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. |
4 | * For use with Cypress Txx3xx parts. | 4 | * For use with Cypress Txx3xx parts. |
5 | * Supported parts include: | 5 | * Supported parts include: |
@@ -19,11 +19,7 @@ | |||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | * GNU General Public License for more details. | 20 | * GNU General Public License for more details. |
21 | * | 21 | * |
22 | * You should have received a copy of the GNU General Public License along | 22 | * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> |
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | 23 | * |
28 | */ | 24 | */ |
29 | 25 | ||
@@ -34,47 +30,6 @@ | |||
34 | 30 | ||
35 | #define CY_I2C_DATA_SIZE 128 | 31 | #define CY_I2C_DATA_SIZE 128 |
36 | 32 | ||
37 | static int cyttsp_i2c_read_block_data(struct cyttsp *ts, | ||
38 | u8 addr, u8 length, void *values) | ||
39 | { | ||
40 | struct i2c_client *client = to_i2c_client(ts->dev); | ||
41 | struct i2c_msg msgs[] = { | ||
42 | { | ||
43 | .addr = client->addr, | ||
44 | .flags = 0, | ||
45 | .len = 1, | ||
46 | .buf = &addr, | ||
47 | }, | ||
48 | { | ||
49 | .addr = client->addr, | ||
50 | .flags = I2C_M_RD, | ||
51 | .len = length, | ||
52 | .buf = values, | ||
53 | }, | ||
54 | }; | ||
55 | int retval; | ||
56 | |||
57 | retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
58 | if (retval < 0) | ||
59 | return retval; | ||
60 | |||
61 | return retval != ARRAY_SIZE(msgs) ? -EIO : 0; | ||
62 | } | ||
63 | |||
64 | static int cyttsp_i2c_write_block_data(struct cyttsp *ts, | ||
65 | u8 addr, u8 length, const void *values) | ||
66 | { | ||
67 | struct i2c_client *client = to_i2c_client(ts->dev); | ||
68 | int retval; | ||
69 | |||
70 | ts->xfer_buf[0] = addr; | ||
71 | memcpy(&ts->xfer_buf[1], values, length); | ||
72 | |||
73 | retval = i2c_master_send(client, ts->xfer_buf, length + 1); | ||
74 | |||
75 | return retval < 0 ? retval : 0; | ||
76 | } | ||
77 | |||
78 | static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { | 33 | static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { |
79 | .bustype = BUS_I2C, | 34 | .bustype = BUS_I2C, |
80 | .write = cyttsp_i2c_write_block_data, | 35 | .write = cyttsp_i2c_write_block_data, |
@@ -98,7 +53,6 @@ static int cyttsp_i2c_probe(struct i2c_client *client, | |||
98 | return PTR_ERR(ts); | 53 | return PTR_ERR(ts); |
99 | 54 | ||
100 | i2c_set_clientdata(client, ts); | 55 | i2c_set_clientdata(client, ts); |
101 | |||
102 | return 0; | 56 | return 0; |
103 | } | 57 | } |
104 | 58 | ||
diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c new file mode 100644 index 000000000000..07c553fbcef2 --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_i2c_common.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * cyttsp_i2c_common.c | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. | ||
4 | * For use with Cypress Txx3xx and Txx4xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * TMA4XX | ||
9 | * TMA1036 | ||
10 | * | ||
11 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
12 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * version 2, and only version 2, as published by the | ||
17 | * Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/device.h> | ||
29 | #include <linux/export.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/types.h> | ||
33 | |||
34 | int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, | ||
35 | u8 addr, u8 length, void *values) | ||
36 | { | ||
37 | struct i2c_client *client = to_i2c_client(dev); | ||
38 | struct i2c_msg msgs[] = { | ||
39 | { | ||
40 | .addr = client->addr, | ||
41 | .flags = 0, | ||
42 | .len = 1, | ||
43 | .buf = &addr, | ||
44 | }, | ||
45 | { | ||
46 | .addr = client->addr, | ||
47 | .flags = I2C_M_RD, | ||
48 | .len = length, | ||
49 | .buf = values, | ||
50 | }, | ||
51 | }; | ||
52 | int retval; | ||
53 | |||
54 | retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
55 | if (retval < 0) | ||
56 | return retval; | ||
57 | |||
58 | return retval != ARRAY_SIZE(msgs) ? -EIO : 0; | ||
59 | } | ||
60 | EXPORT_SYMBOL_GPL(cyttsp_i2c_read_block_data); | ||
61 | |||
62 | int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, | ||
63 | u8 addr, u8 length, const void *values) | ||
64 | { | ||
65 | struct i2c_client *client = to_i2c_client(dev); | ||
66 | int retval; | ||
67 | |||
68 | xfer_buf[0] = addr; | ||
69 | memcpy(&xfer_buf[1], values, length); | ||
70 | |||
71 | retval = i2c_master_send(client, xfer_buf, length + 1); | ||
72 | |||
73 | return retval < 0 ? retval : 0; | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data); | ||
76 | |||
77 | |||
78 | MODULE_LICENSE("GPL"); | ||
79 | MODULE_AUTHOR("Cypress"); | ||
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c index 861b7f77605b..1df625337b84 100644 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ b/drivers/input/touchscreen/cyttsp_spi.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * | 8 | * |
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | 9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. |
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | 10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> |
11 | * Copyright (C) 2013 Cypress Semiconductor | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
@@ -19,11 +20,7 @@ | |||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | * GNU General Public License for more details. | 21 | * GNU General Public License for more details. |
21 | * | 22 | * |
22 | * You should have received a copy of the GNU General Public License along | 23 | * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> |
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | 24 | * |
28 | */ | 25 | */ |
29 | 26 | ||
@@ -43,19 +40,19 @@ | |||
43 | #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) | 40 | #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) |
44 | #define CY_SPI_BITS_PER_WORD 8 | 41 | #define CY_SPI_BITS_PER_WORD 8 |
45 | 42 | ||
46 | static int cyttsp_spi_xfer(struct cyttsp *ts, | 43 | static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, |
47 | u8 op, u8 reg, u8 *buf, int length) | 44 | u8 op, u8 reg, u8 *buf, int length) |
48 | { | 45 | { |
49 | struct spi_device *spi = to_spi_device(ts->dev); | 46 | struct spi_device *spi = to_spi_device(dev); |
50 | struct spi_message msg; | 47 | struct spi_message msg; |
51 | struct spi_transfer xfer[2]; | 48 | struct spi_transfer xfer[2]; |
52 | u8 *wr_buf = &ts->xfer_buf[0]; | 49 | u8 *wr_buf = &xfer_buf[0]; |
53 | u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE]; | 50 | u8 *rd_buf = &xfer_buf[CY_SPI_DATA_BUF_SIZE]; |
54 | int retval; | 51 | int retval; |
55 | int i; | 52 | int i; |
56 | 53 | ||
57 | if (length > CY_SPI_DATA_SIZE) { | 54 | if (length > CY_SPI_DATA_SIZE) { |
58 | dev_err(ts->dev, "%s: length %d is too big.\n", | 55 | dev_err(dev, "%s: length %d is too big.\n", |
59 | __func__, length); | 56 | __func__, length); |
60 | return -EINVAL; | 57 | return -EINVAL; |
61 | } | 58 | } |
@@ -95,13 +92,13 @@ static int cyttsp_spi_xfer(struct cyttsp *ts, | |||
95 | break; | 92 | break; |
96 | 93 | ||
97 | default: | 94 | default: |
98 | dev_err(ts->dev, "%s: bad operation code=%d\n", __func__, op); | 95 | dev_err(dev, "%s: bad operation code=%d\n", __func__, op); |
99 | return -EINVAL; | 96 | return -EINVAL; |
100 | } | 97 | } |
101 | 98 | ||
102 | retval = spi_sync(spi, &msg); | 99 | retval = spi_sync(spi, &msg); |
103 | if (retval < 0) { | 100 | if (retval < 0) { |
104 | dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n", | 101 | dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n", |
105 | __func__, retval, xfer[1].len, op); | 102 | __func__, retval, xfer[1].len, op); |
106 | 103 | ||
107 | /* | 104 | /* |
@@ -113,14 +110,13 @@ static int cyttsp_spi_xfer(struct cyttsp *ts, | |||
113 | 110 | ||
114 | if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 || | 111 | if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 || |
115 | rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) { | 112 | rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) { |
116 | 113 | dev_dbg(dev, "%s: operation %d failed\n", __func__, op); | |
117 | dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op); | ||
118 | 114 | ||
119 | for (i = 0; i < CY_SPI_CMD_BYTES; i++) | 115 | for (i = 0; i < CY_SPI_CMD_BYTES; i++) |
120 | dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n", | 116 | dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n", |
121 | __func__, i, rd_buf[i]); | 117 | __func__, i, rd_buf[i]); |
122 | for (i = 0; i < length; i++) | 118 | for (i = 0; i < length; i++) |
123 | dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n", | 119 | dev_dbg(dev, "%s: test buf[%d]:0x%02x\n", |
124 | __func__, i, buf[i]); | 120 | __func__, i, buf[i]); |
125 | 121 | ||
126 | return -EIO; | 122 | return -EIO; |
@@ -129,16 +125,18 @@ static int cyttsp_spi_xfer(struct cyttsp *ts, | |||
129 | return 0; | 125 | return 0; |
130 | } | 126 | } |
131 | 127 | ||
132 | static int cyttsp_spi_read_block_data(struct cyttsp *ts, | 128 | static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, |
133 | u8 addr, u8 length, void *data) | 129 | u8 addr, u8 length, void *data) |
134 | { | 130 | { |
135 | return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length); | 131 | return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data, |
132 | length); | ||
136 | } | 133 | } |
137 | 134 | ||
138 | static int cyttsp_spi_write_block_data(struct cyttsp *ts, | 135 | static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, |
139 | u8 addr, u8 length, const void *data) | 136 | u8 addr, u8 length, const void *data) |
140 | { | 137 | { |
141 | return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, addr, (void *)data, length); | 138 | return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, |
139 | length); | ||
142 | } | 140 | } |
143 | 141 | ||
144 | static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = { | 142 | static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = { |
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c index 8f561e22bdd4..ab64d58c3ac0 100644 --- a/drivers/input/touchscreen/da9052_tsi.c +++ b/drivers/input/touchscreen/da9052_tsi.c | |||
@@ -329,8 +329,6 @@ static int da9052_ts_remove(struct platform_device *pdev) | |||
329 | input_unregister_device(tsi->dev); | 329 | input_unregister_device(tsi->dev); |
330 | kfree(tsi); | 330 | kfree(tsi); |
331 | 331 | ||
332 | platform_set_drvdata(pdev, NULL); | ||
333 | |||
334 | return 0; | 332 | return 0; |
335 | } | 333 | } |
336 | 334 | ||
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index 39f3df8670c3..ef5fcb0945e9 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c | |||
@@ -166,24 +166,22 @@ static int egalax_firmware_version(struct i2c_client *client) | |||
166 | } | 166 | } |
167 | 167 | ||
168 | static int egalax_ts_probe(struct i2c_client *client, | 168 | static int egalax_ts_probe(struct i2c_client *client, |
169 | const struct i2c_device_id *id) | 169 | const struct i2c_device_id *id) |
170 | { | 170 | { |
171 | struct egalax_ts *ts; | 171 | struct egalax_ts *ts; |
172 | struct input_dev *input_dev; | 172 | struct input_dev *input_dev; |
173 | int ret; | ||
174 | int error; | 173 | int error; |
175 | 174 | ||
176 | ts = kzalloc(sizeof(struct egalax_ts), GFP_KERNEL); | 175 | ts = devm_kzalloc(&client->dev, sizeof(struct egalax_ts), GFP_KERNEL); |
177 | if (!ts) { | 176 | if (!ts) { |
178 | dev_err(&client->dev, "Failed to allocate memory\n"); | 177 | dev_err(&client->dev, "Failed to allocate memory\n"); |
179 | return -ENOMEM; | 178 | return -ENOMEM; |
180 | } | 179 | } |
181 | 180 | ||
182 | input_dev = input_allocate_device(); | 181 | input_dev = devm_input_allocate_device(&client->dev); |
183 | if (!input_dev) { | 182 | if (!input_dev) { |
184 | dev_err(&client->dev, "Failed to allocate memory\n"); | 183 | dev_err(&client->dev, "Failed to allocate memory\n"); |
185 | error = -ENOMEM; | 184 | return -ENOMEM; |
186 | goto err_free_ts; | ||
187 | } | 185 | } |
188 | 186 | ||
189 | ts->client = client; | 187 | ts->client = client; |
@@ -193,19 +191,17 @@ static int egalax_ts_probe(struct i2c_client *client, | |||
193 | error = egalax_wake_up_device(client); | 191 | error = egalax_wake_up_device(client); |
194 | if (error) { | 192 | if (error) { |
195 | dev_err(&client->dev, "Failed to wake up the controller\n"); | 193 | dev_err(&client->dev, "Failed to wake up the controller\n"); |
196 | goto err_free_dev; | 194 | return error; |
197 | } | 195 | } |
198 | 196 | ||
199 | ret = egalax_firmware_version(client); | 197 | error = egalax_firmware_version(client); |
200 | if (ret < 0) { | 198 | if (error < 0) { |
201 | dev_err(&client->dev, "Failed to read firmware version\n"); | 199 | dev_err(&client->dev, "Failed to read firmware version\n"); |
202 | error = -EIO; | 200 | return error; |
203 | goto err_free_dev; | ||
204 | } | 201 | } |
205 | 202 | ||
206 | input_dev->name = "EETI eGalax Touch Screen"; | 203 | input_dev->name = "EETI eGalax Touch Screen"; |
207 | input_dev->id.bustype = BUS_I2C; | 204 | input_dev->id.bustype = BUS_I2C; |
208 | input_dev->dev.parent = &client->dev; | ||
209 | 205 | ||
210 | __set_bit(EV_ABS, input_dev->evbit); | 206 | __set_bit(EV_ABS, input_dev->evbit); |
211 | __set_bit(EV_KEY, input_dev->evbit); | 207 | __set_bit(EV_KEY, input_dev->evbit); |
@@ -221,41 +217,21 @@ static int egalax_ts_probe(struct i2c_client *client, | |||
221 | 217 | ||
222 | input_set_drvdata(input_dev, ts); | 218 | input_set_drvdata(input_dev, ts); |
223 | 219 | ||
224 | error = request_threaded_irq(client->irq, NULL, egalax_ts_interrupt, | 220 | error = devm_request_threaded_irq(&client->dev, client->irq, NULL, |
225 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 221 | egalax_ts_interrupt, |
226 | "egalax_ts", ts); | 222 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
223 | "egalax_ts", ts); | ||
227 | if (error < 0) { | 224 | if (error < 0) { |
228 | dev_err(&client->dev, "Failed to register interrupt\n"); | 225 | dev_err(&client->dev, "Failed to register interrupt\n"); |
229 | goto err_free_dev; | 226 | return error; |
230 | } | 227 | } |
231 | 228 | ||
232 | error = input_register_device(ts->input_dev); | 229 | error = input_register_device(ts->input_dev); |
233 | if (error) | 230 | if (error) |
234 | goto err_free_irq; | 231 | return error; |
235 | 232 | ||
236 | i2c_set_clientdata(client, ts); | 233 | i2c_set_clientdata(client, ts); |
237 | return 0; | 234 | return 0; |
238 | |||
239 | err_free_irq: | ||
240 | free_irq(client->irq, ts); | ||
241 | err_free_dev: | ||
242 | input_free_device(input_dev); | ||
243 | err_free_ts: | ||
244 | kfree(ts); | ||
245 | |||
246 | return error; | ||
247 | } | ||
248 | |||
249 | static int egalax_ts_remove(struct i2c_client *client) | ||
250 | { | ||
251 | struct egalax_ts *ts = i2c_get_clientdata(client); | ||
252 | |||
253 | free_irq(client->irq, ts); | ||
254 | |||
255 | input_unregister_device(ts->input_dev); | ||
256 | kfree(ts); | ||
257 | |||
258 | return 0; | ||
259 | } | 235 | } |
260 | 236 | ||
261 | static const struct i2c_device_id egalax_ts_id[] = { | 237 | static const struct i2c_device_id egalax_ts_id[] = { |
@@ -301,7 +277,6 @@ static struct i2c_driver egalax_ts_driver = { | |||
301 | }, | 277 | }, |
302 | .id_table = egalax_ts_id, | 278 | .id_table = egalax_ts_id, |
303 | .probe = egalax_ts_probe, | 279 | .probe = egalax_ts_probe, |
304 | .remove = egalax_ts_remove, | ||
305 | }; | 280 | }; |
306 | 281 | ||
307 | module_i2c_driver(egalax_ts_driver); | 282 | module_i2c_driver(egalax_ts_driver); |
diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c index 465db5dba8b4..e30d837dae2f 100644 --- a/drivers/input/touchscreen/intel-mid-touch.c +++ b/drivers/input/touchscreen/intel-mid-touch.c | |||
@@ -651,8 +651,6 @@ static int mrstouch_remove(struct platform_device *pdev) | |||
651 | input_unregister_device(tsdev->input); | 651 | input_unregister_device(tsdev->input); |
652 | kfree(tsdev); | 652 | kfree(tsdev); |
653 | 653 | ||
654 | platform_set_drvdata(pdev, NULL); | ||
655 | |||
656 | return 0; | 654 | return 0; |
657 | } | 655 | } |
658 | 656 | ||
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index 282d7c7ad2fc..e463a79ffecc 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c | |||
@@ -145,7 +145,6 @@ static int jornada720_ts_probe(struct platform_device *pdev) | |||
145 | fail2: | 145 | fail2: |
146 | free_irq(IRQ_GPIO9, pdev); | 146 | free_irq(IRQ_GPIO9, pdev); |
147 | fail1: | 147 | fail1: |
148 | platform_set_drvdata(pdev, NULL); | ||
149 | input_free_device(input_dev); | 148 | input_free_device(input_dev); |
150 | kfree(jornada_ts); | 149 | kfree(jornada_ts); |
151 | return error; | 150 | return error; |
@@ -156,7 +155,6 @@ static int jornada720_ts_remove(struct platform_device *pdev) | |||
156 | struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); | 155 | struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); |
157 | 156 | ||
158 | free_irq(IRQ_GPIO9, pdev); | 157 | free_irq(IRQ_GPIO9, pdev); |
159 | platform_set_drvdata(pdev, NULL); | ||
160 | input_unregister_device(jornada_ts->dev); | 158 | input_unregister_device(jornada_ts->dev); |
161 | kfree(jornada_ts); | 159 | kfree(jornada_ts); |
162 | 160 | ||
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index 89308fe38752..d6f099c47f84 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c | |||
@@ -233,8 +233,6 @@ static int mc13783_ts_remove(struct platform_device *pdev) | |||
233 | { | 233 | { |
234 | struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); | 234 | struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); |
235 | 235 | ||
236 | platform_set_drvdata(pdev, NULL); | ||
237 | |||
238 | destroy_workqueue(priv->workq); | 236 | destroy_workqueue(priv->workq); |
239 | input_unregister_device(priv->idev); | 237 | input_unregister_device(priv->idev); |
240 | kfree(priv); | 238 | kfree(priv); |
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 51e7b87827a4..50fb1293874e 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c | |||
@@ -336,7 +336,6 @@ static int titsc_remove(struct platform_device *pdev) | |||
336 | 336 | ||
337 | input_unregister_device(ts_dev->input); | 337 | input_unregister_device(ts_dev->input); |
338 | 338 | ||
339 | platform_set_drvdata(pdev, NULL); | ||
340 | kfree(ts_dev); | 339 | kfree(ts_dev); |
341 | return 0; | 340 | return 0; |
342 | } | 341 | } |
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c index acfb87607b87..c47827a26e3c 100644 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ b/drivers/input/touchscreen/tnetv107x-ts.c | |||
@@ -351,7 +351,6 @@ error_clk: | |||
351 | error_map: | 351 | error_map: |
352 | release_mem_region(ts->res->start, resource_size(ts->res)); | 352 | release_mem_region(ts->res->start, resource_size(ts->res)); |
353 | error_res: | 353 | error_res: |
354 | platform_set_drvdata(pdev, NULL); | ||
355 | kfree(ts); | 354 | kfree(ts); |
356 | 355 | ||
357 | return error; | 356 | return error; |
@@ -366,7 +365,6 @@ static int tsc_remove(struct platform_device *pdev) | |||
366 | clk_put(ts->clk); | 365 | clk_put(ts->clk); |
367 | iounmap(ts->regs); | 366 | iounmap(ts->regs); |
368 | release_mem_region(ts->res->start, resource_size(ts->res)); | 367 | release_mem_region(ts->res->start, resource_size(ts->res)); |
369 | platform_set_drvdata(pdev, NULL); | ||
370 | kfree(ts); | 368 | kfree(ts); |
371 | 369 | ||
372 | return 0; | 370 | return 0; |
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index 820a066c3b8a..94cde2cb1491 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/workqueue.h> | 17 | #include <linux/workqueue.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/input.h> | 19 | #include <linux/input.h> |
20 | #include <linux/input-polldev.h> | ||
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
21 | #include <linux/mfd/tps6507x.h> | 22 | #include <linux/mfd/tps6507x.h> |
22 | #include <linux/input/tps6507x-ts.h> | 23 | #include <linux/input/tps6507x-ts.h> |
@@ -38,20 +39,13 @@ struct ts_event { | |||
38 | }; | 39 | }; |
39 | 40 | ||
40 | struct tps6507x_ts { | 41 | struct tps6507x_ts { |
41 | struct input_dev *input_dev; | ||
42 | struct device *dev; | 42 | struct device *dev; |
43 | struct input_polled_dev *poll_dev; | ||
44 | struct tps6507x_dev *mfd; | ||
43 | char phys[32]; | 45 | char phys[32]; |
44 | struct delayed_work work; | ||
45 | unsigned polling; /* polling is active */ | ||
46 | struct ts_event tc; | 46 | struct ts_event tc; |
47 | struct tps6507x_dev *mfd; | ||
48 | u16 model; | ||
49 | unsigned pendown; | ||
50 | int irq; | ||
51 | void (*clear_penirq)(void); | ||
52 | unsigned long poll_period; /* ms */ | ||
53 | u16 min_pressure; | 47 | u16 min_pressure; |
54 | int vref; /* non-zero to leave vref on */ | 48 | bool pendown; |
55 | }; | 49 | }; |
56 | 50 | ||
57 | static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data) | 51 | static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data) |
@@ -161,18 +155,15 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc) | |||
161 | return ret; | 155 | return ret; |
162 | } | 156 | } |
163 | 157 | ||
164 | static void tps6507x_ts_handler(struct work_struct *work) | 158 | static void tps6507x_ts_poll(struct input_polled_dev *poll_dev) |
165 | { | 159 | { |
166 | struct tps6507x_ts *tsc = container_of(work, | 160 | struct tps6507x_ts *tsc = poll_dev->private; |
167 | struct tps6507x_ts, work.work); | 161 | struct input_dev *input_dev = poll_dev->input; |
168 | struct input_dev *input_dev = tsc->input_dev; | 162 | bool pendown; |
169 | int pendown; | ||
170 | int schd; | ||
171 | int poll = 0; | ||
172 | s32 ret; | 163 | s32 ret; |
173 | 164 | ||
174 | ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE, | 165 | ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE, |
175 | &tsc->tc.pressure); | 166 | &tsc->tc.pressure); |
176 | if (ret) | 167 | if (ret) |
177 | goto done; | 168 | goto done; |
178 | 169 | ||
@@ -183,7 +174,7 @@ static void tps6507x_ts_handler(struct work_struct *work) | |||
183 | input_report_key(input_dev, BTN_TOUCH, 0); | 174 | input_report_key(input_dev, BTN_TOUCH, 0); |
184 | input_report_abs(input_dev, ABS_PRESSURE, 0); | 175 | input_report_abs(input_dev, ABS_PRESSURE, 0); |
185 | input_sync(input_dev); | 176 | input_sync(input_dev); |
186 | tsc->pendown = 0; | 177 | tsc->pendown = false; |
187 | } | 178 | } |
188 | 179 | ||
189 | if (pendown) { | 180 | if (pendown) { |
@@ -208,76 +199,69 @@ static void tps6507x_ts_handler(struct work_struct *work) | |||
208 | input_report_abs(input_dev, ABS_Y, tsc->tc.y); | 199 | input_report_abs(input_dev, ABS_Y, tsc->tc.y); |
209 | input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure); | 200 | input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure); |
210 | input_sync(input_dev); | 201 | input_sync(input_dev); |
211 | tsc->pendown = 1; | 202 | tsc->pendown = true; |
212 | poll = 1; | ||
213 | } | 203 | } |
214 | 204 | ||
215 | done: | 205 | done: |
216 | /* always poll if not using interrupts */ | 206 | tps6507x_adc_standby(tsc); |
217 | poll = 1; | ||
218 | |||
219 | if (poll) { | ||
220 | schd = schedule_delayed_work(&tsc->work, | ||
221 | msecs_to_jiffies(tsc->poll_period)); | ||
222 | if (schd) | ||
223 | tsc->polling = 1; | ||
224 | else { | ||
225 | tsc->polling = 0; | ||
226 | dev_err(tsc->dev, "re-schedule failed"); | ||
227 | } | ||
228 | } else | ||
229 | tsc->polling = 0; | ||
230 | |||
231 | ret = tps6507x_adc_standby(tsc); | ||
232 | } | 207 | } |
233 | 208 | ||
234 | static int tps6507x_ts_probe(struct platform_device *pdev) | 209 | static int tps6507x_ts_probe(struct platform_device *pdev) |
235 | { | 210 | { |
236 | int error; | ||
237 | struct tps6507x_ts *tsc; | ||
238 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); | 211 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); |
239 | struct touchscreen_init_data *init_data; | 212 | const struct tps6507x_board *tps_board; |
213 | const struct touchscreen_init_data *init_data; | ||
214 | struct tps6507x_ts *tsc; | ||
215 | struct input_polled_dev *poll_dev; | ||
240 | struct input_dev *input_dev; | 216 | struct input_dev *input_dev; |
241 | struct tps6507x_board *tps_board; | 217 | int error; |
242 | int schd; | ||
243 | 218 | ||
244 | /** | 219 | /* |
245 | * tps_board points to pmic related constants | 220 | * tps_board points to pmic related constants |
246 | * coming from the board-evm file. | 221 | * coming from the board-evm file. |
247 | */ | 222 | */ |
248 | 223 | tps_board = dev_get_platdata(tps6507x_dev->dev); | |
249 | tps_board = (struct tps6507x_board *)tps6507x_dev->dev->platform_data; | ||
250 | |||
251 | if (!tps_board) { | 224 | if (!tps_board) { |
252 | dev_err(tps6507x_dev->dev, | 225 | dev_err(tps6507x_dev->dev, |
253 | "Could not find tps6507x platform data\n"); | 226 | "Could not find tps6507x platform data\n"); |
254 | return -EIO; | 227 | return -ENODEV; |
255 | } | 228 | } |
256 | 229 | ||
257 | /** | 230 | /* |
258 | * init_data points to array of regulator_init structures | 231 | * init_data points to array of regulator_init structures |
259 | * coming from the board-evm file. | 232 | * coming from the board-evm file. |
260 | */ | 233 | */ |
261 | |||
262 | init_data = tps_board->tps6507x_ts_init_data; | 234 | init_data = tps_board->tps6507x_ts_init_data; |
263 | 235 | ||
264 | tsc = kzalloc(sizeof(struct tps6507x_ts), GFP_KERNEL); | 236 | tsc = kzalloc(sizeof(struct tps6507x_ts), GFP_KERNEL); |
265 | if (!tsc) { | 237 | if (!tsc) { |
266 | dev_err(tps6507x_dev->dev, "failed to allocate driver data\n"); | 238 | dev_err(tps6507x_dev->dev, "failed to allocate driver data\n"); |
267 | error = -ENOMEM; | 239 | return -ENOMEM; |
268 | goto err0; | ||
269 | } | 240 | } |
270 | 241 | ||
271 | tps6507x_dev->ts = tsc; | ||
272 | tsc->mfd = tps6507x_dev; | 242 | tsc->mfd = tps6507x_dev; |
273 | tsc->dev = tps6507x_dev->dev; | 243 | tsc->dev = tps6507x_dev->dev; |
274 | input_dev = input_allocate_device(); | 244 | tsc->min_pressure = init_data ? |
275 | if (!input_dev) { | 245 | init_data->min_pressure : TPS_DEFAULT_MIN_PRESSURE; |
276 | dev_err(tsc->dev, "Failed to allocate input device.\n"); | 246 | |
247 | snprintf(tsc->phys, sizeof(tsc->phys), | ||
248 | "%s/input0", dev_name(tsc->dev)); | ||
249 | |||
250 | poll_dev = input_allocate_polled_device(); | ||
251 | if (!poll_dev) { | ||
252 | dev_err(tsc->dev, "Failed to allocate polled input device.\n"); | ||
277 | error = -ENOMEM; | 253 | error = -ENOMEM; |
278 | goto err1; | 254 | goto err_free_mem; |
279 | } | 255 | } |
280 | 256 | ||
257 | tsc->poll_dev = poll_dev; | ||
258 | |||
259 | poll_dev->private = tsc; | ||
260 | poll_dev->poll = tps6507x_ts_poll; | ||
261 | poll_dev->poll_interval = init_data ? | ||
262 | init_data->poll_period : TSC_DEFAULT_POLL_PERIOD; | ||
263 | |||
264 | input_dev = poll_dev->input; | ||
281 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 265 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
282 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 266 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
283 | 267 | ||
@@ -286,76 +270,42 @@ static int tps6507x_ts_probe(struct platform_device *pdev) | |||
286 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0); | 270 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0); |
287 | 271 | ||
288 | input_dev->name = "TPS6507x Touchscreen"; | 272 | input_dev->name = "TPS6507x Touchscreen"; |
289 | input_dev->id.bustype = BUS_I2C; | ||
290 | input_dev->dev.parent = tsc->dev; | ||
291 | |||
292 | snprintf(tsc->phys, sizeof(tsc->phys), | ||
293 | "%s/input0", dev_name(tsc->dev)); | ||
294 | input_dev->phys = tsc->phys; | 273 | input_dev->phys = tsc->phys; |
295 | 274 | input_dev->dev.parent = tsc->dev; | |
296 | dev_dbg(tsc->dev, "device: %s\n", input_dev->phys); | 275 | input_dev->id.bustype = BUS_I2C; |
297 | |||
298 | input_set_drvdata(input_dev, tsc); | ||
299 | |||
300 | tsc->input_dev = input_dev; | ||
301 | |||
302 | INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler); | ||
303 | |||
304 | if (init_data) { | 276 | if (init_data) { |
305 | tsc->poll_period = init_data->poll_period; | ||
306 | tsc->vref = init_data->vref; | ||
307 | tsc->min_pressure = init_data->min_pressure; | ||
308 | input_dev->id.vendor = init_data->vendor; | 277 | input_dev->id.vendor = init_data->vendor; |
309 | input_dev->id.product = init_data->product; | 278 | input_dev->id.product = init_data->product; |
310 | input_dev->id.version = init_data->version; | 279 | input_dev->id.version = init_data->version; |
311 | } else { | ||
312 | tsc->poll_period = TSC_DEFAULT_POLL_PERIOD; | ||
313 | tsc->min_pressure = TPS_DEFAULT_MIN_PRESSURE; | ||
314 | } | 280 | } |
315 | 281 | ||
316 | error = tps6507x_adc_standby(tsc); | 282 | error = tps6507x_adc_standby(tsc); |
317 | if (error) | 283 | if (error) |
318 | goto err2; | 284 | goto err_free_polled_dev; |
319 | 285 | ||
320 | error = input_register_device(input_dev); | 286 | error = input_register_polled_device(poll_dev); |
321 | if (error) | 287 | if (error) |
322 | goto err2; | 288 | goto err_free_polled_dev; |
323 | 289 | ||
324 | schd = schedule_delayed_work(&tsc->work, | 290 | platform_set_drvdata(pdev, tsc); |
325 | msecs_to_jiffies(tsc->poll_period)); | ||
326 | |||
327 | if (schd) | ||
328 | tsc->polling = 1; | ||
329 | else { | ||
330 | tsc->polling = 0; | ||
331 | dev_err(tsc->dev, "schedule failed"); | ||
332 | goto err2; | ||
333 | } | ||
334 | platform_set_drvdata(pdev, tps6507x_dev); | ||
335 | 291 | ||
336 | return 0; | 292 | return 0; |
337 | 293 | ||
338 | err2: | 294 | err_free_polled_dev: |
339 | cancel_delayed_work_sync(&tsc->work); | 295 | input_free_polled_device(poll_dev); |
340 | input_free_device(input_dev); | 296 | err_free_mem: |
341 | err1: | ||
342 | kfree(tsc); | 297 | kfree(tsc); |
343 | tps6507x_dev->ts = NULL; | ||
344 | err0: | ||
345 | return error; | 298 | return error; |
346 | } | 299 | } |
347 | 300 | ||
348 | static int tps6507x_ts_remove(struct platform_device *pdev) | 301 | static int tps6507x_ts_remove(struct platform_device *pdev) |
349 | { | 302 | { |
350 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); | 303 | struct tps6507x_ts *tsc = platform_get_drvdata(pdev); |
351 | struct tps6507x_ts *tsc = tps6507x_dev->ts; | 304 | struct input_polled_dev *poll_dev = tsc->poll_dev; |
352 | struct input_dev *input_dev = tsc->input_dev; | ||
353 | |||
354 | cancel_delayed_work_sync(&tsc->work); | ||
355 | 305 | ||
356 | input_unregister_device(input_dev); | 306 | input_unregister_polled_device(poll_dev); |
307 | input_free_polled_device(poll_dev); | ||
357 | 308 | ||
358 | tps6507x_dev->ts = NULL; | ||
359 | kfree(tsc); | 309 | kfree(tsc); |
360 | 310 | ||
361 | return 0; | 311 | return 0; |
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index d2ef8f05c66e..003d0c3b5d08 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
@@ -318,8 +318,6 @@ static int w90x900ts_remove(struct platform_device *pdev) | |||
318 | input_unregister_device(w90p910_ts->input); | 318 | input_unregister_device(w90p910_ts->input); |
319 | kfree(w90p910_ts); | 319 | kfree(w90p910_ts); |
320 | 320 | ||
321 | platform_set_drvdata(pdev, NULL); | ||
322 | |||
323 | return 0; | 321 | return 0; |
324 | } | 322 | } |
325 | 323 | ||
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index bf0d07620bac..7ccaa1b12b05 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Wacom Penabled Driver for I2C | 2 | * Wacom Penabled Driver for I2C |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Tatsunosuke Tobita, Wacom. | 4 | * Copyright (c) 2011 - 2013 Tatsunosuke Tobita, Wacom. |
5 | * <tobita.tatsunosuke@wacom.co.jp> | 5 | * <tobita.tatsunosuke@wacom.co.jp> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it | 7 | * This program is free software; you can redistribute it |
@@ -27,7 +27,6 @@ | |||
27 | #define WACOM_CMD_THROW0 0x05 | 27 | #define WACOM_CMD_THROW0 0x05 |
28 | #define WACOM_CMD_THROW1 0x00 | 28 | #define WACOM_CMD_THROW1 0x00 |
29 | #define WACOM_QUERY_SIZE 19 | 29 | #define WACOM_QUERY_SIZE 19 |
30 | #define WACOM_RETRY_CNT 100 | ||
31 | 30 | ||
32 | struct wacom_features { | 31 | struct wacom_features { |
33 | int x_max; | 32 | int x_max; |
@@ -40,6 +39,8 @@ struct wacom_i2c { | |||
40 | struct i2c_client *client; | 39 | struct i2c_client *client; |
41 | struct input_dev *input; | 40 | struct input_dev *input; |
42 | u8 data[WACOM_QUERY_SIZE]; | 41 | u8 data[WACOM_QUERY_SIZE]; |
42 | bool prox; | ||
43 | int tool; | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | static int wacom_query_device(struct i2c_client *client, | 46 | static int wacom_query_device(struct i2c_client *client, |
@@ -112,9 +113,14 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) | |||
112 | y = le16_to_cpup((__le16 *)&data[6]); | 113 | y = le16_to_cpup((__le16 *)&data[6]); |
113 | pressure = le16_to_cpup((__le16 *)&data[8]); | 114 | pressure = le16_to_cpup((__le16 *)&data[8]); |
114 | 115 | ||
116 | if (!wac_i2c->prox) | ||
117 | wac_i2c->tool = (data[3] & 0x0c) ? | ||
118 | BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
119 | |||
120 | wac_i2c->prox = data[3] & 0x20; | ||
121 | |||
115 | input_report_key(input, BTN_TOUCH, tsw || ers); | 122 | input_report_key(input, BTN_TOUCH, tsw || ers); |
116 | input_report_key(input, BTN_TOOL_PEN, tsw); | 123 | input_report_key(input, wac_i2c->tool, wac_i2c->prox); |
117 | input_report_key(input, BTN_TOOL_RUBBER, ers); | ||
118 | input_report_key(input, BTN_STYLUS, f1); | 124 | input_report_key(input, BTN_STYLUS, f1); |
119 | input_report_key(input, BTN_STYLUS2, f2); | 125 | input_report_key(input, BTN_STYLUS2, f2); |
120 | input_report_abs(input, ABS_X, x); | 126 | input_report_abs(input, ABS_X, x); |
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 5f68f2cfdfd0..d5cc3acecfd3 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/uaccess.h> | 44 | #include <linux/uaccess.h> |
45 | #include <linux/moduleparam.h> | 45 | #include <linux/moduleparam.h> |
46 | #include <linux/jiffies.h> | 46 | #include <linux/jiffies.h> |
47 | #include <linux/syscalls.h> | ||
47 | 48 | ||
48 | #include <asm/ptrace.h> | 49 | #include <asm/ptrace.h> |
49 | #include <asm/irq_regs.h> | 50 | #include <asm/irq_regs.h> |
@@ -586,6 +587,7 @@ struct sysrq_state { | |||
586 | 587 | ||
587 | /* reset sequence handling */ | 588 | /* reset sequence handling */ |
588 | bool reset_canceled; | 589 | bool reset_canceled; |
590 | bool reset_requested; | ||
589 | unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)]; | 591 | unsigned long reset_keybit[BITS_TO_LONGS(KEY_CNT)]; |
590 | int reset_seq_len; | 592 | int reset_seq_len; |
591 | int reset_seq_cnt; | 593 | int reset_seq_cnt; |
@@ -624,18 +626,26 @@ static void sysrq_parse_reset_sequence(struct sysrq_state *state) | |||
624 | state->reset_seq_version = sysrq_reset_seq_version; | 626 | state->reset_seq_version = sysrq_reset_seq_version; |
625 | } | 627 | } |
626 | 628 | ||
627 | static void sysrq_do_reset(unsigned long dummy) | 629 | static void sysrq_do_reset(unsigned long _state) |
628 | { | 630 | { |
629 | __handle_sysrq(sysrq_xlate[KEY_B], false); | 631 | struct sysrq_state *state = (struct sysrq_state *) _state; |
632 | |||
633 | state->reset_requested = true; | ||
634 | |||
635 | sys_sync(); | ||
636 | kernel_restart(NULL); | ||
630 | } | 637 | } |
631 | 638 | ||
632 | static void sysrq_handle_reset_request(struct sysrq_state *state) | 639 | static void sysrq_handle_reset_request(struct sysrq_state *state) |
633 | { | 640 | { |
641 | if (state->reset_requested) | ||
642 | __handle_sysrq(sysrq_xlate[KEY_B], false); | ||
643 | |||
634 | if (sysrq_reset_downtime_ms) | 644 | if (sysrq_reset_downtime_ms) |
635 | mod_timer(&state->keyreset_timer, | 645 | mod_timer(&state->keyreset_timer, |
636 | jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms)); | 646 | jiffies + msecs_to_jiffies(sysrq_reset_downtime_ms)); |
637 | else | 647 | else |
638 | sysrq_do_reset(0); | 648 | sysrq_do_reset((unsigned long)state); |
639 | } | 649 | } |
640 | 650 | ||
641 | static void sysrq_detect_reset_sequence(struct sysrq_state *state, | 651 | static void sysrq_detect_reset_sequence(struct sysrq_state *state, |
@@ -837,7 +847,8 @@ static int sysrq_connect(struct input_handler *handler, | |||
837 | sysrq->handle.handler = handler; | 847 | sysrq->handle.handler = handler; |
838 | sysrq->handle.name = "sysrq"; | 848 | sysrq->handle.name = "sysrq"; |
839 | sysrq->handle.private = sysrq; | 849 | sysrq->handle.private = sysrq; |
840 | setup_timer(&sysrq->keyreset_timer, sysrq_do_reset, 0); | 850 | setup_timer(&sysrq->keyreset_timer, |
851 | sysrq_do_reset, (unsigned long)sysrq); | ||
841 | 852 | ||
842 | error = input_register_handle(&sysrq->handle); | 853 | error = input_register_handle(&sysrq->handle); |
843 | if (error) { | 854 | if (error) { |
diff --git a/include/linux/input/tps6507x-ts.h b/include/linux/input/tps6507x-ts.h index ab1440313924..b433df801d92 100644 --- a/include/linux/input/tps6507x-ts.h +++ b/include/linux/input/tps6507x-ts.h | |||
@@ -14,7 +14,6 @@ | |||
14 | /* Board specific touch screen initial values */ | 14 | /* Board specific touch screen initial values */ |
15 | struct touchscreen_init_data { | 15 | struct touchscreen_init_data { |
16 | int poll_period; /* ms */ | 16 | int poll_period; /* ms */ |
17 | int vref; /* non-zero to leave vref on */ | ||
18 | __u16 min_pressure; /* min reading to be treated as a touch */ | 17 | __u16 min_pressure; /* min reading to be treated as a touch */ |
19 | __u16 vendor; | 18 | __u16 vendor; |
20 | __u16 product; | 19 | __u16 product; |
diff --git a/include/linux/mfd/tps6507x.h b/include/linux/mfd/tps6507x.h index c923e4864f55..c2ae56933539 100644 --- a/include/linux/mfd/tps6507x.h +++ b/include/linux/mfd/tps6507x.h | |||
@@ -163,7 +163,6 @@ struct tps6507x_dev { | |||
163 | 163 | ||
164 | /* Client devices */ | 164 | /* Client devices */ |
165 | struct tps6507x_pmic *pmic; | 165 | struct tps6507x_pmic *pmic; |
166 | struct tps6507x_ts *ts; | ||
167 | }; | 166 | }; |
168 | 167 | ||
169 | #endif /* __LINUX_MFD_TPS6507X_H */ | 168 | #endif /* __LINUX_MFD_TPS6507X_H */ |
diff --git a/include/linux/platform_data/cyttsp4.h b/include/linux/platform_data/cyttsp4.h new file mode 100644 index 000000000000..6eba54aff1dc --- /dev/null +++ b/include/linux/platform_data/cyttsp4.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Header file for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com (kev@cypress.com) | ||
27 | * | ||
28 | */ | ||
29 | #ifndef _CYTTSP4_H_ | ||
30 | #define _CYTTSP4_H_ | ||
31 | |||
32 | #define CYTTSP4_MT_NAME "cyttsp4_mt" | ||
33 | #define CYTTSP4_I2C_NAME "cyttsp4_i2c_adapter" | ||
34 | #define CYTTSP4_SPI_NAME "cyttsp4_spi_adapter" | ||
35 | |||
36 | #define CY_TOUCH_SETTINGS_MAX 32 | ||
37 | |||
38 | struct touch_framework { | ||
39 | const uint16_t *abs; | ||
40 | uint8_t size; | ||
41 | uint8_t enable_vkeys; | ||
42 | } __packed; | ||
43 | |||
44 | struct cyttsp4_mt_platform_data { | ||
45 | struct touch_framework *frmwrk; | ||
46 | unsigned short flags; | ||
47 | char const *inp_dev_name; | ||
48 | }; | ||
49 | |||
50 | struct touch_settings { | ||
51 | const uint8_t *data; | ||
52 | uint32_t size; | ||
53 | uint8_t tag; | ||
54 | } __packed; | ||
55 | |||
56 | struct cyttsp4_core_platform_data { | ||
57 | int irq_gpio; | ||
58 | int rst_gpio; | ||
59 | int level_irq_udelay; | ||
60 | int (*xres)(struct cyttsp4_core_platform_data *pdata, | ||
61 | struct device *dev); | ||
62 | int (*init)(struct cyttsp4_core_platform_data *pdata, | ||
63 | int on, struct device *dev); | ||
64 | int (*power)(struct cyttsp4_core_platform_data *pdata, | ||
65 | int on, struct device *dev, atomic_t *ignore_irq); | ||
66 | int (*irq_stat)(struct cyttsp4_core_platform_data *pdata, | ||
67 | struct device *dev); | ||
68 | struct touch_settings *sett[CY_TOUCH_SETTINGS_MAX]; | ||
69 | }; | ||
70 | |||
71 | struct cyttsp4_platform_data { | ||
72 | struct cyttsp4_core_platform_data *core_pdata; | ||
73 | struct cyttsp4_mt_platform_data *mt_pdata; | ||
74 | }; | ||
75 | |||
76 | #endif /* _CYTTSP4_H_ */ | ||
diff --git a/include/linux/platform_data/keypad-pxa27x.h b/include/linux/platform_data/keypad-pxa27x.h index 5ce8d5e6ea51..24625569d16d 100644 --- a/include/linux/platform_data/keypad-pxa27x.h +++ b/include/linux/platform_data/keypad-pxa27x.h | |||
@@ -36,10 +36,9 @@ | |||
36 | struct pxa27x_keypad_platform_data { | 36 | struct pxa27x_keypad_platform_data { |
37 | 37 | ||
38 | /* code map for the matrix keys */ | 38 | /* code map for the matrix keys */ |
39 | const struct matrix_keymap_data *matrix_keymap_data; | ||
39 | unsigned int matrix_key_rows; | 40 | unsigned int matrix_key_rows; |
40 | unsigned int matrix_key_cols; | 41 | unsigned int matrix_key_cols; |
41 | unsigned int *matrix_key_map; | ||
42 | int matrix_key_map_size; | ||
43 | 42 | ||
44 | /* direct keys */ | 43 | /* direct keys */ |
45 | int direct_key_num; | 44 | int direct_key_num; |