Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/acpi_support/acpi_ibm.c
/*- | /*- | ||||
* Copyright (c) 2004 Takanori Watanabe | * Copyright (c) 2004 Takanori Watanabe | ||||
* Copyright (c) 2005 Markus Brueffer <markus@FreeBSD.org> | * Copyright (c) 2005 Markus Brueffer <markus@FreeBSD.org> | ||||
* Copyright (c) 2018 Michael Gmelin <grembo@FreeBSD.org> | |||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
#define ACPI_IBM_METHOD_THINKLIGHT 7 | #define ACPI_IBM_METHOD_THINKLIGHT 7 | ||||
#define ACPI_IBM_METHOD_BLUETOOTH 8 | #define ACPI_IBM_METHOD_BLUETOOTH 8 | ||||
#define ACPI_IBM_METHOD_WLAN 9 | #define ACPI_IBM_METHOD_WLAN 9 | ||||
#define ACPI_IBM_METHOD_FANSPEED 10 | #define ACPI_IBM_METHOD_FANSPEED 10 | ||||
#define ACPI_IBM_METHOD_FANLEVEL 11 | #define ACPI_IBM_METHOD_FANLEVEL 11 | ||||
#define ACPI_IBM_METHOD_FANSTATUS 12 | #define ACPI_IBM_METHOD_FANSTATUS 12 | ||||
#define ACPI_IBM_METHOD_THERMAL 13 | #define ACPI_IBM_METHOD_THERMAL 13 | ||||
#define ACPI_IBM_METHOD_HANDLEREVENTS 14 | #define ACPI_IBM_METHOD_HANDLEREVENTS 14 | ||||
#define ACPI_IBM_METHOD_KBD_BACKLIGHT 15 | |||||
#define ACPI_IBM_METHOD_KBD_BL_LEDON 16 | |||||
#define ACPI_IBM_METHOD_KBD_BL_LEDOFF 17 | |||||
#define ACPI_IBM_METHOD_MICMUTE_LED 18 | |||||
/* Hotkeys/Buttons */ | /* Hotkeys/Buttons */ | ||||
#define IBM_RTC_HOTKEY1 0x64 | #define IBM_RTC_HOTKEY1 0x64 | ||||
#define IBM_RTC_MASK_HOME (1 << 0) | #define IBM_RTC_MASK_HOME (1 << 0) | ||||
#define IBM_RTC_MASK_SEARCH (1 << 1) | #define IBM_RTC_MASK_SEARCH (1 << 1) | ||||
#define IBM_RTC_MASK_MAIL (1 << 2) | #define IBM_RTC_MASK_MAIL (1 << 2) | ||||
#define IBM_RTC_MASK_WLAN (1 << 5) | #define IBM_RTC_MASK_WLAN (1 << 5) | ||||
#define IBM_RTC_HOTKEY2 0x65 | #define IBM_RTC_HOTKEY2 0x65 | ||||
Show All 39 Lines | |||||
#define IBM_NAME_THERMAL_UPDT "UPDT" | #define IBM_NAME_THERMAL_UPDT "UPDT" | ||||
#define IBM_NAME_EVENTS_STATUS_GET "DHKC" | #define IBM_NAME_EVENTS_STATUS_GET "DHKC" | ||||
#define IBM_NAME_EVENTS_MASK_GET "DHKN" | #define IBM_NAME_EVENTS_MASK_GET "DHKN" | ||||
#define IBM_NAME_EVENTS_STATUS_SET "MHKC" | #define IBM_NAME_EVENTS_STATUS_SET "MHKC" | ||||
#define IBM_NAME_EVENTS_MASK_SET "MHKM" | #define IBM_NAME_EVENTS_MASK_SET "MHKM" | ||||
#define IBM_NAME_EVENTS_GET "MHKP" | #define IBM_NAME_EVENTS_GET "MHKP" | ||||
#define IBM_NAME_EVENTS_AVAILMASK "MHKA" | #define IBM_NAME_EVENTS_AVAILMASK "MHKA" | ||||
#define IBM_NAME_EVENTS_VERSION "MHKV" | |||||
#define IBM_NAME_KBD_BACKLIGHT_GET "MLCG" | |||||
#define IBM_NAME_MASK_KBD_BL_SUPPORT (1 << 9) | |||||
#define IBM_NAME_MASK_KBD_BL_LEVEL 0x3 | |||||
#define IBM_NAME_KBD_BACKLIGHT_SET "MLCS" | |||||
#define IBM_NAME_MICMUTE_LED_SET "MMTS" | |||||
#define IBM_NAME_MICMUTE_LED_OFF 0x0 | |||||
#define IBM_NAME_MICMUTE_LED_ON 0x2 | |||||
#define IBM_NAME_MICMUTE_LED_BLINK 0x3 | |||||
/* Event Code */ | /* Event Code */ | ||||
#define IBM_EVENT_LCD_BACKLIGHT 0x03 | #define IBM_EVENT_LCD_BACKLIGHT 0x03 | ||||
#define IBM_EVENT_SUSPEND_TO_RAM 0x04 | #define IBM_EVENT_SUSPEND_TO_RAM 0x04 | ||||
#define IBM_EVENT_BLUETOOTH 0x05 | #define IBM_EVENT_BLUETOOTH 0x05 | ||||
#define IBM_EVENT_SCREEN_EXPAND 0x07 | #define IBM_EVENT_SCREEN_EXPAND 0x07 | ||||
#define IBM_EVENT_SUSPEND_TO_DISK 0x0c | #define IBM_EVENT_SUSPEND_TO_DISK 0x0c | ||||
#define IBM_EVENT_BRIGHTNESS_UP 0x10 | #define IBM_EVENT_BRIGHTNESS_UP 0x10 | ||||
#define IBM_EVENT_BRIGHTNESS_DOWN 0x11 | #define IBM_EVENT_BRIGHTNESS_DOWN 0x11 | ||||
Show All 24 Lines | struct acpi_ibm_softc { | ||||
/* Keylight commands and states */ | /* Keylight commands and states */ | ||||
ACPI_HANDLE light_handle; | ACPI_HANDLE light_handle; | ||||
int light_cmd_on; | int light_cmd_on; | ||||
int light_cmd_off; | int light_cmd_off; | ||||
int light_val; | int light_val; | ||||
int light_get_supported; | int light_get_supported; | ||||
int light_set_supported; | int light_set_supported; | ||||
/* led(4) interface */ | /* led(4) interface for thinklight */ | ||||
struct cdev *led_dev; | struct cdev *led_dev; | ||||
int led_busy; | int led_busy; | ||||
int led_state; | int led_state; | ||||
/* Keyboard backlight support */ | |||||
int kbd_backlight_supported; | |||||
int kbd_backlight_val; | |||||
/* led(4) interface for keyboard backlight */ | |||||
struct cdev *kbd_backlight_led_dev; | |||||
int kbd_backlight_led_busy; | |||||
int kbd_backlight_led_state; | |||||
int kbd_backlight_ledon; | |||||
int kbd_backlight_ledoff; | |||||
/* micmute led */ | |||||
int micmute_led_supported; | |||||
int micmute_led_val; | |||||
/* led(4) interface for micmute led */ | |||||
struct cdev *micmute_led_dev; | |||||
int micmute_led_busy; | |||||
int micmute_led_state; | |||||
int wlan_bt_flags; | int wlan_bt_flags; | ||||
int thermal_updt_supported; | int thermal_updt_supported; | ||||
unsigned int events_availmask; | unsigned int events_availmask; | ||||
unsigned int events_initialmask; | unsigned int events_initialmask; | ||||
int events_mask_supported; | int events_mask_supported; | ||||
int events_enable; | int events_enable; | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | int flag_rdonly; | ||||
.method = ACPI_IBM_METHOD_FANLEVEL, | .method = ACPI_IBM_METHOD_FANLEVEL, | ||||
.description = "Fan level", | .description = "Fan level", | ||||
}, | }, | ||||
{ | { | ||||
.name = "fan", | .name = "fan", | ||||
.method = ACPI_IBM_METHOD_FANSTATUS, | .method = ACPI_IBM_METHOD_FANSTATUS, | ||||
.description = "Fan enable", | .description = "Fan enable", | ||||
}, | }, | ||||
{ | |||||
.name = "kbd_backlight", | |||||
.method = ACPI_IBM_METHOD_KBD_BACKLIGHT, | |||||
.description = "Keyboard backlight level", | |||||
}, | |||||
{ | |||||
.name = "kbd_backlight_ledon", | |||||
.method = ACPI_IBM_METHOD_KBD_BL_LEDON, | |||||
.description = "Keyboard backlight LED on level", | |||||
}, | |||||
{ | |||||
.name = "kbd_backlight_ledoff", | |||||
.method = ACPI_IBM_METHOD_KBD_BL_LEDOFF, | |||||
.description = "Keyboard backlight LED off level", | |||||
}, | |||||
{ | |||||
.name = "micmute_led", | |||||
.method = ACPI_IBM_METHOD_MICMUTE_LED, | |||||
.description = "Control micmute LED", | |||||
}, | |||||
{ NULL, 0, NULL, 0 } | { NULL, 0, NULL, 0 } | ||||
}; | }; | ||||
/* | /* | ||||
* Per-model default list of event mask. | * Per-model default list of event mask. | ||||
*/ | */ | ||||
#define ACPI_IBM_HKEY_RFKILL_MASK (1 << 4) | #define ACPI_IBM_HKEY_RFKILL_MASK (1 << 4) | ||||
Show All 29 Lines | |||||
static int acpi_ibm_probe(device_t dev); | static int acpi_ibm_probe(device_t dev); | ||||
static int acpi_ibm_attach(device_t dev); | static int acpi_ibm_attach(device_t dev); | ||||
static int acpi_ibm_detach(device_t dev); | static int acpi_ibm_detach(device_t dev); | ||||
static int acpi_ibm_resume(device_t dev); | static int acpi_ibm_resume(device_t dev); | ||||
static void ibm_led(void *softc, int onoff); | static void ibm_led(void *softc, int onoff); | ||||
static void ibm_led_task(struct acpi_ibm_softc *sc, int pending __unused); | static void ibm_led_task(struct acpi_ibm_softc *sc, int pending __unused); | ||||
static void ibm_kbd_backlight_led(void *softc, int onoff); | |||||
static void ibm_kbd_backlight_led_task(struct acpi_ibm_softc *sc, | |||||
int pending __unused); | |||||
static void ibm_micmute_led(void *softc, int onoff); | |||||
static void ibm_micmute_led_task(struct acpi_ibm_softc *sc, int pending __unused); | |||||
static int acpi_ibm_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_ibm_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method); | static int acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method); | ||||
static int acpi_ibm_sysctl_get(struct acpi_ibm_softc *sc, int method); | static int acpi_ibm_sysctl_get(struct acpi_ibm_softc *sc, int method); | ||||
static int acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int val); | static int acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int val); | ||||
static int acpi_ibm_eventmask_set(struct acpi_ibm_softc *sc, int val); | static int acpi_ibm_eventmask_set(struct acpi_ibm_softc *sc, int val); | ||||
static int acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static int acpi_ibm_handlerevents_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_ibm_handlerevents_sysctl(SYSCTL_HANDLER_ARGS); | ||||
static void acpi_ibm_notify(ACPI_HANDLE h, UINT32 notify, void *context); | static void acpi_ibm_notify(ACPI_HANDLE h, UINT32 notify, void *context); | ||||
static int acpi_ibm_brightness_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_brightness_set(struct acpi_ibm_softc *sc, int arg); | ||||
static int acpi_ibm_bluetooth_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_bluetooth_set(struct acpi_ibm_softc *sc, int arg); | ||||
static int acpi_ibm_thinklight_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_thinklight_set(struct acpi_ibm_softc *sc, int arg); | ||||
static int acpi_ibm_volume_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_volume_set(struct acpi_ibm_softc *sc, int arg); | ||||
static int acpi_ibm_mute_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_mute_set(struct acpi_ibm_softc *sc, int arg); | ||||
static int acpi_ibm_kbd_backlight_set(struct acpi_ibm_softc *sc, int arg); | |||||
static int acpi_ibm_micmute_led_set(struct acpi_ibm_softc *sc, int arg); | |||||
static device_method_t acpi_ibm_methods[] = { | static device_method_t acpi_ibm_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, acpi_ibm_probe), | DEVMETHOD(device_probe, acpi_ibm_probe), | ||||
DEVMETHOD(device_attach, acpi_ibm_attach), | DEVMETHOD(device_attach, acpi_ibm_attach), | ||||
DEVMETHOD(device_detach, acpi_ibm_detach), | DEVMETHOD(device_detach, acpi_ibm_detach), | ||||
DEVMETHOD(device_resume, acpi_ibm_resume), | DEVMETHOD(device_resume, acpi_ibm_resume), | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t acpi_ibm_driver = { | static driver_t acpi_ibm_driver = { | ||||
"acpi_ibm", | "acpi_ibm", | ||||
acpi_ibm_methods, | acpi_ibm_methods, | ||||
sizeof(struct acpi_ibm_softc), | sizeof(struct acpi_ibm_softc), | ||||
}; | }; | ||||
static devclass_t acpi_ibm_devclass; | static devclass_t acpi_ibm_devclass; | ||||
DRIVER_MODULE(acpi_ibm, acpi, acpi_ibm_driver, acpi_ibm_devclass, | DRIVER_MODULE(acpi_ibm, acpi, acpi_ibm_driver, acpi_ibm_devclass, | ||||
0, 0); | 0, 0); | ||||
MODULE_DEPEND(acpi_ibm, acpi, 1, 1, 1); | MODULE_DEPEND(acpi_ibm, acpi, 1, 1, 1); | ||||
static char *ibm_ids[] = {"IBM0068", "LEN0068", NULL}; | static char *ibm_ids[] = {"IBM0068", "LEN0068", "LEN0268", NULL}; | ||||
static void | static void | ||||
ibm_led(void *softc, int onoff) | ibm_led(void *softc, int onoff) | ||||
{ | { | ||||
struct acpi_ibm_softc* sc = (struct acpi_ibm_softc*) softc; | struct acpi_ibm_softc* sc = (struct acpi_ibm_softc*) softc; | ||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | ||||
Show All 13 Lines | ibm_led_task(struct acpi_ibm_softc *sc, int pending __unused) | ||||
ACPI_SERIAL_BEGIN(ibm); | ACPI_SERIAL_BEGIN(ibm); | ||||
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_THINKLIGHT, sc->led_state); | acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_THINKLIGHT, sc->led_state); | ||||
ACPI_SERIAL_END(ibm); | ACPI_SERIAL_END(ibm); | ||||
sc->led_busy = 0; | sc->led_busy = 0; | ||||
} | } | ||||
static void | |||||
ibm_kbd_backlight_led(void *softc, int onoff) | |||||
{ | |||||
struct acpi_ibm_softc* sc = (struct acpi_ibm_softc*) softc; | |||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
if (sc->kbd_backlight_led_busy) | |||||
return; | |||||
sc->kbd_backlight_led_busy = 1; | |||||
sc->kbd_backlight_led_state = onoff; | |||||
AcpiOsExecute(OSL_NOTIFY_HANDLER, (void *)ibm_kbd_backlight_led_task, | |||||
sc); | |||||
} | |||||
static void | |||||
ibm_kbd_backlight_led_task(struct acpi_ibm_softc *sc, int pending __unused) | |||||
{ | |||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
ACPI_SERIAL_BEGIN(ibm); | |||||
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_KBD_BACKLIGHT, | |||||
sc->kbd_backlight_led_state ? | |||||
sc->kbd_backlight_ledon : sc->kbd_backlight_ledoff); | |||||
ACPI_SERIAL_END(ibm); | |||||
sc->kbd_backlight_led_busy = 0; | |||||
} | |||||
static void | |||||
ibm_micmute_led(void *softc, int onoff) | |||||
{ | |||||
struct acpi_ibm_softc* sc = (struct acpi_ibm_softc*) softc; | |||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
if (sc->micmute_led_busy) | |||||
return; | |||||
sc->micmute_led_busy = 1; | |||||
sc->micmute_led_state = onoff; | |||||
AcpiOsExecute(OSL_NOTIFY_HANDLER, (void *)ibm_micmute_led_task, sc); | |||||
} | |||||
static void | |||||
ibm_micmute_led_task(struct acpi_ibm_softc *sc, int pending __unused) | |||||
{ | |||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
ACPI_SERIAL_BEGIN(ibm); | |||||
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_MICMUTE_LED, | |||||
sc->micmute_led_state); | |||||
ACPI_SERIAL_END(ibm); | |||||
sc->micmute_led_busy = 0; | |||||
} | |||||
static int | static int | ||||
acpi_ibm_probe(device_t dev) | acpi_ibm_probe(device_t dev) | ||||
{ | { | ||||
if (acpi_disabled("ibm") || | if (acpi_disabled("ibm") || | ||||
ACPI_ID_PROBE(device_get_parent(dev), dev, ibm_ids) == NULL || | ACPI_ID_PROBE(device_get_parent(dev), dev, ibm_ids) == NULL || | ||||
device_get_unit(dev) != 0) | device_get_unit(dev) != 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
device_set_desc(dev, "IBM ThinkPad ACPI Extras"); | device_set_desc(dev, "IBM ThinkPad ACPI Extras"); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
acpi_ibm_attach(device_t dev) | acpi_ibm_attach(device_t dev) | ||||
{ | { | ||||
int i; | ACPI_OBJECT p, *bufp; | ||||
ACPI_OBJECT_LIST args; | |||||
ACPI_BUFFER buf; | |||||
int hkey_version; | |||||
struct acpi_ibm_softc *sc; | struct acpi_ibm_softc *sc; | ||||
char *maker, *product; | char *maker, *product; | ||||
devclass_t ec_devclass; | devclass_t ec_devclass; | ||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); | ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->dev = dev; | sc->dev = dev; | ||||
Show All 21 Lines | sc->events_mask_supported = ACPI_SUCCESS(acpi_GetInteger(sc->handle, | ||||
IBM_NAME_EVENTS_MASK_GET, &sc->events_initialmask)); | IBM_NAME_EVENTS_MASK_GET, &sc->events_initialmask)); | ||||
if (sc->events_mask_supported) { | if (sc->events_mask_supported) { | ||||
SYSCTL_ADD_UINT(sc->sysctl_ctx, | SYSCTL_ADD_UINT(sc->sysctl_ctx, | ||||
SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, | SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, | ||||
"initialmask", CTLFLAG_RD, | "initialmask", CTLFLAG_RD, | ||||
&sc->events_initialmask, 0, "Initial eventmask"); | &sc->events_initialmask, 0, "Initial eventmask"); | ||||
/* The availmask is the bitmask of supported events */ | /* | ||||
* The availmask is the bitmask of supported events, it's determined | |||||
* by calling MHKA. Old pre-0x100 versions of the hkey interface (MHKV) | |||||
emaste: s/MKHV/MHKV/ | |||||
* take no parameter to determine the hotkey mask. Newer models | |||||
* (post-2015, like T460, T470s, Carbon X1) take one integer parameter: | |||||
* 1: Retrieve availmask like before | |||||
* 2: Retrieve adaptive keyboard mask (currently not supported | |||||
* by this driver), only supported on models featuring | |||||
* the adaptive keyboard, otherwise returns 0 | |||||
*/ | |||||
if (ACPI_FAILURE(acpi_GetInteger(sc->handle, | if (ACPI_FAILURE(acpi_GetInteger(sc->handle, | ||||
IBM_NAME_EVENTS_VERSION, &hkey_version))) | |||||
hkey_version = 0x100; /* default to version 1 of the hkey interface */ | |||||
if ((hkey_version >> 8) < 2) { | |||||
if (ACPI_FAILURE(acpi_GetInteger(sc->handle, | |||||
IBM_NAME_EVENTS_AVAILMASK, &sc->events_availmask))) | IBM_NAME_EVENTS_AVAILMASK, &sc->events_availmask))) | ||||
sc->events_availmask = 0xffffffff; | sc->events_availmask = 0xffffffff; | ||||
} else { | |||||
p.Type = ACPI_TYPE_INTEGER; | |||||
p.Integer.Value = 1; | |||||
args.Count = 1; | |||||
args.Pointer = &p; | |||||
buf.Length = ACPI_ALLOCATE_BUFFER; | |||||
if (ACPI_FAILURE(AcpiEvaluateObjectTyped(sc->handle, | |||||
IBM_NAME_EVENTS_AVAILMASK, &args, &buf, | |||||
ACPI_TYPE_INTEGER))) | |||||
sc->events_availmask = 0xffffffff; | |||||
else { | |||||
bufp = buf.Pointer; | |||||
sc->events_availmask= bufp->Integer.Value; | |||||
AcpiOsFree(buf.Pointer); | |||||
} | |||||
} | |||||
SYSCTL_ADD_UINT(sc->sysctl_ctx, | SYSCTL_ADD_UINT(sc->sysctl_ctx, | ||||
SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, | SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, | ||||
"availmask", CTLFLAG_RD, | "availmask", CTLFLAG_RD, | ||||
&sc->events_availmask, 0, "Mask of supported events"); | &sc->events_availmask, 0, "Mask of supported events"); | ||||
} | } | ||||
/* Hook up proc nodes */ | /* Hook up proc nodes */ | ||||
Show All 38 Lines | acpi_ibm_attach(device_t dev) | ||||
AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, | AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, | ||||
acpi_ibm_notify, dev); | acpi_ibm_notify, dev); | ||||
/* Hook up light to led(4) */ | /* Hook up light to led(4) */ | ||||
if (sc->light_set_supported) | if (sc->light_set_supported) | ||||
sc->led_dev = led_create_state(ibm_led, sc, "thinklight", | sc->led_dev = led_create_state(ibm_led, sc, "thinklight", | ||||
(sc->light_val ? 1 : 0)); | (sc->light_val ? 1 : 0)); | ||||
/* Hook up keyboard backlight to led(4) */ | |||||
if (sc->kbd_backlight_supported) | |||||
sc->kbd_backlight_led_dev = led_create_state( | |||||
ibm_kbd_backlight_led, sc, "kbd_backlight", | |||||
(sc->kbd_backlight_val ? 1 : 0)); | |||||
if (sc->micmute_led_supported) | |||||
sc->micmute_led_dev = led_create_state(ibm_micmute_led, sc, | |||||
"micmute", 0); | |||||
/* Enable per-model events. */ | /* Enable per-model events. */ | ||||
maker = kern_getenv("smbios.system.maker"); | maker = kern_getenv("smbios.system.maker"); | ||||
product = kern_getenv("smbios.system.product"); | product = kern_getenv("smbios.system.product"); | ||||
if (maker == NULL || product == NULL) | if (maker == NULL || product == NULL) | ||||
goto nosmbios; | goto nosmbios; | ||||
for (i = 0; i < nitems(acpi_ibm_models); i++) { | for (int i = 0; i < nitems(acpi_ibm_models); i++) { | ||||
if (strcmp(maker, acpi_ibm_models[i].maker) == 0 && | if (strcmp(maker, acpi_ibm_models[i].maker) == 0 && | ||||
strcmp(product, acpi_ibm_models[i].product) == 0) { | strcmp(product, acpi_ibm_models[i].product) == 0) { | ||||
ACPI_SERIAL_BEGIN(ibm); | ACPI_SERIAL_BEGIN(ibm); | ||||
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, | acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, | ||||
acpi_ibm_models[i].eventmask); | acpi_ibm_models[i].eventmask); | ||||
ACPI_SERIAL_END(ibm); | ACPI_SERIAL_END(ibm); | ||||
} | } | ||||
} | } | ||||
Show All 24 Lines | acpi_ibm_detach(device_t dev) | ||||
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, sc->events_initialmask); | acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, sc->events_initialmask); | ||||
ACPI_SERIAL_END(ibm); | ACPI_SERIAL_END(ibm); | ||||
AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, acpi_ibm_notify); | AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, acpi_ibm_notify); | ||||
if (sc->led_dev != NULL) | if (sc->led_dev != NULL) | ||||
led_destroy(sc->led_dev); | led_destroy(sc->led_dev); | ||||
if (sc->kbd_backlight_led_dev != NULL) | |||||
led_destroy(sc->kbd_backlight_led_dev); | |||||
if (sc->micmute_led_dev != NULL) | |||||
led_destroy(sc->micmute_led_dev); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
acpi_ibm_resume(device_t dev) | acpi_ibm_resume(device_t dev) | ||||
{ | { | ||||
struct acpi_ibm_softc *sc = device_get_softc(dev); | struct acpi_ibm_softc *sc = device_get_softc(dev); | ||||
▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | acpi_ibm_sysctl_get(struct acpi_ibm_softc *sc, int method) | ||||
case ACPI_IBM_METHOD_FANSTATUS: | case ACPI_IBM_METHOD_FANSTATUS: | ||||
if (!sc->fan_handle) { | if (!sc->fan_handle) { | ||||
ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSTATUS, &val_ec, 1); | ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSTATUS, &val_ec, 1); | ||||
val = (val_ec & IBM_EC_MASK_FANSTATUS) == IBM_EC_MASK_FANSTATUS; | val = (val_ec & IBM_EC_MASK_FANSTATUS) == IBM_EC_MASK_FANSTATUS; | ||||
} | } | ||||
else | else | ||||
val = -1; | val = -1; | ||||
break; | break; | ||||
case ACPI_IBM_METHOD_KBD_BACKLIGHT: | |||||
if (sc->kbd_backlight_supported) | |||||
acpi_GetInteger(sc->handle, IBM_NAME_KBD_BACKLIGHT_GET, &val); | |||||
else | |||||
val = sc->kbd_backlight_val; | |||||
val &= IBM_NAME_MASK_KBD_BL_LEVEL; | |||||
break; | |||||
case ACPI_IBM_METHOD_KBD_BL_LEDON: | |||||
val = sc->kbd_backlight_ledon; | |||||
break; | |||||
case ACPI_IBM_METHOD_KBD_BL_LEDOFF: | |||||
val = sc->kbd_backlight_ledoff; | |||||
break; | |||||
case ACPI_IBM_METHOD_MICMUTE_LED: | |||||
val = sc->micmute_led_val; | |||||
break; | |||||
} | } | ||||
return (val); | return (val); | ||||
} | } | ||||
static int | static int | ||||
acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int arg) | acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int arg) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | case ACPI_IBM_METHOD_FANSTATUS: | ||||
if (!sc->fan_handle) { | if (!sc->fan_handle) { | ||||
/* Read the current fanstatus */ | /* Read the current fanstatus */ | ||||
ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSTATUS, &val_ec, 1); | ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSTATUS, &val_ec, 1); | ||||
return ACPI_EC_WRITE(sc->ec_dev, IBM_EC_FANSTATUS, | return ACPI_EC_WRITE(sc->ec_dev, IBM_EC_FANSTATUS, | ||||
(arg == 1) ? (val_ec | IBM_EC_MASK_FANSTATUS) : (val_ec & (~IBM_EC_MASK_FANSTATUS)), 1); | (arg == 1) ? (val_ec | IBM_EC_MASK_FANSTATUS) : (val_ec & (~IBM_EC_MASK_FANSTATUS)), 1); | ||||
} | } | ||||
break; | break; | ||||
case ACPI_IBM_METHOD_KBD_BACKLIGHT: | |||||
return acpi_ibm_kbd_backlight_set(sc, arg); | |||||
break; | |||||
case ACPI_IBM_METHOD_KBD_BL_LEDON: | |||||
if (arg < 0 || arg > 2) | |||||
return (EINVAL); | |||||
Done Inline Actionsextra whitespace here emaste: extra whitespace here | |||||
sc->kbd_backlight_ledon = arg; | |||||
break; | |||||
case ACPI_IBM_METHOD_KBD_BL_LEDOFF: | |||||
if (arg < 0 || arg > 2) | |||||
return (EINVAL); | |||||
Done Inline Actionsand here emaste: and here | |||||
sc->kbd_backlight_ledoff = arg; | |||||
break; | |||||
case ACPI_IBM_METHOD_MICMUTE_LED: | |||||
return acpi_ibm_micmute_led_set(sc, arg); | |||||
break; | |||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method) | acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | case ACPI_IBM_METHOD_THERMAL: | ||||
if (ACPI_SUCCESS(acpi_GetInteger(sc->ec_handle, IBM_NAME_THERMAL_GET, &dummy))) { | if (ACPI_SUCCESS(acpi_GetInteger(sc->ec_handle, IBM_NAME_THERMAL_GET, &dummy))) { | ||||
sc->thermal_updt_supported = ACPI_SUCCESS(acpi_GetInteger(sc->ec_handle, IBM_NAME_THERMAL_UPDT, &dummy)); | sc->thermal_updt_supported = ACPI_SUCCESS(acpi_GetInteger(sc->ec_handle, IBM_NAME_THERMAL_UPDT, &dummy)); | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
return (FALSE); | return (FALSE); | ||||
case ACPI_IBM_METHOD_HANDLEREVENTS: | case ACPI_IBM_METHOD_HANDLEREVENTS: | ||||
return (TRUE); | return (TRUE); | ||||
case ACPI_IBM_METHOD_KBD_BACKLIGHT: | |||||
if (ACPI_FAILURE(acpi_GetInteger(sc->handle, IBM_NAME_KBD_BACKLIGHT_GET, | |||||
&sc->kbd_backlight_val))) | |||||
sc->kbd_backlight_val = 0; | |||||
sc->kbd_backlight_supported = sc->kbd_backlight_val & | |||||
IBM_NAME_MASK_KBD_BL_SUPPORT; | |||||
sc->kbd_backlight_val &= IBM_NAME_MASK_KBD_BL_LEVEL; | |||||
if (sc->kbd_backlight_supported) | |||||
return (TRUE); | |||||
return (FALSE); | |||||
case ACPI_IBM_METHOD_KBD_BL_LEDON: | |||||
sc->kbd_backlight_ledon = 1; | |||||
if (sc->kbd_backlight_supported) | |||||
return (TRUE); | |||||
return (FALSE); | |||||
case ACPI_IBM_METHOD_KBD_BL_LEDOFF: | |||||
sc->kbd_backlight_ledoff = 0; | |||||
if (sc->kbd_backlight_supported) | |||||
return (TRUE); | |||||
return (FALSE); | |||||
case ACPI_IBM_METHOD_MICMUTE_LED: | |||||
sc->micmute_led_supported = ACPI_SUCCESS(acpi_SetInteger( | |||||
sc->handle, IBM_NAME_MICMUTE_LED_SET, | |||||
IBM_NAME_MICMUTE_LED_OFF)); | |||||
if (sc->micmute_led_supported) | |||||
return (TRUE); | |||||
return (FALSE); | |||||
} | } | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
static int | static int | ||||
acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS) | acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct acpi_ibm_softc *sc; | struct acpi_ibm_softc *sc; | ||||
▲ Show 20 Lines • Show All 283 Lines • ▼ Show 20 Lines | if (sc->cmos_handle) { | ||||
status = AcpiEvaluateObject(sc->cmos_handle, NULL, &Args, NULL); | status = AcpiEvaluateObject(sc->cmos_handle, NULL, &Args, NULL); | ||||
if (ACPI_FAILURE(status)) | if (ACPI_FAILURE(status)) | ||||
return (status); | return (status); | ||||
} | } | ||||
val_ec = (arg == 1) ? val_ec | IBM_EC_MASK_MUTE : | val_ec = (arg == 1) ? val_ec | IBM_EC_MASK_MUTE : | ||||
val_ec & (~IBM_EC_MASK_MUTE); | val_ec & (~IBM_EC_MASK_MUTE); | ||||
return ACPI_EC_WRITE(sc->ec_dev, IBM_EC_VOLUME, val_ec, 1); | return ACPI_EC_WRITE(sc->ec_dev, IBM_EC_VOLUME, val_ec, 1); | ||||
} | |||||
static int | |||||
acpi_ibm_kbd_backlight_set(struct acpi_ibm_softc *sc, int arg) | |||||
{ | |||||
ACPI_STATUS status; | |||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
ACPI_SERIAL_ASSERT(ibm); | |||||
if (arg < 0 || arg > 2) | |||||
return (EINVAL); | |||||
if (sc->kbd_backlight_supported) { | |||||
status = acpi_SetInteger(sc->handle, IBM_NAME_KBD_BACKLIGHT_SET, arg); | |||||
if (ACPI_SUCCESS(status)) | |||||
sc->kbd_backlight_val = arg; | |||||
return (status); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
acpi_ibm_micmute_led_set(struct acpi_ibm_softc *sc, int arg) | |||||
{ | |||||
int led_arg; | |||||
ACPI_STATUS status; | |||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
ACPI_SERIAL_ASSERT(ibm); | |||||
if (arg < 0 || arg > 2) | |||||
return (EINVAL); | |||||
switch (arg) { | |||||
case 0: | |||||
led_arg = IBM_NAME_MICMUTE_LED_OFF; | |||||
break; | |||||
case 1: | |||||
led_arg = IBM_NAME_MICMUTE_LED_ON; | |||||
break; | |||||
case 2: | |||||
led_arg = IBM_NAME_MICMUTE_LED_BLINK; | |||||
break; | |||||
} | |||||
if (sc->micmute_led_supported) { | |||||
status = acpi_SetInteger(sc->handle, IBM_NAME_MICMUTE_LED_SET, led_arg); | |||||
if (ACPI_SUCCESS(status)) | |||||
sc->micmute_led_val = arg; | |||||
return (status); | |||||
} | |||||
return (0); | |||||
} | } | ||||
static void | static void | ||||
acpi_ibm_eventhandler(struct acpi_ibm_softc *sc, int arg) | acpi_ibm_eventhandler(struct acpi_ibm_softc *sc, int arg) | ||||
{ | { | ||||
int val; | int val; | ||||
UINT64 val_ec; | UINT64 val_ec; | ||||
ACPI_STATUS status; | ACPI_STATUS status; | ||||
▲ Show 20 Lines • Show All 95 Lines • Show Last 20 Lines |
s/MKHV/MHKV/