Created
August 6, 2013 21:51
-
-
Save felipec/6169047 to your computer and use it in GitHub Desktop.
ASUS fan control
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* | |
* obj-m := fan.o | |
* KDIR := /lib/modules/$(shell uname -r)/build | |
* PWD := $(shell pwd) | |
* | |
* all: | |
* $(MAKE) -C $(KDIR) M=$(PWD) modules | |
* | |
* clean: | |
* $(MAKE) -C $(KDIR) M=$(PWD) clean | |
*/ | |
#include <linux/module.h> | |
#include <linux/kernel.h> | |
#include <linux/init.h> | |
#include <linux/acpi.h> | |
#include <linux/thermal.h> | |
#include <linux/dmi.h> | |
MODULE_AUTHOR("Felipe Contreras <felipe.contreras@gmail.com>"); | |
MODULE_DESCRIPTION("ASUS fan driver"); | |
MODULE_LICENSE("GPL"); | |
static struct thermal_cooling_device *cdev; | |
static int fan_get_max_state(struct thermal_cooling_device *cdev, | |
unsigned long *state) | |
{ | |
*state = 0xff; | |
return 0; | |
} | |
static int fan_get_cur_state(struct thermal_cooling_device *cdev, | |
unsigned long *state) | |
{ | |
struct acpi_object_list params; | |
union acpi_object in_objs[1]; | |
unsigned long long value; | |
acpi_status r; | |
params.count = ARRAY_SIZE(in_objs); | |
params.pointer = in_objs; | |
in_objs[0].type = ACPI_TYPE_INTEGER; | |
in_objs[0].integer.value = 0; | |
r = acpi_evaluate_integer(NULL, "\\_TZ.RFAN", ¶ms, &value); | |
if (r != AE_OK) | |
return r; | |
*state = value; | |
return 0; | |
} | |
static int fan_set(struct thermal_cooling_device *cdev, int fan, int speed) | |
{ | |
struct acpi_object_list params; | |
union acpi_object in_objs[2]; | |
unsigned long long value; | |
params.count = ARRAY_SIZE(in_objs); | |
params.pointer = in_objs; | |
in_objs[0].type = ACPI_TYPE_INTEGER; | |
in_objs[0].integer.value = fan; | |
in_objs[1].type = ACPI_TYPE_INTEGER; | |
in_objs[1].integer.value = speed; | |
return acpi_evaluate_integer(NULL, "\\_SB.PCI0.LPCB.EC0.SFNV", ¶ms, &value); | |
} | |
static int fan_set_cur_state(struct thermal_cooling_device *cdev, | |
unsigned long state) | |
{ | |
return fan_set(cdev, 1, state); | |
} | |
static int fan_set_auto(struct thermal_cooling_device *cdev) | |
{ | |
return fan_set(cdev, 0, 0); | |
} | |
static const struct thermal_cooling_device_ops fan_cooling_ops = { | |
.get_max_state = fan_get_max_state, | |
.get_cur_state = fan_get_cur_state, | |
.set_cur_state = fan_set_cur_state, | |
}; | |
static int __init fan_init(void) | |
{ | |
if (strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "ASUSTeK COMPUTER INC.")) | |
return -ENODEV; | |
cdev = thermal_cooling_device_register("Fan", NULL, &fan_cooling_ops); | |
if (IS_ERR(cdev)) | |
return PTR_ERR(cdev); | |
fan_set_auto(cdev); | |
return 0; | |
} | |
static void __exit fan_exit(void) | |
{ | |
fan_set_auto(cdev); | |
thermal_cooling_device_unregister(cdev); | |
} | |
module_init(fan_init); | |
module_exit(fan_exit); |
@asuxer this module don't create /sys/class/hwmon
devices. Control your fan with:
$ echo 200 | sudo tee /sys/class/thermal/cooling_deviceN/cur_state
- added full Makefile
- added "hack" to set fan back to automatic without unloading the module
-> forked here: https://gist.github.com/daringer/721e2cea17b570512097
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
OK I give up...
I recompiled the original Ubuntu kernel, but patched it with the diff from here
https://lkml.org/lkml/2013/10/8/800
(http://www.gossamer-threads.com/lists/linux/kernel/1796054)
Reboot, then I re-run sensors-detect, then sudo pwmconfig (from package fancontrol) but still I get
/usr/sbin/pwmconfig: There are no fan-capable sensor modules installed
felipec, please tell us what you did. You say it works perfectly for you?