diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7d9ae394e597..a6b8af69915d 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -257,7 +257,6 @@ config INPUT_MMA8450 config INPUT_APANEL tristate "Fujitsu Lifebook Application Panel buttons" depends on X86 && I2C && LEDS_CLASS - select INPUT_POLLDEV select CHECK_SIGNATURE help Say Y here for support of the Application Panel buttons, used on diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index 53ec40d1b90d..7276657ad7ca 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include @@ -51,19 +51,28 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX]; #define MAX_PANEL_KEYS 12 struct apanel { - struct input_polled_dev *ipdev; + struct input_dev *idev; struct i2c_client *client; unsigned short keymap[MAX_PANEL_KEYS]; - u16 nkeys; + u16 nkeys; struct led_classdev mail_led; }; +static const unsigned short apanel_keymap[MAX_PANEL_KEYS] = { + [0] = KEY_MAIL, + [1] = KEY_WWW, + [2] = KEY_PROG2, + [3] = KEY_PROG1, -static int apanel_probe(struct i2c_client *, const struct i2c_device_id *); + [8] = KEY_FORWARD, + [9] = KEY_REWIND, + [10] = KEY_STOPCD, + [11] = KEY_PLAYPAUSE, +}; static void report_key(struct input_dev *input, unsigned keycode) { - pr_debug(APANEL ": report key %#x\n", keycode); + dev_dbg(input->dev.parent, "report key %#x\n", keycode); input_report_key(input, keycode, 1); input_sync(input); @@ -79,10 +88,9 @@ static void report_key(struct input_dev *input, unsigned keycode) * CD keys: * Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800) */ -static void apanel_poll(struct input_polled_dev *ipdev) +static void apanel_poll(struct input_dev *idev) { - struct apanel *ap = ipdev->private; - struct input_dev *idev = ipdev->input; + struct apanel *ap = input_get_drvdata(idev); u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; s32 data; int i; @@ -112,22 +120,76 @@ static int mail_led_set(struct led_classdev *led, return i2c_smbus_write_word_data(ap->client, 0x10, led_bits); } -static int apanel_remove(struct i2c_client *client) +static int apanel_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct apanel *ap = i2c_get_clientdata(client); + struct apanel *ap; + struct input_dev *idev; + u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; + int i, err; - if (device_chip[APANEL_DEV_LED] != CHIP_NONE) - led_classdev_unregister(&ap->mail_led); + ap = devm_kzalloc(&client->dev, sizeof(*ap), GFP_KERNEL); + if (!ap) + return -ENOMEM; - input_unregister_polled_device(ap->ipdev); - input_free_polled_device(ap->ipdev); + idev = devm_input_allocate_device(&client->dev); + if (!idev) + return -ENOMEM; + + ap->idev = idev; + ap->client = client; + + i2c_set_clientdata(client, ap); + + err = i2c_smbus_write_word_data(client, cmd, 0); + if (err) { + dev_warn(&client->dev, "smbus write error %d\n", err); + return err; + } + + input_set_drvdata(idev, ap); + + idev->name = APANEL_NAME " buttons"; + idev->phys = "apanel/input0"; + idev->id.bustype = BUS_HOST; + + memcpy(ap->keymap, apanel_keymap, sizeof(apanel_keymap)); + idev->keycode = ap->keymap; + idev->keycodesize = sizeof(ap->keymap[0]); + idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4; + + set_bit(EV_KEY, idev->evbit); + for (i = 0; i < idev->keycodemax; i++) + if (ap->keymap[i]) + set_bit(ap->keymap[i], idev->keybit); + + err = input_setup_polling(idev, apanel_poll); + if (err) + return err; + + input_set_poll_interval(idev, POLL_INTERVAL_DEFAULT); + + err = input_register_device(idev); + if (err) + return err; + + if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { + ap->mail_led.name = "mail:blue"; + ap->mail_led.brightness_set_blocking = mail_led_set; + err = devm_led_classdev_register(&client->dev, &ap->mail_led); + if (err) + return err; + } return 0; } static void apanel_shutdown(struct i2c_client *client) { - apanel_remove(client); + struct apanel *ap = i2c_get_clientdata(client); + + if (device_chip[APANEL_DEV_LED] != CHIP_NONE) + led_set_brightness(&ap->mail_led, LED_OFF); } static const struct i2c_device_id apanel_id[] = { @@ -140,98 +202,11 @@ static struct i2c_driver apanel_driver = { .driver = { .name = APANEL, }, - .probe = &apanel_probe, - .remove = &apanel_remove, - .shutdown = &apanel_shutdown, + .probe = apanel_probe, + .shutdown = apanel_shutdown, .id_table = apanel_id, }; -static struct apanel apanel = { - .keymap = { - [0] = KEY_MAIL, - [1] = KEY_WWW, - [2] = KEY_PROG2, - [3] = KEY_PROG1, - - [8] = KEY_FORWARD, - [9] = KEY_REWIND, - [10] = KEY_STOPCD, - [11] = KEY_PLAYPAUSE, - - }, - .mail_led = { - .name = "mail:blue", - .brightness_set_blocking = mail_led_set, - }, -}; - -/* NB: Only one panel on the i2c. */ -static int apanel_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct apanel *ap; - struct input_polled_dev *ipdev; - struct input_dev *idev; - u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; - int i, err = -ENOMEM; - - ap = &apanel; - - ipdev = input_allocate_polled_device(); - if (!ipdev) - goto out1; - - ap->ipdev = ipdev; - ap->client = client; - - i2c_set_clientdata(client, ap); - - err = i2c_smbus_write_word_data(client, cmd, 0); - if (err) { - dev_warn(&client->dev, APANEL ": smbus write error %d\n", - err); - goto out3; - } - - ipdev->poll = apanel_poll; - ipdev->poll_interval = POLL_INTERVAL_DEFAULT; - ipdev->private = ap; - - idev = ipdev->input; - idev->name = APANEL_NAME " buttons"; - idev->phys = "apanel/input0"; - idev->id.bustype = BUS_HOST; - idev->dev.parent = &client->dev; - - set_bit(EV_KEY, idev->evbit); - - idev->keycode = ap->keymap; - idev->keycodesize = sizeof(ap->keymap[0]); - idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4; - - for (i = 0; i < idev->keycodemax; i++) - if (ap->keymap[i]) - set_bit(ap->keymap[i], idev->keybit); - - err = input_register_polled_device(ipdev); - if (err) - goto out3; - - if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { - err = led_classdev_register(&client->dev, &ap->mail_led); - if (err) - goto out4; - } - - return 0; -out4: - input_unregister_polled_device(ipdev); -out3: - input_free_polled_device(ipdev); -out1: - return err; -} - /* Scan the system ROM for the signature "FJKEYINF" */ static __init const void __iomem *bios_signature(const void __iomem *bios) {