aboutsummaryrefslogtreecommitdiffstats
path: root/ubuntu/omnibook/fan_policy.c
blob: 67915ffedbb48ab90e12dba5ac8faea146df3099 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
 * fan_policy.c -- fan policy support
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * Written by Soós Péter <sp@osb.hu>, 2002-2004
 * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
 */

#include "omnibook.h"

#include <linux/ctype.h>
#include "hardware.h"

/*
 * Default temperature limits.
 * Danger! You may overheat your CPU!
 * Do not change these values unless you exactly know what you do.
 */

#define OMNIBOOK_FAN_LEVELS			8
#define OMNIBOOK_FAN_MIN			25	/* Minimal value of fan off temperature */
#define OMNIBOOK_FOT_MAX			75	/* Maximal value of fan off temperature */
#define OMNIBOOK_FAN_MAX			95	/* Maximal value of fan on temperature */
#define OMNIBOOK_FOT_DEFAULT			60	/* Default value of fan off temperature */
#define OMNIBOOK_FAN1_DEFAULT			75	/* Default value of fan on temperature */
#define OMNIBOOK_FAN2_DEFAULT			85	/* Default value of fan level 2 temperature */
#define OMNIBOOK_FAN3_DEFAULT			90	/* Default value of fan level 3 temperature */
#define OMNIBOOK_FAN4_DEFAULT			95	/* Default value of fan level 4 temperature */
#define OMNIBOOK_FAN5_DEFAULT			95	/* Default value of fan level 5 temperature */
#define OMNIBOOK_FAN6_DEFAULT			95	/* Default value of fan level 6 temperature */
#define OMNIBOOK_FAN7_DEFAULT			95	/* Default value of fan level 7 temperature */

static const u8 fan_defaults[] = {
		OMNIBOOK_FOT_DEFAULT,
		OMNIBOOK_FAN1_DEFAULT,
		OMNIBOOK_FAN2_DEFAULT,
		OMNIBOOK_FAN3_DEFAULT,
		OMNIBOOK_FAN4_DEFAULT,
		OMNIBOOK_FAN5_DEFAULT,
		OMNIBOOK_FAN6_DEFAULT,
		OMNIBOOK_FAN7_DEFAULT,
};

static int omnibook_get_fan_policy(struct omnibook_operation *io_op, u8 *fan_policy)
{
	int retval ;
	int i;

	for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
		io_op->read_addr = XE3GF_FOT + i;
		if ((retval = __backend_byte_read(io_op, &fan_policy[i])))
			return retval;
	}

	return 0;
}

static int omnibook_set_fan_policy(struct omnibook_operation *io_op, const u8 *fan_policy)
{
	int retval;
	int i;

	if (fan_policy[0] > OMNIBOOK_FOT_MAX)
		return -EINVAL;

	for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
		if ((fan_policy[i] > fan_policy[i + 1])
		    || (fan_policy[i] < OMNIBOOK_FAN_MIN)
		    || (fan_policy[i] > OMNIBOOK_FAN_MAX))
			return -EINVAL;
	}
	for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
		io_op->write_addr = XE3GF_FOT + i;
		if ((retval = __backend_byte_write(io_op, fan_policy[i])))
			return retval;
	}

	return 0;
}

static int omnibook_fan_policy_read(char *buffer, struct omnibook_operation *io_op)
{
	int retval;
	int len = 0;
	u8 i;
	u8 fan_policy[OMNIBOOK_FAN_LEVELS];

	if(mutex_lock_interruptible(&io_op->backend->mutex))
		return -ERESTARTSYS;

	retval = omnibook_get_fan_policy(io_op, &fan_policy[0]);

	mutex_unlock(&io_op->backend->mutex);

	if(retval)
		return retval;

	len += sprintf(buffer + len, "Fan off temperature:        %2d C\n", fan_policy[0]);
	len += sprintf(buffer + len, "Fan on temperature:         %2d C\n", fan_policy[1]);
	for (i = 2; i < OMNIBOOK_FAN_LEVELS; i++) {
		len +=
		    sprintf(buffer + len, "Fan level %1d temperature:    %2d C\n", i,
			    fan_policy[i]);
	}
	len += sprintf(buffer + len, "Minimal temperature to set: %2d C\n", OMNIBOOK_FAN_MIN);
	len += sprintf(buffer + len, "Maximal temperature to set: %2d C\n", OMNIBOOK_FAN_MAX);

	return len;
}

static int omnibook_fan_policy_write(char *buffer, struct omnibook_operation *io_op)
{
	int n = 0;
	char *b;
	char *endp;
	int retval;
	int temp;
	u8 fan_policy[OMNIBOOK_FAN_LEVELS];

	if(mutex_lock_interruptible(&io_op->backend->mutex))
		return -ERESTARTSYS;

	if ((retval = omnibook_get_fan_policy(io_op, &fan_policy[0])))
		goto out;

	/* 
	 * Could also be done much simpler using sscanf(,"%u %u ... 
	 * but this would hardcode OMNIBOOK_FAN_LEVELS.
	 * The parsed format is "%u " repeated OMNIBOOK_FAN_LEVELS+1 times
	 */

	b = buffer;
	do {
		dprintk("n=[%i] b=[%s]\n", n, b);
		if (n > OMNIBOOK_FAN_LEVELS) {
			retval = -EINVAL;
			goto out;
		}
		if (!isspace(*b)) {
			temp = simple_strtoul(b, &endp, 10);
			if (endp != b) {	/* there was a match */
				fan_policy[n++] = temp;
				b = endp;
			} else {
				retval = -EINVAL;
				goto out;
			}
		} else
			b++;
	} while ((*b != '\0') && (*b != '\n'));

	/* A zero value set the defaults */
	if ((fan_policy[0] == 0) && (n == 1))
		retval = omnibook_set_fan_policy(io_op, &fan_defaults[0]);
	else
		retval = omnibook_set_fan_policy(io_op, &fan_policy[0]);

	out:
	mutex_unlock(&io_op->backend->mutex);
	return retval;
}

static struct omnibook_tbl fan_policy_table[] __initdata = {
	{XE3GF, {EC,}},
	{0,}
};

static struct omnibook_feature __declared_feature fan_policy_driver = {
	.name = "fan_policy",
	.enabled = 1,
	.read = omnibook_fan_policy_read,
	.write = omnibook_fan_policy_write,
	.ectypes = XE3GF,
	.tbl = fan_policy_table,
};

module_param_named(fan_policy, fan_policy_driver.enabled, int, S_IRUGO);
MODULE_PARM_DESC(fan_policy, "Use 0 to disable, 1 to enable fan control policy support");
/* End of file */