From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 19 Dec 2024 01:47:39 +0000 Subject: [PATCH] add wifi6 8852be driver --- kernel/drivers/input/misc/apanel.c | 210 ++++++++++++++++++++------------------------------- 1 files changed, 83 insertions(+), 127 deletions(-) diff --git a/kernel/drivers/input/misc/apanel.c b/kernel/drivers/input/misc/apanel.c index 094bddf..7276657 100644 --- a/kernel/drivers/input/misc/apanel.c +++ b/kernel/drivers/input/misc/apanel.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Fujitsu Lifebook Application Panel button drive * * Copyright (C) 2007 Stephen Hemminger <shemminger@linux-foundation.org> * Copyright (C) 2001-2003 Jochen Eisinger <jochen@penguin-breeder.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. * * Many Fujitsu Lifebook laptops have a small panel of buttons that are * accessible via the i2c/smbus interface. This driver polls those @@ -20,9 +17,8 @@ #include <linux/module.h> #include <linux/ioport.h> #include <linux/io.h> -#include <linux/input-polldev.h> +#include <linux/input.h> #include <linux/i2c.h> -#include <linux/workqueue.h> #include <linux/leds.h> #define APANEL_NAME "Fujitsu Application Panel" @@ -55,21 +51,28 @@ #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 led_bits; - struct work_struct led_work; + 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); @@ -85,10 +88,9 @@ * 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; @@ -109,43 +111,85 @@ report_key(idev, ap->keymap[i]); } -/* Track state changes of LED */ -static void led_update(struct work_struct *work) -{ - struct apanel *ap = container_of(work, struct apanel, led_work); - - i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits); -} - -static void mail_led_set(struct led_classdev *led, +static int mail_led_set(struct led_classdev *led, enum led_brightness value) { struct apanel *ap = container_of(led, struct apanel, mail_led); + u16 led_bits = value != LED_OFF ? 0x8000 : 0x0000; - if (value != LED_OFF) - ap->led_bits |= 0x8000; - else - ap->led_bits &= ~0x8000; - - schedule_work(&ap->led_work); + 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[] = { @@ -158,98 +202,10 @@ .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 = 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; - - INIT_WORK(&ap->led_work, led_update); - 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) -- Gitblit v1.6.2