diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-27 02:44:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-27 02:44:20 -0400 |
commit | 396e6e49c58bb23d1814d3c240c736c9f01523c5 (patch) | |
tree | a6ec8dac896c3ea3ac7b1bb0dce8728766afcf91 /drivers/input | |
parent | 18974369cfe23acf16d0fb79e0d1fba7a9a95ec0 (diff) | |
parent | 6ad390a25a9d1d8606b9b826878f0a30639dc2b3 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (68 commits)
Input: adp5589-keys - add support for the ADP5585 derivatives
Input: imx_keypad - add pm suspend and resume support
Input: force feedback - potential integer wrap in input_ff_create()
Input: tsc2007 - make sure that X plate resistance is specified
Input: serio_raw - fix memory leak when closing char device
Input: serio_raw - kick clients when disconnecting port
Input: serio_raw - explicitly mark disconnected ports as dead
Input: serio_raw - fix coding style issues
Input: serio_raw - use dev_*() for messages
Input: serio_raw - use bool for boolean data
Input: serio_raw - perform proper locking when adding clients to list
Input: serio_raw - rename serio_raw_list to serio_raw_client
Input: serio_raw - use kref instead of rolling out its own refcounting
Input: psmouse - switch to using dev_*() for messages
Input: wacom - correct max Y value on medium bamboos
Input: wacom - add ABS_DISTANCE to Bamboo Pen reports
Input: wacom - remove unneeded touch pressure initialization
Input: lm8323 - wrap suspend and resume in CONFIG_PM_SLEEP
Input: ad7879-i2c - wrap suspend and resume in CONFIG_PM_SLEEP
Input: synaptics_i2c - wrap suspend and resume in CONFIG_PM_SLEEP
...
Diffstat (limited to 'drivers/input')
59 files changed, 4035 insertions, 839 deletions
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 3367f760d75a..480eb9d9876a 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c | |||
@@ -309,9 +309,10 @@ EXPORT_SYMBOL_GPL(input_ff_event); | |||
309 | * Once ff device is created you need to setup its upload, erase, | 309 | * Once ff device is created you need to setup its upload, erase, |
310 | * playback and other handlers before registering input device | 310 | * playback and other handlers before registering input device |
311 | */ | 311 | */ |
312 | int input_ff_create(struct input_dev *dev, int max_effects) | 312 | int input_ff_create(struct input_dev *dev, unsigned int max_effects) |
313 | { | 313 | { |
314 | struct ff_device *ff; | 314 | struct ff_device *ff; |
315 | size_t ff_dev_size; | ||
315 | int i; | 316 | int i; |
316 | 317 | ||
317 | if (!max_effects) { | 318 | if (!max_effects) { |
@@ -319,8 +320,12 @@ int input_ff_create(struct input_dev *dev, int max_effects) | |||
319 | return -EINVAL; | 320 | return -EINVAL; |
320 | } | 321 | } |
321 | 322 | ||
322 | ff = kzalloc(sizeof(struct ff_device) + | 323 | ff_dev_size = sizeof(struct ff_device) + |
323 | max_effects * sizeof(struct file *), GFP_KERNEL); | 324 | max_effects * sizeof(struct file *); |
325 | if (ff_dev_size < max_effects) /* overflow */ | ||
326 | return -EINVAL; | ||
327 | |||
328 | ff = kzalloc(ff_dev_size, GFP_KERNEL); | ||
324 | if (!ff) | 329 | if (!ff) |
325 | return -ENOMEM; | 330 | return -ENOMEM; |
326 | 331 | ||
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index c48c81f0308d..9150ee78e00a 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c | |||
@@ -117,6 +117,7 @@ void input_mt_report_finger_count(struct input_dev *dev, int count) | |||
117 | input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2); | 117 | input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2); |
118 | input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3); | 118 | input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3); |
119 | input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4); | 119 | input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4); |
120 | input_event(dev, EV_KEY, BTN_TOOL_QUINTTAP, count == 5); | ||
120 | } | 121 | } |
121 | EXPORT_SYMBOL(input_mt_report_finger_count); | 122 | EXPORT_SYMBOL(input_mt_report_finger_count); |
122 | 123 | ||
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index b1aabde87523..b253973881b8 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c | |||
@@ -49,8 +49,10 @@ static int input_open_polled_device(struct input_dev *input) | |||
49 | dev->open(dev); | 49 | dev->open(dev); |
50 | 50 | ||
51 | /* Only start polling if polling is enabled */ | 51 | /* Only start polling if polling is enabled */ |
52 | if (dev->poll_interval > 0) | 52 | if (dev->poll_interval > 0) { |
53 | queue_delayed_work(system_freezable_wq, &dev->work, 0); | 53 | dev->poll(dev); |
54 | input_polldev_queue_work(dev); | ||
55 | } | ||
54 | 56 | ||
55 | return 0; | 57 | return 0; |
56 | } | 58 | } |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b4dee9d5a055..615c21f2a553 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -33,10 +33,10 @@ config KEYBOARD_ADP5588 | |||
33 | module will be called adp5588-keys. | 33 | module will be called adp5588-keys. |
34 | 34 | ||
35 | config KEYBOARD_ADP5589 | 35 | config KEYBOARD_ADP5589 |
36 | tristate "ADP5589 I2C QWERTY Keypad and IO Expander" | 36 | tristate "ADP5585/ADP5589 I2C QWERTY Keypad and IO Expander" |
37 | depends on I2C | 37 | depends on I2C |
38 | help | 38 | help |
39 | Say Y here if you want to use a ADP5589 attached to your | 39 | Say Y here if you want to use a ADP5585/ADP5589 attached to your |
40 | system I2C bus. | 40 | system I2C bus. |
41 | 41 | ||
42 | To compile this driver as a module, choose M here: the | 42 | To compile this driver as a module, choose M here: the |
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index e34eeb8ae371..4a7f534cf64b 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c | |||
@@ -550,7 +550,7 @@ static int __devinit adp5588_probe(struct i2c_client *client, | |||
550 | } | 550 | } |
551 | 551 | ||
552 | error = request_irq(client->irq, adp5588_irq, | 552 | error = request_irq(client->irq, adp5588_irq, |
553 | IRQF_TRIGGER_FALLING | IRQF_DISABLED, | 553 | IRQF_TRIGGER_FALLING, |
554 | client->dev.driver->name, kpad); | 554 | client->dev.driver->name, kpad); |
555 | if (error) { | 555 | if (error) { |
556 | dev_err(&client->dev, "irq %d busy?\n", client->irq); | 556 | dev_err(&client->dev, "irq %d busy?\n", client->irq); |
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index c7708263051b..02b5d53031bf 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Description: keypad driver for ADP5589 | 2 | * Description: keypad driver for ADP5589, ADP5585 |
3 | * I2C QWERTY Keypad and IO Expander | 3 | * I2C QWERTY Keypad and IO Expander |
4 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 4 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
5 | * | 5 | * |
@@ -22,35 +22,165 @@ | |||
22 | 22 | ||
23 | #include <linux/input/adp5589.h> | 23 | #include <linux/input/adp5589.h> |
24 | 24 | ||
25 | /* ADP5589/ADP5585 Common Registers */ | ||
26 | #define ADP5589_5_ID 0x00 | ||
27 | #define ADP5589_5_INT_STATUS 0x01 | ||
28 | #define ADP5589_5_STATUS 0x02 | ||
29 | #define ADP5589_5_FIFO_1 0x03 | ||
30 | #define ADP5589_5_FIFO_2 0x04 | ||
31 | #define ADP5589_5_FIFO_3 0x05 | ||
32 | #define ADP5589_5_FIFO_4 0x06 | ||
33 | #define ADP5589_5_FIFO_5 0x07 | ||
34 | #define ADP5589_5_FIFO_6 0x08 | ||
35 | #define ADP5589_5_FIFO_7 0x09 | ||
36 | #define ADP5589_5_FIFO_8 0x0A | ||
37 | #define ADP5589_5_FIFO_9 0x0B | ||
38 | #define ADP5589_5_FIFO_10 0x0C | ||
39 | #define ADP5589_5_FIFO_11 0x0D | ||
40 | #define ADP5589_5_FIFO_12 0x0E | ||
41 | #define ADP5589_5_FIFO_13 0x0F | ||
42 | #define ADP5589_5_FIFO_14 0x10 | ||
43 | #define ADP5589_5_FIFO_15 0x11 | ||
44 | #define ADP5589_5_FIFO_16 0x12 | ||
45 | #define ADP5589_5_GPI_INT_STAT_A 0x13 | ||
46 | #define ADP5589_5_GPI_INT_STAT_B 0x14 | ||
47 | |||
48 | /* ADP5589 Registers */ | ||
49 | #define ADP5589_GPI_INT_STAT_C 0x15 | ||
50 | #define ADP5589_GPI_STATUS_A 0x16 | ||
51 | #define ADP5589_GPI_STATUS_B 0x17 | ||
52 | #define ADP5589_GPI_STATUS_C 0x18 | ||
53 | #define ADP5589_RPULL_CONFIG_A 0x19 | ||
54 | #define ADP5589_RPULL_CONFIG_B 0x1A | ||
55 | #define ADP5589_RPULL_CONFIG_C 0x1B | ||
56 | #define ADP5589_RPULL_CONFIG_D 0x1C | ||
57 | #define ADP5589_RPULL_CONFIG_E 0x1D | ||
58 | #define ADP5589_GPI_INT_LEVEL_A 0x1E | ||
59 | #define ADP5589_GPI_INT_LEVEL_B 0x1F | ||
60 | #define ADP5589_GPI_INT_LEVEL_C 0x20 | ||
61 | #define ADP5589_GPI_EVENT_EN_A 0x21 | ||
62 | #define ADP5589_GPI_EVENT_EN_B 0x22 | ||
63 | #define ADP5589_GPI_EVENT_EN_C 0x23 | ||
64 | #define ADP5589_GPI_INTERRUPT_EN_A 0x24 | ||
65 | #define ADP5589_GPI_INTERRUPT_EN_B 0x25 | ||
66 | #define ADP5589_GPI_INTERRUPT_EN_C 0x26 | ||
67 | #define ADP5589_DEBOUNCE_DIS_A 0x27 | ||
68 | #define ADP5589_DEBOUNCE_DIS_B 0x28 | ||
69 | #define ADP5589_DEBOUNCE_DIS_C 0x29 | ||
70 | #define ADP5589_GPO_DATA_OUT_A 0x2A | ||
71 | #define ADP5589_GPO_DATA_OUT_B 0x2B | ||
72 | #define ADP5589_GPO_DATA_OUT_C 0x2C | ||
73 | #define ADP5589_GPO_OUT_MODE_A 0x2D | ||
74 | #define ADP5589_GPO_OUT_MODE_B 0x2E | ||
75 | #define ADP5589_GPO_OUT_MODE_C 0x2F | ||
76 | #define ADP5589_GPIO_DIRECTION_A 0x30 | ||
77 | #define ADP5589_GPIO_DIRECTION_B 0x31 | ||
78 | #define ADP5589_GPIO_DIRECTION_C 0x32 | ||
79 | #define ADP5589_UNLOCK1 0x33 | ||
80 | #define ADP5589_UNLOCK2 0x34 | ||
81 | #define ADP5589_EXT_LOCK_EVENT 0x35 | ||
82 | #define ADP5589_UNLOCK_TIMERS 0x36 | ||
83 | #define ADP5589_LOCK_CFG 0x37 | ||
84 | #define ADP5589_RESET1_EVENT_A 0x38 | ||
85 | #define ADP5589_RESET1_EVENT_B 0x39 | ||
86 | #define ADP5589_RESET1_EVENT_C 0x3A | ||
87 | #define ADP5589_RESET2_EVENT_A 0x3B | ||
88 | #define ADP5589_RESET2_EVENT_B 0x3C | ||
89 | #define ADP5589_RESET_CFG 0x3D | ||
90 | #define ADP5589_PWM_OFFT_LOW 0x3E | ||
91 | #define ADP5589_PWM_OFFT_HIGH 0x3F | ||
92 | #define ADP5589_PWM_ONT_LOW 0x40 | ||
93 | #define ADP5589_PWM_ONT_HIGH 0x41 | ||
94 | #define ADP5589_PWM_CFG 0x42 | ||
95 | #define ADP5589_CLOCK_DIV_CFG 0x43 | ||
96 | #define ADP5589_LOGIC_1_CFG 0x44 | ||
97 | #define ADP5589_LOGIC_2_CFG 0x45 | ||
98 | #define ADP5589_LOGIC_FF_CFG 0x46 | ||
99 | #define ADP5589_LOGIC_INT_EVENT_EN 0x47 | ||
100 | #define ADP5589_POLL_PTIME_CFG 0x48 | ||
101 | #define ADP5589_PIN_CONFIG_A 0x49 | ||
102 | #define ADP5589_PIN_CONFIG_B 0x4A | ||
103 | #define ADP5589_PIN_CONFIG_C 0x4B | ||
104 | #define ADP5589_PIN_CONFIG_D 0x4C | ||
105 | #define ADP5589_GENERAL_CFG 0x4D | ||
106 | #define ADP5589_INT_EN 0x4E | ||
107 | |||
108 | /* ADP5585 Registers */ | ||
109 | #define ADP5585_GPI_STATUS_A 0x15 | ||
110 | #define ADP5585_GPI_STATUS_B 0x16 | ||
111 | #define ADP5585_RPULL_CONFIG_A 0x17 | ||
112 | #define ADP5585_RPULL_CONFIG_B 0x18 | ||
113 | #define ADP5585_RPULL_CONFIG_C 0x19 | ||
114 | #define ADP5585_RPULL_CONFIG_D 0x1A | ||
115 | #define ADP5585_GPI_INT_LEVEL_A 0x1B | ||
116 | #define ADP5585_GPI_INT_LEVEL_B 0x1C | ||
117 | #define ADP5585_GPI_EVENT_EN_A 0x1D | ||
118 | #define ADP5585_GPI_EVENT_EN_B 0x1E | ||
119 | #define ADP5585_GPI_INTERRUPT_EN_A 0x1F | ||
120 | #define ADP5585_GPI_INTERRUPT_EN_B 0x20 | ||
121 | #define ADP5585_DEBOUNCE_DIS_A 0x21 | ||
122 | #define ADP5585_DEBOUNCE_DIS_B 0x22 | ||
123 | #define ADP5585_GPO_DATA_OUT_A 0x23 | ||
124 | #define ADP5585_GPO_DATA_OUT_B 0x24 | ||
125 | #define ADP5585_GPO_OUT_MODE_A 0x25 | ||
126 | #define ADP5585_GPO_OUT_MODE_B 0x26 | ||
127 | #define ADP5585_GPIO_DIRECTION_A 0x27 | ||
128 | #define ADP5585_GPIO_DIRECTION_B 0x28 | ||
129 | #define ADP5585_RESET1_EVENT_A 0x29 | ||
130 | #define ADP5585_RESET1_EVENT_B 0x2A | ||
131 | #define ADP5585_RESET1_EVENT_C 0x2B | ||
132 | #define ADP5585_RESET2_EVENT_A 0x2C | ||
133 | #define ADP5585_RESET2_EVENT_B 0x2D | ||
134 | #define ADP5585_RESET_CFG 0x2E | ||
135 | #define ADP5585_PWM_OFFT_LOW 0x2F | ||
136 | #define ADP5585_PWM_OFFT_HIGH 0x30 | ||
137 | #define ADP5585_PWM_ONT_LOW 0x31 | ||
138 | #define ADP5585_PWM_ONT_HIGH 0x32 | ||
139 | #define ADP5585_PWM_CFG 0x33 | ||
140 | #define ADP5585_LOGIC_CFG 0x34 | ||
141 | #define ADP5585_LOGIC_FF_CFG 0x35 | ||
142 | #define ADP5585_LOGIC_INT_EVENT_EN 0x36 | ||
143 | #define ADP5585_POLL_PTIME_CFG 0x37 | ||
144 | #define ADP5585_PIN_CONFIG_A 0x38 | ||
145 | #define ADP5585_PIN_CONFIG_B 0x39 | ||
146 | #define ADP5585_PIN_CONFIG_D 0x3A | ||
147 | #define ADP5585_GENERAL_CFG 0x3B | ||
148 | #define ADP5585_INT_EN 0x3C | ||
149 | |||
150 | /* ID Register */ | ||
151 | #define ADP5589_5_DEVICE_ID_MASK 0xF | ||
152 | #define ADP5589_5_MAN_ID_MASK 0xF | ||
153 | #define ADP5589_5_MAN_ID_SHIFT 4 | ||
154 | #define ADP5589_5_MAN_ID 0x02 | ||
155 | |||
25 | /* GENERAL_CFG Register */ | 156 | /* GENERAL_CFG Register */ |
26 | #define OSC_EN (1 << 7) | 157 | #define OSC_EN (1 << 7) |
27 | #define CORE_CLK(x) (((x) & 0x3) << 5) | 158 | #define CORE_CLK(x) (((x) & 0x3) << 5) |
28 | #define LCK_TRK_LOGIC (1 << 4) | 159 | #define LCK_TRK_LOGIC (1 << 4) /* ADP5589 only */ |
29 | #define LCK_TRK_GPI (1 << 3) | 160 | #define LCK_TRK_GPI (1 << 3) /* ADP5589 only */ |
30 | #define INT_CFG (1 << 1) | 161 | #define INT_CFG (1 << 1) |
31 | #define RST_CFG (1 << 0) | 162 | #define RST_CFG (1 << 0) |
32 | 163 | ||
33 | /* INT_EN Register */ | 164 | /* INT_EN Register */ |
34 | #define LOGIC2_IEN (1 << 5) | 165 | #define LOGIC2_IEN (1 << 5) /* ADP5589 only */ |
35 | #define LOGIC1_IEN (1 << 4) | 166 | #define LOGIC1_IEN (1 << 4) |
36 | #define LOCK_IEN (1 << 3) | 167 | #define LOCK_IEN (1 << 3) /* ADP5589 only */ |
37 | #define OVRFLOW_IEN (1 << 2) | 168 | #define OVRFLOW_IEN (1 << 2) |
38 | #define GPI_IEN (1 << 1) | 169 | #define GPI_IEN (1 << 1) |
39 | #define EVENT_IEN (1 << 0) | 170 | #define EVENT_IEN (1 << 0) |
40 | 171 | ||
41 | /* Interrupt Status Register */ | 172 | /* Interrupt Status Register */ |
42 | #define LOGIC2_INT (1 << 5) | 173 | #define LOGIC2_INT (1 << 5) /* ADP5589 only */ |
43 | #define LOGIC1_INT (1 << 4) | 174 | #define LOGIC1_INT (1 << 4) |
44 | #define LOCK_INT (1 << 3) | 175 | #define LOCK_INT (1 << 3) /* ADP5589 only */ |
45 | #define OVRFLOW_INT (1 << 2) | 176 | #define OVRFLOW_INT (1 << 2) |
46 | #define GPI_INT (1 << 1) | 177 | #define GPI_INT (1 << 1) |
47 | #define EVENT_INT (1 << 0) | 178 | #define EVENT_INT (1 << 0) |
48 | 179 | ||
49 | /* STATUS Register */ | 180 | /* STATUS Register */ |
50 | 181 | #define LOGIC2_STAT (1 << 7) /* ADP5589 only */ | |
51 | #define LOGIC2_STAT (1 << 7) | ||
52 | #define LOGIC1_STAT (1 << 6) | 182 | #define LOGIC1_STAT (1 << 6) |
53 | #define LOCK_STAT (1 << 5) | 183 | #define LOCK_STAT (1 << 5) /* ADP5589 only */ |
54 | #define KEC 0xF | 184 | #define KEC 0xF |
55 | 185 | ||
56 | /* PIN_CONFIG_D Register */ | 186 | /* PIN_CONFIG_D Register */ |
@@ -61,27 +191,54 @@ | |||
61 | #define LOCK_EN (1 << 0) | 191 | #define LOCK_EN (1 << 0) |
62 | 192 | ||
63 | #define PTIME_MASK 0x3 | 193 | #define PTIME_MASK 0x3 |
64 | #define LTIME_MASK 0x3 | 194 | #define LTIME_MASK 0x3 /* ADP5589 only */ |
65 | 195 | ||
66 | /* Key Event Register xy */ | 196 | /* Key Event Register xy */ |
67 | #define KEY_EV_PRESSED (1 << 7) | 197 | #define KEY_EV_PRESSED (1 << 7) |
68 | #define KEY_EV_MASK (0x7F) | 198 | #define KEY_EV_MASK (0x7F) |
69 | 199 | ||
70 | #define KEYP_MAX_EVENT 16 | 200 | #define KEYP_MAX_EVENT 16 |
201 | #define ADP5589_MAXGPIO 19 | ||
202 | #define ADP5585_MAXGPIO 11 /* 10 on the ADP5585-01, 11 on ADP5585-02 */ | ||
71 | 203 | ||
72 | #define MAXGPIO 19 | 204 | enum { |
73 | #define ADP_BANK(offs) ((offs) >> 3) | 205 | ADP5589, |
74 | #define ADP_BIT(offs) (1u << ((offs) & 0x7)) | 206 | ADP5585_01, |
207 | ADP5585_02 | ||
208 | }; | ||
209 | |||
210 | struct adp_constants { | ||
211 | u8 maxgpio; | ||
212 | u8 keymapsize; | ||
213 | u8 gpi_pin_row_base; | ||
214 | u8 gpi_pin_row_end; | ||
215 | u8 gpi_pin_col_base; | ||
216 | u8 gpi_pin_base; | ||
217 | u8 gpi_pin_end; | ||
218 | u8 gpimapsize_max; | ||
219 | u8 max_row_num; | ||
220 | u8 max_col_num; | ||
221 | u8 row_mask; | ||
222 | u8 col_mask; | ||
223 | u8 col_shift; | ||
224 | u8 c4_extend_cfg; | ||
225 | u8 (*bank) (u8 offset); | ||
226 | u8 (*bit) (u8 offset); | ||
227 | u8 (*reg) (u8 reg); | ||
228 | }; | ||
75 | 229 | ||
76 | struct adp5589_kpad { | 230 | struct adp5589_kpad { |
77 | struct i2c_client *client; | 231 | struct i2c_client *client; |
78 | struct input_dev *input; | 232 | struct input_dev *input; |
233 | const struct adp_constants *var; | ||
79 | unsigned short keycode[ADP5589_KEYMAPSIZE]; | 234 | unsigned short keycode[ADP5589_KEYMAPSIZE]; |
80 | const struct adp5589_gpi_map *gpimap; | 235 | const struct adp5589_gpi_map *gpimap; |
81 | unsigned short gpimapsize; | 236 | unsigned short gpimapsize; |
82 | unsigned extend_cfg; | 237 | unsigned extend_cfg; |
238 | bool is_adp5585; | ||
239 | bool adp5585_support_row5; | ||
83 | #ifdef CONFIG_GPIOLIB | 240 | #ifdef CONFIG_GPIOLIB |
84 | unsigned char gpiomap[MAXGPIO]; | 241 | unsigned char gpiomap[ADP5589_MAXGPIO]; |
85 | bool export_gpio; | 242 | bool export_gpio; |
86 | struct gpio_chip gc; | 243 | struct gpio_chip gc; |
87 | struct mutex gpio_lock; /* Protect cached dir, dat_out */ | 244 | struct mutex gpio_lock; /* Protect cached dir, dat_out */ |
@@ -90,6 +247,129 @@ struct adp5589_kpad { | |||
90 | #endif | 247 | #endif |
91 | }; | 248 | }; |
92 | 249 | ||
250 | /* | ||
251 | * ADP5589 / ADP5585 derivative / variant handling | ||
252 | */ | ||
253 | |||
254 | |||
255 | /* ADP5589 */ | ||
256 | |||
257 | static unsigned char adp5589_bank(unsigned char offset) | ||
258 | { | ||
259 | return offset >> 3; | ||
260 | } | ||
261 | |||
262 | static unsigned char adp5589_bit(unsigned char offset) | ||
263 | { | ||
264 | return 1u << (offset & 0x7); | ||
265 | } | ||
266 | |||
267 | static unsigned char adp5589_reg(unsigned char reg) | ||
268 | { | ||
269 | return reg; | ||
270 | } | ||
271 | |||
272 | static const struct adp_constants const_adp5589 = { | ||
273 | .maxgpio = ADP5589_MAXGPIO, | ||
274 | .keymapsize = ADP5589_KEYMAPSIZE, | ||
275 | .gpi_pin_row_base = ADP5589_GPI_PIN_ROW_BASE, | ||
276 | .gpi_pin_row_end = ADP5589_GPI_PIN_ROW_END, | ||
277 | .gpi_pin_col_base = ADP5589_GPI_PIN_COL_BASE, | ||
278 | .gpi_pin_base = ADP5589_GPI_PIN_BASE, | ||
279 | .gpi_pin_end = ADP5589_GPI_PIN_END, | ||
280 | .gpimapsize_max = ADP5589_GPIMAPSIZE_MAX, | ||
281 | .c4_extend_cfg = 12, | ||
282 | .max_row_num = ADP5589_MAX_ROW_NUM, | ||
283 | .max_col_num = ADP5589_MAX_COL_NUM, | ||
284 | .row_mask = ADP5589_ROW_MASK, | ||
285 | .col_mask = ADP5589_COL_MASK, | ||
286 | .col_shift = ADP5589_COL_SHIFT, | ||
287 | .bank = adp5589_bank, | ||
288 | .bit = adp5589_bit, | ||
289 | .reg = adp5589_reg, | ||
290 | }; | ||
291 | |||
292 | /* ADP5585 */ | ||
293 | |||
294 | static unsigned char adp5585_bank(unsigned char offset) | ||
295 | { | ||
296 | return offset > ADP5585_MAX_ROW_NUM; | ||
297 | } | ||
298 | |||
299 | static unsigned char adp5585_bit(unsigned char offset) | ||
300 | { | ||
301 | return (offset > ADP5585_MAX_ROW_NUM) ? | ||
302 | 1u << (offset - ADP5585_COL_SHIFT) : 1u << offset; | ||
303 | } | ||
304 | |||
305 | static const unsigned char adp5585_reg_lut[] = { | ||
306 | [ADP5589_GPI_STATUS_A] = ADP5585_GPI_STATUS_A, | ||
307 | [ADP5589_GPI_STATUS_B] = ADP5585_GPI_STATUS_B, | ||
308 | [ADP5589_RPULL_CONFIG_A] = ADP5585_RPULL_CONFIG_A, | ||
309 | [ADP5589_RPULL_CONFIG_B] = ADP5585_RPULL_CONFIG_B, | ||
310 | [ADP5589_RPULL_CONFIG_C] = ADP5585_RPULL_CONFIG_C, | ||
311 | [ADP5589_RPULL_CONFIG_D] = ADP5585_RPULL_CONFIG_D, | ||
312 | [ADP5589_GPI_INT_LEVEL_A] = ADP5585_GPI_INT_LEVEL_A, | ||
313 | [ADP5589_GPI_INT_LEVEL_B] = ADP5585_GPI_INT_LEVEL_B, | ||
314 | [ADP5589_GPI_EVENT_EN_A] = ADP5585_GPI_EVENT_EN_A, | ||
315 | [ADP5589_GPI_EVENT_EN_B] = ADP5585_GPI_EVENT_EN_B, | ||
316 | [ADP5589_GPI_INTERRUPT_EN_A] = ADP5585_GPI_INTERRUPT_EN_A, | ||
317 | [ADP5589_GPI_INTERRUPT_EN_B] = ADP5585_GPI_INTERRUPT_EN_B, | ||
318 | [ADP5589_DEBOUNCE_DIS_A] = ADP5585_DEBOUNCE_DIS_A, | ||
319 | [ADP5589_DEBOUNCE_DIS_B] = ADP5585_DEBOUNCE_DIS_B, | ||
320 | [ADP5589_GPO_DATA_OUT_A] = ADP5585_GPO_DATA_OUT_A, | ||
321 | [ADP5589_GPO_DATA_OUT_B] = ADP5585_GPO_DATA_OUT_B, | ||
322 | [ADP5589_GPO_OUT_MODE_A] = ADP5585_GPO_OUT_MODE_A, | ||
323 | [ADP5589_GPO_OUT_MODE_B] = ADP5585_GPO_OUT_MODE_B, | ||
324 | [ADP5589_GPIO_DIRECTION_A] = ADP5585_GPIO_DIRECTION_A, | ||
325 | [ADP5589_GPIO_DIRECTION_B] = ADP5585_GPIO_DIRECTION_B, | ||
326 | [ADP5589_RESET1_EVENT_A] = ADP5585_RESET1_EVENT_A, | ||
327 | [ADP5589_RESET1_EVENT_B] = ADP5585_RESET1_EVENT_B, | ||
328 | [ADP5589_RESET1_EVENT_C] = ADP5585_RESET1_EVENT_C, | ||
329 | [ADP5589_RESET2_EVENT_A] = ADP5585_RESET2_EVENT_A, | ||
330 | [ADP5589_RESET2_EVENT_B] = ADP5585_RESET2_EVENT_B, | ||
331 | [ADP5589_RESET_CFG] = ADP5585_RESET_CFG, | ||
332 | [ADP5589_PWM_OFFT_LOW] = ADP5585_PWM_OFFT_LOW, | ||
333 | [ADP5589_PWM_OFFT_HIGH] = ADP5585_PWM_OFFT_HIGH, | ||
334 | [ADP5589_PWM_ONT_LOW] = ADP5585_PWM_ONT_LOW, | ||
335 | [ADP5589_PWM_ONT_HIGH] = ADP5585_PWM_ONT_HIGH, | ||
336 | [ADP5589_PWM_CFG] = ADP5585_PWM_CFG, | ||
337 | [ADP5589_LOGIC_1_CFG] = ADP5585_LOGIC_CFG, | ||
338 | [ADP5589_LOGIC_FF_CFG] = ADP5585_LOGIC_FF_CFG, | ||
339 | [ADP5589_LOGIC_INT_EVENT_EN] = ADP5585_LOGIC_INT_EVENT_EN, | ||
340 | [ADP5589_POLL_PTIME_CFG] = ADP5585_POLL_PTIME_CFG, | ||
341 | [ADP5589_PIN_CONFIG_A] = ADP5585_PIN_CONFIG_A, | ||
342 | [ADP5589_PIN_CONFIG_B] = ADP5585_PIN_CONFIG_B, | ||
343 | [ADP5589_PIN_CONFIG_D] = ADP5585_PIN_CONFIG_D, | ||
344 | [ADP5589_GENERAL_CFG] = ADP5585_GENERAL_CFG, | ||
345 | [ADP5589_INT_EN] = ADP5585_INT_EN, | ||
346 | }; | ||
347 | |||
348 | static unsigned char adp5585_reg(unsigned char reg) | ||
349 | { | ||
350 | return adp5585_reg_lut[reg]; | ||
351 | } | ||
352 | |||
353 | static const struct adp_constants const_adp5585 = { | ||
354 | .maxgpio = ADP5585_MAXGPIO, | ||
355 | .keymapsize = ADP5585_KEYMAPSIZE, | ||
356 | .gpi_pin_row_base = ADP5585_GPI_PIN_ROW_BASE, | ||
357 | .gpi_pin_row_end = ADP5585_GPI_PIN_ROW_END, | ||
358 | .gpi_pin_col_base = ADP5585_GPI_PIN_COL_BASE, | ||
359 | .gpi_pin_base = ADP5585_GPI_PIN_BASE, | ||
360 | .gpi_pin_end = ADP5585_GPI_PIN_END, | ||
361 | .gpimapsize_max = ADP5585_GPIMAPSIZE_MAX, | ||
362 | .c4_extend_cfg = 10, | ||
363 | .max_row_num = ADP5585_MAX_ROW_NUM, | ||
364 | .max_col_num = ADP5585_MAX_COL_NUM, | ||
365 | .row_mask = ADP5585_ROW_MASK, | ||
366 | .col_mask = ADP5585_COL_MASK, | ||
367 | .col_shift = ADP5585_COL_SHIFT, | ||
368 | .bank = adp5585_bank, | ||
369 | .bit = adp5585_bit, | ||
370 | .reg = adp5585_reg, | ||
371 | }; | ||
372 | |||
93 | static int adp5589_read(struct i2c_client *client, u8 reg) | 373 | static int adp5589_read(struct i2c_client *client, u8 reg) |
94 | { | 374 | { |
95 | int ret = i2c_smbus_read_byte_data(client, reg); | 375 | int ret = i2c_smbus_read_byte_data(client, reg); |
@@ -109,19 +389,20 @@ static int adp5589_write(struct i2c_client *client, u8 reg, u8 val) | |||
109 | static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) | 389 | static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) |
110 | { | 390 | { |
111 | struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); | 391 | struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); |
112 | unsigned int bank = ADP_BANK(kpad->gpiomap[off]); | 392 | unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); |
113 | unsigned int bit = ADP_BIT(kpad->gpiomap[off]); | 393 | unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); |
114 | 394 | ||
115 | return !!(adp5589_read(kpad->client, ADP5589_GPI_STATUS_A + bank) & | 395 | return !!(adp5589_read(kpad->client, |
116 | bit); | 396 | kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) & |
397 | bit); | ||
117 | } | 398 | } |
118 | 399 | ||
119 | static void adp5589_gpio_set_value(struct gpio_chip *chip, | 400 | static void adp5589_gpio_set_value(struct gpio_chip *chip, |
120 | unsigned off, int val) | 401 | unsigned off, int val) |
121 | { | 402 | { |
122 | struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); | 403 | struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); |
123 | unsigned int bank = ADP_BANK(kpad->gpiomap[off]); | 404 | unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); |
124 | unsigned int bit = ADP_BIT(kpad->gpiomap[off]); | 405 | unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); |
125 | 406 | ||
126 | mutex_lock(&kpad->gpio_lock); | 407 | mutex_lock(&kpad->gpio_lock); |
127 | 408 | ||
@@ -130,8 +411,8 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip, | |||
130 | else | 411 | else |
131 | kpad->dat_out[bank] &= ~bit; | 412 | kpad->dat_out[bank] &= ~bit; |
132 | 413 | ||
133 | adp5589_write(kpad->client, ADP5589_GPO_DATA_OUT_A + bank, | 414 | adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) + |
134 | kpad->dat_out[bank]); | 415 | bank, kpad->dat_out[bank]); |
135 | 416 | ||
136 | mutex_unlock(&kpad->gpio_lock); | 417 | mutex_unlock(&kpad->gpio_lock); |
137 | } | 418 | } |
@@ -139,14 +420,15 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip, | |||
139 | static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) | 420 | static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) |
140 | { | 421 | { |
141 | struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); | 422 | struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); |
142 | unsigned int bank = ADP_BANK(kpad->gpiomap[off]); | 423 | unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); |
143 | unsigned int bit = ADP_BIT(kpad->gpiomap[off]); | 424 | unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); |
144 | int ret; | 425 | int ret; |
145 | 426 | ||
146 | mutex_lock(&kpad->gpio_lock); | 427 | mutex_lock(&kpad->gpio_lock); |
147 | 428 | ||
148 | kpad->dir[bank] &= ~bit; | 429 | kpad->dir[bank] &= ~bit; |
149 | ret = adp5589_write(kpad->client, ADP5589_GPIO_DIRECTION_A + bank, | 430 | ret = adp5589_write(kpad->client, |
431 | kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank, | ||
150 | kpad->dir[bank]); | 432 | kpad->dir[bank]); |
151 | 433 | ||
152 | mutex_unlock(&kpad->gpio_lock); | 434 | mutex_unlock(&kpad->gpio_lock); |
@@ -158,8 +440,8 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip, | |||
158 | unsigned off, int val) | 440 | unsigned off, int val) |
159 | { | 441 | { |
160 | struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); | 442 | struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc); |
161 | unsigned int bank = ADP_BANK(kpad->gpiomap[off]); | 443 | unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); |
162 | unsigned int bit = ADP_BIT(kpad->gpiomap[off]); | 444 | unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); |
163 | int ret; | 445 | int ret; |
164 | 446 | ||
165 | mutex_lock(&kpad->gpio_lock); | 447 | mutex_lock(&kpad->gpio_lock); |
@@ -171,9 +453,10 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip, | |||
171 | else | 453 | else |
172 | kpad->dat_out[bank] &= ~bit; | 454 | kpad->dat_out[bank] &= ~bit; |
173 | 455 | ||
174 | ret = adp5589_write(kpad->client, ADP5589_GPO_DATA_OUT_A + bank, | 456 | ret = adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) |
175 | kpad->dat_out[bank]); | 457 | + bank, kpad->dat_out[bank]); |
176 | ret |= adp5589_write(kpad->client, ADP5589_GPIO_DIRECTION_A + bank, | 458 | ret |= adp5589_write(kpad->client, |
459 | kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank, | ||
177 | kpad->dir[bank]); | 460 | kpad->dir[bank]); |
178 | 461 | ||
179 | mutex_unlock(&kpad->gpio_lock); | 462 | mutex_unlock(&kpad->gpio_lock); |
@@ -184,26 +467,29 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip, | |||
184 | static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad, | 467 | static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad, |
185 | const struct adp5589_kpad_platform_data *pdata) | 468 | const struct adp5589_kpad_platform_data *pdata) |
186 | { | 469 | { |
187 | bool pin_used[MAXGPIO]; | 470 | bool pin_used[ADP5589_MAXGPIO]; |
188 | int n_unused = 0; | 471 | int n_unused = 0; |
189 | int i; | 472 | int i; |
190 | 473 | ||
191 | memset(pin_used, false, sizeof(pin_used)); | 474 | memset(pin_used, false, sizeof(pin_used)); |
192 | 475 | ||
193 | for (i = 0; i < MAXGPIO; i++) | 476 | for (i = 0; i < kpad->var->maxgpio; i++) |
194 | if (pdata->keypad_en_mask & (1 << i)) | 477 | if (pdata->keypad_en_mask & (1 << i)) |
195 | pin_used[i] = true; | 478 | pin_used[i] = true; |
196 | 479 | ||
197 | for (i = 0; i < kpad->gpimapsize; i++) | 480 | for (i = 0; i < kpad->gpimapsize; i++) |
198 | pin_used[kpad->gpimap[i].pin - ADP5589_GPI_PIN_BASE] = true; | 481 | pin_used[kpad->gpimap[i].pin - kpad->var->gpi_pin_base] = true; |
199 | 482 | ||
200 | if (kpad->extend_cfg & R4_EXTEND_CFG) | 483 | if (kpad->extend_cfg & R4_EXTEND_CFG) |
201 | pin_used[4] = true; | 484 | pin_used[4] = true; |
202 | 485 | ||
203 | if (kpad->extend_cfg & C4_EXTEND_CFG) | 486 | if (kpad->extend_cfg & C4_EXTEND_CFG) |
204 | pin_used[12] = true; | 487 | pin_used[kpad->var->c4_extend_cfg] = true; |
488 | |||
489 | if (!kpad->adp5585_support_row5) | ||
490 | pin_used[5] = true; | ||
205 | 491 | ||
206 | for (i = 0; i < MAXGPIO; i++) | 492 | for (i = 0; i < kpad->var->maxgpio; i++) |
207 | if (!pin_used[i]) | 493 | if (!pin_used[i]) |
208 | kpad->gpiomap[n_unused++] = i; | 494 | kpad->gpiomap[n_unused++] = i; |
209 | 495 | ||
@@ -246,11 +532,11 @@ static int __devinit adp5589_gpio_add(struct adp5589_kpad *kpad) | |||
246 | return error; | 532 | return error; |
247 | } | 533 | } |
248 | 534 | ||
249 | for (i = 0; i <= ADP_BANK(MAXGPIO); i++) { | 535 | for (i = 0; i <= kpad->var->bank(kpad->var->maxgpio); i++) { |
250 | kpad->dat_out[i] = adp5589_read(kpad->client, | 536 | kpad->dat_out[i] = adp5589_read(kpad->client, kpad->var->reg( |
251 | ADP5589_GPO_DATA_OUT_A + i); | 537 | ADP5589_GPO_DATA_OUT_A) + i); |
252 | kpad->dir[i] = adp5589_read(kpad->client, | 538 | kpad->dir[i] = adp5589_read(kpad->client, kpad->var->reg( |
253 | ADP5589_GPIO_DIRECTION_A + i); | 539 | ADP5589_GPIO_DIRECTION_A) + i); |
254 | } | 540 | } |
255 | 541 | ||
256 | if (gpio_data->setup) { | 542 | if (gpio_data->setup) { |
@@ -317,11 +603,11 @@ static void adp5589_report_events(struct adp5589_kpad *kpad, int ev_cnt) | |||
317 | int i; | 603 | int i; |
318 | 604 | ||
319 | for (i = 0; i < ev_cnt; i++) { | 605 | for (i = 0; i < ev_cnt; i++) { |
320 | int key = adp5589_read(kpad->client, ADP5589_FIFO_1 + i); | 606 | int key = adp5589_read(kpad->client, ADP5589_5_FIFO_1 + i); |
321 | int key_val = key & KEY_EV_MASK; | 607 | int key_val = key & KEY_EV_MASK; |
322 | 608 | ||
323 | if (key_val >= ADP5589_GPI_PIN_BASE && | 609 | if (key_val >= kpad->var->gpi_pin_base && |
324 | key_val <= ADP5589_GPI_PIN_END) { | 610 | key_val <= kpad->var->gpi_pin_end) { |
325 | adp5589_report_switches(kpad, key, key_val); | 611 | adp5589_report_switches(kpad, key, key_val); |
326 | } else { | 612 | } else { |
327 | input_report_key(kpad->input, | 613 | input_report_key(kpad->input, |
@@ -337,29 +623,30 @@ static irqreturn_t adp5589_irq(int irq, void *handle) | |||
337 | struct i2c_client *client = kpad->client; | 623 | struct i2c_client *client = kpad->client; |
338 | int status, ev_cnt; | 624 | int status, ev_cnt; |
339 | 625 | ||
340 | status = adp5589_read(client, ADP5589_INT_STATUS); | 626 | status = adp5589_read(client, ADP5589_5_INT_STATUS); |
341 | 627 | ||
342 | if (status & OVRFLOW_INT) /* Unlikely and should never happen */ | 628 | if (status & OVRFLOW_INT) /* Unlikely and should never happen */ |
343 | dev_err(&client->dev, "Event Overflow Error\n"); | 629 | dev_err(&client->dev, "Event Overflow Error\n"); |
344 | 630 | ||
345 | if (status & EVENT_INT) { | 631 | if (status & EVENT_INT) { |
346 | ev_cnt = adp5589_read(client, ADP5589_STATUS) & KEC; | 632 | ev_cnt = adp5589_read(client, ADP5589_5_STATUS) & KEC; |
347 | if (ev_cnt) { | 633 | if (ev_cnt) { |
348 | adp5589_report_events(kpad, ev_cnt); | 634 | adp5589_report_events(kpad, ev_cnt); |
349 | input_sync(kpad->input); | 635 | input_sync(kpad->input); |
350 | } | 636 | } |
351 | } | 637 | } |
352 | 638 | ||
353 | adp5589_write(client, ADP5589_INT_STATUS, status); /* Status is W1C */ | 639 | adp5589_write(client, ADP5589_5_INT_STATUS, status); /* Status is W1C */ |
354 | 640 | ||
355 | return IRQ_HANDLED; | 641 | return IRQ_HANDLED; |
356 | } | 642 | } |
357 | 643 | ||
358 | static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key) | 644 | static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad, |
645 | unsigned short key) | ||
359 | { | 646 | { |
360 | int i; | 647 | int i; |
361 | 648 | ||
362 | for (i = 0; i < ADP5589_KEYMAPSIZE; i++) | 649 | for (i = 0; i < kpad->var->keymapsize; i++) |
363 | if (key == kpad->keycode[i]) | 650 | if (key == kpad->keycode[i]) |
364 | return (i + 1) | KEY_EV_PRESSED; | 651 | return (i + 1) | KEY_EV_PRESSED; |
365 | 652 | ||
@@ -372,19 +659,23 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad) | |||
372 | { | 659 | { |
373 | struct i2c_client *client = kpad->client; | 660 | struct i2c_client *client = kpad->client; |
374 | const struct adp5589_kpad_platform_data *pdata = | 661 | const struct adp5589_kpad_platform_data *pdata = |
375 | client->dev.platform_data; | 662 | client->dev.platform_data; |
376 | int i, ret; | 663 | u8 (*reg) (u8) = kpad->var->reg; |
377 | unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; | 664 | unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; |
378 | unsigned char pull_mask = 0; | 665 | unsigned char pull_mask = 0; |
666 | int i, ret; | ||
667 | |||
668 | ret = adp5589_write(client, reg(ADP5589_PIN_CONFIG_A), | ||
669 | pdata->keypad_en_mask & kpad->var->row_mask); | ||
670 | ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_B), | ||
671 | (pdata->keypad_en_mask >> kpad->var->col_shift) & | ||
672 | kpad->var->col_mask); | ||
379 | 673 | ||
380 | ret = adp5589_write(client, ADP5589_PIN_CONFIG_A, | 674 | if (!kpad->is_adp5585) |
381 | pdata->keypad_en_mask & 0xFF); | 675 | ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C, |
382 | ret |= adp5589_write(client, ADP5589_PIN_CONFIG_B, | 676 | (pdata->keypad_en_mask >> 16) & 0xFF); |
383 | (pdata->keypad_en_mask >> 8) & 0xFF); | ||
384 | ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C, | ||
385 | (pdata->keypad_en_mask >> 16) & 0xFF); | ||
386 | 677 | ||
387 | if (pdata->en_keylock) { | 678 | if (!kpad->is_adp5585 && pdata->en_keylock) { |
388 | ret |= adp5589_write(client, ADP5589_UNLOCK1, | 679 | ret |= adp5589_write(client, ADP5589_UNLOCK1, |
389 | pdata->unlock_key1); | 680 | pdata->unlock_key1); |
390 | ret |= adp5589_write(client, ADP5589_UNLOCK2, | 681 | ret |= adp5589_write(client, ADP5589_UNLOCK2, |
@@ -395,96 +686,130 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad) | |||
395 | } | 686 | } |
396 | 687 | ||
397 | for (i = 0; i < KEYP_MAX_EVENT; i++) | 688 | for (i = 0; i < KEYP_MAX_EVENT; i++) |
398 | ret |= adp5589_read(client, ADP5589_FIFO_1 + i); | 689 | ret |= adp5589_read(client, ADP5589_5_FIFO_1 + i); |
399 | 690 | ||
400 | for (i = 0; i < pdata->gpimapsize; i++) { | 691 | for (i = 0; i < pdata->gpimapsize; i++) { |
401 | unsigned short pin = pdata->gpimap[i].pin; | 692 | unsigned short pin = pdata->gpimap[i].pin; |
402 | 693 | ||
403 | if (pin <= ADP5589_GPI_PIN_ROW_END) { | 694 | if (pin <= kpad->var->gpi_pin_row_end) { |
404 | evt_mode1 |= (1 << (pin - ADP5589_GPI_PIN_ROW_BASE)); | 695 | evt_mode1 |= (1 << (pin - kpad->var->gpi_pin_row_base)); |
405 | } else { | 696 | } else { |
406 | evt_mode2 |= | 697 | evt_mode2 |= |
407 | ((1 << (pin - ADP5589_GPI_PIN_COL_BASE)) & 0xFF); | 698 | ((1 << (pin - kpad->var->gpi_pin_col_base)) & 0xFF); |
408 | evt_mode3 |= | 699 | if (!kpad->is_adp5585) |
409 | ((1 << (pin - ADP5589_GPI_PIN_COL_BASE)) >> 8); | 700 | evt_mode3 |= ((1 << (pin - |
701 | kpad->var->gpi_pin_col_base)) >> 8); | ||
410 | } | 702 | } |
411 | } | 703 | } |
412 | 704 | ||
413 | if (pdata->gpimapsize) { | 705 | if (pdata->gpimapsize) { |
414 | ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_A, evt_mode1); | 706 | ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_A), |
415 | ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_B, evt_mode2); | 707 | evt_mode1); |
416 | ret |= adp5589_write(client, ADP5589_GPI_EVENT_EN_C, evt_mode3); | 708 | ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_B), |
709 | evt_mode2); | ||
710 | if (!kpad->is_adp5585) | ||
711 | ret |= adp5589_write(client, | ||
712 | reg(ADP5589_GPI_EVENT_EN_C), | ||
713 | evt_mode3); | ||
417 | } | 714 | } |
418 | 715 | ||
419 | if (pdata->pull_dis_mask & pdata->pullup_en_100k & | 716 | if (pdata->pull_dis_mask & pdata->pullup_en_100k & |
420 | pdata->pullup_en_300k & pdata->pulldown_en_300k) | 717 | pdata->pullup_en_300k & pdata->pulldown_en_300k) |
421 | dev_warn(&client->dev, "Conflicting pull resistor config\n"); | 718 | dev_warn(&client->dev, "Conflicting pull resistor config\n"); |
422 | 719 | ||
423 | for (i = 0; i < MAXGPIO; i++) { | 720 | for (i = 0; i <= kpad->var->max_row_num; i++) { |
424 | unsigned val = 0; | 721 | unsigned val = 0, bit = (1 << i); |
722 | if (pdata->pullup_en_300k & bit) | ||
723 | val = 0; | ||
724 | else if (pdata->pulldown_en_300k & bit) | ||
725 | val = 1; | ||
726 | else if (pdata->pullup_en_100k & bit) | ||
727 | val = 2; | ||
728 | else if (pdata->pull_dis_mask & bit) | ||
729 | val = 3; | ||
730 | |||
731 | pull_mask |= val << (2 * (i & 0x3)); | ||
732 | |||
733 | if (i == 3 || i == kpad->var->max_row_num) { | ||
734 | ret |= adp5589_write(client, reg(ADP5585_RPULL_CONFIG_A) | ||
735 | + (i >> 2), pull_mask); | ||
736 | pull_mask = 0; | ||
737 | } | ||
738 | } | ||
425 | 739 | ||
426 | if (pdata->pullup_en_300k & (1 << i)) | 740 | for (i = 0; i <= kpad->var->max_col_num; i++) { |
741 | unsigned val = 0, bit = 1 << (i + kpad->var->col_shift); | ||
742 | if (pdata->pullup_en_300k & bit) | ||
427 | val = 0; | 743 | val = 0; |
428 | else if (pdata->pulldown_en_300k & (1 << i)) | 744 | else if (pdata->pulldown_en_300k & bit) |
429 | val = 1; | 745 | val = 1; |
430 | else if (pdata->pullup_en_100k & (1 << i)) | 746 | else if (pdata->pullup_en_100k & bit) |
431 | val = 2; | 747 | val = 2; |
432 | else if (pdata->pull_dis_mask & (1 << i)) | 748 | else if (pdata->pull_dis_mask & bit) |
433 | val = 3; | 749 | val = 3; |
434 | 750 | ||
435 | pull_mask |= val << (2 * (i & 0x3)); | 751 | pull_mask |= val << (2 * (i & 0x3)); |
436 | 752 | ||
437 | if ((i & 0x3) == 0x3 || i == MAXGPIO - 1) { | 753 | if (i == 3 || i == kpad->var->max_col_num) { |
438 | ret |= adp5589_write(client, | 754 | ret |= adp5589_write(client, |
439 | ADP5589_RPULL_CONFIG_A + (i >> 2), | 755 | reg(ADP5585_RPULL_CONFIG_C) + |
440 | pull_mask); | 756 | (i >> 2), pull_mask); |
441 | pull_mask = 0; | 757 | pull_mask = 0; |
442 | } | 758 | } |
443 | } | 759 | } |
444 | 760 | ||
445 | if (pdata->reset1_key_1 && pdata->reset1_key_2 && pdata->reset1_key_3) { | 761 | if (pdata->reset1_key_1 && pdata->reset1_key_2 && pdata->reset1_key_3) { |
446 | ret |= adp5589_write(client, ADP5589_RESET1_EVENT_A, | 762 | ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_A), |
447 | adp5589_get_evcode(kpad, | 763 | adp5589_get_evcode(kpad, |
448 | pdata->reset1_key_1)); | 764 | pdata->reset1_key_1)); |
449 | ret |= adp5589_write(client, ADP5589_RESET1_EVENT_B, | 765 | ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_B), |
450 | adp5589_get_evcode(kpad, | 766 | adp5589_get_evcode(kpad, |
451 | pdata->reset1_key_2)); | 767 | pdata->reset1_key_2)); |
452 | ret |= adp5589_write(client, ADP5589_RESET1_EVENT_C, | 768 | ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_C), |
453 | adp5589_get_evcode(kpad, | 769 | adp5589_get_evcode(kpad, |
454 | pdata->reset1_key_3)); | 770 | pdata->reset1_key_3)); |
455 | kpad->extend_cfg |= R4_EXTEND_CFG; | 771 | kpad->extend_cfg |= R4_EXTEND_CFG; |
456 | } | 772 | } |
457 | 773 | ||
458 | if (pdata->reset2_key_1 && pdata->reset2_key_2) { | 774 | if (pdata->reset2_key_1 && pdata->reset2_key_2) { |
459 | ret |= adp5589_write(client, ADP5589_RESET2_EVENT_A, | 775 | ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_A), |
460 | adp5589_get_evcode(kpad, | 776 | adp5589_get_evcode(kpad, |
461 | pdata->reset2_key_1)); | 777 | pdata->reset2_key_1)); |
462 | ret |= adp5589_write(client, ADP5589_RESET2_EVENT_B, | 778 | ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_B), |
463 | adp5589_get_evcode(kpad, | 779 | adp5589_get_evcode(kpad, |
464 | pdata->reset2_key_2)); | 780 | pdata->reset2_key_2)); |
465 | kpad->extend_cfg |= C4_EXTEND_CFG; | 781 | kpad->extend_cfg |= C4_EXTEND_CFG; |
466 | } | 782 | } |
467 | 783 | ||
468 | if (kpad->extend_cfg) { | 784 | if (kpad->extend_cfg) { |
469 | ret |= adp5589_write(client, ADP5589_RESET_CFG, | 785 | ret |= adp5589_write(client, reg(ADP5589_RESET_CFG), |
470 | pdata->reset_cfg); | 786 | pdata->reset_cfg); |
471 | ret |= adp5589_write(client, ADP5589_PIN_CONFIG_D, | 787 | ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_D), |
472 | kpad->extend_cfg); | 788 | kpad->extend_cfg); |
473 | } | 789 | } |
474 | 790 | ||
475 | for (i = 0; i <= ADP_BANK(MAXGPIO); i++) | 791 | ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_A), |
476 | ret |= adp5589_write(client, ADP5589_DEBOUNCE_DIS_A + i, | 792 | pdata->debounce_dis_mask & kpad->var->row_mask); |
477 | pdata->debounce_dis_mask >> (i * 8)); | ||
478 | 793 | ||
479 | ret |= adp5589_write(client, ADP5589_POLL_PTIME_CFG, | 794 | ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_B), |
795 | (pdata->debounce_dis_mask >> kpad->var->col_shift) | ||
796 | & kpad->var->col_mask); | ||
797 | |||
798 | if (!kpad->is_adp5585) | ||
799 | ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_C), | ||
800 | (pdata->debounce_dis_mask >> 16) & 0xFF); | ||
801 | |||
802 | ret |= adp5589_write(client, reg(ADP5589_POLL_PTIME_CFG), | ||
480 | pdata->scan_cycle_time & PTIME_MASK); | 803 | pdata->scan_cycle_time & PTIME_MASK); |
481 | ret |= adp5589_write(client, ADP5589_INT_STATUS, LOGIC2_INT | | 804 | ret |= adp5589_write(client, ADP5589_5_INT_STATUS, |
482 | LOGIC1_INT | OVRFLOW_INT | LOCK_INT | | 805 | (kpad->is_adp5585 ? 0 : LOGIC2_INT) | |
806 | LOGIC1_INT | OVRFLOW_INT | | ||
807 | (kpad->is_adp5585 ? 0 : LOCK_INT) | | ||
483 | GPI_INT | EVENT_INT); /* Status is W1C */ | 808 | GPI_INT | EVENT_INT); /* Status is W1C */ |
484 | 809 | ||
485 | ret |= adp5589_write(client, ADP5589_GENERAL_CFG, | 810 | ret |= adp5589_write(client, reg(ADP5589_GENERAL_CFG), |
486 | INT_CFG | OSC_EN | CORE_CLK(3)); | 811 | INT_CFG | OSC_EN | CORE_CLK(3)); |
487 | ret |= adp5589_write(client, ADP5589_INT_EN, | 812 | ret |= adp5589_write(client, reg(ADP5589_INT_EN), |
488 | OVRFLOW_IEN | GPI_IEN | EVENT_IEN); | 813 | OVRFLOW_IEN | GPI_IEN | EVENT_IEN); |
489 | 814 | ||
490 | if (ret < 0) { | 815 | if (ret < 0) { |
@@ -497,30 +822,33 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad) | |||
497 | 822 | ||
498 | static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad) | 823 | static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad) |
499 | { | 824 | { |
500 | int gpi_stat1 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_A); | ||
501 | int gpi_stat2 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_B); | ||
502 | int gpi_stat3 = adp5589_read(kpad->client, ADP5589_GPI_STATUS_C); | ||
503 | int gpi_stat_tmp, pin_loc; | 825 | int gpi_stat_tmp, pin_loc; |
504 | int i; | 826 | int i; |
827 | int gpi_stat1 = adp5589_read(kpad->client, | ||
828 | kpad->var->reg(ADP5589_GPI_STATUS_A)); | ||
829 | int gpi_stat2 = adp5589_read(kpad->client, | ||
830 | kpad->var->reg(ADP5589_GPI_STATUS_B)); | ||
831 | int gpi_stat3 = !kpad->is_adp5585 ? | ||
832 | adp5589_read(kpad->client, ADP5589_GPI_STATUS_C) : 0; | ||
505 | 833 | ||
506 | for (i = 0; i < kpad->gpimapsize; i++) { | 834 | for (i = 0; i < kpad->gpimapsize; i++) { |
507 | unsigned short pin = kpad->gpimap[i].pin; | 835 | unsigned short pin = kpad->gpimap[i].pin; |
508 | 836 | ||
509 | if (pin <= ADP5589_GPI_PIN_ROW_END) { | 837 | if (pin <= kpad->var->gpi_pin_row_end) { |
510 | gpi_stat_tmp = gpi_stat1; | 838 | gpi_stat_tmp = gpi_stat1; |
511 | pin_loc = pin - ADP5589_GPI_PIN_ROW_BASE; | 839 | pin_loc = pin - kpad->var->gpi_pin_row_base; |
512 | } else if ((pin - ADP5589_GPI_PIN_COL_BASE) < 8) { | 840 | } else if ((pin - kpad->var->gpi_pin_col_base) < 8) { |
513 | gpi_stat_tmp = gpi_stat2; | 841 | gpi_stat_tmp = gpi_stat2; |
514 | pin_loc = pin - ADP5589_GPI_PIN_COL_BASE; | 842 | pin_loc = pin - kpad->var->gpi_pin_col_base; |
515 | } else { | 843 | } else { |
516 | gpi_stat_tmp = gpi_stat3; | 844 | gpi_stat_tmp = gpi_stat3; |
517 | pin_loc = pin - ADP5589_GPI_PIN_COL_BASE - 8; | 845 | pin_loc = pin - kpad->var->gpi_pin_col_base - 8; |
518 | } | 846 | } |
519 | 847 | ||
520 | if (gpi_stat_tmp < 0) { | 848 | if (gpi_stat_tmp < 0) { |
521 | dev_err(&kpad->client->dev, | 849 | dev_err(&kpad->client->dev, |
522 | "Can't read GPIO_DAT_STAT switch" | 850 | "Can't read GPIO_DAT_STAT switch %d, default to OFF\n", |
523 | " %d default to OFF\n", pin); | 851 | pin); |
524 | gpi_stat_tmp = 0; | 852 | gpi_stat_tmp = 0; |
525 | } | 853 | } |
526 | 854 | ||
@@ -536,7 +864,8 @@ static int __devinit adp5589_probe(struct i2c_client *client, | |||
536 | const struct i2c_device_id *id) | 864 | const struct i2c_device_id *id) |
537 | { | 865 | { |
538 | struct adp5589_kpad *kpad; | 866 | struct adp5589_kpad *kpad; |
539 | const struct adp5589_kpad_platform_data *pdata; | 867 | const struct adp5589_kpad_platform_data *pdata = |
868 | client->dev.platform_data; | ||
540 | struct input_dev *input; | 869 | struct input_dev *input; |
541 | unsigned int revid; | 870 | unsigned int revid; |
542 | int ret, i; | 871 | int ret, i; |
@@ -548,56 +877,79 @@ static int __devinit adp5589_probe(struct i2c_client *client, | |||
548 | return -EIO; | 877 | return -EIO; |
549 | } | 878 | } |
550 | 879 | ||
551 | pdata = client->dev.platform_data; | ||
552 | if (!pdata) { | 880 | if (!pdata) { |
553 | dev_err(&client->dev, "no platform data?\n"); | 881 | dev_err(&client->dev, "no platform data?\n"); |
554 | return -EINVAL; | 882 | return -EINVAL; |
555 | } | 883 | } |
556 | 884 | ||
557 | if (!((pdata->keypad_en_mask & 0xFF) && | 885 | kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); |
558 | (pdata->keypad_en_mask >> 8)) || !pdata->keymap) { | 886 | if (!kpad) |
887 | return -ENOMEM; | ||
888 | |||
889 | switch (id->driver_data) { | ||
890 | case ADP5585_02: | ||
891 | kpad->adp5585_support_row5 = true; | ||
892 | case ADP5585_01: | ||
893 | kpad->is_adp5585 = true; | ||
894 | kpad->var = &const_adp5585; | ||
895 | break; | ||
896 | case ADP5589: | ||
897 | kpad->var = &const_adp5589; | ||
898 | break; | ||
899 | } | ||
900 | |||
901 | if (!((pdata->keypad_en_mask & kpad->var->row_mask) && | ||
902 | (pdata->keypad_en_mask >> kpad->var->col_shift)) || | ||
903 | !pdata->keymap) { | ||
559 | dev_err(&client->dev, "no rows, cols or keymap from pdata\n"); | 904 | dev_err(&client->dev, "no rows, cols or keymap from pdata\n"); |
560 | return -EINVAL; | 905 | error = -EINVAL; |
906 | goto err_free_mem; | ||
561 | } | 907 | } |
562 | 908 | ||
563 | if (pdata->keymapsize != ADP5589_KEYMAPSIZE) { | 909 | if (pdata->keymapsize != kpad->var->keymapsize) { |
564 | dev_err(&client->dev, "invalid keymapsize\n"); | 910 | dev_err(&client->dev, "invalid keymapsize\n"); |
565 | return -EINVAL; | 911 | error = -EINVAL; |
912 | goto err_free_mem; | ||
566 | } | 913 | } |
567 | 914 | ||
568 | if (!pdata->gpimap && pdata->gpimapsize) { | 915 | if (!pdata->gpimap && pdata->gpimapsize) { |
569 | dev_err(&client->dev, "invalid gpimap from pdata\n"); | 916 | dev_err(&client->dev, "invalid gpimap from pdata\n"); |
570 | return -EINVAL; | 917 | error = -EINVAL; |
918 | goto err_free_mem; | ||
571 | } | 919 | } |
572 | 920 | ||
573 | if (pdata->gpimapsize > ADP5589_GPIMAPSIZE_MAX) { | 921 | if (pdata->gpimapsize > kpad->var->gpimapsize_max) { |
574 | dev_err(&client->dev, "invalid gpimapsize\n"); | 922 | dev_err(&client->dev, "invalid gpimapsize\n"); |
575 | return -EINVAL; | 923 | error = -EINVAL; |
924 | goto err_free_mem; | ||
576 | } | 925 | } |
577 | 926 | ||
578 | for (i = 0; i < pdata->gpimapsize; i++) { | 927 | for (i = 0; i < pdata->gpimapsize; i++) { |
579 | unsigned short pin = pdata->gpimap[i].pin; | 928 | unsigned short pin = pdata->gpimap[i].pin; |
580 | 929 | ||
581 | if (pin < ADP5589_GPI_PIN_BASE || pin > ADP5589_GPI_PIN_END) { | 930 | if (pin < kpad->var->gpi_pin_base || |
931 | pin > kpad->var->gpi_pin_end) { | ||
582 | dev_err(&client->dev, "invalid gpi pin data\n"); | 932 | dev_err(&client->dev, "invalid gpi pin data\n"); |
583 | return -EINVAL; | 933 | error = -EINVAL; |
934 | goto err_free_mem; | ||
584 | } | 935 | } |
585 | 936 | ||
586 | if ((1 << (pin - ADP5589_GPI_PIN_ROW_BASE)) & | 937 | if ((1 << (pin - kpad->var->gpi_pin_row_base)) & |
587 | pdata->keypad_en_mask) { | 938 | pdata->keypad_en_mask) { |
588 | dev_err(&client->dev, "invalid gpi row/col data\n"); | 939 | dev_err(&client->dev, "invalid gpi row/col data\n"); |
589 | return -EINVAL; | 940 | error = -EINVAL; |
941 | goto err_free_mem; | ||
590 | } | 942 | } |
591 | } | 943 | } |
592 | 944 | ||
593 | if (!client->irq) { | 945 | if (!client->irq) { |
594 | dev_err(&client->dev, "no IRQ?\n"); | 946 | dev_err(&client->dev, "no IRQ?\n"); |
595 | return -EINVAL; | 947 | error = -EINVAL; |
948 | goto err_free_mem; | ||
596 | } | 949 | } |
597 | 950 | ||
598 | kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); | ||
599 | input = input_allocate_device(); | 951 | input = input_allocate_device(); |
600 | if (!kpad || !input) { | 952 | if (!input) { |
601 | error = -ENOMEM; | 953 | error = -ENOMEM; |
602 | goto err_free_mem; | 954 | goto err_free_mem; |
603 | } | 955 | } |
@@ -605,13 +957,13 @@ static int __devinit adp5589_probe(struct i2c_client *client, | |||
605 | kpad->client = client; | 957 | kpad->client = client; |
606 | kpad->input = input; | 958 | kpad->input = input; |
607 | 959 | ||
608 | ret = adp5589_read(client, ADP5589_ID); | 960 | ret = adp5589_read(client, ADP5589_5_ID); |
609 | if (ret < 0) { | 961 | if (ret < 0) { |
610 | error = ret; | 962 | error = ret; |
611 | goto err_free_mem; | 963 | goto err_free_input; |
612 | } | 964 | } |
613 | 965 | ||
614 | revid = (u8) ret & ADP5589_DEVICE_ID_MASK; | 966 | revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK; |
615 | 967 | ||
616 | input->name = client->name; | 968 | input->name = client->name; |
617 | input->phys = "adp5589-keys/input0"; | 969 | input->phys = "adp5589-keys/input0"; |
@@ -652,7 +1004,7 @@ static int __devinit adp5589_probe(struct i2c_client *client, | |||
652 | error = input_register_device(input); | 1004 | error = input_register_device(input); |
653 | if (error) { | 1005 | if (error) { |
654 | dev_err(&client->dev, "unable to register input device\n"); | 1006 | dev_err(&client->dev, "unable to register input device\n"); |
655 | goto err_free_mem; | 1007 | goto err_free_input; |
656 | } | 1008 | } |
657 | 1009 | ||
658 | error = request_threaded_irq(client->irq, NULL, adp5589_irq, | 1010 | error = request_threaded_irq(client->irq, NULL, adp5589_irq, |
@@ -685,8 +1037,9 @@ err_free_irq: | |||
685 | err_unreg_dev: | 1037 | err_unreg_dev: |
686 | input_unregister_device(input); | 1038 | input_unregister_device(input); |
687 | input = NULL; | 1039 | input = NULL; |
688 | err_free_mem: | 1040 | err_free_input: |
689 | input_free_device(input); | 1041 | input_free_device(input); |
1042 | err_free_mem: | ||
690 | kfree(kpad); | 1043 | kfree(kpad); |
691 | 1044 | ||
692 | return error; | 1045 | return error; |
@@ -696,7 +1049,7 @@ static int __devexit adp5589_remove(struct i2c_client *client) | |||
696 | { | 1049 | { |
697 | struct adp5589_kpad *kpad = i2c_get_clientdata(client); | 1050 | struct adp5589_kpad *kpad = i2c_get_clientdata(client); |
698 | 1051 | ||
699 | adp5589_write(client, ADP5589_GENERAL_CFG, 0); | 1052 | adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0); |
700 | free_irq(client->irq, kpad); | 1053 | free_irq(client->irq, kpad); |
701 | input_unregister_device(kpad->input); | 1054 | input_unregister_device(kpad->input); |
702 | adp5589_gpio_remove(kpad); | 1055 | adp5589_gpio_remove(kpad); |
@@ -736,7 +1089,9 @@ static int adp5589_resume(struct device *dev) | |||
736 | static SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume); | 1089 | static SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume); |
737 | 1090 | ||
738 | static const struct i2c_device_id adp5589_id[] = { | 1091 | static const struct i2c_device_id adp5589_id[] = { |
739 | {"adp5589-keys", 0}, | 1092 | {"adp5589-keys", ADP5589}, |
1093 | {"adp5585-keys", ADP5585_01}, | ||
1094 | {"adp5585-02-keys", ADP5585_02}, /* Adds ROW5 to ADP5585 */ | ||
740 | {} | 1095 | {} |
741 | }; | 1096 | }; |
742 | 1097 | ||
@@ -767,4 +1122,4 @@ module_exit(adp5589_exit); | |||
767 | 1122 | ||
768 | MODULE_LICENSE("GPL"); | 1123 | MODULE_LICENSE("GPL"); |
769 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 1124 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
770 | MODULE_DESCRIPTION("ADP5589 Keypad driver"); | 1125 | MODULE_DESCRIPTION("ADP5589/ADP5585 Keypad driver"); |
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index cd89d17162a3..9d82b3aeff5e 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c | |||
@@ -271,7 +271,7 @@ static int __init davinci_ks_probe(struct platform_device *pdev) | |||
271 | } | 271 | } |
272 | 272 | ||
273 | error = request_irq(davinci_ks->irq, davinci_ks_interrupt, | 273 | error = request_irq(davinci_ks->irq, davinci_ks_interrupt, |
274 | IRQF_DISABLED, pdev->name, davinci_ks); | 274 | 0, pdev->name, davinci_ks); |
275 | if (error < 0) { | 275 | if (error < 0) { |
276 | dev_err(dev, "unable to register davinci key scan interrupt\n"); | 276 | dev_err(dev, "unable to register davinci key scan interrupt\n"); |
277 | goto fail5; | 277 | goto fail5; |
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index aa17e024d803..4662c5da8018 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c | |||
@@ -323,7 +323,7 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | |||
323 | platform_set_drvdata(pdev, keypad); | 323 | platform_set_drvdata(pdev, keypad); |
324 | 324 | ||
325 | err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, | 325 | err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, |
326 | IRQF_DISABLED, pdev->name, keypad); | 326 | 0, pdev->name, keypad); |
327 | if (err) | 327 | if (err) |
328 | goto failed_free_dev; | 328 | goto failed_free_dev; |
329 | 329 | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 67df91af8424..ed1ed469d085 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -461,8 +461,7 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, | |||
461 | struct device_node *node, *pp; | 461 | struct device_node *node, *pp; |
462 | int i; | 462 | int i; |
463 | struct gpio_keys_button *buttons; | 463 | struct gpio_keys_button *buttons; |
464 | const u32 *reg; | 464 | u32 reg; |
465 | int len; | ||
466 | 465 | ||
467 | node = dev->of_node; | 466 | node = dev->of_node; |
468 | if (node == NULL) | 467 | if (node == NULL) |
@@ -470,7 +469,7 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, | |||
470 | 469 | ||
471 | memset(pdata, 0, sizeof *pdata); | 470 | memset(pdata, 0, sizeof *pdata); |
472 | 471 | ||
473 | pdata->rep = !!of_get_property(node, "autorepeat", &len); | 472 | pdata->rep = !!of_get_property(node, "autorepeat", NULL); |
474 | 473 | ||
475 | /* First count the subnodes */ | 474 | /* First count the subnodes */ |
476 | pdata->nbuttons = 0; | 475 | pdata->nbuttons = 0; |
@@ -498,22 +497,25 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, | |||
498 | buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags); | 497 | buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags); |
499 | buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW; | 498 | buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW; |
500 | 499 | ||
501 | reg = of_get_property(pp, "linux,code", &len); | 500 | if (of_property_read_u32(pp, "linux,code", ®)) { |
502 | if (!reg) { | ||
503 | dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio); | 501 | dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio); |
504 | goto out_fail; | 502 | goto out_fail; |
505 | } | 503 | } |
506 | buttons[i].code = be32_to_cpup(reg); | 504 | buttons[i].code = reg; |
507 | 505 | ||
508 | buttons[i].desc = of_get_property(pp, "label", &len); | 506 | buttons[i].desc = of_get_property(pp, "label", NULL); |
509 | 507 | ||
510 | reg = of_get_property(pp, "linux,input-type", &len); | 508 | if (of_property_read_u32(pp, "linux,input-type", ®) == 0) |
511 | buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY; | 509 | buttons[i].type = reg; |
510 | else | ||
511 | buttons[i].type = EV_KEY; | ||
512 | 512 | ||
513 | buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); | 513 | buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); |
514 | 514 | ||
515 | reg = of_get_property(pp, "debounce-interval", &len); | 515 | if (of_property_read_u32(pp, "debounce-interval", ®) == 0) |
516 | buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5; | 516 | buttons[i].debounce_interval = reg; |
517 | else | ||
518 | buttons[i].debounce_interval = 5; | ||
517 | 519 | ||
518 | i++; | 520 | i++; |
519 | } | 521 | } |
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index d92c15c39e68..ccebd2d09151 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c | |||
@@ -510,7 +510,7 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) | |||
510 | /* Ensure that the keypad will stay dormant until opened */ | 510 | /* Ensure that the keypad will stay dormant until opened */ |
511 | imx_keypad_inhibit(keypad); | 511 | imx_keypad_inhibit(keypad); |
512 | 512 | ||
513 | error = request_irq(irq, imx_keypad_irq_handler, IRQF_DISABLED, | 513 | error = request_irq(irq, imx_keypad_irq_handler, 0, |
514 | pdev->name, keypad); | 514 | pdev->name, keypad); |
515 | if (error) { | 515 | if (error) { |
516 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 516 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
@@ -567,10 +567,54 @@ static int __devexit imx_keypad_remove(struct platform_device *pdev) | |||
567 | return 0; | 567 | return 0; |
568 | } | 568 | } |
569 | 569 | ||
570 | #ifdef CONFIG_PM_SLEEP | ||
571 | static int imx_kbd_suspend(struct device *dev) | ||
572 | { | ||
573 | struct platform_device *pdev = to_platform_device(dev); | ||
574 | struct imx_keypad *kbd = platform_get_drvdata(pdev); | ||
575 | struct input_dev *input_dev = kbd->input_dev; | ||
576 | |||
577 | /* imx kbd can wake up system even clock is disabled */ | ||
578 | mutex_lock(&input_dev->mutex); | ||
579 | |||
580 | if (input_dev->users) | ||
581 | clk_disable(kbd->clk); | ||
582 | |||
583 | mutex_unlock(&input_dev->mutex); | ||
584 | |||
585 | if (device_may_wakeup(&pdev->dev)) | ||
586 | enable_irq_wake(kbd->irq); | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static int imx_kbd_resume(struct device *dev) | ||
592 | { | ||
593 | struct platform_device *pdev = to_platform_device(dev); | ||
594 | struct imx_keypad *kbd = platform_get_drvdata(pdev); | ||
595 | struct input_dev *input_dev = kbd->input_dev; | ||
596 | |||
597 | if (device_may_wakeup(&pdev->dev)) | ||
598 | disable_irq_wake(kbd->irq); | ||
599 | |||
600 | mutex_lock(&input_dev->mutex); | ||
601 | |||
602 | if (input_dev->users) | ||
603 | clk_enable(kbd->clk); | ||
604 | |||
605 | mutex_unlock(&input_dev->mutex); | ||
606 | |||
607 | return 0; | ||
608 | } | ||
609 | #endif | ||
610 | |||
611 | static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume); | ||
612 | |||
570 | static struct platform_driver imx_keypad_driver = { | 613 | static struct platform_driver imx_keypad_driver = { |
571 | .driver = { | 614 | .driver = { |
572 | .name = "imx-keypad", | 615 | .name = "imx-keypad", |
573 | .owner = THIS_MODULE, | 616 | .owner = THIS_MODULE, |
617 | .pm = &imx_kbd_pm_ops, | ||
574 | }, | 618 | }, |
575 | .probe = imx_keypad_probe, | 619 | .probe = imx_keypad_probe, |
576 | .remove = __devexit_p(imx_keypad_remove), | 620 | .remove = __devexit_p(imx_keypad_remove), |
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 2cd3e1d56ea4..0aa6740e60d0 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c | |||
@@ -129,7 +129,7 @@ static int __devinit jornada720_kbd_probe(struct platform_device *pdev) | |||
129 | 129 | ||
130 | err = request_irq(IRQ_GPIO0, | 130 | err = request_irq(IRQ_GPIO0, |
131 | jornada720_kbd_interrupt, | 131 | jornada720_kbd_interrupt, |
132 | IRQF_DISABLED | IRQF_TRIGGER_FALLING, | 132 | IRQF_TRIGGER_FALLING, |
133 | "jornadakbd", pdev); | 133 | "jornadakbd", pdev); |
134 | if (err) { | 134 | if (err) { |
135 | printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n"); | 135 | printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n"); |
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 756348a7f93a..82d1dc8badd5 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c | |||
@@ -788,7 +788,7 @@ static int __devexit lm8323_remove(struct i2c_client *client) | |||
788 | return 0; | 788 | return 0; |
789 | } | 789 | } |
790 | 790 | ||
791 | #ifdef CONFIG_PM | 791 | #ifdef CONFIG_PM_SLEEP |
792 | /* | 792 | /* |
793 | * We don't need to explicitly suspend the chip, as it already switches off | 793 | * We don't need to explicitly suspend the chip, as it already switches off |
794 | * when there's no activity. | 794 | * when there's no activity. |
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index b02e4268e18f..e2ae657717ea 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -343,7 +343,6 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev, | |||
343 | for (i = 0; i < pdata->num_row_gpios; i++) { | 343 | for (i = 0; i < pdata->num_row_gpios; i++) { |
344 | err = request_irq(gpio_to_irq(pdata->row_gpios[i]), | 344 | err = request_irq(gpio_to_irq(pdata->row_gpios[i]), |
345 | matrix_keypad_interrupt, | 345 | matrix_keypad_interrupt, |
346 | IRQF_DISABLED | | ||
347 | IRQF_TRIGGER_RISING | | 346 | IRQF_TRIGGER_RISING | |
348 | IRQF_TRIGGER_FALLING, | 347 | IRQF_TRIGGER_FALLING, |
349 | "matrix-keypad", keypad); | 348 | "matrix-keypad", keypad); |
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 4b0ec35259a1..eca6ae63de14 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -535,7 +535,7 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
535 | input_dev->evbit[0] |= BIT_MASK(EV_REL); | 535 | input_dev->evbit[0] |= BIT_MASK(EV_REL); |
536 | } | 536 | } |
537 | 537 | ||
538 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, | 538 | error = request_irq(irq, pxa27x_keypad_irq_handler, 0, |
539 | pdev->name, keypad); | 539 | pdev->name, keypad); |
540 | if (error) { | 540 | if (error) { |
541 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 541 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index b7123a44b6ec..35451bf780c7 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c | |||
@@ -148,7 +148,7 @@ static int __devinit pxa930_rotary_probe(struct platform_device *pdev) | |||
148 | r->input_dev = input_dev; | 148 | r->input_dev = input_dev; |
149 | input_set_drvdata(input_dev, r); | 149 | input_set_drvdata(input_dev, r); |
150 | 150 | ||
151 | err = request_irq(irq, rotary_irq, IRQF_DISABLED, | 151 | err = request_irq(irq, rotary_irq, 0, |
152 | "enhanced rotary", r); | 152 | "enhanced rotary", r); |
153 | if (err) { | 153 | if (err) { |
154 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 154 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 99122f59e988..f60c9e82f204 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c | |||
@@ -90,7 +90,7 @@ struct tc_keypad { | |||
90 | bool keypad_stopped; | 90 | bool keypad_stopped; |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) | 93 | static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) |
94 | { | 94 | { |
95 | int ret; | 95 | int ret; |
96 | struct tc3589x *tc3589x = keypad->tc3589x; | 96 | struct tc3589x *tc3589x = keypad->tc3589x; |
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index a5a77915c650..cf3228b0ab90 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c | |||
@@ -55,6 +55,7 @@ | |||
55 | 55 | ||
56 | #define KBC_ROW_CFG0_0 0x8 | 56 | #define KBC_ROW_CFG0_0 0x8 |
57 | #define KBC_COL_CFG0_0 0x18 | 57 | #define KBC_COL_CFG0_0 0x18 |
58 | #define KBC_TO_CNT_0 0x24 | ||
58 | #define KBC_INIT_DLY_0 0x28 | 59 | #define KBC_INIT_DLY_0 0x28 |
59 | #define KBC_RPT_DLY_0 0x2c | 60 | #define KBC_RPT_DLY_0 0x2c |
60 | #define KBC_KP_ENT0_0 0x30 | 61 | #define KBC_KP_ENT0_0 0x30 |
@@ -70,6 +71,7 @@ struct tegra_kbc { | |||
70 | spinlock_t lock; | 71 | spinlock_t lock; |
71 | unsigned int repoll_dly; | 72 | unsigned int repoll_dly; |
72 | unsigned long cp_dly_jiffies; | 73 | unsigned long cp_dly_jiffies; |
74 | unsigned int cp_to_wkup_dly; | ||
73 | bool use_fn_map; | 75 | bool use_fn_map; |
74 | bool use_ghost_filter; | 76 | bool use_ghost_filter; |
75 | const struct tegra_kbc_platform_data *pdata; | 77 | const struct tegra_kbc_platform_data *pdata; |
@@ -258,12 +260,10 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
258 | u32 val = 0; | 260 | u32 val = 0; |
259 | unsigned int i; | 261 | unsigned int i; |
260 | unsigned int num_down = 0; | 262 | unsigned int num_down = 0; |
261 | unsigned long flags; | ||
262 | bool fn_keypress = false; | 263 | bool fn_keypress = false; |
263 | bool key_in_same_row = false; | 264 | bool key_in_same_row = false; |
264 | bool key_in_same_col = false; | 265 | bool key_in_same_col = false; |
265 | 266 | ||
266 | spin_lock_irqsave(&kbc->lock, flags); | ||
267 | for (i = 0; i < KBC_MAX_KPENT; i++) { | 267 | for (i = 0; i < KBC_MAX_KPENT; i++) { |
268 | if ((i % 4) == 0) | 268 | if ((i % 4) == 0) |
269 | val = readl(kbc->mmio + KBC_KP_ENT0_0 + i); | 269 | val = readl(kbc->mmio + KBC_KP_ENT0_0 + i); |
@@ -292,7 +292,7 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
292 | * any 2 of the 3 keys share a row, and any 2 of them share a column. | 292 | * any 2 of the 3 keys share a row, and any 2 of them share a column. |
293 | * If so ignore the key presses for this iteration. | 293 | * If so ignore the key presses for this iteration. |
294 | */ | 294 | */ |
295 | if ((kbc->use_ghost_filter) && (num_down >= 3)) { | 295 | if (kbc->use_ghost_filter && num_down >= 3) { |
296 | for (i = 0; i < num_down; i++) { | 296 | for (i = 0; i < num_down; i++) { |
297 | unsigned int j; | 297 | unsigned int j; |
298 | u8 curr_col = scancodes[i] & 0x07; | 298 | u8 curr_col = scancodes[i] & 0x07; |
@@ -325,8 +325,6 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
325 | } | 325 | } |
326 | } | 326 | } |
327 | 327 | ||
328 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
329 | |||
330 | /* Ignore the key presses for this iteration? */ | 328 | /* Ignore the key presses for this iteration? */ |
331 | if (key_in_same_col && key_in_same_row) | 329 | if (key_in_same_col && key_in_same_row) |
332 | return; | 330 | return; |
@@ -341,6 +339,18 @@ static void tegra_kbc_report_keys(struct tegra_kbc *kbc) | |||
341 | kbc->num_pressed_keys = num_down; | 339 | kbc->num_pressed_keys = num_down; |
342 | } | 340 | } |
343 | 341 | ||
342 | static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable) | ||
343 | { | ||
344 | u32 val; | ||
345 | |||
346 | val = readl(kbc->mmio + KBC_CONTROL_0); | ||
347 | if (enable) | ||
348 | val |= KBC_CONTROL_FIFO_CNT_INT_EN; | ||
349 | else | ||
350 | val &= ~KBC_CONTROL_FIFO_CNT_INT_EN; | ||
351 | writel(val, kbc->mmio + KBC_CONTROL_0); | ||
352 | } | ||
353 | |||
344 | static void tegra_kbc_keypress_timer(unsigned long data) | 354 | static void tegra_kbc_keypress_timer(unsigned long data) |
345 | { | 355 | { |
346 | struct tegra_kbc *kbc = (struct tegra_kbc *)data; | 356 | struct tegra_kbc *kbc = (struct tegra_kbc *)data; |
@@ -348,6 +358,8 @@ static void tegra_kbc_keypress_timer(unsigned long data) | |||
348 | u32 val; | 358 | u32 val; |
349 | unsigned int i; | 359 | unsigned int i; |
350 | 360 | ||
361 | spin_lock_irqsave(&kbc->lock, flags); | ||
362 | |||
351 | val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf; | 363 | val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf; |
352 | if (val) { | 364 | if (val) { |
353 | unsigned long dly; | 365 | unsigned long dly; |
@@ -369,26 +381,19 @@ static void tegra_kbc_keypress_timer(unsigned long data) | |||
369 | kbc->num_pressed_keys = 0; | 381 | kbc->num_pressed_keys = 0; |
370 | 382 | ||
371 | /* All keys are released so enable the keypress interrupt */ | 383 | /* All keys are released so enable the keypress interrupt */ |
372 | spin_lock_irqsave(&kbc->lock, flags); | 384 | tegra_kbc_set_fifo_interrupt(kbc, true); |
373 | val = readl(kbc->mmio + KBC_CONTROL_0); | ||
374 | val |= KBC_CONTROL_FIFO_CNT_INT_EN; | ||
375 | writel(val, kbc->mmio + KBC_CONTROL_0); | ||
376 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
377 | } | 385 | } |
386 | |||
387 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
378 | } | 388 | } |
379 | 389 | ||
380 | static irqreturn_t tegra_kbc_isr(int irq, void *args) | 390 | static irqreturn_t tegra_kbc_isr(int irq, void *args) |
381 | { | 391 | { |
382 | struct tegra_kbc *kbc = args; | 392 | struct tegra_kbc *kbc = args; |
383 | u32 val, ctl; | 393 | unsigned long flags; |
394 | u32 val; | ||
384 | 395 | ||
385 | /* | 396 | spin_lock_irqsave(&kbc->lock, flags); |
386 | * Until all keys are released, defer further processing to | ||
387 | * the polling loop in tegra_kbc_keypress_timer | ||
388 | */ | ||
389 | ctl = readl(kbc->mmio + KBC_CONTROL_0); | ||
390 | ctl &= ~KBC_CONTROL_FIFO_CNT_INT_EN; | ||
391 | writel(ctl, kbc->mmio + KBC_CONTROL_0); | ||
392 | 397 | ||
393 | /* | 398 | /* |
394 | * Quickly bail out & reenable interrupts if the fifo threshold | 399 | * Quickly bail out & reenable interrupts if the fifo threshold |
@@ -399,15 +404,15 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args) | |||
399 | 404 | ||
400 | if (val & KBC_INT_FIFO_CNT_INT_STATUS) { | 405 | if (val & KBC_INT_FIFO_CNT_INT_STATUS) { |
401 | /* | 406 | /* |
402 | * Schedule timer to run when hardware is in continuous | 407 | * Until all keys are released, defer further processing to |
403 | * polling mode. | 408 | * the polling loop in tegra_kbc_keypress_timer. |
404 | */ | 409 | */ |
410 | tegra_kbc_set_fifo_interrupt(kbc, false); | ||
405 | mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies); | 411 | mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies); |
406 | } else { | ||
407 | ctl |= KBC_CONTROL_FIFO_CNT_INT_EN; | ||
408 | writel(ctl, kbc->mmio + KBC_CONTROL_0); | ||
409 | } | 412 | } |
410 | 413 | ||
414 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
415 | |||
411 | return IRQ_HANDLED; | 416 | return IRQ_HANDLED; |
412 | } | 417 | } |
413 | 418 | ||
@@ -455,7 +460,6 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) | |||
455 | static int tegra_kbc_start(struct tegra_kbc *kbc) | 460 | static int tegra_kbc_start(struct tegra_kbc *kbc) |
456 | { | 461 | { |
457 | const struct tegra_kbc_platform_data *pdata = kbc->pdata; | 462 | const struct tegra_kbc_platform_data *pdata = kbc->pdata; |
458 | unsigned long flags; | ||
459 | unsigned int debounce_cnt; | 463 | unsigned int debounce_cnt; |
460 | u32 val = 0; | 464 | u32 val = 0; |
461 | 465 | ||
@@ -493,7 +497,6 @@ static int tegra_kbc_start(struct tegra_kbc *kbc) | |||
493 | * Atomically clear out any remaining entries in the key FIFO | 497 | * Atomically clear out any remaining entries in the key FIFO |
494 | * and enable keyboard interrupts. | 498 | * and enable keyboard interrupts. |
495 | */ | 499 | */ |
496 | spin_lock_irqsave(&kbc->lock, flags); | ||
497 | while (1) { | 500 | while (1) { |
498 | val = readl(kbc->mmio + KBC_INT_0); | 501 | val = readl(kbc->mmio + KBC_INT_0); |
499 | val >>= 4; | 502 | val >>= 4; |
@@ -504,7 +507,6 @@ static int tegra_kbc_start(struct tegra_kbc *kbc) | |||
504 | val = readl(kbc->mmio + KBC_KP_ENT1_0); | 507 | val = readl(kbc->mmio + KBC_KP_ENT1_0); |
505 | } | 508 | } |
506 | writel(0x7, kbc->mmio + KBC_INT_0); | 509 | writel(0x7, kbc->mmio + KBC_INT_0); |
507 | spin_unlock_irqrestore(&kbc->lock, flags); | ||
508 | 510 | ||
509 | enable_irq(kbc->irq); | 511 | enable_irq(kbc->irq); |
510 | 512 | ||
@@ -734,18 +736,30 @@ static int tegra_kbc_suspend(struct device *dev) | |||
734 | struct platform_device *pdev = to_platform_device(dev); | 736 | struct platform_device *pdev = to_platform_device(dev); |
735 | struct tegra_kbc *kbc = platform_get_drvdata(pdev); | 737 | struct tegra_kbc *kbc = platform_get_drvdata(pdev); |
736 | 738 | ||
739 | mutex_lock(&kbc->idev->mutex); | ||
737 | if (device_may_wakeup(&pdev->dev)) { | 740 | if (device_may_wakeup(&pdev->dev)) { |
738 | tegra_kbc_setup_wakekeys(kbc, true); | 741 | disable_irq(kbc->irq); |
739 | enable_irq_wake(kbc->irq); | 742 | del_timer_sync(&kbc->timer); |
743 | tegra_kbc_set_fifo_interrupt(kbc, false); | ||
744 | |||
740 | /* Forcefully clear the interrupt status */ | 745 | /* Forcefully clear the interrupt status */ |
741 | writel(0x7, kbc->mmio + KBC_INT_0); | 746 | writel(0x7, kbc->mmio + KBC_INT_0); |
747 | /* | ||
748 | * Store the previous resident time of continuous polling mode. | ||
749 | * Force the keyboard into interrupt mode. | ||
750 | */ | ||
751 | kbc->cp_to_wkup_dly = readl(kbc->mmio + KBC_TO_CNT_0); | ||
752 | writel(0, kbc->mmio + KBC_TO_CNT_0); | ||
753 | |||
754 | tegra_kbc_setup_wakekeys(kbc, true); | ||
742 | msleep(30); | 755 | msleep(30); |
756 | |||
757 | enable_irq_wake(kbc->irq); | ||
743 | } else { | 758 | } else { |
744 | mutex_lock(&kbc->idev->mutex); | ||
745 | if (kbc->idev->users) | 759 | if (kbc->idev->users) |
746 | tegra_kbc_stop(kbc); | 760 | tegra_kbc_stop(kbc); |
747 | mutex_unlock(&kbc->idev->mutex); | ||
748 | } | 761 | } |
762 | mutex_unlock(&kbc->idev->mutex); | ||
749 | 763 | ||
750 | return 0; | 764 | return 0; |
751 | } | 765 | } |
@@ -756,15 +770,22 @@ static int tegra_kbc_resume(struct device *dev) | |||
756 | struct tegra_kbc *kbc = platform_get_drvdata(pdev); | 770 | struct tegra_kbc *kbc = platform_get_drvdata(pdev); |
757 | int err = 0; | 771 | int err = 0; |
758 | 772 | ||
773 | mutex_lock(&kbc->idev->mutex); | ||
759 | if (device_may_wakeup(&pdev->dev)) { | 774 | if (device_may_wakeup(&pdev->dev)) { |
760 | disable_irq_wake(kbc->irq); | 775 | disable_irq_wake(kbc->irq); |
761 | tegra_kbc_setup_wakekeys(kbc, false); | 776 | tegra_kbc_setup_wakekeys(kbc, false); |
777 | |||
778 | /* Restore the resident time of continuous polling mode. */ | ||
779 | writel(kbc->cp_to_wkup_dly, kbc->mmio + KBC_TO_CNT_0); | ||
780 | |||
781 | tegra_kbc_set_fifo_interrupt(kbc, true); | ||
782 | |||
783 | enable_irq(kbc->irq); | ||
762 | } else { | 784 | } else { |
763 | mutex_lock(&kbc->idev->mutex); | ||
764 | if (kbc->idev->users) | 785 | if (kbc->idev->users) |
765 | err = tegra_kbc_start(kbc); | 786 | err = tegra_kbc_start(kbc); |
766 | mutex_unlock(&kbc->idev->mutex); | ||
767 | } | 787 | } |
788 | mutex_unlock(&kbc->idev->mutex); | ||
768 | 789 | ||
769 | return err; | 790 | return err; |
770 | } | 791 | } |
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index ee2bf6bcf291..318586dadacf 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
@@ -203,7 +203,7 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | |||
203 | input_dev->keycode, input_dev->keybit); | 203 | input_dev->keycode, input_dev->keybit); |
204 | 204 | ||
205 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, | 205 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, |
206 | IRQF_DISABLED, pdev->name, keypad); | 206 | 0, pdev->name, keypad); |
207 | if (error) { | 207 | if (error) { |
208 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 208 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
209 | goto failed_put_clk; | 209 | goto failed_put_clk; |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index c9104bb4db06..a1aa35a053b7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -62,6 +62,17 @@ config INPUT_AD714X_SPI | |||
62 | To compile this driver as a module, choose M here: the | 62 | To compile this driver as a module, choose M here: the |
63 | module will be called ad714x-spi. | 63 | module will be called ad714x-spi. |
64 | 64 | ||
65 | config INPUT_BMA150 | ||
66 | tristate "BMA150/SMB380 acceleration sensor support" | ||
67 | depends on I2C | ||
68 | select INPUT_POLLDEV | ||
69 | help | ||
70 | Say Y here if you have Bosch Sensortec's BMA150 or SMB380 | ||
71 | acceleration sensor hooked to an I2C bus. | ||
72 | |||
73 | To compile this driver as a module, choose M here: the | ||
74 | module will be called bma150. | ||
75 | |||
65 | config INPUT_PCSPKR | 76 | config INPUT_PCSPKR |
66 | tristate "PC Speaker support" | 77 | tristate "PC Speaker support" |
67 | depends on PCSPKR_PLATFORM | 78 | depends on PCSPKR_PLATFORM |
@@ -74,6 +85,29 @@ config INPUT_PCSPKR | |||
74 | To compile this driver as a module, choose M here: the | 85 | To compile this driver as a module, choose M here: the |
75 | module will be called pcspkr. | 86 | module will be called pcspkr. |
76 | 87 | ||
88 | config INPUT_PM8XXX_VIBRATOR | ||
89 | tristate "Qualcomm PM8XXX vibrator support" | ||
90 | depends on MFD_PM8XXX | ||
91 | select INPUT_FF_MEMLESS | ||
92 | help | ||
93 | This option enables device driver support for the vibrator | ||
94 | on Qualcomm PM8xxx chip. This driver supports ff-memless interface | ||
95 | from input framework. | ||
96 | |||
97 | To compile this driver as module, choose M here: the | ||
98 | module will be called pm8xxx-vibrator. | ||
99 | |||
100 | config INPUT_PMIC8XXX_PWRKEY | ||
101 | tristate "PMIC8XXX power key support" | ||
102 | depends on MFD_PM8XXX | ||
103 | help | ||
104 | Say Y here if you want support for the PMIC8XXX power key. | ||
105 | |||
106 | If unsure, say N. | ||
107 | |||
108 | To compile this driver as a module, choose M here: the | ||
109 | module will be called pmic8xxx-pwrkey. | ||
110 | |||
77 | config INPUT_SPARCSPKR | 111 | config INPUT_SPARCSPKR |
78 | tristate "SPARC Speaker support" | 112 | tristate "SPARC Speaker support" |
79 | depends on PCI && SPARC64 | 113 | depends on PCI && SPARC64 |
@@ -379,17 +413,6 @@ config INPUT_PWM_BEEPER | |||
379 | To compile this driver as a module, choose M here: the module will be | 413 | To compile this driver as a module, choose M here: the module will be |
380 | called pwm-beeper. | 414 | called pwm-beeper. |
381 | 415 | ||
382 | config INPUT_PMIC8XXX_PWRKEY | ||
383 | tristate "PMIC8XXX power key support" | ||
384 | depends on MFD_PM8XXX | ||
385 | help | ||
386 | Say Y here if you want support for the PMIC8XXX power key. | ||
387 | |||
388 | If unsure, say N. | ||
389 | |||
390 | To compile this driver as a module, choose M here: the | ||
391 | module will be called pmic8xxx-pwrkey. | ||
392 | |||
393 | config INPUT_GPIO_ROTARY_ENCODER | 416 | config INPUT_GPIO_ROTARY_ENCODER |
394 | tristate "Rotary encoders connected to GPIO pins" | 417 | tristate "Rotary encoders connected to GPIO pins" |
395 | depends on GPIOLIB && GENERIC_GPIO | 418 | depends on GPIOLIB && GENERIC_GPIO |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 299ad5edba84..53a8d0faad52 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | |||
17 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 17 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
18 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 18 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
19 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | 19 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o |
20 | obj-$(CONFIG_INPUT_BMA150) += bma150.o | ||
20 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 21 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
21 | obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o | 22 | obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o |
22 | obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o | 23 | obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o |
@@ -34,9 +35,10 @@ obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o | |||
34 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o | 35 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o |
35 | obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o | 36 | obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o |
36 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | 37 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o |
38 | obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o | ||
39 | obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o | ||
37 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | 40 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o |
38 | obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o | 41 | obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o |
39 | obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o | ||
40 | obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o | 42 | obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o |
41 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o | 43 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o |
42 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | 44 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o |
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index 025417d74ca2..56810fb4eadd 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c | |||
@@ -116,13 +116,13 @@ static struct i2c_driver ad714x_i2c_driver = { | |||
116 | .id_table = ad714x_id, | 116 | .id_table = ad714x_id, |
117 | }; | 117 | }; |
118 | 118 | ||
119 | static __init int ad714x_i2c_init(void) | 119 | static int __init ad714x_i2c_init(void) |
120 | { | 120 | { |
121 | return i2c_add_driver(&ad714x_i2c_driver); | 121 | return i2c_add_driver(&ad714x_i2c_driver); |
122 | } | 122 | } |
123 | module_init(ad714x_i2c_init); | 123 | module_init(ad714x_i2c_init); |
124 | 124 | ||
125 | static __exit void ad714x_i2c_exit(void) | 125 | static void __exit ad714x_i2c_exit(void) |
126 | { | 126 | { |
127 | i2c_del_driver(&ad714x_i2c_driver); | 127 | i2c_del_driver(&ad714x_i2c_driver); |
128 | } | 128 | } |
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c new file mode 100644 index 000000000000..8f55b54352b6 --- /dev/null +++ b/drivers/input/misc/bma150.c | |||
@@ -0,0 +1,691 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Bosch Sensortec GmbH | ||
3 | * Copyright (c) 2011 Unixphere | ||
4 | * | ||
5 | * This driver adds support for Bosch Sensortec's digital acceleration | ||
6 | * sensors BMA150 and SMB380. | ||
7 | * The SMB380 is fully compatible with BMA150 and only differs in packaging. | ||
8 | * | ||
9 | * The datasheet for the BMA150 chip can be found here: | ||
10 | * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA150-DS000-07.pdf | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
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 | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/input.h> | ||
30 | #include <linux/input-polldev.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/pm.h> | ||
35 | #include <linux/pm_runtime.h> | ||
36 | #include <linux/bma150.h> | ||
37 | |||
38 | #define ABSMAX_ACC_VAL 0x01FF | ||
39 | #define ABSMIN_ACC_VAL -(ABSMAX_ACC_VAL) | ||
40 | |||
41 | /* Each axis is represented by a 2-byte data word */ | ||
42 | #define BMA150_XYZ_DATA_SIZE 6 | ||
43 | |||
44 | /* Input poll interval in milliseconds */ | ||
45 | #define BMA150_POLL_INTERVAL 10 | ||
46 | #define BMA150_POLL_MAX 200 | ||
47 | #define BMA150_POLL_MIN 0 | ||
48 | |||
49 | #define BMA150_BW_25HZ 0 | ||
50 | #define BMA150_BW_50HZ 1 | ||
51 | #define BMA150_BW_100HZ 2 | ||
52 | #define BMA150_BW_190HZ 3 | ||
53 | #define BMA150_BW_375HZ 4 | ||
54 | #define BMA150_BW_750HZ 5 | ||
55 | #define BMA150_BW_1500HZ 6 | ||
56 | |||
57 | #define BMA150_RANGE_2G 0 | ||
58 | #define BMA150_RANGE_4G 1 | ||
59 | #define BMA150_RANGE_8G 2 | ||
60 | |||
61 | #define BMA150_MODE_NORMAL 0 | ||
62 | #define BMA150_MODE_SLEEP 2 | ||
63 | #define BMA150_MODE_WAKE_UP 3 | ||
64 | |||
65 | /* Data register addresses */ | ||
66 | #define BMA150_DATA_0_REG 0x00 | ||
67 | #define BMA150_DATA_1_REG 0x01 | ||
68 | #define BMA150_DATA_2_REG 0x02 | ||
69 | |||
70 | /* Control register addresses */ | ||
71 | #define BMA150_CTRL_0_REG 0x0A | ||
72 | #define BMA150_CTRL_1_REG 0x0B | ||
73 | #define BMA150_CTRL_2_REG 0x14 | ||
74 | #define BMA150_CTRL_3_REG 0x15 | ||
75 | |||
76 | /* Configuration/Setting register addresses */ | ||
77 | #define BMA150_CFG_0_REG 0x0C | ||
78 | #define BMA150_CFG_1_REG 0x0D | ||
79 | #define BMA150_CFG_2_REG 0x0E | ||
80 | #define BMA150_CFG_3_REG 0x0F | ||
81 | #define BMA150_CFG_4_REG 0x10 | ||
82 | #define BMA150_CFG_5_REG 0x11 | ||
83 | |||
84 | #define BMA150_CHIP_ID 2 | ||
85 | #define BMA150_CHIP_ID_REG BMA150_DATA_0_REG | ||
86 | |||
87 | #define BMA150_ACC_X_LSB_REG BMA150_DATA_2_REG | ||
88 | |||
89 | #define BMA150_SLEEP_POS 0 | ||
90 | #define BMA150_SLEEP_MSK 0x01 | ||
91 | #define BMA150_SLEEP_REG BMA150_CTRL_0_REG | ||
92 | |||
93 | #define BMA150_BANDWIDTH_POS 0 | ||
94 | #define BMA150_BANDWIDTH_MSK 0x07 | ||
95 | #define BMA150_BANDWIDTH_REG BMA150_CTRL_2_REG | ||
96 | |||
97 | #define BMA150_RANGE_POS 3 | ||
98 | #define BMA150_RANGE_MSK 0x18 | ||
99 | #define BMA150_RANGE_REG BMA150_CTRL_2_REG | ||
100 | |||
101 | #define BMA150_WAKE_UP_POS 0 | ||
102 | #define BMA150_WAKE_UP_MSK 0x01 | ||
103 | #define BMA150_WAKE_UP_REG BMA150_CTRL_3_REG | ||
104 | |||
105 | #define BMA150_SW_RES_POS 1 | ||
106 | #define BMA150_SW_RES_MSK 0x02 | ||
107 | #define BMA150_SW_RES_REG BMA150_CTRL_0_REG | ||
108 | |||
109 | /* Any-motion interrupt register fields */ | ||
110 | #define BMA150_ANY_MOTION_EN_POS 6 | ||
111 | #define BMA150_ANY_MOTION_EN_MSK 0x40 | ||
112 | #define BMA150_ANY_MOTION_EN_REG BMA150_CTRL_1_REG | ||
113 | |||
114 | #define BMA150_ANY_MOTION_DUR_POS 6 | ||
115 | #define BMA150_ANY_MOTION_DUR_MSK 0xC0 | ||
116 | #define BMA150_ANY_MOTION_DUR_REG BMA150_CFG_5_REG | ||
117 | |||
118 | #define BMA150_ANY_MOTION_THRES_REG BMA150_CFG_4_REG | ||
119 | |||
120 | /* Advanced interrupt register fields */ | ||
121 | #define BMA150_ADV_INT_EN_POS 6 | ||
122 | #define BMA150_ADV_INT_EN_MSK 0x40 | ||
123 | #define BMA150_ADV_INT_EN_REG BMA150_CTRL_3_REG | ||
124 | |||
125 | /* High-G interrupt register fields */ | ||
126 | #define BMA150_HIGH_G_EN_POS 1 | ||
127 | #define BMA150_HIGH_G_EN_MSK 0x02 | ||
128 | #define BMA150_HIGH_G_EN_REG BMA150_CTRL_1_REG | ||
129 | |||
130 | #define BMA150_HIGH_G_HYST_POS 3 | ||
131 | #define BMA150_HIGH_G_HYST_MSK 0x38 | ||
132 | #define BMA150_HIGH_G_HYST_REG BMA150_CFG_5_REG | ||
133 | |||
134 | #define BMA150_HIGH_G_DUR_REG BMA150_CFG_3_REG | ||
135 | #define BMA150_HIGH_G_THRES_REG BMA150_CFG_2_REG | ||
136 | |||
137 | /* Low-G interrupt register fields */ | ||
138 | #define BMA150_LOW_G_EN_POS 0 | ||
139 | #define BMA150_LOW_G_EN_MSK 0x01 | ||
140 | #define BMA150_LOW_G_EN_REG BMA150_CTRL_1_REG | ||
141 | |||
142 | #define BMA150_LOW_G_HYST_POS 0 | ||
143 | #define BMA150_LOW_G_HYST_MSK 0x07 | ||
144 | #define BMA150_LOW_G_HYST_REG BMA150_CFG_5_REG | ||
145 | |||
146 | #define BMA150_LOW_G_DUR_REG BMA150_CFG_1_REG | ||
147 | #define BMA150_LOW_G_THRES_REG BMA150_CFG_0_REG | ||
148 | |||
149 | struct bma150_data { | ||
150 | struct i2c_client *client; | ||
151 | struct input_polled_dev *input_polled; | ||
152 | struct input_dev *input; | ||
153 | u8 mode; | ||
154 | }; | ||
155 | |||
156 | /* | ||
157 | * The settings for the given range, bandwidth and interrupt features | ||
158 | * are stated and verified by Bosch Sensortec where they are configured | ||
159 | * to provide a generic sensitivity performance. | ||
160 | */ | ||
161 | static struct bma150_cfg default_cfg __devinitdata = { | ||
162 | .any_motion_int = 1, | ||
163 | .hg_int = 1, | ||
164 | .lg_int = 1, | ||
165 | .any_motion_dur = 0, | ||
166 | .any_motion_thres = 0, | ||
167 | .hg_hyst = 0, | ||
168 | .hg_dur = 150, | ||
169 | .hg_thres = 160, | ||
170 | .lg_hyst = 0, | ||
171 | .lg_dur = 150, | ||
172 | .lg_thres = 20, | ||
173 | .range = BMA150_RANGE_2G, | ||
174 | .bandwidth = BMA150_BW_50HZ | ||
175 | }; | ||
176 | |||
177 | static int bma150_write_byte(struct i2c_client *client, u8 reg, u8 val) | ||
178 | { | ||
179 | s32 ret; | ||
180 | |||
181 | /* As per specification, disable irq in between register writes */ | ||
182 | if (client->irq) | ||
183 | disable_irq_nosync(client->irq); | ||
184 | |||
185 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
186 | |||
187 | if (client->irq) | ||
188 | enable_irq(client->irq); | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static int bma150_set_reg_bits(struct i2c_client *client, | ||
194 | int val, int shift, u8 mask, u8 reg) | ||
195 | { | ||
196 | int data; | ||
197 | |||
198 | data = i2c_smbus_read_byte_data(client, reg); | ||
199 | if (data < 0) | ||
200 | return data; | ||
201 | |||
202 | data = (data & ~mask) | ((val << shift) & mask); | ||
203 | return bma150_write_byte(client, reg, data); | ||
204 | } | ||
205 | |||
206 | static int bma150_set_mode(struct bma150_data *bma150, u8 mode) | ||
207 | { | ||
208 | int error; | ||
209 | |||
210 | error = bma150_set_reg_bits(bma150->client, mode, BMA150_WAKE_UP_POS, | ||
211 | BMA150_WAKE_UP_MSK, BMA150_WAKE_UP_REG); | ||
212 | if (error) | ||
213 | return error; | ||
214 | |||
215 | error = bma150_set_reg_bits(bma150->client, mode, BMA150_SLEEP_POS, | ||
216 | BMA150_SLEEP_MSK, BMA150_SLEEP_REG); | ||
217 | if (error) | ||
218 | return error; | ||
219 | |||
220 | if (mode == BMA150_MODE_NORMAL) | ||
221 | msleep(2); | ||
222 | |||
223 | bma150->mode = mode; | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int __devinit bma150_soft_reset(struct bma150_data *bma150) | ||
228 | { | ||
229 | int error; | ||
230 | |||
231 | error = bma150_set_reg_bits(bma150->client, 1, BMA150_SW_RES_POS, | ||
232 | BMA150_SW_RES_MSK, BMA150_SW_RES_REG); | ||
233 | if (error) | ||
234 | return error; | ||
235 | |||
236 | msleep(2); | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int __devinit bma150_set_range(struct bma150_data *bma150, u8 range) | ||
241 | { | ||
242 | return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS, | ||
243 | BMA150_RANGE_MSK, BMA150_RANGE_REG); | ||
244 | } | ||
245 | |||
246 | static int __devinit bma150_set_bandwidth(struct bma150_data *bma150, u8 bw) | ||
247 | { | ||
248 | return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS, | ||
249 | BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG); | ||
250 | } | ||
251 | |||
252 | static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150, | ||
253 | u8 enable, u8 hyst, u8 dur, u8 thres) | ||
254 | { | ||
255 | int error; | ||
256 | |||
257 | error = bma150_set_reg_bits(bma150->client, hyst, | ||
258 | BMA150_LOW_G_HYST_POS, BMA150_LOW_G_HYST_MSK, | ||
259 | BMA150_LOW_G_HYST_REG); | ||
260 | if (error) | ||
261 | return error; | ||
262 | |||
263 | error = bma150_write_byte(bma150->client, BMA150_LOW_G_DUR_REG, dur); | ||
264 | if (error) | ||
265 | return error; | ||
266 | |||
267 | error = bma150_write_byte(bma150->client, BMA150_LOW_G_THRES_REG, thres); | ||
268 | if (error) | ||
269 | return error; | ||
270 | |||
271 | return bma150_set_reg_bits(bma150->client, !!enable, | ||
272 | BMA150_LOW_G_EN_POS, BMA150_LOW_G_EN_MSK, | ||
273 | BMA150_LOW_G_EN_REG); | ||
274 | } | ||
275 | |||
276 | static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150, | ||
277 | u8 enable, u8 hyst, u8 dur, u8 thres) | ||
278 | { | ||
279 | int error; | ||
280 | |||
281 | error = bma150_set_reg_bits(bma150->client, hyst, | ||
282 | BMA150_HIGH_G_HYST_POS, BMA150_HIGH_G_HYST_MSK, | ||
283 | BMA150_HIGH_G_HYST_REG); | ||
284 | if (error) | ||
285 | return error; | ||
286 | |||
287 | error = bma150_write_byte(bma150->client, | ||
288 | BMA150_HIGH_G_DUR_REG, dur); | ||
289 | if (error) | ||
290 | return error; | ||
291 | |||
292 | error = bma150_write_byte(bma150->client, | ||
293 | BMA150_HIGH_G_THRES_REG, thres); | ||
294 | if (error) | ||
295 | return error; | ||
296 | |||
297 | return bma150_set_reg_bits(bma150->client, !!enable, | ||
298 | BMA150_HIGH_G_EN_POS, BMA150_HIGH_G_EN_MSK, | ||
299 | BMA150_HIGH_G_EN_REG); | ||
300 | } | ||
301 | |||
302 | |||
303 | static int __devinit bma150_set_any_motion_interrupt(struct bma150_data *bma150, | ||
304 | u8 enable, u8 dur, u8 thres) | ||
305 | { | ||
306 | int error; | ||
307 | |||
308 | error = bma150_set_reg_bits(bma150->client, dur, | ||
309 | BMA150_ANY_MOTION_DUR_POS, | ||
310 | BMA150_ANY_MOTION_DUR_MSK, | ||
311 | BMA150_ANY_MOTION_DUR_REG); | ||
312 | if (error) | ||
313 | return error; | ||
314 | |||
315 | error = bma150_write_byte(bma150->client, | ||
316 | BMA150_ANY_MOTION_THRES_REG, thres); | ||
317 | if (error) | ||
318 | return error; | ||
319 | |||
320 | error = bma150_set_reg_bits(bma150->client, !!enable, | ||
321 | BMA150_ADV_INT_EN_POS, BMA150_ADV_INT_EN_MSK, | ||
322 | BMA150_ADV_INT_EN_REG); | ||
323 | if (error) | ||
324 | return error; | ||
325 | |||
326 | return bma150_set_reg_bits(bma150->client, !!enable, | ||
327 | BMA150_ANY_MOTION_EN_POS, | ||
328 | BMA150_ANY_MOTION_EN_MSK, | ||
329 | BMA150_ANY_MOTION_EN_REG); | ||
330 | } | ||
331 | |||
332 | static void bma150_report_xyz(struct bma150_data *bma150) | ||
333 | { | ||
334 | u8 data[BMA150_XYZ_DATA_SIZE]; | ||
335 | s16 x, y, z; | ||
336 | s32 ret; | ||
337 | |||
338 | ret = i2c_smbus_read_i2c_block_data(bma150->client, | ||
339 | BMA150_ACC_X_LSB_REG, BMA150_XYZ_DATA_SIZE, data); | ||
340 | if (ret != BMA150_XYZ_DATA_SIZE) | ||
341 | return; | ||
342 | |||
343 | x = ((0xc0 & data[0]) >> 6) | (data[1] << 2); | ||
344 | y = ((0xc0 & data[2]) >> 6) | (data[3] << 2); | ||
345 | z = ((0xc0 & data[4]) >> 6) | (data[5] << 2); | ||
346 | |||
347 | /* sign extension */ | ||
348 | x = (s16) (x << 6) >> 6; | ||
349 | y = (s16) (y << 6) >> 6; | ||
350 | z = (s16) (z << 6) >> 6; | ||
351 | |||
352 | input_report_abs(bma150->input, ABS_X, x); | ||
353 | input_report_abs(bma150->input, ABS_Y, y); | ||
354 | input_report_abs(bma150->input, ABS_Z, z); | ||
355 | input_sync(bma150->input); | ||
356 | } | ||
357 | |||
358 | static irqreturn_t bma150_irq_thread(int irq, void *dev) | ||
359 | { | ||
360 | bma150_report_xyz(dev); | ||
361 | |||
362 | return IRQ_HANDLED; | ||
363 | } | ||
364 | |||
365 | static void bma150_poll(struct input_polled_dev *dev) | ||
366 | { | ||
367 | bma150_report_xyz(dev->private); | ||
368 | } | ||
369 | |||
370 | static int bma150_open(struct bma150_data *bma150) | ||
371 | { | ||
372 | int error; | ||
373 | |||
374 | error = pm_runtime_get_sync(&bma150->client->dev); | ||
375 | if (error && error != -ENOSYS) | ||
376 | return error; | ||
377 | |||
378 | /* | ||
379 | * See if runtime PM woke up the device. If runtime PM | ||
380 | * is disabled we need to do it ourselves. | ||
381 | */ | ||
382 | if (bma150->mode != BMA150_MODE_NORMAL) { | ||
383 | error = bma150_set_mode(bma150, BMA150_MODE_NORMAL); | ||
384 | if (error) | ||
385 | return error; | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static void bma150_close(struct bma150_data *bma150) | ||
392 | { | ||
393 | pm_runtime_put_sync(&bma150->client->dev); | ||
394 | |||
395 | if (bma150->mode != BMA150_MODE_SLEEP) | ||
396 | bma150_set_mode(bma150, BMA150_MODE_SLEEP); | ||
397 | } | ||
398 | |||
399 | static int bma150_irq_open(struct input_dev *input) | ||
400 | { | ||
401 | struct bma150_data *bma150 = input_get_drvdata(input); | ||
402 | |||
403 | return bma150_open(bma150); | ||
404 | } | ||
405 | |||
406 | static void bma150_irq_close(struct input_dev *input) | ||
407 | { | ||
408 | struct bma150_data *bma150 = input_get_drvdata(input); | ||
409 | |||
410 | bma150_close(bma150); | ||
411 | } | ||
412 | |||
413 | static void bma150_poll_open(struct input_polled_dev *ipoll_dev) | ||
414 | { | ||
415 | struct bma150_data *bma150 = ipoll_dev->private; | ||
416 | |||
417 | bma150_open(bma150); | ||
418 | } | ||
419 | |||
420 | static void bma150_poll_close(struct input_polled_dev *ipoll_dev) | ||
421 | { | ||
422 | struct bma150_data *bma150 = ipoll_dev->private; | ||
423 | |||
424 | bma150_close(bma150); | ||
425 | } | ||
426 | |||
427 | static int __devinit bma150_initialize(struct bma150_data *bma150, | ||
428 | const struct bma150_cfg *cfg) | ||
429 | { | ||
430 | int error; | ||
431 | |||
432 | error = bma150_soft_reset(bma150); | ||
433 | if (error) | ||
434 | return error; | ||
435 | |||
436 | error = bma150_set_bandwidth(bma150, cfg->bandwidth); | ||
437 | if (error) | ||
438 | return error; | ||
439 | |||
440 | error = bma150_set_range(bma150, cfg->range); | ||
441 | if (error) | ||
442 | return error; | ||
443 | |||
444 | if (bma150->client->irq) { | ||
445 | error = bma150_set_any_motion_interrupt(bma150, | ||
446 | cfg->any_motion_int, | ||
447 | cfg->any_motion_dur, | ||
448 | cfg->any_motion_thres); | ||
449 | if (error) | ||
450 | return error; | ||
451 | |||
452 | error = bma150_set_high_g_interrupt(bma150, | ||
453 | cfg->hg_int, cfg->hg_hyst, | ||
454 | cfg->hg_dur, cfg->hg_thres); | ||
455 | if (error) | ||
456 | return error; | ||
457 | |||
458 | error = bma150_set_low_g_interrupt(bma150, | ||
459 | cfg->lg_int, cfg->lg_hyst, | ||
460 | cfg->lg_dur, cfg->lg_thres); | ||
461 | if (error) | ||
462 | return error; | ||
463 | } | ||
464 | |||
465 | return bma150_set_mode(bma150, BMA150_MODE_SLEEP); | ||
466 | } | ||
467 | |||
468 | static void __devinit bma150_init_input_device(struct bma150_data *bma150, | ||
469 | struct input_dev *idev) | ||
470 | { | ||
471 | idev->name = BMA150_DRIVER; | ||
472 | idev->phys = BMA150_DRIVER "/input0"; | ||
473 | idev->id.bustype = BUS_I2C; | ||
474 | idev->dev.parent = &bma150->client->dev; | ||
475 | |||
476 | idev->evbit[0] = BIT_MASK(EV_ABS); | ||
477 | input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); | ||
478 | input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); | ||
479 | input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); | ||
480 | } | ||
481 | |||
482 | static int __devinit bma150_register_input_device(struct bma150_data *bma150) | ||
483 | { | ||
484 | struct input_dev *idev; | ||
485 | int error; | ||
486 | |||
487 | idev = input_allocate_device(); | ||
488 | if (!idev) | ||
489 | return -ENOMEM; | ||
490 | |||
491 | bma150_init_input_device(bma150, idev); | ||
492 | |||
493 | idev->open = bma150_irq_open; | ||
494 | idev->close = bma150_irq_close; | ||
495 | input_set_drvdata(idev, bma150); | ||
496 | |||
497 | error = input_register_device(idev); | ||
498 | if (error) { | ||
499 | input_free_device(idev); | ||
500 | return error; | ||
501 | } | ||
502 | |||
503 | bma150->input = idev; | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static int __devinit bma150_register_polled_device(struct bma150_data *bma150) | ||
508 | { | ||
509 | struct input_polled_dev *ipoll_dev; | ||
510 | int error; | ||
511 | |||
512 | ipoll_dev = input_allocate_polled_device(); | ||
513 | if (!ipoll_dev) | ||
514 | return -ENOMEM; | ||
515 | |||
516 | ipoll_dev->private = bma150; | ||
517 | ipoll_dev->open = bma150_poll_open; | ||
518 | ipoll_dev->close = bma150_poll_close; | ||
519 | ipoll_dev->poll = bma150_poll; | ||
520 | ipoll_dev->poll_interval = BMA150_POLL_INTERVAL; | ||
521 | ipoll_dev->poll_interval_min = BMA150_POLL_MIN; | ||
522 | ipoll_dev->poll_interval_max = BMA150_POLL_MAX; | ||
523 | |||
524 | bma150_init_input_device(bma150, ipoll_dev->input); | ||
525 | |||
526 | error = input_register_polled_device(ipoll_dev); | ||
527 | if (error) { | ||
528 | input_free_polled_device(ipoll_dev); | ||
529 | return error; | ||
530 | } | ||
531 | |||
532 | bma150->input_polled = ipoll_dev; | ||
533 | bma150->input = ipoll_dev->input; | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int __devinit bma150_probe(struct i2c_client *client, | ||
539 | const struct i2c_device_id *id) | ||
540 | { | ||
541 | const struct bma150_platform_data *pdata = client->dev.platform_data; | ||
542 | const struct bma150_cfg *cfg; | ||
543 | struct bma150_data *bma150; | ||
544 | int chip_id; | ||
545 | int error; | ||
546 | |||
547 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
548 | dev_err(&client->dev, "i2c_check_functionality error\n"); | ||
549 | return -EIO; | ||
550 | } | ||
551 | |||
552 | chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG); | ||
553 | if (chip_id != BMA150_CHIP_ID) { | ||
554 | dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id); | ||
555 | return -EINVAL; | ||
556 | } | ||
557 | |||
558 | bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL); | ||
559 | if (!bma150) | ||
560 | return -ENOMEM; | ||
561 | |||
562 | bma150->client = client; | ||
563 | |||
564 | if (pdata) { | ||
565 | if (pdata->irq_gpio_cfg) { | ||
566 | error = pdata->irq_gpio_cfg(); | ||
567 | if (error) { | ||
568 | dev_err(&client->dev, | ||
569 | "IRQ GPIO conf. error %d, error %d\n", | ||
570 | client->irq, error); | ||
571 | goto err_free_mem; | ||
572 | } | ||
573 | } | ||
574 | cfg = &pdata->cfg; | ||
575 | } else { | ||
576 | cfg = &default_cfg; | ||
577 | } | ||
578 | |||
579 | error = bma150_initialize(bma150, cfg); | ||
580 | if (error) | ||
581 | goto err_free_mem; | ||
582 | |||
583 | if (client->irq > 0) { | ||
584 | error = bma150_register_input_device(bma150); | ||
585 | if (error) | ||
586 | goto err_free_mem; | ||
587 | |||
588 | error = request_threaded_irq(client->irq, | ||
589 | NULL, bma150_irq_thread, | ||
590 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
591 | BMA150_DRIVER, bma150); | ||
592 | if (error) { | ||
593 | dev_err(&client->dev, | ||
594 | "irq request failed %d, error %d\n", | ||
595 | client->irq, error); | ||
596 | input_unregister_device(bma150->input); | ||
597 | goto err_free_mem; | ||
598 | } | ||
599 | } else { | ||
600 | error = bma150_register_polled_device(bma150); | ||
601 | if (error) | ||
602 | goto err_free_mem; | ||
603 | } | ||
604 | |||
605 | i2c_set_clientdata(client, bma150); | ||
606 | |||
607 | pm_runtime_enable(&client->dev); | ||
608 | |||
609 | return 0; | ||
610 | |||
611 | err_free_mem: | ||
612 | kfree(bma150); | ||
613 | return error; | ||
614 | } | ||
615 | |||
616 | static int __devexit bma150_remove(struct i2c_client *client) | ||
617 | { | ||
618 | struct bma150_data *bma150 = i2c_get_clientdata(client); | ||
619 | |||
620 | pm_runtime_disable(&client->dev); | ||
621 | |||
622 | if (client->irq > 0) { | ||
623 | free_irq(client->irq, bma150); | ||
624 | input_unregister_device(bma150->input); | ||
625 | } else { | ||
626 | input_unregister_polled_device(bma150->input_polled); | ||
627 | input_free_polled_device(bma150->input_polled); | ||
628 | } | ||
629 | |||
630 | kfree(bma150); | ||
631 | |||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | #ifdef CONFIG_PM | ||
636 | static int bma150_suspend(struct device *dev) | ||
637 | { | ||
638 | struct i2c_client *client = to_i2c_client(dev); | ||
639 | struct bma150_data *bma150 = i2c_get_clientdata(client); | ||
640 | |||
641 | return bma150_set_mode(bma150, BMA150_MODE_SLEEP); | ||
642 | } | ||
643 | |||
644 | static int bma150_resume(struct device *dev) | ||
645 | { | ||
646 | struct i2c_client *client = to_i2c_client(dev); | ||
647 | struct bma150_data *bma150 = i2c_get_clientdata(client); | ||
648 | |||
649 | return bma150_set_mode(bma150, BMA150_MODE_NORMAL); | ||
650 | } | ||
651 | #endif | ||
652 | |||
653 | static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); | ||
654 | |||
655 | static const struct i2c_device_id bma150_id[] = { | ||
656 | { "bma150", 0 }, | ||
657 | { "smb380", 0 }, | ||
658 | { "bma023", 0 }, | ||
659 | { } | ||
660 | }; | ||
661 | |||
662 | MODULE_DEVICE_TABLE(i2c, bma150_id); | ||
663 | |||
664 | static struct i2c_driver bma150_driver = { | ||
665 | .driver = { | ||
666 | .owner = THIS_MODULE, | ||
667 | .name = BMA150_DRIVER, | ||
668 | .pm = &bma150_pm, | ||
669 | }, | ||
670 | .class = I2C_CLASS_HWMON, | ||
671 | .id_table = bma150_id, | ||
672 | .probe = bma150_probe, | ||
673 | .remove = __devexit_p(bma150_remove), | ||
674 | }; | ||
675 | |||
676 | static int __init BMA150_init(void) | ||
677 | { | ||
678 | return i2c_add_driver(&bma150_driver); | ||
679 | } | ||
680 | |||
681 | static void __exit BMA150_exit(void) | ||
682 | { | ||
683 | i2c_del_driver(&bma150_driver); | ||
684 | } | ||
685 | |||
686 | MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>"); | ||
687 | MODULE_DESCRIPTION("BMA150 driver"); | ||
688 | MODULE_LICENSE("GPL"); | ||
689 | |||
690 | module_init(BMA150_init); | ||
691 | module_exit(BMA150_exit); | ||
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index 1f38302a5951..302ab46ce752 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c | |||
@@ -111,7 +111,7 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev) | |||
111 | input_dev->event = ixp4xx_spkr_event; | 111 | input_dev->event = ixp4xx_spkr_event; |
112 | 112 | ||
113 | err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt, | 113 | err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt, |
114 | IRQF_DISABLED | IRQF_NO_SUSPEND, "ixp4xx-beeper", | 114 | IRQF_NO_SUSPEND, "ixp4xx-beeper", |
115 | (void *) dev->id); | 115 | (void *) dev->id); |
116 | if (err) | 116 | if (err) |
117 | goto err_free_device; | 117 | goto err_free_device; |
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 0794778295fc..4d60080bb5d5 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c | |||
@@ -88,13 +88,13 @@ static int mma8450_write(struct mma8450 *m, unsigned off, u8 v) | |||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z) | 91 | static int mma8450_read_block(struct mma8450 *m, unsigned off, |
92 | u8 *buf, size_t size) | ||
92 | { | 93 | { |
93 | struct i2c_client *c = m->client; | 94 | struct i2c_client *c = m->client; |
94 | u8 buff[6]; | ||
95 | int err; | 95 | int err; |
96 | 96 | ||
97 | err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff); | 97 | err = i2c_smbus_read_i2c_block_data(c, off, size, buf); |
98 | if (err < 0) { | 98 | if (err < 0) { |
99 | dev_err(&c->dev, | 99 | dev_err(&c->dev, |
100 | "failed to read block data at 0x%02x, error %d\n", | 100 | "failed to read block data at 0x%02x, error %d\n", |
@@ -102,10 +102,6 @@ static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z) | |||
102 | return err; | 102 | return err; |
103 | } | 103 | } |
104 | 104 | ||
105 | *x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf); | ||
106 | *y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf); | ||
107 | *z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf); | ||
108 | |||
109 | return 0; | 105 | return 0; |
110 | } | 106 | } |
111 | 107 | ||
@@ -114,7 +110,7 @@ static void mma8450_poll(struct input_polled_dev *dev) | |||
114 | struct mma8450 *m = dev->private; | 110 | struct mma8450 *m = dev->private; |
115 | int x, y, z; | 111 | int x, y, z; |
116 | int ret; | 112 | int ret; |
117 | int err; | 113 | u8 buf[6]; |
118 | 114 | ||
119 | ret = mma8450_read(m, MMA8450_STATUS); | 115 | ret = mma8450_read(m, MMA8450_STATUS); |
120 | if (ret < 0) | 116 | if (ret < 0) |
@@ -123,10 +119,14 @@ static void mma8450_poll(struct input_polled_dev *dev) | |||
123 | if (!(ret & MMA8450_STATUS_ZXYDR)) | 119 | if (!(ret & MMA8450_STATUS_ZXYDR)) |
124 | return; | 120 | return; |
125 | 121 | ||
126 | err = mma8450_read_xyz(m, &x, &y, &z); | 122 | ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf)); |
127 | if (err) | 123 | if (ret < 0) |
128 | return; | 124 | return; |
129 | 125 | ||
126 | x = ((buf[1] << 4) & 0xff0) | (buf[0] & 0xf); | ||
127 | y = ((buf[3] << 4) & 0xff0) | (buf[2] & 0xf); | ||
128 | z = ((buf[5] << 4) & 0xff0) | (buf[4] & 0xf); | ||
129 | |||
130 | input_report_abs(dev->input, ABS_X, x); | 130 | input_report_abs(dev->input, ABS_X, x); |
131 | input_report_abs(dev->input, ABS_Y, y); | 131 | input_report_abs(dev->input, ABS_Y, y); |
132 | input_report_abs(dev->input, ABS_Z, z); | 132 | input_report_abs(dev->input, ABS_Z, z); |
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c new file mode 100644 index 000000000000..43192930824b --- /dev/null +++ b/drivers/input/misc/pm8xxx-vibrator.c | |||
@@ -0,0 +1,296 @@ | |||
1 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/mfd/pm8xxx/core.h> | ||
21 | |||
22 | #define VIB_DRV 0x4A | ||
23 | |||
24 | #define VIB_DRV_SEL_MASK 0xf8 | ||
25 | #define VIB_DRV_SEL_SHIFT 0x03 | ||
26 | #define VIB_DRV_EN_MANUAL_MASK 0xfc | ||
27 | |||
28 | #define VIB_MAX_LEVEL_mV (3100) | ||
29 | #define VIB_MIN_LEVEL_mV (1200) | ||
30 | #define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV) | ||
31 | |||
32 | #define MAX_FF_SPEED 0xff | ||
33 | |||
34 | /** | ||
35 | * struct pm8xxx_vib - structure to hold vibrator data | ||
36 | * @vib_input_dev: input device supporting force feedback | ||
37 | * @work: work structure to set the vibration parameters | ||
38 | * @dev: device supporting force feedback | ||
39 | * @speed: speed of vibration set from userland | ||
40 | * @active: state of vibrator | ||
41 | * @level: level of vibration to set in the chip | ||
42 | * @reg_vib_drv: VIB_DRV register value | ||
43 | */ | ||
44 | struct pm8xxx_vib { | ||
45 | struct input_dev *vib_input_dev; | ||
46 | struct work_struct work; | ||
47 | struct device *dev; | ||
48 | int speed; | ||
49 | int level; | ||
50 | bool active; | ||
51 | u8 reg_vib_drv; | ||
52 | }; | ||
53 | |||
54 | /** | ||
55 | * pm8xxx_vib_read_u8 - helper to read a byte from pmic chip | ||
56 | * @vib: pointer to vibrator structure | ||
57 | * @data: placeholder for data to be read | ||
58 | * @reg: register address | ||
59 | */ | ||
60 | static int pm8xxx_vib_read_u8(struct pm8xxx_vib *vib, | ||
61 | u8 *data, u16 reg) | ||
62 | { | ||
63 | int rc; | ||
64 | |||
65 | rc = pm8xxx_readb(vib->dev->parent, reg, data); | ||
66 | if (rc < 0) | ||
67 | dev_warn(vib->dev, "Error reading pm8xxx reg 0x%x(0x%x)\n", | ||
68 | reg, rc); | ||
69 | return rc; | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * pm8xxx_vib_write_u8 - helper to write a byte to pmic chip | ||
74 | * @vib: pointer to vibrator structure | ||
75 | * @data: data to write | ||
76 | * @reg: register address | ||
77 | */ | ||
78 | static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib, | ||
79 | u8 data, u16 reg) | ||
80 | { | ||
81 | int rc; | ||
82 | |||
83 | rc = pm8xxx_writeb(vib->dev->parent, reg, data); | ||
84 | if (rc < 0) | ||
85 | dev_warn(vib->dev, "Error writing pm8xxx reg 0x%x(0x%x)\n", | ||
86 | reg, rc); | ||
87 | return rc; | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * pm8xxx_vib_set - handler to start/stop vibration | ||
92 | * @vib: pointer to vibrator structure | ||
93 | * @on: state to set | ||
94 | */ | ||
95 | static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on) | ||
96 | { | ||
97 | int rc; | ||
98 | u8 val = vib->reg_vib_drv; | ||
99 | |||
100 | if (on) | ||
101 | val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK); | ||
102 | else | ||
103 | val &= ~VIB_DRV_SEL_MASK; | ||
104 | |||
105 | rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV); | ||
106 | if (rc < 0) | ||
107 | return rc; | ||
108 | |||
109 | vib->reg_vib_drv = val; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * pm8xxx_work_handler - worker to set vibration level | ||
115 | * @work: pointer to work_struct | ||
116 | */ | ||
117 | static void pm8xxx_work_handler(struct work_struct *work) | ||
118 | { | ||
119 | struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work); | ||
120 | int rc; | ||
121 | u8 val; | ||
122 | |||
123 | rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); | ||
124 | if (rc < 0) | ||
125 | return; | ||
126 | |||
127 | /* | ||
128 | * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so | ||
129 | * scale the level to fit into these ranges. | ||
130 | */ | ||
131 | if (vib->speed) { | ||
132 | vib->active = true; | ||
133 | vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) + | ||
134 | VIB_MIN_LEVEL_mV; | ||
135 | vib->level /= 100; | ||
136 | } else { | ||
137 | vib->active = false; | ||
138 | vib->level = VIB_MIN_LEVEL_mV / 100; | ||
139 | } | ||
140 | |||
141 | pm8xxx_vib_set(vib, vib->active); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * pm8xxx_vib_close - callback of input close callback | ||
146 | * @dev: input device pointer | ||
147 | * | ||
148 | * Turns off the vibrator. | ||
149 | */ | ||
150 | static void pm8xxx_vib_close(struct input_dev *dev) | ||
151 | { | ||
152 | struct pm8xxx_vib *vib = input_get_drvdata(dev); | ||
153 | |||
154 | cancel_work_sync(&vib->work); | ||
155 | if (vib->active) | ||
156 | pm8xxx_vib_set(vib, false); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * pm8xxx_vib_play_effect - function to handle vib effects. | ||
161 | * @dev: input device pointer | ||
162 | * @data: data of effect | ||
163 | * @effect: effect to play | ||
164 | * | ||
165 | * Currently this driver supports only rumble effects. | ||
166 | */ | ||
167 | static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data, | ||
168 | struct ff_effect *effect) | ||
169 | { | ||
170 | struct pm8xxx_vib *vib = input_get_drvdata(dev); | ||
171 | |||
172 | vib->speed = effect->u.rumble.strong_magnitude >> 8; | ||
173 | if (!vib->speed) | ||
174 | vib->speed = effect->u.rumble.weak_magnitude >> 9; | ||
175 | |||
176 | schedule_work(&vib->work); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static int __devinit pm8xxx_vib_probe(struct platform_device *pdev) | ||
182 | |||
183 | { | ||
184 | struct pm8xxx_vib *vib; | ||
185 | struct input_dev *input_dev; | ||
186 | int error; | ||
187 | u8 val; | ||
188 | |||
189 | vib = kzalloc(sizeof(*vib), GFP_KERNEL); | ||
190 | input_dev = input_allocate_device(); | ||
191 | if (!vib || !input_dev) { | ||
192 | dev_err(&pdev->dev, "couldn't allocate memory\n"); | ||
193 | error = -ENOMEM; | ||
194 | goto err_free_mem; | ||
195 | } | ||
196 | |||
197 | INIT_WORK(&vib->work, pm8xxx_work_handler); | ||
198 | vib->dev = &pdev->dev; | ||
199 | vib->vib_input_dev = input_dev; | ||
200 | |||
201 | /* operate in manual mode */ | ||
202 | error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); | ||
203 | if (error < 0) | ||
204 | goto err_free_mem; | ||
205 | val &= ~VIB_DRV_EN_MANUAL_MASK; | ||
206 | error = pm8xxx_vib_write_u8(vib, val, VIB_DRV); | ||
207 | if (error < 0) | ||
208 | goto err_free_mem; | ||
209 | |||
210 | vib->reg_vib_drv = val; | ||
211 | |||
212 | input_dev->name = "pm8xxx_vib_ffmemless"; | ||
213 | input_dev->id.version = 1; | ||
214 | input_dev->dev.parent = &pdev->dev; | ||
215 | input_dev->close = pm8xxx_vib_close; | ||
216 | input_set_drvdata(input_dev, vib); | ||
217 | input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE); | ||
218 | |||
219 | error = input_ff_create_memless(input_dev, NULL, | ||
220 | pm8xxx_vib_play_effect); | ||
221 | if (error) { | ||
222 | dev_err(&pdev->dev, | ||
223 | "couldn't register vibrator as FF device\n"); | ||
224 | goto err_free_mem; | ||
225 | } | ||
226 | |||
227 | error = input_register_device(input_dev); | ||
228 | if (error) { | ||
229 | dev_err(&pdev->dev, "couldn't register input device\n"); | ||
230 | goto err_destroy_memless; | ||
231 | } | ||
232 | |||
233 | platform_set_drvdata(pdev, vib); | ||
234 | return 0; | ||
235 | |||
236 | err_destroy_memless: | ||
237 | input_ff_destroy(input_dev); | ||
238 | err_free_mem: | ||
239 | input_free_device(input_dev); | ||
240 | kfree(vib); | ||
241 | |||
242 | return error; | ||
243 | } | ||
244 | |||
245 | static int __devexit pm8xxx_vib_remove(struct platform_device *pdev) | ||
246 | { | ||
247 | struct pm8xxx_vib *vib = platform_get_drvdata(pdev); | ||
248 | |||
249 | input_unregister_device(vib->vib_input_dev); | ||
250 | kfree(vib); | ||
251 | |||
252 | platform_set_drvdata(pdev, NULL); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | #ifdef CONFIG_PM_SLEEP | ||
258 | static int pm8xxx_vib_suspend(struct device *dev) | ||
259 | { | ||
260 | struct pm8xxx_vib *vib = dev_get_drvdata(dev); | ||
261 | |||
262 | /* Turn off the vibrator */ | ||
263 | pm8xxx_vib_set(vib, false); | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | #endif | ||
268 | |||
269 | static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); | ||
270 | |||
271 | static struct platform_driver pm8xxx_vib_driver = { | ||
272 | .probe = pm8xxx_vib_probe, | ||
273 | .remove = __devexit_p(pm8xxx_vib_remove), | ||
274 | .driver = { | ||
275 | .name = "pm8xxx-vib", | ||
276 | .owner = THIS_MODULE, | ||
277 | .pm = &pm8xxx_vib_pm_ops, | ||
278 | }, | ||
279 | }; | ||
280 | |||
281 | static int __init pm8xxx_vib_init(void) | ||
282 | { | ||
283 | return platform_driver_register(&pm8xxx_vib_driver); | ||
284 | } | ||
285 | module_init(pm8xxx_vib_init); | ||
286 | |||
287 | static void __exit pm8xxx_vib_exit(void) | ||
288 | { | ||
289 | platform_driver_unregister(&pm8xxx_vib_driver); | ||
290 | } | ||
291 | module_exit(pm8xxx_vib_exit); | ||
292 | |||
293 | MODULE_ALIAS("platform:pm8xxx_vib"); | ||
294 | MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework"); | ||
295 | MODULE_LICENSE("GPL v2"); | ||
296 | MODULE_AUTHOR("Amy Maloche <amaloche@codeaurora.org>"); | ||
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index c43002e7ec72..23855e12a30b 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c | |||
@@ -228,7 +228,7 @@ static void twl6040_vibra_close(struct input_dev *input) | |||
228 | mutex_unlock(&info->mutex); | 228 | mutex_unlock(&info->mutex); |
229 | } | 229 | } |
230 | 230 | ||
231 | #if CONFIG_PM_SLEEP | 231 | #ifdef CONFIG_PM_SLEEP |
232 | static int twl6040_vibra_suspend(struct device *dev) | 232 | static int twl6040_vibra_suspend(struct device *dev) |
233 | { | 233 | { |
234 | struct platform_device *pdev = to_platform_device(dev); | 234 | struct platform_device *pdev = to_platform_device(dev); |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 99d58764ef03..003587c71f43 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -23,13 +23,6 @@ | |||
23 | #include "psmouse.h" | 23 | #include "psmouse.h" |
24 | #include "alps.h" | 24 | #include "alps.h" |
25 | 25 | ||
26 | #undef DEBUG | ||
27 | #ifdef DEBUG | ||
28 | #define dbg(format, arg...) printk(KERN_INFO "alps.c: " format "\n", ## arg) | ||
29 | #else | ||
30 | #define dbg(format, arg...) do {} while (0) | ||
31 | #endif | ||
32 | |||
33 | #define ALPS_OLDPROTO 0x01 /* old style input */ | 26 | #define ALPS_OLDPROTO 0x01 /* old style input */ |
34 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ | 27 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ |
35 | #define ALPS_PASS 0x04 /* device has a pass-through port */ | 28 | #define ALPS_PASS 0x04 /* device has a pass-through port */ |
@@ -297,10 +290,10 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | |||
297 | psmouse->packet[4] | | 290 | psmouse->packet[4] | |
298 | psmouse->packet[5]) & 0x80) || | 291 | psmouse->packet[5]) & 0x80) || |
299 | (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { | 292 | (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { |
300 | dbg("refusing packet %x %x %x %x " | 293 | psmouse_dbg(psmouse, |
301 | "(suspected interleaved ps/2)\n", | 294 | "refusing packet %x %x %x %x (suspected interleaved ps/2)\n", |
302 | psmouse->packet[3], psmouse->packet[4], | 295 | psmouse->packet[3], psmouse->packet[4], |
303 | psmouse->packet[5], psmouse->packet[6]); | 296 | psmouse->packet[5], psmouse->packet[6]); |
304 | return PSMOUSE_BAD_DATA; | 297 | return PSMOUSE_BAD_DATA; |
305 | } | 298 | } |
306 | 299 | ||
@@ -319,13 +312,13 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | |||
319 | * There is also possibility that we got 6-byte ALPS | 312 | * There is also possibility that we got 6-byte ALPS |
320 | * packet followed by 3-byte packet from trackpoint. We | 313 | * packet followed by 3-byte packet from trackpoint. We |
321 | * can not distinguish between these 2 scenarios but | 314 | * can not distinguish between these 2 scenarios but |
322 | * becase the latter is unlikely to happen in course of | 315 | * because the latter is unlikely to happen in course of |
323 | * normal operation (user would need to press all | 316 | * normal operation (user would need to press all |
324 | * buttons on the pad and start moving trackpoint | 317 | * buttons on the pad and start moving trackpoint |
325 | * without touching the pad surface) we assume former. | 318 | * without touching the pad surface) we assume former. |
326 | * Even if we are wrong the wost thing that would happen | 319 | * Even if we are wrong the wost thing that would happen |
327 | * the cursor would jump but we should not get protocol | 320 | * the cursor would jump but we should not get protocol |
328 | * desynchronization. | 321 | * de-synchronization. |
329 | */ | 322 | */ |
330 | 323 | ||
331 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], | 324 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], |
@@ -361,10 +354,10 @@ static void alps_flush_packet(unsigned long data) | |||
361 | if ((psmouse->packet[3] | | 354 | if ((psmouse->packet[3] | |
362 | psmouse->packet[4] | | 355 | psmouse->packet[4] | |
363 | psmouse->packet[5]) & 0x80) { | 356 | psmouse->packet[5]) & 0x80) { |
364 | dbg("refusing packet %x %x %x " | 357 | psmouse_dbg(psmouse, |
365 | "(suspected interleaved ps/2)\n", | 358 | "refusing packet %x %x %x (suspected interleaved ps/2)\n", |
366 | psmouse->packet[3], psmouse->packet[4], | 359 | psmouse->packet[3], psmouse->packet[4], |
367 | psmouse->packet[5]); | 360 | psmouse->packet[5]); |
368 | } else { | 361 | } else { |
369 | alps_process_packet(psmouse); | 362 | alps_process_packet(psmouse); |
370 | } | 363 | } |
@@ -396,16 +389,18 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
396 | } | 389 | } |
397 | 390 | ||
398 | if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { | 391 | if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { |
399 | dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", | 392 | psmouse_dbg(psmouse, |
400 | psmouse->packet[0], model->mask0, model->byte0); | 393 | "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", |
394 | psmouse->packet[0], model->mask0, model->byte0); | ||
401 | return PSMOUSE_BAD_DATA; | 395 | return PSMOUSE_BAD_DATA; |
402 | } | 396 | } |
403 | 397 | ||
404 | /* Bytes 2 - 6 should have 0 in the highest bit */ | 398 | /* Bytes 2 - 6 should have 0 in the highest bit */ |
405 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && | 399 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && |
406 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { | 400 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { |
407 | dbg("refusing packet[%i] = %x\n", | 401 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
408 | psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); | 402 | psmouse->pktcnt - 1, |
403 | psmouse->packet[psmouse->pktcnt - 1]); | ||
409 | return PSMOUSE_BAD_DATA; | 404 | return PSMOUSE_BAD_DATA; |
410 | } | 405 | } |
411 | 406 | ||
@@ -439,7 +434,8 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int | |||
439 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | 434 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) |
440 | return NULL; | 435 | return NULL; |
441 | 436 | ||
442 | dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]); | 437 | psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", |
438 | param[0], param[1], param[2]); | ||
443 | 439 | ||
444 | if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100)) | 440 | if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100)) |
445 | return NULL; | 441 | return NULL; |
@@ -459,7 +455,8 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int | |||
459 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | 455 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) |
460 | return NULL; | 456 | return NULL; |
461 | 457 | ||
462 | dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]); | 458 | psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", |
459 | param[0], param[1], param[2]); | ||
463 | 460 | ||
464 | if (version) { | 461 | if (version) { |
465 | for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) | 462 | for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) |
@@ -527,7 +524,8 @@ static int alps_get_status(struct psmouse *psmouse, char *param) | |||
527 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | 524 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) |
528 | return -1; | 525 | return -1; |
529 | 526 | ||
530 | dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]); | 527 | psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x", |
528 | param[0], param[1], param[2]); | ||
531 | 529 | ||
532 | return 0; | 530 | return 0; |
533 | } | 531 | } |
@@ -605,12 +603,12 @@ static int alps_hw_init(struct psmouse *psmouse) | |||
605 | } | 603 | } |
606 | 604 | ||
607 | if (alps_tap_mode(psmouse, true)) { | 605 | if (alps_tap_mode(psmouse, true)) { |
608 | printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); | 606 | psmouse_warn(psmouse, "Failed to enable hardware tapping\n"); |
609 | return -1; | 607 | return -1; |
610 | } | 608 | } |
611 | 609 | ||
612 | if (alps_absolute_mode(psmouse)) { | 610 | if (alps_absolute_mode(psmouse)) { |
613 | printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); | 611 | psmouse_err(psmouse, "Failed to enable absolute mode\n"); |
614 | return -1; | 612 | return -1; |
615 | } | 613 | } |
616 | 614 | ||
@@ -621,7 +619,7 @@ static int alps_hw_init(struct psmouse *psmouse) | |||
621 | 619 | ||
622 | /* ALPS needs stream mode, otherwise it won't report any data */ | 620 | /* ALPS needs stream mode, otherwise it won't report any data */ |
623 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { | 621 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { |
624 | printk(KERN_ERR "alps.c: Failed to enable stream mode\n"); | 622 | psmouse_err(psmouse, "Failed to enable stream mode\n"); |
625 | return -1; | 623 | return -1; |
626 | } | 624 | } |
627 | 625 | ||
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 32503565faf9..09b93b11a274 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -10,8 +10,6 @@ | |||
10 | * Trademarks are the property of their respective owners. | 10 | * Trademarks are the property of their respective owners. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_BASENAME ": " fmt | ||
14 | |||
15 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
16 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
17 | #include <linux/module.h> | 15 | #include <linux/module.h> |
@@ -25,13 +23,10 @@ | |||
25 | #define elantech_debug(fmt, ...) \ | 23 | #define elantech_debug(fmt, ...) \ |
26 | do { \ | 24 | do { \ |
27 | if (etd->debug) \ | 25 | if (etd->debug) \ |
28 | printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ | 26 | psmouse_printk(KERN_DEBUG, psmouse, \ |
27 | fmt, ##__VA_ARGS__); \ | ||
29 | } while (0) | 28 | } while (0) |
30 | 29 | ||
31 | static bool force_elantech; | ||
32 | module_param_named(force_elantech, force_elantech, bool, 0644); | ||
33 | MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); | ||
34 | |||
35 | /* | 30 | /* |
36 | * Send a Synaptics style sliced query command | 31 | * Send a Synaptics style sliced query command |
37 | */ | 32 | */ |
@@ -40,7 +35,7 @@ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, | |||
40 | { | 35 | { |
41 | if (psmouse_sliced_command(psmouse, c) || | 36 | if (psmouse_sliced_command(psmouse, c) || |
42 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 37 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
43 | pr_err("synaptics_send_cmd query 0x%02x failed.\n", c); | 38 | psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c); |
44 | return -1; | 39 | return -1; |
45 | } | 40 | } |
46 | 41 | ||
@@ -69,7 +64,7 @@ static int elantech_ps2_command(struct psmouse *psmouse, | |||
69 | } while (tries > 0); | 64 | } while (tries > 0); |
70 | 65 | ||
71 | if (rc) | 66 | if (rc) |
72 | pr_err("ps2 command 0x%02x failed.\n", command); | 67 | psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command); |
73 | 68 | ||
74 | return rc; | 69 | return rc; |
75 | } | 70 | } |
@@ -84,7 +79,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, | |||
84 | unsigned char param[3]; | 79 | unsigned char param[3]; |
85 | int rc = 0; | 80 | int rc = 0; |
86 | 81 | ||
87 | if (reg < 0x10 || reg > 0x26) | 82 | if (reg < 0x07 || reg > 0x26) |
88 | return -1; | 83 | return -1; |
89 | 84 | ||
90 | if (reg > 0x11 && reg < 0x20) | 85 | if (reg > 0x11 && reg < 0x20) |
@@ -108,12 +103,24 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, | |||
108 | rc = -1; | 103 | rc = -1; |
109 | } | 104 | } |
110 | break; | 105 | break; |
106 | |||
107 | case 3 ... 4: | ||
108 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
109 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | ||
110 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
111 | elantech_ps2_command(psmouse, NULL, reg) || | ||
112 | elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { | ||
113 | rc = -1; | ||
114 | } | ||
115 | break; | ||
111 | } | 116 | } |
112 | 117 | ||
113 | if (rc) | 118 | if (rc) |
114 | pr_err("failed to read register 0x%02x.\n", reg); | 119 | psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg); |
115 | else | 120 | else if (etd->hw_version != 4) |
116 | *val = param[0]; | 121 | *val = param[0]; |
122 | else | ||
123 | *val = param[1]; | ||
117 | 124 | ||
118 | return rc; | 125 | return rc; |
119 | } | 126 | } |
@@ -127,7 +134,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, | |||
127 | struct elantech_data *etd = psmouse->private; | 134 | struct elantech_data *etd = psmouse->private; |
128 | int rc = 0; | 135 | int rc = 0; |
129 | 136 | ||
130 | if (reg < 0x10 || reg > 0x26) | 137 | if (reg < 0x07 || reg > 0x26) |
131 | return -1; | 138 | return -1; |
132 | 139 | ||
133 | if (reg > 0x11 && reg < 0x20) | 140 | if (reg > 0x11 && reg < 0x20) |
@@ -154,11 +161,38 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, | |||
154 | rc = -1; | 161 | rc = -1; |
155 | } | 162 | } |
156 | break; | 163 | break; |
164 | |||
165 | case 3: | ||
166 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
167 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | ||
168 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
169 | elantech_ps2_command(psmouse, NULL, reg) || | ||
170 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
171 | elantech_ps2_command(psmouse, NULL, val) || | ||
172 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { | ||
173 | rc = -1; | ||
174 | } | ||
175 | break; | ||
176 | |||
177 | case 4: | ||
178 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
179 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | ||
180 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
181 | elantech_ps2_command(psmouse, NULL, reg) || | ||
182 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
183 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | ||
184 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
185 | elantech_ps2_command(psmouse, NULL, val) || | ||
186 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { | ||
187 | rc = -1; | ||
188 | } | ||
189 | break; | ||
157 | } | 190 | } |
158 | 191 | ||
159 | if (rc) | 192 | if (rc) |
160 | pr_err("failed to write register 0x%02x with value 0x%02x.\n", | 193 | psmouse_err(psmouse, |
161 | reg, val); | 194 | "failed to write register 0x%02x with value 0x%02x.\n", |
195 | reg, val); | ||
162 | 196 | ||
163 | return rc; | 197 | return rc; |
164 | } | 198 | } |
@@ -166,13 +200,13 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, | |||
166 | /* | 200 | /* |
167 | * Dump a complete mouse movement packet to the syslog | 201 | * Dump a complete mouse movement packet to the syslog |
168 | */ | 202 | */ |
169 | static void elantech_packet_dump(unsigned char *packet, int size) | 203 | static void elantech_packet_dump(struct psmouse *psmouse) |
170 | { | 204 | { |
171 | int i; | 205 | int i; |
172 | 206 | ||
173 | printk(KERN_DEBUG pr_fmt("PS/2 packet [")); | 207 | psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet ["); |
174 | for (i = 0; i < size; i++) | 208 | for (i = 0; i < psmouse->pktsize; i++) |
175 | printk("%s0x%02x ", (i) ? ", " : " ", packet[i]); | 209 | printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]); |
176 | printk("]\n"); | 210 | printk("]\n"); |
177 | } | 211 | } |
178 | 212 | ||
@@ -223,7 +257,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
223 | input_report_abs(dev, ABS_X, | 257 | input_report_abs(dev, ABS_X, |
224 | ((packet[1] & 0x0c) << 6) | packet[2]); | 258 | ((packet[1] & 0x0c) << 6) | packet[2]); |
225 | input_report_abs(dev, ABS_Y, | 259 | input_report_abs(dev, ABS_Y, |
226 | ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); | 260 | etd->y_max - (((packet[1] & 0x03) << 8) | packet[3])); |
227 | } | 261 | } |
228 | 262 | ||
229 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 263 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
@@ -233,7 +267,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
233 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 267 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
234 | 268 | ||
235 | if (etd->fw_version < 0x020000 && | 269 | if (etd->fw_version < 0x020000 && |
236 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { | 270 | (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { |
237 | /* rocker up */ | 271 | /* rocker up */ |
238 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); | 272 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); |
239 | /* rocker down */ | 273 | /* rocker down */ |
@@ -273,11 +307,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
273 | struct elantech_data *etd = psmouse->private; | 307 | struct elantech_data *etd = psmouse->private; |
274 | struct input_dev *dev = psmouse->dev; | 308 | struct input_dev *dev = psmouse->dev; |
275 | unsigned char *packet = psmouse->packet; | 309 | unsigned char *packet = psmouse->packet; |
276 | unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, pres = 0; | 310 | unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0; |
311 | unsigned int width = 0, pres = 0; | ||
277 | 312 | ||
278 | /* byte 0: n1 n0 . . . . R L */ | 313 | /* byte 0: n1 n0 . . . . R L */ |
279 | fingers = (packet[0] & 0xc0) >> 6; | 314 | fingers = (packet[0] & 0xc0) >> 6; |
280 | input_report_key(dev, BTN_TOUCH, fingers != 0); | ||
281 | 315 | ||
282 | switch (fingers) { | 316 | switch (fingers) { |
283 | case 3: | 317 | case 3: |
@@ -290,18 +324,15 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
290 | /* pass through... */ | 324 | /* pass through... */ |
291 | case 1: | 325 | case 1: |
292 | /* | 326 | /* |
293 | * byte 1: . . . . . x10 x9 x8 | 327 | * byte 1: . . . . x11 x10 x9 x8 |
294 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 | 328 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
295 | */ | 329 | */ |
296 | x1 = ((packet[1] & 0x07) << 8) | packet[2]; | 330 | x1 = ((packet[1] & 0x0f) << 8) | packet[2]; |
297 | /* | 331 | /* |
298 | * byte 4: . . . . . . y9 y8 | 332 | * byte 4: . . . . y11 y10 y9 y8 |
299 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | 333 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 |
300 | */ | 334 | */ |
301 | y1 = ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]); | 335 | y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); |
302 | |||
303 | input_report_abs(dev, ABS_X, x1); | ||
304 | input_report_abs(dev, ABS_Y, y1); | ||
305 | 336 | ||
306 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); | 337 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); |
307 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); | 338 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); |
@@ -314,22 +345,18 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
314 | * byte 0: . . ay8 ax8 . . . . | 345 | * byte 0: . . ay8 ax8 . . . . |
315 | * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | 346 | * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 |
316 | */ | 347 | */ |
317 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; | 348 | x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; |
318 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ | 349 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ |
319 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); | 350 | y1 = etd->y_max - |
351 | ((((packet[0] & 0x20) << 3) | packet[2]) << 2); | ||
320 | /* | 352 | /* |
321 | * byte 3: . . by8 bx8 . . . . | 353 | * byte 3: . . by8 bx8 . . . . |
322 | * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 | 354 | * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 |
323 | */ | 355 | */ |
324 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; | 356 | x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; |
325 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ | 357 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ |
326 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); | 358 | y2 = etd->y_max - |
327 | /* | 359 | ((((packet[3] & 0x20) << 3) | packet[5]) << 2); |
328 | * For compatibility with the X Synaptics driver scale up | ||
329 | * one coordinate and report as ordinary mouse movent | ||
330 | */ | ||
331 | input_report_abs(dev, ABS_X, x1 << 2); | ||
332 | input_report_abs(dev, ABS_Y, y1 << 2); | ||
333 | 360 | ||
334 | /* Unknown so just report sensible values */ | 361 | /* Unknown so just report sensible values */ |
335 | pres = 127; | 362 | pres = 127; |
@@ -337,6 +364,11 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
337 | break; | 364 | break; |
338 | } | 365 | } |
339 | 366 | ||
367 | input_report_key(dev, BTN_TOUCH, fingers != 0); | ||
368 | if (fingers != 0) { | ||
369 | input_report_abs(dev, ABS_X, x1); | ||
370 | input_report_abs(dev, ABS_Y, y1); | ||
371 | } | ||
340 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | 372 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); |
341 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 373 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
342 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | 374 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); |
@@ -352,7 +384,208 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
352 | input_sync(dev); | 384 | input_sync(dev); |
353 | } | 385 | } |
354 | 386 | ||
355 | static int elantech_check_parity_v1(struct psmouse *psmouse) | 387 | /* |
388 | * Interpret complete data packets and report absolute mode input events for | ||
389 | * hardware version 3. (12 byte packets for two fingers) | ||
390 | */ | ||
391 | static void elantech_report_absolute_v3(struct psmouse *psmouse, | ||
392 | int packet_type) | ||
393 | { | ||
394 | struct input_dev *dev = psmouse->dev; | ||
395 | struct elantech_data *etd = psmouse->private; | ||
396 | unsigned char *packet = psmouse->packet; | ||
397 | unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; | ||
398 | unsigned int width = 0, pres = 0; | ||
399 | |||
400 | /* byte 0: n1 n0 . . . . R L */ | ||
401 | fingers = (packet[0] & 0xc0) >> 6; | ||
402 | |||
403 | switch (fingers) { | ||
404 | case 3: | ||
405 | case 1: | ||
406 | /* | ||
407 | * byte 1: . . . . x11 x10 x9 x8 | ||
408 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 | ||
409 | */ | ||
410 | x1 = ((packet[1] & 0x0f) << 8) | packet[2]; | ||
411 | /* | ||
412 | * byte 4: . . . . y11 y10 y9 y8 | ||
413 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | ||
414 | */ | ||
415 | y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | ||
416 | break; | ||
417 | |||
418 | case 2: | ||
419 | if (packet_type == PACKET_V3_HEAD) { | ||
420 | /* | ||
421 | * byte 1: . . . . ax11 ax10 ax9 ax8 | ||
422 | * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | ||
423 | */ | ||
424 | etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; | ||
425 | /* | ||
426 | * byte 4: . . . . ay11 ay10 ay9 ay8 | ||
427 | * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 | ||
428 | */ | ||
429 | etd->mt[0].y = etd->y_max - | ||
430 | (((packet[4] & 0x0f) << 8) | packet[5]); | ||
431 | /* | ||
432 | * wait for next packet | ||
433 | */ | ||
434 | return; | ||
435 | } | ||
436 | |||
437 | /* packet_type == PACKET_V3_TAIL */ | ||
438 | x1 = etd->mt[0].x; | ||
439 | y1 = etd->mt[0].y; | ||
440 | x2 = ((packet[1] & 0x0f) << 8) | packet[2]; | ||
441 | y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | ||
442 | break; | ||
443 | } | ||
444 | |||
445 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); | ||
446 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); | ||
447 | |||
448 | input_report_key(dev, BTN_TOUCH, fingers != 0); | ||
449 | if (fingers != 0) { | ||
450 | input_report_abs(dev, ABS_X, x1); | ||
451 | input_report_abs(dev, ABS_Y, y1); | ||
452 | } | ||
453 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | ||
454 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | ||
455 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | ||
456 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); | ||
457 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | ||
458 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | ||
459 | input_report_abs(dev, ABS_PRESSURE, pres); | ||
460 | input_report_abs(dev, ABS_TOOL_WIDTH, width); | ||
461 | |||
462 | input_sync(dev); | ||
463 | } | ||
464 | |||
465 | static void elantech_input_sync_v4(struct psmouse *psmouse) | ||
466 | { | ||
467 | struct input_dev *dev = psmouse->dev; | ||
468 | unsigned char *packet = psmouse->packet; | ||
469 | |||
470 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | ||
471 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | ||
472 | input_mt_report_pointer_emulation(dev, true); | ||
473 | input_sync(dev); | ||
474 | } | ||
475 | |||
476 | static void process_packet_status_v4(struct psmouse *psmouse) | ||
477 | { | ||
478 | struct input_dev *dev = psmouse->dev; | ||
479 | unsigned char *packet = psmouse->packet; | ||
480 | unsigned fingers; | ||
481 | int i; | ||
482 | |||
483 | /* notify finger state change */ | ||
484 | fingers = packet[1] & 0x1f; | ||
485 | for (i = 0; i < ETP_MAX_FINGERS; i++) { | ||
486 | if ((fingers & (1 << i)) == 0) { | ||
487 | input_mt_slot(dev, i); | ||
488 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); | ||
489 | } | ||
490 | } | ||
491 | |||
492 | elantech_input_sync_v4(psmouse); | ||
493 | } | ||
494 | |||
495 | static void process_packet_head_v4(struct psmouse *psmouse) | ||
496 | { | ||
497 | struct input_dev *dev = psmouse->dev; | ||
498 | struct elantech_data *etd = psmouse->private; | ||
499 | unsigned char *packet = psmouse->packet; | ||
500 | int id = ((packet[3] & 0xe0) >> 5) - 1; | ||
501 | int pres, traces; | ||
502 | |||
503 | if (id < 0) | ||
504 | return; | ||
505 | |||
506 | etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; | ||
507 | etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | ||
508 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); | ||
509 | traces = (packet[0] & 0xf0) >> 4; | ||
510 | |||
511 | input_mt_slot(dev, id); | ||
512 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); | ||
513 | |||
514 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); | ||
515 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); | ||
516 | input_report_abs(dev, ABS_MT_PRESSURE, pres); | ||
517 | input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); | ||
518 | /* report this for backwards compatibility */ | ||
519 | input_report_abs(dev, ABS_TOOL_WIDTH, traces); | ||
520 | |||
521 | elantech_input_sync_v4(psmouse); | ||
522 | } | ||
523 | |||
524 | static void process_packet_motion_v4(struct psmouse *psmouse) | ||
525 | { | ||
526 | struct input_dev *dev = psmouse->dev; | ||
527 | struct elantech_data *etd = psmouse->private; | ||
528 | unsigned char *packet = psmouse->packet; | ||
529 | int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; | ||
530 | int id, sid; | ||
531 | |||
532 | id = ((packet[0] & 0xe0) >> 5) - 1; | ||
533 | if (id < 0) | ||
534 | return; | ||
535 | |||
536 | sid = ((packet[3] & 0xe0) >> 5) - 1; | ||
537 | weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; | ||
538 | /* | ||
539 | * Motion packets give us the delta of x, y values of specific fingers, | ||
540 | * but in two's complement. Let the compiler do the conversion for us. | ||
541 | * Also _enlarge_ the numbers to int, in case of overflow. | ||
542 | */ | ||
543 | delta_x1 = (signed char)packet[1]; | ||
544 | delta_y1 = (signed char)packet[2]; | ||
545 | delta_x2 = (signed char)packet[4]; | ||
546 | delta_y2 = (signed char)packet[5]; | ||
547 | |||
548 | etd->mt[id].x += delta_x1 * weight; | ||
549 | etd->mt[id].y -= delta_y1 * weight; | ||
550 | input_mt_slot(dev, id); | ||
551 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); | ||
552 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); | ||
553 | |||
554 | if (sid >= 0) { | ||
555 | etd->mt[sid].x += delta_x2 * weight; | ||
556 | etd->mt[sid].y -= delta_y2 * weight; | ||
557 | input_mt_slot(dev, sid); | ||
558 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); | ||
559 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); | ||
560 | } | ||
561 | |||
562 | elantech_input_sync_v4(psmouse); | ||
563 | } | ||
564 | |||
565 | static void elantech_report_absolute_v4(struct psmouse *psmouse, | ||
566 | int packet_type) | ||
567 | { | ||
568 | switch (packet_type) { | ||
569 | case PACKET_V4_STATUS: | ||
570 | process_packet_status_v4(psmouse); | ||
571 | break; | ||
572 | |||
573 | case PACKET_V4_HEAD: | ||
574 | process_packet_head_v4(psmouse); | ||
575 | break; | ||
576 | |||
577 | case PACKET_V4_MOTION: | ||
578 | process_packet_motion_v4(psmouse); | ||
579 | break; | ||
580 | |||
581 | case PACKET_UNKNOWN: | ||
582 | default: | ||
583 | /* impossible to get here */ | ||
584 | break; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | static int elantech_packet_check_v1(struct psmouse *psmouse) | ||
356 | { | 589 | { |
357 | struct elantech_data *etd = psmouse->private; | 590 | struct elantech_data *etd = psmouse->private; |
358 | unsigned char *packet = psmouse->packet; | 591 | unsigned char *packet = psmouse->packet; |
@@ -376,31 +609,142 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) | |||
376 | etd->parity[packet[3]] == p3; | 609 | etd->parity[packet[3]] == p3; |
377 | } | 610 | } |
378 | 611 | ||
612 | static int elantech_debounce_check_v2(struct psmouse *psmouse) | ||
613 | { | ||
614 | /* | ||
615 | * When we encounter packet that matches this exactly, it means the | ||
616 | * hardware is in debounce status. Just ignore the whole packet. | ||
617 | */ | ||
618 | const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; | ||
619 | unsigned char *packet = psmouse->packet; | ||
620 | |||
621 | return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); | ||
622 | } | ||
623 | |||
624 | static int elantech_packet_check_v2(struct psmouse *psmouse) | ||
625 | { | ||
626 | struct elantech_data *etd = psmouse->private; | ||
627 | unsigned char *packet = psmouse->packet; | ||
628 | |||
629 | /* | ||
630 | * V2 hardware has two flavors. Older ones that do not report pressure, | ||
631 | * and newer ones that reports pressure and width. With newer ones, all | ||
632 | * packets (1, 2, 3 finger touch) have the same constant bits. With | ||
633 | * older ones, 1/3 finger touch packets and 2 finger touch packets | ||
634 | * have different constant bits. | ||
635 | * With all three cases, if the constant bits are not exactly what I | ||
636 | * expected, I consider them invalid. | ||
637 | */ | ||
638 | if (etd->reports_pressure) | ||
639 | return (packet[0] & 0x0c) == 0x04 && | ||
640 | (packet[3] & 0x0f) == 0x02; | ||
641 | |||
642 | if ((packet[0] & 0xc0) == 0x80) | ||
643 | return (packet[0] & 0x0c) == 0x0c && | ||
644 | (packet[3] & 0x0e) == 0x08; | ||
645 | |||
646 | return (packet[0] & 0x3c) == 0x3c && | ||
647 | (packet[1] & 0xf0) == 0x00 && | ||
648 | (packet[3] & 0x3e) == 0x38 && | ||
649 | (packet[4] & 0xf0) == 0x00; | ||
650 | } | ||
651 | |||
652 | /* | ||
653 | * We check the constant bits to determine what packet type we get, | ||
654 | * so packet checking is mandatory for v3 and later hardware. | ||
655 | */ | ||
656 | static int elantech_packet_check_v3(struct psmouse *psmouse) | ||
657 | { | ||
658 | const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; | ||
659 | unsigned char *packet = psmouse->packet; | ||
660 | |||
661 | /* | ||
662 | * check debounce first, it has the same signature in byte 0 | ||
663 | * and byte 3 as PACKET_V3_HEAD. | ||
664 | */ | ||
665 | if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) | ||
666 | return PACKET_DEBOUNCE; | ||
667 | |||
668 | if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) | ||
669 | return PACKET_V3_HEAD; | ||
670 | |||
671 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) | ||
672 | return PACKET_V3_TAIL; | ||
673 | |||
674 | return PACKET_UNKNOWN; | ||
675 | } | ||
676 | |||
677 | static int elantech_packet_check_v4(struct psmouse *psmouse) | ||
678 | { | ||
679 | unsigned char *packet = psmouse->packet; | ||
680 | |||
681 | if ((packet[0] & 0x0c) == 0x04 && | ||
682 | (packet[3] & 0x1f) == 0x11) | ||
683 | return PACKET_V4_HEAD; | ||
684 | |||
685 | if ((packet[0] & 0x0c) == 0x04 && | ||
686 | (packet[3] & 0x1f) == 0x12) | ||
687 | return PACKET_V4_MOTION; | ||
688 | |||
689 | if ((packet[0] & 0x0c) == 0x04 && | ||
690 | (packet[3] & 0x1f) == 0x10) | ||
691 | return PACKET_V4_STATUS; | ||
692 | |||
693 | return PACKET_UNKNOWN; | ||
694 | } | ||
695 | |||
379 | /* | 696 | /* |
380 | * Process byte stream from mouse and handle complete packets | 697 | * Process byte stream from mouse and handle complete packets |
381 | */ | 698 | */ |
382 | static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) | 699 | static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) |
383 | { | 700 | { |
384 | struct elantech_data *etd = psmouse->private; | 701 | struct elantech_data *etd = psmouse->private; |
702 | int packet_type; | ||
385 | 703 | ||
386 | if (psmouse->pktcnt < psmouse->pktsize) | 704 | if (psmouse->pktcnt < psmouse->pktsize) |
387 | return PSMOUSE_GOOD_DATA; | 705 | return PSMOUSE_GOOD_DATA; |
388 | 706 | ||
389 | if (etd->debug > 1) | 707 | if (etd->debug > 1) |
390 | elantech_packet_dump(psmouse->packet, psmouse->pktsize); | 708 | elantech_packet_dump(psmouse); |
391 | 709 | ||
392 | switch (etd->hw_version) { | 710 | switch (etd->hw_version) { |
393 | case 1: | 711 | case 1: |
394 | if (etd->paritycheck && !elantech_check_parity_v1(psmouse)) | 712 | if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) |
395 | return PSMOUSE_BAD_DATA; | 713 | return PSMOUSE_BAD_DATA; |
396 | 714 | ||
397 | elantech_report_absolute_v1(psmouse); | 715 | elantech_report_absolute_v1(psmouse); |
398 | break; | 716 | break; |
399 | 717 | ||
400 | case 2: | 718 | case 2: |
401 | /* We don't know how to check parity in protocol v2 */ | 719 | /* ignore debounce */ |
720 | if (elantech_debounce_check_v2(psmouse)) | ||
721 | return PSMOUSE_FULL_PACKET; | ||
722 | |||
723 | if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) | ||
724 | return PSMOUSE_BAD_DATA; | ||
725 | |||
402 | elantech_report_absolute_v2(psmouse); | 726 | elantech_report_absolute_v2(psmouse); |
403 | break; | 727 | break; |
728 | |||
729 | case 3: | ||
730 | packet_type = elantech_packet_check_v3(psmouse); | ||
731 | /* ignore debounce */ | ||
732 | if (packet_type == PACKET_DEBOUNCE) | ||
733 | return PSMOUSE_FULL_PACKET; | ||
734 | |||
735 | if (packet_type == PACKET_UNKNOWN) | ||
736 | return PSMOUSE_BAD_DATA; | ||
737 | |||
738 | elantech_report_absolute_v3(psmouse, packet_type); | ||
739 | break; | ||
740 | |||
741 | case 4: | ||
742 | packet_type = elantech_packet_check_v4(psmouse); | ||
743 | if (packet_type == PACKET_UNKNOWN) | ||
744 | return PSMOUSE_BAD_DATA; | ||
745 | |||
746 | elantech_report_absolute_v4(psmouse, packet_type); | ||
747 | break; | ||
404 | } | 748 | } |
405 | 749 | ||
406 | return PSMOUSE_FULL_PACKET; | 750 | return PSMOUSE_FULL_PACKET; |
@@ -435,15 +779,29 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) | |||
435 | elantech_write_reg(psmouse, 0x11, etd->reg_11) || | 779 | elantech_write_reg(psmouse, 0x11, etd->reg_11) || |
436 | elantech_write_reg(psmouse, 0x21, etd->reg_21)) { | 780 | elantech_write_reg(psmouse, 0x21, etd->reg_21)) { |
437 | rc = -1; | 781 | rc = -1; |
438 | break; | ||
439 | } | 782 | } |
783 | break; | ||
784 | |||
785 | case 3: | ||
786 | etd->reg_10 = 0x0b; | ||
787 | if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) | ||
788 | rc = -1; | ||
789 | |||
790 | break; | ||
791 | |||
792 | case 4: | ||
793 | etd->reg_07 = 0x01; | ||
794 | if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) | ||
795 | rc = -1; | ||
796 | |||
797 | goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ | ||
440 | } | 798 | } |
441 | 799 | ||
442 | if (rc == 0) { | 800 | if (rc == 0) { |
443 | /* | 801 | /* |
444 | * Read back reg 0x10. For hardware version 1 we must make | 802 | * Read back reg 0x10. For hardware version 1 we must make |
445 | * sure the absolute mode bit is set. For hardware version 2 | 803 | * sure the absolute mode bit is set. For hardware version 2 |
446 | * the touchpad is probably initalising and not ready until | 804 | * the touchpad is probably initializing and not ready until |
447 | * we read back the value we just wrote. | 805 | * we read back the value we just wrote. |
448 | */ | 806 | */ |
449 | do { | 807 | do { |
@@ -456,27 +814,115 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) | |||
456 | } while (tries > 0); | 814 | } while (tries > 0); |
457 | 815 | ||
458 | if (rc) { | 816 | if (rc) { |
459 | pr_err("failed to read back register 0x10.\n"); | 817 | psmouse_err(psmouse, |
818 | "failed to read back register 0x10.\n"); | ||
460 | } else if (etd->hw_version == 1 && | 819 | } else if (etd->hw_version == 1 && |
461 | !(val & ETP_R10_ABSOLUTE_MODE)) { | 820 | !(val & ETP_R10_ABSOLUTE_MODE)) { |
462 | pr_err("touchpad refuses to switch to absolute mode.\n"); | 821 | psmouse_err(psmouse, |
822 | "touchpad refuses to switch to absolute mode.\n"); | ||
463 | rc = -1; | 823 | rc = -1; |
464 | } | 824 | } |
465 | } | 825 | } |
466 | 826 | ||
827 | skip_readback_reg_10: | ||
467 | if (rc) | 828 | if (rc) |
468 | pr_err("failed to initialise registers.\n"); | 829 | psmouse_err(psmouse, "failed to initialise registers.\n"); |
469 | 830 | ||
470 | return rc; | 831 | return rc; |
471 | } | 832 | } |
472 | 833 | ||
834 | static int elantech_set_range(struct psmouse *psmouse, | ||
835 | unsigned int *x_min, unsigned int *y_min, | ||
836 | unsigned int *x_max, unsigned int *y_max, | ||
837 | unsigned int *width) | ||
838 | { | ||
839 | struct elantech_data *etd = psmouse->private; | ||
840 | unsigned char param[3]; | ||
841 | unsigned char traces; | ||
842 | |||
843 | switch (etd->hw_version) { | ||
844 | case 1: | ||
845 | *x_min = ETP_XMIN_V1; | ||
846 | *y_min = ETP_YMIN_V1; | ||
847 | *x_max = ETP_XMAX_V1; | ||
848 | *y_max = ETP_YMAX_V1; | ||
849 | break; | ||
850 | |||
851 | case 2: | ||
852 | if (etd->fw_version == 0x020800 || | ||
853 | etd->fw_version == 0x020b00 || | ||
854 | etd->fw_version == 0x020030) { | ||
855 | *x_min = ETP_XMIN_V2; | ||
856 | *y_min = ETP_YMIN_V2; | ||
857 | *x_max = ETP_XMAX_V2; | ||
858 | *y_max = ETP_YMAX_V2; | ||
859 | } else { | ||
860 | int i; | ||
861 | int fixed_dpi; | ||
862 | |||
863 | i = (etd->fw_version > 0x020800 && | ||
864 | etd->fw_version < 0x020900) ? 1 : 2; | ||
865 | |||
866 | if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | ||
867 | return -1; | ||
868 | |||
869 | fixed_dpi = param[1] & 0x10; | ||
870 | |||
871 | if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { | ||
872 | if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) | ||
873 | return -1; | ||
874 | |||
875 | *x_max = (etd->capabilities[1] - i) * param[1] / 2; | ||
876 | *y_max = (etd->capabilities[2] - i) * param[2] / 2; | ||
877 | } else if (etd->fw_version == 0x040216) { | ||
878 | *x_max = 819; | ||
879 | *y_max = 405; | ||
880 | } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) { | ||
881 | *x_max = 900; | ||
882 | *y_max = 500; | ||
883 | } else { | ||
884 | *x_max = (etd->capabilities[1] - i) * 64; | ||
885 | *y_max = (etd->capabilities[2] - i) * 64; | ||
886 | } | ||
887 | } | ||
888 | break; | ||
889 | |||
890 | case 3: | ||
891 | if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | ||
892 | return -1; | ||
893 | |||
894 | *x_max = (0x0f & param[0]) << 8 | param[1]; | ||
895 | *y_max = (0xf0 & param[0]) << 4 | param[2]; | ||
896 | break; | ||
897 | |||
898 | case 4: | ||
899 | if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | ||
900 | return -1; | ||
901 | |||
902 | *x_max = (0x0f & param[0]) << 8 | param[1]; | ||
903 | *y_max = (0xf0 & param[0]) << 4 | param[2]; | ||
904 | traces = etd->capabilities[1]; | ||
905 | if ((traces < 2) || (traces > *x_max)) | ||
906 | return -1; | ||
907 | |||
908 | *width = *x_max / (traces - 1); | ||
909 | break; | ||
910 | } | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | |||
473 | /* | 915 | /* |
474 | * Set the appropriate event bits for the input subsystem | 916 | * Set the appropriate event bits for the input subsystem |
475 | */ | 917 | */ |
476 | static void elantech_set_input_params(struct psmouse *psmouse) | 918 | static int elantech_set_input_params(struct psmouse *psmouse) |
477 | { | 919 | { |
478 | struct input_dev *dev = psmouse->dev; | 920 | struct input_dev *dev = psmouse->dev; |
479 | struct elantech_data *etd = psmouse->private; | 921 | struct elantech_data *etd = psmouse->private; |
922 | unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; | ||
923 | |||
924 | if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) | ||
925 | return -1; | ||
480 | 926 | ||
481 | __set_bit(EV_KEY, dev->evbit); | 927 | __set_bit(EV_KEY, dev->evbit); |
482 | __set_bit(EV_ABS, dev->evbit); | 928 | __set_bit(EV_ABS, dev->evbit); |
@@ -494,30 +940,64 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
494 | case 1: | 940 | case 1: |
495 | /* Rocker button */ | 941 | /* Rocker button */ |
496 | if (etd->fw_version < 0x020000 && | 942 | if (etd->fw_version < 0x020000 && |
497 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { | 943 | (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { |
498 | __set_bit(BTN_FORWARD, dev->keybit); | 944 | __set_bit(BTN_FORWARD, dev->keybit); |
499 | __set_bit(BTN_BACK, dev->keybit); | 945 | __set_bit(BTN_BACK, dev->keybit); |
500 | } | 946 | } |
501 | input_set_abs_params(dev, ABS_X, ETP_XMIN_V1, ETP_XMAX_V1, 0, 0); | 947 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
502 | input_set_abs_params(dev, ABS_Y, ETP_YMIN_V1, ETP_YMAX_V1, 0, 0); | 948 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); |
503 | break; | 949 | break; |
504 | 950 | ||
505 | case 2: | 951 | case 2: |
506 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 952 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
507 | input_set_abs_params(dev, ABS_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); | 953 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); |
508 | input_set_abs_params(dev, ABS_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); | 954 | /* fall through */ |
955 | case 3: | ||
956 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); | ||
957 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); | ||
509 | if (etd->reports_pressure) { | 958 | if (etd->reports_pressure) { |
510 | input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, | 959 | input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, |
511 | ETP_PMAX_V2, 0, 0); | 960 | ETP_PMAX_V2, 0, 0); |
512 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, | 961 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, |
513 | ETP_WMAX_V2, 0, 0); | 962 | ETP_WMAX_V2, 0, 0); |
514 | } | 963 | } |
515 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
516 | input_mt_init_slots(dev, 2); | 964 | input_mt_init_slots(dev, 2); |
517 | input_set_abs_params(dev, ABS_MT_POSITION_X, ETP_XMIN_V2, ETP_XMAX_V2, 0, 0); | 965 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); |
518 | input_set_abs_params(dev, ABS_MT_POSITION_Y, ETP_YMIN_V2, ETP_YMAX_V2, 0, 0); | 966 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); |
967 | break; | ||
968 | |||
969 | case 4: | ||
970 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | ||
971 | /* For X to recognize me as touchpad. */ | ||
972 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); | ||
973 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); | ||
974 | /* | ||
975 | * range of pressure and width is the same as v2, | ||
976 | * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. | ||
977 | */ | ||
978 | input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, | ||
979 | ETP_PMAX_V2, 0, 0); | ||
980 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, | ||
981 | ETP_WMAX_V2, 0, 0); | ||
982 | /* Multitouch capable pad, up to 5 fingers. */ | ||
983 | input_mt_init_slots(dev, ETP_MAX_FINGERS); | ||
984 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); | ||
985 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); | ||
986 | input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, | ||
987 | ETP_PMAX_V2, 0, 0); | ||
988 | /* | ||
989 | * The firmware reports how many trace lines the finger spans, | ||
990 | * convert to surface unit as Protocol-B requires. | ||
991 | */ | ||
992 | input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, | ||
993 | ETP_WMAX_V2 * width, 0, 0); | ||
519 | break; | 994 | break; |
520 | } | 995 | } |
996 | |||
997 | etd->y_max = y_max; | ||
998 | etd->width = width; | ||
999 | |||
1000 | return 0; | ||
521 | } | 1001 | } |
522 | 1002 | ||
523 | struct elantech_attr_data { | 1003 | struct elantech_attr_data { |
@@ -587,6 +1067,7 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse, | |||
587 | elantech_show_int_attr, \ | 1067 | elantech_show_int_attr, \ |
588 | elantech_set_int_attr) | 1068 | elantech_set_int_attr) |
589 | 1069 | ||
1070 | ELANTECH_INT_ATTR(reg_07, 0x07); | ||
590 | ELANTECH_INT_ATTR(reg_10, 0x10); | 1071 | ELANTECH_INT_ATTR(reg_10, 0x10); |
591 | ELANTECH_INT_ATTR(reg_11, 0x11); | 1072 | ELANTECH_INT_ATTR(reg_11, 0x11); |
592 | ELANTECH_INT_ATTR(reg_20, 0x20); | 1073 | ELANTECH_INT_ATTR(reg_20, 0x20); |
@@ -600,6 +1081,7 @@ ELANTECH_INT_ATTR(debug, 0); | |||
600 | ELANTECH_INT_ATTR(paritycheck, 0); | 1081 | ELANTECH_INT_ATTR(paritycheck, 0); |
601 | 1082 | ||
602 | static struct attribute *elantech_attrs[] = { | 1083 | static struct attribute *elantech_attrs[] = { |
1084 | &psmouse_attr_reg_07.dattr.attr, | ||
603 | &psmouse_attr_reg_10.dattr.attr, | 1085 | &psmouse_attr_reg_10.dattr.attr, |
604 | &psmouse_attr_reg_11.dattr.attr, | 1086 | &psmouse_attr_reg_11.dattr.attr, |
605 | &psmouse_attr_reg_20.dattr.attr, | 1087 | &psmouse_attr_reg_20.dattr.attr, |
@@ -651,7 +1133,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
651 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1133 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
652 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1134 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
653 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 1135 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
654 | pr_debug("sending Elantech magic knock failed.\n"); | 1136 | psmouse_dbg(psmouse, "sending Elantech magic knock failed.\n"); |
655 | return -1; | 1137 | return -1; |
656 | } | 1138 | } |
657 | 1139 | ||
@@ -659,9 +1141,11 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
659 | * Report this in case there are Elantech models that use a different | 1141 | * Report this in case there are Elantech models that use a different |
660 | * set of magic numbers | 1142 | * set of magic numbers |
661 | */ | 1143 | */ |
662 | if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { | 1144 | if (param[0] != 0x3c || param[1] != 0x03 || |
663 | pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", | 1145 | (param[2] != 0xc8 && param[2] != 0x00)) { |
664 | param[0], param[1], param[2]); | 1146 | psmouse_dbg(psmouse, |
1147 | "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", | ||
1148 | param[0], param[1], param[2]); | ||
665 | return -1; | 1149 | return -1; |
666 | } | 1150 | } |
667 | 1151 | ||
@@ -671,20 +1155,18 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
671 | * to Elantech magic knock and there might be more. | 1155 | * to Elantech magic knock and there might be more. |
672 | */ | 1156 | */ |
673 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | 1157 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { |
674 | pr_debug("failed to query firmware version.\n"); | 1158 | psmouse_dbg(psmouse, "failed to query firmware version.\n"); |
675 | return -1; | 1159 | return -1; |
676 | } | 1160 | } |
677 | 1161 | ||
678 | pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", | 1162 | psmouse_dbg(psmouse, |
679 | param[0], param[1], param[2]); | 1163 | "Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", |
1164 | param[0], param[1], param[2]); | ||
680 | 1165 | ||
681 | if (!elantech_is_signature_valid(param)) { | 1166 | if (!elantech_is_signature_valid(param)) { |
682 | if (!force_elantech) { | 1167 | psmouse_dbg(psmouse, |
683 | pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); | 1168 | "Probably not a real Elantech touchpad. Aborting.\n"); |
684 | return -1; | 1169 | return -1; |
685 | } | ||
686 | |||
687 | pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); | ||
688 | } | 1170 | } |
689 | 1171 | ||
690 | if (set_properties) { | 1172 | if (set_properties) { |
@@ -715,7 +1197,8 @@ static int elantech_reconnect(struct psmouse *psmouse) | |||
715 | return -1; | 1197 | return -1; |
716 | 1198 | ||
717 | if (elantech_set_absolute_mode(psmouse)) { | 1199 | if (elantech_set_absolute_mode(psmouse)) { |
718 | pr_err("failed to put touchpad back into absolute mode.\n"); | 1200 | psmouse_err(psmouse, |
1201 | "failed to put touchpad back into absolute mode.\n"); | ||
719 | return -1; | 1202 | return -1; |
720 | } | 1203 | } |
721 | 1204 | ||
@@ -723,6 +1206,48 @@ static int elantech_reconnect(struct psmouse *psmouse) | |||
723 | } | 1206 | } |
724 | 1207 | ||
725 | /* | 1208 | /* |
1209 | * determine hardware version and set some properties according to it. | ||
1210 | */ | ||
1211 | static int elantech_set_properties(struct elantech_data *etd) | ||
1212 | { | ||
1213 | int ver = (etd->fw_version & 0x0f0000) >> 16; | ||
1214 | |||
1215 | if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) | ||
1216 | etd->hw_version = 1; | ||
1217 | else if (etd->fw_version < 0x150600) | ||
1218 | etd->hw_version = 2; | ||
1219 | else if (ver == 5) | ||
1220 | etd->hw_version = 3; | ||
1221 | else if (ver == 6) | ||
1222 | etd->hw_version = 4; | ||
1223 | else | ||
1224 | return -1; | ||
1225 | |||
1226 | /* | ||
1227 | * Turn on packet checking by default. | ||
1228 | */ | ||
1229 | etd->paritycheck = 1; | ||
1230 | |||
1231 | /* | ||
1232 | * This firmware suffers from misreporting coordinates when | ||
1233 | * a touch action starts causing the mouse cursor or scrolled page | ||
1234 | * to jump. Enable a workaround. | ||
1235 | */ | ||
1236 | etd->jumpy_cursor = | ||
1237 | (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); | ||
1238 | |||
1239 | if (etd->hw_version > 1) { | ||
1240 | /* For now show extra debug information */ | ||
1241 | etd->debug = 1; | ||
1242 | |||
1243 | if (etd->fw_version >= 0x020800) | ||
1244 | etd->reports_pressure = true; | ||
1245 | } | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1250 | /* | ||
726 | * Initialize the touchpad and create sysfs entries | 1251 | * Initialize the touchpad and create sysfs entries |
727 | */ | 1252 | */ |
728 | int elantech_init(struct psmouse *psmouse) | 1253 | int elantech_init(struct psmouse *psmouse) |
@@ -743,70 +1268,53 @@ int elantech_init(struct psmouse *psmouse) | |||
743 | * Do the version query again so we can store the result | 1268 | * Do the version query again so we can store the result |
744 | */ | 1269 | */ |
745 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | 1270 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { |
746 | pr_err("failed to query firmware version.\n"); | 1271 | psmouse_err(psmouse, "failed to query firmware version.\n"); |
747 | goto init_fail; | 1272 | goto init_fail; |
748 | } | 1273 | } |
749 | |||
750 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; | 1274 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; |
751 | 1275 | ||
752 | /* | 1276 | if (elantech_set_properties(etd)) { |
753 | * Assume every version greater than this is new EeePC style | 1277 | psmouse_err(psmouse, "unknown hardware version, aborting...\n"); |
754 | * hardware with 6 byte packets | ||
755 | */ | ||
756 | if (etd->fw_version >= 0x020030) { | ||
757 | etd->hw_version = 2; | ||
758 | /* For now show extra debug information */ | ||
759 | etd->debug = 1; | ||
760 | /* Don't know how to do parity checking for version 2 */ | ||
761 | etd->paritycheck = 0; | ||
762 | |||
763 | if (etd->fw_version >= 0x020800) | ||
764 | etd->reports_pressure = true; | ||
765 | |||
766 | } else { | ||
767 | etd->hw_version = 1; | ||
768 | etd->paritycheck = 1; | ||
769 | } | ||
770 | |||
771 | pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", | ||
772 | etd->hw_version, param[0], param[1], param[2]); | ||
773 | |||
774 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { | ||
775 | pr_err("failed to query capabilities.\n"); | ||
776 | goto init_fail; | 1278 | goto init_fail; |
777 | } | 1279 | } |
778 | pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", | 1280 | psmouse_info(psmouse, |
779 | param[0], param[1], param[2]); | 1281 | "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n", |
780 | etd->capabilities = param[0]; | 1282 | etd->hw_version, param[0], param[1], param[2]); |
781 | 1283 | ||
782 | /* | 1284 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, |
783 | * This firmware suffers from misreporting coordinates when | 1285 | etd->capabilities)) { |
784 | * a touch action starts causing the mouse cursor or scrolled page | 1286 | psmouse_err(psmouse, "failed to query capabilities.\n"); |
785 | * to jump. Enable a workaround. | 1287 | goto init_fail; |
786 | */ | ||
787 | if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) { | ||
788 | pr_info("firmware version 2.0.34/2.6.0 detected, enabling jumpy cursor workaround\n"); | ||
789 | etd->jumpy_cursor = true; | ||
790 | } | 1288 | } |
1289 | psmouse_info(psmouse, | ||
1290 | "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", | ||
1291 | etd->capabilities[0], etd->capabilities[1], | ||
1292 | etd->capabilities[2]); | ||
791 | 1293 | ||
792 | if (elantech_set_absolute_mode(psmouse)) { | 1294 | if (elantech_set_absolute_mode(psmouse)) { |
793 | pr_err("failed to put touchpad into absolute mode.\n"); | 1295 | psmouse_err(psmouse, |
1296 | "failed to put touchpad into absolute mode.\n"); | ||
794 | goto init_fail; | 1297 | goto init_fail; |
795 | } | 1298 | } |
796 | 1299 | ||
797 | elantech_set_input_params(psmouse); | 1300 | if (elantech_set_input_params(psmouse)) { |
1301 | psmouse_err(psmouse, "failed to query touchpad range.\n"); | ||
1302 | goto init_fail; | ||
1303 | } | ||
798 | 1304 | ||
799 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, | 1305 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, |
800 | &elantech_attr_group); | 1306 | &elantech_attr_group); |
801 | if (error) { | 1307 | if (error) { |
802 | pr_err("failed to create sysfs attributes, error: %d.\n", error); | 1308 | psmouse_err(psmouse, |
1309 | "failed to create sysfs attributes, error: %d.\n", | ||
1310 | error); | ||
803 | goto init_fail; | 1311 | goto init_fail; |
804 | } | 1312 | } |
805 | 1313 | ||
806 | psmouse->protocol_handler = elantech_process_byte; | 1314 | psmouse->protocol_handler = elantech_process_byte; |
807 | psmouse->disconnect = elantech_disconnect; | 1315 | psmouse->disconnect = elantech_disconnect; |
808 | psmouse->reconnect = elantech_reconnect; | 1316 | psmouse->reconnect = elantech_reconnect; |
809 | psmouse->pktsize = etd->hw_version == 2 ? 6 : 4; | 1317 | psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; |
810 | 1318 | ||
811 | return 0; | 1319 | return 0; |
812 | 1320 | ||
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index fabb2b99615c..9e5f1aabea7e 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -16,14 +16,17 @@ | |||
16 | /* | 16 | /* |
17 | * Command values for Synaptics style queries | 17 | * Command values for Synaptics style queries |
18 | */ | 18 | */ |
19 | #define ETP_FW_ID_QUERY 0x00 | ||
19 | #define ETP_FW_VERSION_QUERY 0x01 | 20 | #define ETP_FW_VERSION_QUERY 0x01 |
20 | #define ETP_CAPABILITIES_QUERY 0x02 | 21 | #define ETP_CAPABILITIES_QUERY 0x02 |
22 | #define ETP_SAMPLE_QUERY 0x03 | ||
21 | 23 | ||
22 | /* | 24 | /* |
23 | * Command values for register reading or writing | 25 | * Command values for register reading or writing |
24 | */ | 26 | */ |
25 | #define ETP_REGISTER_READ 0x10 | 27 | #define ETP_REGISTER_READ 0x10 |
26 | #define ETP_REGISTER_WRITE 0x11 | 28 | #define ETP_REGISTER_WRITE 0x11 |
29 | #define ETP_REGISTER_READWRITE 0x00 | ||
27 | 30 | ||
28 | /* | 31 | /* |
29 | * Hardware version 2 custom PS/2 command value | 32 | * Hardware version 2 custom PS/2 command value |
@@ -66,16 +69,13 @@ | |||
66 | #define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1) | 69 | #define ETP_YMAX_V1 (384 - ETP_EDGE_FUZZ_V1) |
67 | 70 | ||
68 | /* | 71 | /* |
69 | * It seems the resolution for hardware version 2 doubled. | 72 | * The resolution for older v2 hardware doubled. |
70 | * Hence the X and Y ranges are doubled too. | 73 | * (newer v2's firmware provides command so we can query) |
71 | * The bezel around the pad also appears to be smaller | ||
72 | */ | 74 | */ |
73 | #define ETP_EDGE_FUZZ_V2 8 | 75 | #define ETP_XMIN_V2 0 |
74 | 76 | #define ETP_XMAX_V2 1152 | |
75 | #define ETP_XMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) | 77 | #define ETP_YMIN_V2 0 |
76 | #define ETP_XMAX_V2 (1152 - ETP_EDGE_FUZZ_V2) | 78 | #define ETP_YMAX_V2 768 |
77 | #define ETP_YMIN_V2 ( 0 + ETP_EDGE_FUZZ_V2) | ||
78 | #define ETP_YMAX_V2 ( 768 - ETP_EDGE_FUZZ_V2) | ||
79 | 79 | ||
80 | #define ETP_PMIN_V2 0 | 80 | #define ETP_PMIN_V2 0 |
81 | #define ETP_PMAX_V2 255 | 81 | #define ETP_PMAX_V2 255 |
@@ -83,17 +83,37 @@ | |||
83 | #define ETP_WMAX_V2 15 | 83 | #define ETP_WMAX_V2 15 |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * For two finger touches the coordinate of each finger gets reported | 86 | * v3 hardware has 2 kinds of packet types, |
87 | * separately but with reduced resolution. | 87 | * v4 hardware has 3. |
88 | */ | ||
89 | #define PACKET_UNKNOWN 0x01 | ||
90 | #define PACKET_DEBOUNCE 0x02 | ||
91 | #define PACKET_V3_HEAD 0x03 | ||
92 | #define PACKET_V3_TAIL 0x04 | ||
93 | #define PACKET_V4_HEAD 0x05 | ||
94 | #define PACKET_V4_MOTION 0x06 | ||
95 | #define PACKET_V4_STATUS 0x07 | ||
96 | |||
97 | /* | ||
98 | * track up to 5 fingers for v4 hardware | ||
99 | */ | ||
100 | #define ETP_MAX_FINGERS 5 | ||
101 | |||
102 | /* | ||
103 | * weight value for v4 hardware | ||
88 | */ | 104 | */ |
89 | #define ETP_2FT_FUZZ 4 | 105 | #define ETP_WEIGHT_VALUE 5 |
90 | 106 | ||
91 | #define ETP_2FT_XMIN ( 0 + ETP_2FT_FUZZ) | 107 | /* |
92 | #define ETP_2FT_XMAX (288 - ETP_2FT_FUZZ) | 108 | * The base position for one finger, v4 hardware |
93 | #define ETP_2FT_YMIN ( 0 + ETP_2FT_FUZZ) | 109 | */ |
94 | #define ETP_2FT_YMAX (192 - ETP_2FT_FUZZ) | 110 | struct finger_pos { |
111 | unsigned int x; | ||
112 | unsigned int y; | ||
113 | }; | ||
95 | 114 | ||
96 | struct elantech_data { | 115 | struct elantech_data { |
116 | unsigned char reg_07; | ||
97 | unsigned char reg_10; | 117 | unsigned char reg_10; |
98 | unsigned char reg_11; | 118 | unsigned char reg_11; |
99 | unsigned char reg_20; | 119 | unsigned char reg_20; |
@@ -104,13 +124,16 @@ struct elantech_data { | |||
104 | unsigned char reg_25; | 124 | unsigned char reg_25; |
105 | unsigned char reg_26; | 125 | unsigned char reg_26; |
106 | unsigned char debug; | 126 | unsigned char debug; |
107 | unsigned char capabilities; | 127 | unsigned char capabilities[3]; |
108 | bool paritycheck; | 128 | bool paritycheck; |
109 | bool jumpy_cursor; | 129 | bool jumpy_cursor; |
110 | bool reports_pressure; | 130 | bool reports_pressure; |
111 | unsigned char hw_version; | 131 | unsigned char hw_version; |
112 | unsigned int fw_version; | 132 | unsigned int fw_version; |
113 | unsigned int single_finger_reports; | 133 | unsigned int single_finger_reports; |
134 | unsigned int y_max; | ||
135 | unsigned int width; | ||
136 | struct finger_pos mt[ETP_MAX_FINGERS]; | ||
114 | unsigned char parity[256]; | 137 | unsigned char parity[256]; |
115 | }; | 138 | }; |
116 | 139 | ||
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 4d17d9f3320b..0470dd46b566 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -136,10 +136,10 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y) | |||
136 | /* discard if too big, or half that but > 4 times the prev delta */ | 136 | /* discard if too big, or half that but > 4 times the prev delta */ |
137 | if (avx > recalib_delta || | 137 | if (avx > recalib_delta || |
138 | (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) { | 138 | (avx > recalib_delta / 2 && ((avx / 4) > priv->xlast))) { |
139 | hgpk_err(psmouse, "detected %dpx jump in x\n", x); | 139 | psmouse_warn(psmouse, "detected %dpx jump in x\n", x); |
140 | priv->xbigj = avx; | 140 | priv->xbigj = avx; |
141 | } else if (approx_half(avx, priv->xbigj)) { | 141 | } else if (approx_half(avx, priv->xbigj)) { |
142 | hgpk_err(psmouse, "detected secondary %dpx jump in x\n", x); | 142 | psmouse_warn(psmouse, "detected secondary %dpx jump in x\n", x); |
143 | priv->xbigj = avx; | 143 | priv->xbigj = avx; |
144 | priv->xsaw_secondary++; | 144 | priv->xsaw_secondary++; |
145 | } else { | 145 | } else { |
@@ -151,10 +151,10 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y) | |||
151 | 151 | ||
152 | if (avy > recalib_delta || | 152 | if (avy > recalib_delta || |
153 | (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) { | 153 | (avy > recalib_delta / 2 && ((avy / 4) > priv->ylast))) { |
154 | hgpk_err(psmouse, "detected %dpx jump in y\n", y); | 154 | psmouse_warn(psmouse, "detected %dpx jump in y\n", y); |
155 | priv->ybigj = avy; | 155 | priv->ybigj = avy; |
156 | } else if (approx_half(avy, priv->ybigj)) { | 156 | } else if (approx_half(avy, priv->ybigj)) { |
157 | hgpk_err(psmouse, "detected secondary %dpx jump in y\n", y); | 157 | psmouse_warn(psmouse, "detected secondary %dpx jump in y\n", y); |
158 | priv->ybigj = avy; | 158 | priv->ybigj = avy; |
159 | priv->ysaw_secondary++; | 159 | priv->ysaw_secondary++; |
160 | } else { | 160 | } else { |
@@ -168,7 +168,7 @@ static int hgpk_discard_decay_hack(struct psmouse *psmouse, int x, int y) | |||
168 | priv->ylast = avy; | 168 | priv->ylast = avy; |
169 | 169 | ||
170 | if (do_recal && jumpy_delay) { | 170 | if (do_recal && jumpy_delay) { |
171 | hgpk_err(psmouse, "scheduling recalibration\n"); | 171 | psmouse_warn(psmouse, "scheduling recalibration\n"); |
172 | psmouse_queue_work(psmouse, &priv->recalib_wq, | 172 | psmouse_queue_work(psmouse, &priv->recalib_wq, |
173 | msecs_to_jiffies(jumpy_delay)); | 173 | msecs_to_jiffies(jumpy_delay)); |
174 | } | 174 | } |
@@ -260,8 +260,8 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, | |||
260 | * movement, it is probably a case of the user moving the | 260 | * movement, it is probably a case of the user moving the |
261 | * cursor very slowly across the screen. */ | 261 | * cursor very slowly across the screen. */ |
262 | if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { | 262 | if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { |
263 | hgpk_err(psmouse, "packet spew detected (%d,%d)\n", | 263 | psmouse_warn(psmouse, "packet spew detected (%d,%d)\n", |
264 | priv->x_tally, priv->y_tally); | 264 | priv->x_tally, priv->y_tally); |
265 | priv->spew_flag = RECALIBRATING; | 265 | priv->spew_flag = RECALIBRATING; |
266 | psmouse_queue_work(psmouse, &priv->recalib_wq, | 266 | psmouse_queue_work(psmouse, &priv->recalib_wq, |
267 | msecs_to_jiffies(spew_delay)); | 267 | msecs_to_jiffies(spew_delay)); |
@@ -333,12 +333,12 @@ static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet) | |||
333 | } | 333 | } |
334 | 334 | ||
335 | if (!valid) | 335 | if (!valid) |
336 | hgpk_dbg(psmouse, | 336 | psmouse_dbg(psmouse, |
337 | "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n", | 337 | "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n", |
338 | priv->mode, pktcnt, | 338 | priv->mode, pktcnt, |
339 | psmouse->packet[0], psmouse->packet[1], | 339 | psmouse->packet[0], psmouse->packet[1], |
340 | psmouse->packet[2], psmouse->packet[3], | 340 | psmouse->packet[2], psmouse->packet[3], |
341 | psmouse->packet[4], psmouse->packet[5]); | 341 | psmouse->packet[4], psmouse->packet[5]); |
342 | 342 | ||
343 | return valid; | 343 | return valid; |
344 | } | 344 | } |
@@ -361,19 +361,20 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse) | |||
361 | 361 | ||
362 | input_report_abs(idev, ABS_PRESSURE, z); | 362 | input_report_abs(idev, ABS_PRESSURE, z); |
363 | if (tpdebug) | 363 | if (tpdebug) |
364 | hgpk_dbg(psmouse, "pd=%d fd=%d z=%d", | 364 | psmouse_dbg(psmouse, "pd=%d fd=%d z=%d", |
365 | pt_down, finger_down, z); | 365 | pt_down, finger_down, z); |
366 | } else { | 366 | } else { |
367 | /* | 367 | /* |
368 | * PenTablet mode does not report pressure, so we don't | 368 | * PenTablet mode does not report pressure, so we don't |
369 | * report it here | 369 | * report it here |
370 | */ | 370 | */ |
371 | if (tpdebug) | 371 | if (tpdebug) |
372 | hgpk_dbg(psmouse, "pd=%d ", down); | 372 | psmouse_dbg(psmouse, "pd=%d ", down); |
373 | } | 373 | } |
374 | 374 | ||
375 | if (tpdebug) | 375 | if (tpdebug) |
376 | hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y); | 376 | psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", |
377 | left, right, x, y); | ||
377 | 378 | ||
378 | input_report_key(idev, BTN_TOUCH, down); | 379 | input_report_key(idev, BTN_TOUCH, down); |
379 | input_report_key(idev, BTN_LEFT, left); | 380 | input_report_key(idev, BTN_LEFT, left); |
@@ -395,7 +396,7 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse) | |||
395 | if (x == priv->abs_x && y == priv->abs_y) { | 396 | if (x == priv->abs_x && y == priv->abs_y) { |
396 | if (++priv->dupe_count > SPEW_WATCH_COUNT) { | 397 | if (++priv->dupe_count > SPEW_WATCH_COUNT) { |
397 | if (tpdebug) | 398 | if (tpdebug) |
398 | hgpk_dbg(psmouse, "hard spew detected\n"); | 399 | psmouse_dbg(psmouse, "hard spew detected\n"); |
399 | priv->spew_flag = RECALIBRATING; | 400 | priv->spew_flag = RECALIBRATING; |
400 | psmouse_queue_work(psmouse, &priv->recalib_wq, | 401 | psmouse_queue_work(psmouse, &priv->recalib_wq, |
401 | msecs_to_jiffies(spew_delay)); | 402 | msecs_to_jiffies(spew_delay)); |
@@ -412,7 +413,7 @@ static void hgpk_process_advanced_packet(struct psmouse *psmouse) | |||
412 | int y_diff = priv->abs_y - y; | 413 | int y_diff = priv->abs_y - y; |
413 | if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) { | 414 | if (hgpk_discard_decay_hack(psmouse, x_diff, y_diff)) { |
414 | if (tpdebug) | 415 | if (tpdebug) |
415 | hgpk_dbg(psmouse, "discarding\n"); | 416 | psmouse_dbg(psmouse, "discarding\n"); |
416 | goto done; | 417 | goto done; |
417 | } | 418 | } |
418 | hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff); | 419 | hgpk_spewing_hack(psmouse, left, right, x_diff, y_diff); |
@@ -437,20 +438,21 @@ static void hgpk_process_simple_packet(struct psmouse *psmouse) | |||
437 | int y = ((packet[0] << 3) & 0x100) - packet[2]; | 438 | int y = ((packet[0] << 3) & 0x100) - packet[2]; |
438 | 439 | ||
439 | if (packet[0] & 0xc0) | 440 | if (packet[0] & 0xc0) |
440 | hgpk_dbg(psmouse, | 441 | psmouse_dbg(psmouse, |
441 | "overflow -- 0x%02x 0x%02x 0x%02x\n", | 442 | "overflow -- 0x%02x 0x%02x 0x%02x\n", |
442 | packet[0], packet[1], packet[2]); | 443 | packet[0], packet[1], packet[2]); |
443 | 444 | ||
444 | if (hgpk_discard_decay_hack(psmouse, x, y)) { | 445 | if (hgpk_discard_decay_hack(psmouse, x, y)) { |
445 | if (tpdebug) | 446 | if (tpdebug) |
446 | hgpk_dbg(psmouse, "discarding\n"); | 447 | psmouse_dbg(psmouse, "discarding\n"); |
447 | return; | 448 | return; |
448 | } | 449 | } |
449 | 450 | ||
450 | hgpk_spewing_hack(psmouse, left, right, x, y); | 451 | hgpk_spewing_hack(psmouse, left, right, x, y); |
451 | 452 | ||
452 | if (tpdebug) | 453 | if (tpdebug) |
453 | hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y); | 454 | psmouse_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", |
455 | left, right, x, y); | ||
454 | 456 | ||
455 | input_report_key(dev, BTN_LEFT, left); | 457 | input_report_key(dev, BTN_LEFT, left); |
456 | input_report_key(dev, BTN_RIGHT, right); | 458 | input_report_key(dev, BTN_RIGHT, right); |
@@ -482,9 +484,8 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse) | |||
482 | * ugh, got a packet inside our recalibration | 484 | * ugh, got a packet inside our recalibration |
483 | * window, schedule another recalibration. | 485 | * window, schedule another recalibration. |
484 | */ | 486 | */ |
485 | hgpk_dbg(psmouse, | 487 | psmouse_dbg(psmouse, |
486 | "packet inside calibration window, " | 488 | "packet inside calibration window, queueing another recalibration\n"); |
487 | "queueing another recalibration\n"); | ||
488 | psmouse_queue_work(psmouse, &priv->recalib_wq, | 489 | psmouse_queue_work(psmouse, &priv->recalib_wq, |
489 | msecs_to_jiffies(post_interrupt_delay)); | 490 | msecs_to_jiffies(post_interrupt_delay)); |
490 | } | 491 | } |
@@ -628,7 +629,7 @@ static int hgpk_reset_device(struct psmouse *psmouse, bool recalibrate) | |||
628 | 629 | ||
629 | err = hgpk_select_mode(psmouse); | 630 | err = hgpk_select_mode(psmouse); |
630 | if (err) { | 631 | if (err) { |
631 | hgpk_err(psmouse, "failed to select mode\n"); | 632 | psmouse_err(psmouse, "failed to select mode\n"); |
632 | return err; | 633 | return err; |
633 | } | 634 | } |
634 | 635 | ||
@@ -648,11 +649,11 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse) | |||
648 | return 0; | 649 | return 0; |
649 | 650 | ||
650 | if (!autorecal) { | 651 | if (!autorecal) { |
651 | hgpk_dbg(psmouse, "recalibrations disabled, ignoring\n"); | 652 | psmouse_dbg(psmouse, "recalibration disabled, ignoring\n"); |
652 | return 0; | 653 | return 0; |
653 | } | 654 | } |
654 | 655 | ||
655 | hgpk_dbg(psmouse, "recalibrating touchpad..\n"); | 656 | psmouse_dbg(psmouse, "recalibrating touchpad..\n"); |
656 | 657 | ||
657 | /* we don't want to race with the irq handler, nor with resyncs */ | 658 | /* we don't want to race with the irq handler, nor with resyncs */ |
658 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | 659 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); |
@@ -675,7 +676,7 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse) | |||
675 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 676 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
676 | 677 | ||
677 | if (tpdebug) | 678 | if (tpdebug) |
678 | hgpk_dbg(psmouse, "touchpad reactivated\n"); | 679 | psmouse_dbg(psmouse, "touchpad reactivated\n"); |
679 | 680 | ||
680 | /* | 681 | /* |
681 | * If we get packets right away after recalibrating, it's likely | 682 | * If we get packets right away after recalibrating, it's likely |
@@ -727,16 +728,16 @@ static int hgpk_toggle_powersave(struct psmouse *psmouse, int enable) | |||
727 | 728 | ||
728 | err = hgpk_reset_device(psmouse, false); | 729 | err = hgpk_reset_device(psmouse, false); |
729 | if (err) { | 730 | if (err) { |
730 | hgpk_err(psmouse, "Failed to reset device!\n"); | 731 | psmouse_err(psmouse, "Failed to reset device!\n"); |
731 | return err; | 732 | return err; |
732 | } | 733 | } |
733 | 734 | ||
734 | /* should be all set, enable the touchpad */ | 735 | /* should be all set, enable the touchpad */ |
735 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 736 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
736 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 737 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
737 | hgpk_dbg(psmouse, "Touchpad powered up.\n"); | 738 | psmouse_dbg(psmouse, "Touchpad powered up.\n"); |
738 | } else { | 739 | } else { |
739 | hgpk_dbg(psmouse, "Powering off touchpad.\n"); | 740 | psmouse_dbg(psmouse, "Powering off touchpad.\n"); |
740 | 741 | ||
741 | if (ps2_command(ps2dev, NULL, 0xec) || | 742 | if (ps2_command(ps2dev, NULL, 0xec) || |
742 | ps2_command(ps2dev, NULL, 0xec) || | 743 | ps2_command(ps2dev, NULL, 0xec) || |
@@ -923,7 +924,7 @@ static void hgpk_recalib_work(struct work_struct *work) | |||
923 | struct psmouse *psmouse = priv->psmouse; | 924 | struct psmouse *psmouse = priv->psmouse; |
924 | 925 | ||
925 | if (hgpk_force_recalibrate(psmouse)) | 926 | if (hgpk_force_recalibrate(psmouse)) |
926 | hgpk_err(psmouse, "recalibration failed!\n"); | 927 | psmouse_err(psmouse, "recalibration failed!\n"); |
927 | } | 928 | } |
928 | 929 | ||
929 | static int hgpk_register(struct psmouse *psmouse) | 930 | static int hgpk_register(struct psmouse *psmouse) |
@@ -947,14 +948,15 @@ static int hgpk_register(struct psmouse *psmouse) | |||
947 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 948 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
948 | &psmouse_attr_powered.dattr); | 949 | &psmouse_attr_powered.dattr); |
949 | if (err) { | 950 | if (err) { |
950 | hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n"); | 951 | psmouse_err(psmouse, "Failed creating 'powered' sysfs node\n"); |
951 | return err; | 952 | return err; |
952 | } | 953 | } |
953 | 954 | ||
954 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 955 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
955 | &psmouse_attr_hgpk_mode.dattr); | 956 | &psmouse_attr_hgpk_mode.dattr); |
956 | if (err) { | 957 | if (err) { |
957 | hgpk_err(psmouse, "Failed creating 'hgpk_mode' sysfs node\n"); | 958 | psmouse_err(psmouse, |
959 | "Failed creating 'hgpk_mode' sysfs node\n"); | ||
958 | goto err_remove_powered; | 960 | goto err_remove_powered; |
959 | } | 961 | } |
960 | 962 | ||
@@ -963,8 +965,8 @@ static int hgpk_register(struct psmouse *psmouse) | |||
963 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 965 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
964 | &psmouse_attr_recalibrate.dattr); | 966 | &psmouse_attr_recalibrate.dattr); |
965 | if (err) { | 967 | if (err) { |
966 | hgpk_err(psmouse, | 968 | psmouse_err(psmouse, |
967 | "Failed creating 'recalibrate' sysfs node\n"); | 969 | "Failed creating 'recalibrate' sysfs node\n"); |
968 | goto err_remove_mode; | 970 | goto err_remove_mode; |
969 | } | 971 | } |
970 | } | 972 | } |
@@ -1027,13 +1029,13 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) | |||
1027 | return -EIO; | 1029 | return -EIO; |
1028 | } | 1030 | } |
1029 | 1031 | ||
1030 | hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]); | 1032 | psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]); |
1031 | 1033 | ||
1032 | /* HGPK signature: 0x67, 0x00, 0x<model> */ | 1034 | /* HGPK signature: 0x67, 0x00, 0x<model> */ |
1033 | if (param[0] != 0x67 || param[1] != 0x00) | 1035 | if (param[0] != 0x67 || param[1] != 0x00) |
1034 | return -ENODEV; | 1036 | return -ENODEV; |
1035 | 1037 | ||
1036 | hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]); | 1038 | psmouse_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]); |
1037 | 1039 | ||
1038 | return param[2]; | 1040 | return param[2]; |
1039 | } | 1041 | } |
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h index 311c0e87fcbf..dd686771cfe0 100644 --- a/drivers/input/mouse/hgpk.h +++ b/drivers/input/mouse/hgpk.h | |||
@@ -46,17 +46,6 @@ struct hgpk_data { | |||
46 | int xsaw_secondary, ysaw_secondary; /* jumpiness detection */ | 46 | int xsaw_secondary, ysaw_secondary; /* jumpiness detection */ |
47 | }; | 47 | }; |
48 | 48 | ||
49 | #define hgpk_dbg(psmouse, format, arg...) \ | ||
50 | dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
51 | #define hgpk_err(psmouse, format, arg...) \ | ||
52 | dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
53 | #define hgpk_info(psmouse, format, arg...) \ | ||
54 | dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
55 | #define hgpk_warn(psmouse, format, arg...) \ | ||
56 | dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
57 | #define hgpk_notice(psmouse, format, arg...) \ | ||
58 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) | ||
59 | |||
60 | #ifdef CONFIG_MOUSE_PS2_OLPC | 49 | #ifdef CONFIG_MOUSE_PS2_OLPC |
61 | void hgpk_module_init(void); | 50 | void hgpk_module_init(void); |
62 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); | 51 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); |
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 83bcaba96b89..2c4db636de6c 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -169,8 +169,8 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) | |||
169 | 169 | ||
170 | if (relative_packet) { | 170 | if (relative_packet) { |
171 | if (!dev2) | 171 | if (!dev2) |
172 | printk(KERN_WARNING "lifebook.c: got relative packet " | 172 | psmouse_warn(psmouse, |
173 | "but no relative device set up\n"); | 173 | "got relative packet but no relative device set up\n"); |
174 | } else { | 174 | } else { |
175 | if (lifebook_use_6byte_proto) { | 175 | if (lifebook_use_6byte_proto) { |
176 | input_report_abs(dev1, ABS_X, | 176 | input_report_abs(dev1, ABS_X, |
@@ -212,7 +212,7 @@ static int lifebook_absolute_mode(struct psmouse *psmouse) | |||
212 | 212 | ||
213 | /* | 213 | /* |
214 | * Enable absolute output -- ps2_command fails always but if | 214 | * Enable absolute output -- ps2_command fails always but if |
215 | * you leave this call out the touchsreen will never send | 215 | * you leave this call out the touchscreen will never send |
216 | * absolute coordinates | 216 | * absolute coordinates |
217 | */ | 217 | */ |
218 | param = lifebook_use_6byte_proto ? 0x08 : 0x07; | 218 | param = lifebook_use_6byte_proto ? 0x08 : 0x07; |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index c9983aee9082..faac2c3bef74 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -82,11 +82,11 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse) | |||
82 | packet[0] = packet[2] | 0x08; | 82 | packet[0] = packet[2] | 0x08; |
83 | break; | 83 | break; |
84 | 84 | ||
85 | #ifdef DEBUG | ||
86 | default: | 85 | default: |
87 | printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n", | 86 | psmouse_dbg(psmouse, |
88 | (packet[1] >> 4) | (packet[0] & 0x30)); | 87 | "Received PS2++ packet #%x, but don't know how to handle.\n", |
89 | #endif | 88 | (packet[1] >> 4) | (packet[0] & 0x30)); |
89 | break; | ||
90 | } | 90 | } |
91 | } else { | 91 | } else { |
92 | /* Standard PS/2 motion data */ | 92 | /* Standard PS/2 motion data */ |
@@ -382,7 +382,7 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties) | |||
382 | } | 382 | } |
383 | 383 | ||
384 | } else { | 384 | } else { |
385 | printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model); | 385 | psmouse_warn(psmouse, "Detected unknown Logitech mouse model %d\n", model); |
386 | } | 386 | } |
387 | 387 | ||
388 | if (set_properties) { | 388 | if (set_properties) { |
@@ -400,9 +400,9 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties) | |||
400 | error = device_create_file(&psmouse->ps2dev.serio->dev, | 400 | error = device_create_file(&psmouse->ps2dev.serio->dev, |
401 | &psmouse_attr_smartscroll.dattr); | 401 | &psmouse_attr_smartscroll.dattr); |
402 | if (error) { | 402 | if (error) { |
403 | printk(KERN_ERR | 403 | psmouse_err(psmouse, |
404 | "logips2pp.c: failed to create smartscroll " | 404 | "failed to create smartscroll sysfs attribute, error: %d\n", |
405 | "sysfs attribute, error: %d\n", error); | 405 | error); |
406 | return -1; | 406 | return -1; |
407 | } | 407 | } |
408 | } | 408 | } |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 3f74baee102b..9f352fbd7b4f 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -11,6 +11,9 @@ | |||
11 | * the Free Software Foundation. | 11 | * the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
15 | #define psmouse_fmt(fmt) fmt | ||
16 | |||
14 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
15 | #include <linux/module.h> | 18 | #include <linux/module.h> |
16 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
@@ -251,11 +254,14 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
251 | switch (rc) { | 254 | switch (rc) { |
252 | case PSMOUSE_BAD_DATA: | 255 | case PSMOUSE_BAD_DATA: |
253 | if (psmouse->state == PSMOUSE_ACTIVATED) { | 256 | if (psmouse->state == PSMOUSE_ACTIVATED) { |
254 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | 257 | psmouse_warn(psmouse, |
255 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 258 | "%s at %s lost sync at byte %d\n", |
259 | psmouse->name, psmouse->phys, | ||
260 | psmouse->pktcnt); | ||
256 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { | 261 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { |
257 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 262 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
258 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 263 | psmouse_notice(psmouse, |
264 | "issuing reconnect request\n"); | ||
259 | serio_reconnect(psmouse->ps2dev.serio); | 265 | serio_reconnect(psmouse->ps2dev.serio); |
260 | return -1; | 266 | return -1; |
261 | } | 267 | } |
@@ -267,8 +273,9 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
267 | psmouse->pktcnt = 0; | 273 | psmouse->pktcnt = 0; |
268 | if (psmouse->out_of_sync_cnt) { | 274 | if (psmouse->out_of_sync_cnt) { |
269 | psmouse->out_of_sync_cnt = 0; | 275 | psmouse->out_of_sync_cnt = 0; |
270 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | 276 | psmouse_notice(psmouse, |
271 | psmouse->name, psmouse->phys); | 277 | "%s at %s - driver resynced.\n", |
278 | psmouse->name, psmouse->phys); | ||
272 | } | 279 | } |
273 | break; | 280 | break; |
274 | 281 | ||
@@ -295,9 +302,10 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
295 | ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { | 302 | ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { |
296 | 303 | ||
297 | if (psmouse->state == PSMOUSE_ACTIVATED) | 304 | if (psmouse->state == PSMOUSE_ACTIVATED) |
298 | printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", | 305 | psmouse_warn(psmouse, |
299 | flags & SERIO_TIMEOUT ? " timeout" : "", | 306 | "bad data from KBC -%s%s\n", |
300 | flags & SERIO_PARITY ? " bad parity" : ""); | 307 | flags & SERIO_TIMEOUT ? " timeout" : "", |
308 | flags & SERIO_PARITY ? " bad parity" : ""); | ||
301 | ps2_cmd_aborted(&psmouse->ps2dev); | 309 | ps2_cmd_aborted(&psmouse->ps2dev); |
302 | goto out; | 310 | goto out; |
303 | } | 311 | } |
@@ -315,8 +323,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
315 | 323 | ||
316 | if (psmouse->state == PSMOUSE_ACTIVATED && | 324 | if (psmouse->state == PSMOUSE_ACTIVATED && |
317 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { | 325 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { |
318 | printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", | 326 | psmouse_info(psmouse, "%s at %s lost synchronization, throwing %d bytes away.\n", |
319 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 327 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
320 | psmouse->badbyte = psmouse->packet[0]; | 328 | psmouse->badbyte = psmouse->packet[0]; |
321 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 329 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
322 | psmouse_queue_work(psmouse, &psmouse->resync_work, 0); | 330 | psmouse_queue_work(psmouse, &psmouse->resync_work, 0); |
@@ -943,7 +951,8 @@ static int psmouse_probe(struct psmouse *psmouse) | |||
943 | */ | 951 | */ |
944 | 952 | ||
945 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS)) | 953 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_DIS)) |
946 | printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", ps2dev->serio->phys); | 954 | psmouse_warn(psmouse, "Failed to reset mouse on %s\n", |
955 | ps2dev->serio->phys); | ||
947 | 956 | ||
948 | return 0; | 957 | return 0; |
949 | } | 958 | } |
@@ -1005,8 +1014,8 @@ static void psmouse_initialize(struct psmouse *psmouse) | |||
1005 | static void psmouse_activate(struct psmouse *psmouse) | 1014 | static void psmouse_activate(struct psmouse *psmouse) |
1006 | { | 1015 | { |
1007 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) | 1016 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) |
1008 | printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", | 1017 | psmouse_warn(psmouse, "Failed to enable mouse on %s\n", |
1009 | psmouse->ps2dev.serio->phys); | 1018 | psmouse->ps2dev.serio->phys); |
1010 | 1019 | ||
1011 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 1020 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
1012 | } | 1021 | } |
@@ -1020,14 +1029,14 @@ static void psmouse_activate(struct psmouse *psmouse) | |||
1020 | static void psmouse_deactivate(struct psmouse *psmouse) | 1029 | static void psmouse_deactivate(struct psmouse *psmouse) |
1021 | { | 1030 | { |
1022 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) | 1031 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) |
1023 | printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n", | 1032 | psmouse_warn(psmouse, "Failed to deactivate mouse on %s\n", |
1024 | psmouse->ps2dev.serio->phys); | 1033 | psmouse->ps2dev.serio->phys); |
1025 | 1034 | ||
1026 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 1035 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
1027 | } | 1036 | } |
1028 | 1037 | ||
1029 | /* | 1038 | /* |
1030 | * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it. | 1039 | * psmouse_poll() - default poll handler. Everyone except for ALPS uses it. |
1031 | */ | 1040 | */ |
1032 | 1041 | ||
1033 | static int psmouse_poll(struct psmouse *psmouse) | 1042 | static int psmouse_poll(struct psmouse *psmouse) |
@@ -1115,14 +1124,15 @@ static void psmouse_resync(struct work_struct *work) | |||
1115 | } | 1124 | } |
1116 | 1125 | ||
1117 | if (!enabled) { | 1126 | if (!enabled) { |
1118 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", | 1127 | psmouse_warn(psmouse, "failed to re-enable mouse on %s\n", |
1119 | psmouse->ps2dev.serio->phys); | 1128 | psmouse->ps2dev.serio->phys); |
1120 | failed = true; | 1129 | failed = true; |
1121 | } | 1130 | } |
1122 | 1131 | ||
1123 | if (failed) { | 1132 | if (failed) { |
1124 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 1133 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
1125 | printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n"); | 1134 | psmouse_info(psmouse, |
1135 | "resync failed, issuing reconnect request\n"); | ||
1126 | serio_reconnect(serio); | 1136 | serio_reconnect(serio); |
1127 | } else | 1137 | } else |
1128 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 1138 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
@@ -1155,8 +1165,8 @@ static void psmouse_cleanup(struct serio *serio) | |||
1155 | * Disable stream mode so cleanup routine can proceed undisturbed. | 1165 | * Disable stream mode so cleanup routine can proceed undisturbed. |
1156 | */ | 1166 | */ |
1157 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) | 1167 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) |
1158 | printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n", | 1168 | psmouse_warn(psmouse, "Failed to disable mouse on %s\n", |
1159 | psmouse->ps2dev.serio->phys); | 1169 | psmouse->ps2dev.serio->phys); |
1160 | 1170 | ||
1161 | if (psmouse->cleanup) | 1171 | if (psmouse->cleanup) |
1162 | psmouse->cleanup(psmouse); | 1172 | psmouse->cleanup(psmouse); |
@@ -1400,7 +1410,8 @@ static int psmouse_reconnect(struct serio *serio) | |||
1400 | int rc = -1; | 1410 | int rc = -1; |
1401 | 1411 | ||
1402 | if (!drv || !psmouse) { | 1412 | if (!drv || !psmouse) { |
1403 | printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n"); | 1413 | psmouse_dbg(psmouse, |
1414 | "reconnect request, but serio is disconnected, ignoring...\n"); | ||
1404 | return -1; | 1415 | return -1; |
1405 | } | 1416 | } |
1406 | 1417 | ||
@@ -1427,8 +1438,9 @@ static int psmouse_reconnect(struct serio *serio) | |||
1427 | goto out; | 1438 | goto out; |
1428 | } | 1439 | } |
1429 | 1440 | ||
1430 | /* ok, the device type (and capabilities) match the old one, | 1441 | /* |
1431 | * we can continue using it, complete intialization | 1442 | * OK, the device type (and capabilities) match the old one, |
1443 | * we can continue using it, complete initialization | ||
1432 | */ | 1444 | */ |
1433 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 1445 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
1434 | 1446 | ||
@@ -1586,9 +1598,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
1586 | 1598 | ||
1587 | while (!list_empty(&serio->children)) { | 1599 | while (!list_empty(&serio->children)) { |
1588 | if (++retry > 3) { | 1600 | if (++retry > 3) { |
1589 | printk(KERN_WARNING | 1601 | psmouse_warn(psmouse, |
1590 | "psmouse: failed to destroy children ports, " | 1602 | "failed to destroy children ports, protocol change aborted.\n"); |
1591 | "protocol change aborted.\n"); | ||
1592 | input_free_device(new_dev); | 1603 | input_free_device(new_dev); |
1593 | return -EIO; | 1604 | return -EIO; |
1594 | } | 1605 | } |
@@ -1715,7 +1726,7 @@ static int __init psmouse_init(void) | |||
1715 | 1726 | ||
1716 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | 1727 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); |
1717 | if (!kpsmoused_wq) { | 1728 | if (!kpsmoused_wq) { |
1718 | printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); | 1729 | pr_err("failed to create kpsmoused workqueue\n"); |
1719 | return -ENOMEM; | 1730 | return -ENOMEM; |
1720 | } | 1731 | } |
1721 | 1732 | ||
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 593e910bfc7a..9b84b0c4e371 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -150,4 +150,29 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ | |||
150 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | 150 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ |
151 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true) | 151 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true) |
152 | 152 | ||
153 | #ifndef psmouse_fmt | ||
154 | #define psmouse_fmt(fmt) KBUILD_BASENAME ": " fmt | ||
155 | #endif | ||
156 | |||
157 | #define psmouse_dbg(psmouse, format, ...) \ | ||
158 | dev_dbg(&(psmouse)->ps2dev.serio->dev, \ | ||
159 | psmouse_fmt(format), ##__VA_ARGS__) | ||
160 | #define psmouse_info(psmouse, format, ...) \ | ||
161 | dev_info(&(psmouse)->ps2dev.serio->dev, \ | ||
162 | psmouse_fmt(format), ##__VA_ARGS__) | ||
163 | #define psmouse_warn(psmouse, format, ...) \ | ||
164 | dev_warn(&(psmouse)->ps2dev.serio->dev, \ | ||
165 | psmouse_fmt(format), ##__VA_ARGS__) | ||
166 | #define psmouse_err(psmouse, format, ...) \ | ||
167 | dev_err(&(psmouse)->ps2dev.serio->dev, \ | ||
168 | psmouse_fmt(format), ##__VA_ARGS__) | ||
169 | #define psmouse_notice(psmouse, format, ...) \ | ||
170 | dev_notice(&(psmouse)->ps2dev.serio->dev, \ | ||
171 | psmouse_fmt(format), ##__VA_ARGS__) | ||
172 | #define psmouse_printk(level, psmouse, format, ...) \ | ||
173 | dev_printk(level, \ | ||
174 | &(psmouse)->ps2dev.serio->dev, \ | ||
175 | psmouse_fmt(format), ##__VA_ARGS__) | ||
176 | |||
177 | |||
153 | #endif /* _PSMOUSE_H */ | 178 | #endif /* _PSMOUSE_H */ |
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 6c5d84fcdea1..ee3b0ca9d592 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c | |||
@@ -183,7 +183,7 @@ static int __devinit pxa930_trkball_probe(struct platform_device *pdev) | |||
183 | /* held the module in reset, will be enabled in open() */ | 183 | /* held the module in reset, will be enabled in open() */ |
184 | pxa930_trkball_disable(trkball); | 184 | pxa930_trkball_disable(trkball); |
185 | 185 | ||
186 | error = request_irq(irq, pxa930_trkball_interrupt, IRQF_DISABLED, | 186 | error = request_irq(irq, pxa930_trkball_interrupt, 0, |
187 | pdev->name, trkball); | 187 | pdev->name, trkball); |
188 | if (error) { | 188 | if (error) { |
189 | dev_err(&pdev->dev, "failed to request irq: %d\n", error); | 189 | dev_err(&pdev->dev, "failed to request irq: %d\n", error); |
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 2fc887a51066..c5b12d2e955a 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
@@ -607,11 +607,12 @@ static void fsp_packet_debug(unsigned char packet[]) | |||
607 | 607 | ||
608 | ps2_packet_cnt++; | 608 | ps2_packet_cnt++; |
609 | jiffies_msec = jiffies_to_msecs(jiffies); | 609 | jiffies_msec = jiffies_to_msecs(jiffies); |
610 | printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", | 610 | psmouse_dbg(psmouse, |
611 | jiffies_msec, packet[0], packet[1], packet[2], packet[3]); | 611 | "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", |
612 | jiffies_msec, packet[0], packet[1], packet[2], packet[3]); | ||
612 | 613 | ||
613 | if (jiffies_msec - ps2_last_second > 1000) { | 614 | if (jiffies_msec - ps2_last_second > 1000) { |
614 | printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt); | 615 | psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt); |
615 | ps2_packet_cnt = 0; | 616 | ps2_packet_cnt = 0; |
616 | ps2_last_second = jiffies_msec; | 617 | ps2_last_second = jiffies_msec; |
617 | } | 618 | } |
@@ -820,9 +821,9 @@ int fsp_init(struct psmouse *psmouse) | |||
820 | return -ENODEV; | 821 | return -ENODEV; |
821 | } | 822 | } |
822 | 823 | ||
823 | printk(KERN_INFO | 824 | psmouse_info(psmouse, |
824 | "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", | 825 | "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", |
825 | ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); | 826 | ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); |
826 | 827 | ||
827 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); | 828 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); |
828 | if (!priv) | 829 | if (!priv) |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 5538fc657af1..c080b828e5dc 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -44,6 +44,16 @@ | |||
44 | #define YMIN_NOMINAL 1408 | 44 | #define YMIN_NOMINAL 1408 |
45 | #define YMAX_NOMINAL 4448 | 45 | #define YMAX_NOMINAL 4448 |
46 | 46 | ||
47 | /* | ||
48 | * Synaptics touchpads report the y coordinate from bottom to top, which is | ||
49 | * opposite from what userspace expects. | ||
50 | * This function is used to invert y before reporting. | ||
51 | */ | ||
52 | static int synaptics_invert_y(int y) | ||
53 | { | ||
54 | return YMAX_NOMINAL + YMIN_NOMINAL - y; | ||
55 | } | ||
56 | |||
47 | 57 | ||
48 | /***************************************************************************** | 58 | /***************************************************************************** |
49 | * Stuff we need even when we do not want native Synaptics support | 59 | * Stuff we need even when we do not want native Synaptics support |
@@ -157,8 +167,8 @@ static int synaptics_capability(struct psmouse *psmouse) | |||
157 | 167 | ||
158 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { | 168 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { |
159 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { | 169 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { |
160 | printk(KERN_ERR "Synaptics claims to have extended capabilities," | 170 | psmouse_warn(psmouse, |
161 | " but I'm not able to read them.\n"); | 171 | "device claims to have extended capabilities, but I'm not able to read them.\n"); |
162 | } else { | 172 | } else { |
163 | priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 173 | priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
164 | 174 | ||
@@ -173,8 +183,8 @@ static int synaptics_capability(struct psmouse *psmouse) | |||
173 | 183 | ||
174 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { | 184 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { |
175 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { | 185 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { |
176 | printk(KERN_ERR "Synaptics claims to have extended capability 0x0c," | 186 | psmouse_warn(psmouse, |
177 | " but I'm not able to read it.\n"); | 187 | "device claims to have extended capability 0x0c, but I'm not able to read it.\n"); |
178 | } else { | 188 | } else { |
179 | priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 189 | priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
180 | } | 190 | } |
@@ -222,8 +232,8 @@ static int synaptics_resolution(struct psmouse *psmouse) | |||
222 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && | 232 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && |
223 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { | 233 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { |
224 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { | 234 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { |
225 | printk(KERN_ERR "Synaptics claims to have max coordinates" | 235 | psmouse_warn(psmouse, |
226 | " query, but I'm not able to read it.\n"); | 236 | "device claims to have max coordinates query, but I'm not able to read it.\n"); |
227 | } else { | 237 | } else { |
228 | priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); | 238 | priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); |
229 | priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); | 239 | priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); |
@@ -233,8 +243,8 @@ static int synaptics_resolution(struct psmouse *psmouse) | |||
233 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && | 243 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && |
234 | SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { | 244 | SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { |
235 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { | 245 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { |
236 | printk(KERN_ERR "Synaptics claims to have min coordinates" | 246 | psmouse_warn(psmouse, |
237 | " query, but I'm not able to read it.\n"); | 247 | "device claims to have min coordinates query, but I'm not able to read it.\n"); |
238 | } else { | 248 | } else { |
239 | priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); | 249 | priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); |
240 | priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); | 250 | priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); |
@@ -294,7 +304,8 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) | |||
294 | static unsigned char param = 0xc8; | 304 | static unsigned char param = 0xc8; |
295 | struct synaptics_data *priv = psmouse->private; | 305 | struct synaptics_data *priv = psmouse->private; |
296 | 306 | ||
297 | if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | 307 | if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || |
308 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) | ||
298 | return 0; | 309 | return 0; |
299 | 310 | ||
300 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) | 311 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) |
@@ -377,7 +388,8 @@ static void synaptics_pt_activate(struct psmouse *psmouse) | |||
377 | priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT; | 388 | priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT; |
378 | 389 | ||
379 | if (synaptics_mode_cmd(psmouse, priv->mode)) | 390 | if (synaptics_mode_cmd(psmouse, priv->mode)) |
380 | printk(KERN_INFO "synaptics: failed to switch guest protocol\n"); | 391 | psmouse_warn(psmouse, |
392 | "failed to switch guest protocol\n"); | ||
381 | } | 393 | } |
382 | } | 394 | } |
383 | 395 | ||
@@ -387,7 +399,8 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
387 | 399 | ||
388 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 400 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
389 | if (!serio) { | 401 | if (!serio) { |
390 | printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n"); | 402 | psmouse_err(psmouse, |
403 | "not enough memory for pass-through port\n"); | ||
391 | return; | 404 | return; |
392 | } | 405 | } |
393 | 406 | ||
@@ -401,7 +414,8 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
401 | 414 | ||
402 | psmouse->pt_activate = synaptics_pt_activate; | 415 | psmouse->pt_activate = synaptics_pt_activate; |
403 | 416 | ||
404 | printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys); | 417 | psmouse_info(psmouse, "serio: %s port at %s\n", |
418 | serio->name, psmouse->phys); | ||
405 | serio_register_port(serio); | 419 | serio_register_port(serio); |
406 | } | 420 | } |
407 | 421 | ||
@@ -409,6 +423,44 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
409 | * Functions to interpret the absolute mode packets | 423 | * Functions to interpret the absolute mode packets |
410 | ****************************************************************************/ | 424 | ****************************************************************************/ |
411 | 425 | ||
426 | static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count, | ||
427 | int sgm, int agm) | ||
428 | { | ||
429 | state->count = count; | ||
430 | state->sgm = sgm; | ||
431 | state->agm = agm; | ||
432 | } | ||
433 | |||
434 | static void synaptics_parse_agm(const unsigned char buf[], | ||
435 | struct synaptics_data *priv, | ||
436 | struct synaptics_hw_state *hw) | ||
437 | { | ||
438 | struct synaptics_hw_state *agm = &priv->agm; | ||
439 | int agm_packet_type; | ||
440 | |||
441 | agm_packet_type = (buf[5] & 0x30) >> 4; | ||
442 | switch (agm_packet_type) { | ||
443 | case 1: | ||
444 | /* Gesture packet: (x, y, z) half resolution */ | ||
445 | agm->w = hw->w; | ||
446 | agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; | ||
447 | agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; | ||
448 | agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; | ||
449 | break; | ||
450 | |||
451 | case 2: | ||
452 | /* AGM-CONTACT packet: (count, sgm, agm) */ | ||
453 | synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]); | ||
454 | break; | ||
455 | |||
456 | default: | ||
457 | break; | ||
458 | } | ||
459 | |||
460 | /* Record that at least one AGM has been received since last SGM */ | ||
461 | priv->agm_pending = true; | ||
462 | } | ||
463 | |||
412 | static int synaptics_parse_hw_state(const unsigned char buf[], | 464 | static int synaptics_parse_hw_state(const unsigned char buf[], |
413 | struct synaptics_data *priv, | 465 | struct synaptics_data *priv, |
414 | struct synaptics_hw_state *hw) | 466 | struct synaptics_hw_state *hw) |
@@ -442,11 +494,10 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
442 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; | 494 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; |
443 | } | 495 | } |
444 | 496 | ||
445 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) { | 497 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || |
446 | /* Gesture packet: (x, y, z) at half resolution */ | 498 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && |
447 | priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; | 499 | hw->w == 2) { |
448 | priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; | 500 | synaptics_parse_agm(buf, priv, hw); |
449 | priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; | ||
450 | return 1; | 501 | return 1; |
451 | } | 502 | } |
452 | 503 | ||
@@ -502,8 +553,7 @@ static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot, | |||
502 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | 553 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); |
503 | if (active) { | 554 | if (active) { |
504 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 555 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
505 | input_report_abs(dev, ABS_MT_POSITION_Y, | 556 | input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y)); |
506 | YMAX_NOMINAL + YMIN_NOMINAL - y); | ||
507 | } | 557 | } |
508 | } | 558 | } |
509 | 559 | ||
@@ -526,6 +576,388 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev, | |||
526 | } | 576 | } |
527 | } | 577 | } |
528 | 578 | ||
579 | static void synaptics_report_buttons(struct psmouse *psmouse, | ||
580 | const struct synaptics_hw_state *hw) | ||
581 | { | ||
582 | struct input_dev *dev = psmouse->dev; | ||
583 | struct synaptics_data *priv = psmouse->private; | ||
584 | int i; | ||
585 | |||
586 | input_report_key(dev, BTN_LEFT, hw->left); | ||
587 | input_report_key(dev, BTN_RIGHT, hw->right); | ||
588 | |||
589 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | ||
590 | input_report_key(dev, BTN_MIDDLE, hw->middle); | ||
591 | |||
592 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { | ||
593 | input_report_key(dev, BTN_FORWARD, hw->up); | ||
594 | input_report_key(dev, BTN_BACK, hw->down); | ||
595 | } | ||
596 | |||
597 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | ||
598 | input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); | ||
599 | } | ||
600 | |||
601 | static void synaptics_report_slot(struct input_dev *dev, int slot, | ||
602 | const struct synaptics_hw_state *hw) | ||
603 | { | ||
604 | input_mt_slot(dev, slot); | ||
605 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL)); | ||
606 | if (!hw) | ||
607 | return; | ||
608 | |||
609 | input_report_abs(dev, ABS_MT_POSITION_X, hw->x); | ||
610 | input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y)); | ||
611 | input_report_abs(dev, ABS_MT_PRESSURE, hw->z); | ||
612 | } | ||
613 | |||
614 | static void synaptics_report_mt_data(struct psmouse *psmouse, | ||
615 | struct synaptics_mt_state *mt_state, | ||
616 | const struct synaptics_hw_state *sgm) | ||
617 | { | ||
618 | struct input_dev *dev = psmouse->dev; | ||
619 | struct synaptics_data *priv = psmouse->private; | ||
620 | struct synaptics_hw_state *agm = &priv->agm; | ||
621 | struct synaptics_mt_state *old = &priv->mt_state; | ||
622 | |||
623 | switch (mt_state->count) { | ||
624 | case 0: | ||
625 | synaptics_report_slot(dev, 0, NULL); | ||
626 | synaptics_report_slot(dev, 1, NULL); | ||
627 | break; | ||
628 | case 1: | ||
629 | if (mt_state->sgm == -1) { | ||
630 | synaptics_report_slot(dev, 0, NULL); | ||
631 | synaptics_report_slot(dev, 1, NULL); | ||
632 | } else if (mt_state->sgm == 0) { | ||
633 | synaptics_report_slot(dev, 0, sgm); | ||
634 | synaptics_report_slot(dev, 1, NULL); | ||
635 | } else { | ||
636 | synaptics_report_slot(dev, 0, NULL); | ||
637 | synaptics_report_slot(dev, 1, sgm); | ||
638 | } | ||
639 | break; | ||
640 | default: | ||
641 | /* | ||
642 | * If the finger slot contained in SGM is valid, and either | ||
643 | * hasn't changed, or is new, then report SGM in MTB slot 0. | ||
644 | * Otherwise, empty MTB slot 0. | ||
645 | */ | ||
646 | if (mt_state->sgm != -1 && | ||
647 | (mt_state->sgm == old->sgm || old->sgm == -1)) | ||
648 | synaptics_report_slot(dev, 0, sgm); | ||
649 | else | ||
650 | synaptics_report_slot(dev, 0, NULL); | ||
651 | |||
652 | /* | ||
653 | * If the finger slot contained in AGM is valid, and either | ||
654 | * hasn't changed, or is new, then report AGM in MTB slot 1. | ||
655 | * Otherwise, empty MTB slot 1. | ||
656 | */ | ||
657 | if (mt_state->agm != -1 && | ||
658 | (mt_state->agm == old->agm || old->agm == -1)) | ||
659 | synaptics_report_slot(dev, 1, agm); | ||
660 | else | ||
661 | synaptics_report_slot(dev, 1, NULL); | ||
662 | break; | ||
663 | } | ||
664 | |||
665 | /* Don't use active slot count to generate BTN_TOOL events. */ | ||
666 | input_mt_report_pointer_emulation(dev, false); | ||
667 | |||
668 | /* Send the number of fingers reported by touchpad itself. */ | ||
669 | input_mt_report_finger_count(dev, mt_state->count); | ||
670 | |||
671 | synaptics_report_buttons(psmouse, sgm); | ||
672 | |||
673 | input_sync(dev); | ||
674 | } | ||
675 | |||
676 | /* Handle case where mt_state->count = 0 */ | ||
677 | static void synaptics_image_sensor_0f(struct synaptics_data *priv, | ||
678 | struct synaptics_mt_state *mt_state) | ||
679 | { | ||
680 | synaptics_mt_state_set(mt_state, 0, -1, -1); | ||
681 | priv->mt_state_lost = false; | ||
682 | } | ||
683 | |||
684 | /* Handle case where mt_state->count = 1 */ | ||
685 | static void synaptics_image_sensor_1f(struct synaptics_data *priv, | ||
686 | struct synaptics_mt_state *mt_state) | ||
687 | { | ||
688 | struct synaptics_hw_state *agm = &priv->agm; | ||
689 | struct synaptics_mt_state *old = &priv->mt_state; | ||
690 | |||
691 | /* | ||
692 | * If the last AGM was (0,0,0), and there is only one finger left, | ||
693 | * then we absolutely know that SGM contains slot 0, and all other | ||
694 | * fingers have been removed. | ||
695 | */ | ||
696 | if (priv->agm_pending && agm->z == 0) { | ||
697 | synaptics_mt_state_set(mt_state, 1, 0, -1); | ||
698 | priv->mt_state_lost = false; | ||
699 | return; | ||
700 | } | ||
701 | |||
702 | switch (old->count) { | ||
703 | case 0: | ||
704 | synaptics_mt_state_set(mt_state, 1, 0, -1); | ||
705 | break; | ||
706 | case 1: | ||
707 | /* | ||
708 | * If mt_state_lost, then the previous transition was 3->1, | ||
709 | * and SGM now contains either slot 0 or 1, but we don't know | ||
710 | * which. So, we just assume that the SGM now contains slot 1. | ||
711 | * | ||
712 | * If pending AGM and either: | ||
713 | * (a) the previous SGM slot contains slot 0, or | ||
714 | * (b) there was no SGM slot | ||
715 | * then, the SGM now contains slot 1 | ||
716 | * | ||
717 | * Case (a) happens with very rapid "drum roll" gestures, where | ||
718 | * slot 0 finger is lifted and a new slot 1 finger touches | ||
719 | * within one reporting interval. | ||
720 | * | ||
721 | * Case (b) happens if initially two or more fingers tap | ||
722 | * briefly, and all but one lift before the end of the first | ||
723 | * reporting interval. | ||
724 | * | ||
725 | * (In both these cases, slot 0 will becomes empty, so SGM | ||
726 | * contains slot 1 with the new finger) | ||
727 | * | ||
728 | * Else, if there was no previous SGM, it now contains slot 0. | ||
729 | * | ||
730 | * Otherwise, SGM still contains the same slot. | ||
731 | */ | ||
732 | if (priv->mt_state_lost || | ||
733 | (priv->agm_pending && old->sgm <= 0)) | ||
734 | synaptics_mt_state_set(mt_state, 1, 1, -1); | ||
735 | else if (old->sgm == -1) | ||
736 | synaptics_mt_state_set(mt_state, 1, 0, -1); | ||
737 | break; | ||
738 | case 2: | ||
739 | /* | ||
740 | * If mt_state_lost, we don't know which finger SGM contains. | ||
741 | * | ||
742 | * So, report 1 finger, but with both slots empty. | ||
743 | * We will use slot 1 on subsequent 1->1 | ||
744 | */ | ||
745 | if (priv->mt_state_lost) { | ||
746 | synaptics_mt_state_set(mt_state, 1, -1, -1); | ||
747 | break; | ||
748 | } | ||
749 | /* | ||
750 | * Since the last AGM was NOT (0,0,0), it was the finger in | ||
751 | * slot 0 that has been removed. | ||
752 | * So, SGM now contains previous AGM's slot, and AGM is now | ||
753 | * empty. | ||
754 | */ | ||
755 | synaptics_mt_state_set(mt_state, 1, old->agm, -1); | ||
756 | break; | ||
757 | case 3: | ||
758 | /* | ||
759 | * Since last AGM was not (0,0,0), we don't know which finger | ||
760 | * is left. | ||
761 | * | ||
762 | * So, report 1 finger, but with both slots empty. | ||
763 | * We will use slot 1 on subsequent 1->1 | ||
764 | */ | ||
765 | synaptics_mt_state_set(mt_state, 1, -1, -1); | ||
766 | priv->mt_state_lost = true; | ||
767 | break; | ||
768 | case 4: | ||
769 | case 5: | ||
770 | /* mt_state was updated by AGM-CONTACT packet */ | ||
771 | break; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | /* Handle case where mt_state->count = 2 */ | ||
776 | static void synaptics_image_sensor_2f(struct synaptics_data *priv, | ||
777 | struct synaptics_mt_state *mt_state) | ||
778 | { | ||
779 | struct synaptics_mt_state *old = &priv->mt_state; | ||
780 | |||
781 | switch (old->count) { | ||
782 | case 0: | ||
783 | synaptics_mt_state_set(mt_state, 2, 0, 1); | ||
784 | break; | ||
785 | case 1: | ||
786 | /* | ||
787 | * If previous SGM contained slot 1 or higher, SGM now contains | ||
788 | * slot 0 (the newly touching finger) and AGM contains SGM's | ||
789 | * previous slot. | ||
790 | * | ||
791 | * Otherwise, SGM still contains slot 0 and AGM now contains | ||
792 | * slot 1. | ||
793 | */ | ||
794 | if (old->sgm >= 1) | ||
795 | synaptics_mt_state_set(mt_state, 2, 0, old->sgm); | ||
796 | else | ||
797 | synaptics_mt_state_set(mt_state, 2, 0, 1); | ||
798 | break; | ||
799 | case 2: | ||
800 | /* | ||
801 | * If mt_state_lost, SGM now contains either finger 1 or 2, but | ||
802 | * we don't know which. | ||
803 | * So, we just assume that the SGM contains slot 0 and AGM 1. | ||
804 | */ | ||
805 | if (priv->mt_state_lost) | ||
806 | synaptics_mt_state_set(mt_state, 2, 0, 1); | ||
807 | /* | ||
808 | * Otherwise, use the same mt_state, since it either hasn't | ||
809 | * changed, or was updated by a recently received AGM-CONTACT | ||
810 | * packet. | ||
811 | */ | ||
812 | break; | ||
813 | case 3: | ||
814 | /* | ||
815 | * 3->2 transitions have two unsolvable problems: | ||
816 | * 1) no indication is given which finger was removed | ||
817 | * 2) no way to tell if agm packet was for finger 3 | ||
818 | * before 3->2, or finger 2 after 3->2. | ||
819 | * | ||
820 | * So, report 2 fingers, but empty all slots. | ||
821 | * We will guess slots [0,1] on subsequent 2->2. | ||
822 | */ | ||
823 | synaptics_mt_state_set(mt_state, 2, -1, -1); | ||
824 | priv->mt_state_lost = true; | ||
825 | break; | ||
826 | case 4: | ||
827 | case 5: | ||
828 | /* mt_state was updated by AGM-CONTACT packet */ | ||
829 | break; | ||
830 | } | ||
831 | } | ||
832 | |||
833 | /* Handle case where mt_state->count = 3 */ | ||
834 | static void synaptics_image_sensor_3f(struct synaptics_data *priv, | ||
835 | struct synaptics_mt_state *mt_state) | ||
836 | { | ||
837 | struct synaptics_mt_state *old = &priv->mt_state; | ||
838 | |||
839 | switch (old->count) { | ||
840 | case 0: | ||
841 | synaptics_mt_state_set(mt_state, 3, 0, 2); | ||
842 | break; | ||
843 | case 1: | ||
844 | /* | ||
845 | * If previous SGM contained slot 2 or higher, SGM now contains | ||
846 | * slot 0 (one of the newly touching fingers) and AGM contains | ||
847 | * SGM's previous slot. | ||
848 | * | ||
849 | * Otherwise, SGM now contains slot 0 and AGM contains slot 2. | ||
850 | */ | ||
851 | if (old->sgm >= 2) | ||
852 | synaptics_mt_state_set(mt_state, 3, 0, old->sgm); | ||
853 | else | ||
854 | synaptics_mt_state_set(mt_state, 3, 0, 2); | ||
855 | break; | ||
856 | case 2: | ||
857 | /* | ||
858 | * If the AGM previously contained slot 3 or higher, then the | ||
859 | * newly touching finger is in the lowest available slot. | ||
860 | * | ||
861 | * If SGM was previously 1 or higher, then the new SGM is | ||
862 | * now slot 0 (with a new finger), otherwise, the new finger | ||
863 | * is now in a hidden slot between 0 and AGM's slot. | ||
864 | * | ||
865 | * In all such cases, the SGM now contains slot 0, and the AGM | ||
866 | * continues to contain the same slot as before. | ||
867 | */ | ||
868 | if (old->agm >= 3) { | ||
869 | synaptics_mt_state_set(mt_state, 3, 0, old->agm); | ||
870 | break; | ||
871 | } | ||
872 | |||
873 | /* | ||
874 | * After some 3->1 and all 3->2 transitions, we lose track | ||
875 | * of which slot is reported by SGM and AGM. | ||
876 | * | ||
877 | * For 2->3 in this state, report 3 fingers, but empty all | ||
878 | * slots, and we will guess (0,2) on a subsequent 0->3. | ||
879 | * | ||
880 | * To userspace, the resulting transition will look like: | ||
881 | * 2:[0,1] -> 3:[-1,-1] -> 3:[0,2] | ||
882 | */ | ||
883 | if (priv->mt_state_lost) { | ||
884 | synaptics_mt_state_set(mt_state, 3, -1, -1); | ||
885 | break; | ||
886 | } | ||
887 | |||
888 | /* | ||
889 | * If the (SGM,AGM) really previously contained slots (0, 1), | ||
890 | * then we cannot know what slot was just reported by the AGM, | ||
891 | * because the 2->3 transition can occur either before or after | ||
892 | * the AGM packet. Thus, this most recent AGM could contain | ||
893 | * either the same old slot 1 or the new slot 2. | ||
894 | * Subsequent AGMs will be reporting slot 2. | ||
895 | * | ||
896 | * To userspace, the resulting transition will look like: | ||
897 | * 2:[0,1] -> 3:[0,-1] -> 3:[0,2] | ||
898 | */ | ||
899 | synaptics_mt_state_set(mt_state, 3, 0, -1); | ||
900 | break; | ||
901 | case 3: | ||
902 | /* | ||
903 | * If, for whatever reason, the previous agm was invalid, | ||
904 | * Assume SGM now contains slot 0, AGM now contains slot 2. | ||
905 | */ | ||
906 | if (old->agm <= 2) | ||
907 | synaptics_mt_state_set(mt_state, 3, 0, 2); | ||
908 | /* | ||
909 | * mt_state either hasn't changed, or was updated by a recently | ||
910 | * received AGM-CONTACT packet. | ||
911 | */ | ||
912 | break; | ||
913 | |||
914 | case 4: | ||
915 | case 5: | ||
916 | /* mt_state was updated by AGM-CONTACT packet */ | ||
917 | break; | ||
918 | } | ||
919 | } | ||
920 | |||
921 | /* Handle case where mt_state->count = 4, or = 5 */ | ||
922 | static void synaptics_image_sensor_45f(struct synaptics_data *priv, | ||
923 | struct synaptics_mt_state *mt_state) | ||
924 | { | ||
925 | /* mt_state was updated correctly by AGM-CONTACT packet */ | ||
926 | priv->mt_state_lost = false; | ||
927 | } | ||
928 | |||
929 | static void synaptics_image_sensor_process(struct psmouse *psmouse, | ||
930 | struct synaptics_hw_state *sgm) | ||
931 | { | ||
932 | struct synaptics_data *priv = psmouse->private; | ||
933 | struct synaptics_hw_state *agm = &priv->agm; | ||
934 | struct synaptics_mt_state mt_state; | ||
935 | |||
936 | /* Initialize using current mt_state (as updated by last agm) */ | ||
937 | mt_state = agm->mt_state; | ||
938 | |||
939 | /* | ||
940 | * Update mt_state using the new finger count and current mt_state. | ||
941 | */ | ||
942 | if (sgm->z == 0) | ||
943 | synaptics_image_sensor_0f(priv, &mt_state); | ||
944 | else if (sgm->w >= 4) | ||
945 | synaptics_image_sensor_1f(priv, &mt_state); | ||
946 | else if (sgm->w == 0) | ||
947 | synaptics_image_sensor_2f(priv, &mt_state); | ||
948 | else if (sgm->w == 1 && mt_state.count <= 3) | ||
949 | synaptics_image_sensor_3f(priv, &mt_state); | ||
950 | else | ||
951 | synaptics_image_sensor_45f(priv, &mt_state); | ||
952 | |||
953 | /* Send resulting input events to user space */ | ||
954 | synaptics_report_mt_data(psmouse, &mt_state, sgm); | ||
955 | |||
956 | /* Store updated mt_state */ | ||
957 | priv->mt_state = agm->mt_state = mt_state; | ||
958 | priv->agm_pending = false; | ||
959 | } | ||
960 | |||
529 | /* | 961 | /* |
530 | * called for each full received packet from the touchpad | 962 | * called for each full received packet from the touchpad |
531 | */ | 963 | */ |
@@ -536,11 +968,15 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
536 | struct synaptics_hw_state hw; | 968 | struct synaptics_hw_state hw; |
537 | int num_fingers; | 969 | int num_fingers; |
538 | int finger_width; | 970 | int finger_width; |
539 | int i; | ||
540 | 971 | ||
541 | if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) | 972 | if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) |
542 | return; | 973 | return; |
543 | 974 | ||
975 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { | ||
976 | synaptics_image_sensor_process(psmouse, &hw); | ||
977 | return; | ||
978 | } | ||
979 | |||
544 | if (hw.scroll) { | 980 | if (hw.scroll) { |
545 | priv->scroll += hw.scroll; | 981 | priv->scroll += hw.scroll; |
546 | 982 | ||
@@ -586,7 +1022,8 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
586 | } | 1022 | } |
587 | 1023 | ||
588 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | 1024 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) |
589 | synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers); | 1025 | synaptics_report_semi_mt_data(dev, &hw, &priv->agm, |
1026 | num_fingers); | ||
590 | 1027 | ||
591 | /* Post events | 1028 | /* Post events |
592 | * BTN_TOUCH has to be first as mousedev relies on it when doing | 1029 | * BTN_TOUCH has to be first as mousedev relies on it when doing |
@@ -597,7 +1034,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
597 | 1034 | ||
598 | if (num_fingers > 0) { | 1035 | if (num_fingers > 0) { |
599 | input_report_abs(dev, ABS_X, hw.x); | 1036 | input_report_abs(dev, ABS_X, hw.x); |
600 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); | 1037 | input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y)); |
601 | } | 1038 | } |
602 | input_report_abs(dev, ABS_PRESSURE, hw.z); | 1039 | input_report_abs(dev, ABS_PRESSURE, hw.z); |
603 | 1040 | ||
@@ -605,35 +1042,25 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
605 | input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); | 1042 | input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); |
606 | 1043 | ||
607 | input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); | 1044 | input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); |
608 | input_report_key(dev, BTN_LEFT, hw.left); | ||
609 | input_report_key(dev, BTN_RIGHT, hw.right); | ||
610 | |||
611 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 1045 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { |
612 | input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); | 1046 | input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); |
613 | input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); | 1047 | input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); |
614 | } | 1048 | } |
615 | 1049 | ||
616 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | 1050 | synaptics_report_buttons(psmouse, &hw); |
617 | input_report_key(dev, BTN_MIDDLE, hw.middle); | ||
618 | |||
619 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { | ||
620 | input_report_key(dev, BTN_FORWARD, hw.up); | ||
621 | input_report_key(dev, BTN_BACK, hw.down); | ||
622 | } | ||
623 | |||
624 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | ||
625 | input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i)); | ||
626 | 1051 | ||
627 | input_sync(dev); | 1052 | input_sync(dev); |
628 | } | 1053 | } |
629 | 1054 | ||
630 | static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type) | 1055 | static int synaptics_validate_byte(struct psmouse *psmouse, |
1056 | int idx, unsigned char pkt_type) | ||
631 | { | 1057 | { |
632 | static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 }; | 1058 | static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 }; |
633 | static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 }; | 1059 | static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 }; |
634 | static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 }; | 1060 | static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 }; |
635 | static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 }; | 1061 | static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 }; |
636 | static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 }; | 1062 | static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 }; |
1063 | const char *packet = psmouse->packet; | ||
637 | 1064 | ||
638 | if (idx < 0 || idx > 4) | 1065 | if (idx < 0 || idx > 4) |
639 | return 0; | 1066 | return 0; |
@@ -651,7 +1078,7 @@ static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned cha | |||
651 | return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; | 1078 | return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; |
652 | 1079 | ||
653 | default: | 1080 | default: |
654 | printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type); | 1081 | psmouse_err(psmouse, "unknown packet type %d\n", pkt_type); |
655 | return 0; | 1082 | return 0; |
656 | } | 1083 | } |
657 | } | 1084 | } |
@@ -661,8 +1088,8 @@ static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse) | |||
661 | int i; | 1088 | int i; |
662 | 1089 | ||
663 | for (i = 0; i < 5; i++) | 1090 | for (i = 0; i < 5; i++) |
664 | if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) { | 1091 | if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) { |
665 | printk(KERN_INFO "synaptics: using relaxed packet validation\n"); | 1092 | psmouse_info(psmouse, "using relaxed packet validation\n"); |
666 | return SYN_NEWABS_RELAXED; | 1093 | return SYN_NEWABS_RELAXED; |
667 | } | 1094 | } |
668 | 1095 | ||
@@ -687,46 +1114,56 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) | |||
687 | return PSMOUSE_FULL_PACKET; | 1114 | return PSMOUSE_FULL_PACKET; |
688 | } | 1115 | } |
689 | 1116 | ||
690 | return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ? | 1117 | return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ? |
691 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; | 1118 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; |
692 | } | 1119 | } |
693 | 1120 | ||
694 | /***************************************************************************** | 1121 | /***************************************************************************** |
695 | * Driver initialization/cleanup functions | 1122 | * Driver initialization/cleanup functions |
696 | ****************************************************************************/ | 1123 | ****************************************************************************/ |
697 | static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | 1124 | static void set_abs_position_params(struct input_dev *dev, |
1125 | struct synaptics_data *priv, int x_code, | ||
1126 | int y_code) | ||
698 | { | 1127 | { |
699 | int i; | 1128 | int x_min = priv->x_min ?: XMIN_NOMINAL; |
1129 | int x_max = priv->x_max ?: XMAX_NOMINAL; | ||
1130 | int y_min = priv->y_min ?: YMIN_NOMINAL; | ||
1131 | int y_max = priv->y_max ?: YMAX_NOMINAL; | ||
700 | int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ? | 1132 | int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ? |
701 | SYN_REDUCED_FILTER_FUZZ : 0; | 1133 | SYN_REDUCED_FILTER_FUZZ : 0; |
702 | 1134 | ||
1135 | input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0); | ||
1136 | input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0); | ||
1137 | input_abs_set_res(dev, x_code, priv->x_res); | ||
1138 | input_abs_set_res(dev, y_code, priv->y_res); | ||
1139 | } | ||
1140 | |||
1141 | static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | ||
1142 | { | ||
1143 | int i; | ||
1144 | |||
703 | __set_bit(INPUT_PROP_POINTER, dev->propbit); | 1145 | __set_bit(INPUT_PROP_POINTER, dev->propbit); |
704 | 1146 | ||
705 | __set_bit(EV_ABS, dev->evbit); | 1147 | __set_bit(EV_ABS, dev->evbit); |
706 | input_set_abs_params(dev, ABS_X, | 1148 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); |
707 | priv->x_min ?: XMIN_NOMINAL, | ||
708 | priv->x_max ?: XMAX_NOMINAL, | ||
709 | fuzz, 0); | ||
710 | input_set_abs_params(dev, ABS_Y, | ||
711 | priv->y_min ?: YMIN_NOMINAL, | ||
712 | priv->y_max ?: YMAX_NOMINAL, | ||
713 | fuzz, 0); | ||
714 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 1149 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
715 | 1150 | ||
716 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | 1151 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { |
1152 | input_mt_init_slots(dev, 2); | ||
1153 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, | ||
1154 | ABS_MT_POSITION_Y); | ||
1155 | /* Image sensors can report per-contact pressure */ | ||
1156 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | ||
1157 | |||
1158 | /* Image sensors can signal 4 and 5 finger clicks */ | ||
1159 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | ||
1160 | __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); | ||
1161 | } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | ||
1162 | /* Non-image sensors with AGM use semi-mt */ | ||
717 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | 1163 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); |
718 | input_mt_init_slots(dev, 2); | 1164 | input_mt_init_slots(dev, 2); |
719 | input_set_abs_params(dev, ABS_MT_POSITION_X, | 1165 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, |
720 | priv->x_min ?: XMIN_NOMINAL, | 1166 | ABS_MT_POSITION_Y); |
721 | priv->x_max ?: XMAX_NOMINAL, | ||
722 | fuzz, 0); | ||
723 | input_set_abs_params(dev, ABS_MT_POSITION_Y, | ||
724 | priv->y_min ?: YMIN_NOMINAL, | ||
725 | priv->y_max ?: YMAX_NOMINAL, | ||
726 | fuzz, 0); | ||
727 | |||
728 | input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res); | ||
729 | input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res); | ||
730 | } | 1167 | } |
731 | 1168 | ||
732 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 1169 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
@@ -759,9 +1196,6 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
759 | __clear_bit(REL_X, dev->relbit); | 1196 | __clear_bit(REL_X, dev->relbit); |
760 | __clear_bit(REL_Y, dev->relbit); | 1197 | __clear_bit(REL_Y, dev->relbit); |
761 | 1198 | ||
762 | input_abs_set_res(dev, ABS_X, priv->x_res); | ||
763 | input_abs_set_res(dev, ABS_Y, priv->y_res); | ||
764 | |||
765 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 1199 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
766 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); | 1200 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); |
767 | /* Clickpads report only left button */ | 1201 | /* Clickpads report only left button */ |
@@ -793,21 +1227,21 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
793 | return -1; | 1227 | return -1; |
794 | 1228 | ||
795 | if (retry > 1) | 1229 | if (retry > 1) |
796 | printk(KERN_DEBUG "Synaptics reconnected after %d tries\n", | 1230 | psmouse_dbg(psmouse, "reconnected after %d tries\n", retry); |
797 | retry); | ||
798 | 1231 | ||
799 | if (synaptics_query_hardware(psmouse)) { | 1232 | if (synaptics_query_hardware(psmouse)) { |
800 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); | 1233 | psmouse_err(psmouse, "Unable to query device.\n"); |
801 | return -1; | 1234 | return -1; |
802 | } | 1235 | } |
803 | 1236 | ||
804 | if (synaptics_set_absolute_mode(psmouse)) { | 1237 | if (synaptics_set_absolute_mode(psmouse)) { |
805 | printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); | 1238 | psmouse_err(psmouse, "Unable to initialize device.\n"); |
806 | return -1; | 1239 | return -1; |
807 | } | 1240 | } |
808 | 1241 | ||
809 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | 1242 | if (synaptics_set_advanced_gesture_mode(psmouse)) { |
810 | printk(KERN_ERR "Advanced gesture mode reconnect failed.\n"); | 1243 | psmouse_err(psmouse, |
1244 | "Advanced gesture mode reconnect failed.\n"); | ||
811 | return -1; | 1245 | return -1; |
812 | } | 1246 | } |
813 | 1247 | ||
@@ -815,12 +1249,12 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
815 | old_priv.model_id != priv->model_id || | 1249 | old_priv.model_id != priv->model_id || |
816 | old_priv.capabilities != priv->capabilities || | 1250 | old_priv.capabilities != priv->capabilities || |
817 | old_priv.ext_cap != priv->ext_cap) { | 1251 | old_priv.ext_cap != priv->ext_cap) { |
818 | printk(KERN_ERR "Synaptics hardware appears to be different: " | 1252 | psmouse_err(psmouse, |
819 | "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", | 1253 | "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", |
820 | old_priv.identity, priv->identity, | 1254 | old_priv.identity, priv->identity, |
821 | old_priv.model_id, priv->model_id, | 1255 | old_priv.model_id, priv->model_id, |
822 | old_priv.capabilities, priv->capabilities, | 1256 | old_priv.capabilities, priv->capabilities, |
823 | old_priv.ext_cap, priv->ext_cap); | 1257 | old_priv.ext_cap, priv->ext_cap); |
824 | return -1; | 1258 | return -1; |
825 | } | 1259 | } |
826 | 1260 | ||
@@ -901,7 +1335,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
901 | * just fine. | 1335 | * just fine. |
902 | */ | 1336 | */ |
903 | if (broken_olpc_ec) { | 1337 | if (broken_olpc_ec) { |
904 | printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n"); | 1338 | psmouse_info(psmouse, |
1339 | "OLPC XO detected, not enabling Synaptics protocol.\n"); | ||
905 | return -ENODEV; | 1340 | return -ENODEV; |
906 | } | 1341 | } |
907 | 1342 | ||
@@ -912,26 +1347,28 @@ int synaptics_init(struct psmouse *psmouse) | |||
912 | psmouse_reset(psmouse); | 1347 | psmouse_reset(psmouse); |
913 | 1348 | ||
914 | if (synaptics_query_hardware(psmouse)) { | 1349 | if (synaptics_query_hardware(psmouse)) { |
915 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); | 1350 | psmouse_err(psmouse, "Unable to query device.\n"); |
916 | goto init_fail; | 1351 | goto init_fail; |
917 | } | 1352 | } |
918 | 1353 | ||
919 | if (synaptics_set_absolute_mode(psmouse)) { | 1354 | if (synaptics_set_absolute_mode(psmouse)) { |
920 | printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); | 1355 | psmouse_err(psmouse, "Unable to initialize device.\n"); |
921 | goto init_fail; | 1356 | goto init_fail; |
922 | } | 1357 | } |
923 | 1358 | ||
924 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | 1359 | if (synaptics_set_advanced_gesture_mode(psmouse)) { |
925 | printk(KERN_ERR "Advanced gesture mode init failed.\n"); | 1360 | psmouse_err(psmouse, "Advanced gesture mode init failed.\n"); |
926 | goto init_fail; | 1361 | goto init_fail; |
927 | } | 1362 | } |
928 | 1363 | ||
929 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; | 1364 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; |
930 | 1365 | ||
931 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", | 1366 | psmouse_info(psmouse, |
932 | SYN_ID_MODEL(priv->identity), | 1367 | "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", |
933 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), | 1368 | SYN_ID_MODEL(priv->identity), |
934 | priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c); | 1369 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), |
1370 | priv->model_id, | ||
1371 | priv->capabilities, priv->ext_cap, priv->ext_cap_0c); | ||
935 | 1372 | ||
936 | set_input_params(psmouse->dev, priv); | 1373 | set_input_params(psmouse->dev, priv); |
937 | 1374 | ||
@@ -963,8 +1400,9 @@ int synaptics_init(struct psmouse *psmouse) | |||
963 | * the same rate as a standard PS/2 mouse). | 1400 | * the same rate as a standard PS/2 mouse). |
964 | */ | 1401 | */ |
965 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { | 1402 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { |
966 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", | 1403 | psmouse_info(psmouse, |
967 | dmi_get_system_info(DMI_PRODUCT_NAME)); | 1404 | "Toshiba %s detected, limiting rate to 40pps.\n", |
1405 | dmi_get_system_info(DMI_PRODUCT_NAME)); | ||
968 | psmouse->rate = 40; | 1406 | psmouse->rate = 40; |
969 | } | 1407 | } |
970 | 1408 | ||
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index ca040aa80fa7..622aea8dd7e0 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -74,6 +74,8 @@ | |||
74 | * 2 0x04 reduced filtering firmware does less filtering on | 74 | * 2 0x04 reduced filtering firmware does less filtering on |
75 | * position data, driver should watch | 75 | * position data, driver should watch |
76 | * for noise. | 76 | * for noise. |
77 | * 2 0x08 image sensor image sensor tracks 5 fingers, but only | ||
78 | * reports 2. | ||
77 | * 2 0x20 report min query 0x0f gives min coord reported | 79 | * 2 0x20 report min query 0x0f gives min coord reported |
78 | */ | 80 | */ |
79 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ | 81 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ |
@@ -82,6 +84,7 @@ | |||
82 | #define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x002000) | 84 | #define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x002000) |
83 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) | 85 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) |
84 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) | 86 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) |
87 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) | ||
85 | 88 | ||
86 | /* synaptics modes query bits */ | 89 | /* synaptics modes query bits */ |
87 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 90 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
@@ -112,9 +115,18 @@ | |||
112 | #define SYN_REDUCED_FILTER_FUZZ 8 | 115 | #define SYN_REDUCED_FILTER_FUZZ 8 |
113 | 116 | ||
114 | /* | 117 | /* |
115 | * A structure to describe the state of the touchpad hardware (buttons and pad) | 118 | * A structure to describe which internal touchpad finger slots are being |
119 | * reported in raw packets. | ||
116 | */ | 120 | */ |
121 | struct synaptics_mt_state { | ||
122 | int count; /* num fingers being tracked */ | ||
123 | int sgm; /* which slot is reported by sgm pkt */ | ||
124 | int agm; /* which slot is reported by agm pkt*/ | ||
125 | }; | ||
117 | 126 | ||
127 | /* | ||
128 | * A structure to describe the state of the touchpad hardware (buttons and pad) | ||
129 | */ | ||
118 | struct synaptics_hw_state { | 130 | struct synaptics_hw_state { |
119 | int x; | 131 | int x; |
120 | int y; | 132 | int y; |
@@ -127,6 +139,9 @@ struct synaptics_hw_state { | |||
127 | unsigned int down:1; | 139 | unsigned int down:1; |
128 | unsigned char ext_buttons; | 140 | unsigned char ext_buttons; |
129 | signed char scroll; | 141 | signed char scroll; |
142 | |||
143 | /* As reported in last AGM-CONTACT packets */ | ||
144 | struct synaptics_mt_state mt_state; | ||
130 | }; | 145 | }; |
131 | 146 | ||
132 | struct synaptics_data { | 147 | struct synaptics_data { |
@@ -146,7 +161,15 @@ struct synaptics_data { | |||
146 | 161 | ||
147 | struct serio *pt_port; /* Pass-through serio port */ | 162 | struct serio *pt_port; /* Pass-through serio port */ |
148 | 163 | ||
149 | struct synaptics_hw_state mt; /* current gesture packet */ | 164 | struct synaptics_mt_state mt_state; /* Current mt finger state */ |
165 | bool mt_state_lost; /* mt_state may be incorrect */ | ||
166 | |||
167 | /* | ||
168 | * Last received Advanced Gesture Mode (AGM) packet. An AGM packet | ||
169 | * contains position data for a second contact, at half resolution. | ||
170 | */ | ||
171 | struct synaptics_hw_state agm; | ||
172 | bool agm_pending; /* new AGM packet received */ | ||
150 | }; | 173 | }; |
151 | 174 | ||
152 | void synaptics_module_init(void); | 175 | void synaptics_module_init(void); |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index cba3c84d2f21..4b755cb5b38c 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c | |||
@@ -570,7 +570,7 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, | |||
570 | "Requesting IRQ: %d\n", touch->client->irq); | 570 | "Requesting IRQ: %d\n", touch->client->irq); |
571 | 571 | ||
572 | ret = request_irq(touch->client->irq, synaptics_i2c_irq, | 572 | ret = request_irq(touch->client->irq, synaptics_i2c_irq, |
573 | IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING, | 573 | IRQ_TYPE_EDGE_FALLING, |
574 | DRIVER_NAME, touch); | 574 | DRIVER_NAME, touch); |
575 | if (ret) { | 575 | if (ret) { |
576 | dev_warn(&touch->client->dev, | 576 | dev_warn(&touch->client->dev, |
@@ -619,7 +619,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) | |||
619 | return 0; | 619 | return 0; |
620 | } | 620 | } |
621 | 621 | ||
622 | #ifdef CONFIG_PM | 622 | #ifdef CONFIG_PM_SLEEP |
623 | static int synaptics_i2c_suspend(struct device *dev) | 623 | static int synaptics_i2c_suspend(struct device *dev) |
624 | { | 624 | { |
625 | struct i2c_client *client = to_i2c_client(dev); | 625 | struct i2c_client *client = to_i2c_client(dev); |
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index b7ba4597f7f0..4d4cd142bbbb 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * the Free Software Foundation. | 9 | * the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kref.h> | ||
12 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
14 | #include <linux/poll.h> | 15 | #include <linux/poll.h> |
@@ -33,15 +34,16 @@ struct serio_raw { | |||
33 | unsigned int tail, head; | 34 | unsigned int tail, head; |
34 | 35 | ||
35 | char name[16]; | 36 | char name[16]; |
36 | unsigned int refcnt; | 37 | struct kref kref; |
37 | struct serio *serio; | 38 | struct serio *serio; |
38 | struct miscdevice dev; | 39 | struct miscdevice dev; |
39 | wait_queue_head_t wait; | 40 | wait_queue_head_t wait; |
40 | struct list_head list; | 41 | struct list_head client_list; |
41 | struct list_head node; | 42 | struct list_head node; |
43 | bool dead; | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | struct serio_raw_list { | 46 | struct serio_raw_client { |
45 | struct fasync_struct *fasync; | 47 | struct fasync_struct *fasync; |
46 | struct serio_raw *serio_raw; | 48 | struct serio_raw *serio_raw; |
47 | struct list_head node; | 49 | struct list_head node; |
@@ -49,7 +51,6 @@ struct serio_raw_list { | |||
49 | 51 | ||
50 | static DEFINE_MUTEX(serio_raw_mutex); | 52 | static DEFINE_MUTEX(serio_raw_mutex); |
51 | static LIST_HEAD(serio_raw_list); | 53 | static LIST_HEAD(serio_raw_list); |
52 | static unsigned int serio_raw_no; | ||
53 | 54 | ||
54 | /********************************************************************* | 55 | /********************************************************************* |
55 | * Interface with userspace (file operations) * | 56 | * Interface with userspace (file operations) * |
@@ -57,9 +58,9 @@ static unsigned int serio_raw_no; | |||
57 | 58 | ||
58 | static int serio_raw_fasync(int fd, struct file *file, int on) | 59 | static int serio_raw_fasync(int fd, struct file *file, int on) |
59 | { | 60 | { |
60 | struct serio_raw_list *list = file->private_data; | 61 | struct serio_raw_client *client = file->private_data; |
61 | 62 | ||
62 | return fasync_helper(fd, file, on, &list->fasync); | 63 | return fasync_helper(fd, file, on, &client->fasync); |
63 | } | 64 | } |
64 | 65 | ||
65 | static struct serio_raw *serio_raw_locate(int minor) | 66 | static struct serio_raw *serio_raw_locate(int minor) |
@@ -77,8 +78,8 @@ static struct serio_raw *serio_raw_locate(int minor) | |||
77 | static int serio_raw_open(struct inode *inode, struct file *file) | 78 | static int serio_raw_open(struct inode *inode, struct file *file) |
78 | { | 79 | { |
79 | struct serio_raw *serio_raw; | 80 | struct serio_raw *serio_raw; |
80 | struct serio_raw_list *list; | 81 | struct serio_raw_client *client; |
81 | int retval = 0; | 82 | int retval; |
82 | 83 | ||
83 | retval = mutex_lock_interruptible(&serio_raw_mutex); | 84 | retval = mutex_lock_interruptible(&serio_raw_mutex); |
84 | if (retval) | 85 | if (retval) |
@@ -90,60 +91,61 @@ static int serio_raw_open(struct inode *inode, struct file *file) | |||
90 | goto out; | 91 | goto out; |
91 | } | 92 | } |
92 | 93 | ||
93 | if (!serio_raw->serio) { | 94 | if (serio_raw->dead) { |
94 | retval = -ENODEV; | 95 | retval = -ENODEV; |
95 | goto out; | 96 | goto out; |
96 | } | 97 | } |
97 | 98 | ||
98 | list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL); | 99 | client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL); |
99 | if (!list) { | 100 | if (!client) { |
100 | retval = -ENOMEM; | 101 | retval = -ENOMEM; |
101 | goto out; | 102 | goto out; |
102 | } | 103 | } |
103 | 104 | ||
104 | list->serio_raw = serio_raw; | 105 | client->serio_raw = serio_raw; |
105 | file->private_data = list; | 106 | file->private_data = client; |
107 | |||
108 | kref_get(&serio_raw->kref); | ||
106 | 109 | ||
107 | serio_raw->refcnt++; | 110 | serio_pause_rx(serio_raw->serio); |
108 | list_add_tail(&list->node, &serio_raw->list); | 111 | list_add_tail(&client->node, &serio_raw->client_list); |
112 | serio_continue_rx(serio_raw->serio); | ||
109 | 113 | ||
110 | out: | 114 | out: |
111 | mutex_unlock(&serio_raw_mutex); | 115 | mutex_unlock(&serio_raw_mutex); |
112 | return retval; | 116 | return retval; |
113 | } | 117 | } |
114 | 118 | ||
115 | static int serio_raw_cleanup(struct serio_raw *serio_raw) | 119 | static void serio_raw_free(struct kref *kref) |
116 | { | 120 | { |
117 | if (--serio_raw->refcnt == 0) { | 121 | struct serio_raw *serio_raw = |
118 | misc_deregister(&serio_raw->dev); | 122 | container_of(kref, struct serio_raw, kref); |
119 | list_del_init(&serio_raw->node); | ||
120 | kfree(serio_raw); | ||
121 | 123 | ||
122 | return 1; | 124 | put_device(&serio_raw->serio->dev); |
123 | } | 125 | kfree(serio_raw); |
124 | |||
125 | return 0; | ||
126 | } | 126 | } |
127 | 127 | ||
128 | static int serio_raw_release(struct inode *inode, struct file *file) | 128 | static int serio_raw_release(struct inode *inode, struct file *file) |
129 | { | 129 | { |
130 | struct serio_raw_list *list = file->private_data; | 130 | struct serio_raw_client *client = file->private_data; |
131 | struct serio_raw *serio_raw = list->serio_raw; | 131 | struct serio_raw *serio_raw = client->serio_raw; |
132 | 132 | ||
133 | mutex_lock(&serio_raw_mutex); | 133 | serio_pause_rx(serio_raw->serio); |
134 | list_del(&client->node); | ||
135 | serio_continue_rx(serio_raw->serio); | ||
134 | 136 | ||
135 | serio_raw_cleanup(serio_raw); | 137 | kfree(client); |
138 | |||
139 | kref_put(&serio_raw->kref, serio_raw_free); | ||
136 | 140 | ||
137 | mutex_unlock(&serio_raw_mutex); | ||
138 | return 0; | 141 | return 0; |
139 | } | 142 | } |
140 | 143 | ||
141 | static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) | 144 | static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) |
142 | { | 145 | { |
143 | unsigned long flags; | 146 | bool empty; |
144 | int empty; | ||
145 | 147 | ||
146 | spin_lock_irqsave(&serio_raw->serio->lock, flags); | 148 | serio_pause_rx(serio_raw->serio); |
147 | 149 | ||
148 | empty = serio_raw->head == serio_raw->tail; | 150 | empty = serio_raw->head == serio_raw->tail; |
149 | if (!empty) { | 151 | if (!empty) { |
@@ -151,30 +153,31 @@ static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) | |||
151 | serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; | 153 | serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; |
152 | } | 154 | } |
153 | 155 | ||
154 | spin_unlock_irqrestore(&serio_raw->serio->lock, flags); | 156 | serio_continue_rx(serio_raw->serio); |
155 | 157 | ||
156 | return !empty; | 158 | return !empty; |
157 | } | 159 | } |
158 | 160 | ||
159 | static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 161 | static ssize_t serio_raw_read(struct file *file, char __user *buffer, |
162 | size_t count, loff_t *ppos) | ||
160 | { | 163 | { |
161 | struct serio_raw_list *list = file->private_data; | 164 | struct serio_raw_client *client = file->private_data; |
162 | struct serio_raw *serio_raw = list->serio_raw; | 165 | struct serio_raw *serio_raw = client->serio_raw; |
163 | char uninitialized_var(c); | 166 | char uninitialized_var(c); |
164 | ssize_t retval = 0; | 167 | ssize_t retval = 0; |
165 | 168 | ||
166 | if (!serio_raw->serio) | 169 | if (serio_raw->dead) |
167 | return -ENODEV; | 170 | return -ENODEV; |
168 | 171 | ||
169 | if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK)) | 172 | if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK)) |
170 | return -EAGAIN; | 173 | return -EAGAIN; |
171 | 174 | ||
172 | retval = wait_event_interruptible(list->serio_raw->wait, | 175 | retval = wait_event_interruptible(serio_raw->wait, |
173 | serio_raw->head != serio_raw->tail || !serio_raw->serio); | 176 | serio_raw->head != serio_raw->tail || serio_raw->dead); |
174 | if (retval) | 177 | if (retval) |
175 | return retval; | 178 | return retval; |
176 | 179 | ||
177 | if (!serio_raw->serio) | 180 | if (serio_raw->dead) |
178 | return -ENODEV; | 181 | return -ENODEV; |
179 | 182 | ||
180 | while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) { | 183 | while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) { |
@@ -186,9 +189,11 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t cou | |||
186 | return retval; | 189 | return retval; |
187 | } | 190 | } |
188 | 191 | ||
189 | static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 192 | static ssize_t serio_raw_write(struct file *file, const char __user *buffer, |
193 | size_t count, loff_t *ppos) | ||
190 | { | 194 | { |
191 | struct serio_raw_list *list = file->private_data; | 195 | struct serio_raw_client *client = file->private_data; |
196 | struct serio_raw *serio_raw = client->serio_raw; | ||
192 | ssize_t written = 0; | 197 | ssize_t written = 0; |
193 | int retval; | 198 | int retval; |
194 | unsigned char c; | 199 | unsigned char c; |
@@ -197,7 +202,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz | |||
197 | if (retval) | 202 | if (retval) |
198 | return retval; | 203 | return retval; |
199 | 204 | ||
200 | if (!list->serio_raw->serio) { | 205 | if (serio_raw->dead) { |
201 | retval = -ENODEV; | 206 | retval = -ENODEV; |
202 | goto out; | 207 | goto out; |
203 | } | 208 | } |
@@ -210,7 +215,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz | |||
210 | retval = -EFAULT; | 215 | retval = -EFAULT; |
211 | goto out; | 216 | goto out; |
212 | } | 217 | } |
213 | if (serio_write(list->serio_raw->serio, c)) { | 218 | if (serio_write(serio_raw->serio, c)) { |
214 | retval = -EIO; | 219 | retval = -EIO; |
215 | goto out; | 220 | goto out; |
216 | } | 221 | } |
@@ -224,46 +229,49 @@ out: | |||
224 | 229 | ||
225 | static unsigned int serio_raw_poll(struct file *file, poll_table *wait) | 230 | static unsigned int serio_raw_poll(struct file *file, poll_table *wait) |
226 | { | 231 | { |
227 | struct serio_raw_list *list = file->private_data; | 232 | struct serio_raw_client *client = file->private_data; |
233 | struct serio_raw *serio_raw = client->serio_raw; | ||
234 | unsigned int mask; | ||
228 | 235 | ||
229 | poll_wait(file, &list->serio_raw->wait, wait); | 236 | poll_wait(file, &serio_raw->wait, wait); |
230 | 237 | ||
231 | if (list->serio_raw->head != list->serio_raw->tail) | 238 | mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM; |
239 | if (serio_raw->head != serio_raw->tail) | ||
232 | return POLLIN | POLLRDNORM; | 240 | return POLLIN | POLLRDNORM; |
233 | 241 | ||
234 | return 0; | 242 | return 0; |
235 | } | 243 | } |
236 | 244 | ||
237 | static const struct file_operations serio_raw_fops = { | 245 | static const struct file_operations serio_raw_fops = { |
238 | .owner = THIS_MODULE, | 246 | .owner = THIS_MODULE, |
239 | .open = serio_raw_open, | 247 | .open = serio_raw_open, |
240 | .release = serio_raw_release, | 248 | .release = serio_raw_release, |
241 | .read = serio_raw_read, | 249 | .read = serio_raw_read, |
242 | .write = serio_raw_write, | 250 | .write = serio_raw_write, |
243 | .poll = serio_raw_poll, | 251 | .poll = serio_raw_poll, |
244 | .fasync = serio_raw_fasync, | 252 | .fasync = serio_raw_fasync, |
245 | .llseek = noop_llseek, | 253 | .llseek = noop_llseek, |
246 | }; | 254 | }; |
247 | 255 | ||
248 | 256 | ||
249 | /********************************************************************* | 257 | /********************************************************************* |
250 | * Interface with serio port * | 258 | * Interface with serio port * |
251 | *********************************************************************/ | 259 | *********************************************************************/ |
252 | 260 | ||
253 | static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data, | 261 | static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data, |
254 | unsigned int dfl) | 262 | unsigned int dfl) |
255 | { | 263 | { |
256 | struct serio_raw *serio_raw = serio_get_drvdata(serio); | 264 | struct serio_raw *serio_raw = serio_get_drvdata(serio); |
257 | struct serio_raw_list *list; | 265 | struct serio_raw_client *client; |
258 | unsigned int head = serio_raw->head; | 266 | unsigned int head = serio_raw->head; |
259 | 267 | ||
260 | /* we are holding serio->lock here so we are prootected */ | 268 | /* we are holding serio->lock here so we are protected */ |
261 | serio_raw->queue[head] = data; | 269 | serio_raw->queue[head] = data; |
262 | head = (head + 1) % SERIO_RAW_QUEUE_LEN; | 270 | head = (head + 1) % SERIO_RAW_QUEUE_LEN; |
263 | if (likely(head != serio_raw->tail)) { | 271 | if (likely(head != serio_raw->tail)) { |
264 | serio_raw->head = head; | 272 | serio_raw->head = head; |
265 | list_for_each_entry(list, &serio_raw->list, node) | 273 | list_for_each_entry(client, &serio_raw->client_list, node) |
266 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 274 | kill_fasync(&client->fasync, SIGIO, POLL_IN); |
267 | wake_up_interruptible(&serio_raw->wait); | 275 | wake_up_interruptible(&serio_raw->wait); |
268 | } | 276 | } |
269 | 277 | ||
@@ -272,29 +280,37 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data, | |||
272 | 280 | ||
273 | static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) | 281 | static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) |
274 | { | 282 | { |
283 | static atomic_t serio_raw_no = ATOMIC_INIT(0); | ||
275 | struct serio_raw *serio_raw; | 284 | struct serio_raw *serio_raw; |
276 | int err; | 285 | int err; |
277 | 286 | ||
278 | if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) { | 287 | serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL); |
279 | printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n"); | 288 | if (!serio_raw) { |
289 | dev_dbg(&serio->dev, "can't allocate memory for a device\n"); | ||
280 | return -ENOMEM; | 290 | return -ENOMEM; |
281 | } | 291 | } |
282 | 292 | ||
283 | mutex_lock(&serio_raw_mutex); | 293 | snprintf(serio_raw->name, sizeof(serio_raw->name), |
294 | "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1); | ||
295 | kref_init(&serio_raw->kref); | ||
296 | INIT_LIST_HEAD(&serio_raw->client_list); | ||
297 | init_waitqueue_head(&serio_raw->wait); | ||
284 | 298 | ||
285 | snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++); | ||
286 | serio_raw->refcnt = 1; | ||
287 | serio_raw->serio = serio; | 299 | serio_raw->serio = serio; |
288 | INIT_LIST_HEAD(&serio_raw->list); | 300 | get_device(&serio->dev); |
289 | init_waitqueue_head(&serio_raw->wait); | ||
290 | 301 | ||
291 | serio_set_drvdata(serio, serio_raw); | 302 | serio_set_drvdata(serio, serio_raw); |
292 | 303 | ||
293 | err = serio_open(serio, drv); | 304 | err = serio_open(serio, drv); |
294 | if (err) | 305 | if (err) |
295 | goto out_free; | 306 | goto err_free; |
307 | |||
308 | err = mutex_lock_killable(&serio_raw_mutex); | ||
309 | if (err) | ||
310 | goto err_close; | ||
296 | 311 | ||
297 | list_add_tail(&serio_raw->node, &serio_raw_list); | 312 | list_add_tail(&serio_raw->node, &serio_raw_list); |
313 | mutex_unlock(&serio_raw_mutex); | ||
298 | 314 | ||
299 | serio_raw->dev.minor = PSMOUSE_MINOR; | 315 | serio_raw->dev.minor = PSMOUSE_MINOR; |
300 | serio_raw->dev.name = serio_raw->name; | 316 | serio_raw->dev.name = serio_raw->name; |
@@ -308,23 +324,23 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) | |||
308 | } | 324 | } |
309 | 325 | ||
310 | if (err) { | 326 | if (err) { |
311 | printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n", | 327 | dev_err(&serio->dev, |
328 | "failed to register raw access device for %s\n", | ||
312 | serio->phys); | 329 | serio->phys); |
313 | goto out_close; | 330 | goto err_unlink; |
314 | } | 331 | } |
315 | 332 | ||
316 | printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n", | 333 | dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n", |
317 | serio->phys, serio_raw->name, serio_raw->dev.minor); | 334 | serio->phys, serio_raw->name, serio_raw->dev.minor); |
318 | goto out; | 335 | return 0; |
319 | 336 | ||
320 | out_close: | 337 | err_unlink: |
321 | serio_close(serio); | ||
322 | list_del_init(&serio_raw->node); | 338 | list_del_init(&serio_raw->node); |
323 | out_free: | 339 | err_close: |
340 | serio_close(serio); | ||
341 | err_free: | ||
324 | serio_set_drvdata(serio, NULL); | 342 | serio_set_drvdata(serio, NULL); |
325 | kfree(serio_raw); | 343 | kref_put(&serio_raw->kref, serio_raw_free); |
326 | out: | ||
327 | mutex_unlock(&serio_raw_mutex); | ||
328 | return err; | 344 | return err; |
329 | } | 345 | } |
330 | 346 | ||
@@ -334,7 +350,8 @@ static int serio_raw_reconnect(struct serio *serio) | |||
334 | struct serio_driver *drv = serio->drv; | 350 | struct serio_driver *drv = serio->drv; |
335 | 351 | ||
336 | if (!drv || !serio_raw) { | 352 | if (!drv || !serio_raw) { |
337 | printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n"); | 353 | dev_dbg(&serio->dev, |
354 | "reconnect request, but serio is disconnected, ignoring...\n"); | ||
338 | return -1; | 355 | return -1; |
339 | } | 356 | } |
340 | 357 | ||
@@ -345,22 +362,40 @@ static int serio_raw_reconnect(struct serio *serio) | |||
345 | return 0; | 362 | return 0; |
346 | } | 363 | } |
347 | 364 | ||
365 | /* | ||
366 | * Wake up users waiting for IO so they can disconnect from | ||
367 | * dead device. | ||
368 | */ | ||
369 | static void serio_raw_hangup(struct serio_raw *serio_raw) | ||
370 | { | ||
371 | struct serio_raw_client *client; | ||
372 | |||
373 | serio_pause_rx(serio_raw->serio); | ||
374 | list_for_each_entry(client, &serio_raw->client_list, node) | ||
375 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | ||
376 | serio_continue_rx(serio_raw->serio); | ||
377 | |||
378 | wake_up_interruptible(&serio_raw->wait); | ||
379 | } | ||
380 | |||
381 | |||
348 | static void serio_raw_disconnect(struct serio *serio) | 382 | static void serio_raw_disconnect(struct serio *serio) |
349 | { | 383 | { |
350 | struct serio_raw *serio_raw; | 384 | struct serio_raw *serio_raw = serio_get_drvdata(serio); |
385 | |||
386 | misc_deregister(&serio_raw->dev); | ||
351 | 387 | ||
352 | mutex_lock(&serio_raw_mutex); | 388 | mutex_lock(&serio_raw_mutex); |
389 | serio_raw->dead = true; | ||
390 | list_del_init(&serio_raw->node); | ||
391 | mutex_unlock(&serio_raw_mutex); | ||
353 | 392 | ||
354 | serio_raw = serio_get_drvdata(serio); | 393 | serio_raw_hangup(serio_raw); |
355 | 394 | ||
356 | serio_close(serio); | 395 | serio_close(serio); |
357 | serio_set_drvdata(serio, NULL); | 396 | kref_put(&serio_raw->kref, serio_raw_free); |
358 | |||
359 | serio_raw->serio = NULL; | ||
360 | if (!serio_raw_cleanup(serio_raw)) | ||
361 | wake_up_interruptible(&serio_raw->wait); | ||
362 | 397 | ||
363 | mutex_unlock(&serio_raw_mutex); | 398 | serio_set_drvdata(serio, NULL); |
364 | } | 399 | } |
365 | 400 | ||
366 | static struct serio_device_id serio_raw_serio_ids[] = { | 401 | static struct serio_device_id serio_raw_serio_ids[] = { |
@@ -391,7 +426,7 @@ static struct serio_driver serio_raw_drv = { | |||
391 | .connect = serio_raw_connect, | 426 | .connect = serio_raw_connect, |
392 | .reconnect = serio_raw_reconnect, | 427 | .reconnect = serio_raw_reconnect, |
393 | .disconnect = serio_raw_disconnect, | 428 | .disconnect = serio_raw_disconnect, |
394 | .manual_bind = 1, | 429 | .manual_bind = true, |
395 | }; | 430 | }; |
396 | 431 | ||
397 | static int __init serio_raw_init(void) | 432 | static int __init serio_raw_init(void) |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 23317bd09c82..0783864a7dc2 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
@@ -11,7 +11,7 @@ | |||
11 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | 11 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> |
12 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | 12 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> |
13 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | 13 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> |
14 | * Copyright (c) 2002-2009 Ping Cheng <pingc@wacom.com> | 14 | * Copyright (c) 2002-2011 Ping Cheng <pingc@wacom.com> |
15 | * | 15 | * |
16 | * ChangeLog: | 16 | * ChangeLog: |
17 | * v0.1 (vp) - Initial release | 17 | * v0.1 (vp) - Initial release |
@@ -93,7 +93,7 @@ | |||
93 | /* | 93 | /* |
94 | * Version Information | 94 | * Version Information |
95 | */ | 95 | */ |
96 | #define DRIVER_VERSION "v1.52" | 96 | #define DRIVER_VERSION "v1.53" |
97 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 97 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
98 | #define DRIVER_DESC "USB Wacom tablet driver" | 98 | #define DRIVER_DESC "USB Wacom tablet driver" |
99 | #define DRIVER_LICENSE "GPL" | 99 | #define DRIVER_LICENSE "GPL" |
@@ -114,6 +114,12 @@ struct wacom { | |||
114 | struct mutex lock; | 114 | struct mutex lock; |
115 | bool open; | 115 | bool open; |
116 | char phys[32]; | 116 | char phys[32]; |
117 | struct wacom_led { | ||
118 | u8 select[2]; /* status led selector (0..3) */ | ||
119 | u8 llv; /* status led brightness no button (1..127) */ | ||
120 | u8 hlv; /* status led brightness button pressed (1..127) */ | ||
121 | u8 img_lum; /* OLED matrix display brightness */ | ||
122 | } led; | ||
117 | }; | 123 | }; |
118 | 124 | ||
119 | extern const struct usb_device_id wacom_ids[]; | 125 | extern const struct usb_device_id wacom_ids[]; |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 958b4eb6369d..1c1b7b43cf92 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -48,27 +48,49 @@ struct hid_descriptor { | |||
48 | /* defines to get/set USB message */ | 48 | /* defines to get/set USB message */ |
49 | #define USB_REQ_GET_REPORT 0x01 | 49 | #define USB_REQ_GET_REPORT 0x01 |
50 | #define USB_REQ_SET_REPORT 0x09 | 50 | #define USB_REQ_SET_REPORT 0x09 |
51 | |||
51 | #define WAC_HID_FEATURE_REPORT 0x03 | 52 | #define WAC_HID_FEATURE_REPORT 0x03 |
52 | #define WAC_MSG_RETRIES 5 | 53 | #define WAC_MSG_RETRIES 5 |
53 | 54 | ||
54 | static int usb_get_report(struct usb_interface *intf, unsigned char type, | 55 | #define WAC_CMD_LED_CONTROL 0x20 |
55 | unsigned char id, void *buf, int size) | 56 | #define WAC_CMD_ICON_START 0x21 |
57 | #define WAC_CMD_ICON_XFER 0x23 | ||
58 | #define WAC_CMD_RETRIES 10 | ||
59 | |||
60 | static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id, | ||
61 | void *buf, size_t size, unsigned int retries) | ||
56 | { | 62 | { |
57 | return usb_control_msg(interface_to_usbdev(intf), | 63 | struct usb_device *dev = interface_to_usbdev(intf); |
58 | usb_rcvctrlpipe(interface_to_usbdev(intf), 0), | 64 | int retval; |
59 | USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 65 | |
60 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | 66 | do { |
61 | buf, size, 100); | 67 | retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
68 | USB_REQ_GET_REPORT, | ||
69 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
70 | (type << 8) + id, | ||
71 | intf->altsetting[0].desc.bInterfaceNumber, | ||
72 | buf, size, 100); | ||
73 | } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); | ||
74 | |||
75 | return retval; | ||
62 | } | 76 | } |
63 | 77 | ||
64 | static int usb_set_report(struct usb_interface *intf, unsigned char type, | 78 | static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id, |
65 | unsigned char id, void *buf, int size) | 79 | void *buf, size_t size, unsigned int retries) |
66 | { | 80 | { |
67 | return usb_control_msg(interface_to_usbdev(intf), | 81 | struct usb_device *dev = interface_to_usbdev(intf); |
68 | usb_sndctrlpipe(interface_to_usbdev(intf), 0), | 82 | int retval; |
69 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 83 | |
70 | (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, | 84 | do { |
71 | buf, size, 1000); | 85 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
86 | USB_REQ_SET_REPORT, | ||
87 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
88 | (type << 8) + id, | ||
89 | intf->altsetting[0].desc.bInterfaceNumber, | ||
90 | buf, size, 1000); | ||
91 | } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); | ||
92 | |||
93 | return retval; | ||
72 | } | 94 | } |
73 | 95 | ||
74 | static void wacom_sys_irq(struct urb *urb) | 96 | static void wacom_sys_irq(struct urb *urb) |
@@ -319,23 +341,23 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
319 | rep_data[2] = 0; | 341 | rep_data[2] = 0; |
320 | rep_data[3] = 0; | 342 | rep_data[3] = 0; |
321 | report_id = 3; | 343 | report_id = 3; |
322 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | 344 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, |
323 | report_id, rep_data, 4); | 345 | report_id, rep_data, 4, 1); |
324 | if (error >= 0) | 346 | if (error >= 0) |
325 | error = usb_get_report(intf, | 347 | error = wacom_get_report(intf, |
326 | WAC_HID_FEATURE_REPORT, report_id, | 348 | WAC_HID_FEATURE_REPORT, |
327 | rep_data, 4); | 349 | report_id, rep_data, 4, 1); |
328 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); | 350 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); |
329 | } else if (features->type != TABLETPC) { | 351 | } else if (features->type != TABLETPC) { |
330 | do { | 352 | do { |
331 | rep_data[0] = 2; | 353 | rep_data[0] = 2; |
332 | rep_data[1] = 2; | 354 | rep_data[1] = 2; |
333 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | 355 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, |
334 | report_id, rep_data, 2); | 356 | report_id, rep_data, 2, 1); |
335 | if (error >= 0) | 357 | if (error >= 0) |
336 | error = usb_get_report(intf, | 358 | error = wacom_get_report(intf, |
337 | WAC_HID_FEATURE_REPORT, report_id, | 359 | WAC_HID_FEATURE_REPORT, |
338 | rep_data, 2); | 360 | report_id, rep_data, 2, 1); |
339 | } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES); | 361 | } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES); |
340 | } | 362 | } |
341 | 363 | ||
@@ -454,6 +476,275 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom) | |||
454 | } | 476 | } |
455 | } | 477 | } |
456 | 478 | ||
479 | static int wacom_led_control(struct wacom *wacom) | ||
480 | { | ||
481 | unsigned char *buf; | ||
482 | int retval, led = 0; | ||
483 | |||
484 | buf = kzalloc(9, GFP_KERNEL); | ||
485 | if (!buf) | ||
486 | return -ENOMEM; | ||
487 | |||
488 | if (wacom->wacom_wac.features.type == WACOM_21UX2) | ||
489 | led = (wacom->led.select[1] << 4) | 0x40; | ||
490 | |||
491 | led |= wacom->led.select[0] | 0x4; | ||
492 | |||
493 | buf[0] = WAC_CMD_LED_CONTROL; | ||
494 | buf[1] = led; | ||
495 | buf[2] = wacom->led.llv; | ||
496 | buf[3] = wacom->led.hlv; | ||
497 | buf[4] = wacom->led.img_lum; | ||
498 | |||
499 | retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, | ||
500 | buf, 9, WAC_CMD_RETRIES); | ||
501 | kfree(buf); | ||
502 | |||
503 | return retval; | ||
504 | } | ||
505 | |||
506 | static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img) | ||
507 | { | ||
508 | unsigned char *buf; | ||
509 | int i, retval; | ||
510 | |||
511 | buf = kzalloc(259, GFP_KERNEL); | ||
512 | if (!buf) | ||
513 | return -ENOMEM; | ||
514 | |||
515 | /* Send 'start' command */ | ||
516 | buf[0] = WAC_CMD_ICON_START; | ||
517 | buf[1] = 1; | ||
518 | retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START, | ||
519 | buf, 2, WAC_CMD_RETRIES); | ||
520 | if (retval < 0) | ||
521 | goto out; | ||
522 | |||
523 | buf[0] = WAC_CMD_ICON_XFER; | ||
524 | buf[1] = button_id & 0x07; | ||
525 | for (i = 0; i < 4; i++) { | ||
526 | buf[2] = i; | ||
527 | memcpy(buf + 3, img + i * 256, 256); | ||
528 | |||
529 | retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER, | ||
530 | buf, 259, WAC_CMD_RETRIES); | ||
531 | if (retval < 0) | ||
532 | break; | ||
533 | } | ||
534 | |||
535 | /* Send 'stop' */ | ||
536 | buf[0] = WAC_CMD_ICON_START; | ||
537 | buf[1] = 0; | ||
538 | wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START, | ||
539 | buf, 2, WAC_CMD_RETRIES); | ||
540 | |||
541 | out: | ||
542 | kfree(buf); | ||
543 | return retval; | ||
544 | } | ||
545 | |||
546 | static ssize_t wacom_led_select_store(struct device *dev, int set_id, | ||
547 | const char *buf, size_t count) | ||
548 | { | ||
549 | struct wacom *wacom = dev_get_drvdata(dev); | ||
550 | unsigned int id; | ||
551 | int err; | ||
552 | |||
553 | err = kstrtouint(buf, 10, &id); | ||
554 | if (err) | ||
555 | return err; | ||
556 | |||
557 | mutex_lock(&wacom->lock); | ||
558 | |||
559 | wacom->led.select[set_id] = id & 0x3; | ||
560 | err = wacom_led_control(wacom); | ||
561 | |||
562 | mutex_unlock(&wacom->lock); | ||
563 | |||
564 | return err < 0 ? err : count; | ||
565 | } | ||
566 | |||
567 | #define DEVICE_LED_SELECT_ATTR(SET_ID) \ | ||
568 | static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \ | ||
569 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
570 | { \ | ||
571 | return wacom_led_select_store(dev, SET_ID, buf, count); \ | ||
572 | } \ | ||
573 | static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \ | ||
574 | struct device_attribute *attr, char *buf) \ | ||
575 | { \ | ||
576 | struct wacom *wacom = dev_get_drvdata(dev); \ | ||
577 | return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]); \ | ||
578 | } \ | ||
579 | static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR, \ | ||
580 | wacom_led##SET_ID##_select_show, \ | ||
581 | wacom_led##SET_ID##_select_store) | ||
582 | |||
583 | DEVICE_LED_SELECT_ATTR(0); | ||
584 | DEVICE_LED_SELECT_ATTR(1); | ||
585 | |||
586 | static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest, | ||
587 | const char *buf, size_t count) | ||
588 | { | ||
589 | unsigned int value; | ||
590 | int err; | ||
591 | |||
592 | err = kstrtouint(buf, 10, &value); | ||
593 | if (err) | ||
594 | return err; | ||
595 | |||
596 | mutex_lock(&wacom->lock); | ||
597 | |||
598 | *dest = value & 0x7f; | ||
599 | err = wacom_led_control(wacom); | ||
600 | |||
601 | mutex_unlock(&wacom->lock); | ||
602 | |||
603 | return err < 0 ? err : count; | ||
604 | } | ||
605 | |||
606 | #define DEVICE_LUMINANCE_ATTR(name, field) \ | ||
607 | static ssize_t wacom_##name##_luminance_store(struct device *dev, \ | ||
608 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
609 | { \ | ||
610 | struct wacom *wacom = dev_get_drvdata(dev); \ | ||
611 | \ | ||
612 | return wacom_luminance_store(wacom, &wacom->led.field, \ | ||
613 | buf, count); \ | ||
614 | } \ | ||
615 | static DEVICE_ATTR(name##_luminance, S_IWUSR, \ | ||
616 | NULL, wacom_##name##_luminance_store) | ||
617 | |||
618 | DEVICE_LUMINANCE_ATTR(status0, llv); | ||
619 | DEVICE_LUMINANCE_ATTR(status1, hlv); | ||
620 | DEVICE_LUMINANCE_ATTR(buttons, img_lum); | ||
621 | |||
622 | static ssize_t wacom_button_image_store(struct device *dev, int button_id, | ||
623 | const char *buf, size_t count) | ||
624 | { | ||
625 | struct wacom *wacom = dev_get_drvdata(dev); | ||
626 | int err; | ||
627 | |||
628 | if (count != 1024) | ||
629 | return -EINVAL; | ||
630 | |||
631 | mutex_lock(&wacom->lock); | ||
632 | |||
633 | err = wacom_led_putimage(wacom, button_id, buf); | ||
634 | |||
635 | mutex_unlock(&wacom->lock); | ||
636 | |||
637 | return err < 0 ? err : count; | ||
638 | } | ||
639 | |||
640 | #define DEVICE_BTNIMG_ATTR(BUTTON_ID) \ | ||
641 | static ssize_t wacom_btnimg##BUTTON_ID##_store(struct device *dev, \ | ||
642 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
643 | { \ | ||
644 | return wacom_button_image_store(dev, BUTTON_ID, buf, count); \ | ||
645 | } \ | ||
646 | static DEVICE_ATTR(button##BUTTON_ID##_rawimg, S_IWUSR, \ | ||
647 | NULL, wacom_btnimg##BUTTON_ID##_store) | ||
648 | |||
649 | DEVICE_BTNIMG_ATTR(0); | ||
650 | DEVICE_BTNIMG_ATTR(1); | ||
651 | DEVICE_BTNIMG_ATTR(2); | ||
652 | DEVICE_BTNIMG_ATTR(3); | ||
653 | DEVICE_BTNIMG_ATTR(4); | ||
654 | DEVICE_BTNIMG_ATTR(5); | ||
655 | DEVICE_BTNIMG_ATTR(6); | ||
656 | DEVICE_BTNIMG_ATTR(7); | ||
657 | |||
658 | static struct attribute *cintiq_led_attrs[] = { | ||
659 | &dev_attr_status_led0_select.attr, | ||
660 | &dev_attr_status_led1_select.attr, | ||
661 | NULL | ||
662 | }; | ||
663 | |||
664 | static struct attribute_group cintiq_led_attr_group = { | ||
665 | .name = "wacom_led", | ||
666 | .attrs = cintiq_led_attrs, | ||
667 | }; | ||
668 | |||
669 | static struct attribute *intuos4_led_attrs[] = { | ||
670 | &dev_attr_status0_luminance.attr, | ||
671 | &dev_attr_status1_luminance.attr, | ||
672 | &dev_attr_status_led0_select.attr, | ||
673 | &dev_attr_buttons_luminance.attr, | ||
674 | &dev_attr_button0_rawimg.attr, | ||
675 | &dev_attr_button1_rawimg.attr, | ||
676 | &dev_attr_button2_rawimg.attr, | ||
677 | &dev_attr_button3_rawimg.attr, | ||
678 | &dev_attr_button4_rawimg.attr, | ||
679 | &dev_attr_button5_rawimg.attr, | ||
680 | &dev_attr_button6_rawimg.attr, | ||
681 | &dev_attr_button7_rawimg.attr, | ||
682 | NULL | ||
683 | }; | ||
684 | |||
685 | static struct attribute_group intuos4_led_attr_group = { | ||
686 | .name = "wacom_led", | ||
687 | .attrs = intuos4_led_attrs, | ||
688 | }; | ||
689 | |||
690 | static int wacom_initialize_leds(struct wacom *wacom) | ||
691 | { | ||
692 | int error; | ||
693 | |||
694 | /* Initialize default values */ | ||
695 | switch (wacom->wacom_wac.features.type) { | ||
696 | case INTUOS4: | ||
697 | case INTUOS4L: | ||
698 | wacom->led.select[0] = 0; | ||
699 | wacom->led.select[1] = 0; | ||
700 | wacom->led.llv = 10; | ||
701 | wacom->led.hlv = 20; | ||
702 | wacom->led.img_lum = 10; | ||
703 | error = sysfs_create_group(&wacom->intf->dev.kobj, | ||
704 | &intuos4_led_attr_group); | ||
705 | break; | ||
706 | |||
707 | case WACOM_21UX2: | ||
708 | wacom->led.select[0] = 0; | ||
709 | wacom->led.select[1] = 0; | ||
710 | wacom->led.llv = 0; | ||
711 | wacom->led.hlv = 0; | ||
712 | wacom->led.img_lum = 0; | ||
713 | |||
714 | error = sysfs_create_group(&wacom->intf->dev.kobj, | ||
715 | &cintiq_led_attr_group); | ||
716 | break; | ||
717 | |||
718 | default: | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | if (error) { | ||
723 | dev_err(&wacom->intf->dev, | ||
724 | "cannot create sysfs group err: %d\n", error); | ||
725 | return error; | ||
726 | } | ||
727 | wacom_led_control(wacom); | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static void wacom_destroy_leds(struct wacom *wacom) | ||
733 | { | ||
734 | switch (wacom->wacom_wac.features.type) { | ||
735 | case INTUOS4: | ||
736 | case INTUOS4L: | ||
737 | sysfs_remove_group(&wacom->intf->dev.kobj, | ||
738 | &intuos4_led_attr_group); | ||
739 | break; | ||
740 | |||
741 | case WACOM_21UX2: | ||
742 | sysfs_remove_group(&wacom->intf->dev.kobj, | ||
743 | &cintiq_led_attr_group); | ||
744 | break; | ||
745 | } | ||
746 | } | ||
747 | |||
457 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 748 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
458 | { | 749 | { |
459 | struct usb_device *dev = interface_to_usbdev(intf); | 750 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -542,16 +833,21 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
542 | wacom->irq->transfer_dma = wacom->data_dma; | 833 | wacom->irq->transfer_dma = wacom->data_dma; |
543 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 834 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
544 | 835 | ||
545 | error = input_register_device(input_dev); | 836 | error = wacom_initialize_leds(wacom); |
546 | if (error) | 837 | if (error) |
547 | goto fail4; | 838 | goto fail4; |
548 | 839 | ||
840 | error = input_register_device(input_dev); | ||
841 | if (error) | ||
842 | goto fail5; | ||
843 | |||
549 | /* Note that if query fails it is not a hard failure */ | 844 | /* Note that if query fails it is not a hard failure */ |
550 | wacom_query_tablet_data(intf, features); | 845 | wacom_query_tablet_data(intf, features); |
551 | 846 | ||
552 | usb_set_intfdata(intf, wacom); | 847 | usb_set_intfdata(intf, wacom); |
553 | return 0; | 848 | return 0; |
554 | 849 | ||
850 | fail5: wacom_destroy_leds(wacom); | ||
555 | fail4: wacom_remove_shared_data(wacom_wac); | 851 | fail4: wacom_remove_shared_data(wacom_wac); |
556 | fail3: usb_free_urb(wacom->irq); | 852 | fail3: usb_free_urb(wacom->irq); |
557 | fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); | 853 | fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); |
@@ -568,6 +864,7 @@ static void wacom_disconnect(struct usb_interface *intf) | |||
568 | 864 | ||
569 | usb_kill_urb(wacom->irq); | 865 | usb_kill_urb(wacom->irq); |
570 | input_unregister_device(wacom->wacom_wac.input); | 866 | input_unregister_device(wacom->wacom_wac.input); |
867 | wacom_destroy_leds(wacom); | ||
571 | usb_free_urb(wacom->irq); | 868 | usb_free_urb(wacom->irq); |
572 | usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, | 869 | usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, |
573 | wacom->wacom_wac.data, wacom->data_dma); | 870 | wacom->wacom_wac.data, wacom->data_dma); |
@@ -590,17 +887,16 @@ static int wacom_resume(struct usb_interface *intf) | |||
590 | { | 887 | { |
591 | struct wacom *wacom = usb_get_intfdata(intf); | 888 | struct wacom *wacom = usb_get_intfdata(intf); |
592 | struct wacom_features *features = &wacom->wacom_wac.features; | 889 | struct wacom_features *features = &wacom->wacom_wac.features; |
593 | int rv; | 890 | int rv = 0; |
594 | 891 | ||
595 | mutex_lock(&wacom->lock); | 892 | mutex_lock(&wacom->lock); |
596 | 893 | ||
597 | /* switch to wacom mode first */ | 894 | /* switch to wacom mode first */ |
598 | wacom_query_tablet_data(intf, features); | 895 | wacom_query_tablet_data(intf, features); |
896 | wacom_led_control(wacom); | ||
599 | 897 | ||
600 | if (wacom->open) | 898 | if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0) |
601 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); | 899 | rv = -EIO; |
602 | else | ||
603 | rv = 0; | ||
604 | 900 | ||
605 | mutex_unlock(&wacom->lock); | 901 | mutex_unlock(&wacom->lock); |
606 | 902 | ||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 9dea71849f40..da0d8761e778 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -874,7 +874,15 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) | |||
874 | x = le16_to_cpup((__le16 *)&data[2]); | 874 | x = le16_to_cpup((__le16 *)&data[2]); |
875 | y = le16_to_cpup((__le16 *)&data[4]); | 875 | y = le16_to_cpup((__le16 *)&data[4]); |
876 | p = le16_to_cpup((__le16 *)&data[6]); | 876 | p = le16_to_cpup((__le16 *)&data[6]); |
877 | d = data[8]; | 877 | /* |
878 | * Convert distance from out prox to distance from tablet. | ||
879 | * distance will be greater than distance_max once | ||
880 | * touching and applying pressure; do not report negative | ||
881 | * distance. | ||
882 | */ | ||
883 | if (data[8] <= wacom->features.distance_max) | ||
884 | d = wacom->features.distance_max - data[8]; | ||
885 | |||
878 | pen = data[1] & 0x01; | 886 | pen = data[1] & 0x01; |
879 | btn1 = data[1] & 0x02; | 887 | btn1 = data[1] & 0x02; |
880 | btn2 = data[1] & 0x04; | 888 | btn2 = data[1] & 0x04; |
@@ -1030,8 +1038,6 @@ void wacom_setup_device_quirks(struct wacom_features *features) | |||
1030 | features->y_max <<= 5; | 1038 | features->y_max <<= 5; |
1031 | features->x_fuzz <<= 5; | 1039 | features->x_fuzz <<= 5; |
1032 | features->y_fuzz <<= 5; | 1040 | features->y_fuzz <<= 5; |
1033 | features->pressure_max = 256; | ||
1034 | features->pressure_fuzz = 16; | ||
1035 | features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES; | 1041 | features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES; |
1036 | } | 1042 | } |
1037 | } | 1043 | } |
@@ -1241,14 +1247,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1241 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | 1247 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, |
1242 | 0, features->y_max, | 1248 | 0, features->y_max, |
1243 | features->y_fuzz, 0); | 1249 | features->y_fuzz, 0); |
1244 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | ||
1245 | 0, features->pressure_max, | ||
1246 | features->pressure_fuzz, 0); | ||
1247 | } else if (features->device_type == BTN_TOOL_PEN) { | 1250 | } else if (features->device_type == BTN_TOOL_PEN) { |
1248 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | 1251 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
1249 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | 1252 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
1250 | __set_bit(BTN_STYLUS, input_dev->keybit); | 1253 | __set_bit(BTN_STYLUS, input_dev->keybit); |
1251 | __set_bit(BTN_STYLUS2, input_dev->keybit); | 1254 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
1255 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, | ||
1256 | features->distance_max, | ||
1257 | 0, 0); | ||
1252 | } | 1258 | } |
1253 | break; | 1259 | break; |
1254 | } | 1260 | } |
@@ -1469,37 +1475,37 @@ static const struct wacom_features wacom_features_0x47 = | |||
1469 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1475 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1470 | static const struct wacom_features wacom_features_0xD0 = | 1476 | static const struct wacom_features wacom_features_0xD0 = |
1471 | { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1477 | { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1472 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1478 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1473 | static const struct wacom_features wacom_features_0xD1 = | 1479 | static const struct wacom_features wacom_features_0xD1 = |
1474 | { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1480 | { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1475 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1481 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1476 | static const struct wacom_features wacom_features_0xD2 = | 1482 | static const struct wacom_features wacom_features_0xD2 = |
1477 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1483 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1478 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1484 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1479 | static const struct wacom_features wacom_features_0xD3 = | 1485 | static const struct wacom_features wacom_features_0xD3 = |
1480 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, | 1486 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, |
1481 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1487 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1482 | static const struct wacom_features wacom_features_0xD4 = | 1488 | static const struct wacom_features wacom_features_0xD4 = |
1483 | { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1489 | { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1484 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1490 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1485 | static const struct wacom_features wacom_features_0xD5 = | 1491 | static const struct wacom_features wacom_features_0xD5 = |
1486 | { "Wacom Bamboo Pen 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, | 1492 | { "Wacom Bamboo Pen 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, |
1487 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1493 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1488 | static const struct wacom_features wacom_features_0xD6 = | 1494 | static const struct wacom_features wacom_features_0xD6 = |
1489 | { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1495 | { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1490 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1496 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1491 | static const struct wacom_features wacom_features_0xD7 = | 1497 | static const struct wacom_features wacom_features_0xD7 = |
1492 | { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1498 | { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1493 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1499 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1494 | static const struct wacom_features wacom_features_0xD8 = | 1500 | static const struct wacom_features wacom_features_0xD8 = |
1495 | { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, | 1501 | { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, |
1496 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1502 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1497 | static const struct wacom_features wacom_features_0xDA = | 1503 | static const struct wacom_features wacom_features_0xDA = |
1498 | { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1504 | { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
1499 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1505 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1500 | static struct wacom_features wacom_features_0xDB = | 1506 | static struct wacom_features wacom_features_0xDB = |
1501 | { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, | 1507 | { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, |
1502 | 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1508 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
1503 | static const struct wacom_features wacom_features_0x6004 = | 1509 | static const struct wacom_features wacom_features_0x6004 = |
1504 | { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, | 1510 | { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, |
1505 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1511 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index cabd9e54863f..3488ffe1fa0a 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -651,6 +651,18 @@ config TOUCHSCREEN_TOUCHIT213 | |||
651 | To compile this driver as a module, choose M here: the | 651 | To compile this driver as a module, choose M here: the |
652 | module will be called touchit213. | 652 | module will be called touchit213. |
653 | 653 | ||
654 | config TOUCHSCREEN_TSC_SERIO | ||
655 | tristate "TSC-10/25/40 serial touchscreen support" | ||
656 | select SERIO | ||
657 | help | ||
658 | Say Y here if you have a TSC-10, 25 or 40 serial touchscreen connected | ||
659 | to your system. | ||
660 | |||
661 | If unsure, say N. | ||
662 | |||
663 | To compile this driver as a module, choose M here: the | ||
664 | module will be called tsc40. | ||
665 | |||
654 | config TOUCHSCREEN_TSC2005 | 666 | config TOUCHSCREEN_TSC2005 |
655 | tristate "TSC2005 based touchscreens" | 667 | tristate "TSC2005 based touchscreens" |
656 | depends on SPI_MASTER && GENERIC_HARDIRQS | 668 | depends on SPI_MASTER && GENERIC_HARDIRQS |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 282d6f76ae26..f957676035a4 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -46,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | |||
46 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 46 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
47 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 47 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
48 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 48 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
49 | obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO) += tsc40.o | ||
49 | obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o | 50 | obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o |
50 | obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o | 51 | obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o |
51 | obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o | 52 | obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o |
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index 4e4e58cec6c8..c789b974c795 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ | 17 | #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ |
18 | 18 | ||
19 | #ifdef CONFIG_PM | 19 | #ifdef CONFIG_PM_SLEEP |
20 | static int ad7879_i2c_suspend(struct device *dev) | 20 | static int ad7879_i2c_suspend(struct device *dev) |
21 | { | 21 | { |
22 | struct i2c_client *client = to_i2c_client(dev); | 22 | struct i2c_client *client = to_i2c_client(dev); |
@@ -36,9 +36,9 @@ static int ad7879_i2c_resume(struct device *dev) | |||
36 | 36 | ||
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | #endif | ||
39 | 40 | ||
40 | static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume); | 41 | static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume); |
41 | #endif | ||
42 | 42 | ||
43 | /* All registers are word-sized. | 43 | /* All registers are word-sized. |
44 | * AD7879 uses a high-byte first convention. | 44 | * AD7879 uses a high-byte first convention. |
@@ -119,9 +119,7 @@ static struct i2c_driver ad7879_i2c_driver = { | |||
119 | .driver = { | 119 | .driver = { |
120 | .name = "ad7879", | 120 | .name = "ad7879", |
121 | .owner = THIS_MODULE, | 121 | .owner = THIS_MODULE, |
122 | #ifdef CONFIG_PM | ||
123 | .pm = &ad7879_i2c_pm, | 122 | .pm = &ad7879_i2c_pm, |
124 | #endif | ||
125 | }, | 123 | }, |
126 | .probe = ad7879_i2c_probe, | 124 | .probe = ad7879_i2c_probe, |
127 | .remove = __devexit_p(ad7879_i2c_remove), | 125 | .remove = __devexit_p(ad7879_i2c_remove), |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index f5d66859f232..a596c2775d1a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -910,12 +910,17 @@ static ssize_t mxt_object_show(struct device *dev, | |||
910 | for (i = 0; i < data->info.object_num; i++) { | 910 | for (i = 0; i < data->info.object_num; i++) { |
911 | object = data->object_table + i; | 911 | object = data->object_table + i; |
912 | 912 | ||
913 | count += sprintf(buf + count, | 913 | count += snprintf(buf + count, PAGE_SIZE - count, |
914 | "Object Table Element %d(Type %d)\n", | 914 | "Object[%d] (Type %d)\n", |
915 | i + 1, object->type); | 915 | i + 1, object->type); |
916 | if (count >= PAGE_SIZE) | ||
917 | return PAGE_SIZE - 1; | ||
916 | 918 | ||
917 | if (!mxt_object_readable(object->type)) { | 919 | if (!mxt_object_readable(object->type)) { |
918 | count += sprintf(buf + count, "\n"); | 920 | count += snprintf(buf + count, PAGE_SIZE - count, |
921 | "\n"); | ||
922 | if (count >= PAGE_SIZE) | ||
923 | return PAGE_SIZE - 1; | ||
919 | continue; | 924 | continue; |
920 | } | 925 | } |
921 | 926 | ||
@@ -925,11 +930,15 @@ static ssize_t mxt_object_show(struct device *dev, | |||
925 | if (error) | 930 | if (error) |
926 | return error; | 931 | return error; |
927 | 932 | ||
928 | count += sprintf(buf + count, | 933 | count += snprintf(buf + count, PAGE_SIZE - count, |
929 | " Byte %d: 0x%x (%d)\n", j, val, val); | 934 | "\t[%2d]: %02x (%d)\n", j, val, val); |
935 | if (count >= PAGE_SIZE) | ||
936 | return PAGE_SIZE - 1; | ||
930 | } | 937 | } |
931 | 938 | ||
932 | count += sprintf(buf + count, "\n"); | 939 | count += snprintf(buf + count, PAGE_SIZE - count, "\n"); |
940 | if (count >= PAGE_SIZE) | ||
941 | return PAGE_SIZE - 1; | ||
933 | } | 942 | } |
934 | 943 | ||
935 | return count; | 944 | return count; |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 432c69be6ac6..122a87883659 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -229,7 +229,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
229 | goto err_release_mem; | 229 | goto err_release_mem; |
230 | } | 230 | } |
231 | 231 | ||
232 | err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED, | 232 | err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0, |
233 | pdev->dev.driver->name, ts_dev); | 233 | pdev->dev.driver->name, ts_dev); |
234 | if (err) { | 234 | if (err) { |
235 | dev_err(&pdev->dev, "failed to allocate irq.\n"); | 235 | dev_err(&pdev->dev, "failed to allocate irq.\n"); |
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 211811ae5525..6107e563e681 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -396,14 +396,14 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
396 | set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); | 396 | set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); |
397 | 397 | ||
398 | if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, | 398 | if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, |
399 | IRQF_SHARED | IRQF_DISABLED, "h3600_action", ts->dev)) { | 399 | IRQF_SHARED, "h3600_action", ts->dev)) { |
400 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); | 400 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); |
401 | err = -EBUSY; | 401 | err = -EBUSY; |
402 | goto fail1; | 402 | goto fail1; |
403 | } | 403 | } |
404 | 404 | ||
405 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, | 405 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, |
406 | IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", ts->dev)) { | 406 | IRQF_SHARED, "h3600_suspend", ts->dev)) { |
407 | printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); | 407 | printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); |
408 | err = -EBUSY; | 408 | err = -EBUSY; |
409 | goto fail2; | 409 | goto fail2; |
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c index dd4e8f020b99..639a6044183d 100644 --- a/drivers/input/touchscreen/hp680_ts_input.c +++ b/drivers/input/touchscreen/hp680_ts_input.c | |||
@@ -93,7 +93,7 @@ static int __init hp680_ts_init(void) | |||
93 | hp680_ts_dev->phys = "hp680_ts/input0"; | 93 | hp680_ts_dev->phys = "hp680_ts/input0"; |
94 | 94 | ||
95 | if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, | 95 | if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, |
96 | IRQF_DISABLED, MODNAME, 0) < 0) { | 96 | 0, MODNAME, 0) < 0) { |
97 | printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", | 97 | printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", |
98 | HP680_TS_IRQ); | 98 | HP680_TS_IRQ); |
99 | err = -EBUSY; | 99 | err = -EBUSY; |
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index 4b0a061811ff..50076c2d59e2 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c | |||
@@ -127,7 +127,7 @@ static int __devinit jornada720_ts_probe(struct platform_device *pdev) | |||
127 | 127 | ||
128 | error = request_irq(IRQ_GPIO9, | 128 | error = request_irq(IRQ_GPIO9, |
129 | jornada720_ts_interrupt, | 129 | jornada720_ts_interrupt, |
130 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | 130 | IRQF_TRIGGER_RISING, |
131 | "HP7XX Touchscreen driver", pdev); | 131 | "HP7XX Touchscreen driver", pdev); |
132 | if (error) { | 132 | if (error) { |
133 | printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n"); | 133 | printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n"); |
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index dcf803f5a1f7..0a484ed5295c 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c | |||
@@ -276,7 +276,7 @@ static int __devinit lpc32xx_ts_probe(struct platform_device *pdev) | |||
276 | input_set_drvdata(input, tsc); | 276 | input_set_drvdata(input, tsc); |
277 | 277 | ||
278 | error = request_irq(tsc->irq, lpc32xx_ts_interrupt, | 278 | error = request_irq(tsc->irq, lpc32xx_ts_interrupt, |
279 | IRQF_DISABLED, pdev->name, tsc); | 279 | 0, pdev->name, tsc); |
280 | if (error) { | 280 | if (error) { |
281 | dev_err(&pdev->dev, "failed requesting interrupt\n"); | 281 | dev_err(&pdev->dev, "failed requesting interrupt\n"); |
282 | goto err_put_clock; | 282 | goto err_put_clock; |
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index c7f9cebebbb6..4c012fb2b01e 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Penmount serial touchscreen driver | 2 | * Penmount serial touchscreen driver |
3 | * | 3 | * |
4 | * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> | 4 | * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> |
5 | * Copyright (c) 2011 John Sung <penmount.touch@gmail.com> | ||
5 | * | 6 | * |
6 | * Based on ELO driver (drivers/input/touchscreen/elo.c) | 7 | * Based on ELO driver (drivers/input/touchscreen/elo.c) |
7 | * Copyright (c) 2004 Vojtech Pavlik | 8 | * Copyright (c) 2004 Vojtech Pavlik |
@@ -18,12 +19,14 @@ | |||
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <linux/input.h> | 21 | #include <linux/input.h> |
22 | #include <linux/input/mt.h> | ||
21 | #include <linux/serio.h> | 23 | #include <linux/serio.h> |
22 | #include <linux/init.h> | 24 | #include <linux/init.h> |
23 | 25 | ||
24 | #define DRIVER_DESC "Penmount serial touchscreen driver" | 26 | #define DRIVER_DESC "PenMount serial touchscreen driver" |
25 | 27 | ||
26 | MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); | 28 | MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); |
29 | MODULE_AUTHOR("John Sung <penmount.touch@gmail.com>"); | ||
27 | MODULE_DESCRIPTION(DRIVER_DESC); | 30 | MODULE_DESCRIPTION(DRIVER_DESC); |
28 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
29 | 32 | ||
@@ -31,7 +34,19 @@ MODULE_LICENSE("GPL"); | |||
31 | * Definitions & global arrays. | 34 | * Definitions & global arrays. |
32 | */ | 35 | */ |
33 | 36 | ||
34 | #define PM_MAX_LENGTH 5 | 37 | #define PM_MAX_LENGTH 6 |
38 | #define PM_MAX_MTSLOT 16 | ||
39 | #define PM_3000_MTSLOT 2 | ||
40 | #define PM_6250_MTSLOT 12 | ||
41 | |||
42 | /* | ||
43 | * Multi-touch slot | ||
44 | */ | ||
45 | |||
46 | struct mt_slot { | ||
47 | unsigned short x, y; | ||
48 | bool active; /* is the touch valid? */ | ||
49 | }; | ||
35 | 50 | ||
36 | /* | 51 | /* |
37 | * Per-touchscreen data. | 52 | * Per-touchscreen data. |
@@ -43,25 +58,119 @@ struct pm { | |||
43 | int idx; | 58 | int idx; |
44 | unsigned char data[PM_MAX_LENGTH]; | 59 | unsigned char data[PM_MAX_LENGTH]; |
45 | char phys[32]; | 60 | char phys[32]; |
61 | unsigned char packetsize; | ||
62 | unsigned char maxcontacts; | ||
63 | struct mt_slot slots[PM_MAX_MTSLOT]; | ||
64 | void (*parse_packet)(struct pm *); | ||
46 | }; | 65 | }; |
47 | 66 | ||
48 | static irqreturn_t pm_interrupt(struct serio *serio, | 67 | /* |
49 | unsigned char data, unsigned int flags) | 68 | * pm_mtevent() sends mt events and also emulates pointer movement |
69 | */ | ||
70 | |||
71 | static void pm_mtevent(struct pm *pm, struct input_dev *input) | ||
72 | { | ||
73 | int i; | ||
74 | |||
75 | for (i = 0; i < pm->maxcontacts; ++i) { | ||
76 | input_mt_slot(input, i); | ||
77 | input_mt_report_slot_state(input, MT_TOOL_FINGER, | ||
78 | pm->slots[i].active); | ||
79 | if (pm->slots[i].active) { | ||
80 | input_event(input, EV_ABS, ABS_MT_POSITION_X, pm->slots[i].x); | ||
81 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, pm->slots[i].y); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | input_mt_report_pointer_emulation(input, true); | ||
86 | input_sync(input); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * pm_checkpacket() checks if data packet is valid | ||
91 | */ | ||
92 | |||
93 | static bool pm_checkpacket(unsigned char *packet) | ||
94 | { | ||
95 | int total = 0; | ||
96 | int i; | ||
97 | |||
98 | for (i = 0; i < 5; i++) | ||
99 | total += packet[i]; | ||
100 | |||
101 | return packet[5] == (unsigned char)~(total & 0xff); | ||
102 | } | ||
103 | |||
104 | static void pm_parse_9000(struct pm *pm) | ||
50 | { | 105 | { |
51 | struct pm *pm = serio_get_drvdata(serio); | ||
52 | struct input_dev *dev = pm->dev; | 106 | struct input_dev *dev = pm->dev; |
53 | 107 | ||
54 | pm->data[pm->idx] = data; | 108 | if ((pm->data[0] & 0x80) && pm->packetsize == ++pm->idx) { |
109 | input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]); | ||
110 | input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]); | ||
111 | input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40)); | ||
112 | input_sync(dev); | ||
113 | pm->idx = 0; | ||
114 | } | ||
115 | } | ||
55 | 116 | ||
56 | if (pm->data[0] & 0x80) { | 117 | static void pm_parse_6000(struct pm *pm) |
57 | if (PM_MAX_LENGTH == ++pm->idx) { | 118 | { |
58 | input_report_abs(dev, ABS_X, pm->data[2] * 128 + pm->data[1]); | 119 | struct input_dev *dev = pm->dev; |
59 | input_report_abs(dev, ABS_Y, pm->data[4] * 128 + pm->data[3]); | 120 | |
60 | input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40)); | 121 | if ((pm->data[0] & 0xbf) == 0x30 && pm->packetsize == ++pm->idx) { |
122 | if (pm_checkpacket(pm->data)) { | ||
123 | input_report_abs(dev, ABS_X, | ||
124 | pm->data[2] * 256 + pm->data[1]); | ||
125 | input_report_abs(dev, ABS_Y, | ||
126 | pm->data[4] * 256 + pm->data[3]); | ||
127 | input_report_key(dev, BTN_TOUCH, pm->data[0] & 0x40); | ||
61 | input_sync(dev); | 128 | input_sync(dev); |
62 | pm->idx = 0; | ||
63 | } | 129 | } |
130 | pm->idx = 0; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void pm_parse_3000(struct pm *pm) | ||
135 | { | ||
136 | struct input_dev *dev = pm->dev; | ||
137 | |||
138 | if ((pm->data[0] & 0xce) == 0x40 && pm->packetsize == ++pm->idx) { | ||
139 | if (pm_checkpacket(pm->data)) { | ||
140 | int slotnum = pm->data[0] & 0x0f; | ||
141 | pm->slots[slotnum].active = pm->data[0] & 0x30; | ||
142 | pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1]; | ||
143 | pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3]; | ||
144 | pm_mtevent(pm, dev); | ||
145 | } | ||
146 | pm->idx = 0; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static void pm_parse_6250(struct pm *pm) | ||
151 | { | ||
152 | struct input_dev *dev = pm->dev; | ||
153 | |||
154 | if ((pm->data[0] & 0xb0) == 0x30 && pm->packetsize == ++pm->idx) { | ||
155 | if (pm_checkpacket(pm->data)) { | ||
156 | int slotnum = pm->data[0] & 0x0f; | ||
157 | pm->slots[slotnum].active = pm->data[0] & 0x40; | ||
158 | pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1]; | ||
159 | pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3]; | ||
160 | pm_mtevent(pm, dev); | ||
161 | } | ||
162 | pm->idx = 0; | ||
64 | } | 163 | } |
164 | } | ||
165 | |||
166 | static irqreturn_t pm_interrupt(struct serio *serio, | ||
167 | unsigned char data, unsigned int flags) | ||
168 | { | ||
169 | struct pm *pm = serio_get_drvdata(serio); | ||
170 | |||
171 | pm->data[pm->idx] = data; | ||
172 | |||
173 | pm->parse_packet(pm); | ||
65 | 174 | ||
66 | return IRQ_HANDLED; | 175 | return IRQ_HANDLED; |
67 | } | 176 | } |
@@ -74,17 +183,17 @@ static void pm_disconnect(struct serio *serio) | |||
74 | { | 183 | { |
75 | struct pm *pm = serio_get_drvdata(serio); | 184 | struct pm *pm = serio_get_drvdata(serio); |
76 | 185 | ||
77 | input_get_device(pm->dev); | ||
78 | input_unregister_device(pm->dev); | ||
79 | serio_close(serio); | 186 | serio_close(serio); |
80 | serio_set_drvdata(serio, NULL); | 187 | |
81 | input_put_device(pm->dev); | 188 | input_unregister_device(pm->dev); |
82 | kfree(pm); | 189 | kfree(pm); |
190 | |||
191 | serio_set_drvdata(serio, NULL); | ||
83 | } | 192 | } |
84 | 193 | ||
85 | /* | 194 | /* |
86 | * pm_connect() is the routine that is called when someone adds a | 195 | * pm_connect() is the routine that is called when someone adds a |
87 | * new serio device that supports Gunze protocol and registers it as | 196 | * new serio device that supports PenMount protocol and registers it as |
88 | * an input device. | 197 | * an input device. |
89 | */ | 198 | */ |
90 | 199 | ||
@@ -92,6 +201,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) | |||
92 | { | 201 | { |
93 | struct pm *pm; | 202 | struct pm *pm; |
94 | struct input_dev *input_dev; | 203 | struct input_dev *input_dev; |
204 | int max_x, max_y; | ||
95 | int err; | 205 | int err; |
96 | 206 | ||
97 | pm = kzalloc(sizeof(struct pm), GFP_KERNEL); | 207 | pm = kzalloc(sizeof(struct pm), GFP_KERNEL); |
@@ -104,8 +214,9 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) | |||
104 | pm->serio = serio; | 214 | pm->serio = serio; |
105 | pm->dev = input_dev; | 215 | pm->dev = input_dev; |
106 | snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys); | 216 | snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys); |
217 | pm->maxcontacts = 1; | ||
107 | 218 | ||
108 | input_dev->name = "Penmount Serial TouchScreen"; | 219 | input_dev->name = "PenMount Serial TouchScreen"; |
109 | input_dev->phys = pm->phys; | 220 | input_dev->phys = pm->phys; |
110 | input_dev->id.bustype = BUS_RS232; | 221 | input_dev->id.bustype = BUS_RS232; |
111 | input_dev->id.vendor = SERIO_PENMOUNT; | 222 | input_dev->id.vendor = SERIO_PENMOUNT; |
@@ -113,10 +224,52 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) | |||
113 | input_dev->id.version = 0x0100; | 224 | input_dev->id.version = 0x0100; |
114 | input_dev->dev.parent = &serio->dev; | 225 | input_dev->dev.parent = &serio->dev; |
115 | 226 | ||
116 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 227 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
117 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 228 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
118 | input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0); | 229 | |
119 | input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0); | 230 | switch (serio->id.id) { |
231 | default: | ||
232 | case 0: | ||
233 | pm->packetsize = 5; | ||
234 | pm->parse_packet = pm_parse_9000; | ||
235 | input_dev->id.product = 0x9000; | ||
236 | max_x = max_y = 0x3ff; | ||
237 | break; | ||
238 | |||
239 | case 1: | ||
240 | pm->packetsize = 6; | ||
241 | pm->parse_packet = pm_parse_6000; | ||
242 | input_dev->id.product = 0x6000; | ||
243 | max_x = max_y = 0x3ff; | ||
244 | break; | ||
245 | |||
246 | case 2: | ||
247 | pm->packetsize = 6; | ||
248 | pm->parse_packet = pm_parse_3000; | ||
249 | input_dev->id.product = 0x3000; | ||
250 | max_x = max_y = 0x7ff; | ||
251 | pm->maxcontacts = PM_3000_MTSLOT; | ||
252 | break; | ||
253 | |||
254 | case 3: | ||
255 | pm->packetsize = 6; | ||
256 | pm->parse_packet = pm_parse_6250; | ||
257 | input_dev->id.product = 0x6250; | ||
258 | max_x = max_y = 0x3ff; | ||
259 | pm->maxcontacts = PM_6250_MTSLOT; | ||
260 | break; | ||
261 | } | ||
262 | |||
263 | input_set_abs_params(pm->dev, ABS_X, 0, max_x, 0, 0); | ||
264 | input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0); | ||
265 | |||
266 | if (pm->maxcontacts > 1) { | ||
267 | input_mt_init_slots(pm->dev, pm->maxcontacts); | ||
268 | input_set_abs_params(pm->dev, | ||
269 | ABS_MT_POSITION_X, 0, max_x, 0, 0); | ||
270 | input_set_abs_params(pm->dev, | ||
271 | ABS_MT_POSITION_Y, 0, max_y, 0, 0); | ||
272 | } | ||
120 | 273 | ||
121 | serio_set_drvdata(serio, pm); | 274 | serio_set_drvdata(serio, pm); |
122 | 275 | ||
@@ -155,7 +308,7 @@ MODULE_DEVICE_TABLE(serio, pm_serio_ids); | |||
155 | 308 | ||
156 | static struct serio_driver pm_drv = { | 309 | static struct serio_driver pm_drv = { |
157 | .driver = { | 310 | .driver = { |
158 | .name = "penmountlpc", | 311 | .name = "serio-penmount", |
159 | }, | 312 | }, |
160 | .description = DRIVER_DESC, | 313 | .description = DRIVER_DESC, |
161 | .id_table = pm_serio_ids, | 314 | .id_table = pm_serio_ids, |
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 8feb7f3c8be1..64ce697a3456 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c | |||
@@ -328,7 +328,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) | |||
328 | ts.shift = info->oversampling_shift; | 328 | ts.shift = info->oversampling_shift; |
329 | ts.features = platform_get_device_id(pdev)->driver_data; | 329 | ts.features = platform_get_device_id(pdev)->driver_data; |
330 | 330 | ||
331 | ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, | 331 | ret = request_irq(ts.irq_tc, stylus_irq, 0, |
332 | "s3c2410_ts_pen", ts.input); | 332 | "s3c2410_ts_pen", ts.input); |
333 | if (ret) { | 333 | if (ret) { |
334 | dev_err(dev, "cannot get TC interrupt\n"); | 334 | dev_err(dev, "cannot get TC interrupt\n"); |
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index fadc11545b1e..1f674cb6c55b 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -66,7 +66,6 @@ struct ts_event { | |||
66 | struct tsc2007 { | 66 | struct tsc2007 { |
67 | struct input_dev *input; | 67 | struct input_dev *input; |
68 | char phys[32]; | 68 | char phys[32]; |
69 | struct delayed_work work; | ||
70 | 69 | ||
71 | struct i2c_client *client; | 70 | struct i2c_client *client; |
72 | 71 | ||
@@ -76,9 +75,11 @@ struct tsc2007 { | |||
76 | unsigned long poll_delay; | 75 | unsigned long poll_delay; |
77 | unsigned long poll_period; | 76 | unsigned long poll_period; |
78 | 77 | ||
79 | bool pendown; | ||
80 | int irq; | 78 | int irq; |
81 | 79 | ||
80 | wait_queue_head_t wait; | ||
81 | bool stopped; | ||
82 | |||
82 | int (*get_pendown_state)(void); | 83 | int (*get_pendown_state)(void); |
83 | void (*clear_penirq)(void); | 84 | void (*clear_penirq)(void); |
84 | }; | 85 | }; |
@@ -141,25 +142,8 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) | |||
141 | return rt; | 142 | return rt; |
142 | } | 143 | } |
143 | 144 | ||
144 | static void tsc2007_send_up_event(struct tsc2007 *tsc) | 145 | static bool tsc2007_is_pen_down(struct tsc2007 *ts) |
145 | { | 146 | { |
146 | struct input_dev *input = tsc->input; | ||
147 | |||
148 | dev_dbg(&tsc->client->dev, "UP\n"); | ||
149 | |||
150 | input_report_key(input, BTN_TOUCH, 0); | ||
151 | input_report_abs(input, ABS_PRESSURE, 0); | ||
152 | input_sync(input); | ||
153 | } | ||
154 | |||
155 | static void tsc2007_work(struct work_struct *work) | ||
156 | { | ||
157 | struct tsc2007 *ts = | ||
158 | container_of(to_delayed_work(work), struct tsc2007, work); | ||
159 | bool debounced = false; | ||
160 | struct ts_event tc; | ||
161 | u32 rt; | ||
162 | |||
163 | /* | 147 | /* |
164 | * NOTE: We can't rely on the pressure to determine the pen down | 148 | * NOTE: We can't rely on the pressure to determine the pen down |
165 | * state, even though this controller has a pressure sensor. | 149 | * state, even though this controller has a pressure sensor. |
@@ -170,79 +154,82 @@ static void tsc2007_work(struct work_struct *work) | |||
170 | * The only safe way to check for the pen up condition is in the | 154 | * The only safe way to check for the pen up condition is in the |
171 | * work function by reading the pen signal state (it's a GPIO | 155 | * work function by reading the pen signal state (it's a GPIO |
172 | * and IRQ). Unfortunately such callback is not always available, | 156 | * and IRQ). Unfortunately such callback is not always available, |
173 | * in that case we have rely on the pressure anyway. | 157 | * in that case we assume that the pen is down and expect caller |
158 | * to fall back on the pressure reading. | ||
174 | */ | 159 | */ |
175 | if (ts->get_pendown_state) { | ||
176 | if (unlikely(!ts->get_pendown_state())) { | ||
177 | tsc2007_send_up_event(ts); | ||
178 | ts->pendown = false; | ||
179 | goto out; | ||
180 | } | ||
181 | 160 | ||
182 | dev_dbg(&ts->client->dev, "pen is still down\n"); | 161 | if (!ts->get_pendown_state) |
183 | } | 162 | return true; |
163 | |||
164 | return ts->get_pendown_state(); | ||
165 | } | ||
166 | |||
167 | static irqreturn_t tsc2007_soft_irq(int irq, void *handle) | ||
168 | { | ||
169 | struct tsc2007 *ts = handle; | ||
170 | struct input_dev *input = ts->input; | ||
171 | struct ts_event tc; | ||
172 | u32 rt; | ||
184 | 173 | ||
185 | tsc2007_read_values(ts, &tc); | 174 | while (!ts->stopped && tsc2007_is_pen_down(ts)) { |
186 | 175 | ||
187 | rt = tsc2007_calculate_pressure(ts, &tc); | 176 | /* pen is down, continue with the measurement */ |
188 | if (rt > ts->max_rt) { | 177 | tsc2007_read_values(ts, &tc); |
189 | /* | ||
190 | * Sample found inconsistent by debouncing or pressure is | ||
191 | * beyond the maximum. Don't report it to user space, | ||
192 | * repeat at least once more the measurement. | ||
193 | */ | ||
194 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | ||
195 | debounced = true; | ||
196 | goto out; | ||
197 | 178 | ||
198 | } | 179 | rt = tsc2007_calculate_pressure(ts, &tc); |
199 | 180 | ||
200 | if (rt) { | 181 | if (rt == 0 && !ts->get_pendown_state) { |
201 | struct input_dev *input = ts->input; | 182 | /* |
183 | * If pressure reported is 0 and we don't have | ||
184 | * callback to check pendown state, we have to | ||
185 | * assume that pen was lifted up. | ||
186 | */ | ||
187 | break; | ||
188 | } | ||
202 | 189 | ||
203 | if (!ts->pendown) { | 190 | if (rt <= ts->max_rt) { |
204 | dev_dbg(&ts->client->dev, "DOWN\n"); | 191 | dev_dbg(&ts->client->dev, |
192 | "DOWN point(%4d,%4d), pressure (%4u)\n", | ||
193 | tc.x, tc.y, rt); | ||
205 | 194 | ||
206 | input_report_key(input, BTN_TOUCH, 1); | 195 | input_report_key(input, BTN_TOUCH, 1); |
207 | ts->pendown = true; | 196 | input_report_abs(input, ABS_X, tc.x); |
197 | input_report_abs(input, ABS_Y, tc.y); | ||
198 | input_report_abs(input, ABS_PRESSURE, rt); | ||
199 | |||
200 | input_sync(input); | ||
201 | |||
202 | } else { | ||
203 | /* | ||
204 | * Sample found inconsistent by debouncing or pressure is | ||
205 | * beyond the maximum. Don't report it to user space, | ||
206 | * repeat at least once more the measurement. | ||
207 | */ | ||
208 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | ||
208 | } | 209 | } |
209 | 210 | ||
210 | input_report_abs(input, ABS_X, tc.x); | 211 | wait_event_timeout(ts->wait, ts->stopped, |
211 | input_report_abs(input, ABS_Y, tc.y); | 212 | msecs_to_jiffies(ts->poll_period)); |
212 | input_report_abs(input, ABS_PRESSURE, rt); | 213 | } |
213 | 214 | ||
214 | input_sync(input); | 215 | dev_dbg(&ts->client->dev, "UP\n"); |
215 | 216 | ||
216 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", | 217 | input_report_key(input, BTN_TOUCH, 0); |
217 | tc.x, tc.y, rt); | 218 | input_report_abs(input, ABS_PRESSURE, 0); |
219 | input_sync(input); | ||
218 | 220 | ||
219 | } else if (!ts->get_pendown_state && ts->pendown) { | 221 | if (ts->clear_penirq) |
220 | /* | 222 | ts->clear_penirq(); |
221 | * We don't have callback to check pendown state, so we | ||
222 | * have to assume that since pressure reported is 0 the | ||
223 | * pen was lifted up. | ||
224 | */ | ||
225 | tsc2007_send_up_event(ts); | ||
226 | ts->pendown = false; | ||
227 | } | ||
228 | 223 | ||
229 | out: | 224 | return IRQ_HANDLED; |
230 | if (ts->pendown || debounced) | ||
231 | schedule_delayed_work(&ts->work, | ||
232 | msecs_to_jiffies(ts->poll_period)); | ||
233 | else | ||
234 | enable_irq(ts->irq); | ||
235 | } | 225 | } |
236 | 226 | ||
237 | static irqreturn_t tsc2007_irq(int irq, void *handle) | 227 | static irqreturn_t tsc2007_hard_irq(int irq, void *handle) |
238 | { | 228 | { |
239 | struct tsc2007 *ts = handle; | 229 | struct tsc2007 *ts = handle; |
240 | 230 | ||
241 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) { | 231 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) |
242 | disable_irq_nosync(ts->irq); | 232 | return IRQ_WAKE_THREAD; |
243 | schedule_delayed_work(&ts->work, | ||
244 | msecs_to_jiffies(ts->poll_delay)); | ||
245 | } | ||
246 | 233 | ||
247 | if (ts->clear_penirq) | 234 | if (ts->clear_penirq) |
248 | ts->clear_penirq(); | 235 | ts->clear_penirq(); |
@@ -250,17 +237,40 @@ static irqreturn_t tsc2007_irq(int irq, void *handle) | |||
250 | return IRQ_HANDLED; | 237 | return IRQ_HANDLED; |
251 | } | 238 | } |
252 | 239 | ||
253 | static void tsc2007_free_irq(struct tsc2007 *ts) | 240 | static void tsc2007_stop(struct tsc2007 *ts) |
254 | { | 241 | { |
255 | free_irq(ts->irq, ts); | 242 | ts->stopped = true; |
256 | if (cancel_delayed_work_sync(&ts->work)) { | 243 | mb(); |
257 | /* | 244 | wake_up(&ts->wait); |
258 | * Work was pending, therefore we need to enable | 245 | |
259 | * IRQ here to balance the disable_irq() done in the | 246 | disable_irq(ts->irq); |
260 | * interrupt handler. | 247 | } |
261 | */ | 248 | |
262 | enable_irq(ts->irq); | 249 | static int tsc2007_open(struct input_dev *input_dev) |
250 | { | ||
251 | struct tsc2007 *ts = input_get_drvdata(input_dev); | ||
252 | int err; | ||
253 | |||
254 | ts->stopped = false; | ||
255 | mb(); | ||
256 | |||
257 | enable_irq(ts->irq); | ||
258 | |||
259 | /* Prepare for touch readings - power down ADC and enable PENIRQ */ | ||
260 | err = tsc2007_xfer(ts, PWRDOWN); | ||
261 | if (err < 0) { | ||
262 | tsc2007_stop(ts); | ||
263 | return err; | ||
263 | } | 264 | } |
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static void tsc2007_close(struct input_dev *input_dev) | ||
270 | { | ||
271 | struct tsc2007 *ts = input_get_drvdata(input_dev); | ||
272 | |||
273 | tsc2007_stop(ts); | ||
264 | } | 274 | } |
265 | 275 | ||
266 | static int __devinit tsc2007_probe(struct i2c_client *client, | 276 | static int __devinit tsc2007_probe(struct i2c_client *client, |
@@ -290,7 +300,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client, | |||
290 | ts->client = client; | 300 | ts->client = client; |
291 | ts->irq = client->irq; | 301 | ts->irq = client->irq; |
292 | ts->input = input_dev; | 302 | ts->input = input_dev; |
293 | INIT_DELAYED_WORK(&ts->work, tsc2007_work); | 303 | init_waitqueue_head(&ts->wait); |
294 | 304 | ||
295 | ts->model = pdata->model; | 305 | ts->model = pdata->model; |
296 | ts->x_plate_ohms = pdata->x_plate_ohms; | 306 | ts->x_plate_ohms = pdata->x_plate_ohms; |
@@ -300,6 +310,12 @@ static int __devinit tsc2007_probe(struct i2c_client *client, | |||
300 | ts->get_pendown_state = pdata->get_pendown_state; | 310 | ts->get_pendown_state = pdata->get_pendown_state; |
301 | ts->clear_penirq = pdata->clear_penirq; | 311 | ts->clear_penirq = pdata->clear_penirq; |
302 | 312 | ||
313 | if (pdata->x_plate_ohms == 0) { | ||
314 | dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); | ||
315 | err = -EINVAL; | ||
316 | goto err_free_mem; | ||
317 | } | ||
318 | |||
303 | snprintf(ts->phys, sizeof(ts->phys), | 319 | snprintf(ts->phys, sizeof(ts->phys), |
304 | "%s/input0", dev_name(&client->dev)); | 320 | "%s/input0", dev_name(&client->dev)); |
305 | 321 | ||
@@ -307,6 +323,11 @@ static int __devinit tsc2007_probe(struct i2c_client *client, | |||
307 | input_dev->phys = ts->phys; | 323 | input_dev->phys = ts->phys; |
308 | input_dev->id.bustype = BUS_I2C; | 324 | input_dev->id.bustype = BUS_I2C; |
309 | 325 | ||
326 | input_dev->open = tsc2007_open; | ||
327 | input_dev->close = tsc2007_close; | ||
328 | |||
329 | input_set_drvdata(input_dev, ts); | ||
330 | |||
310 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 331 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
311 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 332 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
312 | 333 | ||
@@ -318,17 +339,14 @@ static int __devinit tsc2007_probe(struct i2c_client *client, | |||
318 | if (pdata->init_platform_hw) | 339 | if (pdata->init_platform_hw) |
319 | pdata->init_platform_hw(); | 340 | pdata->init_platform_hw(); |
320 | 341 | ||
321 | err = request_irq(ts->irq, tsc2007_irq, 0, | 342 | err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, |
322 | client->dev.driver->name, ts); | 343 | IRQF_ONESHOT, client->dev.driver->name, ts); |
323 | if (err < 0) { | 344 | if (err < 0) { |
324 | dev_err(&client->dev, "irq %d busy?\n", ts->irq); | 345 | dev_err(&client->dev, "irq %d busy?\n", ts->irq); |
325 | goto err_free_mem; | 346 | goto err_free_mem; |
326 | } | 347 | } |
327 | 348 | ||
328 | /* Prepare for touch readings - power down ADC and enable PENIRQ */ | 349 | tsc2007_stop(ts); |
329 | err = tsc2007_xfer(ts, PWRDOWN); | ||
330 | if (err < 0) | ||
331 | goto err_free_irq; | ||
332 | 350 | ||
333 | err = input_register_device(input_dev); | 351 | err = input_register_device(input_dev); |
334 | if (err) | 352 | if (err) |
@@ -339,7 +357,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client, | |||
339 | return 0; | 357 | return 0; |
340 | 358 | ||
341 | err_free_irq: | 359 | err_free_irq: |
342 | tsc2007_free_irq(ts); | 360 | free_irq(ts->irq, ts); |
343 | if (pdata->exit_platform_hw) | 361 | if (pdata->exit_platform_hw) |
344 | pdata->exit_platform_hw(); | 362 | pdata->exit_platform_hw(); |
345 | err_free_mem: | 363 | err_free_mem: |
@@ -353,7 +371,7 @@ static int __devexit tsc2007_remove(struct i2c_client *client) | |||
353 | struct tsc2007 *ts = i2c_get_clientdata(client); | 371 | struct tsc2007 *ts = i2c_get_clientdata(client); |
354 | struct tsc2007_platform_data *pdata = client->dev.platform_data; | 372 | struct tsc2007_platform_data *pdata = client->dev.platform_data; |
355 | 373 | ||
356 | tsc2007_free_irq(ts); | 374 | free_irq(ts->irq, ts); |
357 | 375 | ||
358 | if (pdata->exit_platform_hw) | 376 | if (pdata->exit_platform_hw) |
359 | pdata->exit_platform_hw(); | 377 | pdata->exit_platform_hw(); |
diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c new file mode 100644 index 000000000000..29d5ed4dd31c --- /dev/null +++ b/drivers/input/touchscreen/tsc40.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * TSC-40 serial touchscreen driver. It should be compatible with | ||
3 | * TSC-10 and 25. | ||
4 | * | ||
5 | * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de> | ||
6 | * License: GPLv2 as published by the FSF. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/input.h> | ||
13 | #include <linux/serio.h> | ||
14 | #include <linux/init.h> | ||
15 | |||
16 | #define PACKET_LENGTH 5 | ||
17 | struct tsc_ser { | ||
18 | struct input_dev *dev; | ||
19 | struct serio *serio; | ||
20 | u32 idx; | ||
21 | unsigned char data[PACKET_LENGTH]; | ||
22 | char phys[32]; | ||
23 | }; | ||
24 | |||
25 | static void tsc_process_data(struct tsc_ser *ptsc) | ||
26 | { | ||
27 | struct input_dev *dev = ptsc->dev; | ||
28 | u8 *data = ptsc->data; | ||
29 | u32 x; | ||
30 | u32 y; | ||
31 | |||
32 | x = ((data[1] & 0x03) << 8) | data[2]; | ||
33 | y = ((data[3] & 0x03) << 8) | data[4]; | ||
34 | |||
35 | input_report_abs(dev, ABS_X, x); | ||
36 | input_report_abs(dev, ABS_Y, y); | ||
37 | input_report_key(dev, BTN_TOUCH, 1); | ||
38 | |||
39 | input_sync(dev); | ||
40 | } | ||
41 | |||
42 | static irqreturn_t tsc_interrupt(struct serio *serio, | ||
43 | unsigned char data, unsigned int flags) | ||
44 | { | ||
45 | struct tsc_ser *ptsc = serio_get_drvdata(serio); | ||
46 | struct input_dev *dev = ptsc->dev; | ||
47 | |||
48 | ptsc->data[ptsc->idx] = data; | ||
49 | switch (ptsc->idx++) { | ||
50 | case 0: | ||
51 | if (unlikely((data & 0x3e) != 0x10)) { | ||
52 | dev_dbg(&serio->dev, | ||
53 | "unsynchronized packet start (0x%02x)\n", data); | ||
54 | ptsc->idx = 0; | ||
55 | } else if (!(data & 0x01)) { | ||
56 | input_report_key(dev, BTN_TOUCH, 0); | ||
57 | input_sync(dev); | ||
58 | ptsc->idx = 0; | ||
59 | } | ||
60 | break; | ||
61 | |||
62 | case 1: | ||
63 | case 3: | ||
64 | if (unlikely(data & 0xfc)) { | ||
65 | dev_dbg(&serio->dev, | ||
66 | "unsynchronized data 0x%02x at offset %d\n", | ||
67 | data, ptsc->idx - 1); | ||
68 | ptsc->idx = 0; | ||
69 | } | ||
70 | break; | ||
71 | |||
72 | case 4: | ||
73 | tsc_process_data(ptsc); | ||
74 | ptsc->idx = 0; | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | return IRQ_HANDLED; | ||
79 | } | ||
80 | |||
81 | static int tsc_connect(struct serio *serio, struct serio_driver *drv) | ||
82 | { | ||
83 | struct tsc_ser *ptsc; | ||
84 | struct input_dev *input_dev; | ||
85 | int error; | ||
86 | |||
87 | ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL); | ||
88 | input_dev = input_allocate_device(); | ||
89 | if (!ptsc || !input_dev) { | ||
90 | error = -ENOMEM; | ||
91 | goto fail1; | ||
92 | } | ||
93 | |||
94 | ptsc->serio = serio; | ||
95 | ptsc->dev = input_dev; | ||
96 | snprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys); | ||
97 | |||
98 | input_dev->name = "TSC-10/25/40 Serial TouchScreen"; | ||
99 | input_dev->phys = ptsc->phys; | ||
100 | input_dev->id.bustype = BUS_RS232; | ||
101 | input_dev->id.vendor = SERIO_TSC40; | ||
102 | input_dev->id.product = 40; | ||
103 | input_dev->id.version = 0x0001; | ||
104 | input_dev->dev.parent = &serio->dev; | ||
105 | |||
106 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
107 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
108 | input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0); | ||
109 | input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); | ||
110 | input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0); | ||
111 | |||
112 | serio_set_drvdata(serio, ptsc); | ||
113 | |||
114 | error = serio_open(serio, drv); | ||
115 | if (error) | ||
116 | goto fail2; | ||
117 | |||
118 | error = input_register_device(ptsc->dev); | ||
119 | if (error) | ||
120 | goto fail3; | ||
121 | |||
122 | return 0; | ||
123 | |||
124 | fail3: | ||
125 | serio_close(serio); | ||
126 | fail2: | ||
127 | serio_set_drvdata(serio, NULL); | ||
128 | fail1: | ||
129 | input_free_device(input_dev); | ||
130 | kfree(ptsc); | ||
131 | return error; | ||
132 | } | ||
133 | |||
134 | static void tsc_disconnect(struct serio *serio) | ||
135 | { | ||
136 | struct tsc_ser *ptsc = serio_get_drvdata(serio); | ||
137 | |||
138 | serio_close(serio); | ||
139 | |||
140 | input_unregister_device(ptsc->dev); | ||
141 | kfree(ptsc); | ||
142 | |||
143 | serio_set_drvdata(serio, NULL); | ||
144 | } | ||
145 | |||
146 | static struct serio_device_id tsc_serio_ids[] = { | ||
147 | { | ||
148 | .type = SERIO_RS232, | ||
149 | .proto = SERIO_TSC40, | ||
150 | .id = SERIO_ANY, | ||
151 | .extra = SERIO_ANY, | ||
152 | }, | ||
153 | { 0 } | ||
154 | }; | ||
155 | MODULE_DEVICE_TABLE(serio, tsc_serio_ids); | ||
156 | |||
157 | #define DRIVER_DESC "TSC-10/25/40 serial touchscreen driver" | ||
158 | |||
159 | static struct serio_driver tsc_drv = { | ||
160 | .driver = { | ||
161 | .name = "tsc40", | ||
162 | }, | ||
163 | .description = DRIVER_DESC, | ||
164 | .id_table = tsc_serio_ids, | ||
165 | .interrupt = tsc_interrupt, | ||
166 | .connect = tsc_connect, | ||
167 | .disconnect = tsc_disconnect, | ||
168 | }; | ||
169 | |||
170 | static int __init tsc_ser_init(void) | ||
171 | { | ||
172 | return serio_register_driver(&tsc_drv); | ||
173 | } | ||
174 | module_init(tsc_ser_init); | ||
175 | |||
176 | static void __exit tsc_exit(void) | ||
177 | { | ||
178 | serio_unregister_driver(&tsc_drv); | ||
179 | } | ||
180 | module_exit(tsc_exit); | ||
181 | |||
182 | MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); | ||
183 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
184 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 7a45d68c3516..217aa51135c5 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
@@ -279,7 +279,7 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
279 | 279 | ||
280 | w90p910_ts->irq_num = platform_get_irq(pdev, 0); | 280 | w90p910_ts->irq_num = platform_get_irq(pdev, 0); |
281 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, | 281 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, |
282 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { | 282 | 0, "w90p910ts", w90p910_ts)) { |
283 | err = -EBUSY; | 283 | err = -EBUSY; |
284 | goto fail4; | 284 | goto fail4; |
285 | } | 285 | } |
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 9941d39df43d..1569a3934ab2 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
@@ -367,6 +367,20 @@ static int w8001_command(struct w8001 *w8001, unsigned char command, | |||
367 | return rc; | 367 | return rc; |
368 | } | 368 | } |
369 | 369 | ||
370 | static int w8001_open(struct input_dev *dev) | ||
371 | { | ||
372 | struct w8001 *w8001 = input_get_drvdata(dev); | ||
373 | |||
374 | return w8001_command(w8001, W8001_CMD_START, false); | ||
375 | } | ||
376 | |||
377 | static void w8001_close(struct input_dev *dev) | ||
378 | { | ||
379 | struct w8001 *w8001 = input_get_drvdata(dev); | ||
380 | |||
381 | w8001_command(w8001, W8001_CMD_STOP, false); | ||
382 | } | ||
383 | |||
370 | static int w8001_setup(struct w8001 *w8001) | 384 | static int w8001_setup(struct w8001 *w8001) |
371 | { | 385 | { |
372 | struct input_dev *dev = w8001->dev; | 386 | struct input_dev *dev = w8001->dev; |
@@ -476,7 +490,7 @@ static int w8001_setup(struct w8001 *w8001) | |||
476 | 490 | ||
477 | strlcat(w8001->name, " Touchscreen", sizeof(w8001->name)); | 491 | strlcat(w8001->name, " Touchscreen", sizeof(w8001->name)); |
478 | 492 | ||
479 | return w8001_command(w8001, W8001_CMD_START, false); | 493 | return 0; |
480 | } | 494 | } |
481 | 495 | ||
482 | /* | 496 | /* |
@@ -487,12 +501,12 @@ static void w8001_disconnect(struct serio *serio) | |||
487 | { | 501 | { |
488 | struct w8001 *w8001 = serio_get_drvdata(serio); | 502 | struct w8001 *w8001 = serio_get_drvdata(serio); |
489 | 503 | ||
490 | input_get_device(w8001->dev); | ||
491 | input_unregister_device(w8001->dev); | ||
492 | serio_close(serio); | 504 | serio_close(serio); |
493 | serio_set_drvdata(serio, NULL); | 505 | |
494 | input_put_device(w8001->dev); | 506 | input_unregister_device(w8001->dev); |
495 | kfree(w8001); | 507 | kfree(w8001); |
508 | |||
509 | serio_set_drvdata(serio, NULL); | ||
496 | } | 510 | } |
497 | 511 | ||
498 | /* | 512 | /* |
@@ -536,6 +550,11 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
536 | input_dev->id.version = 0x0100; | 550 | input_dev->id.version = 0x0100; |
537 | input_dev->dev.parent = &serio->dev; | 551 | input_dev->dev.parent = &serio->dev; |
538 | 552 | ||
553 | input_dev->open = w8001_open; | ||
554 | input_dev->close = w8001_close; | ||
555 | |||
556 | input_set_drvdata(input_dev, w8001); | ||
557 | |||
539 | err = input_register_device(w8001->dev); | 558 | err = input_register_device(w8001->dev); |
540 | if (err) | 559 | if (err) |
541 | goto fail3; | 560 | goto fail3; |