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: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
This commit is contained in:
Dmitry Torokhov 2010-08-04 22:30:02 -07:00 committed by Matthew Garrett
parent 97490f1cf8
commit 1a765cac9a
2 changed files with 62 additions and 111 deletions

View File

@ -171,6 +171,7 @@ config PANASONIC_LAPTOP
tristate "Panasonic Laptop Extras"
depends on INPUT && ACPI
depends on BACKLIGHT_CLASS_DEVICE
select INPUT_SPARSEKMAP
---help---
This driver adds support for access to backlight control and hotkeys
on Panasonic Let's Note laptops.

View File

@ -128,6 +128,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#ifndef ACPI_HOTKEY_COMPONENT
@ -200,30 +201,29 @@ static struct acpi_driver acpi_pcc_driver = {
},
};
#define KEYMAP_SIZE 11
static const unsigned int initial_keymap[KEYMAP_SIZE] = {
/* 0 */ KEY_RESERVED,
/* 1 */ KEY_BRIGHTNESSDOWN,
/* 2 */ KEY_BRIGHTNESSUP,
/* 3 */ KEY_DISPLAYTOGGLE,
/* 4 */ KEY_MUTE,
/* 5 */ KEY_VOLUMEDOWN,
/* 6 */ KEY_VOLUMEUP,
/* 7 */ KEY_SLEEP,
/* 8 */ KEY_PROG1, /* Change CPU boost */
/* 9 */ KEY_BATTERY,
/* 10 */ KEY_SUSPEND,
static const struct key_entry panasonic_keymap[] = {
{ KE_KEY, 0, { KEY_RESERVED } },
{ KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
{ KE_KEY, 2, { KEY_BRIGHTNESSUP } },
{ KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
{ KE_KEY, 4, { KEY_MUTE } },
{ KE_KEY, 5, { KEY_VOLUMEDOWN } },
{ KE_KEY, 6, { KEY_VOLUMEUP } },
{ KE_KEY, 7, { KEY_SLEEP } },
{ KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */
{ KE_KEY, 9, { KEY_BATTERY } },
{ KE_KEY, 10, { KEY_SUSPEND } },
{ KE_END, 0 }
};
struct pcc_acpi {
acpi_handle handle;
unsigned long num_sifr;
int sticky_mode;
u32 *sinf;
u32 *sinf;
struct acpi_device *device;
struct input_dev *input_dev;
struct backlight_device *backlight;
unsigned int keymap[KEYMAP_SIZE];
};
struct pcc_keyinput {
@ -446,56 +446,10 @@ static struct attribute_group pcc_attr_group = {
/* 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)
{
struct input_dev *hotk_input_dev = pcc->input_dev;
int rc;
int key_code, hkey_num;
unsigned long long result;
rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
@ -508,25 +462,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
hkey_num = result & 0xf;
if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
if (!sparse_keymap_report_event(hotk_input_dev,
result & 0xf, result & 0x80, false))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"hotkey number out of range: %d\n",
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;
"Unknown hotkey event: %d\n", result));
}
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)
{
int i, rc;
struct input_dev *input_dev;
int error;
pcc->input_dev = input_allocate_device();
if (!pcc->input_dev) {
input_dev = input_allocate_device();
if (!input_dev) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Couldn't allocate input device for hotkey"));
return -ENOMEM;
}
pcc->input_dev->evbit[0] = BIT(EV_KEY);
input_dev->name = ACPI_PCC_DRIVER_NAME;
input_dev->phys = ACPI_PCC_INPUT_PHYS;
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
pcc->input_dev->name = ACPI_PCC_DRIVER_NAME;
pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS;
pcc->input_dev->id.bustype = BUS_HOST;
pcc->input_dev->id.vendor = 0x0001;
pcc->input_dev->id.product = 0x0001;
pcc->input_dev->id.version = 0x0100;
pcc->input_dev->getkeycode = pcc_getkeycode;
pcc->input_dev->setkeycode = pcc_setkeycode;
error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
if (error) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to setup input device keymap\n"));
goto err_free_dev;
}
/* load initial keymap */
memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap));
error = input_register_device(input_dev);
if (error) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unable to register input device\n"));
goto err_free_keymap;
}
for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++)
__set_bit(pcc->keymap[i], pcc->input_dev->keybit);
__clear_bit(KEY_RESERVED, pcc->input_dev->keybit);
pcc->input_dev = input_dev;
return 0;
input_set_drvdata(pcc->input_dev, pcc);
err_free_keymap:
sparse_keymap_free(input_dev);
err_free_dev:
input_free_device(input_dev);
return error;
}
rc = input_register_device(pcc->input_dev);
if (rc < 0)
input_free_device(pcc->input_dev);
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 */
@ -636,7 +590,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error installing keyinput handler\n"));
goto out_hotkey;
goto out_sinf;
}
if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
@ -651,7 +605,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
&pcc_backlight_ops, &props);
if (IS_ERR(pcc->backlight)) {
result = PTR_ERR(pcc->backlight);
goto out_sinf;
goto out_input;
}
/* read the initial brightness setting from the hardware */
@ -669,12 +623,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
out_backlight:
backlight_device_unregister(pcc->backlight);
out_input:
acpi_pcc_destroy_input(pcc);
out_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:
kfree(pcc);
@ -709,9 +661,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
backlight_device_unregister(pcc->backlight);
input_unregister_device(pcc->input_dev);
/* no need to input_free_device() since core input API refcount and
* free()s the device */
acpi_pcc_destroy_input(pcc);
kfree(pcc->sinf);
kfree(pcc);