diff options
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/Kconfig | 10 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/keyboard/cap1106.c | 335 | ||||
-rw-r--r-- | drivers/input/keyboard/imx_keypad.c | 6 | ||||
-rw-r--r-- | drivers/input/keyboard/max7359_keypad.c | 45 |
5 files changed, 364 insertions, 33 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index f7e79b481349..a3958c63d7d5 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -665,4 +665,14 @@ config KEYBOARD_CROS_EC | |||
665 | To compile this driver as a module, choose M here: the | 665 | To compile this driver as a module, choose M here: the |
666 | module will be called cros_ec_keyb. | 666 | module will be called cros_ec_keyb. |
667 | 667 | ||
668 | config KEYBOARD_CAP1106 | ||
669 | tristate "Microchip CAP1106 touch sensor" | ||
670 | depends on OF && I2C | ||
671 | select REGMAP_I2C | ||
672 | help | ||
673 | Say Y here to enable the CAP1106 touch sensor driver. | ||
674 | |||
675 | To compile this driver as a module, choose M here: the | ||
676 | module will be called cap1106. | ||
677 | |||
668 | endif | 678 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 7504ae19049d..0a3345634d79 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | |||
11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
14 | obj-$(CONFIG_KEYBOARD_CAP1106) += cap1106.o | ||
14 | obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o | 15 | obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o |
15 | obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o | 16 | obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o |
16 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o | 17 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o |
diff --git a/drivers/input/keyboard/cap1106.c b/drivers/input/keyboard/cap1106.c new file mode 100644 index 000000000000..f7d7a0d4ab4e --- /dev/null +++ b/drivers/input/keyboard/cap1106.c | |||
@@ -0,0 +1,335 @@ | |||
1 | /* | ||
2 | * Input driver for Microchip CAP1106, 6 channel capacitive touch sensor | ||
3 | * | ||
4 | * http://www.microchip.com/wwwproducts/Devices.aspx?product=CAP1106 | ||
5 | * | ||
6 | * (c) 2014 Daniel Mack <linux@zonque.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/of_irq.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/gpio/consumer.h> | ||
21 | |||
22 | #define CAP1106_REG_MAIN_CONTROL 0x00 | ||
23 | #define CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT (6) | ||
24 | #define CAP1106_REG_MAIN_CONTROL_GAIN_MASK (0xc0) | ||
25 | #define CAP1106_REG_MAIN_CONTROL_DLSEEP BIT(4) | ||
26 | #define CAP1106_REG_GENERAL_STATUS 0x02 | ||
27 | #define CAP1106_REG_SENSOR_INPUT 0x03 | ||
28 | #define CAP1106_REG_NOISE_FLAG_STATUS 0x0a | ||
29 | #define CAP1106_REG_SENOR_DELTA(X) (0x10 + (X)) | ||
30 | #define CAP1106_REG_SENSITIVITY_CONTROL 0x1f | ||
31 | #define CAP1106_REG_CONFIG 0x20 | ||
32 | #define CAP1106_REG_SENSOR_ENABLE 0x21 | ||
33 | #define CAP1106_REG_SENSOR_CONFIG 0x22 | ||
34 | #define CAP1106_REG_SENSOR_CONFIG2 0x23 | ||
35 | #define CAP1106_REG_SAMPLING_CONFIG 0x24 | ||
36 | #define CAP1106_REG_CALIBRATION 0x25 | ||
37 | #define CAP1106_REG_INT_ENABLE 0x26 | ||
38 | #define CAP1106_REG_REPEAT_RATE 0x28 | ||
39 | #define CAP1106_REG_MT_CONFIG 0x2a | ||
40 | #define CAP1106_REG_MT_PATTERN_CONFIG 0x2b | ||
41 | #define CAP1106_REG_MT_PATTERN 0x2d | ||
42 | #define CAP1106_REG_RECALIB_CONFIG 0x2f | ||
43 | #define CAP1106_REG_SENSOR_THRESH(X) (0x30 + (X)) | ||
44 | #define CAP1106_REG_SENSOR_NOISE_THRESH 0x38 | ||
45 | #define CAP1106_REG_STANDBY_CHANNEL 0x40 | ||
46 | #define CAP1106_REG_STANDBY_CONFIG 0x41 | ||
47 | #define CAP1106_REG_STANDBY_SENSITIVITY 0x42 | ||
48 | #define CAP1106_REG_STANDBY_THRESH 0x43 | ||
49 | #define CAP1106_REG_CONFIG2 0x44 | ||
50 | #define CAP1106_REG_SENSOR_BASE_CNT(X) (0x50 + (X)) | ||
51 | #define CAP1106_REG_SENSOR_CALIB (0xb1 + (X)) | ||
52 | #define CAP1106_REG_SENSOR_CALIB_LSB1 0xb9 | ||
53 | #define CAP1106_REG_SENSOR_CALIB_LSB2 0xba | ||
54 | #define CAP1106_REG_PRODUCT_ID 0xfd | ||
55 | #define CAP1106_REG_MANUFACTURER_ID 0xfe | ||
56 | #define CAP1106_REG_REVISION 0xff | ||
57 | |||
58 | #define CAP1106_NUM_CHN 6 | ||
59 | #define CAP1106_PRODUCT_ID 0x55 | ||
60 | #define CAP1106_MANUFACTURER_ID 0x5d | ||
61 | |||
62 | struct cap1106_priv { | ||
63 | struct regmap *regmap; | ||
64 | struct input_dev *idev; | ||
65 | |||
66 | /* config */ | ||
67 | unsigned int keycodes[CAP1106_NUM_CHN]; | ||
68 | }; | ||
69 | |||
70 | static const struct reg_default cap1106_reg_defaults[] = { | ||
71 | { CAP1106_REG_MAIN_CONTROL, 0x00 }, | ||
72 | { CAP1106_REG_GENERAL_STATUS, 0x00 }, | ||
73 | { CAP1106_REG_SENSOR_INPUT, 0x00 }, | ||
74 | { CAP1106_REG_NOISE_FLAG_STATUS, 0x00 }, | ||
75 | { CAP1106_REG_SENSITIVITY_CONTROL, 0x2f }, | ||
76 | { CAP1106_REG_CONFIG, 0x20 }, | ||
77 | { CAP1106_REG_SENSOR_ENABLE, 0x3f }, | ||
78 | { CAP1106_REG_SENSOR_CONFIG, 0xa4 }, | ||
79 | { CAP1106_REG_SENSOR_CONFIG2, 0x07 }, | ||
80 | { CAP1106_REG_SAMPLING_CONFIG, 0x39 }, | ||
81 | { CAP1106_REG_CALIBRATION, 0x00 }, | ||
82 | { CAP1106_REG_INT_ENABLE, 0x3f }, | ||
83 | { CAP1106_REG_REPEAT_RATE, 0x3f }, | ||
84 | { CAP1106_REG_MT_CONFIG, 0x80 }, | ||
85 | { CAP1106_REG_MT_PATTERN_CONFIG, 0x00 }, | ||
86 | { CAP1106_REG_MT_PATTERN, 0x3f }, | ||
87 | { CAP1106_REG_RECALIB_CONFIG, 0x8a }, | ||
88 | { CAP1106_REG_SENSOR_THRESH(0), 0x40 }, | ||
89 | { CAP1106_REG_SENSOR_THRESH(1), 0x40 }, | ||
90 | { CAP1106_REG_SENSOR_THRESH(2), 0x40 }, | ||
91 | { CAP1106_REG_SENSOR_THRESH(3), 0x40 }, | ||
92 | { CAP1106_REG_SENSOR_THRESH(4), 0x40 }, | ||
93 | { CAP1106_REG_SENSOR_THRESH(5), 0x40 }, | ||
94 | { CAP1106_REG_SENSOR_NOISE_THRESH, 0x01 }, | ||
95 | { CAP1106_REG_STANDBY_CHANNEL, 0x00 }, | ||
96 | { CAP1106_REG_STANDBY_CONFIG, 0x39 }, | ||
97 | { CAP1106_REG_STANDBY_SENSITIVITY, 0x02 }, | ||
98 | { CAP1106_REG_STANDBY_THRESH, 0x40 }, | ||
99 | { CAP1106_REG_CONFIG2, 0x40 }, | ||
100 | { CAP1106_REG_SENSOR_CALIB_LSB1, 0x00 }, | ||
101 | { CAP1106_REG_SENSOR_CALIB_LSB2, 0x00 }, | ||
102 | }; | ||
103 | |||
104 | static bool cap1106_volatile_reg(struct device *dev, unsigned int reg) | ||
105 | { | ||
106 | switch (reg) { | ||
107 | case CAP1106_REG_MAIN_CONTROL: | ||
108 | case CAP1106_REG_SENSOR_INPUT: | ||
109 | case CAP1106_REG_SENOR_DELTA(0): | ||
110 | case CAP1106_REG_SENOR_DELTA(1): | ||
111 | case CAP1106_REG_SENOR_DELTA(2): | ||
112 | case CAP1106_REG_SENOR_DELTA(3): | ||
113 | case CAP1106_REG_SENOR_DELTA(4): | ||
114 | case CAP1106_REG_SENOR_DELTA(5): | ||
115 | case CAP1106_REG_PRODUCT_ID: | ||
116 | case CAP1106_REG_MANUFACTURER_ID: | ||
117 | case CAP1106_REG_REVISION: | ||
118 | return true; | ||
119 | } | ||
120 | |||
121 | return false; | ||
122 | } | ||
123 | |||
124 | static const struct regmap_config cap1106_regmap_config = { | ||
125 | .reg_bits = 8, | ||
126 | .val_bits = 8, | ||
127 | |||
128 | .max_register = CAP1106_REG_REVISION, | ||
129 | .reg_defaults = cap1106_reg_defaults, | ||
130 | |||
131 | .num_reg_defaults = ARRAY_SIZE(cap1106_reg_defaults), | ||
132 | .cache_type = REGCACHE_RBTREE, | ||
133 | .volatile_reg = cap1106_volatile_reg, | ||
134 | }; | ||
135 | |||
136 | static irqreturn_t cap1106_thread_func(int irq_num, void *data) | ||
137 | { | ||
138 | struct cap1106_priv *priv = data; | ||
139 | unsigned int status; | ||
140 | int ret, i; | ||
141 | |||
142 | /* | ||
143 | * Deassert interrupt. This needs to be done before reading the status | ||
144 | * registers, which will not carry valid values otherwise. | ||
145 | */ | ||
146 | ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, 1, 0); | ||
147 | if (ret < 0) | ||
148 | goto out; | ||
149 | |||
150 | ret = regmap_read(priv->regmap, CAP1106_REG_SENSOR_INPUT, &status); | ||
151 | if (ret < 0) | ||
152 | goto out; | ||
153 | |||
154 | for (i = 0; i < CAP1106_NUM_CHN; i++) | ||
155 | input_report_key(priv->idev, priv->keycodes[i], | ||
156 | status & (1 << i)); | ||
157 | |||
158 | input_sync(priv->idev); | ||
159 | |||
160 | out: | ||
161 | return IRQ_HANDLED; | ||
162 | } | ||
163 | |||
164 | static int cap1106_set_sleep(struct cap1106_priv *priv, bool sleep) | ||
165 | { | ||
166 | return regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, | ||
167 | CAP1106_REG_MAIN_CONTROL_DLSEEP, | ||
168 | sleep ? CAP1106_REG_MAIN_CONTROL_DLSEEP : 0); | ||
169 | } | ||
170 | |||
171 | static int cap1106_input_open(struct input_dev *idev) | ||
172 | { | ||
173 | struct cap1106_priv *priv = input_get_drvdata(idev); | ||
174 | |||
175 | return cap1106_set_sleep(priv, false); | ||
176 | } | ||
177 | |||
178 | static void cap1106_input_close(struct input_dev *idev) | ||
179 | { | ||
180 | struct cap1106_priv *priv = input_get_drvdata(idev); | ||
181 | |||
182 | cap1106_set_sleep(priv, true); | ||
183 | } | ||
184 | |||
185 | static int cap1106_i2c_probe(struct i2c_client *i2c_client, | ||
186 | const struct i2c_device_id *id) | ||
187 | { | ||
188 | struct device *dev = &i2c_client->dev; | ||
189 | struct cap1106_priv *priv; | ||
190 | struct device_node *node; | ||
191 | int i, error, irq, gain = 0; | ||
192 | unsigned int val, rev; | ||
193 | u32 gain32, keycodes[CAP1106_NUM_CHN]; | ||
194 | |||
195 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
196 | if (!priv) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | priv->regmap = devm_regmap_init_i2c(i2c_client, &cap1106_regmap_config); | ||
200 | if (IS_ERR(priv->regmap)) | ||
201 | return PTR_ERR(priv->regmap); | ||
202 | |||
203 | error = regmap_read(priv->regmap, CAP1106_REG_PRODUCT_ID, &val); | ||
204 | if (error) | ||
205 | return error; | ||
206 | |||
207 | if (val != CAP1106_PRODUCT_ID) { | ||
208 | dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n", | ||
209 | val, CAP1106_PRODUCT_ID); | ||
210 | return -ENODEV; | ||
211 | } | ||
212 | |||
213 | error = regmap_read(priv->regmap, CAP1106_REG_MANUFACTURER_ID, &val); | ||
214 | if (error) | ||
215 | return error; | ||
216 | |||
217 | if (val != CAP1106_MANUFACTURER_ID) { | ||
218 | dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n", | ||
219 | val, CAP1106_MANUFACTURER_ID); | ||
220 | return -ENODEV; | ||
221 | } | ||
222 | |||
223 | error = regmap_read(priv->regmap, CAP1106_REG_REVISION, &rev); | ||
224 | if (error < 0) | ||
225 | return error; | ||
226 | |||
227 | dev_info(dev, "CAP1106 detected, revision 0x%02x\n", rev); | ||
228 | i2c_set_clientdata(i2c_client, priv); | ||
229 | node = dev->of_node; | ||
230 | |||
231 | if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) { | ||
232 | if (is_power_of_2(gain32) && gain32 <= 8) | ||
233 | gain = ilog2(gain32); | ||
234 | else | ||
235 | dev_err(dev, "Invalid sensor-gain value %d\n", gain32); | ||
236 | } | ||
237 | |||
238 | BUILD_BUG_ON(ARRAY_SIZE(keycodes) != ARRAY_SIZE(priv->keycodes)); | ||
239 | |||
240 | /* Provide some useful defaults */ | ||
241 | for (i = 0; i < ARRAY_SIZE(keycodes); i++) | ||
242 | keycodes[i] = KEY_A + i; | ||
243 | |||
244 | of_property_read_u32_array(node, "linux,keycodes", | ||
245 | keycodes, ARRAY_SIZE(keycodes)); | ||
246 | |||
247 | for (i = 0; i < ARRAY_SIZE(keycodes); i++) | ||
248 | priv->keycodes[i] = keycodes[i]; | ||
249 | |||
250 | error = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, | ||
251 | CAP1106_REG_MAIN_CONTROL_GAIN_MASK, | ||
252 | gain << CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT); | ||
253 | if (error) | ||
254 | return error; | ||
255 | |||
256 | /* Disable autorepeat. The Linux input system has its own handling. */ | ||
257 | error = regmap_write(priv->regmap, CAP1106_REG_REPEAT_RATE, 0); | ||
258 | if (error) | ||
259 | return error; | ||
260 | |||
261 | priv->idev = devm_input_allocate_device(dev); | ||
262 | if (!priv->idev) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | priv->idev->name = "CAP1106 capacitive touch sensor"; | ||
266 | priv->idev->id.bustype = BUS_I2C; | ||
267 | priv->idev->evbit[0] = BIT_MASK(EV_KEY); | ||
268 | |||
269 | if (of_property_read_bool(node, "autorepeat")) | ||
270 | __set_bit(EV_REP, priv->idev->evbit); | ||
271 | |||
272 | for (i = 0; i < CAP1106_NUM_CHN; i++) | ||
273 | __set_bit(priv->keycodes[i], priv->idev->keybit); | ||
274 | |||
275 | priv->idev->id.vendor = CAP1106_MANUFACTURER_ID; | ||
276 | priv->idev->id.product = CAP1106_PRODUCT_ID; | ||
277 | priv->idev->id.version = rev; | ||
278 | |||
279 | priv->idev->open = cap1106_input_open; | ||
280 | priv->idev->close = cap1106_input_close; | ||
281 | |||
282 | input_set_drvdata(priv->idev, priv); | ||
283 | |||
284 | /* | ||
285 | * Put the device in deep sleep mode for now. | ||
286 | * ->open() will bring it back once the it is actually needed. | ||
287 | */ | ||
288 | cap1106_set_sleep(priv, true); | ||
289 | |||
290 | error = input_register_device(priv->idev); | ||
291 | if (error) | ||
292 | return error; | ||
293 | |||
294 | irq = irq_of_parse_and_map(node, 0); | ||
295 | if (!irq) { | ||
296 | dev_err(dev, "Unable to parse or map IRQ\n"); | ||
297 | return -ENXIO; | ||
298 | } | ||
299 | |||
300 | error = devm_request_threaded_irq(dev, irq, NULL, cap1106_thread_func, | ||
301 | IRQF_ONESHOT, dev_name(dev), priv); | ||
302 | if (error) | ||
303 | return error; | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static const struct of_device_id cap1106_dt_ids[] = { | ||
309 | { .compatible = "microchip,cap1106", }, | ||
310 | {} | ||
311 | }; | ||
312 | MODULE_DEVICE_TABLE(of, cap1106_dt_ids); | ||
313 | |||
314 | static const struct i2c_device_id cap1106_i2c_ids[] = { | ||
315 | { "cap1106", 0 }, | ||
316 | {} | ||
317 | }; | ||
318 | MODULE_DEVICE_TABLE(i2c, cap1106_i2c_ids); | ||
319 | |||
320 | static struct i2c_driver cap1106_i2c_driver = { | ||
321 | .driver = { | ||
322 | .name = "cap1106", | ||
323 | .owner = THIS_MODULE, | ||
324 | .of_match_table = cap1106_dt_ids, | ||
325 | }, | ||
326 | .id_table = cap1106_i2c_ids, | ||
327 | .probe = cap1106_i2c_probe, | ||
328 | }; | ||
329 | |||
330 | module_i2c_driver(cap1106_i2c_driver); | ||
331 | |||
332 | MODULE_ALIAS("platform:cap1106"); | ||
333 | MODULE_DESCRIPTION("Microchip CAP1106 driver"); | ||
334 | MODULE_AUTHOR("Daniel Mack <linux@zonque.org>"); | ||
335 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 8280cb16260b..20a99c368d16 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c | |||
@@ -531,8 +531,7 @@ static int imx_keypad_probe(struct platform_device *pdev) | |||
531 | return 0; | 531 | return 0; |
532 | } | 532 | } |
533 | 533 | ||
534 | #ifdef CONFIG_PM_SLEEP | 534 | static int __maybe_unused imx_kbd_suspend(struct device *dev) |
535 | static int imx_kbd_suspend(struct device *dev) | ||
536 | { | 535 | { |
537 | struct platform_device *pdev = to_platform_device(dev); | 536 | struct platform_device *pdev = to_platform_device(dev); |
538 | struct imx_keypad *kbd = platform_get_drvdata(pdev); | 537 | struct imx_keypad *kbd = platform_get_drvdata(pdev); |
@@ -552,7 +551,7 @@ static int imx_kbd_suspend(struct device *dev) | |||
552 | return 0; | 551 | return 0; |
553 | } | 552 | } |
554 | 553 | ||
555 | static int imx_kbd_resume(struct device *dev) | 554 | static int __maybe_unused imx_kbd_resume(struct device *dev) |
556 | { | 555 | { |
557 | struct platform_device *pdev = to_platform_device(dev); | 556 | struct platform_device *pdev = to_platform_device(dev); |
558 | struct imx_keypad *kbd = platform_get_drvdata(pdev); | 557 | struct imx_keypad *kbd = platform_get_drvdata(pdev); |
@@ -575,7 +574,6 @@ err_clk: | |||
575 | 574 | ||
576 | return ret; | 575 | return ret; |
577 | } | 576 | } |
578 | #endif | ||
579 | 577 | ||
580 | static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume); | 578 | static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume); |
581 | 579 | ||
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 430b54539720..faa6da53eba8 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c | |||
@@ -203,12 +203,17 @@ static int max7359_probe(struct i2c_client *client, | |||
203 | 203 | ||
204 | dev_dbg(&client->dev, "keys FIFO is 0x%02x\n", ret); | 204 | dev_dbg(&client->dev, "keys FIFO is 0x%02x\n", ret); |
205 | 205 | ||
206 | keypad = kzalloc(sizeof(struct max7359_keypad), GFP_KERNEL); | 206 | keypad = devm_kzalloc(&client->dev, sizeof(struct max7359_keypad), |
207 | input_dev = input_allocate_device(); | 207 | GFP_KERNEL); |
208 | if (!keypad || !input_dev) { | 208 | if (!keypad) { |
209 | dev_err(&client->dev, "failed to allocate memory\n"); | 209 | dev_err(&client->dev, "failed to allocate memory\n"); |
210 | error = -ENOMEM; | 210 | return -ENOMEM; |
211 | goto failed_free_mem; | 211 | } |
212 | |||
213 | input_dev = devm_input_allocate_device(&client->dev); | ||
214 | if (!input_dev) { | ||
215 | dev_err(&client->dev, "failed to allocate input device\n"); | ||
216 | return -ENOMEM; | ||
212 | } | 217 | } |
213 | 218 | ||
214 | keypad->client = client; | 219 | keypad->client = client; |
@@ -230,19 +235,20 @@ static int max7359_probe(struct i2c_client *client, | |||
230 | 235 | ||
231 | max7359_build_keycode(keypad, keymap_data); | 236 | max7359_build_keycode(keypad, keymap_data); |
232 | 237 | ||
233 | error = request_threaded_irq(client->irq, NULL, max7359_interrupt, | 238 | error = devm_request_threaded_irq(&client->dev, client->irq, NULL, |
234 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 239 | max7359_interrupt, |
235 | client->name, keypad); | 240 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, |
241 | client->name, keypad); | ||
236 | if (error) { | 242 | if (error) { |
237 | dev_err(&client->dev, "failed to register interrupt\n"); | 243 | dev_err(&client->dev, "failed to register interrupt\n"); |
238 | goto failed_free_mem; | 244 | return error; |
239 | } | 245 | } |
240 | 246 | ||
241 | /* Register the input device */ | 247 | /* Register the input device */ |
242 | error = input_register_device(input_dev); | 248 | error = input_register_device(input_dev); |
243 | if (error) { | 249 | if (error) { |
244 | dev_err(&client->dev, "failed to register input device\n"); | 250 | dev_err(&client->dev, "failed to register input device\n"); |
245 | goto failed_free_irq; | 251 | return error; |
246 | } | 252 | } |
247 | 253 | ||
248 | /* Initialize MAX7359 */ | 254 | /* Initialize MAX7359 */ |
@@ -252,24 +258,6 @@ static int max7359_probe(struct i2c_client *client, | |||
252 | device_init_wakeup(&client->dev, 1); | 258 | device_init_wakeup(&client->dev, 1); |
253 | 259 | ||
254 | return 0; | 260 | return 0; |
255 | |||
256 | failed_free_irq: | ||
257 | free_irq(client->irq, keypad); | ||
258 | failed_free_mem: | ||
259 | input_free_device(input_dev); | ||
260 | kfree(keypad); | ||
261 | return error; | ||
262 | } | ||
263 | |||
264 | static int max7359_remove(struct i2c_client *client) | ||
265 | { | ||
266 | struct max7359_keypad *keypad = i2c_get_clientdata(client); | ||
267 | |||
268 | free_irq(client->irq, keypad); | ||
269 | input_unregister_device(keypad->input_dev); | ||
270 | kfree(keypad); | ||
271 | |||
272 | return 0; | ||
273 | } | 261 | } |
274 | 262 | ||
275 | #ifdef CONFIG_PM_SLEEP | 263 | #ifdef CONFIG_PM_SLEEP |
@@ -313,7 +301,6 @@ static struct i2c_driver max7359_i2c_driver = { | |||
313 | .pm = &max7359_pm, | 301 | .pm = &max7359_pm, |
314 | }, | 302 | }, |
315 | .probe = max7359_probe, | 303 | .probe = max7359_probe, |
316 | .remove = max7359_remove, | ||
317 | .id_table = max7359_ids, | 304 | .id_table = max7359_ids, |
318 | }; | 305 | }; |
319 | 306 | ||