Re: acpithinkpad(4) fan control - sysctl callback in kernel?
On 2010/11/30 09:10, Christopher Zimmermann wrote: > Still I'd like to implement a sysctl interface. The example of > lid_suspend did not help much. I need something like a callback when > userspace changes the sysctl variable. Is this possible? Or should I do > it like it is done for lid_suspend and regularly poll the variable? Look at ddb.trigger (DBCTL_TRIGGER).
Re: acpithinkpad(4) fan control - sysctl callback in kernel?
On 11/22/10 23:01, joshua stein wrote: > as for code implementing the sysctl, it would probably be something > created under machdep, like the recently added machdep.lidsuspend. Thanks for your code. It helped me to do a first test of the fan control on my T43. It reacts strangely (regulates fan speed on only 3 steps from 3000 to 4000 rpm). Still I'd like to implement a sysctl interface. The example of lid_suspend did not help much. I need something like a callback when userspace changes the sysctl variable. Is this possible? Or should I do it like it is done for lid_suspend and regularly poll the variable? Christopher
Re: acpithinkpad(4) fan control
On Mon, 22 Nov 2010 16:01:18 -0600 joshua stein wrote: > it would be helpful to have some kind of > watchdog to reset the fan to auto/high if something goes wrong, but > i don't know whether that's even possible. while probably not a big > issue on a laptop, if the fan was on manual/low when the kernel > panicked and left to sit there for many hours, some things could > overheat. Almost all modern processors cut the current back and often switch the system off regardless of any bios/acpi settings. This may cause a bit off stress on components around heat syncs etc, but generally the only problems caused are to data on hard disks due to unexpected shutdowns. The only real thing to worry about, would be it shutting off more often than it should or when you want to run traces after the panic etc..
Re: acpithinkpad(4) fan control
> When I have this working I want to implement a PID controler for it. > Since I'd like to see this get committed, where would be the preferred > place to put the PID-controller? Kernel or userland? kernel, definitely. it would be helpful to have some kind of watchdog to reset the fan to auto/high if something goes wrong, but i don't know whether that's even possible. while probably not a big issue on a laptop, if the fan was on manual/low when the kernel panicked and left to sit there for many hours, some things could overheat. i wrote this code last year to react to the thinkpad temperature sensors and change the fan speed accordingly. it makes my x301 completely silent most of the time and then occasionally turns the fan on low when doing a make build or when firefox is trying to do something as "complicated" as render a webpage. it has no manual control nor any watchdog. there is also other unrelated junk in the diff, but it is what i'm running against -current. as for code implementing the sysctl, it would probably be something created under machdep, like the recently added machdep.lidsuspend. Index: acpithinkpad.c === RCS file: /cvs/src/sys/dev/acpi/acpithinkpad.c,v retrieving revision 1.24 diff -u -p -r1.24 acpithinkpad.c --- acpithinkpad.c 7 Aug 2010 16:21:20 - 1.24 +++ acpithinkpad.c 29 Nov 2010 19:02:40 - @@ -1,6 +1,6 @@ /* $OpenBSD: acpithinkpad.c,v 1.24 2010/08/07 16:21:20 deraadt Exp $ */ /* - * Copyright (c) 2008 joshua stein + * Copyright (c) 2008, 2010 joshua stein * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -59,10 +59,11 @@ #defineTHINKPAD_BUTTON_VOLUME_DOWN 0x1016 #defineTHINKPAD_BUTTON_VOLUME_MUTE 0x1017 #defineTHINKPAD_BUTTON_THINKVANTAGE0x1018 +#defineTHINKPAD_BUTTON_THINKVANTAGE2 0x4120 #defineTHINKPAD_BUTTON_FN_F11 0x100b #defineTHINKPAD_BUTTON_HIBERNATE 0x100c -#defineTHINKPAD_LID_OPEN 0x5001 -#defineTHINKPAD_LID_CLOSED 0x5002 +#defineTHINKPAD_LID_CLOSED 0x5001 +#defineTHINKPAD_LID_OPEN 0x5002 #defineTHINKPAD_TABLET_SCREEN_NORMAL 0x500a #defineTHINKPAD_TABLET_SCREEN_ROTATED 0x5009 #defineTHINKPAD_BRIGHTNESS_CHANGED 0x5010 @@ -71,11 +72,23 @@ #defineTHINKPAD_POWER_CHANGED 0x6030 #defineTHINKPAD_SWITCH_WIRELESS0x7000 -#define THINKPAD_NSENSORS 9 -#define THINKPAD_NTEMPSENSORS 8 +#defineTHINKPAD_NSENSORS 9 +#defineTHINKPAD_NTEMPSENSORS 8 -#define THINKPAD_ECOFFSET_FANLO0x84 -#define THINKPAD_ECOFFSET_FANHI0x85 +#defineTHINKPAD_ECBRIGHTNESS_OFFSET0x31 +#defineTHINKPAD_ECBRIGHTNESS_LEVEL_MASK 0x1f + +#defineTHINKPAD_ECOFFSET_FANLO 0x84 +#defineTHINKPAD_ECOFFSET_FANHI 0x85 + +#defineTHINKPAD_ECOFFSET_FANLEVEL 0x2f + +#defineTHINKPAD_ECFANLEVEL_AUTO7 + +/* highest temperatures (from any sensor) allowed at each fan level (after + * level 2's max temp, it will be put in auto mode) */ +#defineTHINKPAD_MAX_TEMP_LEVEL155 +#defineTHINKPAD_MAX_TEMP_LEVEL265 struct acpithinkpad_softc { struct devicesc_dev; @@ -88,7 +101,15 @@ struct acpithinkpad_softc { struct ksensordevsc_sensdev; }; -extern void acpiec_read(struct acpiec_softc *, u_int8_t, int, u_int8_t *); +/* models (according to smbios version in bios.c) that need a brightness helper */ +extern char *hw_ver; +const char *acpithinkpad_models_to_help[] = { + "ThinkPad X61s", + "ThinkPad T61", +}; + +intthinkpad_need_helper = 0; +intstaged_temp_setting = 0; intthinkpad_match(struct device *, void *, void *); void thinkpad_attach(struct device *, struct device *, void *); @@ -100,11 +121,14 @@ int thinkpad_cmos(struct acpithinkpad_so intthinkpad_volume_down(struct acpithinkpad_softc *); intthinkpad_volume_up(struct acpithinkpad_softc *); intthinkpad_volume_mute(struct acpithinkpad_softc *); +intthinkpad_brightness_get(struct acpithinkpad_softc *); intthinkpad_brightness_up(struct acpithinkpad_softc *); intthinkpad_brightness_down(struct acpithinkpad_softc *); +void thinkpad_set_fan_level(struct acpithinkpad_softc *, uint8_t); voidthinkpad_sensor_attach(struct acpithinkpad_softc *sc); voidthinkpad_sensor_refresh(void *); +void thinkpad_video_setup(struct acpithinkpad_softc *); struct cfattach acpithinkpad_ca = { sizeof(struct acpithinkpad_softc), thinkpad_match, thinkpad_attach @@ -158,13 +182,16 @@ thinkpad_sensor_attach(struct acpithinkp sensor_attach(&sc->sc_sensdev,
Re: acpithinkpad(4) fan control
On Mon, Nov 29, 2010 at 03:23:58PM +0100, Christopher Zimmermann wrote: > Hi! > > I'd like to implement fan speed control for Thinkpads. It is documented > at http://www.thinkwiki.org/wiki/How_to_control_fan_speed#Hardware_specs > and linux also implements this (but with special case for TP 570, > 600e/x, 770e, 770x - anyone here with access to one of these?) > Implementing a driver for this will be a piece of cake, but I need help > with communication to userspace to get started. I guess the way to go is > sysctl (?) FWIW, I've hacked up that piece of cake for my X300 once. I just used some spare function-keys (Fn-F1,F2,F3) to play with it. (Diff attached) However, since you can damage your hardware with this, I'm not sure whether we want to add support for this into OpenBSD. Index: acpithinkpad.c === RCS file: /cvs/src/sys/dev/acpi/acpithinkpad.c,v retrieving revision 1.24 diff -p -u -p -u -r1.24 acpithinkpad.c --- acpithinkpad.c 7 Aug 2010 16:21:20 - 1.24 +++ acpithinkpad.c 22 Aug 2010 15:43:22 - @@ -86,6 +86,7 @@ struct acpithinkpad_softc { struct ksensor sc_sens[THINKPAD_NSENSORS]; struct ksensordevsc_sensdev; + int cur_fanspeed; }; extern void acpiec_read(struct acpiec_softc *, u_int8_t, int, u_int8_t *); @@ -102,6 +103,9 @@ int thinkpad_volume_up(struct acpithinkp intthinkpad_volume_mute(struct acpithinkpad_softc *); intthinkpad_brightness_up(struct acpithinkpad_softc *); intthinkpad_brightness_down(struct acpithinkpad_softc *); +intthinkpad_get_fan(struct acpithinkpad_softc *); +intthinkpad_step_fan_up(struct acpithinkpad_softc *); +intthinkpad_step_fan_down(struct acpithinkpad_softc *); voidthinkpad_sensor_attach(struct acpithinkpad_softc *sc); voidthinkpad_sensor_refresh(void *); @@ -114,6 +118,9 @@ struct cfdriver acpithinkpad_cd = { NULL, "acpithinkpad", DV_DULL }; +int fan_speeds[] = { 0, 1, 2, 3, 4, 5, 6, 7, 128 }; +#define MAX_FAN_SPEEDS 8 + const char *acpithinkpad_hids[] = { ACPI_DEV_THINKPAD, 0 }; int @@ -288,10 +295,19 @@ thinkpad_hotkey(struct aml_node *node, i #endif handled = 1; break; - case THINKPAD_BUTTON_HIBERNATE: case THINKPAD_BUTTON_FN_F1: + thinkpad_get_fan(sc); + handled = 1; + break; case THINKPAD_BUTTON_LOCK_SCREEN: + thinkpad_step_fan_down(sc); + handled = 1; + break; case THINKPAD_BUTTON_BATTERY_INFO: + thinkpad_step_fan_up(sc); + handled = 1; + break; + case THINKPAD_BUTTON_HIBERNATE: case THINKPAD_BUTTON_FN_F6: case THINKPAD_BUTTON_EXTERNAL_SCREEN: case THINKPAD_BUTTON_POINTER_SWITCH: @@ -417,6 +433,52 @@ int thinkpad_volume_up(struct acpithinkpad_softc *sc) { return (thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_UP)); +} + +int +thinkpad_get_fan(struct acpithinkpad_softc *sc) +{ + u_int8_t buffer[2]; + + acpiec_read(sc->sc_acpi->sc_ec, 0x2f, 1, buffer); + printf("EC f...@0x2f: 0x%x\n", buffer[0]); + + acpiec_read(sc->sc_acpi->sc_ec, 0x84, 2, buffer); + + /* XXX LE only. But are there any BE thinkpads? */ + printf("EC Fan Speed: %u RPM\n", *((u_int16_t*)buffer)); + + return (0); +} + +int +thinkpad_step_fan_up(struct acpithinkpad_softc *sc) +{ + if (sc->cur_fanspeed + 1 > MAX_FAN_SPEEDS) + return (-1); + + sc->cur_fanspeed++; + + printf("Adjust fan to: %u\n", fan_speeds[sc->cur_fanspeed]); + acpiec_write(sc->sc_acpi->sc_ec, 0x2f, 1, + (u_int8_t *)&fan_speeds[sc->cur_fanspeed]); + + return (0); +} + +int +thinkpad_step_fan_down(struct acpithinkpad_softc *sc) +{ + if (sc->cur_fanspeed - 1 < 0) + return (-1); + + sc->cur_fanspeed--; + + printf("Adjust fan to: %u\n", fan_speeds[sc->cur_fanspeed]); + acpiec_write(sc->sc_acpi->sc_ec, 0x2f, 1, + (u_int8_t *)&fan_speeds[sc->cur_fanspeed]); + + return (0); } int
Re: acpithinkpad(4) fan control
This needs to be all handled in the kernel. User space can only get status. We'd love to see this code. On Mon, Nov 29, 2010 at 03:23:58PM +0100, Christopher Zimmermann wrote: > Hi! > > I'd like to implement fan speed control for Thinkpads. It is documented > at http://www.thinkwiki.org/wiki/How_to_control_fan_speed#Hardware_specs > and linux also implements this (but with special case for TP 570, > 600e/x, 770e, 770x - anyone here with access to one of these?) > Implementing a driver for this will be a piece of cake, but I need help > with communication to userspace to get started. I guess the way to go is > sysctl (?) > In acpithinkpad only read only sensor variables are created. > How do I create r/w variables - where can I find code examples? And where > in the sysctl tree should I put them? > > When I have this working I want to implement a PID controler for it. > Since I'd like to see this get committed, where would be the preferred > place to put the PID-controller? Kernel or userland? > > > Christopher
acpithinkpad(4) fan control
Hi! I'd like to implement fan speed control for Thinkpads. It is documented at http://www.thinkwiki.org/wiki/How_to_control_fan_speed#Hardware_specs and linux also implements this (but with special case for TP 570, 600e/x, 770e, 770x - anyone here with access to one of these?) Implementing a driver for this will be a piece of cake, but I need help with communication to userspace to get started. I guess the way to go is sysctl (?) In acpithinkpad only read only sensor variables are created. How do I create r/w variables - where can I find code examples? And where in the sysctl tree should I put them? When I have this working I want to implement a PID controler for it. Since I'd like to see this get committed, where would be the preferred place to put the PID-controller? Kernel or userland? Christopher