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",
                                        &params, 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",
                                        &params, 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",
                                        &params, 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

Reply via email to