Commit 83e4947a authored by Hans de Goede's avatar Hans de Goede Committed by Dmitry Torokhov

Input: gpio-keys - add support for setkeycode

gpio-keys input devices created by the soc_button_array driver are
configured with key-codes based on ACPI provided information.

Unfortunately on some tablets this info is wrong, and we need to have
a quirk to fix things up.

Add support for input_setkeycode to the gpio-keys driver, so that
the existing udev hwdb mechanism can be used to fix things up on these
tablets.
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 5c4fa2a6
...@@ -36,6 +36,8 @@ struct gpio_button_data { ...@@ -36,6 +36,8 @@ struct gpio_button_data {
struct input_dev *input; struct input_dev *input;
struct gpio_desc *gpiod; struct gpio_desc *gpiod;
unsigned short *code;
struct timer_list release_timer; struct timer_list release_timer;
unsigned int release_delay; /* in msecs, for IRQ-only buttons */ unsigned int release_delay; /* in msecs, for IRQ-only buttons */
...@@ -52,6 +54,7 @@ struct gpio_keys_drvdata { ...@@ -52,6 +54,7 @@ struct gpio_keys_drvdata {
const struct gpio_keys_platform_data *pdata; const struct gpio_keys_platform_data *pdata;
struct input_dev *input; struct input_dev *input;
struct mutex disable_lock; struct mutex disable_lock;
unsigned short *keymap;
struct gpio_button_data data[0]; struct gpio_button_data data[0];
}; };
...@@ -203,7 +206,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, ...@@ -203,7 +206,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
if (only_disabled && !bdata->disabled) if (only_disabled && !bdata->disabled)
continue; continue;
__set_bit(bdata->button->code, bits); __set_bit(*bdata->code, bits);
} }
ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", n_events, 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, ...@@ -254,7 +257,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
if (bdata->button->type != type) if (bdata->button->type != type)
continue; continue;
if (test_bit(bdata->button->code, bits) && if (test_bit(*bdata->code, bits) &&
!bdata->button->can_disable) { !bdata->button->can_disable) {
error = -EINVAL; error = -EINVAL;
goto out; goto out;
...@@ -269,7 +272,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, ...@@ -269,7 +272,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
if (bdata->button->type != type) if (bdata->button->type != type)
continue; continue;
if (test_bit(bdata->button->code, bits)) if (test_bit(*bdata->code, bits))
gpio_keys_disable_button(bdata); gpio_keys_disable_button(bdata);
else else
gpio_keys_enable_button(bdata); gpio_keys_enable_button(bdata);
...@@ -371,7 +374,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) ...@@ -371,7 +374,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
if (state) if (state)
input_event(input, type, button->code, button->value); input_event(input, type, button->code, button->value);
} else { } else {
input_event(input, type, button->code, state); input_event(input, type, *bdata->code, state);
} }
input_sync(input); input_sync(input);
} }
...@@ -411,7 +414,7 @@ static void gpio_keys_irq_timer(unsigned long _data) ...@@ -411,7 +414,7 @@ static void gpio_keys_irq_timer(unsigned long _data)
spin_lock_irqsave(&bdata->lock, flags); spin_lock_irqsave(&bdata->lock, flags);
if (bdata->key_pressed) { if (bdata->key_pressed) {
input_event(input, EV_KEY, bdata->button->code, 0); input_event(input, EV_KEY, *bdata->code, 0);
input_sync(input); input_sync(input);
bdata->key_pressed = false; bdata->key_pressed = false;
} }
...@@ -421,7 +424,6 @@ static void gpio_keys_irq_timer(unsigned long _data) ...@@ -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) static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
{ {
struct gpio_button_data *bdata = dev_id; struct gpio_button_data *bdata = dev_id;
const struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input; struct input_dev *input = bdata->input;
unsigned long flags; unsigned long flags;
...@@ -433,11 +435,11 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) ...@@ -433,11 +435,11 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
if (bdata->button->wakeup) if (bdata->button->wakeup)
pm_wakeup_event(bdata->input->dev.parent, 0); 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); input_sync(input);
if (!bdata->release_delay) { if (!bdata->release_delay) {
input_event(input, EV_KEY, button->code, 0); input_event(input, EV_KEY, *bdata->code, 0);
input_sync(input); input_sync(input);
goto out; goto out;
} }
...@@ -465,12 +467,14 @@ static void gpio_keys_quiesce_key(void *data) ...@@ -465,12 +467,14 @@ static void gpio_keys_quiesce_key(void *data)
static int gpio_keys_setup_key(struct platform_device *pdev, static int gpio_keys_setup_key(struct platform_device *pdev,
struct input_dev *input, struct input_dev *input,
struct gpio_button_data *bdata, struct gpio_keys_drvdata *ddata,
const struct gpio_keys_button *button, const struct gpio_keys_button *button,
int idx,
struct fwnode_handle *child) struct fwnode_handle *child)
{ {
const char *desc = button->desc ? button->desc : "gpio_keys"; const char *desc = button->desc ? button->desc : "gpio_keys";
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct gpio_button_data *bdata = &ddata->data[idx];
irq_handler_t isr; irq_handler_t isr;
unsigned long irqflags; unsigned long irqflags;
int irq; int irq;
...@@ -577,7 +581,9 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -577,7 +581,9 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
irqflags = 0; 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 * Install custom action to cancel release timer and
...@@ -750,6 +756,12 @@ static int gpio_keys_probe(struct platform_device *pdev) ...@@ -750,6 +756,12 @@ static int gpio_keys_probe(struct platform_device *pdev)
return -ENOMEM; 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); input = devm_input_allocate_device(dev);
if (!input) { if (!input) {
dev_err(dev, "failed to allocate input device\n"); dev_err(dev, "failed to allocate input device\n");
...@@ -774,13 +786,16 @@ static int gpio_keys_probe(struct platform_device *pdev) ...@@ -774,13 +786,16 @@ static int gpio_keys_probe(struct platform_device *pdev)
input->id.product = 0x0001; input->id.product = 0x0001;
input->id.version = 0x0100; 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 */ /* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep) if (pdata->rep)
__set_bit(EV_REP, input->evbit); __set_bit(EV_REP, input->evbit);
for (i = 0; i < pdata->nbuttons; i++) { for (i = 0; i < pdata->nbuttons; i++) {
const struct gpio_keys_button *button = &pdata->buttons[i]; const struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_button_data *bdata = &ddata->data[i];
if (!dev_get_platdata(dev)) { if (!dev_get_platdata(dev)) {
child = device_get_next_child_node(&pdev->dev, child); child = device_get_next_child_node(&pdev->dev, child);
...@@ -792,7 +807,8 @@ static int gpio_keys_probe(struct platform_device *pdev) ...@@ -792,7 +807,8 @@ static int gpio_keys_probe(struct platform_device *pdev)
} }
} }
error = gpio_keys_setup_key(pdev, input, bdata, button, child); error = gpio_keys_setup_key(pdev, input, ddata,
button, i, child);
if (error) { if (error) {
fwnode_handle_put(child); fwnode_handle_put(child);
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment