Revision: 49 http://svn.sourceforge.net/mactel-linux/?rev=49&view=rev Author: nboichat Date: 2006-10-15 00:33:49 -0700 (Sun, 15 Oct 2006)
Log Message: ----------- Add fan control to applesmc. Modified Paths: -------------- trunk/kernel/mactel-patches-2.6.18/applesmc.patch Modified: trunk/kernel/mactel-patches-2.6.18/applesmc.patch =================================================================== --- trunk/kernel/mactel-patches-2.6.18/applesmc.patch 2006-10-14 05:24:47 UTC (rev 48) +++ trunk/kernel/mactel-patches-2.6.18/applesmc.patch 2006-10-15 07:33:49 UTC (rev 49) @@ -41,17 +41,20 @@ obj-$(CONFIG_SENSORS_F71805F) += f71805f.o diff -pruN linux-2.6.18/drivers/hwmon.vanilla/applesmc.c linux-2.6.18/drivers/hwmon/applesmc.c --- linux-2.6.18/drivers/hwmon.vanilla/applesmc.c 1970-01-01 07:30:00.000000000 +0730 -+++ linux-2.6.18/drivers/hwmon/applesmc.c 2006-10-14 13:09:10.000000000 +0800 -@@ -0,0 +1,575 @@ ++++ linux-2.6.18/drivers/hwmon/applesmc.c 2006-10-15 15:19:30.000000000 +0800 +@@ -0,0 +1,809 @@ +/* + * drivers/hwmon/applesmc.c - driver for Apple's SMC (various sensors) + * + * Copyright (C) 2006 Nicolas Boichat <[EMAIL PROTECTED]> + * -+ * Based on hdaps.c driver : ++ * Based on hdaps.c driver: + * Copyright (C) 2005 Robert Love <[EMAIL PROTECTED]> + * Copyright (C) 2005 Jesper Juhl <[EMAIL PROTECTED]> + * ++ * Fan control based on smcFanControl: ++ * Copyright (C) 2006 Hendrik Holtmann <[EMAIL PROTECTED]> ++ * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License v2 as published by the + * Free Software Foundation. @@ -87,15 +90,25 @@ +#define APPLESMC_READ_CMD 0x10 +#define APPLESMC_WRITE_CMD 0x11 + -+#define LIGHT_SENSOR_LEFT_KEY "ALV0" //0x414c5630, r-o length 6 -+#define LIGHT_SENSOR_RIGHT_KEY "ALV1" //0x414c5631, r-o length 6 -+#define BACKLIGHT_KEY "LKSB" //0x4c4b5342, w-o -+#define CLAMSHELL_KEY "MSLD" //0x4d534c44, r-o length 1 (unused) -+#define MOTION_SENSOR_X_KEY "MO_X" //0x4d4f5f58, r-o length 2 -+#define MOTION_SENSOR_Y_KEY "MO_Y" //0x4d4f5f58, r-o length 2 -+#define MOTION_SENSOR_Z_KEY "MO_Z" //0x4d4f5f58, r-o length 2 -+#define MOTION_SENSOR_KEY "MOCN" //0x4d4f434e, r/w length 2 ++#define LIGHT_SENSOR_LEFT_KEY "ALV0" //r-o length 6 ++#define LIGHT_SENSOR_RIGHT_KEY "ALV1" //r-o length 6 ++#define BACKLIGHT_KEY "LKSB" //w-o + ++#define CLAMSHELL_KEY "MSLD" //r-o length 1 (unused) ++ ++#define MOTION_SENSOR_X_KEY "MO_X" //r-o length 2 ++#define MOTION_SENSOR_Y_KEY "MO_Y" //r-o length 2 ++#define MOTION_SENSOR_Z_KEY "MO_Z" //r-o length 2 ++#define MOTION_SENSOR_KEY "MOCN" //r/w length 2 ++ ++#define FANS_COUNT "FNum" //r-o length 1 ++#define FANS_MANUAL "FS! " //r-w length 2 ++#define FAN_ACTUAL_SPEED "F0Ac" //r-o length 2 ++#define FAN_MIN_SPEED "F0Mn" //r-o length 2 ++#define FAN_MAX_SPEED "F0Mx" //r-o length 2 ++#define FAN_SAFE_SPEED "F0Sf" //r-o length 2 ++#define FAN_TARGET_SPEED "F0Tg" //r-w length 2 ++ +#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ +#define INIT_WAIT_MSECS 50 /* ... in 50ms increments */ + @@ -117,11 +130,6 @@ +/* Indicate whether this computer has light sensors and keyboard backlight. */ +static unsigned int applesmc_light = 0; + -+#if 0 -+static unsigned int hdaps_invert; -+static u8 km_activity; -+#endif -+ +static DECLARE_MUTEX(applesmc_sem); + +/* @@ -287,7 +295,26 @@ + return ret; +} + ++/* ++ * applesmc_get_fan_count - get the number of fans. Callers must NOT hold ++ * applesmc_sem. ++ */ ++static int applesmc_get_fan_count(void) ++{ ++ int ret; ++ u8 buffer[1]; + ++ down(&applesmc_sem); ++ ++ ret = applesmc_read_key(FANS_COUNT, buffer, 1); ++ ++ up(&applesmc_sem); ++ if (ret) ++ return ret; ++ else ++ return buffer[0]; ++} ++ +/* Device model stuff */ +static int applesmc_probe(struct platform_device *dev) +{ @@ -393,15 +420,125 @@ + goto out; + ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, 6); + right = buffer[2]; ++ ++out: ++ up(&applesmc_sem); + if (ret) ++ return ret; ++ else ++ return sprintf(buf, "(%d,%d)\n", left, right); ++} ++ ++static ssize_t applesmc_show_fan_speed(struct device *dev, char *buf, ++ char* key, int offset) ++{ ++ int ret; ++ u16 speed = 0; ++ char newkey[5]; ++ u8 buffer[2]; ++ ++ newkey[0] = key[0]; ++ newkey[1] = '0' + offset; ++ newkey[2] = key[2]; ++ newkey[3] = key[3]; ++ newkey[4] = 0; ++ ++ down(&applesmc_sem); ++ ++ ret = applesmc_read_key(newkey, buffer, 2); ++ speed = (buffer[0] << 8 | buffer[1]) >> 2; ++ ++ up(&applesmc_sem); ++ if (ret) ++ return ret; ++ else ++ return sprintf(buf, "%d\n", speed); ++} ++ ++static ssize_t applesmc_store_fan_speed(struct device *dev, const char *buf, ++ size_t count, char* key, int offset) ++{ ++ int ret; ++ u32 speed; ++ char newkey[5]; ++ u8 buffer[2]; ++ ++ speed = simple_strtoul(buf, NULL, 10); ++ ++ if (speed > 0x4000) /* Bigger than a 14-bit value */ ++ return -EINVAL; ++ ++ newkey[0] = key[0]; ++ newkey[1] = '0' + offset; ++ newkey[2] = key[2]; ++ newkey[3] = key[3]; ++ newkey[4] = 0; ++ ++ down(&applesmc_sem); ++ ++ buffer[0] = (speed >> 6) & 0xff; ++ buffer[1] = (speed << 2) & 0xff; ++ ret = applesmc_write_key(newkey, buffer, 2); ++ ++ up(&applesmc_sem); ++ if (ret) ++ return ret; ++ else ++ return count; ++} ++ ++static ssize_t applesmc_show_fan_manual(struct device *dev, char *buf, ++ int offset) ++{ ++ int ret; ++ u16 manual = 0; ++ u8 buffer[2]; ++ ++ down(&applesmc_sem); ++ ++ ret = applesmc_read_key(FANS_MANUAL, buffer, 2); ++ manual = ((buffer[0] << 8 | buffer[1]) >> offset) & 0x01; ++ ++ up(&applesmc_sem); ++ if (ret) ++ return ret; ++ else ++ return sprintf(buf, "%d\n", manual); ++} ++ ++static ssize_t applesmc_store_fan_manual(struct device *dev, const char *buf, ++ size_t count, int offset) ++{ ++ int ret; ++ u8 buffer[2]; ++ u32 input; ++ u16 val; ++ ++ input = simple_strtoul(buf, NULL, 10); ++ ++ down(&applesmc_sem); ++ ++ ret = applesmc_read_key(FANS_MANUAL, buffer, 2); ++ val = (buffer[0] << 8 | buffer[1]); ++ if (ret) + goto out; + ++ if (input) ++ val = val | (0x01 << offset); ++ else ++ val = val & ~(0x01 << offset); ++ ++ buffer[0] = (val >> 8) & 0xFF; ++ buffer[1] = val & 0xFF; ++ ++ ret = applesmc_write_key(FANS_MANUAL, buffer, 2); ++ +out: + up(&applesmc_sem); + if (ret) + return ret; + else -+ return sprintf(buf, "(%d,%d)\n", left, right); ++ return count; +} + +static ssize_t applesmc_calibrate_show(struct device *dev, @@ -464,7 +601,82 @@ + .attrs = applesmc_attributes, +}; + ++#define sysfs_fan_speeds_offset(offset) \ ++static ssize_t show_fan_actual_speed_##offset (struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return applesmc_show_fan_speed(dev, buf, FAN_ACTUAL_SPEED, offset); \ ++} \ ++static DEVICE_ATTR(fan##offset##_actual_speed, S_IRUGO, \ ++ show_fan_actual_speed_##offset, NULL); \ ++\ ++static ssize_t show_fan_minimum_speed_##offset (struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return applesmc_show_fan_speed(dev, buf, FAN_MIN_SPEED, offset); \ ++} \ ++static DEVICE_ATTR(fan##offset##_minimum_speed, S_IRUGO, \ ++ show_fan_minimum_speed_##offset, NULL); \ ++\ ++static ssize_t show_fan_maximum_speed_##offset (struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return applesmc_show_fan_speed(dev, buf, FAN_MAX_SPEED, offset); \ ++} \ ++static DEVICE_ATTR(fan##offset##_maximum_speed, S_IRUGO, \ ++ show_fan_maximum_speed_##offset, NULL); \ ++\ ++static ssize_t show_fan_safe_speed_##offset (struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return applesmc_show_fan_speed(dev, buf, FAN_SAFE_SPEED, offset); \ ++} \ ++static DEVICE_ATTR(fan##offset##_safe_speed, S_IRUGO, \ ++ show_fan_safe_speed_##offset, NULL); \ ++\ ++static ssize_t show_fan_target_speed_##offset (struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return applesmc_show_fan_speed(dev, buf, FAN_TARGET_SPEED, offset); \ ++} \ ++static ssize_t store_fan_target_speed_##offset (struct device *dev, \ ++ struct device_attribute *attr, const char *buf, size_t count) \ ++{ \ ++ return applesmc_store_fan_speed(dev, buf, count, FAN_TARGET_SPEED, offset); \ ++} \ ++static DEVICE_ATTR(fan##offset##_target_speed, S_IRUGO | S_IWUSR, \ ++ show_fan_target_speed_##offset, store_fan_target_speed_##offset); + ++#define sysfs_fan_manual_offset(offset) \ ++static ssize_t show_fan_manual_##offset (struct device *dev, \ ++ struct device_attribute *attr, char *buf) \ ++{ \ ++ return applesmc_show_fan_manual(dev, buf, offset); \ ++} \ ++static ssize_t store_fan_manual_##offset (struct device *dev, \ ++ struct device_attribute *attr, const char *buf, size_t count) \ ++{ \ ++ return applesmc_store_fan_manual(dev, buf, count, offset); \ ++} \ ++static DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \ ++ show_fan_manual_##offset, store_fan_manual_##offset); ++ ++ ++sysfs_fan_speeds_offset(0); ++sysfs_fan_manual_offset(0); ++sysfs_fan_speeds_offset(1); ++sysfs_fan_manual_offset(1); ++ ++#define device_create_file_fan(client, offset) \ ++do { \ ++sysfs_create_file(client, &dev_attr_fan##offset##_actual_speed.attr); \ ++sysfs_create_file(client, &dev_attr_fan##offset##_minimum_speed.attr); \ ++sysfs_create_file(client, &dev_attr_fan##offset##_maximum_speed.attr); \ ++sysfs_create_file(client, &dev_attr_fan##offset##_safe_speed.attr); \ ++sysfs_create_file(client, &dev_attr_fan##offset##_target_speed.attr); \ ++sysfs_create_file(client, &dev_attr_fan##offset##_manual.attr); \ ++} while (0) ++ +/* Module stuff */ + +/* applesmc_light_dmi_match - found a match. return one, short-circuiting the hunt. */ @@ -545,6 +757,28 @@ + if (ret) + goto out_device; + ++ /* create fan files */ ++ ret = applesmc_get_fan_count(); ++ if (ret < 0) { ++ printk(KERN_ERR "applesmc: Cannot get the number of fans.\n"); ++ } ++ else { ++ printk(KERN_INFO "applesmc: %d fans found.\n", ret); ++ ++ switch (ret) { ++ default: ++ printk(KERN_WARNING "applesmc: More than 2 fans found," ++ " but at most 2 fans are supported" ++ " by the driver.\n"); ++ case 2: ++ device_create_file_fan(&pdev->dev.kobj, 1); ++ case 1: ++ device_create_file_fan(&pdev->dev.kobj, 0); ++ case 0: ++ ; ++ } ++ } ++ + applesmc_idev = input_allocate_device(); + if (!applesmc_idev) { + ret = -ENOMEM; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Mactel-linux-devel mailing list Mactel-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mactel-linux-devel