Commit 52bbe3c7 authored by Alan Jenkins's avatar Alan Jenkins Committed by Len Brown

eeepc-laptop: code movement

Move e.g. backlight_init() and backlight_exit() together along with the
other backlight functions, instead of grouping init() and exit()
functions.  Move e.g. backlight_ops to follow the functions it refers
to, and remove the forward declarations.  The code itself should remain
unchanged.

The eeepc-laptop driver implements a number of interfaces like the
backlight class driver.  This change makes it easier to examine the
implementation of one interface at at a time, without having to search
through the file to find init() and exit() functions etc.
Signed-off-by: default avatarAlan Jenkins <alan-jenkins@tuffmail.co.uk>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 9db106be
...@@ -44,6 +44,9 @@ ...@@ -44,6 +44,9 @@
#define EEEPC_HOTK_DEVICE_NAME "Hotkey" #define EEEPC_HOTK_DEVICE_NAME "Hotkey"
#define EEEPC_HOTK_HID "ASUS010" #define EEEPC_HOTK_HID "ASUS010"
MODULE_AUTHOR("Corentin Chary, Eric Cooper");
MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
MODULE_LICENSE("GPL");
/* /*
* Definitions for Asus EeePC * Definitions for Asus EeePC
...@@ -118,57 +121,6 @@ static const char *cm_setv[] = { ...@@ -118,57 +121,6 @@ static const char *cm_setv[] = {
NULL, NULL, "PBPS", "TPDS" NULL, NULL, "PBPS", "TPDS"
}; };
#define EEEPC_EC_SC00 0x61
#define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
#define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
#define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
#define EEEPC_EC_SFB0 0xD0
#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
/*
* This is the main structure, we can use it to store useful information
* about the hotk device
*/
struct eeepc_hotk {
struct acpi_device *device; /* the device we are in */
acpi_handle handle; /* the handle of the hotk device */
u32 cm_supported; /* the control methods supported
by this BIOS */
u16 event_count[128]; /* count for each event */
struct input_dev *inputdev;
u16 *keycode_map;
struct rfkill *wlan_rfkill;
struct rfkill *bluetooth_rfkill;
struct rfkill *wwan3g_rfkill;
struct rfkill *wimax_rfkill;
struct hotplug_slot *hotplug_slot;
struct mutex hotplug_lock;
};
/* The actual device the driver binds to */
static struct eeepc_hotk *ehotk;
/* Platform device/driver */
static int eeepc_hotk_thaw(struct device *device);
static int eeepc_hotk_restore(struct device *device);
static struct dev_pm_ops eeepc_pm_ops = {
.thaw = eeepc_hotk_thaw,
.restore = eeepc_hotk_restore,
};
static struct platform_driver platform_driver = {
.driver = {
.name = EEEPC_HOTK_FILE,
.owner = THIS_MODULE,
.pm = &eeepc_pm_ops,
}
};
static struct platform_device *platform_device;
struct key_entry { struct key_entry {
char type; char type;
u8 code; u8 code;
...@@ -189,48 +141,40 @@ static struct key_entry eeepc_keymap[] = { ...@@ -189,48 +141,40 @@ static struct key_entry eeepc_keymap[] = {
{KE_KEY, 0x1b, KEY_ZOOM }, {KE_KEY, 0x1b, KEY_ZOOM },
{KE_KEY, 0x1c, KEY_PROG2 }, {KE_KEY, 0x1c, KEY_PROG2 },
{KE_KEY, 0x1d, KEY_PROG3 }, {KE_KEY, 0x1d, KEY_PROG3 },
{KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
{KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP }, {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP },
{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
{KE_END, 0}, {KE_END, 0},
}; };
/* /*
* The hotkey driver declaration * This is the main structure, we can use it to store useful information
* about the hotk device
*/ */
static int eeepc_hotk_add(struct acpi_device *device); struct eeepc_hotk {
static int eeepc_hotk_remove(struct acpi_device *device, int type); struct acpi_device *device; /* the device we are in */
static void eeepc_hotk_notify(struct acpi_device *device, u32 event); acpi_handle handle; /* the handle of the hotk device */
u32 cm_supported; /* the control methods supported
static const struct acpi_device_id eeepc_device_ids[] = { by this BIOS */
{EEEPC_HOTK_HID, 0}, u16 event_count[128]; /* count for each event */
{"", 0}, struct input_dev *inputdev;
}; u16 *keycode_map;
MODULE_DEVICE_TABLE(acpi, eeepc_device_ids); struct rfkill *wlan_rfkill;
struct rfkill *bluetooth_rfkill;
static struct acpi_driver eeepc_hotk_driver = { struct rfkill *wwan3g_rfkill;
.name = EEEPC_HOTK_NAME, struct rfkill *wimax_rfkill;
.class = EEEPC_HOTK_CLASS, struct hotplug_slot *hotplug_slot;
.owner = THIS_MODULE, struct mutex hotplug_lock;
.ids = eeepc_device_ids,
.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
.ops = {
.add = eeepc_hotk_add,
.remove = eeepc_hotk_remove,
.notify = eeepc_hotk_notify,
},
}; };
/* PCI hotplug ops */ /* The actual device the driver binds to */
static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); static struct eeepc_hotk *ehotk;
static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { /* The platform device */
.owner = THIS_MODULE, static struct platform_device *platform_device;
.get_adapter_status = eeepc_get_adapter_status,
.get_power_status = eeepc_get_adapter_status,
};
/* The backlight device /sys/class/backlight */ /* The backlight device /sys/class/backlight */
static struct backlight_device *eeepc_backlight_device; static struct backlight_device *eeepc_backlight_device;
...@@ -238,19 +182,6 @@ static struct backlight_device *eeepc_backlight_device; ...@@ -238,19 +182,6 @@ static struct backlight_device *eeepc_backlight_device;
/* The hwmon device */ /* The hwmon device */
static struct device *eeepc_hwmon_device; static struct device *eeepc_hwmon_device;
/*
* The backlight class declaration
*/
static int read_brightness(struct backlight_device *bd);
static int update_bl_status(struct backlight_device *bd);
static struct backlight_ops eeepcbl_ops = {
.get_brightness = read_brightness,
.update_status = update_bl_status,
};
MODULE_AUTHOR("Corentin Chary, Eric Cooper");
MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
MODULE_LICENSE("GPL");
/* /*
* ACPI Helpers * ACPI Helpers
...@@ -314,55 +245,6 @@ static int get_acpi(int cm) ...@@ -314,55 +245,6 @@ static int get_acpi(int cm)
return value; return value;
} }
/*
* Backlight
*/
static int read_brightness(struct backlight_device *bd)
{
return get_acpi(CM_ASL_PANELBRIGHT);
}
static int set_brightness(struct backlight_device *bd, int value)
{
return set_acpi(CM_ASL_PANELBRIGHT, value);
}
static int update_bl_status(struct backlight_device *bd)
{
return set_brightness(bd, bd->props.brightness);
}
/*
* Rfkill helpers
*/
static bool eeepc_wlan_rfkill_blocked(void)
{
if (get_acpi(CM_ASL_WLAN) == 1)
return false;
return true;
}
static int eeepc_rfkill_set(void *data, bool blocked)
{
unsigned long asl = (unsigned long)data;
return set_acpi(asl, !blocked);
}
static const struct rfkill_ops eeepc_rfkill_ops = {
.set_block = eeepc_rfkill_set,
};
static void __devinit eeepc_enable_camera(void)
{
/*
* If the following call to set_acpi() fails, it's because there's no
* camera so we can ignore the error.
*/
if (get_acpi(CM_ASL_CAMERA) == 0)
set_acpi(CM_ASL_CAMERA, 1);
}
/* /*
* Sys helpers * Sys helpers
*/ */
...@@ -574,248 +456,97 @@ static struct led_classdev tpd_led = { ...@@ -574,248 +456,97 @@ static struct led_classdev tpd_led = {
.max_brightness = 1 .max_brightness = 1
}; };
/* static int eeepc_led_init(struct device *dev)
* Hotkey functions
*/
static struct key_entry *eepc_get_entry_by_scancode(int code)
{ {
struct key_entry *key; int rv;
for (key = eeepc_keymap; key->type != KE_END; key++)
if (code == key->code)
return key;
return NULL; if (get_acpi(CM_ASL_TPD) == -ENODEV)
} return 0;
static struct key_entry *eepc_get_entry_by_keycode(int code) led_workqueue = create_singlethread_workqueue("led_workqueue");
{ if (!led_workqueue)
struct key_entry *key; return -ENOMEM;
for (key = eeepc_keymap; key->type != KE_END; key++) rv = led_classdev_register(dev, &tpd_led);
if (code == key->keycode && key->type == KE_KEY) if (rv) {
return key; destroy_workqueue(led_workqueue);
return rv;
}
return NULL; return 0;
} }
static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) static void eeepc_led_exit(void)
{ {
struct key_entry *key = eepc_get_entry_by_scancode(scancode); if (tpd_led.dev)
led_classdev_unregister(&tpd_led);
if (led_workqueue)
destroy_workqueue(led_workqueue);
}
if (key && key->type == KE_KEY) {
*keycode = key->keycode;
return 0;
}
return -EINVAL; /*
* PCI hotplug (for wlan rfkill)
*/
static bool eeepc_wlan_rfkill_blocked(void)
{
if (get_acpi(CM_ASL_WLAN) == 1)
return false;
return true;
} }
static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) static void eeepc_rfkill_hotplug(void)
{ {
struct key_entry *key; struct pci_dev *dev;
int old_keycode; struct pci_bus *bus;
bool blocked = eeepc_wlan_rfkill_blocked();
if (keycode < 0 || keycode > KEY_MAX) if (ehotk->wlan_rfkill)
return -EINVAL; rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
key = eepc_get_entry_by_scancode(scancode); mutex_lock(&ehotk->hotplug_lock);
if (key && key->type == KE_KEY) {
old_keycode = key->keycode; if (ehotk->hotplug_slot) {
key->keycode = keycode; bus = pci_find_bus(0, 1);
set_bit(keycode, dev->keybit); if (!bus) {
if (!eepc_get_entry_by_keycode(old_keycode)) pr_warning("Unable to find PCI bus 1?\n");
clear_bit(old_keycode, dev->keybit); goto out_unlock;
return 0; }
if (!blocked) {
dev = pci_get_slot(bus, 0);
if (dev) {
/* Device already present */
pci_dev_put(dev);
goto out_unlock;
}
dev = pci_scan_single_device(bus, 0);
if (dev) {
pci_bus_assign_resources(bus);
if (pci_bus_add_device(dev))
pr_err("Unable to hotplug wifi\n");
}
} else {
dev = pci_get_slot(bus, 0);
if (dev) {
pci_remove_bus_device(dev);
pci_dev_put(dev);
}
}
} }
return -EINVAL; out_unlock:
mutex_unlock(&ehotk->hotplug_lock);
} }
static void cmsg_quirk(int cm, const char *name) static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
{ {
int dummy; if (event != ACPI_NOTIFY_BUS_CHECK)
return;
/* Some BIOSes do not report cm although it is avaliable.
Check if cm_getv[cm] works and, if yes, assume cm should be set. */
if (!(ehotk->cm_supported & (1 << cm))
&& !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
pr_info("%s (%x) not reported by BIOS,"
" enabling anyway\n", name, 1 << cm);
ehotk->cm_supported |= 1 << cm;
}
}
static void cmsg_quirks(void)
{
cmsg_quirk(CM_ASL_LID, "LID");
cmsg_quirk(CM_ASL_TYPE, "TYPE");
cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
cmsg_quirk(CM_ASL_TPD, "TPD");
}
static int eeepc_hotk_init(void)
{
unsigned int init_flags;
int result;
result = acpi_bus_get_status(ehotk->device);
if (result)
return result;
if (!ehotk->device->status.present) {
pr_err("Hotkey device not present, aborting\n");
return -ENODEV;
}
init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
pr_notice("Hotkey init flags 0x%x\n", init_flags);
if (write_acpi_int(ehotk->handle, "INIT", init_flags)) {
pr_err("Hotkey initialization failed\n");
return -ENODEV;
}
/* get control methods supported */
if (read_acpi_int(ehotk->handle, "CMSG",
&ehotk->cm_supported)) {
pr_err("Get control methods supported failed\n");
return -ENODEV;
}
cmsg_quirks();
pr_info("Get control methods supported: 0x%x\n", ehotk->cm_supported);
return 0;
}
static int eeepc_backlight_notify(void)
{
struct backlight_device *bd = eeepc_backlight_device;
int old = bd->props.brightness;
backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
return old;
}
static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
u8 *value)
{
int val = get_acpi(CM_ASL_WLAN);
if (val == 1 || val == 0)
*value = val;
else
return -EINVAL;
return 0;
}
static void eeepc_rfkill_hotplug(void)
{
struct pci_dev *dev;
struct pci_bus *bus;
bool blocked = eeepc_wlan_rfkill_blocked();
if (ehotk->wlan_rfkill)
rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
mutex_lock(&ehotk->hotplug_lock);
if (ehotk->hotplug_slot) {
bus = pci_find_bus(0, 1);
if (!bus) {
pr_warning("Unable to find PCI bus 1?\n");
goto out_unlock;
}
if (!blocked) {
dev = pci_get_slot(bus, 0);
if (dev) {
/* Device already present */
pci_dev_put(dev);
goto out_unlock;
}
dev = pci_scan_single_device(bus, 0);
if (dev) {
pci_bus_assign_resources(bus);
if (pci_bus_add_device(dev))
pr_err("Unable to hotplug wifi\n");
}
} else {
dev = pci_get_slot(bus, 0);
if (dev) {
pci_remove_bus_device(dev);
pci_dev_put(dev);
}
}
}
out_unlock:
mutex_unlock(&ehotk->hotplug_lock);
}
static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
{
if (event != ACPI_NOTIFY_BUS_CHECK)
return;
eeepc_rfkill_hotplug(); eeepc_rfkill_hotplug();
} }
static void eeepc_input_notify(int event)
{
static struct key_entry *key;
key = eepc_get_entry_by_scancode(event);
if (key) {
switch (key->type) {
case KE_KEY:
input_report_key(ehotk->inputdev, key->keycode,
1);
input_sync(ehotk->inputdev);
input_report_key(ehotk->inputdev, key->keycode,
0);
input_sync(ehotk->inputdev);
break;
}
}
}
static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
{
u16 count;
if (event > ACPI_MAX_SYS_NOTIFY)
return;
count = ehotk->event_count[event % 128]++;
acpi_bus_generate_proc_event(ehotk->device, event, count);
acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
dev_name(&ehotk->device->dev), event,
count);
if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
int old_brightness, new_brightness;
/* Update backlight device. */
old_brightness = eeepc_backlight_notify();
/* Convert brightness event to keypress (obsolescent hack). */
new_brightness = event - NOTIFY_BRN_MIN;
if (new_brightness < old_brightness) {
event = NOTIFY_BRN_MIN; /* brightness down */
} else if (new_brightness > old_brightness) {
event = NOTIFY_BRN_MAX; /* brightness up */
} else {
/*
* no change in brightness - already at min/max,
* event will be desired value (or else ignored).
*/
}
}
eeepc_input_notify(event);
}
static int eeepc_register_rfkill_notifier(char *node) static int eeepc_register_rfkill_notifier(char *node)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
...@@ -853,12 +584,31 @@ static void eeepc_unregister_rfkill_notifier(char *node) ...@@ -853,12 +584,31 @@ static void eeepc_unregister_rfkill_notifier(char *node)
} }
} }
static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
u8 *value)
{
int val = get_acpi(CM_ASL_WLAN);
if (val == 1 || val == 0)
*value = val;
else
return -EINVAL;
return 0;
}
static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
{ {
kfree(hotplug_slot->info); kfree(hotplug_slot->info);
kfree(hotplug_slot); kfree(hotplug_slot);
} }
static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
.owner = THIS_MODULE,
.get_adapter_status = eeepc_get_adapter_status,
.get_power_status = eeepc_get_adapter_status,
};
static int eeepc_setup_pci_hotplug(void) static int eeepc_setup_pci_hotplug(void)
{ {
int ret = -ENOMEM; int ret = -ENOMEM;
...@@ -901,6 +651,140 @@ error_slot: ...@@ -901,6 +651,140 @@ error_slot:
return ret; return ret;
} }
/*
* Rfkill devices
*/
static int eeepc_rfkill_set(void *data, bool blocked)
{
unsigned long asl = (unsigned long)data;
return set_acpi(asl, !blocked);
}
static const struct rfkill_ops eeepc_rfkill_ops = {
.set_block = eeepc_rfkill_set,
};
static int eeepc_new_rfkill(struct rfkill **rfkill,
const char *name, struct device *dev,
enum rfkill_type type, int cm)
{
int result;
result = get_acpi(cm);
if (result < 0)
return result;
*rfkill = rfkill_alloc(name, dev, type,
&eeepc_rfkill_ops, (void *)(unsigned long)cm);
if (!*rfkill)
return -EINVAL;
rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
result = rfkill_register(*rfkill);
if (result) {
rfkill_destroy(*rfkill);
*rfkill = NULL;
return result;
}
return 0;
}
static void eeepc_rfkill_exit(void)
{
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5");
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
if (ehotk->wlan_rfkill) {
rfkill_unregister(ehotk->wlan_rfkill);
rfkill_destroy(ehotk->wlan_rfkill);
ehotk->wlan_rfkill = NULL;
}
/*
* Refresh pci hotplug in case the rfkill state was changed after
* eeepc_unregister_rfkill_notifier()
*/
eeepc_rfkill_hotplug();
if (ehotk->hotplug_slot)
pci_hp_deregister(ehotk->hotplug_slot);
if (ehotk->bluetooth_rfkill) {
rfkill_unregister(ehotk->bluetooth_rfkill);
rfkill_destroy(ehotk->bluetooth_rfkill);
ehotk->bluetooth_rfkill = NULL;
}
if (ehotk->wwan3g_rfkill) {
rfkill_unregister(ehotk->wwan3g_rfkill);
rfkill_destroy(ehotk->wwan3g_rfkill);
ehotk->wwan3g_rfkill = NULL;
}
if (ehotk->wimax_rfkill) {
rfkill_unregister(ehotk->wimax_rfkill);
rfkill_destroy(ehotk->wimax_rfkill);
ehotk->wimax_rfkill = NULL;
}
}
static int eeepc_rfkill_init(struct device *dev)
{
int result = 0;
mutex_init(&ehotk->hotplug_lock);
result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
"eeepc-wlan", dev,
RFKILL_TYPE_WLAN, CM_ASL_WLAN);
if (result && result != -ENODEV)
goto exit;
result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
"eeepc-bluetooth", dev,
RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
if (result && result != -ENODEV)
goto exit;
result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
"eeepc-wwan3g", dev,
RFKILL_TYPE_WWAN, CM_ASL_3G);
if (result && result != -ENODEV)
goto exit;
result = eeepc_new_rfkill(&ehotk->wimax_rfkill,
"eeepc-wimax", dev,
RFKILL_TYPE_WIMAX, CM_ASL_WIMAX);
if (result && result != -ENODEV)
goto exit;
result = eeepc_setup_pci_hotplug();
/*
* If we get -EBUSY then something else is handling the PCI hotplug -
* don't fail in this case
*/
if (result == -EBUSY)
result = 0;
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5");
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
/*
* Refresh pci hotplug in case the rfkill state was changed during
* setup.
*/
eeepc_rfkill_hotplug();
exit:
if (result && result != -ENODEV)
eeepc_rfkill_exit();
return result;
}
/*
* Platform driver - hibernate/resume callbacks
*/
static int eeepc_hotk_thaw(struct device *device) static int eeepc_hotk_thaw(struct device *device)
{ {
if (ehotk->wlan_rfkill) { if (ehotk->wlan_rfkill) {
...@@ -937,9 +821,31 @@ static int eeepc_hotk_restore(struct device *device) ...@@ -937,9 +821,31 @@ static int eeepc_hotk_restore(struct device *device)
return 0; return 0;
} }
static struct dev_pm_ops eeepc_pm_ops = {
.thaw = eeepc_hotk_thaw,
.restore = eeepc_hotk_restore,
};
static struct platform_driver platform_driver = {
.driver = {
.name = EEEPC_HOTK_FILE,
.owner = THIS_MODULE,
.pm = &eeepc_pm_ops,
}
};
/* /*
* Hwmon * Hwmon device
*/ */
#define EEEPC_EC_SC00 0x61
#define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
#define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
#define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
#define EEEPC_EC_SFB0 0xD0
#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
static int eeepc_get_fan_pwm(void) static int eeepc_get_fan_pwm(void)
{ {
u8 value = 0; u8 value = 0;
...@@ -1043,57 +949,6 @@ static struct attribute_group hwmon_attribute_group = { ...@@ -1043,57 +949,6 @@ static struct attribute_group hwmon_attribute_group = {
.attrs = hwmon_attributes .attrs = hwmon_attributes
}; };
/*
* exit/init
*/
static void eeepc_backlight_exit(void)
{
if (eeepc_backlight_device)
backlight_device_unregister(eeepc_backlight_device);
eeepc_backlight_device = NULL;
}
static void eeepc_rfkill_exit(void)
{
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5");
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
if (ehotk->wlan_rfkill) {
rfkill_unregister(ehotk->wlan_rfkill);
rfkill_destroy(ehotk->wlan_rfkill);
ehotk->wlan_rfkill = NULL;
}
/*
* Refresh pci hotplug in case the rfkill state was changed after
* eeepc_unregister_rfkill_notifier()
*/
eeepc_rfkill_hotplug();
if (ehotk->hotplug_slot)
pci_hp_deregister(ehotk->hotplug_slot);
if (ehotk->bluetooth_rfkill) {
rfkill_unregister(ehotk->bluetooth_rfkill);
rfkill_destroy(ehotk->bluetooth_rfkill);
ehotk->bluetooth_rfkill = NULL;
}
if (ehotk->wwan3g_rfkill) {
rfkill_unregister(ehotk->wwan3g_rfkill);
rfkill_destroy(ehotk->wwan3g_rfkill);
ehotk->wwan3g_rfkill = NULL;
}
if (ehotk->wimax_rfkill) {
rfkill_unregister(ehotk->wimax_rfkill);
rfkill_destroy(ehotk->wimax_rfkill);
ehotk->wimax_rfkill = NULL;
}
}
static void eeepc_input_exit(void)
{
if (ehotk->inputdev)
input_unregister_device(ehotk->inputdev);
}
static void eeepc_hwmon_exit(void) static void eeepc_hwmon_exit(void)
{ {
struct device *hwmon; struct device *hwmon;
...@@ -1107,96 +962,56 @@ static void eeepc_hwmon_exit(void) ...@@ -1107,96 +962,56 @@ static void eeepc_hwmon_exit(void)
eeepc_hwmon_device = NULL; eeepc_hwmon_device = NULL;
} }
static void eeepc_led_exit(void) static int eeepc_hwmon_init(struct device *dev)
{
if (tpd_led.dev)
led_classdev_unregister(&tpd_led);
if (led_workqueue)
destroy_workqueue(led_workqueue);
}
static int eeepc_new_rfkill(struct rfkill **rfkill,
const char *name, struct device *dev,
enum rfkill_type type, int cm)
{ {
struct device *hwmon;
int result; int result;
result = get_acpi(cm); hwmon = hwmon_device_register(dev);
if (result < 0) if (IS_ERR(hwmon)) {
return result; pr_err("Could not register eeepc hwmon device\n");
eeepc_hwmon_device = NULL;
*rfkill = rfkill_alloc(name, dev, type, return PTR_ERR(hwmon);
&eeepc_rfkill_ops, (void *)(unsigned long)cm);
if (!*rfkill)
return -EINVAL;
rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
result = rfkill_register(*rfkill);
if (result) {
rfkill_destroy(*rfkill);
*rfkill = NULL;
return result;
} }
return 0; eeepc_hwmon_device = hwmon;
result = sysfs_create_group(&hwmon->kobj,
&hwmon_attribute_group);
if (result)
eeepc_hwmon_exit();
return result;
} }
/*
static int eeepc_rfkill_init(struct device *dev) * Backlight device
*/
static int read_brightness(struct backlight_device *bd)
{ {
int result = 0; return get_acpi(CM_ASL_PANELBRIGHT);
}
mutex_init(&ehotk->hotplug_lock);
result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
"eeepc-wlan", dev,
RFKILL_TYPE_WLAN, CM_ASL_WLAN);
if (result && result != -ENODEV)
goto exit;
result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
"eeepc-bluetooth", dev,
RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
if (result && result != -ENODEV)
goto exit;
result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
"eeepc-wwan3g", dev,
RFKILL_TYPE_WWAN, CM_ASL_3G);
if (result && result != -ENODEV) static int set_brightness(struct backlight_device *bd, int value)
goto exit; {
return set_acpi(CM_ASL_PANELBRIGHT, value);
}
result = eeepc_new_rfkill(&ehotk->wimax_rfkill, static int update_bl_status(struct backlight_device *bd)
"eeepc-wimax", dev, {
RFKILL_TYPE_WIMAX, CM_ASL_WIMAX); return set_brightness(bd, bd->props.brightness);
}
if (result && result != -ENODEV) static struct backlight_ops eeepcbl_ops = {
goto exit; .get_brightness = read_brightness,
.update_status = update_bl_status,
};
result = eeepc_setup_pci_hotplug(); static int eeepc_backlight_notify(void)
/* {
* If we get -EBUSY then something else is handling the PCI hotplug - struct backlight_device *bd = eeepc_backlight_device;
* don't fail in this case int old = bd->props.brightness;
*/
if (result == -EBUSY)
result = 0;
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5"); backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
/*
* Refresh pci hotplug in case the rfkill state was changed during
* setup.
*/
eeepc_rfkill_hotplug();
exit: return old;
if (result && result != -ENODEV)
eeepc_rfkill_exit();
return result;
} }
static int eeepc_backlight_init(struct device *dev) static int eeepc_backlight_init(struct device *dev)
...@@ -1218,23 +1033,89 @@ static int eeepc_backlight_init(struct device *dev) ...@@ -1218,23 +1033,89 @@ static int eeepc_backlight_init(struct device *dev)
return 0; return 0;
} }
static int eeepc_hwmon_init(struct device *dev) static void eeepc_backlight_exit(void)
{ {
struct device *hwmon; if (eeepc_backlight_device)
int result; backlight_device_unregister(eeepc_backlight_device);
eeepc_backlight_device = NULL;
}
hwmon = hwmon_device_register(dev);
if (IS_ERR(hwmon)) { /*
pr_err("Could not register eeepc hwmon device\n"); * Input device (i.e. hotkeys)
eeepc_hwmon_device = NULL; */
return PTR_ERR(hwmon); static struct key_entry *eeepc_get_entry_by_scancode(int code)
{
struct key_entry *key;
for (key = eeepc_keymap; key->type != KE_END; key++)
if (code == key->code)
return key;
return NULL;
}
static void eeepc_input_notify(int event)
{
static struct key_entry *key;
key = eeepc_get_entry_by_scancode(event);
if (key) {
switch (key->type) {
case KE_KEY:
input_report_key(ehotk->inputdev, key->keycode,
1);
input_sync(ehotk->inputdev);
input_report_key(ehotk->inputdev, key->keycode,
0);
input_sync(ehotk->inputdev);
break;
}
} }
eeepc_hwmon_device = hwmon; }
result = sysfs_create_group(&hwmon->kobj,
&hwmon_attribute_group); static struct key_entry *eepc_get_entry_by_keycode(int code)
if (result) {
eeepc_hwmon_exit(); struct key_entry *key;
return result;
for (key = eeepc_keymap; key->type != KE_END; key++)
if (code == key->keycode && key->type == KE_KEY)
return key;
return NULL;
}
static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
{
struct key_entry *key = eeepc_get_entry_by_scancode(scancode);
if (key && key->type == KE_KEY) {
*keycode = key->keycode;
return 0;
}
return -EINVAL;
}
static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
{
struct key_entry *key;
int old_keycode;
if (keycode < 0 || keycode > KEY_MAX)
return -EINVAL;
key = eeepc_get_entry_by_scancode(scancode);
if (key && key->type == KE_KEY) {
old_keycode = key->keycode;
key->keycode = keycode;
set_bit(keycode, dev->keybit);
if (!eepc_get_entry_by_keycode(old_keycode))
clear_bit(old_keycode, dev->keybit);
return 0;
}
return -EINVAL;
} }
static int eeepc_input_init(struct device *dev) static int eeepc_input_init(struct device *dev)
...@@ -1271,26 +1152,114 @@ static int eeepc_input_init(struct device *dev) ...@@ -1271,26 +1152,114 @@ static int eeepc_input_init(struct device *dev)
return 0; return 0;
} }
static int eeepc_led_init(struct device *dev) static void eeepc_input_exit(void)
{ {
int rv; if (ehotk->inputdev)
input_unregister_device(ehotk->inputdev);
}
if (get_acpi(CM_ASL_TPD) == -ENODEV) /*
return 0; * ACPI driver
*/
static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
{
u16 count;
led_workqueue = create_singlethread_workqueue("led_workqueue"); if (event > ACPI_MAX_SYS_NOTIFY)
if (!led_workqueue) return;
return -ENOMEM; count = ehotk->event_count[event % 128]++;
acpi_bus_generate_proc_event(ehotk->device, event, count);
acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
dev_name(&ehotk->device->dev), event,
count);
rv = led_classdev_register(dev, &tpd_led); if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
if (rv) { int old_brightness, new_brightness;
destroy_workqueue(led_workqueue);
return rv; /* Update backlight device. */
old_brightness = eeepc_backlight_notify();
/* Convert brightness event to keypress (obsolescent hack). */
new_brightness = event - NOTIFY_BRN_MIN;
if (new_brightness < old_brightness) {
event = NOTIFY_BRN_MIN; /* brightness down */
} else if (new_brightness > old_brightness) {
event = NOTIFY_BRN_MAX; /* brightness up */
} else {
/*
* no change in brightness - already at min/max,
* event will be desired value (or else ignored).
*/
}
}
eeepc_input_notify(event);
}
static void cmsg_quirk(int cm, const char *name)
{
int dummy;
/* Some BIOSes do not report cm although it is avaliable.
Check if cm_getv[cm] works and, if yes, assume cm should be set. */
if (!(ehotk->cm_supported & (1 << cm))
&& !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
pr_info("%s (%x) not reported by BIOS,"
" enabling anyway\n", name, 1 << cm);
ehotk->cm_supported |= 1 << cm;
}
}
static void cmsg_quirks(void)
{
cmsg_quirk(CM_ASL_LID, "LID");
cmsg_quirk(CM_ASL_TYPE, "TYPE");
cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
cmsg_quirk(CM_ASL_TPD, "TPD");
}
static int eeepc_hotk_init(void)
{
unsigned int init_flags;
int result;
result = acpi_bus_get_status(ehotk->device);
if (result)
return result;
if (!ehotk->device->status.present) {
pr_err("Hotkey device not present, aborting\n");
return -ENODEV;
}
init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
pr_notice("Hotkey init flags 0x%x\n", init_flags);
if (write_acpi_int(ehotk->handle, "INIT", init_flags)) {
pr_err("Hotkey initialization failed\n");
return -ENODEV;
}
/* get control methods supported */
if (read_acpi_int(ehotk->handle, "CMSG", &ehotk->cm_supported)) {
pr_err("Get control methods supported failed\n");
return -ENODEV;
} }
cmsg_quirks();
pr_info("Get control methods supported: 0x%x\n", ehotk->cm_supported);
return 0; return 0;
} }
static void __devinit eeepc_enable_camera(void)
{
/*
* If the following call to set_acpi() fails, it's because there's no
* camera so we can ignore the error.
*/
if (get_acpi(CM_ASL_CAMERA) == 0)
set_acpi(CM_ASL_CAMERA, 1);
}
static int __devinit eeepc_hotk_add(struct acpi_device *device) static int __devinit eeepc_hotk_add(struct acpi_device *device)
{ {
struct device *dev; struct device *dev;
...@@ -1371,6 +1340,27 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) ...@@ -1371,6 +1340,27 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
return 0; return 0;
} }
static const struct acpi_device_id eeepc_device_ids[] = {
{EEEPC_HOTK_HID, 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
static struct acpi_driver eeepc_hotk_driver = {
.name = EEEPC_HOTK_NAME,
.class = EEEPC_HOTK_CLASS,
.owner = THIS_MODULE,
.ids = eeepc_device_ids,
.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
.ops = {
.add = eeepc_hotk_add,
.remove = eeepc_hotk_remove,
.notify = eeepc_hotk_notify,
},
};
static int __init eeepc_laptop_init(void) static int __init eeepc_laptop_init(void)
{ {
int result; int result;
......
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