Commit 1a765cac authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Matthew Garrett

panasonic-laptop - switch to using sparse keymap library

nstead of implementing its own version of keymap hanlding switch over to
using sparse keymap library.

Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
Signed-off-by: default avatarMatthew Garrett <mjg@redhat.com>
parent 97490f1c
...@@ -171,6 +171,7 @@ config PANASONIC_LAPTOP ...@@ -171,6 +171,7 @@ config PANASONIC_LAPTOP
tristate "Panasonic Laptop Extras" tristate "Panasonic Laptop Extras"
depends on INPUT && ACPI depends on INPUT && ACPI
depends on BACKLIGHT_CLASS_DEVICE depends on BACKLIGHT_CLASS_DEVICE
select INPUT_SPARSEKMAP
---help--- ---help---
This driver adds support for access to backlight control and hotkeys This driver adds support for access to backlight control and hotkeys
on Panasonic Let's Note laptops. on Panasonic Let's Note laptops.
......
...@@ -128,6 +128,7 @@ ...@@ -128,6 +128,7 @@
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h> #include <acpi/acpi_drivers.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#ifndef ACPI_HOTKEY_COMPONENT #ifndef ACPI_HOTKEY_COMPONENT
...@@ -200,19 +201,19 @@ static struct acpi_driver acpi_pcc_driver = { ...@@ -200,19 +201,19 @@ static struct acpi_driver acpi_pcc_driver = {
}, },
}; };
#define KEYMAP_SIZE 11 static const struct key_entry panasonic_keymap[] = {
static const unsigned int initial_keymap[KEYMAP_SIZE] = { { KE_KEY, 0, { KEY_RESERVED } },
/* 0 */ KEY_RESERVED, { KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
/* 1 */ KEY_BRIGHTNESSDOWN, { KE_KEY, 2, { KEY_BRIGHTNESSUP } },
/* 2 */ KEY_BRIGHTNESSUP, { KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
/* 3 */ KEY_DISPLAYTOGGLE, { KE_KEY, 4, { KEY_MUTE } },
/* 4 */ KEY_MUTE, { KE_KEY, 5, { KEY_VOLUMEDOWN } },
/* 5 */ KEY_VOLUMEDOWN, { KE_KEY, 6, { KEY_VOLUMEUP } },
/* 6 */ KEY_VOLUMEUP, { KE_KEY, 7, { KEY_SLEEP } },
/* 7 */ KEY_SLEEP, { KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */
/* 8 */ KEY_PROG1, /* Change CPU boost */ { KE_KEY, 9, { KEY_BATTERY } },
/* 9 */ KEY_BATTERY, { KE_KEY, 10, { KEY_SUSPEND } },
/* 10 */ KEY_SUSPEND, { KE_END, 0 }
}; };
struct pcc_acpi { struct pcc_acpi {
...@@ -223,7 +224,6 @@ struct pcc_acpi { ...@@ -223,7 +224,6 @@ struct pcc_acpi {
struct acpi_device *device; struct acpi_device *device;
struct input_dev *input_dev; struct input_dev *input_dev;
struct backlight_device *backlight; struct backlight_device *backlight;
unsigned int keymap[KEYMAP_SIZE];
}; };
struct pcc_keyinput { struct pcc_keyinput {
...@@ -446,56 +446,10 @@ static struct attribute_group pcc_attr_group = { ...@@ -446,56 +446,10 @@ static struct attribute_group pcc_attr_group = {
/* hotkey input device driver */ /* hotkey input device driver */
static int pcc_getkeycode(struct input_dev *dev,
unsigned int scancode, unsigned int *keycode)
{
struct pcc_acpi *pcc = input_get_drvdata(dev);
if (scancode >= ARRAY_SIZE(pcc->keymap))
return -EINVAL;
*keycode = pcc->keymap[scancode];
return 0;
}
static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode)
{
int i;
for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) {
if (pcc->keymap[i] == keycode)
return i+1;
}
return 0;
}
static int pcc_setkeycode(struct input_dev *dev,
unsigned int scancode, unsigned int keycode)
{
struct pcc_acpi *pcc = input_get_drvdata(dev);
int oldkeycode;
if (scancode >= ARRAY_SIZE(pcc->keymap))
return -EINVAL;
oldkeycode = pcc->keymap[scancode];
pcc->keymap[scancode] = keycode;
set_bit(keycode, dev->keybit);
if (!keymap_get_by_keycode(pcc, oldkeycode))
clear_bit(oldkeycode, dev->keybit);
return 0;
}
static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
{ {
struct input_dev *hotk_input_dev = pcc->input_dev; struct input_dev *hotk_input_dev = pcc->input_dev;
int rc; int rc;
int key_code, hkey_num;
unsigned long long result; unsigned long long result;
rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
...@@ -508,25 +462,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) ...@@ -508,25 +462,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
hkey_num = result & 0xf; if (!sparse_keymap_report_event(hotk_input_dev,
result & 0xf, result & 0x80, false))
if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"hotkey number out of range: %d\n", "Unknown hotkey event: %d\n", result));
hkey_num));
return;
}
key_code = pcc->keymap[hkey_num];
if (key_code != KEY_RESERVED) {
int pushed = (result & 0x80) ? TRUE : FALSE;
input_report_key(hotk_input_dev, key_code, pushed);
input_sync(hotk_input_dev);
}
return;
} }
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
...@@ -545,40 +484,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) ...@@ -545,40 +484,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
static int acpi_pcc_init_input(struct pcc_acpi *pcc) static int acpi_pcc_init_input(struct pcc_acpi *pcc)
{ {
int i, rc; struct input_dev *input_dev;
int error;
pcc->input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!pcc->input_dev) { if (!input_dev) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Couldn't allocate input device for hotkey")); "Couldn't allocate input device for hotkey"));
return -ENOMEM; return -ENOMEM;
} }
pcc->input_dev->evbit[0] = BIT(EV_KEY); input_dev->name = ACPI_PCC_DRIVER_NAME;
input_dev->phys = ACPI_PCC_INPUT_PHYS;
pcc->input_dev->name = ACPI_PCC_DRIVER_NAME; input_dev->id.bustype = BUS_HOST;
pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS; input_dev->id.vendor = 0x0001;
pcc->input_dev->id.bustype = BUS_HOST; input_dev->id.product = 0x0001;
pcc->input_dev->id.vendor = 0x0001; input_dev->id.version = 0x0100;
pcc->input_dev->id.product = 0x0001;
pcc->input_dev->id.version = 0x0100;
pcc->input_dev->getkeycode = pcc_getkeycode;
pcc->input_dev->setkeycode = pcc_setkeycode;
/* load initial keymap */ error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap)); if (error) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to setup input device keymap\n"));
goto err_free_dev;
}
for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) error = input_register_device(input_dev);
__set_bit(pcc->keymap[i], pcc->input_dev->keybit); if (error) {
__clear_bit(KEY_RESERVED, pcc->input_dev->keybit); ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to register input device\n"));
goto err_free_keymap;
}
input_set_drvdata(pcc->input_dev, pcc); pcc->input_dev = input_dev;
return 0;
rc = input_register_device(pcc->input_dev); err_free_keymap:
if (rc < 0) sparse_keymap_free(input_dev);
input_free_device(pcc->input_dev); err_free_dev:
input_free_device(input_dev);
return error;
}
return rc; static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
{
sparse_keymap_free(pcc->input_dev);
input_unregister_device(pcc->input_dev);
/*
* No need to input_free_device() since core input API refcounts
* and free()s the device.
*/
} }
/* kernel module interface */ /* kernel module interface */
...@@ -636,7 +590,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) ...@@ -636,7 +590,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error installing keyinput handler\n")); "Error installing keyinput handler\n"));
goto out_hotkey; goto out_sinf;
} }
if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) { if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
...@@ -651,7 +605,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) ...@@ -651,7 +605,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
&pcc_backlight_ops, &props); &pcc_backlight_ops, &props);
if (IS_ERR(pcc->backlight)) { if (IS_ERR(pcc->backlight)) {
result = PTR_ERR(pcc->backlight); result = PTR_ERR(pcc->backlight);
goto out_sinf; goto out_input;
} }
/* read the initial brightness setting from the hardware */ /* read the initial brightness setting from the hardware */
...@@ -669,12 +623,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) ...@@ -669,12 +623,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
out_backlight: out_backlight:
backlight_device_unregister(pcc->backlight); backlight_device_unregister(pcc->backlight);
out_input:
acpi_pcc_destroy_input(pcc);
out_sinf: out_sinf:
kfree(pcc->sinf); kfree(pcc->sinf);
out_input:
input_unregister_device(pcc->input_dev);
/* no need to input_free_device() since core input API refcount and
* free()s the device */
out_hotkey: out_hotkey:
kfree(pcc); kfree(pcc);
...@@ -709,9 +661,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) ...@@ -709,9 +661,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
backlight_device_unregister(pcc->backlight); backlight_device_unregister(pcc->backlight);
input_unregister_device(pcc->input_dev); acpi_pcc_destroy_input(pcc);
/* no need to input_free_device() since core input API refcount and
* free()s the device */
kfree(pcc->sinf); kfree(pcc->sinf);
kfree(pcc); kfree(pcc);
......
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