From: Mathieu Bérard Date: Sat, 9 Sep 2006 00:06:15 +0000 (+0000) Subject: Merge branche/new-backend 129:HEAD to trunk X-Git-Url: https://gitweb.devoid-pointer.net/?a=commitdiff_plain;h=e55d20bd2bfcc54109222ecec3363928c18a88c4;p=omnibook.git Merge branche/new-backend 129:HEAD to trunk --- diff --git a/Makefile b/Makefile index e684e6d..0bbb255 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,6 @@ INSTDIR = extra #KSRC = /usr/src/linux KSRC = $(VMODDIR)/build KMODDIR = $(KSRC)/drivers/misc/omnibook -KINCDIR = $(KSRC)/include/linux KDOCDIR = $(KSRC)/Documentation/omnibook PWD = $(shell pwd) TODAY = $(shell date +%Y%m%d) @@ -42,19 +41,16 @@ RM = rm -f FIND = find endif -DEBUG = # -D OMNIBOOK_DEBUG -g -O0 +DEBUG = -D OMNIBOOK_DEBUG -g -O0 EXTRA_CFLAGS += -D OMNIBOOK_STANDALONE $(DEBUG) -EXTRA_LDFLAGS += $(src)/sections.lds +EXTRA_LDFLAGS += $(src)/sections.lds -OBJS = ac.o battery.o blank.o display.o dock.o \ - ec.o fan.o fan_policy.o init.o lcd.o hotkeys.o \ - temperature.o touchpad.o dump.o info.o \ - apmemu.o muteled.o compal.o - - -# All extra flags delt with automagically +OBJS = init.o ec.o compal.o acpi.o nbsmi.o \ + ac.o apmemu.o battery.o blank.o bluetooth.o display.o dock.o dump.o \ + fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o temperature.o \ + touchpad.o wireless.o obj-m += $(MODULE_NAME).o omnibook-objs := $(OBJS) @@ -63,11 +59,10 @@ all: $(MODULE_NAME).ko clean: make -C $(KSRC) M=$(PWD) clean - $(RM) *~ "#*#" .swp + $(RM) -r *~ "#*#" .swp $(RM) -r debian/omnibook-source *-stamp $(RM) -r Module.symvers Modules.symvers - (cd misc/obtest; $(RM) obtest *.o) - + (cd misc/obtest; $(RM) obtest *.o;) install: all # Removing module from locations used by previous versions @@ -95,13 +90,10 @@ $(MODULE_NAME).ko: kinstall: $(RM) -r $(KMODDIR) - $(RM) $(KINCDIR)/omnibook.h $(MKDIR) $(KMODDIR) - $(INSTALL) *.c sections.lds $(KMODDIR) - $(INSTALL) apmemu.h compat.h ec.h laptop.h $(KMODDIR) - $(INSTALL) omnibook.h $(KINCDIR) + $(INSTALL) *.h *.c sections.lds $(KMODDIR) $(MKDIR) $(KDOCDIR) - $(INSTALL) doc/README doc/README-OneTouch $(KDOCDIR) + $(INSTALL) doc/README doc/README-Hotkeys $(KDOCDIR) kpatch: kinstall (cd $(KSRC); patch -p1 < $(PWD)/misc/omnibook-integration.patch) diff --git a/ac.c b/ac.c index 2307eb1..cc3d0ae 100644 --- a/ac.c +++ b/ac.c @@ -15,42 +15,26 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif - #include "ec.h" -static const struct omnibook_io_operation ac_io_table[] = { - { XE3GF|TSP10|TSM30X, EC, XE3GF_ADP, 0, XE3GF_ADP_MASK}, - { XE3GC|AMILOD, EC, XE3GC_STA1, 0, XE3GC_ADP_MASK}, - { OB500|OB510|OB6000|OB6100|XE4500, EC, OB500_STA2, 0, OB500_ADP_MASK}, - { OB4150, EC, OB4150_ADP, 0, OB4150_ADP_MASK}, - { XE2, EC, XE2_STA1, 0, XE2_ADP_MASK}, - { 0,} -}; - -static struct omnibook_io_operation *ac_io; - -int omnibook_get_ac(void) +int omnibook_get_ac(struct omnibook_operation *io_op) { u8 ac; int retval; - retval = omnibook_io_read( ac_io, &ac); - if (!retval) - retval = ac ? 1 : 0; + retval = io_op->backend->byte_read(io_op, &ac); + if(!retval) + retval = !!ac; return retval; } -static int omnibook_ac_read(char *buffer) +static int omnibook_ac_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; int ac; - ac = omnibook_get_ac(); + ac = omnibook_get_ac(io_op); if (ac < 0) return ac; @@ -59,21 +43,28 @@ static int omnibook_ac_read(char *buffer) return len; } -static int omnibook_ac_init(void) -{ - ac_io = omnibook_io_match(ac_io_table); - return ac_io ? 0 : -ENODEV; -} +static struct omnibook_tbl ac_table[] __initdata = { + { XE3GF|TSP10|TSM30X, SIMPLE_BYTE(EC,XE3GF_ADP,XE3GF_ADP_MASK)}, + { XE3GC|AMILOD, SIMPLE_BYTE(EC,XE3GC_STA1,XE3GC_ADP_MASK)}, + { OB500|OB510|OB6000|OB6100|XE4500, SIMPLE_BYTE(EC,OB500_STA2,OB500_ADP_MASK)}, + { OB4150, SIMPLE_BYTE(EC,OB4150_ADP,OB4150_ADP_MASK)}, + { XE2, SIMPLE_BYTE(EC,XE2_STA1,XE2_ADP_MASK)}, + { 0,} +}; -static struct omnibook_feature __declared_feature ac_feature = { - .name = "ac", - .enabled = 1, - .read = omnibook_ac_read, - .init = omnibook_ac_init, - .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM30X, +struct omnibook_feature __declared_feature ac_driver = { + .name = "ac", +#ifdef CONFIG_OMNIBOOK_LEGACY + .enabled = 1, +#else + .enabled = 0, +#endif + .read = omnibook_ac_read, + .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM30X, + .tbl = ac_table, }; -module_param_named(ac, ac_feature.enabled, int, S_IRUGO); +module_param_named(ac, ac_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(ac, "Use 0 to disable, 1 to enable AC adapter status monitoring"); /* End of file */ diff --git a/acpi.c b/acpi.c new file mode 100644 index 0000000..9878536 --- /dev/null +++ b/acpi.c @@ -0,0 +1,232 @@ +/* + * acpi.c -- ACPI methods low-level access code for TSM30X class laptops + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Written by Mathieu Bérard , 2006 + * + */ + + + +#include "omnibook.h" +#include "ec.h" + +#ifdef CONFIG_ACPI + +#include + +/* + * ACPI backend masks and strings + */ + +#define EC_ACPI_DEVICE "\\_SB.PCI0.LPCB.EC0" + +#define GET_WIRELESS_METHOD "ANTR" +#define SET_WIRELESS_METHOD "ANTW" +#define WLEX_MASK 0x4 +#define WLAT_MASK 0x1 +#define BTEX_MASK 0x8 +#define BTAT_MASK 0x2 +#define KLSW_MASK 0x10 + +#define GET_DISPLAY_METHOD "DOSS" +#define SET_DISPLAY_METHOD "DOSW" +/* Display reading masks CADL = detected, CSTE = enabled */ +#define LCD_CADL 0x10 +#define CRT_CADL 0x20 +#define TVO_CADL 0x40 +#define LCD_CSTE 0x1 +#define CRT_CSTE 0x2 +#define TVO_CSTE 0x4 + +/* + * Probe for expected ACPI device + * FIXME we check only the ACPI device and not the associated methods + */ +static int omnibook_acpi_probe(const struct omnibook_operation *io_op) +{ + acpi_handle dev_handle; + int retval = 0; + + if(acpi_disabled) { + printk(O_ERR "ACPI is disabled: feature unavailable.\n"); + return -ENODEV; + } + + if(acpi_get_handle(NULL, EC_ACPI_DEVICE, &dev_handle) != AE_OK) { + printk(O_ERR "Can't get handle on ACPI EC device"); + return -ENODEV; + } + + acpi_backend.data = dev_handle; + + dprintk("ACPI probing was successfull\n"); + return retval; +} + +/* + * Execute an ACPI method which return either integer or nothing + * (acpi_evaluate_object wrapper) + */ +static int omnibook_acpi_execute(char *method, const int *param, int *result) +{ + + struct acpi_object_list args_list; + struct acpi_buffer buff; + union acpi_object arg, out_objs[1]; + + if(!(acpi_backend.data)) { + dprintk("no handle on EC ACPI device"); + return -ENODEV; + } + + if(param) { + args_list.count = 1; + args_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = *param; + } else + args_list.count = 0; + + buff.length = sizeof(out_objs); + buff.pointer = out_objs; + + if(acpi_evaluate_object(acpi_backend.data, method, &args_list, &buff) != AE_OK) { + printk(O_ERR "ACPI method execution failed\n"); + return -EIO; + } + + if(!result) /* We don't care what the method returned here */ + return 0; + + if(out_objs[0].type != ACPI_TYPE_INTEGER) { + printk(O_ERR "ACPI method result is not a number\n"); + return -EINVAL; + } + + *result = out_objs[0].integer.value; + return 0; +} + +static int omnibook_acpi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval = 0; + int raw_state; + + if ((retval = omnibook_acpi_execute(GET_WIRELESS_METHOD,0,&raw_state))) + return retval; + + + *state = ( raw_state & WLEX_MASK ) ? WIFI_EX : 0; + *state |= ( raw_state & WLAT_MASK ) ? WIFI_STA : 0; + *state |= ( raw_state & KLSW_MASK ) ? KILLSWITCH : 0; + *state |= ( raw_state & BTEX_MASK ) ? BT_EX : 0; + *state |= ( raw_state & BTAT_MASK ) ? BT_STA : 0; + + return retval; +} + +static int omnibook_acpi_set_wireless(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval = 0; + int raw_state; + + raw_state = state & WIFI_STA; /* bit 0 */ + raw_state |= (state & BT_STA) << 0x1; /* bit 1 */ + + dprintk("set_wireless raw_state: %x\n", raw_state); + + if ((retval = omnibook_acpi_execute(SET_WIRELESS_METHOD,&raw_state,NULL))) + return retval; + + return retval; +} + +static int omnibook_acpi_get_display(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval = 0; + int raw_state = 0; + + retval = omnibook_acpi_execute(GET_DISPLAY_METHOD, 0 , &raw_state); + if(retval < 0) + return retval; + + /* Backend specific to backend-neutral conversion */ + *state = ( raw_state & LCD_CSTE) ? DISPLAY_LCD_ON : 0; + *state |= ( raw_state & CRT_CSTE) ? DISPLAY_CRT_ON : 0; + *state |= ( raw_state & TVO_CSTE) ? DISPLAY_TVO_ON : 0; + + *state |= ( raw_state & LCD_CADL) ? DISPLAY_LCD_DET : 0; + *state |= ( raw_state & CRT_CADL) ? DISPLAY_CRT_DET : 0; + *state |= ( raw_state & TVO_CADL) ? DISPLAY_TVO_DET : 0; + + + return DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON| + DISPLAY_LCD_DET|DISPLAY_CRT_DET|DISPLAY_TVO_DET; +} + +static const unsigned int acpi_display_mode_list[] = { + DISPLAY_LCD_ON, + DISPLAY_CRT_ON, + DISPLAY_LCD_ON|DISPLAY_CRT_ON, + DISPLAY_TVO_ON, + DISPLAY_LCD_ON|DISPLAY_TVO_ON, + DISPLAY_CRT_ON|DISPLAY_TVO_ON, + DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON, +}; + +static int omnibook_acpi_set_display(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval = 0; + int i, matched; + + for(i = 0; i < ARRAY_SIZE(acpi_display_mode_list); i++) { + if(acpi_display_mode_list[i] == state) { + matched = i + 1; /* raw state is array row number + 1 */ + break; + } + } + if(!matched) { + printk("Display mode %x is unsupported.\n", state); + return -EINVAL; + } + + retval = omnibook_acpi_execute(SET_DISPLAY_METHOD, &matched, NULL ); + if(retval < 0) + return retval; + + return DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON; +} + +struct omnibook_backend acpi_backend = { + .name = "acpi", + .init = omnibook_acpi_probe, + .aerial_get = omnibook_acpi_get_wireless, + .aerial_set = omnibook_acpi_set_wireless, + .display_get = omnibook_acpi_get_display, + .display_set = omnibook_acpi_set_display, +}; + +#else /* CONFIG_ACPI */ + +/* dummy backend for non-ACPI systems */ +static int _fail_probe(const struct omnibook_operation *io_op) +{ + return -ENODEV; +} + +struct omnibook_backend acpi_backend = { + .name = "acpi", + .init = _fail_probe, +}; + +#endif /* CONFIG_ACPI */ diff --git a/apmemu.c b/apmemu.c index 192fca5..832959b 100644 --- a/apmemu.c +++ b/apmemu.c @@ -15,12 +15,9 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif +#ifdef CONFIG_OMNIBOOK_LEGACY #ifdef CONFIG_APM #include @@ -68,7 +65,9 @@ -1: Unknown 8) min = minutes; sec = seconds */ -static int omnibook_apmemu_read(char *buffer) +extern struct omnibook_feature ac_driver; + +static int omnibook_apmemu_read(char *buffer, struct omnibook_operation *io_op) { int retval; int len = 0; @@ -100,7 +99,10 @@ static int omnibook_apmemu_read(char *buffer) "?" }; - ac = omnibook_get_ac(); +/* + * FIXME: Broken, how do we know ac and battery are in a usable state ? + */ + ac = omnibook_get_ac(ac_driver.io_op); apm.ac = (ac) ? APMEMU_AC_ONLINE : APMEMU_AC_OFFLINE; /* Asking for Battery 0 as APM does */ retval = omnibook_get_battery_status(0, &battstat); @@ -137,7 +139,7 @@ static int omnibook_apmemu_read(char *buffer) return len; } -static int omnibook_apmemu_init(void) +static int __init omnibook_apmemu_init(struct omnibook_operation *io_op) { #ifdef CONFIG_APM if (!apm_info.disabled) { @@ -148,21 +150,18 @@ static int omnibook_apmemu_init(void) return 0; } -static struct omnibook_feature __declared_feature apmemu_feature = { +static struct omnibook_feature __declared_feature apmemu_driver = { .name = "apmemu", .proc_entry = "apm", /* create /proc/apm */ -#ifdef CONFIG_OMNIBOOK_APMEMU .enabled = 1, -#else - .enabled = 0, -#endif .read = omnibook_apmemu_read, .init = omnibook_apmemu_init, .ectypes = XE3GF|XE3GC|TSP10, }; -module_param_named(apmemu, apmemu_feature.enabled, int, S_IRUGO); +module_param_named(apmemu, apmemu_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(apmemu, "Use 0 to disable, 1 to enable /proc/apm emulation"); +#endif /* CONFIG_OMNIBOOK_LEGACY */ /* End of file */ diff --git a/battery.c b/battery.c index 3c352fb..f9eb553 100644 --- a/battery.c +++ b/battery.c @@ -15,25 +15,21 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif #include "ec.h" -static int omnibook_ec_read16(u8 addr, u16 * data) +static int ec_read16(u8 addr, u16 * data) { int retval; u8 high; u8 low; u16 result; - retval = omnibook_ec_read(addr, &low); + retval = legacy_ec_read(addr, &low); if (retval) return retval; - retval = omnibook_ec_read(addr + 0x01, &high); + retval = legacy_ec_read(addr + 0x01, &high); result = ((high << 8) + low); *data = result; return retval; @@ -55,7 +51,7 @@ static int omnibook_battery_present(int num) if (num >= 2) return -EINVAL; - if ((retval = omnibook_ec_read(XE3GF_BAL, &bat))) + if ((retval = legacy_ec_read(XE3GF_BAL, &bat))) return retval; mask = XE3GF_BAL0_MASK; for (i = 0; i < num; i++) @@ -67,7 +63,7 @@ static int omnibook_battery_present(int num) } else if (omnibook_ectype & (XE3GC|AMILOD) ) { if (num >= 2) return -EINVAL; - if ((retval = omnibook_ec_read(XE3GC_BAT, &bat))) + if ((retval = legacy_ec_read(XE3GC_BAT, &bat))) return retval; mask = XE3GC_BAT0_MASK; for (i = 0; i < num; i++) @@ -104,19 +100,19 @@ static int omnibook_get_battery_info(int num, return retval; if (retval) { if ((retval = - omnibook_ec_read(XE3GF_BTY0 + (offset * num), + legacy_ec_read(XE3GF_BTY0 + (offset * num), &(*battinfo).type))) return retval; if ((retval = - omnibook_ec_read16(XE3GF_BSN0 + (offset * num), + ec_read16(XE3GF_BSN0 + (offset * num), &(*battinfo).sn))) return retval; if ((retval = - omnibook_ec_read16(XE3GF_BDV0 + (offset * num), + ec_read16(XE3GF_BDV0 + (offset * num), &(*battinfo).dv))) return retval; if ((retval = - omnibook_ec_read16(XE3GF_BDC0 + (offset * num), + ec_read16(XE3GF_BDC0 + (offset * num), &(*battinfo).dc))) return retval; @@ -134,15 +130,15 @@ static int omnibook_get_battery_info(int num, return retval; if (retval) { if ((retval = - omnibook_ec_read16(XE3GC_BDV0 + (offset * num), + ec_read16(XE3GC_BDV0 + (offset * num), &(*battinfo).dv))) return retval; if ((retval = - omnibook_ec_read16(XE3GC_BDC0 + (offset * num), + ec_read16(XE3GC_BDC0 + (offset * num), &(*battinfo).dc))) return retval; if ((retval = - omnibook_ec_read(XE3GC_BTY0 + (offset * num), + legacy_ec_read(XE3GC_BTY0 + (offset * num), &(*battinfo).type))) return retval; @@ -161,15 +157,15 @@ static int omnibook_get_battery_info(int num, return retval; if (retval) { if ((retval = - omnibook_ec_read16(AMILOD_BDV0 + (offset * num), + ec_read16(AMILOD_BDV0 + (offset * num), &(*battinfo).dv))) return retval; if ((retval = - omnibook_ec_read16(AMILOD_BDC0 + (offset * num), + ec_read16(AMILOD_BDC0 + (offset * num), &(*battinfo).dc))) return retval; if ((retval = - omnibook_ec_read(AMILOD_BTY0 + (offset * num), + legacy_ec_read(AMILOD_BTY0 + (offset * num), &(*battinfo).type))) return retval; @@ -243,22 +239,22 @@ int omnibook_get_battery_status(int num, return retval; if (retval) { if ((retval = - omnibook_ec_read(XE3GF_BST0 + (offset * num), &status))) + legacy_ec_read(XE3GF_BST0 + (offset * num), &status))) return retval; if ((retval = - omnibook_ec_read16(XE3GF_BRC0 + (offset * num), + ec_read16(XE3GF_BRC0 + (offset * num), &(*battstat).rc))) return retval; if ((retval = - omnibook_ec_read16(XE3GF_BPV0 + (offset * num), + ec_read16(XE3GF_BPV0 + (offset * num), &(*battstat).pv))) return retval; if ((retval = - omnibook_ec_read16(XE3GF_BFC0 + (offset * num), + ec_read16(XE3GF_BFC0 + (offset * num), &(*battstat).lc))) return retval; if ((retval = - omnibook_ec_read(XE3GF_GAU0 + (offset * num), + legacy_ec_read(XE3GF_GAU0 + (offset * num), &(*battstat).gauge))) return retval; @@ -287,18 +283,18 @@ int omnibook_get_battery_status(int num, return retval; if (retval) { if ((retval = - omnibook_ec_read(XE3GC_BST0 + (offset * num), &status))) + legacy_ec_read(XE3GC_BST0 + (offset * num), &status))) return retval; if ((retval = - omnibook_ec_read16(XE3GC_BRC0 + (offset * num), + ec_read16(XE3GC_BRC0 + (offset * num), &(*battstat).rc))) return retval; if ((retval = - omnibook_ec_read16(XE3GC_BPV0 + (offset * num), + ec_read16(XE3GC_BPV0 + (offset * num), &(*battstat).pv))) return retval; if ((retval = - omnibook_ec_read16(XE3GC_BDC0 + (offset * num), &dc))) + ec_read16(XE3GC_BDC0 + (offset * num), &dc))) return retval; if (status & XE3GC_BST_MASK_CRT) @@ -329,18 +325,18 @@ int omnibook_get_battery_status(int num, return retval; if (retval) { if ((retval = - omnibook_ec_read(AMILOD_BST0 + (offset * num), &status))) + legacy_ec_read(AMILOD_BST0 + (offset * num), &status))) return retval; if ((retval = - omnibook_ec_read16(AMILOD_BRC0 + (offset * num), + ec_read16(AMILOD_BRC0 + (offset * num), &(*battstat).rc))) return retval; if ((retval = - omnibook_ec_read16(AMILOD_BPV0 + (offset * num), + ec_read16(AMILOD_BPV0 + (offset * num), &(*battstat).pv))) return retval; if ((retval = - omnibook_ec_read16(AMILOD_BDC0 + (offset * num), &dc))) + ec_read16(AMILOD_BDC0 + (offset * num), &dc))) return retval; if (status & AMILOD_BST_MASK_CRT) @@ -368,27 +364,27 @@ int omnibook_get_battery_status(int num, } else if (omnibook_ectype & (OB500|OB510) ) { switch (num) { case 0: - if ((retval = omnibook_ec_read(OB500_BT1S, &status))) + if ((retval = legacy_ec_read(OB500_BT1S, &status))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT1C, &(*battstat).rc))) + if ((retval = ec_read16(OB500_BT1C, &(*battstat).rc))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT1V, &(*battstat).pv))) + if ((retval = ec_read16(OB500_BT1V, &(*battstat).pv))) return retval; break; case 1: - if ((retval = omnibook_ec_read(OB500_BT2S, &status))) + if ((retval = legacy_ec_read(OB500_BT2S, &status))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT2C, &(*battstat).rc))) + if ((retval = ec_read16(OB500_BT2C, &(*battstat).rc))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT2V, &(*battstat).pv))) + if ((retval = ec_read16(OB500_BT2V, &(*battstat).pv))) return retval; break; case 2: - if ((retval = omnibook_ec_read(OB500_BT3S, &status))) + if ((retval = legacy_ec_read(OB500_BT3S, &status))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT3C, &(*battstat).rc))) + if ((retval = ec_read16(OB500_BT3C, &(*battstat).rc))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT3V, &(*battstat).pv))) + if ((retval = ec_read16(OB500_BT3V, &(*battstat).pv))) return retval; break; default: @@ -413,19 +409,19 @@ int omnibook_get_battery_status(int num, } else if (omnibook_ectype & (OB6000|OB6100|XE4500) ) { switch (num) { case 0: - if ((retval = omnibook_ec_read(OB500_BT1S, &status))) + if ((retval = legacy_ec_read(OB500_BT1S, &status))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT1C, &(*battstat).rc))) + if ((retval = ec_read16(OB500_BT1C, &(*battstat).rc))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT1V, &(*battstat).pv))) + if ((retval = ec_read16(OB500_BT1V, &(*battstat).pv))) return retval; break; case 1: - if ((retval = omnibook_ec_read(OB500_BT3S, &status))) + if ((retval = legacy_ec_read(OB500_BT3S, &status))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT3C, &(*battstat).rc))) + if ((retval = ec_read16(OB500_BT3C, &(*battstat).rc))) return retval; - if ((retval = omnibook_ec_read16(OB500_BT3V, &(*battstat).pv))) + if ((retval = ec_read16(OB500_BT3V, &(*battstat).pv))) return retval; break; default: @@ -448,7 +444,7 @@ int omnibook_get_battery_status(int num, return 0; } -static int omnibook_battery_read(char *buffer) +static int omnibook_battery_read(char *buffer,struct omnibook_operation *io_op) { char *statustr; char *typestr; @@ -553,14 +549,18 @@ static int omnibook_battery_read(char *buffer) return len; } -static struct omnibook_feature __declared_feature battery_feature = { +static struct omnibook_feature __declared_feature battery_driver = { .name = "battery", +#ifdef CONFIG_OMNIBOOK_LEGACY .enabled = 1, +#else + .enabled = 0, +#endif .read = omnibook_battery_read, - .ectypes = XE3GF|XE3GC|AMILOD|TSP10, /* FIXME: OB500|OB6000|OB6100|XE4500 */ + .ectypes = XE3GF|XE3GC|AMILOD|TSP10|TSM30X, /* FIXME: OB500|OB6000|OB6100|XE4500 */ }; -module_param_named(battery, battery_feature.enabled, int, S_IRUGO); +module_param_named(battery, battery_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(battery, "Use 0 to disable, 1 to enable battery status monitoring"); /* End of file */ diff --git a/blank.c b/blank.c index b4d31f5..cf81501 100644 --- a/blank.c +++ b/blank.c @@ -15,65 +15,40 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif #include #include "ec.h" +static struct omnibook_feature blank_driver; + static int omnibook_console_blank_enabled = 0; extern int (*console_blank_hook) (int); +/* + * We would need an io_op parameter,but we are bound to the crapy + * console_blank_hook here + */ + int omnibook_lcd_blank(int blank) { int retval = 0; - u8 cmd; - /* - * XE3GF - * XE3GC - * AMILOD - * TSP10 - * TSM30X - * TSM40 - */ - if (omnibook_ectype & (XE3GF|XE3GC|AMILOD|TSP10|TSM30X|TSM40) ) { - cmd = blank ? OMNIBOOK_KBC_CMD_LCD_OFF : OMNIBOOK_KBC_CMD_LCD_ON; - if ((retval = - omnibook_kbc_command(OMNIBOOK_KBC_CONTROL_CMD, cmd))) - return retval; - /* - * OB500 - * OB6000 - * XE2 - */ - } else if (omnibook_ectype & (OB500|OB6000|XE2) ) { - cmd = inb(OB500_GPO1); - cmd = blank ? cmd & ~OB500_BKLT_MASK : cmd | OB500_BKLT_MASK; - outb(cmd, OB500_GPO1); - /* - * OB510 - * OB61000 - */ - } else if (omnibook_ectype & (OB510|OB6100) ) { - cmd = inb(OB510_GPO2); - cmd = blank ? cmd & ~OB510_BKLT_MASK : cmd | OB510_BKLT_MASK; - outb(cmd, OB510_GPO2); - /* - * UNKNOWN - */ - } else { - printk(O_INFO + + if ( blank_driver.io_op->backend == PIO ) + omnibook_apply_write_mask(blank_driver.io_op, blank); + else if ( blank_driver.io_op->backend == KBC ) + omnibook_toggle(blank_driver.io_op, blank); + else { + printk(O_WARN "LCD console blanking is unsupported on this machine.\n"); retval = -ENODEV; } + return retval; } -static int omnibook_console_blank_enable(void) +static int console_blank_register_hook(void) { if (omnibook_console_blank_enabled == 0) { if (console_blank_hook == NULL) { @@ -90,7 +65,7 @@ static int omnibook_console_blank_enable(void) return 0; } -static int omnibook_console_blank_disable(void) +static int console_blank_unregister_hook(void) { if (console_blank_hook == omnibook_lcd_blank) { console_blank_hook = NULL; @@ -106,7 +81,7 @@ static int omnibook_console_blank_disable(void) return 0; } -static int omnibook_console_blank_read(char *buffer) +static int omnibook_console_blank_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; @@ -117,17 +92,17 @@ static int omnibook_console_blank_read(char *buffer) return len; } -static int omnibook_console_blank_write(char *buffer) +static int omnibook_console_blank_write(char *buffer,struct omnibook_operation *io_op) { int retval; switch (*buffer) { case '0': - if ((retval = omnibook_console_blank_disable())) + if ((retval = console_blank_unregister_hook())) return retval; break; case '1': - if ((retval = omnibook_console_blank_enable())) + if ((retval = console_blank_register_hook())) return retval; break; default: @@ -136,23 +111,25 @@ static int omnibook_console_blank_write(char *buffer) return 0; } -static int omnibook_console_blank_init(void) +static int __init omnibook_console_blank_init(struct omnibook_operation *io_op) { - - int retval; - - if ((retval = omnibook_console_blank_enable())) - return retval; - - return 0; + return console_blank_register_hook(); } -static void omnibook_console_blank_cleanup(void) +static void __exit omnibook_console_blank_cleanup(struct omnibook_operation *io_op) { - omnibook_console_blank_disable(); + console_blank_unregister_hook(); } -static struct omnibook_feature __declared_feature blank_feature = { +static struct omnibook_tbl blank_table[] __initdata = { + { XE3GF|XE3GC|AMILOD|TSP10|TSM30X|TSM40, COMMAND(KBC,OMNIBOOK_KBC_CMD_LCD_OFF,OMNIBOOK_KBC_CMD_LCD_ON)}, + { OB500|OB6000|XE2, { PIO, OB500_GPO1, OB500_GPO1, 0, -OB500_BKLT_MASK, OB500_BKLT_MASK}}, + { OB510|OB6100, { PIO, OB510_GPO2, OB510_GPO2, 0, -OB510_BKLT_MASK, OB510_BKLT_MASK}}, + { 0,} +}; + + +static struct omnibook_feature __declared_feature blank_driver = { .name = "blank", .enabled = 1, .read = omnibook_console_blank_read, @@ -160,8 +137,9 @@ static struct omnibook_feature __declared_feature blank_feature = { .init = omnibook_console_blank_init, .exit = omnibook_console_blank_cleanup, .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE2|AMILOD|TSP10|TSM30X|TSM40, + .tbl = blank_table, }; -module_param_named(blank, blank_feature.enabled, int, S_IRUGO); +module_param_named(blank, blank_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(blank, "Use 0 to disable, 1 to enable lcd console blanking"); /* End of file */ diff --git a/bluetooth.c b/bluetooth.c new file mode 100644 index 0000000..66c8ea1 --- /dev/null +++ b/bluetooth.c @@ -0,0 +1,95 @@ +/* + * wireless.c Bluetooth feature + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Written by Mathieu Bérard , 2006 + * + */ + +#include "omnibook.h" +#include "ec.h" + +static int omnibook_bt_read(char *buffer,struct omnibook_operation *io_op) +{ + int len = 0; + int retval; + unsigned int state; + + if((retval = io_op->backend->aerial_get(io_op, &state))) + return retval; + + len += sprintf(buffer + len,"Bluetooth adapter is %s", (state & BT_EX) ? "present" : "absent"); + if (state & BT_EX) + len += sprintf(buffer + len," and %s", (state & BT_STA) ? "enabled" : "disabled"); + len += sprintf(buffer + len,".\n"); + return len; + +} + +static int omnibook_bt_write(char *buffer,struct omnibook_operation *io_op) +{ + int retval = 0; + unsigned int state; + + if((retval = io_op->backend->aerial_get(io_op, &state))) + return retval; + + if(*buffer == '0' ) + state &= ~BT_STA; + else if (*buffer == '1' ) + state |= BT_STA; + else + return -EINVAL; + + if((retval = io_op->backend->aerial_set(io_op, state))) + return retval; + + return retval; +} + +static struct omnibook_feature bt_feature; + +static int __init omnibook_bt_init(struct omnibook_operation *io_op) +{ + int retval = 0; + unsigned int state; + +/* + * Refuse enabling/disabling a non-existent device + */ + + if((retval = io_op->backend->aerial_get(io_op, &state))) + return retval; + + if(!(state & BT_EX)) + bt_feature.write = NULL; + + return retval; +} + +/* + * To avoid duplication the table is in wireless.c + */ +extern struct omnibook_tbl wireless_table[]; + +static struct omnibook_feature __declared_feature bt_driver = { + .name = "bluetooth", + .enabled = 1, + .read = omnibook_bt_read, + .write = omnibook_bt_write, + .init = omnibook_bt_init, + .ectypes = TSM30X|TSM40, + .tbl = wireless_table, +}; + +module_param_named(bluetooth, bt_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(bluetooth, "Use 0 to disable, 1 to enable bluetooth adapter control"); diff --git a/compal.c b/compal.c index 8b6df94..985feaf 100644 --- a/compal.c +++ b/compal.c @@ -15,20 +15,32 @@ * */ -#ifdef OMNIBOOK_STANDALONE + #include "omnibook.h" -#else -#include -#endif #include #include #include +#include -#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) #include +#define DEFINE_MUTEX(lock) DECLARE_MUTEX(lock) +#define mutex_lock(lock) down(lock) +#define mutex_lock_interruptible(lock) down_interruptible(lock) +#define mutex_unlock(lock) up(lock) +#else +#include +#endif + +#include #include "ec.h" +/* + * ATI's IXP PCI-LPC bridge + */ +#define PCI_DEVICE_ID_ATI_SB400 0x4377 + /* * PCI Config space regiser * Laptop with Intel ICH Chipset @@ -57,8 +69,7 @@ /* * We protect access to the Command/Data/Index interface by a Mutex */ -static DECLARE_MUTEX(compal_sem); - +static DEFINE_MUTEX(compal_lock); /* * Private data of this backend @@ -68,13 +79,15 @@ static struct pci_dev *lpc_bridge; /* Southbridge chip ISA bridge/LPC interface static u32 ioport_base; /* PIO base adress */ static union { u16 word; u32 dword; } pci_reg_state; /* Saved state of register in PCI config spave */ +static int already_failed = 0; /* Backend init already failed at leat once */ /* * Possible list of supported southbridges * Here mostly to implement a more or less clean PCI probing * Works only because of previous DMI probing. + * Shared with nbsmi backend */ -static const struct pci_device_id lpc_bridge_table[] = { +const struct pci_device_id lpc_bridge_table[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, @@ -92,7 +105,8 @@ static const struct pci_device_id lpc_bridge_table[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - { 0, }, /* End of list */ + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SB400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + { 0, }, /* End of list */ }; @@ -103,10 +117,9 @@ static const struct pci_device_id lpc_bridge_table[] = { * Write a 2-bytes wide command to the COMMAND ports * Read the result in the DATA port */ -static unsigned char lowlevel_read(unsigned int command) +static unsigned char lowlevel_read(u16 command) { unsigned char data; - outb((command & 0xff00) >> 8 ,ioport_base + PIO_PORT_COMMAND1); outb(command & 0x00ff ,ioport_base + PIO_PORT_COMMAND2); data = inb(ioport_base + PIO_PORT_DATA); @@ -118,7 +131,7 @@ static unsigned char lowlevel_read(unsigned int command) * Write a 2-bytes wide command to the COMMAND ports * Write the result in the DATA port */ -static void lowlevel_write(unsigned int command, unsigned int data) +static void lowlevel_write(u16 command, u8 data) { outb((command & 0xff00) >> 8 ,ioport_base + PIO_PORT_COMMAND1); outb(command & 0x00ff,ioport_base + PIO_PORT_COMMAND2); @@ -258,15 +271,12 @@ static void clear_cdimode_pci(void) } } - - - /* * Try to init the backend * This function can be called blindly as it use a kref * to check if the init sequence was already done. */ -int omnibook_cdimode_init(void) +static int omnibook_cdimode_init(const struct omnibook_operation *io_op) { int retval = 0; int i; @@ -275,9 +285,14 @@ int omnibook_cdimode_init(void) if(!(omnibook_ectype & TSM30X)) return -ENODEV; + if(already_failed) { + dprintk("CDI backend init already failed, skipping.\n"); + return -ENODEV; + } + if(!refcount) { /* Fist use of the backend */ - down(&compal_sem); + mutex_lock(&compal_lock); dprintk("Try to init cdimode\n"); refcount = kmalloc(sizeof(struct kref),GFP_KERNEL); if(!refcount) { @@ -313,7 +328,7 @@ int omnibook_cdimode_init(void) BUG(); } - if(!request_region(ioport_base ,4 ,"omnibook")) { + if(!request_region(ioport_base ,4 ,OMNIBOOK_MODULE_NAME)) { printk(O_ERR "Request I/O region error\n"); retval = -ENODEV; goto error2; @@ -345,20 +360,26 @@ error2: lpc_bridge = NULL; error1: kfree(refcount); + refcount = NULL; + already_failed = 1; out: - up(&compal_sem); + mutex_unlock(&compal_lock); return retval; } -void cdimode_free(struct kref *ref) +static void cdimode_free(struct kref *ref) { + mutex_lock(&compal_lock); dprintk("Cdimode not used anymore: disposing\n"); pci_dev_put(lpc_bridge); release_region(ioport_base,4); kfree(refcount); + lpc_bridge = NULL; + refcount = NULL; + mutex_unlock(&compal_lock); } -void omnibook_cdimode_exit(void) +static void omnibook_cdimode_exit(const struct omnibook_operation *io_op) { /* ectypes other than TSM30X have no business with this backend */ BUG_ON(!(omnibook_ectype & TSM30X)); @@ -370,31 +391,32 @@ void omnibook_cdimode_exit(void) * Read EC index and write result to value * 'EC index' here is unrelated to an index in the EC registers */ -int omnibook_cdimode_read(unsigned int index, u8 *value) +static int omnibook_cdimode_read(const struct omnibook_operation *io_op, u8 *value) { int retval = 0; - BUG_ON(!(omnibook_ectype & TSM30X)); - if(!lpc_bridge) return -ENODEV; - if(down_interruptible(&compal_sem)) + if(mutex_lock_interruptible(&compal_lock)) return -ERESTARTSYS; retval = enable_cdimode(); if(retval) goto out; - retval = send_ec_cmd(0xfbfd,index); + retval = send_ec_cmd(0xfbfd,(unsigned int) io_op->read_addr); if(retval) goto error; retval = read_ec_cmd(0xfbfe,value); + if(io_op->read_mask) + *value &= io_op->read_mask; + error: clear_cdimode(); out: clear_cdimode_pci(); - up(&compal_sem); + mutex_unlock(&compal_lock); return retval; } @@ -402,35 +424,64 @@ out: * Write value * 'EC index' here is unrelated to an index in the EC registers */ -int omnibook_cdimode_write(unsigned int index, u8 value) +static int omnibook_cdimode_write(const struct omnibook_operation *io_op, u8 value) { int retval = 0; - BUG_ON(!(omnibook_ectype & TSM30X)); - if(!lpc_bridge) return -ENODEV; - if(down_interruptible(&compal_sem)) + if(mutex_lock_interruptible(&compal_lock)) return -ERESTARTSYS; retval = enable_cdimode(); if(retval) goto out; - retval = send_ec_cmd(0xfbfd,index); + retval = send_ec_cmd(0xfbfd,(unsigned int) io_op->write_addr); if(retval) goto error; retval = send_ec_cmd(0xfbfe,value); - error: clear_cdimode(); out: clear_cdimode_pci(); - up(&compal_sem); + mutex_unlock(&compal_lock); return retval; } +/* + * Fn+foo and multimedia hotkeys handling + */ +static int omnibook_cdimode_hotkeys(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval; + struct omnibook_operation hotkeys_op; + + /* Fn+foo handling */ + hotkeys_op.backend = CDI; + hotkeys_op.write_addr = TSM70_FN_INDEX; + hotkeys_op.on_mask = TSM70_FN_ENABLE; + hotkeys_op.off_mask = TSM70_FN_DISABLE; + retval = omnibook_toggle(&hotkeys_op, !!(state & HKEY_FN) ); + if(retval < 0) + return retval; + + /* Multimedia keys handling */ + if(state & HKEY_MULTIMEDIA) { + hotkeys_op.write_addr = TSM70_HOTKEYS_INDEX; + retval = omnibook_cdimode_write(&hotkeys_op, TSM70_HOTKEYS_ENABLE); + } else { + /* FIXME: quirk use kbc backend */ + retval = kbc_backend.byte_write(NULL,OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE); + } + + if(retval < 0) + return retval; + else + return HKEY_MULTIMEDIA|HKEY_FN; +} + /* Scan index space, this hard locks my machine */ #if 0 static int compal_scan(char *buffer) @@ -453,4 +504,13 @@ static int compal_scan(char *buffer) } #endif +struct omnibook_backend compal_backend = { + .name = "compal", + .init = omnibook_cdimode_init, + .exit = omnibook_cdimode_exit, + .byte_read = omnibook_cdimode_read, + .byte_write = omnibook_cdimode_write, + .hotkeys_set = omnibook_cdimode_hotkeys, +}; + /* End of file */ diff --git a/compat.h b/compat.h index fdb1805..29ba628 100644 --- a/compat.h +++ b/compat.h @@ -76,4 +76,7 @@ void inline *kzalloc(size_t size, int flags) } #endif + + + /* End of file */ diff --git a/debian/control b/debian/control index 66023d3..279bcdd 100644 --- a/debian/control +++ b/debian/control @@ -14,7 +14,7 @@ Description: Source for the omnibook driver Pavilions, Toshiba Satellites and some other laptops manufactured by Compal Electronics, Inc as ODM. . - This module is only compatible with Linux kernels >= 2.6.8 + This module is only compatible with Linux kernels >= 2.6.9 . Kernel source is required to compile this module. . diff --git a/display.c b/display.c index 99281c7..8f3b50b 100644 --- a/display.c +++ b/display.c @@ -1,5 +1,5 @@ /* - * display.c -- external display related functions + * display.c -- External display (LCD,VGA,TV-OUT) feature * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -15,54 +15,90 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif - #include "ec.h" -static const struct omnibook_io_operation display_io_table[] = { - { XE3GF|TSP10|TSM30X|TSM40, EC, XE3GF_STA1, 0, XE3GF_SHDD_MASK}, - { XE3GC, EC, XE3GC_STA1, 0, XE3GC_CRTI_MASK}, - { OB500|OB510|OB6000|OB6100|XE4500, EC, OB500_STA1, 0, OB500_CRTS_MASK}, - { OB4150, EC, OB4150_STA2, 0, OB4150_CRST_MASK}, - { 0,} +static const char display_name[][16] = { + "Internal LCD", + "External VGA", + "External TV-OUT", + "External DVI", }; -static struct omnibook_io_operation *display_io; - -static int omnibook_display_read(char *buffer) +static int omnibook_display_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; int retval; - u8 sta; - - if ((retval = omnibook_io_read(display_io, &sta))) + unsigned int sta, en_mask, det_mask; + + retval = io_op->backend->display_get(io_op, &sta); + if ( retval < 0) return retval; - len += - sprintf(buffer + len, "External display is %s\n", - (sta) ? "present" : "not present"); + + for( en_mask = DISPLAY_LCD_ON ; en_mask <= DISPLAY_DVI_ON; en_mask = en_mask << 1) { + det_mask = en_mask << 4; /* see display masks in omnibook.h */ + if( !( retval & en_mask ) && !( retval & det_mask ) ) + continue; /* not supported */ + len += sprintf(buffer + len, "%s:", + display_name[ ffs(en_mask) - 1 ]); + if( retval & det_mask ) + len += sprintf(buffer + len, " display %s", + ( sta & det_mask ) ? "present" : "absent"); + if( retval & en_mask ) + len += sprintf(buffer + len, " port %s", + ( sta & en_mask ) ? "enabled" : "disabled"); + len += sprintf(buffer + len, "\n"); + } + return len; } -static int omnibook_display_init(void) +static int omnibook_display_write(char *buffer,struct omnibook_operation *io_op) { - display_io = omnibook_io_match(display_io_table); - return display_io ? 0 : -ENODEV; -} + int retval; + unsigned int state; + char *endp; + state = simple_strtoul(buffer, &endp, 16); + if (endp == buffer) + return -EINVAL; + else + retval = io_op->backend->display_set(io_op, state); + + return retval; +} -static struct omnibook_feature __declared_feature display_feature = { +static struct omnibook_feature display_driver; + +static int __init omnibook_display_init(struct omnibook_operation *io_op) +{ + /* Disable file writing if unsuported by backend */ + if(!io_op->backend->display_set) + display_driver.write = NULL; + return 0; +} + + +static struct omnibook_tbl display_table[] __initdata = { + { TSM30X, {ACPI, }}, + { XE3GF|TSP10|TSM30X|TSM40, SIMPLE_BYTE(EC,XE3GF_STA1,XE3GF_SHDD_MASK)}, + { XE3GC, SIMPLE_BYTE(EC,XE3GC_STA1,XE3GC_CRTI_MASK)}, + { OB500|OB510|OB6000|OB6100|XE4500, SIMPLE_BYTE(EC,OB500_STA1,OB500_CRTS_MASK)}, + { OB4150, SIMPLE_BYTE(EC,OB4150_STA2,OB4150_CRST_MASK)}, + { 0,} +}; + +static struct omnibook_feature __declared_feature display_driver = { .name = "display", .enabled = 1, - .read = omnibook_display_read, .init = omnibook_display_init, + .read = omnibook_display_read, + .write = omnibook_display_write, .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|TSP10|TSM30X|TSM40, + .tbl = display_table, }; -module_param_named(display, display_feature.enabled, int, S_IRUGO); +module_param_named(display, display_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(display, "Use 0 to disable, 1 to enable display status handling"); /* End of file */ diff --git a/doc/ChangeLog b/doc/ChangeLog index 11140e9..a799ee4 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -13,6 +13,58 @@ Changelog file for omnibook package: DMI entry. This is restoring pre-20060806 behaviour. Invert M40 vs. M40X entry position. +2.20060816 Mathieu Bérard +* Merge from the new-backend branch: Add new backend code + (in compal.c) used with TSM30X class laptops: + Used for lcd access + Used for hotkeys support: now most Fn+key generate a scancode, + as well as the wifi kill switch. + Warning: tested only on TSM40X an TSM70 laptops. +* Create omnibook_io_operation struct and omnibook_io_{read/write} + funtions to simplify implementation of some simple features. + Used with ac display dock and led features. +* Rename onetouch feature to "hotkeys" which is a vendor neutral name. +* The minimal required kernel version is now 2.6.9 (kref API) +* Convert semaphore to mutex with fallback for pre 2.6.16 kernel +* Kill CONFIG_OMNIBOOK_APMEMU and introduce OMNIBOOK_LEGACY: + pre-ACPI features now depends on it. + Default enabling of ac and battery features also + depends on it. It is _disabled_ by default. +* Introduce ACPI methods execution backend: TSM70 needs it + for Display and Wifi/Bluetooth features +* Expand display and hotkeys features +* Introduce experimental NbSmi backend for TSM40. It is + based on technical documentation provided by Toshiba. + Thanks Toshiba ! +* Kill unused omnibook_mem_read/write function for mmio + access +* Cleanup in blank.c fan.c temperature.c +* Unbreak Pio backend: use request/release_region +* Introduce bluetooth and wifi frontend features : they allow + adapter state querry and control (existence probing, wifi + kill switch probing and adapter enabling/disabling). + Supported by TSM30X and TSM40 +* Introduce omnibook_backend struct as a uniform way of + communication between backend and frontend, this + kill omnibook_io_{read/write} and friends. +* Modify ombibook_feature struct to incorporate pointers + to an omnibook_table table and to a omnibook_operation + struct which is picked-up from the ectype matching + omnibook_table entry upon feature initialization +* Add muteled resume handler +* Add touchpad handling for TSM30X +* Add proper display handling for TSM30X +* Change all features struct name from foo_feature to + foo_driver to kept modpost section mismatch detection + silent. Put tbl, init and exit entries to their relevant + sections. + +2.200608017 Mathieu Bérard +* Fix bug in omnibook_io_match +* Fix DMI handling behaviour: we stop on the FIRST matched + DMI entry. This is restoring pre-20060806 behaviour. + Invert M40 vs. M40X entry position. + 2.20060816 Mathieu Bérard * Merge from the new-backend branch: Add new backend code (in compal.c) used with TSM30X class laptops: diff --git a/doc/README b/doc/README index 265ebbf..1b6b129 100644 --- a/doc/README +++ b/doc/README @@ -9,23 +9,20 @@ wants to be a framework to extend the Linux support for HP OmniBook and Pavilion, Toshiba Satellite, Acer Aspire and Compal ACL00 laptops manufactured by Compal Electronics, Inc as ODM. -There is a similar project for Toshiba Satellite laptops wich supports -some HP OmniBooks too at ftp://ftp.poupinou.org/tosh_3000/. - How does it work? ----------------- - Some features of HP OmniBooks can be controlled via the keyboard control + Some features of sup pored laptops can be controlled via the keyboard control and data registers. Commands and parameters were discovered by Pavel Mihaylov. Some other features available via /proc/omnibook/* provided by the - Embedded Controller or other I/O registers of your laptop. Informations - comes from DSDT ACPI table of HP OmniBook XE3 GF dissassembled by Ducrot + Embedded Controller or other I/O registers of your laptop. Information + comes from DSDT ACPI table of HP OmniBook XE3 GF disassembled by Ducrot Bruno and others or discovered by me. Note: You do not have to enable APM or ACPI to use this driver. - All supported models seems to have same keyboard and embedded controller: + Most supported models seems to have same keyboard and embedded controller: National Semiconductor PC87570 Keyboard and ACPI Embedded Controller or compatible, but with different types of firmware. See http://www.national.com/pf/PC/PC87570.html for more info. @@ -85,18 +82,19 @@ How does it work? Toshiba Satellite M35X Toshiba Satellite M70 13. Toshiba Satellite M40 + 14. Toshiba Satellite A105 If your model is not listed above you may try to load the module. If it - have same DMI identification strigs as a supported machine it may works + have same DMI identification strings as a supported machine it may works out of the box. Please report it. Only the /proc/omnibook/dmi and /proc/omnibook/version are working when you load the module on an unsupported machine. In this case you may load the module with ectype parameter to force using a certain EC firmware type or see how became you machine supported at the - end of this documet. + end of this document. -What is working? ----------------- +What are the provided features? +------------------------------- 1. Enabling hotkey buttons. See README-Hotkeys for details. You may enable or disable it via /proc/omnibook/hotkeys. There is a power management handler for reenabling the buttons at resume @@ -126,39 +124,74 @@ What is working? 8. Display status monitoring /proc/omnibook/display. - 9. LCD brightness setting and monitoring. + 9. LCD brightness setting and monitoring via /proc/omnibook/lcd. + +10. Docking station/port replicator support via /proc/omnibook/dock. -10. Docking station/port replicator support. +11. Wifi and Bluetooth adapters monitoring and control via + /proc/omnibook/bluetooth and /proc/omnibook/wifi How to use? ----------- 1. The hotkeys are enabled by default by this module. To disable it use the command: - echo 0 > /proc/omnibook/hotkeys + $ echo off > /proc/omnibook/hotkeys The command - echo 1 > /proc/omnibook/hotkeys + $ echo on > /proc/omnibook/hotkeys enables hotkeys buttons. + + Reading to that same file allow you to read the state of the hotkeys: + + $ cat /proc/omnibook/hotkeys + Multimedia hotkeys are enabled. + Fn hotkeys are enabled. + + The items displayed depends on your laptop model. + Some Toshiba models support advanced hotkeys control. Alternatively to and + on/off command you can fine-tune the behavior of your keyboard's hotkeys + writing an hexadecimal number to the hotkeys files. + To enable a specific hotkeys feature, add its code to this hexadecimal + number. The feature/code table follow: + + Onetouch buttons: 0x1 + Multimedia hotkeys are: 0x2 + Fn hotkeys are: 0x4 + Stick key is: 0x8 + Press Fn twice to lock: 0x10 + Dock events: 0x20 + Fn + F5 hotkey: 0x40 + + That is to enable multimedia hotkeys only do: + $cat 0x2 > /proc/omnibook/hotkeys + To enable Fn hotkeys and Dock events only do: + $cat 0x24 > /proc/omnibook/hotkeys (as 0x24 = 0x4 + 0x20) + + Finally 'off' is equivalent to 0x0, and 'on' to 0x67 that is + Onetouch, Multimedia, Fn, Dock and Fn+F5. + + Unsupported features won't be displayed in /proc/omnibook/hotkeys and writing + their corresponding codes won't have any effect. 2. Console (LCD display) blanking is enabled by this module on machines that support it. It only enabled if another blanking solution (e.g. CONFIG_APM_DISPLAY_BLANK) is not used. To disable this behavior use command: - echo 0 > /proc/omnibook/blank + $ echo 0 > /proc/omnibook/blank To enable this behavior use command: - echo 1 > /proc/omnibook/blank + $ echo 1 > /proc/omnibook/blank 3. To see the battery status use - cat /proc/omnibook/battery + $ cat /proc/omnibook/battery - command. It produce similar output to that you can see below. + It produce similar output to that you can see below. Battery: 0 Type: Li-Ion @@ -175,10 +208,9 @@ How to use? apm is enabled, but via this file you can monitor your battery independently from apm code. - Current ACPI driver reports some bad value about battery at least on my - machine: + ACPI driver might reports some bad value about battery: - $cat /proc/acpi/battery/BAT1/info + $ cat /proc/acpi/battery/BAT1/info present: yes design capacity: 5400 mAh last full capacity: 5400 mAh @@ -194,10 +226,11 @@ How to use? OEM info: HP This is because the methods used for batteries in the DSDT do - not give correct informations. If you want to fix it you may + not give correct information. If you want to fix it you may have to change methods in the DSDT. See http://www.intel.com/technology/iapc/acpi/bios_override.htm for details. + ACPI support for battery should be good on recent laptops. 4. The /proc/omnibook/fan file provides information about fan status: @@ -211,11 +244,11 @@ How to use? On certain machines you may turn on the fan by - echo 1 > /proc/omnibook/fan + $ echo 1 > /proc/omnibook/fan command and turn off by issuing - echo 0 > /proc/omnibook/fan + $ echo 0 > /proc/omnibook/fan command. @@ -255,11 +288,11 @@ How to use? To set the fan policy write the proper values into the /proc/omnibook/fan_policy file. Each value must be greater than or - equal to the prvious one. You do not have to write all values. + equal to the previous one. You do not have to write all values. For example you may set fan off temperature to 60 C, fan on temperature to 70 C and fan level 2 temperature to 80 C by - echo 60 70 80 > /proc/omnibook/fan_policy + $ echo 60 70 80 > /proc/omnibook/fan_policy command. A zero value (echo 0 > /proc/omnibook/fan_policy) sets the default @@ -277,22 +310,22 @@ How to use? 5. The touchpad is enabled by default by the BIOS. To disable it use the command: - echo 0 > /proc/omnibook/touchpad + $ echo 0 > /proc/omnibook/touchpad The command - echo 1 > /proc/omnibook/touchpad + $ echo 1 > /proc/omnibook/touchpad enables the touchpad. 6. The /proc/apm emulation is disabled by default on all machines. You have - to enable it explicit way by module parameter apmemu. To enable it use: + to enable it explicit using the module parameter apmemu. To enable it use: - insmod omnibook apmemu=1 + $ insmod omnibook apmemu=1 You can enable it by /etc/modules.conf with the following entry: - options omnibook apmemu=1 + $ options omnibook apmemu=1 If your kernel have APM support, but the /proc/apm reports buggy values, you may boot your kernel without apm support, and try to load omnibook @@ -303,7 +336,7 @@ How to use? 7. To see the AC adapter status use - cat /proc/omnibook/ac + $ cat /proc/omnibook/ac command. It produce similar output to that you can see below. @@ -317,46 +350,59 @@ How to use? 8. To see the display status use - cat /proc/omnibook/display + $ cat /proc/omnibook/display - command. It produce similar output to that you can see below. + The displayed output depends on your laptop model, as an example: $ cat /proc/omnibook/display - External display is not present + Internal LCD: display present port enabled + External VGA: display absent port disabled + External TV-OUT: display absent port disabled - Or if you have external monitor installed: + If you are adventuresome, and if your laptop model support it, + you can try to enable or disable a specific display port. + To do that, write an hexadecimal number to the display file, adding the + code of display ports you want to enable, the others will be disabled: - $ cat /proc/omnibook/display - External display is present + Internal LCD panel: 0x1 + External VGA port: 0x2 + External TV port: 0x4 + + For example to enable the LCD panel and the TV-OUT port only, you have to + write 0x1 + 0x4 = 0x5: + + $ echo 0x5 > /proc/omnibook/display + + It may or may not work, or even crash your X server. Proceed with caution. 9. To see the LCD brightness use - cat /proc/omnibook/lcd + $ cat /proc/omnibook/lcd - command. It produce similar output to that you can see below. + It produce similar output to that you can see below. $ cat /proc/omnibook/lcd - LCD brightness: 7 + LCD brightness: 5 (max value: 7) - To set it use similar command to that you can see below. + To set it use similar command to that you can see below: - echo 10 > /proc/omnibook/lcd + $ echo 1 > /proc/omnibook/lcd - The value of LCD brightness must be betwenn 0 and 10. + The value of LCD brightness must be between 0 and the printed max boundary, + here you can see it's 7. - Note: Setting the LCD brightness on HP OmniBook XE3 GF via + Bug: Setting the LCD brightness on HP OmniBook XE3 GF via /proc/omnibook/lcd is working if you press one of the brightness control keys once after writing the value - into /proc/omnibook/lcd. I'll try to fix it, but I have - no idea about reason yet. + into /proc/omnibook/lcd. To turn off the LCD backlight use - echo off > /proc/omnibook/lcd + $ echo off > /proc/omnibook/lcd To turn it back on use - echo on > /proc/omnibook/lcd + $ echo on > /proc/omnibook/lcd This is useful if you have an X server, such as the ATI Radeon, that does not know how to turn off the LCD backlight. Use a @@ -378,7 +424,7 @@ How to use? 10. To check that your laptop is docked in a docking station or port replicator use - cat /proc/omnibook/dock + $ cat /proc/omnibook/dock command. It produce similar output to that you can see below. @@ -394,16 +440,37 @@ How to use? You have to enable it explicit way by module parameter dock. To enable it use: - insmod omnibook dock=1 + $ insmod omnibook dock=1 You can enable it by /etc/modules.conf with the following entry: options omnibook dock=1 +11. To read wifi and bluetooth adapters status reading the + /proc/omnibook/wifi and /proc/omnibook/bluetooth files respectively: + + $ cat /proc/omnibook/wifi + Wifi adapter is present and enabled. + Wifi Kill switch is on. + + $ cat /proc/omnibook/bluetooth + Bluetooth adapter is absent. + + You can enable or disable a dectected adapters writing 1 or 0 respectibely + to the corresponding file: + + $ echo 0 > /proc/omnibook/wifi + [ Wifi led shut down, connectivity is lost ] + + $ cat /proc/omnibook/wifi + Wifi adapter is present and disabled. + Wifi Kill switch is on. + + You may enable features above via the proper module parameters. See the output of - modinfo omnibook + $ modinfo omnibook command. @@ -413,12 +480,12 @@ networked) users or you are the only user of the laptop you may load the module with the parameter user to enable non-root accounts to set omnibook paremeters as follows: - insmod omnibook user=1 + $ insmod omnibook user=1 You can enable users to set parameters by /etc/modules.conf with the following entry: - options omnibook user=1 + $ options omnibook user=1 Graphical frontends ------------------- @@ -441,12 +508,7 @@ How can your laptop be supported? If your model is unsupported and you want it to be supported I need four things: -1. Test your machine with Pavel's omke.pl and report the result. You - should include that a feature works or not and details if any - (eg. OneTouch keycodes in hex as appears in syslog after enabling - them by omke.pl etc.). - -2. Force the module to load with an embedded controller firmware type +1. Force the module to load with an embedded controller firmware type detailed above. For example if you want to test that your machine is an XE3GF style model, use the following command: @@ -457,10 +519,10 @@ things: Warning!!! Forced load on an unsupported machine may cause unpredictable result. You have been warned... -3. Send me DMI strings of your machine (/proc/omnibook/dmi after +2. Send me DMI strings of your machine (/proc/omnibook/dmi after loading omnibook module on any machine). -4. If possible send me the DSDT of your machine. If your kernel is +3. If possible send me the DSDT of your machine. If your kernel is configured for ACPI you can found it at /proc/acpi/dsdt. Use the following command to get the DSDT AML file. @@ -476,14 +538,14 @@ things: Please send me the AML file. Note: it is binary file. -5. Developers or advanced users who want to help the developement of this driver +4. Developers or advanced users who want to help the development of this driver can enable an experimental features of the omnibook kernel module: /proc/omnibook/dump, which dump the content of the embedded controller memory. It have to be manually enabled using the dump=1 kernel module parameters - and can be used in conjunction with a carefull examination - of a decompiled DSDT to spot where your laptop stores interesting informations + and can be used in conjunction with a careful examination + of a decompiled DSDT to spot where your laptop stores interesting information such as FAN speed or CPU temperature. This code was written without any documentation from HP or Compal so it @@ -512,11 +574,50 @@ Compal Electronics, Inc. does not response to information requests at all. Meanwhile (in 2002) Compaq and HP merged and as I know Compaq will the supplier of the new laptop models in the merged company. -Some new models of Toshiba Satellite notebooks (M70 and M40) seems to +Some new models of Toshiba Satellite notebooks (M70 and M40X) seems to be made by Compal. +The NbSmi backend code which implement support for some Toshiba Satellite +was made using technical documentation provided by Toshiba. +This code is contained in the nbsmi.c file +Thanks Toshiba for this Linux-friendly behavior. +This technical documentation was provided with the following disclaimer: + +----- Disclaimer Verbatim copy Begin ----- + PLEASE READ THIS INTELLECTUAL PROPERTY DISCLAIMER CAREFULLY BEFORE +USING THE TOSHIBA TECHNICAL INFORMATION AS ATTACHED. + BY USING THE TOSHIBA TECHNICAL INFORMATION, YOU ARE AGREEING TO BE +BOUND BY ALL OF THE TERMS OF THIS INTELLECTUAL PROPERTY DISCLAIMER. + IF YOU DO NOT AGREE TO THE TERMS OF THIS INTELLECTUAL PROPERTY +DISCLAIMER, PROMPTLY RETURN THE ATTACHED TOSHIBA TECHNICAL INFORMATION. + + Copyright (C) 1999, Toshiba Corp. All rights reserved. + + + INTELLECTUAL PROPERTY DISCLAIMER + + NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, OF ANY +INTELLECTUAL PROPERTY RIGHTS OF TOSHIBA IS GRANTED OR INTENDED HEREBY. +NOTWITHSTANDING FORGOING, TOSHIBA WILL NOT MAKE ANY CLAIM BASED ON THE +INTELLECTUAL PROPERTY RIGHTS AGAINST SOFTWARE FOR LINUX DEVELOPED USING +TOSHIBA TECHNICAL INFORMATION, PROVIDED THAT SUCH SOFTWARE IS USED FOR +OR DISTRIBUTED WITH LINUX FOR EXECUTION ON TOSHIABA COMPUTER PRODUCTS. + + TOSHIBA DISCLAIMS ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT +OF PROPRIETARY RIGHTS RELATING TO IMPLEMENTATION OF TOSHIBA TECHNICAL +INFORMATION. TOSHIBA DOES NOT WARRANT OR REPRESENT THAT SUCH +IMPLEMENTATION(S) WILL NOT INFRINGE SUCH RIGHTS. + + TOSHIBA TECHNICAL INFORMATION IS PROVIDED "AS IS" WITH NO WARRNTIES +WHATSOEVER INCLUDING ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR ANY +PARTICULAR PURPOSE. +---- Disclaimer End ---- + For more information you can see the OmniBook mailing list at http://zurich.ai.mit.edu/mailman/listinfo/omnibook +or the Toshiba linux mailing list at +http://linux.toshiba-dme.co.jp/linux/ + You can find actual version of this code at -http://sourceforge.net/projects/omke +http://sourceforge.net/projects/omnibook diff --git a/doc/README-1st b/doc/README-1st index 71e3450..cc9823a 100644 --- a/doc/README-1st +++ b/doc/README-1st @@ -2,9 +2,11 @@ This package intended to provide Linux kernel support for HP OmniBook, HP Pavilion, Toshiba Satellite and some Acer Aspire and Compal laptops. The state of this code is experimental. -This code was written without any documentation about HP OmniBooks and -other machines so it is provided as is without any warranty. Use it on -your own risk. +This code was written using technical documentation provided by Toshiba about +some Toshiba Satellites (M40 ...) and Toshiba Tecra. +This code was written without any documentation about other laptop models. + +It is provided as is without any warranty. Use it on your own risk. The code in the files in the omnibook distribution is licensed for use under the terms of GNU General Public License, included as the file @@ -12,5 +14,4 @@ named COPYING. For installation instructions please read the file named INSTALL. For usage informations and/or bug reports you may read file named README. -For additional informations for using it on kernel 2.6 see README-2.6. For current bugs and problems see file named BUGS. diff --git a/doc/TODO b/doc/TODO index 6759b9f..b9fefb8 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,22 +1,21 @@ TODO ==== +Current issues: + * See if/how key polling can be ported to 2.6 * LED API support -* Clarify the TSM40 situation * Create a clean access method to the i8042 kbd controller (this will require a kernel patch) -* We use I/O ports without a request_region ( ec.c blank.c fan.c) -* To be cleaned: blank fan -* To much global variables sometimes +* To be cleaned: battery dump fan_policy -Items imported from previous version: +Old items imported from previous version: * Fix LCD brighness handling on XE3GF style machines * Fully support OB5xx, OB6xxx and XE4500 style machines * Battery support for OB5xx, OB6xxx and XE4500 style machines -Will probably always remain here: +Will probably remain here forever: * Adding more features of embedded controller * Support more machines diff --git a/dock.c b/dock.c index 1301e54..d25482f 100644 --- a/dock.c +++ b/dock.c @@ -15,30 +15,17 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif #include "ec.h" -static const struct omnibook_io_operation dock_io_table[] = { - { XE3GF, EC, XE3GF_CSPR, 0, XE3GF_CSPR_MASK}, - { OB500|OB510|OB6000|OB6100, EC, OB500_STA1, 0, OB500_DCKS_MASK}, - { OB4150, EC, OB4150_DCID, 0, 0}, - { 0,} -}; - -static struct omnibook_io_operation *dock_io; - -static int omnibook_dock_read(char *buffer) +static int omnibook_dock_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; u8 dock; int retval; - if ((retval = omnibook_io_read(dock_io, &dock))) + if ((retval = io_op->backend->byte_read(io_op,&dock))) return retval; len += @@ -48,20 +35,22 @@ static int omnibook_dock_read(char *buffer) return len; } -static int omnibook_dock_init(void) -{ - dock_io = omnibook_io_match(dock_io_table); - return dock_io ? 0 : -ENODEV; -} +static struct omnibook_tbl dock_table[] __initdata = { + { XE3GF, SIMPLE_BYTE(EC,XE3GF_CSPR,XE3GF_CSPR_MASK)}, + { OB500|OB510|OB6000|OB6100, SIMPLE_BYTE(EC,OB500_STA1,OB500_DCKS_MASK)}, + { OB4150, SIMPLE_BYTE(EC,OB4150_DCID,0)}, + { 0,} +}; + -static struct omnibook_feature __declared_feature dock_feature = { +static struct omnibook_feature __declared_feature dock_driver = { .name = "dock", .enabled = 0, .read = omnibook_dock_read, - .init = omnibook_dock_init, .ectypes = XE3GF|OB500|OB510|OB6000|OB6100|OB4150, + .tbl = dock_table, }; -module_param_named(dock, dock_feature.enabled, int, S_IRUGO); +module_param_named(dock, dock_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(dock, "Use 0 to disable, 1 to enable docking station support"); /* End of file */ diff --git a/dump.c b/dump.c index 142cb44..2c0e47e 100644 --- a/dump.c +++ b/dump.c @@ -19,17 +19,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif - #include "ec.h" static u8 ecdump_regs[256]; -static int ecdump_read(char *buffer) +static int ecdump_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; int i, j; @@ -41,7 +36,7 @@ static int ecdump_read(char *buffer) for (i = 0; i < 255; i += 16) { len += sprintf(buffer + len, "EC 0x%02x:", i); for (j = 0; j < 16; j++) { - if (omnibook_ec_read(i + j, &v)) + if (legacy_ec_read(i + j , &v)) break; if (v != ecdump_regs[i + j]) len += sprintf(buffer + len, " *%02x", v); @@ -64,7 +59,7 @@ static int ecdump_read(char *buffer) return len; } -static int ecdump_write(char *buffer) +static int ecdump_write(char *buffer,struct omnibook_operation *io_op) { int i, v; @@ -76,7 +71,7 @@ static int ecdump_write(char *buffer) } else return -EINVAL; if (i >= 0 && i < 256 && v >= 0 && v < 256) { - if (omnibook_ec_write(i, v)) + if (legacy_ec_write(i, v)) return -EIO; } else return -EINVAL; @@ -84,14 +79,14 @@ static int ecdump_write(char *buffer) return 0; } -static struct omnibook_feature __declared_feature dump_feature = { +static struct omnibook_feature __declared_feature dump_driver = { .name = "dump", .enabled = 0, .read = ecdump_read, .write = ecdump_write, }; -module_param_named(dump, dump_feature.enabled, int, S_IRUGO); +module_param_named(dump, dump_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(dump, "Use 0 to disable, 1 to enable embedded controller register dump support"); /* End of file */ diff --git a/ec.c b/ec.c index 60cadfc..7402398 100644 --- a/ec.c +++ b/ec.c @@ -16,13 +16,13 @@ * Modified by Mathieu Bérard , 2006 */ +#include "omnibook.h" + #include #include #include -#include #include -#include -#include +#include #include #include "ec.h" @@ -35,14 +35,11 @@ #define DEFINE_SPINLOCK(s) spinlock_t s = SPIN_LOCK_UNLOCKED #endif -extern int omnibook_ectype; /* - * Interrupt control + * Interrupt control */ - - static DEFINE_SPINLOCK(omnibook_ec_lock); @@ -107,16 +104,20 @@ static int omnibook_ec_wait(u8 event) * disabled. */ -int omnibook_ec_read(u8 addr, u8 *data) +static int omnibook_ec_read(const struct omnibook_operation *io_op, u8 *data) { - unsigned long flags; int retval; - + #ifdef CONFIG_ACPI_EC - if (likely(!acpi_disabled)) - return ec_read(addr, data); + if (likely(!acpi_disabled)) { + retval = ec_read((u8) io_op->read_addr, data); + if(io_op->read_mask) + *data &= io_op->read_mask; + dprintk("ACPI EC read at %lx success %i.\n",io_op->read_addr,retval); + return retval; + } #endif - spin_lock_irqsave(&omnibook_ec_lock, flags); + spin_lock_irq(&omnibook_ec_lock); retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); if (retval) goto end; @@ -124,35 +125,41 @@ int omnibook_ec_read(u8 addr, u8 *data) retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); if (retval) goto end; - outb(addr, OMNIBOOK_EC_DATA); + outb((u8) io_op->read_addr, OMNIBOOK_EC_DATA); retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_OBF); if (retval) goto end; *data = inb(OMNIBOOK_EC_DATA); + if(io_op->read_mask) + *data &= io_op->read_mask; end: - spin_unlock_irqrestore(&omnibook_ec_lock, flags); + spin_unlock_irq(&omnibook_ec_lock); + dprintk("Custom EC read at %lx success %i.\n",io_op->read_addr,retval); return retval; } - + /* - * Write to the embedded controller - * Decide at run-time if we can use the much cleaner ACPI EC driver instead of - * this implementation, this is the case if ACPI has been compiled and is not + * Write to the embedded controller: + * If OMNIBOOK_LEGACY is set, decide at run-time if we can use the much cleaner + * ACPI EC driver instead of this legacy implementation. + * This is the case if ACPI has been compiled and is not * disabled. + * If OMNIBOOK_LEGACY is unset, we drop our custoim implementation */ -int omnibook_ec_write(u8 addr, u8 data) +static int omnibook_ec_write(const struct omnibook_operation *io_op, u8 data) { - - unsigned long flags; int retval; #ifdef CONFIG_ACPI_EC - if (likely(!acpi_disabled)) - return ec_write(addr, data); + if (likely(!acpi_disabled)) { + retval = ec_write((u8) io_op->write_addr, data); + dprintk("ACPI EC write at %lx success %i.\n",io_op->write_addr,retval); + return retval; + } #endif - spin_lock_irqsave(&omnibook_ec_lock, flags); + spin_lock_irq(&omnibook_ec_lock); retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); if (retval) goto end; @@ -160,16 +167,68 @@ int omnibook_ec_write(u8 addr, u8 data) retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); if (retval) goto end; - outb(addr, OMNIBOOK_EC_DATA); + outb((u8) io_op->write_addr, OMNIBOOK_EC_DATA); retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); if (retval) goto end; outb(data, OMNIBOOK_EC_DATA); end: - spin_unlock_irqrestore(&omnibook_ec_lock, flags); + spin_unlock_irq(&omnibook_ec_lock); + dprintk("Custom EC write at %lx success %i.\n",io_op->write_addr,retval); return retval; } +/* + * legacy access function for unconverted old code who expect old omnibook_ec_read + */ + +int legacy_ec_read(u8 addr, u8 *data) +{ + int retval; + struct omnibook_operation *io_op; + + io_op = kzalloc(sizeof(struct omnibook_operation), GFP_KERNEL); + if(!io_op) + return -ENOMEM; + io_op->read_addr = addr; + retval = omnibook_ec_read(io_op, data); + kfree(io_op); + return retval; +} + + +/* + * legacy access function for unconverted old code who expect old omnibook_ec_write + */ + +int legacy_ec_write(u8 addr, u8 data) +{ + int retval; + struct omnibook_operation *io_op; + + io_op = kzalloc(sizeof(struct omnibook_operation), GFP_KERNEL); + if(!io_op) + return -ENOMEM; + io_op->write_addr = addr; + retval = omnibook_ec_write(io_op, data); + kfree(io_op); + return retval; +} + +static int omnibook_ec_display(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval; + u8 raw_state; + + retval = io_op->backend->byte_read(io_op, &raw_state); + if(retval < 0) + return retval; + + *state = !!(raw_state) & DISPLAY_CRT_DET; + + return DISPLAY_CRT_DET; +} + /* * Registers of the keyboard controller */ @@ -216,17 +275,16 @@ static int omnibook_kbc_wait(u8 event) static int omnibook_kbc_write_command(u8 cmd) { - unsigned long flags; int retval; - spin_lock_irqsave(&omnibook_ec_lock, flags); + spin_lock_irq(&omnibook_ec_lock); retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); if (retval) goto end; outb(cmd, OMNIBOOK_KBC_SC); retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); - end: - spin_unlock_irqrestore(&omnibook_ec_lock, flags); +end: + spin_unlock_irq(&omnibook_ec_lock); return retval; } @@ -236,17 +294,16 @@ static int omnibook_kbc_write_command(u8 cmd) static int omnibook_kbc_write_data(u8 data) { - unsigned long flags; int retval; - spin_lock_irqsave(&omnibook_ec_lock, flags); + spin_lock_irq(&omnibook_ec_lock); retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); if (retval) goto end;; outb(data, OMNIBOOK_KBC_DATA); retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); - end: - spin_unlock_irqrestore(&omnibook_ec_lock, flags); +end: + spin_unlock_irq(&omnibook_ec_lock); return retval; } @@ -254,84 +311,240 @@ static int omnibook_kbc_write_data(u8 data) * Send a command to keyboard controller */ -int omnibook_kbc_command(u8 cmd, u8 data) +static int omnibook_kbc_command(const struct omnibook_operation *io_op, u8 data) { int retval; - - retval = omnibook_kbc_write_command(cmd); - if (retval) + + if ((retval = omnibook_kbc_write_command(OMNIBOOK_KBC_CONTROL_CMD))) return retval; + retval = omnibook_kbc_write_data(data); return retval; } /* - * Common pattern selector: - * Match an ectype and return pointer to corresponding io_operation. - * Also make corresponding backend initialisation if necessary + * Onetouch button hotkey handler */ -void *omnibook_io_match(const struct omnibook_io_operation *io_op) +static int omnibook_kbc_hotkeys(const struct omnibook_operation *io_op, unsigned int state) { - int i; - void *matched = NULL; - for (i = 0; io_op[i].ectypes ; i++) { - if (omnibook_ectype & io_op[i].ectypes) { - if (io_op[i].type == CDI && omnibook_cdimode_init()) - continue; - matched = (void *) &io_op[i]; - break; + int retval; + struct omnibook_operation hotkeys_op; + + hotkeys_op.backend = KBC; + hotkeys_op.on_mask = OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE; + hotkeys_op.off_mask = OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE; + + retval = omnibook_toggle( &hotkeys_op, !!(state & HKEY_ONETOUCH)); + + if(retval < 0) + return retval; + else + return HKEY_ONETOUCH; +} + +/* + * IO port backend. Only support single or dual ports operations + * private data structure: it's the linked list of requested ports + * + * Race condition issue: omnibook_pio_init/exit functions are only called from + * omnibook_backend_match and omnibook_remove from init.c, this should happen + * only at module init/exit time so there is no need for a lock. + */ + +struct pio_private_data_t { + unsigned long addr; + struct kref refcount; + struct list_head list; +}; + +static struct pio_private_data_t pio_private_data = { + .addr = 0, + .list = LIST_HEAD_INIT(pio_private_data.list), +}; + +/* + * Match an entry in the linked list helper function: see if we have and entry + * whose addr field match maddr + */ +static struct pio_private_data_t * + omnibook_match_port(struct pio_private_data_t *data, unsigned long maddr) +{ + struct list_head *p; + struct pio_private_data_t *cursor; + + list_for_each(p , &data->list ) { + cursor = list_entry(p, struct pio_private_data_t, list); + if( cursor->addr == maddr ) { + return cursor; } } - return matched; + return NULL; } /* - * Simple read function for common pattern - * Given an io_operation they read an address and apply a mask on the result + * See if we have to request raddr */ - -int omnibook_io_read(struct omnibook_io_operation *io_op, u8 *value) +static int omnibook_claim_port(struct pio_private_data_t *data, unsigned long raddr) { - int retval = 0; - - switch(io_op->type) { - case EC: - retval = omnibook_ec_read( io_op->read, value); - break; - case CDI: - retval = omnibook_cdimode_read( io_op->read, value); - break; - default: - BUG(); + struct pio_private_data_t *match, *new; + + match = omnibook_match_port( data, raddr); + if(match) { + /* Already requested by us: increment kref and quit */ + kref_get(&match->refcount); + return 0; + } + + /* there was no match: request the region and add to list */ + if(!request_region(raddr ,1 , OMNIBOOK_MODULE_NAME)) { + printk(O_ERR "Request I/O port error\n"); + return -ENODEV; + } + + new = kmalloc(sizeof(struct pio_private_data_t), GFP_KERNEL); + if(!new) { + release_region(raddr ,1 ); + return -ENOMEM; } + + kref_init(&new->refcount); + new->addr = raddr; + list_add(&new->list, &data->list); - if (io_op->mask) - *value = *value & io_op->mask; + return 0; +} + +/* + * Register read_addr and write_addr + */ +static int omnibook_pio_init(const struct omnibook_operation *io_op) +{ + int retval = 0; + + if(io_op->read_addr && + (retval = omnibook_claim_port(io_op->backend->data, io_op->read_addr))) + goto out; + + if(io_op->write_addr && ( io_op->write_addr != io_op->read_addr )) + retval = omnibook_claim_port(io_op->backend->data, io_op->write_addr); + +out: + return retval; +} + +/* + * REALLY release a port + */ +static void omnibook_free_port(struct kref *ref) +{ + struct pio_private_data_t *data; - return retval; + data = container_of(ref, struct pio_private_data_t, refcount); + release_region(data->addr ,1 ); + list_del(&data->list); + kfree(data); } /* - * Simple write function for common pattern - * Given an io_operation they write value at an given address + * Unregister read_addr and write_addr */ +static void omnibook_pio_exit(const struct omnibook_operation *io_op) +{ + struct pio_private_data_t *match; + + match = omnibook_match_port(io_op->backend->data, io_op->read_addr); + if(match) + kref_put(&match->refcount, omnibook_free_port); + + match = NULL; + match = omnibook_match_port(io_op->backend->data, io_op->write_addr); + if(match) + kref_put(&match->refcount, omnibook_free_port); -int omnibook_io_write(struct omnibook_io_operation *io_op, u8 value) +} + +static int omnibook_io_read(const struct omnibook_operation *io_op, u8 *value) +{ + *value = inb(io_op->read_addr); + if(io_op->read_mask) + *value &= io_op->read_mask; + return 0; +} + +static int omnibook_io_write(const struct omnibook_operation *io_op, u8 value) +{ + outb(io_op->write_addr, value); + return 0; +} + + +/* + * Backend interface declarations + */ + +struct omnibook_backend kbc_backend = { + .name = "i8042", + .byte_write = omnibook_kbc_command, + .hotkeys_set = omnibook_kbc_hotkeys, +}; + +struct omnibook_backend pio_backend = { + .name = "pio", + .data = &pio_private_data, + .init = omnibook_pio_init, + .exit = omnibook_pio_exit, + .byte_read = omnibook_io_read, + .byte_write = omnibook_io_write, +}; + +struct omnibook_backend ec_backend = { + .name = "ec", + .byte_read = omnibook_ec_read, + .byte_write = omnibook_ec_write, + .display_get = omnibook_ec_display, +}; + +int omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle) { int retval = 0; + int mask; + u8 data; - switch(io_op->type) { - case EC: - retval = omnibook_ec_write( io_op->write, value); - break; - case CDI: - retval = omnibook_cdimode_write( io_op->write, value); - break; - default: - BUG(); - } + + if((retval = io_op->backend->byte_read(io_op,&data))) + return retval; - return retval; + if( toggle == 1) + mask = io_op->on_mask; + else if( toggle == 0) + mask = io_op->off_mask; + else + return -EINVAL; + + if(mask > 0) + data |= (u8) mask; + else if (mask < 0) + data &= ~((u8) (-mask)); + else + return -EINVAL; + + retval = io_op->backend->byte_write(io_op,data); + + return retval; } +/* + * Helper for toggle like operations + */ +int omnibook_toggle(const struct omnibook_operation *io_op, int toggle) +{ + int retval; + u8 data; + + data = toggle ? io_op->on_mask : io_op->off_mask; + retval = io_op->backend->byte_write(io_op, data); + return retval; +} + + /* End of file */ diff --git a/ec.h b/ec.h index cd22be5..c136b7b 100644 --- a/ec.h +++ b/ec.h @@ -1,6 +1,5 @@ /* - * ec.h -- low level definitions to access Embedded Controller - * and Keyboard Controller and system I/O ports or memory + * ec.h -- low level definitions to access Embedded Controller and co. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,166 +15,205 @@ * Modified by Mathieu Bérard , 2006 */ -extern int omnibook_ec_read(u8 addr, u8 *data); -extern int omnibook_ec_write(u8 addr, u8 data); -extern int omnibook_kbc_command(u8 cmd, u8 data); +#include -struct omnibook_io_operation; +/* + * Quite ugly: + * on_mask and off_maks are also used to store the i8042 data for kbc backend. + * an union seemed overkilled + */ -extern int omnibook_io_read(struct omnibook_io_operation *io_op, u8 *value); -extern int omnibook_io_write(struct omnibook_io_operation *io_op, u8 value); -void *omnibook_io_match(const struct omnibook_io_operation *io_op); +struct omnibook_backend; -extern int omnibook_cdimode_read(unsigned int index, u8 *value); -extern int omnibook_cdimode_write(unsigned int index, u8 value); -extern void omnibook_cdimode_exit(void); -extern int omnibook_cdimode_init(void); +struct omnibook_operation { + struct omnibook_backend *backend; + unsigned long read_addr; /* address for data reading */ + unsigned long write_addr; /* address for data writing */ + u8 read_mask; /* read mask */ + int on_mask; /* mask to set (pos value) or unset (neg value) to put feature to on state */ + int off_mask; /* mask to set (pos value) or unset (neg value) to put feature to off state */ +}; +#define COMMAND(backend,data_on,data_off) .io_op = { backend, 0, 0, 0, data_on, data_off } +#define SIMPLE_BYTE(backend,addr,mask) .io_op = { backend, addr, addr, mask, 0, 0 } + +struct omnibook_tbl { + enum omnibook_ectype_t ectypes; + struct omnibook_operation io_op; +}; /* - * Storage of generic (EC,PIO,...) addresses, read masks, and corresponding ectypes - * This is for use with the omnibook_io_{read/write} and omnibook_io_match - * helper functions + * Backend interface definition + * + * Note: + * display_get/set and hotkey_set/get return a positive value on success + * which set bits corresponds to the actual supported states + * (see omnibook.h for the DISPLAY_* masks) */ -struct omnibook_io_operation { - int ectypes; /* ectype */ - enum { BAD, EC, PIO, MMIO, CDI} type; /* address space */ - u8 read; /* read address */ - u8 write; /* write address */ - u8 mask; /* read mask */ +struct omnibook_backend { + const char *name; /* backend name */ + void *data; /* backend private data pointer */ + int (*init) (const struct omnibook_operation *); + void (*exit) (const struct omnibook_operation *); + int (*byte_read) (const struct omnibook_operation *, u8 *); + int (*byte_write) (const struct omnibook_operation *, u8); + int (*aerial_get) (const struct omnibook_operation *, unsigned int *); + int (*aerial_set) (const struct omnibook_operation *, unsigned int); + int (*hotkeys_get) (const struct omnibook_operation *, unsigned int *); + int (*hotkeys_set) (const struct omnibook_operation *, unsigned int); + int (*display_get) (const struct omnibook_operation *, unsigned int *); + int (*display_set) (const struct omnibook_operation *, unsigned int); }; +extern struct omnibook_backend kbc_backend; +extern struct omnibook_backend pio_backend; +extern struct omnibook_backend ec_backend; +extern struct omnibook_backend acpi_backend; +extern struct omnibook_backend nbsmi_backend; +extern struct omnibook_backend compal_backend; + +#define KBC &kbc_backend +#define PIO &pio_backend +#define EC &ec_backend +#define ACPI &acpi_backend +#define SMI &nbsmi_backend +#define CDI &compal_backend + +int legacy_ec_read(u8 addr, u8 *data); +int legacy_ec_write(u8 addr, u8 data); +int omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle); +int omnibook_toggle(const struct omnibook_operation *io_op, int toggle); + /* * Embedded controller adresses */ -#define XE3GF_CHGM 0x90 /* , 16 bit */ -#define XE3GF_CHGS 0x92 /* , 16 bit */ -#define XE3GF_CHGC 0x94 /* Current charge of board, 16 bit */ -#define XE3GF_CHGV 0x96 /* Current voltage, 16 bit */ -#define XE3GF_CHGA 0x98 /* Current intensity, 16 bit */ -#define XE3GF_BAL 0x9A /* Battery present status */ -#define XE3GF_STA1 0x9C /* Various status bits */ -#define XE3GF_CSPR 0xA1 /* Port replicator status, 1 bit */ -#define XE3GF_ADP 0xA3 /* AC acapter status, 1 bit */ -#define XE3GF_FOT 0xA5 /* Fan off temperature, 8 bit */ -#define XE3GF_FSD1 0xA6 /* Fan on temperature, 8 bit */ -#define XE3GF_FSD2 0xA7 /* Fan level 2 temperature, 8 bit */ -#define XE3GF_FSD3 0xA8 /* Fan level 3 temperature, 8 bit */ -#define XE3GF_FSD4 0xA9 /* Fan level 4 temperature, 8 bit */ -#define XE3GF_FSD5 0xAA /* Fan level 5 temperature, 8 bit */ -#define XE3GF_FSD6 0xAB /* Fan level 6 temperature, 8 bit */ -#define XE3GF_FSD7 0xAC /* Fan level 7 temperature, 8 bit */ -#define XE3GF_FSRD 0xAD /* Fan status, 8 bit */ -#define XE3GF_CTMP 0xB0 /* CPU tempetature, 8 bit */ -#define XE3GF_BRTS 0xB9 /* LCD brightness, 4 bit */ -#define XE3GF_BTY0 0xC0 /* Battery 0 type, 1 bit */ -#define XE3GF_BST0 0xC1 /* Battery 0 status, 3 bit */ -#define XE3GF_BRC0 0xC2 /* Battery 0 remaining capacity, 16 bit */ -#define XE3GF_BSN0 0xC4 /* Battery 0 serial number 16 bit */ -#define XE3GF_BPV0 0xC6 /* Battery 0 present voltage, 16 bit */ -#define XE3GF_BDV0 0xC8 /* Battery 0 design voltage 16 bit */ -#define XE3GF_BDC0 0xCA /* Battery 0 design capacity 16 bit */ -#define XE3GF_BFC0 0xCC /* Battery 0 last full capacity 16 bit */ -#define XE3GF_GAU0 0xCE /* Battery 0 gauge, 8 bit */ -#define XE3GF_BTY1 0xD0 /* Battery 1 type, 1 bit */ -#define XE3GF_BST1 0xD1 /* Battery 1 status, 3 bit */ -#define XE3GF_BRC1 0xD2 /* Battery 1 remaining capacity, 16 bit */ -#define XE3GF_BSN1 0xD4 /* Battery 1 serial number, 16 bit */ -#define XE3GF_BPV1 0xD6 /* Battery 1 present voltage, 16 bit */ -#define XE3GF_BDV1 0xD8 /* Battery 1 design voltage 16 bit */ -#define XE3GF_BDC1 0xDA /* Battery 1 design capacity 16 bit */ -#define XE3GF_BFC1 0xDC /* Battery 1 last full capacity 16 bit */ -#define XE3GF_GAU1 0xDE /* Battery 1 gauge, 8 bit */ +#define XE3GF_CHGM 0x90 /* , 16 bit */ +#define XE3GF_CHGS 0x92 /* , 16 bit */ +#define XE3GF_CHGC 0x94 /* Current charge of board, 16 bit */ +#define XE3GF_CHGV 0x96 /* Current voltage, 16 bit */ +#define XE3GF_CHGA 0x98 /* Current intensity, 16 bit */ +#define XE3GF_BAL 0x9A /* Battery present status */ +#define XE3GF_STA1 0x9C /* Various status bits */ +#define XE3GF_CSPR 0xA1 /* Port replicator status, 1 bit */ +#define XE3GF_ADP 0xA3 /* AC acapter status, 1 bit */ +#define XE3GF_FOT 0xA5 /* Fan off temperature, 8 bit */ +#define XE3GF_FSD1 0xA6 /* Fan on temperature, 8 bit */ +#define XE3GF_FSD2 0xA7 /* Fan level 2 temperature, 8 bit */ +#define XE3GF_FSD3 0xA8 /* Fan level 3 temperature, 8 bit */ +#define XE3GF_FSD4 0xA9 /* Fan level 4 temperature, 8 bit */ +#define XE3GF_FSD5 0xAA /* Fan level 5 temperature, 8 bit */ +#define XE3GF_FSD6 0xAB /* Fan level 6 temperature, 8 bit */ +#define XE3GF_FSD7 0xAC /* Fan level 7 temperature, 8 bit */ +#define XE3GF_FSRD 0xAD /* Fan status, 8 bit */ +#define XE3GF_CTMP 0xB0 /* CPU tempetature, 8 bit */ +#define XE3GF_BRTS 0xB9 /* LCD brightness, 4 bit */ +#define XE3GF_BTY0 0xC0 /* Battery 0 type, 1 bit */ +#define XE3GF_BST0 0xC1 /* Battery 0 status, 3 bit */ +#define XE3GF_BRC0 0xC2 /* Battery 0 remaining capacity, 16 bit */ +#define XE3GF_BSN0 0xC4 /* Battery 0 serial number 16 bit */ +#define XE3GF_BPV0 0xC6 /* Battery 0 present voltage, 16 bit */ +#define XE3GF_BDV0 0xC8 /* Battery 0 design voltage 16 bit */ +#define XE3GF_BDC0 0xCA /* Battery 0 design capacity 16 bit */ +#define XE3GF_BFC0 0xCC /* Battery 0 last full capacity 16 bit */ +#define XE3GF_GAU0 0xCE /* Battery 0 gauge, 8 bit */ +#define XE3GF_BTY1 0xD0 /* Battery 1 type, 1 bit */ +#define XE3GF_BST1 0xD1 /* Battery 1 status, 3 bit */ +#define XE3GF_BRC1 0xD2 /* Battery 1 remaining capacity, 16 bit */ +#define XE3GF_BSN1 0xD4 /* Battery 1 serial number, 16 bit */ +#define XE3GF_BPV1 0xD6 /* Battery 1 present voltage, 16 bit */ +#define XE3GF_BDV1 0xD8 /* Battery 1 design voltage 16 bit */ +#define XE3GF_BDC1 0xDA /* Battery 1 design capacity 16 bit */ +#define XE3GF_BFC1 0xDC /* Battery 1 last full capacity 16 bit */ +#define XE3GF_GAU1 0xDE /* Battery 1 gauge, 8 bit */ /* * Bitmasks for sub byte values */ -#define XE3GF_SHDD_MASK 0x40 /* External display status */ -#define XE3GF_CSPR_MASK 0x01 /* Port replicator status */ -#define XE3GF_ADP_MASK 0x20 /* AC acapter status */ -#define XE3GF_BAL0_MASK 0x01 /* Battery 0 present */ -#define XE3GF_BAL1_MASK 0x02 /* Battery 1 present */ -#define XE3GF_BMF_MASK 0x70 /* Model code */ -#define XE3GF_BTY_MASK 0x80 /* Type: Ni-MH or Li-Ion */ -#define XE3GF_BST_MASK_DSC 0x01 /* Discarging */ -#define XE3GF_BST_MASK_CHR 0x02 /* Charging */ -#define XE3GF_BST_MASK_CRT 0x04 /* Critical */ -#define XE3GF_FSRD_MASK_S1 0x01 /* Fan level 1 */ -#define XE3GF_FSRD_MASK_S2 0x02 /* Fan level 2 */ -#define XE3GF_FSRD_MASK_S3 0x04 /* Fan level 3 */ -#define XE3GF_FSRD_MASK_S4 0x08 /* Fan level 4 */ -#define XE3GF_FSRD_MASK_S5 0x10 /* Fan level 5 */ -#define XE3GF_FSRD_MASK_S6 0x20 /* Fan level 6 */ -#define XE3GF_FSRD_MASK_S7 0x40 /* Fan level 7 */ -#define XE3GF_BRTS_MASK 0x0F /* LCD brightness */ - -#define XE3GF_FAN_ON_MASK 0x02 /* Fan on */ +#define XE3GF_SHDD_MASK 0x40 /* External display status */ +#define XE3GF_CSPR_MASK 0x01 /* Port replicator status */ +#define XE3GF_ADP_MASK 0x20 /* AC acapter status */ +#define XE3GF_BAL0_MASK 0x01 /* Battery 0 present */ +#define XE3GF_BAL1_MASK 0x02 /* Battery 1 present */ +#define XE3GF_BMF_MASK 0x70 /* Model code */ +#define XE3GF_BTY_MASK 0x80 /* Type: Ni-MH or Li-Ion */ +#define XE3GF_BST_MASK_DSC 0x01 /* Discarging */ +#define XE3GF_BST_MASK_CHR 0x02 /* Charging */ +#define XE3GF_BST_MASK_CRT 0x04 /* Critical */ +#define XE3GF_FSRD_MASK_S1 0x01 /* Fan level 1 */ +#define XE3GF_FSRD_MASK_S2 0x02 /* Fan level 2 */ +#define XE3GF_FSRD_MASK_S3 0x04 /* Fan level 3 */ +#define XE3GF_FSRD_MASK_S4 0x08 /* Fan level 4 */ +#define XE3GF_FSRD_MASK_S5 0x10 /* Fan level 5 */ +#define XE3GF_FSRD_MASK_S6 0x20 /* Fan level 6 */ +#define XE3GF_FSRD_MASK_S7 0x40 /* Fan level 7 */ +#define XE3GF_BRTS_MASK 0x0F /* LCD brightness */ +#define XE3GF_FAN_ON_MASK 0x02 /* Fan on */ /* * OmniBook XE3 GC values */ -#define XE3GC_CTMP 0x28 /* CPU tempetature, 8 bit */ -#define XE3GC_STA1 0x30 /* Various status bits */ -#define XE3GC_Q0A 0x31 /* Various status bits */ -#define XE3GC_CCUR 0x38 /* Current charge of board, 16 bit ? */ -#define XE3GC_CVOL 0x3A /* Current voltage, 16 bit ? */ -#define XE3GC_CARM 0x3C /* Current intensity, 16 bit ? */ -#define XE3GC_BAT 0x3E /* Battery present status */ -#define XE3GC_BST0 0x40 /* Battery 0 status, 3 bit */ -#define XE3GC_BPR0 0x41 /* Battery 0 present rate, 16 bit ? */ -#define XE3GC_BRC0 0x43 /* Battery 0 remaining capacity, 16 bit */ -#define XE3GC_BPV0 0x45 /* Battery 0 present voltage, 16 bit */ -#define XE3GC_BDV0 0x47 /* Battery 0 design voltage 16 bit */ -#define XE3GC_BDC0 0x49 /* Battery 0 design capacity 16 bit */ -#define XE3GC_BTY0 0x4A /* Battery 0 type, 1 bit ? */ -#define XE3GC_BTP0 0x4B /* Battery 0 ?, 1 bit */ -#define XE3GC_BSN0 0x4C /* Battery 0 serial number, 8 bit ? */ -#define XE3GC_BMF0 0x4D /* Battery 0 ?,8 bit */ -#define XE3GC_BST1 0x50 /* Battery 1 status, 3 bit */ -#define XE3GC_BPR1 0x51 /* Battery 1 present rate, 16 bit ? */ -#define XE3GC_BRC1 0x53 /* Battery 1 remaining capacity, 16 bit */ -#define XE3GC_BPV1 0x55 /* Battery 1 present voltage, 16 bit */ -#define XE3GC_BDV1 0x57 /* Battery 1 design voltage 16 bit */ -#define XE3GC_BDC1 0x59 /* Battery 1 design capacity 16 bit */ -#define XE3GC_BTY1 0x5A /* Battery 1 type, 1 bit ? */ -#define XE3GC_BTP1 0x5B /* Battery 1 ?, 1 bit */ -#define XE3GC_BSN1 0x5C /* Battery 1 serial number, 8 bit ? */ -#define XE3GC_BMF1 0x5D /* Battery 1 ?,8 bit */ -#define XE3GC_STA2 0x61 /* Various status bits */ -#define XE3GC_BTVL 0x6A /* LCD brightness, 4 bit */ +#define XE3GC_CTMP 0x28 /* CPU tempetature, 8 bit */ +#define XE3GC_STA1 0x30 /* Various status bits */ +#define XE3GC_Q0A 0x31 /* Various status bits */ +#define XE3GC_CCUR 0x38 /* Current charge of board, 16 bit ? */ +#define XE3GC_CVOL 0x3A /* Current voltage, 16 bit ? */ +#define XE3GC_CARM 0x3C /* Current intensity, 16 bit ? */ +#define XE3GC_BAT 0x3E /* Battery present status */ +#define XE3GC_BST0 0x40 /* Battery 0 status, 3 bit */ +#define XE3GC_BPR0 0x41 /* Battery 0 present rate, 16 bit ? */ +#define XE3GC_BRC0 0x43 /* Battery 0 remaining capacity, 16 bit */ +#define XE3GC_BPV0 0x45 /* Battery 0 present voltage, 16 bit */ +#define XE3GC_BDV0 0x47 /* Battery 0 design voltage 16 bit */ +#define XE3GC_BDC0 0x49 /* Battery 0 design capacity 16 bit */ +#define XE3GC_BTY0 0x4A /* Battery 0 type, 1 bit ? */ +#define XE3GC_BTP0 0x4B /* Battery 0 ?, 1 bit */ +#define XE3GC_BSN0 0x4C /* Battery 0 serial number, 8 bit ? */ +#define XE3GC_BMF0 0x4D /* Battery 0 ?,8 bit */ +#define XE3GC_BST1 0x50 /* Battery 1 status, 3 bit */ +#define XE3GC_BPR1 0x51 /* Battery 1 present rate, 16 bit ? */ +#define XE3GC_BRC1 0x53 /* Battery 1 remaining capacity, 16 bit */ +#define XE3GC_BPV1 0x55 /* Battery 1 present voltage, 16 bit */ +#define XE3GC_BDV1 0x57 /* Battery 1 design voltage 16 bit */ +#define XE3GC_BDC1 0x59 /* Battery 1 design capacity 16 bit */ +#define XE3GC_BTY1 0x5A /* Battery 1 type, 1 bit ? */ +#define XE3GC_BTP1 0x5B /* Battery 1 ?, 1 bit */ +#define XE3GC_BSN1 0x5C /* Battery 1 serial number, 8 bit ? */ +#define XE3GC_BMF1 0x5D /* Battery 1 ?,8 bit */ +#define XE3GC_STA2 0x61 /* Various status bits */ +#define XE3GC_BTVL 0x6A /* LCD brightness, 4 bit */ /* * Bitmasks for sub byte values */ -#define XE3GC_ADP_MASK 0x40 /* AC acapter status */ -#define XE3GC_BAT0_MASK 0x01 /* Battery 0 present */ -#define XE3GC_BAT1_MASK 0x02 /* Battery 1 present */ -#define XE3GC_BTY_MASK 0x01 /* Type: Ni-MH or Li-Ion */ -#define XE3GC_BST_MASK_DSC 0x01 /* Discarging */ -#define XE3GC_BST_MASK_CHR 0x02 /* Charging */ -#define XE3GC_BST_MASK_CRT 0x04 /* Critical */ -#define XE3GC_CRTI_MASK 0x04 /* External display status */ -#define XE3GC_SLPB_MASK 0x01 /* Sleep button pressed */ -#define XE3GC_F5_MASK 0x02 /* Fn-F5 - LCD/CRT switch pressed */ -#define XE3GC_VOLD_MASK 0x04 /* Fn-down arrow or Volume down pressed */ -#define XE3GC_VOLU_MASK 0x08 /* Fn-up arrow or Volume up pressed */ -#define XE3GC_MUTE_MASK 0x10 /* Fn+F7 - Volume mute pressed */ -#define XE3GC_CNTR_MASK 0x20 /* Fn+F3/Fn+F4 - Contrast up or down pressed */ -#define XE3GC_BRGT_MASK 0x40 /* Fn+F1/Fn+F2 - Brightness up or down pressed */ -#define XE3GC_BTVL_MASK 0x0F /* LCD brightness */ +#define XE3GC_ADP_MASK 0x40 /* AC acapter status */ +#define XE3GC_BAT0_MASK 0x01 /* Battery 0 present */ +#define XE3GC_BAT1_MASK 0x02 /* Battery 1 present */ +#define XE3GC_BTY_MASK 0x01 /* Type: Ni-MH or Li-Ion */ +#define XE3GC_BST_MASK_DSC 0x01 /* Discarging */ +#define XE3GC_BST_MASK_CHR 0x02 /* Charging */ +#define XE3GC_BST_MASK_CRT 0x04 /* Critical */ +#define XE3GC_CRTI_MASK 0x04 /* External display status */ +#define XE3GC_SLPB_MASK 0x01 /* Sleep button pressed */ +#define XE3GC_F5_MASK 0x02 /* Fn-F5 - LCD/CRT switch pressed */ +#define XE3GC_VOLD_MASK 0x04 /* Fn-down arrow or Volume down pressed */ +#define XE3GC_VOLU_MASK 0x08 /* Fn-up arrow or Volume up pressed */ +#define XE3GC_MUTE_MASK 0x10 /* Fn+F7 - Volume mute pressed */ +#define XE3GC_CNTR_MASK 0x20 /* Fn+F3/Fn+F4 - Contrast up or down pressed */ +#define XE3GC_BRGT_MASK 0x40 /* Fn+F1/Fn+F2 - Brightness up or down pressed */ +#define XE3GC_BTVL_MASK 0x0F /* LCD brightness */ /* * Emulated scancodes */ -#define XE3GC_VOLD_SCAN 0x2E /* Volume down button scancode */ -#define XE3GC_VOLU_SCAN 0x30 /* Volume up button scancode */ -#define XE3GC_MUTE_SCAN 0x20 /* Volume up button scancode */ +#define XE3GC_VOLD_SCAN 0x2E /* Volume down button scancode */ +#define XE3GC_VOLU_SCAN 0x30 /* Volume up button scancode */ +#define XE3GC_MUTE_SCAN 0x20 /* Volume up button scancode */ /* * Toshiba Satellite A105 values and mask @@ -188,104 +226,104 @@ struct omnibook_io_operation { * Fujitsu Amilo D values */ -#define AMILOD_TMP 0x28 /* CPU tempetature, 8 bit */ -#define AMILOD_STA1 0x30 /* Various status bits */ -#define AMILOD_BAT 0x3E /* Battery present status */ -#define AMILOD_BDC0 0x40 /* Battery 0 design capacity 16 bit */ -#define AMILOD_BDV0 0x42 /* Battery 0 design voltage 16 bit */ -#define AMILOD_BTY0 0x44 /* Battery 0 type, 1 bit ? */ -#define AMILOD_BST0 0x45 /* Battery 0 status, 3 bit */ -#define AMILOD_BPR0 0x46 /* Battery 0 present rate, 16 bit ? */ -#define AMILOD_BRC0 0x48 /* Battery 0 remaining capacity, 16 bit */ -#define AMILOD_BPV0 0x4A /* Battery 0 present voltage, 16 bit */ -#define AMILOD_BTP0 0x4C /* Battery 0 ?, 1 bit */ -#define AMILOD_BDC1 0x50 /* Battery 1 design capacity 16 bit */ -#define AMILOD_BDV1 0x52 /* Battery 1 design voltage 16 bit */ -#define AMILOD_BTY1 0x54 /* Battery 1 type, 1 bit ? */ -#define AMILOD_BST1 0x55 /* Battery 1 status, 3 bit */ -#define AMILOD_BPR1 0x56 /* Battery 1 present rate, 16 bit ? */ -#define AMILOD_BRC1 0x58 /* Battery 1 remaining capacity, 16 bit */ -#define AMILOD_BPV1 0x5A /* Battery 1 present voltage, 16 bit */ -#define AMILOD_BTP1 0x5C /* Battery 1 ?, 1 bit */ -#define AMILOD_CBRG 0x6F /* LCD brightness, 4 bit */ +#define AMILOD_TMP 0x28 /* CPU tempetature, 8 bit */ +#define AMILOD_STA1 0x30 /* Various status bits */ +#define AMILOD_BAT 0x3E /* Battery present status */ +#define AMILOD_BDC0 0x40 /* Battery 0 design capacity 16 bit */ +#define AMILOD_BDV0 0x42 /* Battery 0 design voltage 16 bit */ +#define AMILOD_BTY0 0x44 /* Battery 0 type, 1 bit ? */ +#define AMILOD_BST0 0x45 /* Battery 0 status, 3 bit */ +#define AMILOD_BPR0 0x46 /* Battery 0 present rate, 16 bit ? */ +#define AMILOD_BRC0 0x48 /* Battery 0 remaining capacity, 16 bit */ +#define AMILOD_BPV0 0x4A /* Battery 0 present voltage, 16 bit */ +#define AMILOD_BTP0 0x4C /* Battery 0 ?, 1 bit */ +#define AMILOD_BDC1 0x50 /* Battery 1 design capacity 16 bit */ +#define AMILOD_BDV1 0x52 /* Battery 1 design voltage 16 bit */ +#define AMILOD_BTY1 0x54 /* Battery 1 type, 1 bit ? */ +#define AMILOD_BST1 0x55 /* Battery 1 status, 3 bit */ +#define AMILOD_BPR1 0x56 /* Battery 1 present rate, 16 bit ? */ +#define AMILOD_BRC1 0x58 /* Battery 1 remaining capacity, 16 bit */ +#define AMILOD_BPV1 0x5A /* Battery 1 present voltage, 16 bit */ +#define AMILOD_BTP1 0x5C /* Battery 1 ?, 1 bit */ +#define AMILOD_CBRG 0x6F /* LCD brightness, 4 bit */ /* * Bitmasks for sub byte values */ -#define AMILOD_ADP_MASK 0x40 /* AC acapter status */ -#define AMILOD_BAT0_MASK 0x01 /* Battery 0 present */ -#define AMILOD_BAT1_MASK 0x02 /* Battery 1 present */ -#define AMILOD_BTY_MASK 0x01 /* Type: Ni-MH or Li-Ion */ -#define AMILOD_BST_MASK_DSC 0x01 /* Discarging */ -#define AMILOD_BST_MASK_CHR 0x02 /* Charging */ -#define AMILOD_BST_MASK_CRT 0x04 /* Critical */ -#define AMILOD_CBRG_MASK 0x0F /* LCD brightness */ +#define AMILOD_ADP_MASK 0x40 /* AC acapter status */ +#define AMILOD_BAT0_MASK 0x01 /* Battery 0 present */ +#define AMILOD_BAT1_MASK 0x02 /* Battery 1 present */ +#define AMILOD_BTY_MASK 0x01 /* Type: Ni-MH or Li-Ion */ +#define AMILOD_BST_MASK_DSC 0x01 /* Discarging */ +#define AMILOD_BST_MASK_CHR 0x02 /* Charging */ +#define AMILOD_BST_MASK_CRT 0x04 /* Critical */ +#define AMILOD_CBRG_MASK 0x0F /* LCD brightness */ /* * OmniBook 500, 510, 6000, 6100, XE2 values */ -#define OB500_STA1 0x44 /* Various status bits */ -#define OB500_STA2 0x50 /* Various status bits */ -#define OB500_CTMP 0x55 /* CPU tempetature, 8 bit */ -#define OB500_BT1I 0x58 /* Battery 1 ? 16 bit */ -#define OB500_BT1C 0x5A /* Battery 1 remaining capacity 16 bit ? */ -#define OB500_BT1V 0x5C /* Battery 1 present voltage 16 bit ? */ -#define OB500_BT1S 0x5E /* Battery 1 status 3 bit ? */ -#define OB500_BT2I 0x6A /* Battery 2 ? 16 bit */ -#define OB500_BT2C 0x6C /* Battery 2 remaining capacity 16 bit ? */ -#define OB500_BT2V 0x6E /* Battery 2 present voltage 16 bit ? */ -#define OB500_BT2S 0x70 /* Battery 2 status 3 bit ? */ -#define OB500_BT3I 0x5F /* Battery 3 ? 16 bit */ -#define OB500_BT3C 0x61 /* Battery 3 remaining capacity 16 bit ? */ -#define OB500_BT3V 0x63 /* Battery 3 present voltage 16 bit ? */ -#define OB500_BT3S 0x65 /* Battery 3 status 3 bit ? */ - -#define OB6000_STA1 0x77 /* Various status bits */ - -#define XE2_STA1 0x50 /* Various status bits */ +#define OB500_STA1 0x44 /* Various status bits */ +#define OB500_STA2 0x50 /* Various status bits */ +#define OB500_CTMP 0x55 /* CPU tempetature, 8 bit */ +#define OB500_BT1I 0x58 /* Battery 1 ? 16 bit */ +#define OB500_BT1C 0x5A /* Battery 1 remaining capacity 16 bit ? */ +#define OB500_BT1V 0x5C /* Battery 1 present voltage 16 bit ? */ +#define OB500_BT1S 0x5E /* Battery 1 status 3 bit ? */ +#define OB500_BT2I 0x6A /* Battery 2 ? 16 bit */ +#define OB500_BT2C 0x6C /* Battery 2 remaining capacity 16 bit ? */ +#define OB500_BT2V 0x6E /* Battery 2 present voltage 16 bit ? */ +#define OB500_BT2S 0x70 /* Battery 2 status 3 bit ? */ +#define OB500_BT3I 0x5F /* Battery 3 ? 16 bit */ +#define OB500_BT3C 0x61 /* Battery 3 remaining capacity 16 bit ? */ +#define OB500_BT3V 0x63 /* Battery 3 present voltage 16 bit ? */ +#define OB500_BT3S 0x65 /* Battery 3 status 3 bit ? */ + +#define OB6000_STA1 0x77 /* Various status bits */ + +#define XE2_STA1 0x50 /* Various status bits */ /* * Bitmasks for sub byte values */ -#define OB500_LIDS_MASK 0x01 /* LID status */ -#define OB500_CRTS_MASK 0x20 /* External display status */ -#define OB500_SLPS_MASK 0x40 /* Sleep button status */ -#define OB500_DCKS_MASK 0x80 /* Docking status */ -#define OB500_ADP_MASK 0x02 /* AC acapter status */ -#define OB500_BST_MASK_DSC 0x01 /* Discarging */ -#define OB500_BST_MASK_CHR 0x02 /* Charging */ -#define OB500_BST_MASK_CRT 0x04 /* Critical */ +#define OB500_LIDS_MASK 0x01 /* LID status */ +#define OB500_CRTS_MASK 0x20 /* External display status */ +#define OB500_SLPS_MASK 0x40 /* Sleep button status */ +#define OB500_DCKS_MASK 0x80 /* Docking status */ +#define OB500_ADP_MASK 0x02 /* AC acapter status */ +#define OB500_BST_MASK_DSC 0x01 /* Discarging */ +#define OB500_BST_MASK_CHR 0x02 /* Charging */ +#define OB500_BST_MASK_CRT 0x04 /* Critical */ -#define OB6000_FAN_MASK 0x10 /* Fan status */ +#define OB6000_FAN_MASK 0x10 /* Fan status */ -#define XE2_ADP_MASK 0x02 /* AC acapter status */ +#define XE2_ADP_MASK 0x02 /* AC acapter status */ /* * OmniBook 4150 */ -#define OB4150_TMP 0x28 /* CPU tempetature, 8 bit */ -#define OB4150_STA1 0x2E /* Various status bits */ -#define OB4150_STA2 0x2F /* Various status bits */ -#define OB4150_ADP 0x30 /* AC acapter status, 1 bit */ -#define OB4150_DCID 0x2C /* Port replicator */ +#define OB4150_TMP 0x28 /* CPU tempetature, 8 bit */ +#define OB4150_STA1 0x2E /* Various status bits */ +#define OB4150_STA2 0x2F /* Various status bits */ +#define OB4150_ADP 0x30 /* AC acapter status, 1 bit */ +#define OB4150_DCID 0x2C /* Port replicator */ /* * Bitmasks for sub byte values */ -#define OB4150_FAN_MASK 0x01 /* Fan status */ -#define OB4150_ADP_MASK 0x40 /* AC acapter status */ -#define OB4150_CRST_MASK 0x20 /* External display status */ +#define OB4150_FAN_MASK 0x01 /* Fan status */ +#define OB4150_ADP_MASK 0x40 /* AC acapter status */ +#define OB4150_CRST_MASK 0x20 /* External display status */ /* * Keyboard controller command for some laptop functions */ -#define OMNIBOOK_KBC_CONTROL_CMD 0x59 +#define OMNIBOOK_KBC_CONTROL_CMD 0x59 /* * Keyboard controller command parameters for functions available via kbc @@ -306,47 +344,71 @@ struct omnibook_io_operation { * Other I/O ports */ -#define ACL00_AC_STAT 0x11B9 /* AC adapter status on ACL00 */ -#define ACL00_AC_MASK 0x04 /* Bitmask for AC adapter status on ACL00 */ -#define TOSH3K_AC_STAT 0x102D /* AC adapter status on Toshiba 3000 */ -#define TOSH3K_AC_MASK 0x08 /* Bitmask for AC adapter status on Toshiba 3000 */ -#define XE3GF_AC_STAT 0x11B9 /* AC adapter status on XE3 GF */ -#define XE3GF_AC_MASK 0x04 /* Bitmask for AC adapter status on XE3 GF */ -#define XE3GF_LID_STAT 0x11AD /* LID switch status on XE3 GF */ -#define XE3GF_LID_MASK 0x20 /* Bitmask for LID switch status on XE3 GF */ -#define XE3GC_SMIC 0xFE00 - -#define OB500_GPO1 0x8034 /* Fan control */ -#define OB510_GPO2 0x11B9 /* LCD backlight */ -#define OB510_GPIO 0x118F /* Fan control */ - -#define OB500_FAN_ON_MASK 0x0A /* Turn fan on with zero bits */ -#define OB500_FAN_OFF_MASK 0x08 /* Fan status/off */ -#define OB500_BKLT_MASK 0x40 /* LCD backlight */ -#define OB510_FAN_ON_MASK 0x18 /* Turn fan on with zero bits */ -#define OB510_FAN_OFF_MASK 0x10 /* Turn fan on */ -#define OB510_BKLT_MASK 0x01 /* LCD backlight */ - -#define XE2_FAN_MASK 0x02 /* Turn fan on with zero bit */ +#define ACL00_AC_STAT 0x11B9 /* AC adapter status on ACL00 */ +#define ACL00_AC_MASK 0x04 /* Bitmask for AC adapter status on ACL00 */ +#define TOSH3K_AC_STAT 0x102D /* AC adapter status on Toshiba 3000 */ +#define TOSH3K_AC_MASK 0x08 /* Bitmask for AC adapter status on Toshiba 3000 */ +#define XE3GF_AC_STAT 0x11B9 /* AC adapter status on XE3 GF */ +#define XE3GF_AC_MASK 0x04 /* Bitmask for AC adapter status on XE3 GF */ +#define XE3GF_LID_STAT 0x11AD /* LID switch status on XE3 GF */ +#define XE3GF_LID_MASK 0x20 /* Bitmask for LID switch status on XE3 GF */ +#define XE3GC_SMIC 0xFE00 + +#define OB500_GPO1 0x8034 /* Fan control */ +#define OB510_GPO2 0x11B9 /* LCD backlight */ +#define OB510_GPIO 0x118F /* Fan control */ + +#define OB500_FAN_ON_MASK 0x0A /* Turn fan on with zero bits */ +#define OB500_FAN_OFF_MASK 0x08 /* Fan status/off */ +#define OB500_BKLT_MASK 0x40 /* LCD backlight */ +#define OB510_FAN_ON_MASK 0x18 /* Turn fan on with zero bits */ +#define OB510_FAN_OFF_MASK 0x10 /* Turn fan on */ +#define OB510_BKLT_MASK 0x01 /* LCD backlight */ + +#define XE2_FAN_MASK 0x02 /* Turn fan on with zero bit */ /* * Memory adresses */ -#define XE3GC_BCMD 0xFFFFEBC +#define XE3GC_BCMD 0xFFFFEBC /* * Toshiba Satellite A105 values and mask */ -#define A105_BNDT 0xA3 /* LCD brightness */ -#define A105_BNDT_MASK 0x0F +#define A105_BNDT 0xA3 /* LCD brightness */ +#define A105_BNDT_MASK 0x0F /* * Index and values for Command/Data/Index interface */ -#define TSM70_FN_INDEX 0x45 -#define TSM70_FN_ENABLE 0x75 -#define TSM70_LCD_READ 0x5C -#define TSM70_LCD_WRITE 0x5D +#define TSM70_FN_INDEX 0x45 +#define TSM70_FN_ENABLE 0x75 +#define TSM70_FN_DISABLE 0x74 +#define TSM70_HOTKEYS_INDEX 0x59 +#define TSM70_HOTKEYS_ENABLE 0x90 +#define TSM70_LCD_READ 0x5C +#define TSM70_LCD_WRITE 0x5D +#define TSM70_TOUCHPAD_ON 0x80 +#define TSM70_TOUCHPAD_OFF 0x81 + +/* Toshiba SMI funtion */ +#define SMI_FN_PRESSED 0x00 +#define SMI_SET_LCD_BRIGHTNESS 0xa2 +#define SMI_GET_LCD_BRIGHTNESS 0xa3 +#define SMI_GET_KILL_SWITCH 0xa4 +#define SMI_SET_AERIAL 0xa5 +#define SMI_GET_AERIAL 0xa6 +#define SMI_SET_DISPLAY_STATE 0xa7 +#define SMI_GET_DISPLAY_STATE 0xa8 +#define SMI_SET_FN_INTERFACE 0xa9 +#define SMI_GET_FN_INTERFACE 0xaa +#define SMI_GET_FN_LAST_SCAN 0xab +#define SMI_SET_FN_F5_INTERFACE 0xc2 + +#define SMI_FN_KEYS_MASK 0x01 +#define SMI_STICK_KEYS_MASK 0x02 +#define SMI_FN_TWICE_LOCK_MASK 0x04 +#define SMI_FN_DOCK_MASK 0x08 diff --git a/fan.c b/fan.c index 31c35d3..5989eb6 100644 --- a/fan.c +++ b/fan.c @@ -15,212 +15,88 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif #include #include #include "ec.h" -static int omnibook_get_fan(void) +static struct omnibook_operation ctmp_io_op = { EC, XE3GF_CTMP , 0, 0, 0, 0}; +static struct omnibook_operation fot_io_op = { EC, XE3GF_FOT, XE3GF_FOT, 0, 0, 0}; + +static int omnibook_get_fan(struct omnibook_operation *io_op) { u8 fan; int retval; + if((retval = io_op->backend->byte_read(io_op, &fan))) + return retval; + /* - * XE3GF - * TSP10 + * For most models the reading is a bool + * It as to be inverted on all but OB6000|OB6100|OB4150|AMILOD + * TSP10|XE3GF return an integer */ - if (omnibook_ectype & (XE3GF|TSP10) ) { - if ((retval = omnibook_ec_read(XE3GF_FSRD, &fan))) - return retval; + + if(omnibook_ectype & (TSP10|XE3GF)) retval = fan; - /* - * OB500 - */ - } else if (omnibook_ectype & (OB500) ) { - fan = inb(OB500_GPO1); - retval = (fan & OB500_FAN_OFF_MASK) ? 0 : 1; - /* - * OB510 - */ - } else if (omnibook_ectype & (OB510) ) { - fan = inb(OB510_GPIO); - retval = (fan & OB510_FAN_OFF_MASK) ? 0 : 1; - /* - * OB6000 - * OB6100 - */ - } else if (omnibook_ectype & (OB6000|OB6100) ) { - if ((retval = omnibook_ec_read(OB6000_STA1, &fan))) - return retval; - retval = (fan & OB6000_FAN_MASK) ? 1 : 0; - /* - * OB4150 - * AMILOD - */ - } else if (omnibook_ectype & (OB4150|AMILOD) ) { - if ((retval = omnibook_ec_read(OB4150_STA1, &fan))) - return retval; - retval = (fan & OB4150_FAN_MASK) ? 1 : 0; - /* - * XE2 - */ - } else if (omnibook_ectype & (XE2) ) { - fan = inb(OB500_GPO1); - retval = (fan & XE2_FAN_MASK) ? 0 : 1; - } else { - printk(O_INFO "Fan status monitoring is unsupported on this machie.\n"); - retval = -ENODEV; - } + else if(omnibook_ectype & (OB6000|OB6100|OB4150|AMILOD)) + retval = !!fan; + else + retval = !fan; return retval; } -static int omnibook_fan_on(void) +static int omnibook_fan_on(struct omnibook_operation *io_op) { - u8 fan; - int retval = 0; - - /* - * XE3GF - * TSP10 - */ - if (omnibook_ectype & (XE3GF|TSP10) ) { - if ((retval = omnibook_ec_read(XE3GF_FSRD, &fan))) - return retval; - if ((retval = omnibook_ec_write(XE3GF_FSRD, fan | XE3GF_FAN_ON_MASK))) - return retval; - /* - * OB500 - */ - } else if (omnibook_ectype & (OB500) ) { - fan = inb(OB500_GPO1); - outb(fan & ~OB500_FAN_ON_MASK, OB500_GPO1); - - /* - * OB510 - */ - } else if (omnibook_ectype & (OB510) ) { - fan = inb(OB510_GPIO); - outb(fan & ~OB510_FAN_ON_MASK, OB510_GPIO); - /* - * OB6000 - * OB6100 - */ - } else if (omnibook_ectype & (OB6000|OB6100) ) { - - if ((retval = omnibook_ec_read(OB6000_STA1, &fan))) - return retval; - if ((retval = omnibook_ec_write(OB6000_STA1, fan | OB6000_FAN_MASK))) - return retval; - /* - * OB4150 - * AMILOD - */ - } else if (omnibook_ectype & (OB4150|AMILOD) ) { - if ((retval = omnibook_ec_read(OB4150_STA1, &fan))) - return retval; - if ((retval = omnibook_ec_write(OB4150_STA1, fan | OB4150_FAN_MASK))) - return retval; - /* - * XE2 - */ - } else if (omnibook_ectype & (XE2) ) { - fan = inb(OB500_GPO1); - outb(fan & ~XE2_FAN_MASK, OB500_GPO1); - } else { - printk(O_INFO "Direct fan control is unsupported on this machie.\n"); - retval = -ENODEV; - } - - return retval; + return omnibook_apply_write_mask(io_op,1); } -static int omnibook_fan_off(void) +static int omnibook_fan_off(struct omnibook_operation *io_op) { - u8 fan; int retval = 0; - /* - * XE3GF - * TSP10 - */ +/* + * Special handling for XE3GF & TSP10 + */ if (omnibook_ectype & (XE3GF|TSP10) ) { u8 fot, temp; - if ((retval = omnibook_ec_read(XE3GF_FSRD, &fan))) + retval = omnibook_get_fan(io_op); + + /* error or fan is already off */ + if (retval <= 0 ) return retval; - /* fan is already off */ - if (!fan) - return 0; - /* now we set FOT to current temp, then reset to initial value */ - if ((retval = omnibook_ec_read(XE3GF_FOT, &fot))) + if ((retval = fot_io_op.backend->byte_read(&fot_io_op, &fot))) return retval; - if ((retval = omnibook_ec_read(XE3GF_CTMP, &temp))) + if ((retval = ctmp_io_op.backend->byte_read(&ctmp_io_op, &temp))) return retval; - + +/* + * FIXME: should add a timeout + */ do { - omnibook_ec_write(XE3GF_FOT, temp); + fot_io_op.backend->byte_write(&fot_io_op, temp); mdelay(1); - } while (omnibook_get_fan() != 0); + } while (omnibook_get_fan(io_op) != 0); - omnibook_ec_write(XE3GF_FOT, fot); - /* - * OB500 - */ - } else if (omnibook_ectype & (OB500) ) { - fan = inb(OB500_GPO1); - outb(fan | OB500_FAN_OFF_MASK, OB500_GPO1); - /* - * OB510 - */ - } else if (omnibook_ectype & (OB510) ) { - fan = inb(OB510_GPIO); - outb(fan | OB510_FAN_OFF_MASK, OB510_GPIO); - /* - * OB6000 - * OB6100 - */ - } else if (omnibook_ectype & (OB6000|OB6100) ) { - if ((retval = omnibook_ec_read(OB6000_STA1, &fan))) - return retval; - if ((retval = omnibook_ec_write(OB6000_STA1, fan & ~OB6000_FAN_MASK))) - return retval; - /* - * OB4150 - * AMILOD - */ - } else if (omnibook_ectype & (OB4150|AMILOD) ) { - if ((retval = omnibook_ec_read(OB4150_STA1, &fan))) - return retval; - if ((retval = omnibook_ec_write(OB4150_STA1, fan & ~OB4150_FAN_MASK))) - return retval; - /* - * XE2 - */ - } else if (omnibook_ectype & (XE2) ) { - fan = inb(OB500_GPO1); - outb(fan | XE2_FAN_MASK, OB500_GPO1); - } else { - printk(O_INFO "Direct fan control is unsupported on this machie.\n"); - retval = -ENODEV; - } + fot_io_op.backend->byte_write(&fot_io_op, fot); + + } else + retval = omnibook_apply_write_mask(io_op, 0); return retval; } -static int omnibook_fan_read(char *buffer) +static int omnibook_fan_read(char *buffer,struct omnibook_operation *io_op) { int fan; int len = 0; char *str; - fan = omnibook_get_fan(); + fan = omnibook_get_fan(io_op); if (fan < 0) return fan; str = (fan) ? "on" : "off"; @@ -233,17 +109,17 @@ static int omnibook_fan_read(char *buffer) return len; } -static int omnibook_fan_write(char *buffer) +static int omnibook_fan_write(char *buffer,struct omnibook_operation *io_op) { int retval; switch (*buffer) { case '0': - if ((retval = omnibook_fan_off())) + if ((retval = omnibook_fan_off(io_op))) return retval; break; case '1': - if ((retval = omnibook_fan_on())) + if ((retval = omnibook_fan_on(io_op))) return retval; break; default: @@ -254,7 +130,7 @@ static int omnibook_fan_write(char *buffer) static struct omnibook_feature fan_feature; -static int omnibook_fan_init(void) +static int __init omnibook_fan_init(struct omnibook_operation *io_op) { /* * OB4150 @@ -267,13 +143,24 @@ static int omnibook_fan_init(void) return 0; } -static struct omnibook_feature __declared_feature fan_feature = { +static struct omnibook_tbl fan_table[] __initdata = { + { XE3GF|TSP10, {EC,XE3GF_FSRD,XE3GF_FSRD,0,XE3GF_FAN_ON_MASK,0}}, + { OB500, {PIO,OB500_GPO1,OB500_GPO1,OB500_FAN_OFF_MASK,-OB500_FAN_ON_MASK,OB500_FAN_OFF_MASK}}, + { OB510, {PIO,OB510_GPIO,OB510_GPIO,OB510_FAN_OFF_MASK,-OB510_FAN_ON_MASK,OB510_FAN_OFF_MASK}}, + { OB6000|OB6100, {EC,OB6000_STA1,OB6000_STA1,OB6000_FAN_MASK,OB6000_FAN_MASK,-OB6000_FAN_MASK}}, + { OB4150|AMILOD, {EC,OB4150_STA1,0,OB4150_FAN_MASK,0,0}}, + { XE2, {PIO,OB500_GPO1,0,XE2_FAN_MASK,0,0}}, + { 0,} +}; + +static struct omnibook_feature __declared_feature fan_driver = { .name = "fan", .enabled = 1, .read = omnibook_fan_read, .write = omnibook_fan_write, .init = omnibook_fan_init, .ectypes = XE3GF|OB500|OB510|OB6000|OB6100|OB4150|XE2|AMILOD|TSP10, + .tbl = fan_table, }; module_param_named(fan, fan_feature.enabled, int, S_IRUGO); diff --git a/fan_policy.c b/fan_policy.c index e7aeca6..d5b49e9 100644 --- a/fan_policy.c +++ b/fan_policy.c @@ -15,11 +15,7 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif #include #include "ec.h" @@ -56,7 +52,7 @@ static int omnibook_get_fan_policy(void) */ if (omnibook_ectype & (XE3GF) ) { for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) { - if ((retval = omnibook_ec_read(XE3GF_FOT + i, &tmp))) + if ((retval = legacy_ec_read(XE3GF_FOT + i, &tmp))) return retval; omnibook_fan_policy[i] = tmp; } @@ -90,7 +86,7 @@ static int omnibook_set_fan_policy(void) } for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) { if ((retval = - omnibook_ec_write(XE3GF_FOT + i, omnibook_fan_policy[i]))) + legacy_ec_write(XE3GF_FOT + i, omnibook_fan_policy[i]))) return retval; } } else { @@ -121,7 +117,7 @@ static int omnibook_set_fan_policy_defaults(void) */ if (omnibook_ectype & (XE3GF) ) { for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) { - if ((retval = omnibook_ec_write(XE3GF_FOT + i, fan_defaults[i]))) + if ((retval = legacy_ec_write(XE3GF_FOT + i, fan_defaults[i]))) return retval; } } else { @@ -132,7 +128,7 @@ static int omnibook_set_fan_policy_defaults(void) return retval; } -static int omnibook_fan_policy_read(char *buffer) +static int omnibook_fan_policy_read(char *buffer,struct omnibook_operation *io_op) { int retval; int len = 0; @@ -163,7 +159,7 @@ static int omnibook_fan_policy_read(char *buffer) return len; } -static int omnibook_fan_policy_write(char *buffer) +static int omnibook_fan_policy_write(char *buffer,struct omnibook_operation *io_op) { int n = 0; char *b; @@ -205,7 +201,7 @@ static int omnibook_fan_policy_write(char *buffer) return 0; } -static struct omnibook_feature __declared_feature fan_policy_feature = { +static struct omnibook_feature __declared_feature fan_policy_driver = { .name = "fan_policy", .enabled = 1, .read = omnibook_fan_policy_read, @@ -213,6 +209,6 @@ static struct omnibook_feature __declared_feature fan_policy_feature = { .ectypes = XE3GF, }; -module_param_named(fan_policy, fan_policy_feature.enabled, int, S_IRUGO); +module_param_named(fan_policy, fan_policy_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(fan_policy, "Use 0 to disable, 1 to enable fan control policy support"); /* End of file */ diff --git a/hotkeys.c b/hotkeys.c index d6da6bc..3fd00a9 100644 --- a/hotkeys.c +++ b/hotkeys.c @@ -15,80 +15,47 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif - #include "ec.h" -/* - * There is no information about reading Hotkeys status - */ -static int omnibook_hotkeys_enabled = 0; /* - * Some laptop model have require more work to enable an Fn+button hotkeys + * Save state for suspend/resume operation */ -static int omnibook_fnkeys_enabled = 0; +static unsigned int saved_state; -/* - * Enable hotkeys sending command to the i8042 - */ -static int omnibook_hotkeys_on(void) -{ - int retval; - - if ((retval =omnibook_kbc_command - (OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE))) { - printk(O_ERR "Hotkeys enable command failed.\n"); - return retval; - } - omnibook_hotkeys_enabled = 1; - printk(O_INFO "Enabling Hotkey buttons.\n"); - return 0; -} +/* Predefined convinient on/off states */ +#define HKEY_ON HKEY_ONETOUCH|HKEY_MULTIMEDIA|HKEY_FN|HKEY_DOCK|HKEY_FNF5 +#define HKEY_OFF 0 -/* - * Disable hotkeys sending command to the i8042 - */ -static int omnibook_hotkeys_off(void) +static int omnibook_hotkeys_set(struct omnibook_operation *io_op, unsigned int state) { - int retval; + int write_capability; + + write_capability = io_op->backend->hotkeys_set(io_op, state); + if( write_capability < 0) + return write_capability; + + /* Update saved state */ + saved_state = state & write_capability; - if ((retval = omnibook_kbc_command - (OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE))) { - printk(O_ERR "Hotkeys disable command failed.\n"); - return retval; - } - omnibook_hotkeys_enabled = 0; - printk(O_INFO "Disabling Hotkey buttons.\n"); return 0; } -/* - * Enable Fn+foo key writing 75h to EC index 45h - */ -static int omnibook_fnkeys_on(void) +static int omnibook_hotkeys_get(struct omnibook_operation *io_op, unsigned int *state) { - int retval; - if ((retval = omnibook_cdimode_write(TSM70_FN_INDEX, TSM70_FN_ENABLE))) { - printk(O_ERR "fnkeys enable command failed.\n"); - return retval; - } - omnibook_fnkeys_enabled = 1; - printk(O_INFO "Enabling Fn keys.\n"); - return 0; -} + unsigned int read_state = 0; + int read_capability = 0; + + if(io_op->backend->hotkeys_get) + read_capability = io_op->backend->hotkeys_get(io_op, &read_state); + if(read_capability < 0) + return read_capability; -/* - * FIXME Not implemented - */ -static int omnibook_fnkeys_off(void) -{ - printk(O_WARN "Disabling of Fn keys not implemented.\n"); + /* Return previously set state for the fields that are write only */ + *state = (read_state & read_capability) + (saved_state & ~read_capability); + return 0; } @@ -97,104 +64,106 @@ static int omnibook_fnkeys_off(void) */ /* - * omnibook_*keys_enabled = 1 means here "It was enabled prior to suspend, - * please reenable" + * Restore previously saved state */ -static int omnibook_hotkeys_resume(void) -{ - int retval = 0; - retval = (omnibook_hotkeys_enabled ? omnibook_hotkeys_on() : 0); - if (omnibook_ectype & TSM30X) - retval = (omnibook_fnkeys_enabled ? omnibook_fnkeys_on() : 0); - return retval; -} - -static int omnibook_hotkeys_suspend(void) +static int omnibook_hotkeys_resume(struct omnibook_operation *io_op) { - int retval = 0; - retval = (omnibook_hotkeys_enabled ? omnibook_hotkeys_off() : 0); - if (omnibook_ectype & TSM30X) - retval = (omnibook_fnkeys_enabled ? omnibook_fnkeys_off() : 0); - return retval; + int retval; + retval = io_op->backend->hotkeys_set(io_op, saved_state); + return min(retval,0); } -static int omnibook_hotkeys_enable(void) +/* + * Save state and disable hotkeys upon suspend (FIXME is the disabling required ?) + */ +static int omnibook_hotkeys_suspend(struct omnibook_operation *io_op) { int retval = 0; - if (!omnibook_hotkeys_enabled ) - retval = omnibook_hotkeys_on(); - if ((!omnibook_fnkeys_enabled) && ( omnibook_ectype & TSM30X )) - retval = omnibook_fnkeys_on(); + retval = omnibook_hotkeys_get(io_op, &saved_state); + if(retval < 0) + return retval; - return retval; + retval = io_op->backend->hotkeys_set(io_op, HKEY_OFF); + if(retval < 0) + return retval; + + return 0; } -static int omnibook_hotkeys_disable(void) -{ - int retval = 0; - - if (omnibook_hotkeys_enabled ) - retval = omnibook_hotkeys_off(); - if (omnibook_fnkeys_enabled && ( omnibook_ectype & TSM30X )) - retval = omnibook_fnkeys_off(); - - return retval; -} +static const char pretty_name[][27] = { + "Onetouch buttons", + "Multimedia hotkeys are", + "Fn hotkeys are", + "Stick key is", + "Press Fn twice to lock is", + "Dock events are", + "Fn + F5 hotkey is" +}; -static int omnibook_hotkeys_read(char *buffer) +static int omnibook_hotkeys_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; - - len += sprintf(buffer + len, "Hotkey buttons are %s\n", - (omnibook_hotkeys_enabled) ? "enabled" : "disabled"); - - if (omnibook_ectype & TSM30X ) - len += sprintf(buffer + len, "Fn keys are %s\n", - (omnibook_fnkeys_enabled) ? "enabled" : "disabled"); - return len; -} - -static int omnibook_hotkeys_write(char *buffer) -{ - int retval = 0; - switch (*buffer) { - case '0': - retval = omnibook_hotkeys_disable(); - break; - case '1': - retval = omnibook_hotkeys_enable(); - break; - default: - retval = -EINVAL; + int read_capability, write_capability; + unsigned int read_state, mask; + + read_capability = omnibook_hotkeys_get(io_op, &read_state); + if(read_capability < 0) + return read_capability; + + write_capability = omnibook_hotkeys_set(io_op, read_state); + if(write_capability < 0) + return write_capability; + + for( mask = DISPLAY_LCD_ON ; mask <= HKEY_FNF5; mask = mask << 1) { + /* we assume write capability or read capability imply support */ + if( (read_capability | write_capability ) & mask ) + len += sprintf(buffer + len, "%s %s.\n", + pretty_name[ ffs(mask) - 1 ], + ( read_state & mask ) ? "enabled" : "disabled"); } - return retval; + return len; } -static int omnibook_hotkeys_init(void) +static int omnibook_hotkeys_write(char *buffer,struct omnibook_operation *io_op) { - int retval = 0; + unsigned int state; + char *endp; - if ((omnibook_ectype & TSM30X) && omnibook_cdimode_init()) { - retval = -ENODEV; - goto out; + if (strncmp(buffer, "off", 3) == 0) + omnibook_hotkeys_set(io_op, HKEY_OFF); + else if (strncmp(buffer, "on", 2) == 0) + omnibook_hotkeys_set(io_op, HKEY_ON); + else { + state = simple_strtoul(buffer, &endp, 16); + if (endp == buffer) + return -EINVAL; + else + omnibook_hotkeys_set(io_op, state); } - - retval = omnibook_hotkeys_enable(); + return 0; +} -out: - return retval; +static int __init omnibook_hotkeys_init(struct omnibook_operation *io_op) +{ + printk(O_INFO "Enabling all hotkeys.\n"); + return omnibook_hotkeys_set(io_op, HKEY_ON); } -static void omnibook_hotkeys_cleanup(void) +static void __exit omnibook_hotkeys_cleanup(struct omnibook_operation *io_op) { - omnibook_hotkeys_disable(); - - if (omnibook_ectype & TSM30X) - omnibook_cdimode_exit(); + printk(O_INFO "Disabling all hotkeys.\n"); + omnibook_hotkeys_set(io_op, HKEY_OFF); } -static struct omnibook_feature __declared_feature hotkeys_feature = { +static struct omnibook_tbl hotkey_table[] __initdata = { + { XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|AMILOD|TSP10, {KBC,}}, + { TSM30X, {CDI,}}, + { TSM40, {SMI,}}, + { 0,} +}; + +static struct omnibook_feature __declared_feature hotkeys_driver = { .name = "hotkeys", .enabled = 1, .read = omnibook_hotkeys_read, @@ -203,9 +172,10 @@ static struct omnibook_feature __declared_feature hotkeys_feature = { .exit = omnibook_hotkeys_cleanup, .suspend = omnibook_hotkeys_suspend, .resume = omnibook_hotkeys_resume, - .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|AMILOD|TSP10|TSM30X, + .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|AMILOD|TSP10|TSM30X|TSM40, + .tbl = hotkey_table, }; -module_param_named(hotkeys, hotkeys_feature.enabled, int, S_IRUGO); +module_param_named(hotkeys, hotkeys_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(hotkeys, "Use 0 to disable, 1 to enable hotkeys handling"); /* End of file */ diff --git a/info.c b/info.c index 4049d88..386f7f9 100644 --- a/info.c +++ b/info.c @@ -15,16 +15,12 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif #include #include -static int omnibook_version_read(char *buffer) +static int omnibook_version_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; @@ -33,7 +29,7 @@ static int omnibook_version_read(char *buffer) return len; } -static int omnibook_dmi_read(char *buffer) +static int omnibook_dmi_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; @@ -70,19 +66,19 @@ static int omnibook_dmi_read(char *buffer) return len; } -static struct omnibook_feature __declared_feature version_feature = { +static struct omnibook_feature __declared_feature version_driver = { .name = "version", .enabled = 1, .read = omnibook_version_read, }; -static struct omnibook_feature __declared_feature dmi_feature = { +static struct omnibook_feature __declared_feature dmi_driver = { .name = "dmi", .enabled = 1, .read = omnibook_dmi_read, }; -module_param_named(dmi, dmi_feature.enabled, int, S_IRUGO); +module_param_named(dmi, dmi_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(dmi, "Use 0 to disable, 1 to enable DMI informations display support"); /* End of file */ diff --git a/init.c b/init.c index 9972186..b39face 100644 --- a/init.c +++ b/init.c @@ -15,11 +15,7 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif #include #include @@ -38,7 +34,8 @@ static struct proc_dir_entry *omnibook_proc_root = NULL; -int omnibook_ectype = NONE; +enum omnibook_ectype_t omnibook_ectype = NONE; + static char* laptop_model __initdata; static int omnibook_userset = 0; @@ -88,8 +85,8 @@ static struct platform_device omnibook_device = { static struct omnibook_feature *omnibook_available_feature; /* Delimiters of the .features section wich holds all the omnibook_feature structs */ -extern struct omnibook_feature _features_start[]; -extern struct omnibook_feature _features_end[]; +extern struct omnibook_feature _start_features_driver[]; +extern struct omnibook_feature _end_features_driver[]; static int __init dmi_matched(struct dmi_system_id *dmi) { @@ -113,7 +110,7 @@ static int procfile_read_dispatch(char *page, char **start, off_t off, if (!feature || !feature->read) return -EINVAL; - len = feature->read(page); + len = feature->read(page,feature->io_op); if (len < 0) return len; @@ -155,7 +152,7 @@ static int procfile_write_dispatch(struct file *file, /* Make sure the string is \0 terminated */ kernbuf[count] = '\0'; - retval = feature->write(kernbuf); + retval = feature->write(kernbuf,feature->io_op); if (retval == 0) retval = count; @@ -164,23 +161,71 @@ static int procfile_write_dispatch(struct file *file, return retval; } +/* + * Match an ectype and return pointer to corresponding omnibook_operation. + * Also make corresponding backend initialisation if necessary, and skip + * to the next entry if it fails. + */ +static struct omnibook_operation * omnibook_backend_match(struct omnibook_tbl *tbl) +{ + int i; + struct omnibook_operation *matched = NULL; + + for (i = 0; tbl[i].ectypes ; i++) { + if (omnibook_ectype & tbl[i].ectypes) { + if(tbl[i].io_op.backend->init && tbl[i].io_op.backend->init(&tbl[i].io_op)) { + dprintk("Backend %s init failed, skipping entry.\n", tbl[i].io_op.backend->name); + continue; + } + matched = &tbl[i].io_op; + dprintk("Returning table entry n°%i.\n",i); + break; + } + } + return matched; +} + + /* * Initialise a feature and add it to the linked list of active features */ static int __init omnibook_init(struct omnibook_feature *feature) { - int retval; + int retval = 0; mode_t pmode; struct proc_dir_entry *proc_entry; + struct omnibook_operation *op; if (!feature) return -EINVAL; - if (feature->init) { - retval = feature->init(); - if (retval) +/* + * Select appropriate backend for feature operations + * We copy the io_op field so the tbl can be initdata + */ + if(feature->tbl) { + dprintk("begin table match of %s feature.\n",feature->name); + op = omnibook_backend_match(feature->tbl); + if(!op) { + dprintk("match failed: disabling %s.\n",feature->name); return -ENODEV; - } + } + feature->io_op = kmalloc(sizeof(struct omnibook_operation),GFP_KERNEL); + if (!feature->io_op) + return -ENOMEM; + memcpy(feature->io_op, op, sizeof(struct omnibook_operation)); + } else + dprintk("%s feature has no backend table, io_op not initialized.\n",feature->name); + +/* + * Specific feature init code + */ + if (feature->init && (retval = feature->init(feature->io_op))) + goto err; + +/* + * procfs file setup + */ if (feature->name && feature->read) { pmode = S_IFREG | S_IRUGO; if (feature->write) { @@ -189,21 +234,22 @@ static int __init omnibook_init(struct omnibook_feature *feature) pmode |= S_IWUGO; } /* - * Special case for apmemu + * FIXME: Special case for apmemu (not under /proc/omnibook) */ - if (feature->proc_entry) { + if (feature->proc_entry) proc_entry = create_proc_entry(feature->proc_entry, pmode, NULL); - } else { - proc_entry = create_proc_entry(feature->name, pmode, + else + proc_entry = create_proc_entry(feature->name, pmode, omnibook_proc_root); - } + if (!proc_entry) { printk(O_ERR "Unable to create proc entry %s\n",feature->name); if (feature->exit) - feature->exit(); - return -ENOENT; + feature->exit(feature->io_op); + retval = -ENOENT; + goto err; } proc_entry->data = feature; proc_entry->read_proc = &procfile_read_dispatch; @@ -213,6 +259,9 @@ static int __init omnibook_init(struct omnibook_feature *feature) } list_add_tail(&feature->list, &omnibook_available_feature->list); return 0; +err: + kfree(feature->io_op); + return retval; } @@ -233,9 +282,9 @@ static int __init omnibook_probe(struct platform_device *dev) return -ENOMEM; INIT_LIST_HEAD(&omnibook_available_feature->list); - for (i=0; i < _features_end - _features_start; i++ ) { + for (i=0; i < _end_features_driver - _start_features_driver; i++ ) { - feature = &_features_start[i]; + feature = &_start_features_driver[i]; if (!feature->enabled) continue; @@ -266,12 +315,17 @@ static int __exit omnibook_remove(struct platform_device *dev) list_for_each_safe(p, n, &omnibook_available_feature->list) { feature = list_entry(p, struct omnibook_feature, list); list_del(p); - if (feature->exit) - feature->exit(); + /* Feature specific cleanup */ + if (feature->exit) + feature->exit(feature->io_op); + /* Generic backend cleanup */ + if (feature->io_op && feature->io_op->backend->exit) + feature->io_op->backend->exit(feature->io_op); if (feature->proc_entry) remove_proc_entry(feature->proc_entry, NULL); else if (feature->name) remove_proc_entry(feature->name, omnibook_proc_root); + kfree(feature->io_op); } kfree(omnibook_available_feature); @@ -290,7 +344,7 @@ static int omnibook_suspend(struct platform_device *dev, pm_message_t state) list_for_each(p, &omnibook_available_feature->list) { feature = list_entry(p, struct omnibook_feature, list); if (feature->suspend) { - retval = feature->suspend(); + retval = feature->suspend(feature->io_op); if (!retval) printk(O_ERR "Unable to suspend the %s feature", @@ -312,7 +366,7 @@ static int omnibook_resume(struct platform_device *dev) list_for_each(p, &omnibook_available_feature->list) { feature = list_entry(p, struct omnibook_feature, list); if (feature->resume) { - retval = feature->resume(); + retval = feature->resume(feature->io_op); if (!retval) printk(O_ERR "Unable to resume the %s feature", @@ -353,7 +407,7 @@ static int __init omnibook_module_init(void) if (omnibook_ectype != NONE) printk(O_WARN - "Forced load with EC firmware type %i.\n", ffs(omnibook_ectype)); + "Forced load with EC type %i.\n", ffs(omnibook_ectype)); else if ( dmi_check_system(omnibook_ids) ) printk(O_INFO "%s detected.\n", laptop_model); else diff --git a/lcd.c b/lcd.c index 2e4c2f7..3a06a0b 100644 --- a/lcd.c +++ b/lcd.c @@ -16,12 +16,7 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif - #include #ifdef CONFIG_OMNIBOOK_BACKLIGHT @@ -30,7 +25,7 @@ #include "ec.h" -static int omnibook_max_brightness; +static unsigned int omnibook_max_brightness; #ifdef CONFIG_OMNIBOOK_BACKLIGHT @@ -47,24 +42,15 @@ static struct backlight_properties omnibookbl_data = { #endif -static const struct omnibook_io_operation lcd_io_table[] = { - { TSM30X, CDI, TSM70_LCD_READ, TSM70_LCD_WRITE, 0}, - { XE3GF|TSP10|TSM40, EC, XE3GF_BRTS, XE3GF_BRTS, XE3GF_BRTS_MASK}, - { XE3GC, EC, XE3GC_BTVL, XE3GC_BTVL, XE3GC_BTVL_MASK}, - { AMILOD, EC, AMILOD_CBRG, AMILOD_CBRG, XE3GC_BTVL_MASK}, - { TSA105, EC, A105_BNDT, A105_BNDT, A105_BNDT_MASK}, - { 0,} -}; - -static struct omnibook_io_operation *lcd_io; - #ifdef CONFIG_OMNIBOOK_BACKLIGHT static int omnibook_get_backlight(struct backlight_device *bd) { int retval = 0; + struct omnibook_operation *io_op; u8 brgt; - retval = omnibook_io_read(lcd_io, &brgt); + io_op = class_get_devdata(&bd->class_dev); + retval = io_op->backend->byte_read(io_op, &brgt); if (!retval) retval = brgt; @@ -73,27 +59,29 @@ static int omnibook_get_backlight(struct backlight_device *bd) static int omnibook_set_backlight(struct backlight_device *bd) { - int intensity = bd->props->brightness; - return omnibook_io_write(lcd_io, intensity); + u8 intensity = bd->props->brightness; + struct omnibook_operation *io_op; + + io_op = class_get_devdata(&bd->class_dev); + return io_op->backend->byte_write(io_op, intensity); } #endif -static int omnibook_brightness_read(char *buffer) +static int omnibook_brightness_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; - int retval; u8 brgt; - retval = omnibook_io_read(lcd_io, &brgt); - if (retval) - return retval; + io_op->backend->byte_read(io_op, &brgt); - len += sprintf(buffer + len, "LCD brightness: %2d\n", brgt); + len += sprintf(buffer + len, "LCD brightness: %2d (max value: %d)\n", + brgt, + omnibook_max_brightness); return len; } -static int omnibook_brightness_write(char *buffer) +static int omnibook_brightness_write(char *buffer,struct omnibook_operation *io_op) { int brgt = 0; char *endp; @@ -103,21 +91,21 @@ static int omnibook_brightness_write(char *buffer) else if (strncmp(buffer, "on", 2) == 0) omnibook_lcd_blank(0); else { - brgt = simple_strtol(buffer, &endp, 10); + brgt = simple_strtoul(buffer, &endp, 10); if ((endp == buffer) || (brgt < 0) || (brgt > omnibook_max_brightness)) return -EINVAL; else - omnibook_io_write(lcd_io, brgt); + io_op->backend->byte_write(io_op, brgt); } return 0; } -static int omnibook_brightness_init(void) +static int __init omnibook_brightness_init(struct omnibook_operation *io_op) { /* * FIXME: What is exactly de max value for each model ? * I know that it's 7 for the TSM30X, TSM40 and TSA105 - * and previous versions of this driver assumed it was 10 for + * and previous versions of this driver (wrongly) assumed it was 10 for * all models. * * TSM30X @@ -126,19 +114,16 @@ static int omnibook_brightness_init(void) */ if (omnibook_ectype & (TSM30X|TSM40|TSA105) ) omnibook_max_brightness = 7; - else + else { omnibook_max_brightness = 10; - - printk(O_INFO "LCD brightness is between 0 and %i.\n", - omnibook_max_brightness); - - if (!(lcd_io = omnibook_io_match(lcd_io_table))) - return -ENODEV; + printk(O_WARN "Assuming that LCD brightness is between 0 and %i,\n", omnibook_max_brightness); + printk(O_WARN "please contact http://sourceforge.net/projects/omnibook to confirm.\n"); + } #ifdef CONFIG_OMNIBOOK_BACKLIGHT omnibookbl_data.max_brightness = omnibook_max_brightness; omnibook_backlight_device = - backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, &omnibookbl_data); + backlight_device_register(OMNIBOOK_MODULE_NAME, (void *) io_op, &omnibookbl_data); if (IS_ERR(omnibook_backlight_device)) { printk(O_ERR "Unable to register as backlight device.\n"); return -ENODEV; @@ -147,16 +132,24 @@ static int omnibook_brightness_init(void) return 0; } -static void omnibook_brightness_cleanup(void) +static void __exit omnibook_brightness_cleanup(struct omnibook_operation *io_op) { #ifdef CONFIG_OMNIBOOK_BACKLIGHT backlight_device_unregister(omnibook_backlight_device); #endif - - if(lcd_io->type == CDI) - omnibook_cdimode_exit(); } -static struct omnibook_feature __declared_feature lcd_feature = { + +static struct omnibook_tbl lcd_table[] __initdata = { + { TSM30X, {CDI,TSM70_LCD_READ,TSM70_LCD_WRITE,0,0,0}}, + { TSM40, {SMI,SMI_GET_LCD_BRIGHTNESS,SMI_SET_LCD_BRIGHTNESS,0,0,0}}, + { XE3GF|TSP10|TSM30X, SIMPLE_BYTE(EC,XE3GF_BRTS,XE3GF_BRTS_MASK)}, + { XE3GC, SIMPLE_BYTE(EC,XE3GC_BTVL,XE3GC_BTVL_MASK)}, + { AMILOD, SIMPLE_BYTE(EC,AMILOD_CBRG,XE3GC_BTVL_MASK)}, + { TSA105, SIMPLE_BYTE(EC,A105_BNDT,A105_BNDT_MASK)}, + { 0,} +}; + +static struct omnibook_feature __declared_feature lcd_driver = { .name = "lcd", .enabled = 1, .read = omnibook_brightness_read, @@ -164,9 +157,10 @@ static struct omnibook_feature __declared_feature lcd_feature = { .init = omnibook_brightness_init, .exit = omnibook_brightness_cleanup, .ectypes = XE3GF|XE3GC|AMILOD|TSP10|TSM30X|TSM40|TSA105, + .tbl = lcd_table, }; -module_param_named(lcd, lcd_feature.enabled, int, S_IRUGO); +module_param_named(lcd, lcd_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(lcd, "Use 0 to disable, 1 to enable to LCD brightness support"); /* End of file */ diff --git a/misc/omnibook-integration.patch b/misc/omnibook-integration.patch index 3d046dc..445d437 100644 --- a/misc/omnibook-integration.patch +++ b/misc/omnibook-integration.patch @@ -1,19 +1,21 @@ -diff -Nru linux-2.6.17/arch/i386/Kconfig linux-2.6.17-omnibook/arch/i386/Kconfig --- linux-2.6.17/arch/i386/Kconfig 2006-06-18 03:49:35.000000000 +0200 -+++ linux-2.6.17-omnibook/arch/i386/Kconfig 2006-08-04 17:09:26.680717114 +0200 -@@ -334,6 +334,42 @@ ++++ linux-2.6.17-omke/arch/i386/Kconfig 2006-09-07 19:16:40.994446032 +0200 +@@ -334,6 +334,54 @@ Say Y if you intend to run this kernel on a Toshiba portable. Say N otherwise. +config OMNIBOOK -+ tristate "HP (omnibook) laptop support" -+ help -+ This adds a driver to support some features of laptops manufactured -+ by Compal Electronics, Inc as ODM such as HP OmniBook, Pavilion, -+ Compal ACL00 and Toshiba Satellite (wich have Pheonix BIOS and is -+ not supported by Toshiba driver) and Acer Aspire series laptops. ++ tristate "HP Omnibook and Toshiba laptop support" ++ depends on PCI && X86 && EXPERIMENTAL ++ ---help--- ++ This adds a driver to support some features of laptops such as ++ HP OmniBook, Pavilion, Compal ACL00 ,Toshiba Satellite which have ++ a Phoenix BIOS and are not supported by other Toshiba drivers ++ and some Acer Aspire series laptops. + -+ For this driver see the site at: . ++ Most of these are manufactured by Compal Electronics, Inc as ODM ++ ++ See . + + Say Y if you intend to run this kernel on a supported portable. + Say N otherwise. @@ -22,41 +24,50 @@ diff -Nru linux-2.6.17/arch/i386/Kconfig linux-2.6.17-omnibook/arch/i386/Kconfig + inserted in and removed from the running kernel whenever you want). + If you want to compile it as a module, say M here and read + Documentation/modules.txt. -+ The module is called omnibook.ko because originally it was intended -+ to support HP OmniBooks only. ++ ++ The module is called omnibook.ko due to historical reasons. + -+config OMNIBOOK_APMEMU -+ bool "HP omnibook APM emulation" -+ depends on OMNIBOOK -+ help -+ Enable APM emulation by default in the omnibook module. This is -+ mainly for laptops that don't have perfect ACPI support for battery -+ level monitoring. ++config OMNIBOOK_LEGACY ++ bool "HP omnibook legacy features" ++ depends on OMNIBOOK ++ default y if !ACPI ++ ---help--- ++ This option enable support for some legacy features of the omnibook ++ driver, including: ++ * /proc/apm emulation. ++ * non-ACPI support code. ++ * AC adapter and Battery monitoring default enabling. ++ This is mainly for laptops with no or broken ACPI support. ++ ++ If you are unsure, say N. + +config OMNIBOOK_BACKLIGHT -+ bool "HP omnibook backlight support" -+ depends on OMNIBOOK -+ select BACKLIGHT_CLASS_DEVICE -+ help -+ Enable registration of the omnibook module as a backlight device. -+ This allow query and control of the LCD brightness via sysfs. ++ bool "HP omnibook backlight support" ++ depends on OMNIBOOK ++ select BACKLIGHT_CLASS_DEVICE ++ default y ++ ---help--- ++ Enable registration of the omnibook module as a backlight device. ++ This allow query and control of the LCD brightness via sysfs. ++ ++ If you are unsure, say Y. + config I8K tristate "Dell laptop support" ---help--- -diff -Nru linux-2.6.17/drivers/misc/Makefile linux-2.6.17-omnibook/drivers/misc/Makefile +diff -Nru linux-2.6.17/drivers/misc/Makefile linux-2.6.17-omke/drivers/misc/Makefile --- linux-2.6.17/drivers/misc/Makefile 2006-06-18 03:49:35.000000000 +0200 -+++ linux-2.6.17-omnibook/drivers/misc/Makefile 2006-08-04 17:09:26.681716962 +0200 ++++ linux-2.6.17-omke/drivers/misc/Makefile 2006-09-07 14:16:09.775221578 +0200 @@ -5,3 +5,5 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ +obj-$(CONFIG_OMNIBOOK) += omnibook/ + -diff -Nru linux-2.6.17/drivers/misc/omnibook/Makefile linux-2.6.17-omnibook/drivers/misc/omnibook/Makefile +diff -Nru linux-2.6.17/drivers/misc/omnibook/Makefile linux-2.6.17-omke/drivers/misc/omnibook/Makefile --- linux-2.6.17/drivers/misc/omnibook/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.17-omnibook/drivers/misc/omnibook/Makefile 2006-08-04 17:09:26.684716506 +0200 -@@ -0,0 +1,27 @@ ++++ linux-2.6.17-omke/drivers/misc/omnibook/Makefile 2006-09-07 18:15:18.927168481 +0200 +@@ -0,0 +1,28 @@ + +# Makefile -- makefile for the HP OmniBook support module + @@ -81,8 +92,9 @@ diff -Nru linux-2.6.17/drivers/misc/omnibook/Makefile linux-2.6.17-omnibook/driv +EXTRA_LDFLAGS += $(src)/sections.lds +obj-$(CONFIG_OMNIBOOK) += omnibook.o + -+omnibook-objs := ac.o battery.o blank.o display.o dock.o \ -+ec.o fan.o fan_policy.o init.o lcd.o onetouch.o \ -+temperature.o touchpad.o dump.o info.o \ -+apmemu.o muteled.o -+ ++omnibook-objs := init.o ec.o compal.o acpi.o nbsmi.o \ ++ac.o apmemu.o battery.o blank.o bluetooth.o display.o dock.o dump.o \ ++fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o temperature.o \ ++touchpad.o wireless.o + + diff --git a/muteled.c b/muteled.c index 5938a62..620c4bb 100644 --- a/muteled.c +++ b/muteled.c @@ -12,89 +12,74 @@ * General Public License for more details. * * Written by Thomas Perl , 2006 + * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif - #include "ec.h" /* There is no information about reading MUTE LED status */ static int omnibook_muteled_enabled = 0; -static int omnibook_muteled_on(void) -{ - if (omnibook_kbc_command(OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_MUTELED_ON)) { - printk(KERN_ERR "%s: failed muteled on command.\n", OMNIBOOK_MODULE_NAME); - return -EIO; - } - omnibook_muteled_enabled = 1; - return 0; -} - -static int omnibook_muteled_off(void) +static int omnibook_muteled_set(struct omnibook_operation *io_op, int status) { - if (omnibook_kbc_command(OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_MUTELED_OFF)) { - printk(KERN_ERR "%s: failed muteled off command.\n", OMNIBOOK_MODULE_NAME); + if (omnibook_toggle(io_op, !!status)) { + printk(O_ERR "Failed muteled %s command.\n", status ? "on" : "off"); return -EIO; } - omnibook_muteled_enabled = 0; return 0; } - -static int omnibook_muteled_disable(void) -{ - omnibook_muteled_off(); - return 0; -} - -static int omnibook_muteled_enable(void) -{ - omnibook_muteled_on(); - return 0; -} - -static int omnibook_muteled_read(char *buffer) +/* + * Hardware query is unsupported, reading is unreliable. + */ +static int omnibook_muteled_read(char *buffer,struct omnibook_operation *io_op) { int len = 0; - len += sprintf(buffer+len, "The mute LED is %s\n", (omnibook_muteled_enabled) ? "on" : "off"); + len += sprintf(buffer+len, "Last mute LED action was an %s command.\n", + (omnibook_muteled_enabled) ? "on" : "off"); return len; } -static int omnibook_muteled_write(char *buffer) +static int omnibook_muteled_write(char *buffer,struct omnibook_operation *io_op) { - int retval; - - switch (*buffer) { - case '0': - if ((retval = omnibook_muteled_disable())); - return retval; - break; - case '1': - if ((retval = omnibook_muteled_enable())); - return retval; - break; - default: + int cmd; + + if ( *buffer == '0' || *buffer == '1') { + cmd = *buffer - '0'; + if(!omnibook_muteled_set(io_op, cmd)) { + omnibook_muteled_enabled = cmd; + printk(O_INFO "Switching mute LED to %s state.\n", + cmd ? "on" : "off"); + } + } else { return -EINVAL; } return 0; } +static int omnibook_muteled_resume(struct omnibook_operation *io_op) +{ + return omnibook_muteled_set(io_op,omnibook_muteled_enabled); +} + +static struct omnibook_tbl muteled_table[] __initdata = { + { XE4500, COMMAND(KBC,OMNIBOOK_KBC_CMD_MUTELED_ON,OMNIBOOK_KBC_CMD_MUTELED_OFF)}, + { 0,} +}; -static struct omnibook_feature __declared_feature muteled_feature = { +static struct omnibook_feature __declared_feature muteled_driver = { .name = "muteled", .enabled = 1, .read = omnibook_muteled_read, .write = omnibook_muteled_write, + .resume = omnibook_muteled_resume, .ectypes = XE4500, + .tbl = muteled_table, }; -module_param_named(muteled, muteled_feature.enabled, int, S_IRUGO); +module_param_named(muteled, muteled_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(muteled, "Use 0 to disable, 1 to enable 'Audo Mute' LED control"); diff --git a/nbsmi.c b/nbsmi.c new file mode 100644 index 0000000..7734d73 --- /dev/null +++ b/nbsmi.c @@ -0,0 +1,595 @@ +/* + * nbsmi.c -- Toshiba SMI low-level acces code + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Written by Mathieu Bérard , 2006 + * + * Sources of inspirations for this code were: + * -Toshiba via provided hardware specification + * -Thorsten Zachmann with the 's1bl' project + * -Frederico Munoz with the 'tecra_acpi' project + * Thanks to them + */ + +#include "omnibook.h" + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) +#include +#define DEFINE_MUTEX(lock) DECLARE_MUTEX(lock) +#define mutex_lock(lock) down(lock) +#define mutex_lock_interruptible(lock) down_interruptible(lock) +#define mutex_unlock(lock) up(lock) +#else +#include +#endif + +#include +#include +#include +#include +#include +#include "ec.h" + +/* + * ATI's IXP PCI-LPC bridge + */ +#define PCI_DEVICE_ID_ATI_SB400 0x4377 + +#define INTEL_PMBASE 0x40 +#define INTEL_GPE0_EN 0x2c + +#define BUFFER_SIZE 0x20 +#define INTEL_OFFSET 0x60 +#define INTEL_SMI_PORT 0xb2 /* APM_CNT port in INTEL ICH specs */ +#define ATI_OFFSET 0xef +#define ATI_SMI_PORT 0xb0 + +#define EC_INDEX_PORT 0x300 +#define EC_DATA_PORT 0x301 + +/* Masks decode for GetAeral */ +#define WLEX_MASK 0x4 +#define WLAT_MASK 0x8 +#define BTEX_MASK 0x1 +#define BTAT_MASK 0x2 + +/* + * We serialize access to this backend using a mutex + * Crital sections around #SMI triggering are run atomically using a spinlock + */ +static DEFINE_MUTEX(smi_lock); +static DEFINE_SPINLOCK(smi_spinlock); + +/* + * Private data of this backend + */ +static struct kref *refcount; +static struct pci_dev *lpc_bridge; /* Southbridge chip ISA bridge/LPC interface PCI device */ +static u8 start_offset; +static int already_failed = 0; /* Backend init already failed at leat once */ + +/* + * Possible list of supported southbridges + * Here mostly to implement a more or less clean PCI probing + * Works only because of previous DMI probing. + * It's in compal.c + */ +extern const struct pci_device_id lpc_bridge_table[]; + +/* + * Since we are going to trigger an SMI, all registers may be mangled in the + * process. So we save and restore all registers and eflags in the stack. + * We also disable preemtion and IRQs upon SMI call. + */ +static inline void save_all_regs_flag(void) +{ + spin_lock_irq(&smi_spinlock); + __asm__ __volatile__("pushal ; pushfl"); +} + +static inline void restore_all_regs_flag(void) +{ + __asm__ __volatile__("popfl; popal" + : + : + : "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"); + spin_unlock_irq(&smi_spinlock); +} + +static inline void ati_do_smi_call(int *retval, u16 function) +{ + outw( function, ATI_SMI_PORT ); /* Call to SMI */ + *retval = inw(ATI_SMI_PORT + 1); +} + +static inline void intel_do_smi_call(int *retval, u16 function, u32 sci_en) +{ + u32 state; + + state = inl(sci_en); + outl( 0, sci_en ); + + outw( function, INTEL_SMI_PORT ); /* Call to SMI */ + +/* + * Success/Failure state in now stored in eax + */ + __asm__ __volatile__("movl %%eax, %0" + : + : "m" (retval) + ); + + outl( state, sci_en ); +} + + +static int nbsmi_smi_command(u16 function,const u8 *inputbuffer, u8 *outputbuffer) +{ + u32 retval; + u32 sci_en; + int count; + + for(count = 0; count < BUFFER_SIZE; count++) { + outb( count + start_offset, RTC_PORT(2) ); + outb( *(inputbuffer + count), RTC_PORT(3) ); + } + + +/* + * We have to write 0xe4XX to smi_port + * where XX is the SMI function code + */ + function = ( function & 0xff ) << 8; + function |= 0xe4; + + + switch (lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: +/* + * We get the PMBASE offset ( bits 15:7 at 0x40 offset of PCI config space ) + * And we access offset 2c (GPE0_EN), save the state, disable all SCI + * and restore the state in intel_do_smi_call function + */ + pci_read_config_dword(lpc_bridge, INTEL_PMBASE, &sci_en); + sci_en = sci_en & 0xff80; /* Keep bits 15:7 */ + sci_en += INTEL_GPE0_EN; /* GPEO_EN offset */ + save_all_regs_flag(); + intel_do_smi_call(&retval,function,sci_en); + restore_all_regs_flag(); + break; + case PCI_VENDOR_ID_ATI: + save_all_regs_flag(); + ati_do_smi_call(&retval,function); + restore_all_regs_flag(); + break; + default: + BUG(); + } + + for(count = 0; count < BUFFER_SIZE; count++) { + outb( count + start_offset, RTC_PORT(2) ); + *(outputbuffer + count) = inb( RTC_PORT(3) ); + } + + return retval; +} + + +static int nbsmi_smi_read_command(const struct omnibook_operation *io_op, u8 *data) +{ + int retval; + u8 *inputbuffer; + u8 *outputbuffer; + + if(!lpc_bridge) + return -ENODEV; + + if(mutex_lock_interruptible(&smi_lock)) + return -ERESTARTSYS; + + inputbuffer = kcalloc(BUFFER_SIZE,sizeof(u8),GFP_KERNEL); + if(!inputbuffer) { + retval = -ENOMEM; + goto error1; + } + + outputbuffer = kcalloc(BUFFER_SIZE,sizeof(u8),GFP_KERNEL); + if(!inputbuffer) { + retval = -ENOMEM; + goto error2; + } + + retval = nbsmi_smi_command( (u16) io_op->read_addr, inputbuffer, outputbuffer); + if(!retval) + goto out; + + *data = outputbuffer[0]; + + if(io_op->read_mask) + *data &= io_op->read_mask; + +out: + kfree(outputbuffer); +error2: + kfree(inputbuffer); +error1: + mutex_unlock(&smi_lock); + return retval; +} + +static int nbsmi_smi_write_command(const struct omnibook_operation *io_op, u8 data) +{ + int retval; + u8 *inputbuffer; + u8 *outputbuffer; + + if(!lpc_bridge) + return -ENODEV; + + if(mutex_lock_interruptible(&smi_lock)) + return -ERESTARTSYS; + + inputbuffer = kcalloc(BUFFER_SIZE,sizeof(u8),GFP_KERNEL); + if(!inputbuffer) { + retval = -ENOMEM; + goto error1; + } + + outputbuffer = kcalloc(BUFFER_SIZE,sizeof(u8),GFP_KERNEL); + if(!inputbuffer) { + retval = -ENOMEM; + goto error2; + } + + inputbuffer[0] = data; + + retval = nbsmi_smi_command( (u16) io_op->write_addr, inputbuffer, outputbuffer); + + kfree(outputbuffer); +error2: + kfree(inputbuffer); +error1: + mutex_unlock(&smi_lock); + return retval; +} + + +/* + * Read/Write to INDEX/DATA interface at port 0x300 (SMSC Mailbox registers) + * Used by Hotkeys feature under already taken mutex. + */ +static void nbsmi_ec_read_command(u16 index, u16 *data) +{ + spin_lock_irq(&smi_spinlock); + outw(index,EC_INDEX_PORT); + *data = inw(EC_DATA_PORT); + spin_unlock_irq(&smi_spinlock); +} + +static void nbsmi_ec_write_command(u16 index, u16 data) +{ + spin_lock_irq(&smi_spinlock); + outw(index,EC_INDEX_PORT); + outw(data,EC_DATA_PORT); + spin_unlock_irq(&smi_spinlock); +} + +/* + * Try to init the backend + * This function can be called blindly as it use a kref + * to check if the init sequence was already done. + */ + +static int omnibook_nbsmi_init(const struct omnibook_operation *io_op) +{ + int retval = 0; + int i; + u16 ec_data; + u32 smi_port = 0; + +/* ectypes other than TSM40 have no business with this backend */ + if(!(omnibook_ectype & TSM40)) + return -ENODEV; + + if(already_failed) { + dprintk("NbSmi backend init already failed, skipping.\n"); + return -ENODEV; + } + + if(!refcount) { + /* Fist use of the backend */ + mutex_lock(&smi_lock); + dprintk("Try to init NbSmi\n"); + refcount = kmalloc(sizeof(struct kref),GFP_KERNEL); + if(!refcount) { + retval= -ENOMEM; + goto out; + } + + kref_init(refcount); + + /* PCI probing: find the LPC Super I/O bridge PCI device */ + for (i = 0; !lpc_bridge && lpc_bridge_table[i].vendor; ++i) + lpc_bridge = pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device, NULL); + + if (!lpc_bridge) { + printk(O_ERR "Fail to find a supported LPC I/O bridge, please report\n"); + retval = -ENODEV; + goto error1; + } + + if((retval = pci_enable_device(lpc_bridge))) { + printk(O_ERR "Unable to enable PCI device.\n"); + goto error2; + } + + switch (lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + start_offset = INTEL_OFFSET; + smi_port = INTEL_SMI_PORT; + break; + case PCI_VENDOR_ID_ATI: + start_offset = ATI_OFFSET; + smi_port = ATI_SMI_PORT; + break; + default: + BUG(); + } + + if(!request_region(smi_port, 2 , OMNIBOOK_MODULE_NAME)) { + printk(O_ERR "Request SMI I/O region error\n"); + retval = -ENODEV; + goto error2; + } + + if(!request_region(EC_INDEX_PORT, 2 , OMNIBOOK_MODULE_NAME)) { + printk(O_ERR "Request EC I/O region error\n"); + retval = -ENODEV; + goto error3; + } + + + /* + * Try some heuristic tests to avoid enabling this interface on unsuported laptops: + * See what a port 300h read index 8f gives. Guess there is nothing if read 0xffff + */ + + nbsmi_ec_read_command(SMI_FN_PRESSED, &ec_data); + dprintk("NbSmi test probe read: %x\n",ec_data); + if(ec_data == 0xffff) { + printk(O_ERR "Probing at SMSC Mailbox registers failed, disabling NbSmi\n"); + retval = -ENODEV; + goto error4; + } + + + dprintk("NbSmi init ok\n"); + goto out; + } else { + dprintk("NbSmi has already been initialized\n"); + kref_get(refcount); + return 0; + } +error4: + release_region(EC_INDEX_PORT,2); +error3: + release_region(smi_port,2); +error2: + pci_dev_put(lpc_bridge); + lpc_bridge = NULL; +error1: + kfree(refcount); + refcount = NULL; + already_failed = 1; +out: + mutex_unlock(&smi_lock); + return retval; +} + +static void nbsmi_free(struct kref *ref) +{ + u32 smi_port = 0; + + mutex_lock(&smi_lock); + dprintk("NbSmi not used anymore: disposing\n"); + + switch (lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + smi_port = INTEL_SMI_PORT; + break; + case PCI_VENDOR_ID_ATI: + smi_port = ATI_SMI_PORT; + break; + default: + BUG(); + } + + pci_dev_put(lpc_bridge); + release_region(smi_port,2); + release_region(EC_INDEX_PORT,2); + kfree(refcount); + lpc_bridge = NULL; + refcount = NULL; + mutex_unlock(&smi_lock); +} + +static void omnibook_nbsmi_exit(const struct omnibook_operation *io_op) +{ +/* ectypes other than TSM40 have no business with this backend */ + BUG_ON(!(omnibook_ectype & TSM40)); + dprintk("Trying to dispose NbSmi\n"); + kref_put(refcount,nbsmi_free); +} + +static int omnibook_nbsmi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval = 0; + struct omnibook_operation aerial_op; + u8 data; + + aerial_op.read_addr = SMI_GET_KILL_SWITCH; + + if((retval = nbsmi_smi_read_command(&aerial_op, &data))) + goto out; + + *state = data ? KILLSWITCH : 0; /* Make it 1 or 0 */ + + aerial_op.read_addr = SMI_GET_AERIAL; + + if((retval = nbsmi_smi_read_command(&aerial_op, &data))) + goto out; + + *state |= ( data & WLEX_MASK ) ? WIFI_EX : 0; + *state |= ( data & WLAT_MASK ) ? WIFI_STA : 0; + *state |= ( data & BTEX_MASK ) ? BT_EX : 0; + *state |= ( data & BTAT_MASK ) ? BT_STA : 0; + +out: + return retval; +} + + +static int omnibook_nbsmi_set_wireless(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval = 0; + u8 data = 0; + struct omnibook_operation aerial_op; + + aerial_op.write_addr = SMI_SET_AERIAL; + + data |= state & BT_STA; + data |= ( state & WIFI_STA ) << 0x1 ; + + retval = nbsmi_smi_write_command(&aerial_op, data); + + return retval; +} + +/* + * Hotkeys handling + */ +static int omnibook_nbmsi_hotkeys_get(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval; + u8 data = 0; + struct omnibook_operation hotkeys_op; + + hotkeys_op.read_addr = SMI_GET_FN_INTERFACE; + + retval = nbsmi_smi_read_command(&hotkeys_op, &data); + if(retval < 0) + return retval; + + *state = ( data & SMI_FN_KEYS_MASK ) ? HKEY_FN : 0; + *state |= ( data & SMI_STICK_KEYS_MASK ) ? HKEY_STICK : 0; + *state |= ( data & SMI_FN_TWICE_LOCK_MASK ) ? HKEY_TWICE_LOCK : 0; + *state |= ( data & SMI_FN_DOCK_MASK ) ? HKEY_DOCK : 0; + + return HKEY_FN|HKEY_STICK|HKEY_TWICE_LOCK|HKEY_DOCK; +} + +static int omnibook_nbmsi_hotkeys_set(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval; + u8 data = 0; + struct omnibook_operation hotkeys_op; + + hotkeys_op.write_addr = SMI_SET_FN_INTERFACE; + data |= ( state & HKEY_FN ) ? SMI_FN_KEYS_MASK : 0; + data |= ( state & HKEY_STICK) ? SMI_STICK_KEYS_MASK : 0; + data |= ( state & HKEY_TWICE_LOCK) ? SMI_FN_TWICE_LOCK_MASK : 0; + data |= ( state & HKEY_DOCK) ? SMI_FN_DOCK_MASK : 0; + + retval = nbsmi_smi_write_command(&hotkeys_op, data); + if(retval < 0) + return retval; + + hotkeys_op.write_addr = SMI_SET_FN_F5_INTERFACE; + data = !!( state & HKEY_FNF5); + + retval = nbsmi_smi_write_command(&hotkeys_op, data); + if(retval < 0) + return retval; + else + return HKEY_FN|HKEY_STICK|HKEY_TWICE_LOCK|HKEY_DOCK|HKEY_FNF5; +} + +static const unsigned int nbsmi_display_mode_list[] = { + DISPLAY_LCD_ON, + DISPLAY_LCD_ON|DISPLAY_CRT_ON, + DISPLAY_CRT_ON, + DISPLAY_LCD_ON|DISPLAY_TVO_ON, + DISPLAY_TVO_ON, +}; + +static int omnibook_nbmsi_display_get(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval = 0; + u8 data; + struct omnibook_operation display_op; + + display_op.read_addr = SMI_GET_DISPLAY_STATE; + + retval = nbsmi_smi_read_command(&display_op, &data); + if(retval < 0) + return retval; + + if( data > (ARRAY_SIZE(nbsmi_display_mode_list) - 1)) + return -EIO; + + *state = nbsmi_display_mode_list[data]; + + return DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON; +} + +static int omnibook_nbmsi_display_set(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval = 0; + int i; + u8 matched = 0; + struct omnibook_operation display_op; + + display_op.write_addr = SMI_SET_DISPLAY_STATE; + + for(i = 0; i < ARRAY_SIZE(nbsmi_display_mode_list); i++) { + if(nbsmi_display_mode_list[i] == state) { + matched = i; + break; + } + } + if(!matched) { + printk("Display mode %x is unsupported.\n", state); + return -EINVAL; + } + + retval = nbsmi_smi_write_command(&display_op, matched); + if(retval < 0) + return retval; + + return DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON; +} + + + +struct omnibook_backend nbsmi_backend = { + .name = "nbsmi", + .init = omnibook_nbsmi_init, + .exit = omnibook_nbsmi_exit, + .byte_read = nbsmi_smi_read_command, + .byte_write = nbsmi_smi_write_command, + .aerial_get = omnibook_nbsmi_get_wireless, + .aerial_set = omnibook_nbsmi_set_wireless, + .hotkeys_get = omnibook_nbmsi_hotkeys_get, + .hotkeys_set = omnibook_nbmsi_hotkeys_set, + .display_get = omnibook_nbmsi_display_get, + .display_set = omnibook_nbmsi_display_set, +}; diff --git a/omnibook.h b/omnibook.h index fbfd6f6..451f270 100644 --- a/omnibook.h +++ b/omnibook.h @@ -32,39 +32,43 @@ * EC types */ -extern int omnibook_ectype; - -#define NONE 0 /* 0 Default/unknown EC type */ -#define XE3GF (1<<0) /* 1 HP OmniBook XE3 GF, most Toshiba Satellites and more */ -#define XE3GC (1<<1) /* 2 HP OmniBook XE3 GC, GD, GE and compatible */ -#define OB500 (1<<2) /* 3 HP OmniBook 500 and compatible */ -#define OB510 (1<<3) /* 4 HP OmniBook 510 */ -#define OB6000 (1<<4) /* 5 HP OmniBook 6000 */ -#define OB6100 (1<<5) /* 6 HP OmniBook 6100 */ -#define XE4500 (1<<6) /* 7 HP OmniBook xe4500 and compatible */ -#define OB4150 (1<<7) /* 8 HP OmniBook 4150 */ -#define XE2 (1<<8) /* 9 HP OmniBook XE2 */ -#define AMILOD (1<<9) /* 10 Fujitsu Amilo D */ -#define TSP10 (1<<10) /* 11 Toshiba Satellite P10, P15, P20 and compatible */ -#define TSM30X (1<<11) /* 12 Toshiba Satellite M30X, M35X, M40X, M70 and compatible */ -#define TSM40 (1<<12) /* 13 Toshiba Satellite M40 */ -#define TSA105 (1<<13) /* 14 Toshiba Satellite A105 */ - +extern enum omnibook_ectype_t { + NONE = 0, /* 0 Default/unknown EC type */ + XE3GF = (1<<0), /* 1 HP OmniBook XE3 GF, most old Toshiba Satellites */ + XE3GC = (1<<1), /* 2 HP OmniBook XE3 GC, GD, GE and compatible */ + OB500 = (1<<2), /* 3 HP OmniBook 500 and compatible */ + OB510 = (1<<3), /* 4 HP OmniBook 510 */ + OB6000 = (1<<4), /* 5 HP OmniBook 6000 */ + OB6100 = (1<<5), /* 6 HP OmniBook 6100 */ + XE4500 = (1<<6), /* 7 HP OmniBook xe4500 and compatible */ + OB4150 = (1<<7), /* 8 HP OmniBook 4150 */ + XE2 = (1<<8), /* 9 HP OmniBook XE2 */ + AMILOD = (1<<9), /* 10 Fujitsu Amilo D */ + TSP10 = (1<<10), /* 11 Toshiba Satellite P10, P15, P20 and compatible */ + TSM30X = (1<<11), /* 12 Toshiba Satellite M30X, M35X, M40X, M70 and compatible */ + TSM40 = (1<<12), /* 13 Toshiba Satellite M40 */ + TSA105 = (1<<13) /* 14 Toshiba Satellite A105 */ +} omnibook_ectype; + /* * This represent a feature provided by this module */ +struct omnibook_operation; + struct omnibook_feature { char *name; /* Name */ char *proc_entry; /* Specify proc entry relative to /proc (will be omnibook/name otherwise) */ int enabled; /* Set from module parameter */ - int (*read) (char *); /* Procfile read function */ - int (*write) (char *); /* Procfile write function */ - int (*init) (void); /* Specific Initialization function */ - void (*exit) (void); /* Specific Cleanup function */ - int (*suspend) (void); /* PM Suspend function */ - int (*resume) (void); /* PM Resume function */ + int (*read) (char *,struct omnibook_operation *); /* Procfile read function */ + int (*write) (char *,struct omnibook_operation *);/* Procfile write function */ + int (*init) (struct omnibook_operation *); /* Specific Initialization function */ + void (*exit) (struct omnibook_operation *); /* Specific Cleanup function */ + int (*suspend) (struct omnibook_operation *); /* PM Suspend function */ + int (*resume) (struct omnibook_operation *); /* PM Resume function */ int ectypes; /* Type(s) of EC we support for this feature (bitmask) */ + struct omnibook_tbl *tbl; + struct omnibook_operation *io_op; struct list_head list; }; @@ -91,10 +95,55 @@ enum { }; -extern int omnibook_lcd_blank(int blank); -extern int omnibook_get_ac(void); -extern int omnibook_get_battery_status(int num, struct omnibook_battery_state *battstat); -extern int set_omnibook_param(const char *val, struct kernel_param *kp); +/* + * State of a Wifi/Bluetooth adapter + */ +enum { + WIFI_EX = (1<<0), /* 1 1=present 0=absent */ + WIFI_STA = (1<<1), /* 2 1=enabled 0=disabled */ + KILLSWITCH = (1<<2), /* 4 1=radio on 0=radio off */ + BT_EX = (1<<3), /* 8 1=present 0=absent */ + BT_STA = (1<<4), /* 16 1=enabled 0=disabled */ +}; + +/* + * Hotkeys state backend neutral masks + */ +enum { + HKEY_ONETOUCH = (1<<0), /* 1 Ontetouch button scancode generation */ + HKEY_MULTIMEDIA = (1<<1), /* 2 "Multimedia hotkeys" scancode generation */ + HKEY_FN = (1<<2), /* 4 Fn + foo hotkeys scancode generation */ + HKEY_STICK = (1<<3), /* 8 Stick key (no clue what this is about) */ + HKEY_TWICE_LOCK = (1<<4), /* 16 Press Fn twice to lock */ + HKEY_DOCK = (1<<5), /* 32 (Un)Dock events scancode generation */ + HKEY_FNF5 = (1<<6), /* 64 Fn + F5 (toggle display) is enabled */ +}; + + +/* + * Display state backend neutral masks + * _ON masks = port is powered up and running + * _DET masks = a display have been detected to be plugged in the port + */ + +enum { + DISPLAY_LCD_ON = (1<<0), /* 1 Internal LCD panel */ + DISPLAY_CRT_ON = (1<<1), /* 2 External VGA port */ + DISPLAY_TVO_ON = (1<<2), /* 4 External TV-OUT port */ + DISPLAY_DVI_ON = (1<<3), /* 8 External DVI port */ + DISPLAY_LCD_DET = (1<<4), /* 16 Internal LCD panel */ + DISPLAY_CRT_DET = (1<<5), /* 32 External VGA port */ + DISPLAY_TVO_DET = (1<<6), /* 64 External TV-OUT port */ + DISPLAY_DVI_DET = (1<<7), /* 128 External DVI port */ +}; + + + +int omnibook_lcd_blank(int blank); +int omnibook_get_ac(struct omnibook_operation *io_op); +int omnibook_get_battery_status(int num, struct omnibook_battery_state *battstat); +int set_omnibook_param(const char *val, struct kernel_param *kp); + #define __declared_feature __attribute__ (( __section__(".features"), __aligned__(__alignof__ (struct omnibook_feature)))) __attribute_used__ @@ -125,7 +174,7 @@ extern int set_omnibook_param(const char *val, struct kernel_param *kp); #else #undef CONFIG_OMNIBOOK_BACKLIGHT #endif /* BACKLIGHT_CLASS_DEVICE */ -#undef CONFIG_OMNIBOOK_APMEMU +#undef CONFIG_OMNIBOOK_LEGACY #endif /* OMNIBOOK_STANDALONE */ /* End of file */ diff --git a/sections.lds b/sections.lds index 70a539d..7fc90dd 100644 --- a/sections.lds +++ b/sections.lds @@ -1,9 +1,11 @@ -SECTIONS{ +SECTIONS +{ .data : { - _features_start = .; + . = ALIGN(32); + _start_features_driver = .; *(.features) - _features_end = .; + _end_features_driver = .; *(.data) } } diff --git a/temperature.c b/temperature.c index 869ea43..694e462 100644 --- a/temperature.c +++ b/temperature.c @@ -15,86 +15,40 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif - #include "ec.h" -static int omnibook_get_cpu_temp(void) +static int omnibook_temperature_read(char *buffer, struct omnibook_operation *io_op) { - u8 temp = 0; + int len = 0; int retval; - /* - * XE3GF - * TSP10 - * TSM30X - */ - if (omnibook_ectype & (XE3GF|TSP10|TSM30X) ) { - if ((retval = omnibook_ec_read(XE3GF_CTMP, &temp))) - return retval; - retval = temp; - /* - * XE3GC - * AMILOD - */ - } else if (omnibook_ectype & (XE3GC|AMILOD) ) { - if ((retval = omnibook_ec_read(XE3GC_CTMP, &temp))) - return retval; - retval = temp; - /* - * OB500 - * OB510 - * OB6000 - * OB6100 - * XE4500 - * XE2 - */ - } else if (omnibook_ectype & (OB500|OB510|OB6000|OB6100|XE4500|XE2) ) { - if ((retval = omnibook_ec_read(OB500_CTMP, &temp))) - return retval; - retval = temp; - /* - * OB4150 - */ - } else if (omnibook_ectype & (OB4150) ) { + u8 temp; - if ((retval = omnibook_ec_read(OB4150_TMP, &temp))) - return retval; - retval = temp; - } else { - printk(O_INFO - "Temperature monitoring is unsupported on this machine.\n"); - retval = -ENODEV; - } - return retval; -} - -static int omnibook_temperature_read(char *buffer) -{ - int len = 0; - int cpu_temp; - - cpu_temp = omnibook_get_cpu_temp(); - if (cpu_temp < 0) - return cpu_temp; + if((retval = io_op->backend->byte_read(io_op, &temp))) + return retval; len += - sprintf(buffer + len, "CPU temperature: %2d C\n", - cpu_temp); + sprintf(buffer + len, "CPU temperature: %2d C\n", temp); return len; } -static struct omnibook_feature __declared_feature temperature_feature = { +static struct omnibook_tbl temp_table[] __initdata = { + { XE3GF|TSP10|TSM30X, SIMPLE_BYTE(EC,XE3GF_CTMP,0)}, + { XE3GC|AMILOD, SIMPLE_BYTE(EC,XE3GC_CTMP,0)}, + { OB500|OB510|OB6000|OB6100|XE4500|XE2, SIMPLE_BYTE(EC,OB500_CTMP,0)}, + { OB4150, SIMPLE_BYTE(EC,OB4150_TMP,0)}, + { 0,} +}; + +static struct omnibook_feature __declared_feature temperature_driver = { .name = "temperature", .enabled = 1, .read = omnibook_temperature_read, .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM30X, + .tbl = temp_table, }; -module_param_named(temperature, temperature_feature.enabled, int, S_IRUGO); +module_param_named(temperature, temperature_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(temperature, "Use 0 to disable, 1 to enable thermal status and policy support"); /* End of file */ diff --git a/touchpad.c b/touchpad.c index 672f3a5..d7193a7 100644 --- a/touchpad.c +++ b/touchpad.c @@ -15,150 +15,89 @@ * Modified by Mathieu Bérard , 2006 */ -#ifdef OMNIBOOK_STANDALONE #include "omnibook.h" -#else -#include -#endif - #include "ec.h" -/* Touchpad is enabled by default */ +/* Touchpad is assumed to be enabled by default */ static int omnibook_touchpad_enabled = 1; -static int omnibook_touchpad_on(void) +static int omnibook_touchpad_set(struct omnibook_operation *io_op, int status) { - if (omnibook_kbc_command - (OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE)) { - printk(O_ERR "Failed touchpad enable command.\n"); - return -EIO; + int retval = 0; + if ((retval = omnibook_toggle(io_op, !!status))) { + printk(O_ERR "Failed touchpad %sable command.\n", status ? "en" : "dis"); } - return 0; -} - -static int omnibook_touchpad_off(void) -{ - if (omnibook_kbc_command - (OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE)) { - printk(O_ERR "Failed touchpad disable command.\n"); - return -EIO; - } - return 0; + return retval; } /* - * Power management handlers: redisable touchpad on resume + * Power management handlers: redisable touchpad on resume (if requested) */ -int omnibook_touchpad_resume(void) +static int omnibook_touchpad_resume(struct omnibook_operation *io_op) { int retval; - retval = (omnibook_touchpad_enabled ? 0 : omnibook_touchpad_off()); + retval = (omnibook_touchpad_enabled ? 0 : omnibook_touchpad_set(io_op, 0)); return retval; } -static int omnibook_touchpad_enable(void) -{ - /* - * XE3GF - * XE3GC - * TSP10 - */ - if (omnibook_ectype & (XE3GF|XE3GC|TSP10) ) { - - if (!omnibook_touchpad_enabled) { - if (omnibook_touchpad_on()) - return -EIO; - omnibook_touchpad_enabled = 1; - printk(O_INFO "Touchpad is enabled.\n"); - } - /* - * These models have stickpointer, not touchpad: - * OB500 - * OB510 - */ - } else if (omnibook_ectype & (OB500|OB510) ) { - - omnibook_touchpad_enabled = 0; - return -ENODEV; - } else { - omnibook_touchpad_enabled = 1; - return -ENODEV; - } - return 0; -} - -static int omnibook_touchpad_disable(void) -{ - /* - * XE3GF - * XE3GC - * TSP10 - */ - if (omnibook_ectype & (XE3GF|XE3GC|TSP10) ) { - if (omnibook_touchpad_enabled) { - if (omnibook_touchpad_off()) { - return -EIO; - } - omnibook_touchpad_enabled = 0; - printk(O_INFO "Touchpad is disabled.\n"); - } - /* - * These models have stickpointer, not touchpad: - * OB500 - * OB510 - */ - } else if (omnibook_ectype & (OB500|OB510) ) { - omnibook_touchpad_enabled = 0; - return -ENODEV; - } else { - omnibook_touchpad_enabled = 1; - return -ENODEV; - } - return 0; -} - -static int omnibook_touchpad_read(char *buffer) +/* + * Hardware query is unsupported, so reading is unreliable. + */ +static int omnibook_touchpad_read(char *buffer, struct omnibook_operation *io_op) { int len = 0; + len += - sprintf(buffer + len, "Touchpad is %s\n", - (omnibook_touchpad_enabled) ? "enabled" : "disabled"); + sprintf(buffer + len, "Last touchpad action was an %s command.\n", + (omnibook_touchpad_enabled) ? "enable" : "disable"); return len; } -static int omnibook_touchpad_write(char *buffer) +static int omnibook_touchpad_write(char *buffer, struct omnibook_operation *io_op) { - switch (*buffer) { - case '0': - omnibook_touchpad_disable(); - break; - case '1': - omnibook_touchpad_enable(); - break; - default: + int cmd; + + if ( *buffer == '0' || *buffer == '1') { + cmd = *buffer - '0'; + if(!omnibook_touchpad_set(io_op, cmd)) { + omnibook_touchpad_enabled = cmd; + printk(O_INFO "%sabling touchpad.\n", cmd ? "En" : "Dis"); + } + } else { return -EINVAL; } return 0; } -static void omnibook_touchpad_cleanup(void) +/* + * Reenable touchpad upon exit + */ +static void __exit omnibook_touchpad_cleanup(struct omnibook_operation *io_op) { - omnibook_touchpad_enable(); + omnibook_touchpad_set(io_op,1); + printk(O_INFO "Enabling touchpad.\n"); } -static struct omnibook_feature __declared_feature touchpad_feature = { +static struct omnibook_tbl touchpad_table[] __initdata = { + { XE3GF|XE3GC|TSP10, COMMAND(KBC,OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE,OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE)}, + { TSM30X, {CDI, 0, TSM70_FN_INDEX, 0, TSM70_TOUCHPAD_ON, TSM70_TOUCHPAD_OFF}}, + { 0,} +}; + +static struct omnibook_feature __declared_feature touchpad_driver = { .name = "touchpad", .enabled = 1, .read = omnibook_touchpad_read, .write = omnibook_touchpad_write, .exit = omnibook_touchpad_cleanup, .resume = omnibook_touchpad_resume, - .ectypes = XE3GF|XE3GC|TSP10, + .ectypes = XE3GF|XE3GC|TSP10|TSM30X, + .tbl = touchpad_table, }; -module_param_named(touchpad, touchpad_feature.enabled, int, S_IRUGO); +module_param_named(touchpad, touchpad_driver.enabled, int, S_IRUGO); MODULE_PARM_DESC(touchpad, "Use 0 to disable, 1 to enable touchpad handling"); /* End of file */ diff --git a/wireless.c b/wireless.c new file mode 100644 index 0000000..91e2ec2 --- /dev/null +++ b/wireless.c @@ -0,0 +1,101 @@ +/* + * wireless.c Wifi feature + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Written by Mathieu Bérard , 2006 + * + */ + +#include "omnibook.h" +#include "ec.h" + +static int omnibook_wifi_read(char *buffer,struct omnibook_operation *io_op) +{ + int len = 0; + int retval; + unsigned int state; + + if((retval = io_op->backend->aerial_get(io_op,&state))) + return retval; + + len += sprintf(buffer + len,"Wifi adapter is %s", (state & WIFI_EX) ? "present" : "absent"); + if (state & WIFI_EX) + len += sprintf(buffer + len," and %s", (state & WIFI_STA) ? "enabled" : "disabled"); + len += sprintf(buffer + len,".\n"); + len += sprintf(buffer + len,"Wifi Kill switch is %s.\n", (state & KILLSWITCH) ? "on" : "off"); + + return len; + +} + +static int omnibook_wifi_write(char *buffer,struct omnibook_operation *io_op) +{ + int retval = 0; + unsigned int state; + + if((retval = io_op->backend->aerial_get(io_op,&state))) + return retval; + + if(*buffer == '0' ) + state &= ~WIFI_STA; + else if (*buffer == '1' ) + state |= WIFI_STA; + else + return -EINVAL; + + if((retval = io_op->backend->aerial_set(io_op, state))) + return retval; + + return retval; +} + +static struct omnibook_feature wifi_feature; + +static int __init omnibook_wifi_init(struct omnibook_operation *io_op) +{ + int retval = 0; + unsigned int state; + +/* + * Refuse enabling/disabling a non-existent device + */ + + if((retval = io_op->backend->aerial_get(io_op, &state))) + return retval; + + if(!(state & WIFI_EX)) + wifi_feature.write = NULL; + + return retval; +} + +/* + * Shared with bluetooth.c + */ +struct omnibook_tbl wireless_table[] __initdata = { + { TSM30X, {ACPI, 0, 0, 0, 0, 0}}, /* stubs to select backend */ + { TSM40, {SMI, 0, 0, 0, 0, 0}}, /* stubs to select backend */ + { 0,} +}; + +static struct omnibook_feature __declared_feature wifi_driver = { + .name = "wifi", + .enabled = 1, + .read = omnibook_wifi_read, + .write = omnibook_wifi_write, + .init = omnibook_wifi_init, + .ectypes = TSM30X|TSM40, + .tbl = wireless_table, +}; + +module_param_named(wifi, wifi_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(wifi, "Use 0 to disable, 1 to enable Wifi adapter control");