Hello!
I'm wrote some beta driver to control fan speed on asus a8jn laptop,
using information from dsdt and nhc classes
(http://nhc.justred.info/acpi/model/model_id/48.html?symfony=h7q34oidrvgg5hr2ln36m95fv2).
But have one question and one problem. :)
#include <linux/init.h>
#include <linux/module.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
MODULE_LICENSE("GPL");
#define FAN_OFF_TMP 43 //celsius
#define FAN_ON_TMP 57 //celsius
#define TIMER_FREQ 10 //secs
#define FAN_SPEED 0x13 //fan off (other values: 0x12-0x10)
struct timer_list timer;
static void set_fan_speed(unsigned long arg)
{
struct acpi_buffer output;
struct acpi_object_list params;
union acpi_object in_obj, out_obj;
acpi_status status;
int tmp;
output.length = sizeof(out_obj);
output.pointer = &out_obj;
//Get current temperature
status = acpi_evaluate_object(NULL, "\\_TZ.THRM._TMP",
NULL, &output);
if (status != AE_OK) printk("_TZ.THRM._TMP error\n");
tmp = (out_obj.integer.value-2732)/10;
printk("TMP=%d\n", tmp);
//If temperature < FAN_OFF_TMP - disable fan
if(tmp < FAN_OFF_TMP) {
params.count = 1;
params.pointer = &in_obj;
in_obj.type = ACPI_TYPE_INTEGER;
in_obj.integer.value = ((0x84 << 16)
+ (FAN_SPEED << 8) + (0xc4));
status = acpi_evaluate_object(NULL, "\\_SB.ATKD.ECRW",
¶ms, NULL);
if (status != AE_OK) printk("_SB.ATKD.ECRW error\n");
printk("TMP<FAN_OFF_TMP, fan turning off\n");
}
// timer.expires += TIMER_FREQ*HZ;
// add_timer(&timer);
}
static int asus_fan_init(void)
{
struct acpi_object_list params;
union acpi_object in_objs[2];
acpi_status status;
unsigned long j, tdelay;
//On/off temperature
params.count = 2;
params.pointer = in_objs;
in_objs[0].type = in_objs[1].type = ACPI_TYPE_INTEGER;
in_objs[0].integer.value = FAN_ON_TMP;
in_objs[1].integer.value = 0;
status = acpi_evaluate_object(NULL, "\\_TZ.WTML",
¶ms, NULL);
if (status != AE_OK)
printk("_TZ.WTML error\n");
//timer settings
j = jiffies;
tdelay = TIMER_FREQ*HZ;
init_timer(&timer);
timer.data = 0;
timer.function = set_fan_speed;
timer.expires = j + tdelay;
add_timer(&timer);
return 0;
}
static void asus_fan_exit(void)
{
del_timer(&timer);
}
module_init(asus_fan_init);
module_exit(asus_fan_exit);
Is it possible to handle acpi notify event, when temperature changed? At
least, when temperature go through threshold (like _PSV, _AC1,...). In
dsdt i'm found two calls to notify THRM:
Method (_SCP, 1, NotSerialized)
{
TCHG ()
Notify (THRM, 0x81)
}
and
If (LGreaterEqual (Local0, TCRT))
{
Notify (THRM, 0x80)
}
And problem, that
status = acpi_evaluate_object(NULL, "\\_SB.ATKD.ECRW",
¶ms, NULL);
from timer handler cause the kernel panic. If this function called from
module initialization - works fine.
Thanks,
Dmitry Ursegov
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html