summaryrefslogtreecommitdiff
path: root/drivers/input/keyboard/gpio_keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard/gpio_keys.c')
-rw-r--r--drivers/input/keyboard/gpio_keys.c66
1 files changed, 39 insertions, 27 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 582462d0af75..9c92cdf196e3 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -36,6 +36,8 @@ struct gpio_button_data {
struct input_dev *input;
struct gpio_desc *gpiod;
+ unsigned short *code;
+
struct timer_list release_timer;
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
@@ -52,6 +54,7 @@ struct gpio_keys_drvdata {
const struct gpio_keys_platform_data *pdata;
struct input_dev *input;
struct mutex disable_lock;
+ unsigned short *keymap;
struct gpio_button_data data[0];
};
@@ -203,7 +206,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
if (only_disabled && !bdata->disabled)
continue;
- __set_bit(bdata->button->code, bits);
+ __set_bit(*bdata->code, bits);
}
ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", n_events, bits);
@@ -254,7 +257,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
if (bdata->button->type != type)
continue;
- if (test_bit(bdata->button->code, bits) &&
+ if (test_bit(*bdata->code, bits) &&
!bdata->button->can_disable) {
error = -EINVAL;
goto out;
@@ -269,7 +272,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
if (bdata->button->type != type)
continue;
- if (test_bit(bdata->button->code, bits))
+ if (test_bit(*bdata->code, bits))
gpio_keys_disable_button(bdata);
else
gpio_keys_enable_button(bdata);
@@ -371,7 +374,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
if (state)
input_event(input, type, button->code, button->value);
} else {
- input_event(input, type, button->code, state);
+ input_event(input, type, *bdata->code, state);
}
input_sync(input);
}
@@ -411,7 +414,7 @@ static void gpio_keys_irq_timer(unsigned long _data)
spin_lock_irqsave(&bdata->lock, flags);
if (bdata->key_pressed) {
- input_event(input, EV_KEY, bdata->button->code, 0);
+ input_event(input, EV_KEY, *bdata->code, 0);
input_sync(input);
bdata->key_pressed = false;
}
@@ -421,7 +424,6 @@ static void gpio_keys_irq_timer(unsigned long _data)
static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
{
struct gpio_button_data *bdata = dev_id;
- const struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned long flags;
@@ -433,11 +435,11 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
if (bdata->button->wakeup)
pm_wakeup_event(bdata->input->dev.parent, 0);
- input_event(input, EV_KEY, button->code, 1);
+ input_event(input, EV_KEY, *bdata->code, 1);
input_sync(input);
if (!bdata->release_delay) {
- input_event(input, EV_KEY, button->code, 0);
+ input_event(input, EV_KEY, *bdata->code, 0);
input_sync(input);
goto out;
}
@@ -465,12 +467,14 @@ static void gpio_keys_quiesce_key(void *data)
static int gpio_keys_setup_key(struct platform_device *pdev,
struct input_dev *input,
- struct gpio_button_data *bdata,
+ struct gpio_keys_drvdata *ddata,
const struct gpio_keys_button *button,
+ int idx,
struct fwnode_handle *child)
{
const char *desc = button->desc ? button->desc : "gpio_keys";
struct device *dev = &pdev->dev;
+ struct gpio_button_data *bdata = &ddata->data[idx];
irq_handler_t isr;
unsigned long irqflags;
int irq;
@@ -514,8 +518,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
if (button->active_low)
flags |= GPIOF_ACTIVE_LOW;
- error = devm_gpio_request_one(&pdev->dev, button->gpio, flags,
- desc);
+ error = devm_gpio_request_one(dev, button->gpio, flags, desc);
if (error < 0) {
dev_err(dev, "Failed to request GPIO %d, error %d\n",
button->gpio, error);
@@ -577,16 +580,17 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
irqflags = 0;
}
- input_set_capability(input, button->type ?: EV_KEY, button->code);
+ bdata->code = &ddata->keymap[idx];
+ *bdata->code = button->code;
+ input_set_capability(input, button->type ?: EV_KEY, *bdata->code);
/*
* Install custom action to cancel release timer and
* workqueue item.
*/
- error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata);
+ error = devm_add_action(dev, gpio_keys_quiesce_key, bdata);
if (error) {
- dev_err(&pdev->dev,
- "failed to register quiesce action, error: %d\n",
+ dev_err(dev, "failed to register quiesce action, error: %d\n",
error);
return error;
}
@@ -598,8 +602,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
if (!button->can_disable)
irqflags |= IRQF_SHARED;
- error = devm_request_any_context_irq(&pdev->dev, bdata->irq,
- isr, irqflags, desc, bdata);
+ error = devm_request_any_context_irq(dev, bdata->irq, isr, irqflags,
+ desc, bdata);
if (error < 0) {
dev_err(dev, "Unable to claim irq %d; error %d\n",
bdata->irq, error);
@@ -750,6 +754,12 @@ static int gpio_keys_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ ddata->keymap = devm_kcalloc(dev,
+ pdata->nbuttons, sizeof(ddata->keymap[0]),
+ GFP_KERNEL);
+ if (!ddata->keymap)
+ return -ENOMEM;
+
input = devm_input_allocate_device(dev);
if (!input) {
dev_err(dev, "failed to allocate input device\n");
@@ -765,7 +775,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
input->name = pdata->name ? : pdev->name;
input->phys = "gpio-keys/input0";
- input->dev.parent = &pdev->dev;
+ input->dev.parent = dev;
input->open = gpio_keys_open;
input->close = gpio_keys_close;
@@ -774,25 +784,29 @@ static int gpio_keys_probe(struct platform_device *pdev)
input->id.product = 0x0001;
input->id.version = 0x0100;
+ input->keycode = ddata->keymap;
+ input->keycodesize = sizeof(ddata->keymap[0]);
+ input->keycodemax = pdata->nbuttons;
+
/* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
for (i = 0; i < pdata->nbuttons; i++) {
const struct gpio_keys_button *button = &pdata->buttons[i];
- struct gpio_button_data *bdata = &ddata->data[i];
if (!dev_get_platdata(dev)) {
- child = device_get_next_child_node(&pdev->dev, child);
+ child = device_get_next_child_node(dev, child);
if (!child) {
- dev_err(&pdev->dev,
+ dev_err(dev,
"missing child device node for entry %d\n",
i);
return -EINVAL;
}
}
- error = gpio_keys_setup_key(pdev, input, bdata, button, child);
+ error = gpio_keys_setup_key(pdev, input, ddata,
+ button, i, child);
if (error) {
fwnode_handle_put(child);
return error;
@@ -804,7 +818,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
fwnode_handle_put(child);
- error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);
+ error = sysfs_create_group(&dev->kobj, &gpio_keys_attr_group);
if (error) {
dev_err(dev, "Unable to export keys/switches, error: %d\n",
error);
@@ -818,12 +832,12 @@ static int gpio_keys_probe(struct platform_device *pdev)
goto err_remove_group;
}
- device_init_wakeup(&pdev->dev, wakeup);
+ device_init_wakeup(dev, wakeup);
return 0;
err_remove_group:
- sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
+ sysfs_remove_group(&dev->kobj, &gpio_keys_attr_group);
return error;
}
@@ -831,8 +845,6 @@ static int gpio_keys_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
- device_init_wakeup(&pdev->dev, 0);
-
return 0;
}