forked from luck/tmp_suning_uos_patched
Input: apanel - switch to using polled mode of input devices
We have added polled mode to the normal input devices with the intent of retiring input_polled_dev. This converts apanel driver to use the polling mode of standard input devices and removes dependency on INPUT_POLLDEV. While at it, let's convert the driver to use devm. Link: https://lore.kernel.org/r/20191017204217.106453-10-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
9584bded0b
commit
071ec845c8
|
@ -257,7 +257,6 @@ config INPUT_MMA8450
|
||||||
config INPUT_APANEL
|
config INPUT_APANEL
|
||||||
tristate "Fujitsu Lifebook Application Panel buttons"
|
tristate "Fujitsu Lifebook Application Panel buttons"
|
||||||
depends on X86 && I2C && LEDS_CLASS
|
depends on X86 && I2C && LEDS_CLASS
|
||||||
select INPUT_POLLDEV
|
|
||||||
select CHECK_SIGNATURE
|
select CHECK_SIGNATURE
|
||||||
help
|
help
|
||||||
Say Y here for support of the Application Panel buttons, used on
|
Say Y here for support of the Application Panel buttons, used on
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/input-polldev.h>
|
#include <linux/input.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
|
|
||||||
|
@ -51,19 +51,28 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX];
|
||||||
#define MAX_PANEL_KEYS 12
|
#define MAX_PANEL_KEYS 12
|
||||||
|
|
||||||
struct apanel {
|
struct apanel {
|
||||||
struct input_polled_dev *ipdev;
|
struct input_dev *idev;
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
unsigned short keymap[MAX_PANEL_KEYS];
|
unsigned short keymap[MAX_PANEL_KEYS];
|
||||||
u16 nkeys;
|
u16 nkeys;
|
||||||
struct led_classdev mail_led;
|
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)
|
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_report_key(input, keycode, 1);
|
||||||
input_sync(input);
|
input_sync(input);
|
||||||
|
|
||||||
|
@ -79,10 +88,9 @@ static void report_key(struct input_dev *input, unsigned keycode)
|
||||||
* CD keys:
|
* CD keys:
|
||||||
* Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800)
|
* 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 apanel *ap = input_get_drvdata(idev);
|
||||||
struct input_dev *idev = ipdev->input;
|
|
||||||
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
|
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
|
||||||
s32 data;
|
s32 data;
|
||||||
int i;
|
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);
|
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)
|
ap = devm_kzalloc(&client->dev, sizeof(*ap), GFP_KERNEL);
|
||||||
led_classdev_unregister(&ap->mail_led);
|
if (!ap)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
input_unregister_polled_device(ap->ipdev);
|
idev = devm_input_allocate_device(&client->dev);
|
||||||
input_free_polled_device(ap->ipdev);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apanel_shutdown(struct i2c_client *client)
|
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[] = {
|
static const struct i2c_device_id apanel_id[] = {
|
||||||
|
@ -140,98 +202,11 @@ static struct i2c_driver apanel_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = APANEL,
|
.name = APANEL,
|
||||||
},
|
},
|
||||||
.probe = &apanel_probe,
|
.probe = apanel_probe,
|
||||||
.remove = &apanel_remove,
|
.shutdown = apanel_shutdown,
|
||||||
.shutdown = &apanel_shutdown,
|
|
||||||
.id_table = apanel_id,
|
.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" */
|
/* Scan the system ROM for the signature "FJKEYINF" */
|
||||||
static __init const void __iomem *bios_signature(const void __iomem *bios)
|
static __init const void __iomem *bios_signature(const void __iomem *bios)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user