diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 12:32:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 12:32:11 -0400 |
commit | c11f6c82581e8be4e1829c677db54e7f55cebece (patch) | |
tree | 1a116241b0831ded998aabe800bdc24104cbd826 /drivers/platform/x86/acerhdf.c | |
parent | 40aba218969914d1b225e742617adb921cf94eae (diff) | |
parent | 193a6dec1c0246a80b6d0101e4f351ccf877bcac (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (119 commits)
ACPI: don't pass handle for fixed hardware notifications
ACPI: remove null pointer checks in deferred execution path
ACPI: simplify deferred execution path
acerhdf: additional BIOS versions
acerhdf: convert to dev_pm_ops
acerhdf: fix fan control for AOA150 model
thermal: add missing Kconfig dependency
acpi: switch /proc/acpi/{debug_layer,debug_level} to seq_file
hp-wmi: fix rfkill memory leak on unload
ACPI: remove unnecessary #ifdef CONFIG_DMI
ACPI: linux/acpi.h should not include linux/dmi.h
hwmon driver for ACPI 4.0 power meters
topstar-laptop: add new driver for hotkeys support on Topstar N01
thinkpad_acpi: fix rfkill memory leak on unload
thinkpad-acpi: report brightness events when required
thinkpad-acpi: don't poll by default any of the reserved hotkeys
thinkpad-acpi: Fix procfs hotkey reset command
thinkpad-acpi: deprecate hotkey_bios_mask
thinkpad-acpi: hotkey poll fixes
thinkpad-acpi: be more strict when detecting a ThinkPad
...
Diffstat (limited to 'drivers/platform/x86/acerhdf.c')
-rw-r--r-- | drivers/platform/x86/acerhdf.c | 121 |
1 files changed, 78 insertions, 43 deletions
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index bdfee177eefb..0a8f735f6c4a 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c | |||
@@ -52,7 +52,7 @@ | |||
52 | */ | 52 | */ |
53 | #undef START_IN_KERNEL_MODE | 53 | #undef START_IN_KERNEL_MODE |
54 | 54 | ||
55 | #define DRV_VER "0.5.13" | 55 | #define DRV_VER "0.5.17" |
56 | 56 | ||
57 | /* | 57 | /* |
58 | * According to the Atom N270 datasheet, | 58 | * According to the Atom N270 datasheet, |
@@ -90,6 +90,7 @@ static unsigned int fanoff = 58; | |||
90 | static unsigned int verbose; | 90 | static unsigned int verbose; |
91 | static unsigned int fanstate = ACERHDF_FAN_AUTO; | 91 | static unsigned int fanstate = ACERHDF_FAN_AUTO; |
92 | static char force_bios[16]; | 92 | static char force_bios[16]; |
93 | static char force_product[16]; | ||
93 | static unsigned int prev_interval; | 94 | static unsigned int prev_interval; |
94 | struct thermal_zone_device *thz_dev; | 95 | struct thermal_zone_device *thz_dev; |
95 | struct thermal_cooling_device *cl_dev; | 96 | struct thermal_cooling_device *cl_dev; |
@@ -107,34 +108,62 @@ module_param(verbose, uint, 0600); | |||
107 | MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); | 108 | MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); |
108 | module_param_string(force_bios, force_bios, 16, 0); | 109 | module_param_string(force_bios, force_bios, 16, 0); |
109 | MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check"); | 110 | MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check"); |
111 | module_param_string(force_product, force_product, 16, 0); | ||
112 | MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); | ||
113 | |||
114 | /* | ||
115 | * cmd_off: to switch the fan completely off / to check if the fan is off | ||
116 | * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then | ||
117 | * the fan speed depending on the temperature | ||
118 | */ | ||
119 | struct fancmd { | ||
120 | u8 cmd_off; | ||
121 | u8 cmd_auto; | ||
122 | }; | ||
110 | 123 | ||
111 | /* BIOS settings */ | 124 | /* BIOS settings */ |
112 | struct bios_settings_t { | 125 | struct bios_settings_t { |
113 | const char *vendor; | 126 | const char *vendor; |
127 | const char *product; | ||
114 | const char *version; | 128 | const char *version; |
115 | unsigned char fanreg; | 129 | unsigned char fanreg; |
116 | unsigned char tempreg; | 130 | unsigned char tempreg; |
117 | unsigned char fancmd[2]; /* fan off and auto commands */ | 131 | struct fancmd cmd; |
118 | }; | 132 | }; |
119 | 133 | ||
120 | /* Register addresses and values for different BIOS versions */ | 134 | /* Register addresses and values for different BIOS versions */ |
121 | static const struct bios_settings_t bios_tbl[] = { | 135 | static const struct bios_settings_t bios_tbl[] = { |
122 | {"Acer", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, | 136 | /* AOA110 */ |
123 | {"Acer", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, | 137 | {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, |
124 | {"Acer", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, | 138 | {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, |
125 | {"Acer", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, | 139 | {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, |
126 | {"Acer", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, | 140 | {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, |
127 | {"Acer", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, | 141 | {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, |
128 | {"Acer", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, | 142 | {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} }, |
129 | {"Acer", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, | 143 | {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, |
130 | {"Gateway", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, | 144 | {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, |
131 | {"Packard Bell", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, | 145 | {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, |
132 | {"", "", 0, 0, {0, 0} } | 146 | /* AOA150 */ |
147 | {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x00} }, | ||
148 | {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} }, | ||
149 | {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, | ||
150 | {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} }, | ||
151 | {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} }, | ||
152 | {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} }, | ||
153 | {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} }, | ||
154 | {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, | ||
155 | /* special BIOS / other */ | ||
156 | {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, | ||
157 | {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} }, | ||
158 | {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} }, | ||
159 | {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, | ||
160 | {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, | ||
161 | /* pewpew-terminator */ | ||
162 | {"", "", "", 0, 0, {0, 0} } | ||
133 | }; | 163 | }; |
134 | 164 | ||
135 | static const struct bios_settings_t *bios_cfg __read_mostly; | 165 | static const struct bios_settings_t *bios_cfg __read_mostly; |
136 | 166 | ||
137 | |||
138 | static int acerhdf_get_temp(int *temp) | 167 | static int acerhdf_get_temp(int *temp) |
139 | { | 168 | { |
140 | u8 read_temp; | 169 | u8 read_temp; |
@@ -150,13 +179,14 @@ static int acerhdf_get_temp(int *temp) | |||
150 | static int acerhdf_get_fanstate(int *state) | 179 | static int acerhdf_get_fanstate(int *state) |
151 | { | 180 | { |
152 | u8 fan; | 181 | u8 fan; |
153 | bool tmp; | ||
154 | 182 | ||
155 | if (ec_read(bios_cfg->fanreg, &fan)) | 183 | if (ec_read(bios_cfg->fanreg, &fan)) |
156 | return -EINVAL; | 184 | return -EINVAL; |
157 | 185 | ||
158 | tmp = (fan == bios_cfg->fancmd[ACERHDF_FAN_OFF]); | 186 | if (fan != bios_cfg->cmd.cmd_off) |
159 | *state = tmp ? ACERHDF_FAN_OFF : ACERHDF_FAN_AUTO; | 187 | *state = ACERHDF_FAN_AUTO; |
188 | else | ||
189 | *state = ACERHDF_FAN_OFF; | ||
160 | 190 | ||
161 | return 0; | 191 | return 0; |
162 | } | 192 | } |
@@ -175,7 +205,8 @@ static void acerhdf_change_fanstate(int state) | |||
175 | state = ACERHDF_FAN_AUTO; | 205 | state = ACERHDF_FAN_AUTO; |
176 | } | 206 | } |
177 | 207 | ||
178 | cmd = bios_cfg->fancmd[state]; | 208 | cmd = (state == ACERHDF_FAN_OFF) ? bios_cfg->cmd.cmd_off |
209 | : bios_cfg->cmd.cmd_auto; | ||
179 | fanstate = state; | 210 | fanstate = state; |
180 | 211 | ||
181 | ec_write(bios_cfg->fanreg, cmd); | 212 | ec_write(bios_cfg->fanreg, cmd); |
@@ -408,7 +439,7 @@ struct thermal_cooling_device_ops acerhdf_cooling_ops = { | |||
408 | }; | 439 | }; |
409 | 440 | ||
410 | /* suspend / resume functionality */ | 441 | /* suspend / resume functionality */ |
411 | static int acerhdf_suspend(struct platform_device *dev, pm_message_t state) | 442 | static int acerhdf_suspend(struct device *dev) |
412 | { | 443 | { |
413 | if (kernelmode) | 444 | if (kernelmode) |
414 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | 445 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); |
@@ -419,14 +450,6 @@ static int acerhdf_suspend(struct platform_device *dev, pm_message_t state) | |||
419 | return 0; | 450 | return 0; |
420 | } | 451 | } |
421 | 452 | ||
422 | static int acerhdf_resume(struct platform_device *device) | ||
423 | { | ||
424 | if (verbose) | ||
425 | pr_notice("resuming\n"); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int __devinit acerhdf_probe(struct platform_device *device) | 453 | static int __devinit acerhdf_probe(struct platform_device *device) |
431 | { | 454 | { |
432 | return 0; | 455 | return 0; |
@@ -437,15 +460,19 @@ static int acerhdf_remove(struct platform_device *device) | |||
437 | return 0; | 460 | return 0; |
438 | } | 461 | } |
439 | 462 | ||
440 | struct platform_driver acerhdf_drv = { | 463 | static struct dev_pm_ops acerhdf_pm_ops = { |
464 | .suspend = acerhdf_suspend, | ||
465 | .freeze = acerhdf_suspend, | ||
466 | }; | ||
467 | |||
468 | static struct platform_driver acerhdf_driver = { | ||
441 | .driver = { | 469 | .driver = { |
442 | .name = "acerhdf", | 470 | .name = "acerhdf", |
443 | .owner = THIS_MODULE, | 471 | .owner = THIS_MODULE, |
472 | .pm = &acerhdf_pm_ops, | ||
444 | }, | 473 | }, |
445 | .probe = acerhdf_probe, | 474 | .probe = acerhdf_probe, |
446 | .remove = acerhdf_remove, | 475 | .remove = acerhdf_remove, |
447 | .suspend = acerhdf_suspend, | ||
448 | .resume = acerhdf_resume, | ||
449 | }; | 476 | }; |
450 | 477 | ||
451 | 478 | ||
@@ -454,32 +481,40 @@ static int acerhdf_check_hardware(void) | |||
454 | { | 481 | { |
455 | char const *vendor, *version, *product; | 482 | char const *vendor, *version, *product; |
456 | int i; | 483 | int i; |
484 | unsigned long prod_len = 0; | ||
457 | 485 | ||
458 | /* get BIOS data */ | 486 | /* get BIOS data */ |
459 | vendor = dmi_get_system_info(DMI_SYS_VENDOR); | 487 | vendor = dmi_get_system_info(DMI_SYS_VENDOR); |
460 | version = dmi_get_system_info(DMI_BIOS_VERSION); | 488 | version = dmi_get_system_info(DMI_BIOS_VERSION); |
461 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | 489 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
462 | 490 | ||
491 | |||
463 | pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); | 492 | pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); |
464 | 493 | ||
465 | if (!force_bios[0]) { | 494 | if (force_bios[0]) { |
466 | if (strncmp(product, "AO", 2)) { | ||
467 | pr_err("no Aspire One hardware found\n"); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | } else { | ||
471 | pr_info("forcing BIOS version: %s\n", version); | ||
472 | version = force_bios; | 495 | version = force_bios; |
496 | pr_info("forcing BIOS version: %s\n", version); | ||
497 | kernelmode = 0; | ||
498 | } | ||
499 | |||
500 | if (force_product[0]) { | ||
501 | product = force_product; | ||
502 | pr_info("forcing BIOS product: %s\n", product); | ||
473 | kernelmode = 0; | 503 | kernelmode = 0; |
474 | } | 504 | } |
475 | 505 | ||
506 | prod_len = strlen(product); | ||
507 | |||
476 | if (verbose) | 508 | if (verbose) |
477 | pr_info("BIOS info: %s %s, product: %s\n", | 509 | pr_info("BIOS info: %s %s, product: %s\n", |
478 | vendor, version, product); | 510 | vendor, version, product); |
479 | 511 | ||
480 | /* search BIOS version and vendor in BIOS settings table */ | 512 | /* search BIOS version and vendor in BIOS settings table */ |
481 | for (i = 0; bios_tbl[i].version[0]; i++) { | 513 | for (i = 0; bios_tbl[i].version[0]; i++) { |
482 | if (!strcmp(bios_tbl[i].vendor, vendor) && | 514 | if (strlen(bios_tbl[i].product) >= prod_len && |
515 | !strncmp(bios_tbl[i].product, product, | ||
516 | strlen(bios_tbl[i].product)) && | ||
517 | !strcmp(bios_tbl[i].vendor, vendor) && | ||
483 | !strcmp(bios_tbl[i].version, version)) { | 518 | !strcmp(bios_tbl[i].version, version)) { |
484 | bios_cfg = &bios_tbl[i]; | 519 | bios_cfg = &bios_tbl[i]; |
485 | break; | 520 | break; |
@@ -487,8 +522,8 @@ static int acerhdf_check_hardware(void) | |||
487 | } | 522 | } |
488 | 523 | ||
489 | if (!bios_cfg) { | 524 | if (!bios_cfg) { |
490 | pr_err("unknown (unsupported) BIOS version %s/%s, " | 525 | pr_err("unknown (unsupported) BIOS version %s/%s/%s, " |
491 | "please report, aborting!\n", vendor, version); | 526 | "please report, aborting!\n", vendor, product, version); |
492 | return -EINVAL; | 527 | return -EINVAL; |
493 | } | 528 | } |
494 | 529 | ||
@@ -509,7 +544,7 @@ static int acerhdf_register_platform(void) | |||
509 | { | 544 | { |
510 | int err = 0; | 545 | int err = 0; |
511 | 546 | ||
512 | err = platform_driver_register(&acerhdf_drv); | 547 | err = platform_driver_register(&acerhdf_driver); |
513 | if (err) | 548 | if (err) |
514 | return err; | 549 | return err; |
515 | 550 | ||
@@ -525,7 +560,7 @@ static void acerhdf_unregister_platform(void) | |||
525 | return; | 560 | return; |
526 | 561 | ||
527 | platform_device_del(acerhdf_dev); | 562 | platform_device_del(acerhdf_dev); |
528 | platform_driver_unregister(&acerhdf_drv); | 563 | platform_driver_unregister(&acerhdf_driver); |
529 | } | 564 | } |
530 | 565 | ||
531 | static int acerhdf_register_thermal(void) | 566 | static int acerhdf_register_thermal(void) |