diff options
Diffstat (limited to 'drivers/input/keyboard/cros_ec_keyb.c')
| -rw-r--r-- | drivers/input/keyboard/cros_ec_keyb.c | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 6f435125ec03..1c6b0461dc35 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -27,7 +27,7 @@ #include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_proto.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /** * struct cros_ec_keyb - Structure representing EC keyboard device @@ -35,7 +35,6 @@ * @rows: Number of rows in the keypad * @cols: Number of columns in the keypad * @row_shift: log2 or number of rows, rounded up - * @keymap_data: Matrix keymap data used to convert to keyscan values * @ghost_filter: true to enable the matrix key-ghosting filter * @valid_keys: bitmap of existing keys for each matrix column * @old_kb_state: bitmap of keys pressed last scan @@ -50,7 +49,6 @@ struct cros_ec_keyb { unsigned int rows; unsigned int cols; int row_shift; - const struct matrix_keymap_data *keymap_data; bool ghost_filter; uint8_t *valid_keys; uint8_t *old_kb_state; @@ -100,6 +98,21 @@ static const struct cros_ec_bs_map cros_ec_keyb_bs[] = { .code = KEY_VOLUMEDOWN, .bit = EC_MKBP_VOL_DOWN, }, + { + .ev_type = EV_KEY, + .code = KEY_BRIGHTNESSUP, + .bit = EC_MKBP_BRI_UP, + }, + { + .ev_type = EV_KEY, + .code = KEY_BRIGHTNESSDOWN, + .bit = EC_MKBP_BRI_DOWN, + }, + { + .ev_type = EV_KEY, + .code = KEY_SCREENLOCK, + .bit = EC_MKBP_SCREEN_LOCK, + }, /* Switches */ { @@ -248,6 +261,12 @@ static int cros_ec_keyb_work(struct notifier_block *nb, case EC_MKBP_EVENT_KEY_MATRIX: pm_wakeup_event(ckdev->dev, 0); + if (!ckdev->idev) { + dev_warn_once(ckdev->dev, + "Unexpected key matrix event\n"); + return NOTIFY_OK; + } + if (ckdev->ec->event_size != ckdev->cols) { dev_err(ckdev->dev, "Discarded incomplete key matrix event.\n"); @@ -671,10 +690,11 @@ static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj, return attr->mode; } -static const struct attribute_group cros_ec_keyb_attr_group = { +static const struct attribute_group cros_ec_keyb_group = { .is_visible = cros_ec_keyb_attr_is_visible, .attrs = cros_ec_keyb_attrs, }; +__ATTRIBUTE_GROUPS(cros_ec_keyb); static int cros_ec_keyb_probe(struct platform_device *pdev) { @@ -691,6 +711,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) ec = dev_get_drvdata(pdev->dev.parent); if (!ec) return -EPROBE_DEFER; + /* + * Even if the cros_ec_device pointer is available, still need to check + * if the device is fully registered before using it. + */ + if (!cros_ec_device_registered(ec)) + return -EPROBE_DEFER; ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL); if (!ckdev) @@ -715,12 +741,6 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) return err; } - err = devm_device_add_group(dev, &cros_ec_keyb_attr_group); - if (err) { - dev_err(dev, "failed to create attributes: %d\n", err); - return err; - } - ckdev->notifier.notifier_call = cros_ec_keyb_work; err = blocking_notifier_chain_register(&ckdev->ec->event_notifier, &ckdev->notifier); @@ -733,14 +753,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) return 0; } -static int cros_ec_keyb_remove(struct platform_device *pdev) +static void cros_ec_keyb_remove(struct platform_device *pdev) { struct cros_ec_keyb *ckdev = dev_get_drvdata(&pdev->dev); blocking_notifier_chain_unregister(&ckdev->ec->event_notifier, &ckdev->notifier); - - return 0; } #ifdef CONFIG_ACPI @@ -767,6 +785,7 @@ static struct platform_driver cros_ec_keyb_driver = { .remove = cros_ec_keyb_remove, .driver = { .name = "cros-ec-keyb", + .dev_groups = cros_ec_keyb_groups, .of_match_table = of_match_ptr(cros_ec_keyb_of_match), .acpi_match_table = ACPI_PTR(cros_ec_keyb_acpi_match), .pm = pm_sleep_ptr(&cros_ec_keyb_pm_ops), |
