2 * acpi_fan.c - ACPI Fan Driver ($Revision: 29 $)
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/types.h>
26 #include <linux/uaccess.h>
27 #include <linux/thermal.h>
28 #include <linux/acpi.h>
29 #include <linux/platform_device.h>
30 #include <linux/sort.h>
32 MODULE_AUTHOR("Paul Diefenbaugh");
33 MODULE_DESCRIPTION("ACPI Fan Driver");
34 MODULE_LICENSE("GPL");
36 static int acpi_fan_probe(struct platform_device
*pdev
);
37 static int acpi_fan_remove(struct platform_device
*pdev
);
39 static const struct acpi_device_id fan_device_ids
[] = {
44 MODULE_DEVICE_TABLE(acpi
, fan_device_ids
);
46 #ifdef CONFIG_PM_SLEEP
47 static int acpi_fan_suspend(struct device
*dev
);
48 static int acpi_fan_resume(struct device
*dev
);
49 static const struct dev_pm_ops acpi_fan_pm
= {
50 .resume
= acpi_fan_resume
,
51 .freeze
= acpi_fan_suspend
,
52 .thaw
= acpi_fan_resume
,
53 .restore
= acpi_fan_resume
,
55 #define FAN_PM_OPS_PTR (&acpi_fan_pm)
57 #define FAN_PM_OPS_PTR NULL
72 u64 low_speed_notification
;
77 struct acpi_fan_fif fif
;
78 struct acpi_fan_fps
*fps
;
80 struct thermal_cooling_device
*cdev
;
83 static struct platform_driver acpi_fan_driver
= {
84 .probe
= acpi_fan_probe
,
85 .remove
= acpi_fan_remove
,
88 .acpi_match_table
= fan_device_ids
,
93 /* thermal cooling device callbacks */
94 static int fan_get_max_state(struct thermal_cooling_device
*cdev
, unsigned long
97 struct acpi_device
*device
= cdev
->devdata
;
98 struct acpi_fan
*fan
= acpi_driver_data(device
);
101 *state
= fan
->fps_count
- 1;
107 static int fan_get_state_acpi4(struct acpi_device
*device
, unsigned long *state
)
109 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
110 struct acpi_fan
*fan
= acpi_driver_data(device
);
111 union acpi_object
*obj
;
115 status
= acpi_evaluate_object(device
->handle
, "_FST", NULL
, &buffer
);
116 if (ACPI_FAILURE(status
)) {
117 dev_err(&device
->dev
, "Get fan state failed\n");
121 obj
= buffer
.pointer
;
122 if (!obj
|| obj
->type
!= ACPI_TYPE_PACKAGE
||
123 obj
->package
.count
!= 3 ||
124 obj
->package
.elements
[1].type
!= ACPI_TYPE_INTEGER
) {
125 dev_err(&device
->dev
, "Invalid _FST data\n");
130 control
= obj
->package
.elements
[1].integer
.value
;
131 for (i
= 0; i
< fan
->fps_count
; i
++) {
133 * When Fine Grain Control is set, return the state
134 * corresponding to maximum fan->fps[i].control
135 * value compared to the current speed. Here the
136 * fan->fps[] is sorted array with increasing speed.
138 if (fan
->fif
.fine_grain_ctrl
&& control
< fan
->fps
[i
].control
) {
139 i
= (i
> 0) ? i
- 1 : 0;
141 } else if (control
== fan
->fps
[i
].control
) {
145 if (i
== fan
->fps_count
) {
146 dev_dbg(&device
->dev
, "Invalid control value returned\n");
158 static int fan_get_state(struct acpi_device
*device
, unsigned long *state
)
161 int acpi_state
= ACPI_STATE_D0
;
163 result
= acpi_device_update_power(device
, &acpi_state
);
167 *state
= acpi_state
== ACPI_STATE_D3_COLD
168 || acpi_state
== ACPI_STATE_D3_HOT
?
169 0 : (acpi_state
== ACPI_STATE_D0
? 1 : -1);
173 static int fan_get_cur_state(struct thermal_cooling_device
*cdev
, unsigned long
176 struct acpi_device
*device
= cdev
->devdata
;
177 struct acpi_fan
*fan
= acpi_driver_data(device
);
180 return fan_get_state_acpi4(device
, state
);
182 return fan_get_state(device
, state
);
185 static int fan_set_state(struct acpi_device
*device
, unsigned long state
)
187 if (state
!= 0 && state
!= 1)
190 return acpi_device_set_power(device
,
191 state
? ACPI_STATE_D0
: ACPI_STATE_D3_COLD
);
194 static int fan_set_state_acpi4(struct acpi_device
*device
, unsigned long state
)
196 struct acpi_fan
*fan
= acpi_driver_data(device
);
199 if (state
>= fan
->fps_count
)
202 status
= acpi_execute_simple_method(device
->handle
, "_FSL",
203 fan
->fps
[state
].control
);
204 if (ACPI_FAILURE(status
)) {
205 dev_dbg(&device
->dev
, "Failed to set state by _FSL\n");
213 fan_set_cur_state(struct thermal_cooling_device
*cdev
, unsigned long state
)
215 struct acpi_device
*device
= cdev
->devdata
;
216 struct acpi_fan
*fan
= acpi_driver_data(device
);
219 return fan_set_state_acpi4(device
, state
);
221 return fan_set_state(device
, state
);
224 static const struct thermal_cooling_device_ops fan_cooling_ops
= {
225 .get_max_state
= fan_get_max_state
,
226 .get_cur_state
= fan_get_cur_state
,
227 .set_cur_state
= fan_set_cur_state
,
230 /* --------------------------------------------------------------------------
232 * --------------------------------------------------------------------------
235 static bool acpi_fan_is_acpi4(struct acpi_device
*device
)
237 return acpi_has_method(device
->handle
, "_FIF") &&
238 acpi_has_method(device
->handle
, "_FPS") &&
239 acpi_has_method(device
->handle
, "_FSL") &&
240 acpi_has_method(device
->handle
, "_FST");
243 static int acpi_fan_get_fif(struct acpi_device
*device
)
245 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
246 struct acpi_fan
*fan
= acpi_driver_data(device
);
247 struct acpi_buffer format
= { sizeof("NNNN"), "NNNN" };
248 struct acpi_buffer fif
= { sizeof(fan
->fif
), &fan
->fif
};
249 union acpi_object
*obj
;
252 status
= acpi_evaluate_object(device
->handle
, "_FIF", NULL
, &buffer
);
253 if (ACPI_FAILURE(status
))
256 obj
= buffer
.pointer
;
257 if (!obj
|| obj
->type
!= ACPI_TYPE_PACKAGE
) {
258 dev_err(&device
->dev
, "Invalid _FIF data\n");
263 status
= acpi_extract_package(obj
, &format
, &fif
);
264 if (ACPI_FAILURE(status
)) {
265 dev_err(&device
->dev
, "Invalid _FIF element\n");
274 static int acpi_fan_speed_cmp(const void *a
, const void *b
)
276 const struct acpi_fan_fps
*fps1
= a
;
277 const struct acpi_fan_fps
*fps2
= b
;
278 return fps1
->speed
- fps2
->speed
;
281 static int acpi_fan_get_fps(struct acpi_device
*device
)
283 struct acpi_fan
*fan
= acpi_driver_data(device
);
284 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
285 union acpi_object
*obj
;
289 status
= acpi_evaluate_object(device
->handle
, "_FPS", NULL
, &buffer
);
290 if (ACPI_FAILURE(status
))
293 obj
= buffer
.pointer
;
294 if (!obj
|| obj
->type
!= ACPI_TYPE_PACKAGE
|| obj
->package
.count
< 2) {
295 dev_err(&device
->dev
, "Invalid _FPS data\n");
300 fan
->fps_count
= obj
->package
.count
- 1; /* minus revision field */
301 fan
->fps
= devm_kzalloc(&device
->dev
,
302 fan
->fps_count
* sizeof(struct acpi_fan_fps
),
305 dev_err(&device
->dev
, "Not enough memory\n");
309 for (i
= 0; i
< fan
->fps_count
; i
++) {
310 struct acpi_buffer format
= { sizeof("NNNNN"), "NNNNN" };
311 struct acpi_buffer fps
= { sizeof(fan
->fps
[i
]), &fan
->fps
[i
] };
312 status
= acpi_extract_package(&obj
->package
.elements
[i
+ 1],
314 if (ACPI_FAILURE(status
)) {
315 dev_err(&device
->dev
, "Invalid _FPS element\n");
320 /* sort the state array according to fan speed in increase order */
321 sort(fan
->fps
, fan
->fps_count
, sizeof(*fan
->fps
),
322 acpi_fan_speed_cmp
, NULL
);
329 static int acpi_fan_probe(struct platform_device
*pdev
)
332 struct thermal_cooling_device
*cdev
;
333 struct acpi_fan
*fan
;
334 struct acpi_device
*device
= ACPI_COMPANION(&pdev
->dev
);
337 fan
= devm_kzalloc(&pdev
->dev
, sizeof(*fan
), GFP_KERNEL
);
339 dev_err(&device
->dev
, "No memory for fan\n");
342 device
->driver_data
= fan
;
343 platform_set_drvdata(pdev
, fan
);
345 if (acpi_fan_is_acpi4(device
)) {
346 if (acpi_fan_get_fif(device
) || acpi_fan_get_fps(device
))
350 result
= acpi_device_update_power(device
, NULL
);
352 dev_err(&device
->dev
, "Failed to set initial power state\n");
357 if (!strncmp(pdev
->name
, "PNP0C0B", strlen("PNP0C0B")))
360 name
= acpi_device_bid(device
);
362 cdev
= thermal_cooling_device_register(name
, device
,
365 result
= PTR_ERR(cdev
);
369 dev_dbg(&pdev
->dev
, "registered as cooling_device%d\n", cdev
->id
);
372 result
= sysfs_create_link(&pdev
->dev
.kobj
,
376 dev_err(&pdev
->dev
, "Failed to create sysfs link 'thermal_cooling'\n");
378 result
= sysfs_create_link(&cdev
->device
.kobj
,
382 dev_err(&pdev
->dev
, "Failed to create sysfs link 'device'\n");
388 static int acpi_fan_remove(struct platform_device
*pdev
)
390 struct acpi_fan
*fan
= platform_get_drvdata(pdev
);
392 sysfs_remove_link(&pdev
->dev
.kobj
, "thermal_cooling");
393 sysfs_remove_link(&fan
->cdev
->device
.kobj
, "device");
394 thermal_cooling_device_unregister(fan
->cdev
);
399 #ifdef CONFIG_PM_SLEEP
400 static int acpi_fan_suspend(struct device
*dev
)
402 struct acpi_fan
*fan
= dev_get_drvdata(dev
);
406 acpi_device_set_power(ACPI_COMPANION(dev
), ACPI_STATE_D0
);
411 static int acpi_fan_resume(struct device
*dev
)
414 struct acpi_fan
*fan
= dev_get_drvdata(dev
);
419 result
= acpi_device_update_power(ACPI_COMPANION(dev
), NULL
);
421 dev_err(dev
, "Error updating fan power state\n");
427 module_platform_driver(acpi_fan_driver
);