Re: acpithinkpad(4) fan control - sysctl callback in kernel?

2010-11-30 Thread Stuart Henderson
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?

2010-11-30 Thread Christopher Zimmermann
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

2010-11-29 Thread Kevin Chadwick
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

2010-11-29 Thread joshua stein
> 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

2010-11-29 Thread Marco Pfatschbacher
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

2010-11-29 Thread Marco Peereboom
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

2010-11-29 Thread Christopher Zimmermann
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