diff options
author | Douglas Anderson <dianders@chromium.org> | 2017-01-20 05:14:15 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2017-02-08 06:36:23 -0500 |
commit | cdd7950e7aa4a4d0d8ba71e3967aae6d25d09b03 (patch) | |
tree | 5dd015b296e9a1e0d0f68e7d136f751540fc627b | |
parent | b44c4d3f1ee77e7947c525d6a907c0057fa238d2 (diff) |
input: cros_ec_keyb: Add non-matrix buttons and switches
On some newer boards using mkbp we're hooking up non-matrix buttons and
switches to the EC but NOT to the main application processor.
Let's add kernel support to handle this. Rather than creating a whole
new input driver, we'll continue to use cros_ec_keyb and just report the
new keys.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r-- | drivers/input/keyboard/cros_ec_keyb.c | 447 |
1 files changed, 402 insertions, 45 deletions
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 25943e9bc8bf..ad74ebce0cdd 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/mfd/cros_ec.h> | 34 | #include <linux/mfd/cros_ec.h> |
35 | #include <linux/mfd/cros_ec_commands.h> | 35 | #include <linux/mfd/cros_ec_commands.h> |
36 | 36 | ||
37 | #include <asm/unaligned.h> | ||
38 | |||
37 | /* | 39 | /* |
38 | * @rows: Number of rows in the keypad | 40 | * @rows: Number of rows in the keypad |
39 | * @cols: Number of columns in the keypad | 41 | * @cols: Number of columns in the keypad |
@@ -43,8 +45,9 @@ | |||
43 | * @valid_keys: bitmap of existing keys for each matrix column | 45 | * @valid_keys: bitmap of existing keys for each matrix column |
44 | * @old_kb_state: bitmap of keys pressed last scan | 46 | * @old_kb_state: bitmap of keys pressed last scan |
45 | * @dev: Device pointer | 47 | * @dev: Device pointer |
46 | * @idev: Input device | ||
47 | * @ec: Top level ChromeOS device to use to talk to EC | 48 | * @ec: Top level ChromeOS device to use to talk to EC |
49 | * @idev: The input device for the matrix keys. | ||
50 | * @bs_idev: The input device for non-matrix buttons and switches (or NULL). | ||
48 | * @notifier: interrupt event notifier for transport devices | 51 | * @notifier: interrupt event notifier for transport devices |
49 | */ | 52 | */ |
50 | struct cros_ec_keyb { | 53 | struct cros_ec_keyb { |
@@ -57,12 +60,59 @@ struct cros_ec_keyb { | |||
57 | uint8_t *old_kb_state; | 60 | uint8_t *old_kb_state; |
58 | 61 | ||
59 | struct device *dev; | 62 | struct device *dev; |
60 | struct input_dev *idev; | ||
61 | struct cros_ec_device *ec; | 63 | struct cros_ec_device *ec; |
64 | |||
65 | struct input_dev *idev; | ||
66 | struct input_dev *bs_idev; | ||
62 | struct notifier_block notifier; | 67 | struct notifier_block notifier; |
63 | }; | 68 | }; |
64 | 69 | ||
65 | 70 | ||
71 | /** | ||
72 | * cros_ec_bs_map - Struct mapping Linux keycodes to EC button/switch bitmap | ||
73 | * #defines | ||
74 | * | ||
75 | * @ev_type: The type of the input event to generate (e.g., EV_KEY). | ||
76 | * @code: A linux keycode | ||
77 | * @bit: A #define like EC_MKBP_POWER_BUTTON or EC_MKBP_LID_OPEN | ||
78 | * @inverted: If the #define and EV_SW have opposite meanings, this is true. | ||
79 | * Only applicable to switches. | ||
80 | */ | ||
81 | struct cros_ec_bs_map { | ||
82 | unsigned int ev_type; | ||
83 | unsigned int code; | ||
84 | u8 bit; | ||
85 | bool inverted; | ||
86 | }; | ||
87 | |||
88 | /* cros_ec_keyb_bs - Map EC button/switch #defines into kernel ones */ | ||
89 | static const struct cros_ec_bs_map cros_ec_keyb_bs[] = { | ||
90 | /* Buttons */ | ||
91 | { | ||
92 | .ev_type = EV_KEY, | ||
93 | .code = KEY_POWER, | ||
94 | .bit = EC_MKBP_POWER_BUTTON, | ||
95 | }, | ||
96 | { | ||
97 | .ev_type = EV_KEY, | ||
98 | .code = KEY_VOLUMEUP, | ||
99 | .bit = EC_MKBP_VOL_UP, | ||
100 | }, | ||
101 | { | ||
102 | .ev_type = EV_KEY, | ||
103 | .code = KEY_VOLUMEDOWN, | ||
104 | .bit = EC_MKBP_VOL_DOWN, | ||
105 | }, | ||
106 | |||
107 | /* Switches */ | ||
108 | { | ||
109 | .ev_type = EV_SW, | ||
110 | .code = SW_LID, | ||
111 | .bit = EC_MKBP_LID_OPEN, | ||
112 | .inverted = true, | ||
113 | }, | ||
114 | }; | ||
115 | |||
66 | /* | 116 | /* |
67 | * Returns true when there is at least one combination of pressed keys that | 117 | * Returns true when there is at least one combination of pressed keys that |
68 | * results in ghosting. | 118 | * results in ghosting. |
@@ -149,20 +199,33 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev, | |||
149 | input_sync(ckdev->idev); | 199 | input_sync(ckdev->idev); |
150 | } | 200 | } |
151 | 201 | ||
152 | static int cros_ec_keyb_open(struct input_dev *dev) | 202 | /** |
203 | * cros_ec_keyb_report_bs - Report non-matrixed buttons or switches | ||
204 | * | ||
205 | * This takes a bitmap of buttons or switches from the EC and reports events, | ||
206 | * syncing at the end. | ||
207 | * | ||
208 | * @ckdev: The keyboard device. | ||
209 | * @ev_type: The input event type (e.g., EV_KEY). | ||
210 | * @mask: A bitmap of buttons from the EC. | ||
211 | */ | ||
212 | static void cros_ec_keyb_report_bs(struct cros_ec_keyb *ckdev, | ||
213 | unsigned int ev_type, u32 mask) | ||
214 | |||
153 | { | 215 | { |
154 | struct cros_ec_keyb *ckdev = input_get_drvdata(dev); | 216 | struct input_dev *idev = ckdev->bs_idev; |
217 | int i; | ||
155 | 218 | ||
156 | return blocking_notifier_chain_register(&ckdev->ec->event_notifier, | 219 | for (i = 0; i < ARRAY_SIZE(cros_ec_keyb_bs); i++) { |
157 | &ckdev->notifier); | 220 | const struct cros_ec_bs_map *map = &cros_ec_keyb_bs[i]; |
158 | } | ||
159 | 221 | ||
160 | static void cros_ec_keyb_close(struct input_dev *dev) | 222 | if (map->ev_type != ev_type) |
161 | { | 223 | continue; |
162 | struct cros_ec_keyb *ckdev = input_get_drvdata(dev); | ||
163 | 224 | ||
164 | blocking_notifier_chain_unregister(&ckdev->ec->event_notifier, | 225 | input_event(idev, ev_type, map->code, |
165 | &ckdev->notifier); | 226 | !!(mask & BIT(map->bit)) ^ map->inverted); |
227 | } | ||
228 | input_sync(idev); | ||
166 | } | 229 | } |
167 | 230 | ||
168 | static int cros_ec_keyb_work(struct notifier_block *nb, | 231 | static int cros_ec_keyb_work(struct notifier_block *nb, |
@@ -170,22 +233,54 @@ static int cros_ec_keyb_work(struct notifier_block *nb, | |||
170 | { | 233 | { |
171 | struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb, | 234 | struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb, |
172 | notifier); | 235 | notifier); |
236 | u32 val; | ||
237 | unsigned int ev_type; | ||
238 | |||
239 | switch (ckdev->ec->event_data.event_type) { | ||
240 | case EC_MKBP_EVENT_KEY_MATRIX: | ||
241 | /* | ||
242 | * If EC is not the wake source, discard key state changes | ||
243 | * during suspend. | ||
244 | */ | ||
245 | if (queued_during_suspend) | ||
246 | return NOTIFY_OK; | ||
247 | |||
248 | if (ckdev->ec->event_size != ckdev->cols) { | ||
249 | dev_err(ckdev->dev, | ||
250 | "Discarded incomplete key matrix event.\n"); | ||
251 | return NOTIFY_OK; | ||
252 | } | ||
253 | cros_ec_keyb_process(ckdev, | ||
254 | ckdev->ec->event_data.data.key_matrix, | ||
255 | ckdev->ec->event_size); | ||
256 | break; | ||
257 | |||
258 | case EC_MKBP_EVENT_BUTTON: | ||
259 | case EC_MKBP_EVENT_SWITCH: | ||
260 | /* | ||
261 | * If EC is not the wake source, discard key state | ||
262 | * changes during suspend. Switches will be re-checked in | ||
263 | * cros_ec_keyb_resume() to be sure nothing is lost. | ||
264 | */ | ||
265 | if (queued_during_suspend) | ||
266 | return NOTIFY_OK; | ||
267 | |||
268 | if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) { | ||
269 | val = get_unaligned_le32( | ||
270 | &ckdev->ec->event_data.data.buttons); | ||
271 | ev_type = EV_KEY; | ||
272 | } else { | ||
273 | val = get_unaligned_le32( | ||
274 | &ckdev->ec->event_data.data.switches); | ||
275 | ev_type = EV_SW; | ||
276 | } | ||
277 | cros_ec_keyb_report_bs(ckdev, ev_type, val); | ||
278 | break; | ||
173 | 279 | ||
174 | if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX) | 280 | default: |
175 | return NOTIFY_DONE; | 281 | return NOTIFY_DONE; |
176 | /* | ||
177 | * If EC is not the wake source, discard key state changes during | ||
178 | * suspend. | ||
179 | */ | ||
180 | if (queued_during_suspend) | ||
181 | return NOTIFY_OK; | ||
182 | if (ckdev->ec->event_size != ckdev->cols) { | ||
183 | dev_err(ckdev->dev, | ||
184 | "Discarded incomplete key matrix event.\n"); | ||
185 | return NOTIFY_OK; | ||
186 | } | 282 | } |
187 | cros_ec_keyb_process(ckdev, ckdev->ec->event_data.data.key_matrix, | 283 | |
188 | ckdev->ec->event_size); | ||
189 | return NOTIFY_OK; | 284 | return NOTIFY_OK; |
190 | } | 285 | } |
191 | 286 | ||
@@ -213,22 +308,228 @@ static void cros_ec_keyb_compute_valid_keys(struct cros_ec_keyb *ckdev) | |||
213 | } | 308 | } |
214 | } | 309 | } |
215 | 310 | ||
216 | static int cros_ec_keyb_probe(struct platform_device *pdev) | 311 | /** |
312 | * cros_ec_keyb_info - Wrap the EC command EC_CMD_MKBP_INFO | ||
313 | * | ||
314 | * This wraps the EC_CMD_MKBP_INFO, abstracting out all of the marshalling and | ||
315 | * unmarshalling and different version nonsense into something simple. | ||
316 | * | ||
317 | * @ec_dev: The EC device | ||
318 | * @info_type: Either EC_MKBP_INFO_SUPPORTED or EC_MKBP_INFO_CURRENT. | ||
319 | * @event_type: Either EC_MKBP_EVENT_BUTTON or EC_MKBP_EVENT_SWITCH. Actually | ||
320 | * in some cases this could be EC_MKBP_EVENT_KEY_MATRIX or | ||
321 | * EC_MKBP_EVENT_HOST_EVENT too but we don't use in this driver. | ||
322 | * @result: Where we'll store the result; a union | ||
323 | * @result_size: The size of the result. Expected to be the size of one of | ||
324 | * the elements in the union. | ||
325 | * | ||
326 | * Returns 0 if no error or -error upon error. | ||
327 | */ | ||
328 | static int cros_ec_keyb_info(struct cros_ec_device *ec_dev, | ||
329 | enum ec_mkbp_info_type info_type, | ||
330 | enum ec_mkbp_event event_type, | ||
331 | union ec_response_get_next_data *result, | ||
332 | size_t result_size) | ||
217 | { | 333 | { |
218 | struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); | 334 | struct ec_params_mkbp_info *params; |
219 | struct device *dev = &pdev->dev; | 335 | struct cros_ec_command *msg; |
220 | struct cros_ec_keyb *ckdev; | 336 | int ret; |
337 | |||
338 | msg = kzalloc(sizeof(*msg) + max_t(size_t, result_size, | ||
339 | sizeof(*params)), GFP_KERNEL); | ||
340 | if (!msg) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | msg->command = EC_CMD_MKBP_INFO; | ||
344 | msg->version = 1; | ||
345 | msg->outsize = sizeof(*params); | ||
346 | msg->insize = result_size; | ||
347 | params = (struct ec_params_mkbp_info *)msg->data; | ||
348 | params->info_type = info_type; | ||
349 | params->event_type = event_type; | ||
350 | |||
351 | ret = cros_ec_cmd_xfer(ec_dev, msg); | ||
352 | if (ret < 0) { | ||
353 | dev_warn(ec_dev->dev, "Transfer error %d/%d: %d\n", | ||
354 | (int)info_type, (int)event_type, ret); | ||
355 | } else if (msg->result == EC_RES_INVALID_VERSION) { | ||
356 | /* With older ECs we just return 0 for everything */ | ||
357 | memset(result, 0, result_size); | ||
358 | ret = 0; | ||
359 | } else if (msg->result != EC_RES_SUCCESS) { | ||
360 | dev_warn(ec_dev->dev, "Error getting info %d/%d: %d\n", | ||
361 | (int)info_type, (int)event_type, msg->result); | ||
362 | ret = -EPROTO; | ||
363 | } else if (ret != result_size) { | ||
364 | dev_warn(ec_dev->dev, "Wrong size %d/%d: %d != %zu\n", | ||
365 | (int)info_type, (int)event_type, | ||
366 | ret, result_size); | ||
367 | ret = -EPROTO; | ||
368 | } else { | ||
369 | memcpy(result, msg->data, result_size); | ||
370 | ret = 0; | ||
371 | } | ||
372 | |||
373 | kfree(msg); | ||
374 | |||
375 | return ret; | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * cros_ec_keyb_query_switches - Query the state of switches and report | ||
380 | * | ||
381 | * This will ask the EC about the current state of switches and report to the | ||
382 | * kernel. Note that we don't query for buttons because they are more | ||
383 | * transitory and we'll get an update on the next release / press. | ||
384 | * | ||
385 | * @ckdev: The keyboard device | ||
386 | * | ||
387 | * Returns 0 if no error or -error upon error. | ||
388 | */ | ||
389 | static int cros_ec_keyb_query_switches(struct cros_ec_keyb *ckdev) | ||
390 | { | ||
391 | struct cros_ec_device *ec_dev = ckdev->ec; | ||
392 | union ec_response_get_next_data event_data = {}; | ||
393 | int ret; | ||
394 | |||
395 | ret = cros_ec_keyb_info(ec_dev, EC_MKBP_INFO_CURRENT, | ||
396 | EC_MKBP_EVENT_SWITCH, &event_data, | ||
397 | sizeof(event_data.switches)); | ||
398 | if (ret) | ||
399 | return ret; | ||
400 | |||
401 | cros_ec_keyb_report_bs(ckdev, EV_SW, | ||
402 | get_unaligned_le32(&event_data.switches)); | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | /** | ||
408 | * cros_ec_keyb_resume - Resume the keyboard | ||
409 | * | ||
410 | * We use the resume notification as a chance to query the EC for switches. | ||
411 | * | ||
412 | * @dev: The keyboard device | ||
413 | * | ||
414 | * Returns 0 if no error or -error upon error. | ||
415 | */ | ||
416 | static __maybe_unused int cros_ec_keyb_resume(struct device *dev) | ||
417 | { | ||
418 | struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); | ||
419 | |||
420 | if (ckdev->bs_idev) | ||
421 | return cros_ec_keyb_query_switches(ckdev); | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * cros_ec_keyb_register_bs - Register non-matrix buttons/switches | ||
428 | * | ||
429 | * Handles all the bits of the keyboard driver related to non-matrix buttons | ||
430 | * and switches, including asking the EC about which are present and telling | ||
431 | * the kernel to expect them. | ||
432 | * | ||
433 | * If this device has no support for buttons and switches we'll return no error | ||
434 | * but the ckdev->bs_idev will remain NULL when this function exits. | ||
435 | * | ||
436 | * @ckdev: The keyboard device | ||
437 | * | ||
438 | * Returns 0 if no error or -error upon error. | ||
439 | */ | ||
440 | static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev) | ||
441 | { | ||
442 | struct cros_ec_device *ec_dev = ckdev->ec; | ||
443 | struct device *dev = ckdev->dev; | ||
221 | struct input_dev *idev; | 444 | struct input_dev *idev; |
222 | struct device_node *np; | 445 | union ec_response_get_next_data event_data = {}; |
223 | int err; | 446 | const char *phys; |
447 | u32 buttons; | ||
448 | u32 switches; | ||
449 | int ret; | ||
450 | int i; | ||
451 | |||
452 | ret = cros_ec_keyb_info(ec_dev, EC_MKBP_INFO_SUPPORTED, | ||
453 | EC_MKBP_EVENT_BUTTON, &event_data, | ||
454 | sizeof(event_data.buttons)); | ||
455 | if (ret) | ||
456 | return ret; | ||
457 | buttons = get_unaligned_le32(&event_data.buttons); | ||
458 | |||
459 | ret = cros_ec_keyb_info(ec_dev, EC_MKBP_INFO_SUPPORTED, | ||
460 | EC_MKBP_EVENT_SWITCH, &event_data, | ||
461 | sizeof(event_data.switches)); | ||
462 | if (ret) | ||
463 | return ret; | ||
464 | switches = get_unaligned_le32(&event_data.switches); | ||
465 | |||
466 | if (!buttons && !switches) | ||
467 | return 0; | ||
224 | 468 | ||
225 | np = pdev->dev.of_node; | 469 | /* |
226 | if (!np) | 470 | * We call the non-matrix buttons/switches 'input1', if present. |
227 | return -ENODEV; | 471 | * Allocate phys before input dev, to ensure correct tear-down |
472 | * ordering. | ||
473 | */ | ||
474 | phys = devm_kasprintf(dev, GFP_KERNEL, "%s/input1", ec_dev->phys_name); | ||
475 | if (!phys) | ||
476 | return -ENOMEM; | ||
228 | 477 | ||
229 | ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL); | 478 | idev = devm_input_allocate_device(dev); |
230 | if (!ckdev) | 479 | if (!idev) |
231 | return -ENOMEM; | 480 | return -ENOMEM; |
481 | |||
482 | idev->name = "cros_ec_buttons"; | ||
483 | idev->phys = phys; | ||
484 | __set_bit(EV_REP, idev->evbit); | ||
485 | |||
486 | idev->id.bustype = BUS_VIRTUAL; | ||
487 | idev->id.version = 1; | ||
488 | idev->id.product = 0; | ||
489 | idev->dev.parent = dev; | ||
490 | |||
491 | input_set_drvdata(idev, ckdev); | ||
492 | ckdev->bs_idev = idev; | ||
493 | |||
494 | for (i = 0; i < ARRAY_SIZE(cros_ec_keyb_bs); i++) { | ||
495 | const struct cros_ec_bs_map *map = &cros_ec_keyb_bs[i]; | ||
496 | |||
497 | if (buttons & BIT(map->bit)) | ||
498 | input_set_capability(idev, map->ev_type, map->code); | ||
499 | } | ||
500 | |||
501 | ret = cros_ec_keyb_query_switches(ckdev); | ||
502 | if (ret) { | ||
503 | dev_err(dev, "cannot query switches\n"); | ||
504 | return ret; | ||
505 | } | ||
506 | |||
507 | ret = input_register_device(ckdev->bs_idev); | ||
508 | if (ret) { | ||
509 | dev_err(dev, "cannot register input device\n"); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * cros_ec_keyb_register_bs - Register matrix keys | ||
518 | * | ||
519 | * Handles all the bits of the keyboard driver related to matrix keys. | ||
520 | * | ||
521 | * @ckdev: The keyboard device | ||
522 | * | ||
523 | * Returns 0 if no error or -error upon error. | ||
524 | */ | ||
525 | static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) | ||
526 | { | ||
527 | struct cros_ec_device *ec_dev = ckdev->ec; | ||
528 | struct device *dev = ckdev->dev; | ||
529 | struct input_dev *idev; | ||
530 | const char *phys; | ||
531 | int err; | ||
532 | |||
232 | err = matrix_keypad_parse_of_params(dev, &ckdev->rows, &ckdev->cols); | 533 | err = matrix_keypad_parse_of_params(dev, &ckdev->rows, &ckdev->cols); |
233 | if (err) | 534 | if (err) |
234 | return err; | 535 | return err; |
@@ -241,27 +542,28 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) | |||
241 | if (!ckdev->old_kb_state) | 542 | if (!ckdev->old_kb_state) |
242 | return -ENOMEM; | 543 | return -ENOMEM; |
243 | 544 | ||
545 | /* | ||
546 | * We call the keyboard matrix 'input0'. Allocate phys before input | ||
547 | * dev, to ensure correct tear-down ordering. | ||
548 | */ | ||
549 | phys = devm_kasprintf(dev, GFP_KERNEL, "%s/input0", ec_dev->phys_name); | ||
550 | if (!phys) | ||
551 | return -ENOMEM; | ||
552 | |||
244 | idev = devm_input_allocate_device(dev); | 553 | idev = devm_input_allocate_device(dev); |
245 | if (!idev) | 554 | if (!idev) |
246 | return -ENOMEM; | 555 | return -ENOMEM; |
247 | 556 | ||
248 | ckdev->ec = ec; | ||
249 | ckdev->notifier.notifier_call = cros_ec_keyb_work; | ||
250 | ckdev->dev = dev; | ||
251 | dev_set_drvdata(dev, ckdev); | ||
252 | |||
253 | idev->name = CROS_EC_DEV_NAME; | 557 | idev->name = CROS_EC_DEV_NAME; |
254 | idev->phys = ec->phys_name; | 558 | idev->phys = phys; |
255 | __set_bit(EV_REP, idev->evbit); | 559 | __set_bit(EV_REP, idev->evbit); |
256 | 560 | ||
257 | idev->id.bustype = BUS_VIRTUAL; | 561 | idev->id.bustype = BUS_VIRTUAL; |
258 | idev->id.version = 1; | 562 | idev->id.version = 1; |
259 | idev->id.product = 0; | 563 | idev->id.product = 0; |
260 | idev->dev.parent = dev; | 564 | idev->dev.parent = dev; |
261 | idev->open = cros_ec_keyb_open; | ||
262 | idev->close = cros_ec_keyb_close; | ||
263 | 565 | ||
264 | ckdev->ghost_filter = of_property_read_bool(np, | 566 | ckdev->ghost_filter = of_property_read_bool(dev->of_node, |
265 | "google,needs-ghost-filter"); | 567 | "google,needs-ghost-filter"); |
266 | 568 | ||
267 | err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols, | 569 | err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols, |
@@ -287,6 +589,57 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) | |||
287 | return 0; | 589 | return 0; |
288 | } | 590 | } |
289 | 591 | ||
592 | static int cros_ec_keyb_probe(struct platform_device *pdev) | ||
593 | { | ||
594 | struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); | ||
595 | struct device *dev = &pdev->dev; | ||
596 | struct cros_ec_keyb *ckdev; | ||
597 | int err; | ||
598 | |||
599 | if (!dev->of_node) | ||
600 | return -ENODEV; | ||
601 | |||
602 | ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL); | ||
603 | if (!ckdev) | ||
604 | return -ENOMEM; | ||
605 | |||
606 | ckdev->ec = ec; | ||
607 | ckdev->dev = dev; | ||
608 | dev_set_drvdata(dev, ckdev); | ||
609 | |||
610 | err = cros_ec_keyb_register_matrix(ckdev); | ||
611 | if (err) { | ||
612 | dev_err(dev, "cannot register matrix inputs: %d\n", err); | ||
613 | return err; | ||
614 | } | ||
615 | |||
616 | err = cros_ec_keyb_register_bs(ckdev); | ||
617 | if (err) { | ||
618 | dev_err(dev, "cannot register non-matrix inputs: %d\n", err); | ||
619 | return err; | ||
620 | } | ||
621 | |||
622 | ckdev->notifier.notifier_call = cros_ec_keyb_work; | ||
623 | err = blocking_notifier_chain_register(&ckdev->ec->event_notifier, | ||
624 | &ckdev->notifier); | ||
625 | if (err) { | ||
626 | dev_err(dev, "cannot register notifier: %d\n", err); | ||
627 | return err; | ||
628 | } | ||
629 | |||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | static int cros_ec_keyb_remove(struct platform_device *pdev) | ||
634 | { | ||
635 | struct cros_ec_keyb *ckdev = dev_get_drvdata(&pdev->dev); | ||
636 | |||
637 | blocking_notifier_chain_unregister(&ckdev->ec->event_notifier, | ||
638 | &ckdev->notifier); | ||
639 | |||
640 | return 0; | ||
641 | } | ||
642 | |||
290 | #ifdef CONFIG_OF | 643 | #ifdef CONFIG_OF |
291 | static const struct of_device_id cros_ec_keyb_of_match[] = { | 644 | static const struct of_device_id cros_ec_keyb_of_match[] = { |
292 | { .compatible = "google,cros-ec-keyb" }, | 645 | { .compatible = "google,cros-ec-keyb" }, |
@@ -295,11 +648,15 @@ static const struct of_device_id cros_ec_keyb_of_match[] = { | |||
295 | MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match); | 648 | MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match); |
296 | #endif | 649 | #endif |
297 | 650 | ||
651 | static const SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume); | ||
652 | |||
298 | static struct platform_driver cros_ec_keyb_driver = { | 653 | static struct platform_driver cros_ec_keyb_driver = { |
299 | .probe = cros_ec_keyb_probe, | 654 | .probe = cros_ec_keyb_probe, |
655 | .remove = cros_ec_keyb_remove, | ||
300 | .driver = { | 656 | .driver = { |
301 | .name = "cros-ec-keyb", | 657 | .name = "cros-ec-keyb", |
302 | .of_match_table = of_match_ptr(cros_ec_keyb_of_match), | 658 | .of_match_table = of_match_ptr(cros_ec_keyb_of_match), |
659 | .pm = &cros_ec_keyb_pm_ops, | ||
303 | }, | 660 | }, |
304 | }; | 661 | }; |
305 | 662 | ||