diff options
Diffstat (limited to 'drivers/macintosh/windfarm_smu_controls.c')
-rw-r--r-- | drivers/macintosh/windfarm_smu_controls.c | 69 |
1 files changed, 54 insertions, 15 deletions
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 4d811600bdab..a9e88edc0c72 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "windfarm.h" | 25 | #include "windfarm.h" |
26 | 26 | ||
27 | #define VERSION "0.3" | 27 | #define VERSION "0.4" |
28 | 28 | ||
29 | #undef DEBUG | 29 | #undef DEBUG |
30 | 30 | ||
@@ -34,6 +34,8 @@ | |||
34 | #define DBG(args...) do { } while(0) | 34 | #define DBG(args...) do { } while(0) |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | static int smu_supports_new_fans_ops = 1; | ||
38 | |||
37 | /* | 39 | /* |
38 | * SMU fans control object | 40 | * SMU fans control object |
39 | */ | 41 | */ |
@@ -59,23 +61,49 @@ static int smu_set_fan(int pwm, u8 id, u16 value) | |||
59 | 61 | ||
60 | /* Fill SMU command structure */ | 62 | /* Fill SMU command structure */ |
61 | cmd.cmd = SMU_CMD_FAN_COMMAND; | 63 | cmd.cmd = SMU_CMD_FAN_COMMAND; |
62 | cmd.data_len = 14; | 64 | |
65 | /* The SMU has an "old" and a "new" way of setting the fan speed | ||
66 | * Unfortunately, I found no reliable way to know which one works | ||
67 | * on a given machine model. After some investigations it appears | ||
68 | * that MacOS X just tries the new one, and if it fails fallbacks | ||
69 | * to the old ones ... Ugh. | ||
70 | */ | ||
71 | retry: | ||
72 | if (smu_supports_new_fans_ops) { | ||
73 | buffer[0] = 0x30; | ||
74 | buffer[1] = id; | ||
75 | *((u16 *)(&buffer[2])) = value; | ||
76 | cmd.data_len = 4; | ||
77 | } else { | ||
78 | if (id > 7) | ||
79 | return -EINVAL; | ||
80 | /* Fill argument buffer */ | ||
81 | memset(buffer, 0, 16); | ||
82 | buffer[0] = pwm ? 0x10 : 0x00; | ||
83 | buffer[1] = 0x01 << id; | ||
84 | *((u16 *)&buffer[2 + id * 2]) = value; | ||
85 | cmd.data_len = 14; | ||
86 | } | ||
87 | |||
63 | cmd.reply_len = 16; | 88 | cmd.reply_len = 16; |
64 | cmd.data_buf = cmd.reply_buf = buffer; | 89 | cmd.data_buf = cmd.reply_buf = buffer; |
65 | cmd.status = 0; | 90 | cmd.status = 0; |
66 | cmd.done = smu_done_complete; | 91 | cmd.done = smu_done_complete; |
67 | cmd.misc = ∁ | 92 | cmd.misc = ∁ |
68 | 93 | ||
69 | /* Fill argument buffer */ | ||
70 | memset(buffer, 0, 16); | ||
71 | buffer[0] = pwm ? 0x10 : 0x00; | ||
72 | buffer[1] = 0x01 << id; | ||
73 | *((u16 *)&buffer[2 + id * 2]) = value; | ||
74 | |||
75 | rc = smu_queue_cmd(&cmd); | 94 | rc = smu_queue_cmd(&cmd); |
76 | if (rc) | 95 | if (rc) |
77 | return rc; | 96 | return rc; |
78 | wait_for_completion(&comp); | 97 | wait_for_completion(&comp); |
98 | |||
99 | /* Handle fallback (see coment above) */ | ||
100 | if (cmd.status != 0 && smu_supports_new_fans_ops) { | ||
101 | printk(KERN_WARNING "windfarm: SMU failed new fan command " | ||
102 | "falling back to old method\n"); | ||
103 | smu_supports_new_fans_ops = 0; | ||
104 | goto retry; | ||
105 | } | ||
106 | |||
79 | return cmd.status; | 107 | return cmd.status; |
80 | } | 108 | } |
81 | 109 | ||
@@ -158,19 +186,29 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, | |||
158 | 186 | ||
159 | /* Names used on desktop models */ | 187 | /* Names used on desktop models */ |
160 | if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") || | 188 | if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") || |
161 | !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan")) | 189 | !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan") || |
190 | !strcmp(l, "CPU A EXHAUST")) | ||
162 | fct->ctrl.name = "cpu-rear-fan-0"; | 191 | fct->ctrl.name = "cpu-rear-fan-0"; |
163 | else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1")) | 192 | else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1") || |
193 | !strcmp(l, "CPU B EXHAUST")) | ||
164 | fct->ctrl.name = "cpu-rear-fan-1"; | 194 | fct->ctrl.name = "cpu-rear-fan-1"; |
165 | else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") || | 195 | else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") || |
166 | !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan")) | 196 | !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan") || |
197 | !strcmp(l, "CPU A INTAKE")) | ||
167 | fct->ctrl.name = "cpu-front-fan-0"; | 198 | fct->ctrl.name = "cpu-front-fan-0"; |
168 | else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1")) | 199 | else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1") || |
200 | !strcmp(l, "CPU B INTAKE")) | ||
169 | fct->ctrl.name = "cpu-front-fan-1"; | 201 | fct->ctrl.name = "cpu-front-fan-1"; |
170 | else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan")) | 202 | else if (!strcmp(l, "CPU A PUMP")) |
203 | fct->ctrl.name = "cpu-pump-0"; | ||
204 | else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") || | ||
205 | !strcmp(l, "EXPANSION SLOTS INTAKE")) | ||
171 | fct->ctrl.name = "slots-fan"; | 206 | fct->ctrl.name = "slots-fan"; |
172 | else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay")) | 207 | else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay") || |
208 | !strcmp(l, "DRIVE BAY A INTAKE")) | ||
173 | fct->ctrl.name = "drive-bay-fan"; | 209 | fct->ctrl.name = "drive-bay-fan"; |
210 | else if (!strcmp(l, "BACKSIDE")) | ||
211 | fct->ctrl.name = "backside-fan"; | ||
174 | 212 | ||
175 | /* Names used on iMac models */ | 213 | /* Names used on iMac models */ |
176 | if (!strcmp(l, "System Fan") || !strcmp(l, "System fan")) | 214 | if (!strcmp(l, "System Fan") || !strcmp(l, "System fan")) |
@@ -223,7 +261,8 @@ static int __init smu_controls_init(void) | |||
223 | 261 | ||
224 | /* Look for RPM fans */ | 262 | /* Look for RPM fans */ |
225 | for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;) | 263 | for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;) |
226 | if (!strcmp(fans->name, "rpm-fans")) | 264 | if (!strcmp(fans->name, "rpm-fans") || |
265 | device_is_compatible(fans, "smu-rpm-fans")) | ||
227 | break; | 266 | break; |
228 | for (fan = NULL; | 267 | for (fan = NULL; |
229 | fans && (fan = of_get_next_child(fans, fan)) != NULL;) { | 268 | fans && (fan = of_get_next_child(fans, fan)) != NULL;) { |