--- therm_adt7467.c	2004-03-11 03:55:37.000000000 +0100
+++ therm_adx.c	2004-03-17 14:41:57.000000000 +0100
@@ -31,16 +31,22 @@
 
 #undef DEBUG
 
-#define CONFIG_REG   0x40
-#define MANUAL_MASK  0xe0
-#define AUTO_MASK    0x20
-
-static u8 TEMP_REG[3]    = {0x26, 0x25, 0x27}; /* local, cpu, gpu */
-static u8 LIMIT_REG[3]   = {0x6b, 0x6a, 0x6c}; /* local, cpu, gpu */
-static u8 MANUAL_MODE[2] = {0x5c, 0x5d};       
-static u8 REM_CONTROL[2] = {0x00, 0x40};
-static u8 FAN_SPEED[2]   = {0x28, 0x2a};
-static u8 FAN_SPD_SET[2] = {0x30, 0x31};
+#define CONFIG_REG       0x40
+#define MANUAL_MASK      0xe0
+#define AUTO_MASK        0x20
+#define ADM_MANUAL_MASK ~0x80
+#define ADM_AUTO_MASK    0x80
+ 
+static u8 TEMP_REG[3]     = {0x26, 0x25, 0x27}; /* local, cpu, gpu */
+static u8 LIMIT_REG[3]    = {0x6b, 0x6a, 0x6c}; /* local, cpu, gpu */
+static u8 MANUAL_MODE[2]  = {0x5c, 0x5d};       
+static u8 REM_CONTROL[2]  = {0x00, 0x40};
+static u8 FAN_SPEED[2]    = {0x28, 0x2a};
+static u8 FAN_SPD_SET[2]  = {0x30, 0x31};
+
+static u8 ADM_MANUAL_MODE = 0x00;
+static u8 ADM_LIMIT_REG[3]= {0x24, 0x25, 0x26}; /* local, remote, remote */
+static u8 ADM_TEMP_REG[3] = {0x0a, 0x0b, 0x0c}; /* local, remote, remote */
 
 static u8 default_limits_local[3] = {70, 50, 70};    /* local, cpu, gpu */
 static u8 default_limits_chip[3] = {80, 65, 80};    /* local, cpu, gpu */
@@ -66,7 +72,8 @@
 	int			overriding[2];
 };
 
-static enum {ADT7460, ADT7467} therm_type;
+static enum {ADT7460, ADT7467, ADM1030, ADM1031} therm_type;
+static enum {ADT, ADM} therm_family;
 static int therm_bus, therm_address;
 static struct of_device * of_dev;
 static struct thermostat* thermostat;
@@ -78,6 +85,20 @@
 static void write_both_fan_speed(struct thermostat *th, int speed);
 static void write_fan_speed(struct thermostat *th, int speed, int fan);
 
+static char *therm_name(int therm_type)
+{
+	switch (therm_type) {
+		case ADT7460:
+			return "adt7460";
+		case ADT7467:
+			return "adt7467";
+		case ADM1030:
+			return "adm1030";
+		case ADM1031:
+			return "adm1031";
+	}
+	return "unknown";
+}
 static int
 write_reg(struct thermostat* th, int reg, u8 data)
 {
@@ -140,14 +161,16 @@
 		monitor_running = 0;
 		wait_for_completion(&monitor_task_compl);
 	}
-		
-	printk(KERN_INFO "adt746x: Putting max temperatures back from %d, %d, %d,"
+	
+	if (therm_family == ADT) {	
+		printk(KERN_INFO "adt746x: Putting max temperatures back from %d, %d, %d,"
 		" to %d, %d, %d, (°C)\n", 
 		th->limits[0], th->limits[1], th->limits[2],
 		th->initial_limits[0], th->initial_limits[1], th->initial_limits[2]);
-	
-	for (i = 0; i < 3; i++)
-		write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
+		for (i = 0; i < 3; i++)
+			write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
+
+	} 
 
 	write_both_fan_speed(th, -1);
 
@@ -172,13 +195,17 @@
 {
 	u8 tmp[2];
 	u16 res;
-	
-	/* should start with low byte */
-	tmp[1] = read_reg(th, addr);
-	tmp[0] = read_reg(th, addr + 1);
-	
-	res = tmp[1] + (tmp[0] << 8);
-	return (90000*60)/res;
+
+	if (therm_family == ADT) {
+		/* should start with low byte */
+		tmp[1] = read_reg(th, addr);
+		tmp[0] = read_reg(th, addr + 1);
+		
+		res = tmp[1] + (tmp[0] << 8);
+		return (90000*60)/res;
+	} else {
+		return -1;
+	}
 }
 
 static void write_both_fan_speed(struct thermostat *th, int speed)
@@ -197,8 +224,13 @@
 	else if (speed < -1) 
 		speed = 0;
 	
-	if (therm_type == ADT7467 && fan == 1)
+	if (therm_type != ADT7460 && fan == 1)
 		return;
+
+	if (therm_family == ADM && speed >= 0) {
+		printk(KERN_INFO "adt746x: Manual setting of speed not supported on adm103x\n");
+		speed = -1;
+	}
 	
 	if (th->last_speed[fan] != speed) {
 		if (speed == -1)
@@ -211,17 +243,27 @@
 		return;
 	
 	if (speed >= 0) {
-		manual = read_reg(th, MANUAL_MODE[fan]);
-		write_reg(th, MANUAL_MODE[fan], manual|MANUAL_MASK);
-		write_reg(th, FAN_SPD_SET[fan], speed);
+		/* switch to manual */
+		if (therm_family == ADT) {
+			manual = read_reg(th, MANUAL_MODE[fan]);
+			write_reg(th, MANUAL_MODE[fan], manual|MANUAL_MASK);
+			write_reg(th, FAN_SPD_SET[fan], speed);
+		} else {
+			manual = read_reg(th, ADM_MANUAL_MODE);
+			write_reg(th, ADM_MANUAL_MODE, manual & ADM_MANUAL_MASK); 
+		}
+		
 	} else {
 		/* back to automatic */
 		if(therm_type == ADT7460) {
 			manual = read_reg(th, MANUAL_MODE[fan]) & (~MANUAL_MASK);
 			write_reg(th, MANUAL_MODE[fan], manual|REM_CONTROL[fan]);
-		} else {
+		} else if (therm_type == ADT7467) {
 			manual = read_reg(th, MANUAL_MODE[fan]);
 			write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK));
+		} else {
+			manual = read_reg(th, ADM_MANUAL_MODE);
+			write_reg(th, ADM_MANUAL_MODE, manual | ADM_AUTO_MASK);
 		}
 	}
 	
@@ -257,13 +299,16 @@
 		if (fan_speed != -1) {
 #endif
 			for (i = 0; i < 3; i++) {
-				temps[i]  = read_reg(th, TEMP_REG[i]);
+				if (therm_family == ADT)
+					temps[i]  = read_reg(th, TEMP_REG[i]);
+				else
+					temps[i]  = read_reg(th, ADM_TEMP_REG[i]);
 				lims[i]   = th->limits[i];
 			}
 #ifndef DEBUG
 		}
 #endif		
-		if (fan_speed != -1) {
+		if (fan_speed != -1 && (therm_family == ADT)) {
 			int lastvar = 0;		/* for iBook */
 			for (i = 1; i < 3; i++) {	/* we don't care about local sensor */
 				int started = 0;
@@ -331,8 +376,14 @@
 {
 		/* Set CPU limit higher to avoid powerdowns */ 
 		th->limits[i] = default_limits_chip[i] + limit_adjust;
-		write_reg(th, LIMIT_REG[i], th->limits[i]);
-		
+		if (therm_family == ADT) {
+			write_reg(th, LIMIT_REG[i], th->limits[i]);
+		} else {
+			if (th->limits[i] > 124)
+				th->limits[i] = 124;
+			write_reg(th, LIMIT_REG[i], th->limits[i] << 1);
+			
+		}
 		/* set our limits to normal */
 		th->limits[i] = default_limits_local[i] + limit_adjust;
 }
@@ -368,22 +419,23 @@
 	if (fan_speed == -1)
 		fan_speed=128;
 	
-	if(therm_type == ADT7460) {
-		printk(KERN_INFO "adt746x: ADT7460 initializing\n");
-		/* The 7460 needs to be started explicitly */
+	/* adt7460 needs manual init */
+	if(therm_type == ADT7460)
 		write_reg(th, CONFIG_REG, 1);
-	} else
-		printk(KERN_INFO "adt746x: ADT7467 initializing\n");
 
-	for (i = 0; i < 3; i++) {
-		th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
-		set_limit(th, i);
-	}
-	
-	printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
+	printk(KERN_INFO "adt746x: %s initializing\n", therm_name(therm_type));
+
+	if (therm_family == ADT) {
+		for (i = 0; i < 3; i++) {
+			th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
+			set_limit(th, i);
+		}
+
+		printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
 		" to %d, %d, %d (°C)\n", 
 		th->initial_limits[0], th->initial_limits[1], th->initial_limits[2], 
 		th->limits[0], th->limits[1], th->limits[2]);
+	} 
 
 	thermostat = th;
 
@@ -459,6 +511,10 @@
 BUILD_SHOW_FUNC_DEG(cpu_limit,		 thermostat->limits[1])
 BUILD_SHOW_FUNC_DEG(gpu_limit,		 thermostat->limits[2])
 
+BUILD_SHOW_FUNC_DEG(adm_cpu_temperature, (read_reg(thermostat, ADM_TEMP_REG[1])))
+BUILD_SHOW_FUNC_DEG(adm_gpu_temperature, (read_reg(thermostat, ADM_TEMP_REG[2])))
+
+
 BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed)
 BUILD_SHOW_FUNC_INT(cpu_fan_speed,	 (read_fan_speed(thermostat, FAN_SPEED[0])))
 BUILD_SHOW_FUNC_INT(gpu_fan_speed,	 (read_fan_speed(thermostat, FAN_SPEED[1])))
@@ -471,6 +527,12 @@
 		   show_cpu_temperature,NULL);
 static DEVICE_ATTR(gpu_temperature,	S_IRUGO,
 		   show_gpu_temperature,NULL);
+static DEVICE_ATTR(adm_cpu_temperature,	S_IRUGO,
+		   show_adm_cpu_temperature,NULL);
+static DEVICE_ATTR(adm_gpu_temperature,	S_IRUGO,
+		   show_adm_gpu_temperature,NULL);
+
+
 static DEVICE_ATTR(cpu_limit,		S_IRUGO,
 		   show_cpu_limit,	NULL);
 static DEVICE_ATTR(gpu_limit,		S_IRUGO,
@@ -500,11 +562,31 @@
 	np = of_find_node_by_name(NULL, "fan");
 	if (!np)
 		return -ENODEV;
-	if (device_is_compatible(np, "adt7460"))
+	if (device_is_compatible(np, "adt7460")) {
 		therm_type = ADT7460;
-	else if (device_is_compatible(np, "adt7467"))
+		therm_family = ADT;
+	} else if (device_is_compatible(np, "adt7467")) {
 		therm_type = ADT7467;
-	else
+		therm_family = ADT;
+	} else if (device_is_compatible(np, "adm1030")) {
+		therm_type = ADM1030;
+		therm_family = ADM;
+		/* patch nonexistent remote2 */
+		ADM_TEMP_REG[2] = ADM_TEMP_REG[1];
+		ADM_TEMP_REG[1] = ADM_TEMP_REG[0];
+		ADM_LIMIT_REG[2]= ADM_LIMIT_REG[1];
+		ADM_LIMIT_REG[1]= ADM_LIMIT_REG[0];
+		default_limits_local[0] = default_limits_local[1];
+		for (i = 0; i < 3; i++)
+			default_limits_chip[i] = default_limits_local[i];
+	}
+	else if (device_is_compatible(np, "adm1031")) {
+		therm_type = ADM1031;
+		therm_family = ADM;
+		for (i = 0; i < 3; i++)
+			default_limits_chip[i] = default_limits_local[i];
+		
+	} else
 		return -ENODEV;
 
 	prop = (u32 *)get_property(np, "reg", NULL);
@@ -522,14 +604,20 @@
 		printk(KERN_ERR "Can't register temperatures device !\n");
 		return -ENODEV;
 	}
-	
-	device_create_file(&of_dev->dev, &dev_attr_cpu_temperature);
-	device_create_file(&of_dev->dev, &dev_attr_gpu_temperature);
+
+	if (therm_family == ADT) {	
+		device_create_file(&of_dev->dev, &dev_attr_cpu_temperature);
+		device_create_file(&of_dev->dev, &dev_attr_gpu_temperature);
+		device_create_file(&of_dev->dev, &dev_attr_specified_fan_speed);
+		device_create_file(&of_dev->dev, &dev_attr_cpu_fan_speed);
+	} else {
+		device_create_file(&of_dev->dev, &dev_attr_adm_cpu_temperature);
+		device_create_file(&of_dev->dev, &dev_attr_adm_gpu_temperature);
+	}
 	device_create_file(&of_dev->dev, &dev_attr_cpu_limit);
 	device_create_file(&of_dev->dev, &dev_attr_gpu_limit);
 	device_create_file(&of_dev->dev, &dev_attr_limit_adjust);
-	device_create_file(&of_dev->dev, &dev_attr_specified_fan_speed);
-	device_create_file(&of_dev->dev, &dev_attr_cpu_fan_speed);
+
 	if(therm_type == ADT7460)
 		device_create_file(&of_dev->dev, &dev_attr_gpu_fan_speed);
 
@@ -544,15 +632,23 @@
 thermostat_exit(void)
 {
 	if (of_dev) {
-		device_remove_file(&of_dev->dev, &dev_attr_cpu_temperature);
-		device_remove_file(&of_dev->dev, &dev_attr_gpu_temperature);
+		if (therm_family == ADT) {
+			device_remove_file(&of_dev->dev, &dev_attr_cpu_temperature);
+			device_remove_file(&of_dev->dev, &dev_attr_gpu_temperature);
+			device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed);
+			device_remove_file(&of_dev->dev, &dev_attr_cpu_fan_speed);
+		} else {
+			device_remove_file(&of_dev->dev, &dev_attr_adm_cpu_temperature);
+			device_remove_file(&of_dev->dev, &dev_attr_adm_gpu_temperature);
+		}
+
 		device_remove_file(&of_dev->dev, &dev_attr_cpu_limit);
 		device_remove_file(&of_dev->dev, &dev_attr_gpu_limit);
 		device_remove_file(&of_dev->dev, &dev_attr_limit_adjust);
-		device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed);
-		device_remove_file(&of_dev->dev, &dev_attr_cpu_fan_speed);
+
 		if(therm_type == ADT7460)
 			device_remove_file(&of_dev->dev, &dev_attr_gpu_fan_speed);
+
 		of_device_unregister(of_dev);
 	}
 	i2c_del_driver(&thermostat_driver);
