1 /* 2 * acerhdf - A driver which monitors the temperature 3 * of the aspire one netbook, turns on/off the fan 4 * as soon as the upper/lower threshold is reached. 5 * 6 * (C) 2009 - Peter Feuerer peter (a) piie.net 7 * http://piie.net 8 * 2009 Borislav Petkov <petkovbb@gmail.com> 9 * 10 * Inspired by and many thanks to: 11 * o acerfand - Rachel Greenham 12 * o acer_ec.pl - Michael Kurz michi.kurz (at) googlemail.com 13 * - Petr Tomasek tomasek (#) etf,cuni,cz 14 * - Carlos Corbacho cathectic (at) gmail.com 15 * o lkml - Matthew Garrett 16 * - Borislav Petkov 17 * - Andreas Mohr 18 * 19 * This program is free software; you can redistribute it and/or modify 20 * it under the terms of the GNU General Public License as published by 21 * the Free Software Foundation; either version 2 of the License, or 22 * (at your option) any later version. 23 * 24 * This program is distributed in the hope that it will be useful, 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * GNU General Public License for more details. 28 * 29 * You should have received a copy of the GNU General Public License 30 * along with this program; if not, write to the Free Software 31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 32 */ 33 34 #define pr_fmt(fmt) "acerhdf: " fmt 35 36 #include <linux/kernel.h> 37 #include <linux/module.h> 38 #include <linux/fs.h> 39 #include <linux/dmi.h> 40 #include <acpi/acpi_drivers.h> 41 #include <linux/sched.h> 42 #include <linux/thermal.h> 43 #include <linux/platform_device.h> 44 45 /* 46 * The driver is started with "kernel mode off" by default. That means, the BIOS 47 * is still in control of the fan. In this mode the driver allows to read the 48 * temperature of the cpu and a userspace tool may take over control of the fan. 49 * If the driver is switched to "kernel mode" (e.g. via module parameter) the 50 * driver is in full control of the fan. If you want the module to be started in 51 * kernel mode by default, define the following: 52 */ 53 #undef START_IN_KERNEL_MODE 54 55 #define DRV_VER "0.5.22" 56 57 /* 58 * According to the Atom N270 datasheet, 59 * (http://download.intel.com/design/processor/datashts/320032.pdf) the 60 * CPU's optimal operating limits denoted in junction temperature as 61 * measured by the on-die thermal monitor are within 0 <= Tj <= 90. So, 62 * assume 89°C is critical temperature. 63 */ 64 #define ACERHDF_TEMP_CRIT 89000 65 #define ACERHDF_FAN_OFF 0 66 #define ACERHDF_FAN_AUTO 1 67 68 /* 69 * No matter what value the user puts into the fanon variable, turn on the fan 70 * at 80 degree Celsius to prevent hardware damage 71 */ 72 #define ACERHDF_MAX_FANON 80000 73 74 /* 75 * Maximum interval between two temperature checks is 15 seconds, as the die 76 * can get hot really fast under heavy load (plus we shouldn't forget about 77 * possible impact of _external_ aggressive sources such as heaters, sun etc.) 78 */ 79 #define ACERHDF_MAX_INTERVAL 15 80 81 #ifdef START_IN_KERNEL_MODE 82 static int kernelmode = 1; 83 #else 84 static int kernelmode; 85 #endif 86 87 static unsigned int interval = 10; 88 static unsigned int fanon = 63000; 89 static unsigned int fanoff = 58000; 90 static unsigned int verbose; 91 static unsigned int fanstate = ACERHDF_FAN_AUTO; 92 static char force_bios[16]; 93 static char force_product[16]; 94 static unsigned int prev_interval; 95 struct thermal_zone_device *thz_dev; 96 struct thermal_cooling_device *cl_dev; 97 struct platform_device *acerhdf_dev; 98 99 module_param(kernelmode, uint, 0); 100 MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off"); 101 module_param(interval, uint, 0600); 102 MODULE_PARM_DESC(interval, "Polling interval of temperature check"); 103 module_param(fanon, uint, 0600); 104 MODULE_PARM_DESC(fanon, "Turn the fan on above this temperature"); 105 module_param(fanoff, uint, 0600); 106 MODULE_PARM_DESC(fanoff, "Turn the fan off below this temperature"); 107 module_param(verbose, uint, 0600); 108 MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); 109 module_param_string(force_bios, force_bios, 16, 0); 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 116 * chk_off: to check if the fan is off 117 * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then 118 * the fan speed depending on the temperature 119 */ 120 struct fancmd { 121 u8 cmd_off; 122 u8 chk_off; 123 u8 cmd_auto; 124 }; 125 126 /* BIOS settings */ 127 struct bios_settings_t { 128 const char *vendor; 129 const char *product; 130 const char *version; 131 unsigned char fanreg; 132 unsigned char tempreg; 133 struct fancmd cmd; 134 }; 135 136 /* Register addresses and values for different BIOS versions */ 137 static const struct bios_settings_t bios_tbl[] = { 138 /* AOA110 */ 139 {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, 140 {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, 141 {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 142 {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 143 {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 144 {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 145 {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x21, 0x00} }, 146 {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x21, 0x00} }, 147 {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x21, 0x00} }, 148 /* AOA150 */ 149 {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x20, 0x00} }, 150 {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x20, 0x00} }, 151 {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x20, 0x00} }, 152 {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x20, 0x00} }, 153 {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x20, 0x00} }, 154 {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x20, 0x00} }, 155 {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x20, 0x00} }, 156 {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} }, 157 /* Acer 1410 */ 158 {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 159 {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 160 /* Acer 1810xx */ 161 {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 162 {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 163 {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 164 {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 165 /* Gateway */ 166 {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, 167 {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, 168 {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 169 {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 170 {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 171 /* Packard Bell */ 172 {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, 173 {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, 174 {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} }, 175 {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, 176 {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 177 {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 178 /* pewpew-terminator */ 179 {"", "", "", 0, 0, {0, 0, 0} } 180 }; 181 182 static const struct bios_settings_t *bios_cfg __read_mostly; 183 184 static int acerhdf_get_temp(int *temp) 185 { 186 u8 read_temp; 187 188 if (ec_read(bios_cfg->tempreg, &read_temp)) 189 return -EINVAL; 190 191 *temp = read_temp * 1000; 192 193 return 0; 194 } 195 196 static int acerhdf_get_fanstate(int *state) 197 { 198 u8 fan; 199 200 if (ec_read(bios_cfg->fanreg, &fan)) 201 return -EINVAL; 202 203 if (fan != bios_cfg->cmd.chk_off) 204 *state = ACERHDF_FAN_AUTO; 205 else 206 *state = ACERHDF_FAN_OFF; 207 208 return 0; 209 } 210 211 static void acerhdf_change_fanstate(int state) 212 { 213 unsigned char cmd; 214 215 if (verbose) 216 pr_notice("fan %s\n", (state == ACERHDF_FAN_OFF) ? 217 "OFF" : "ON"); 218 219 if ((state != ACERHDF_FAN_OFF) && (state != ACERHDF_FAN_AUTO)) { 220 pr_err("invalid fan state %d requested, setting to auto!\n", 221 state); 222 state = ACERHDF_FAN_AUTO; 223 } 224 225 cmd = (state == ACERHDF_FAN_OFF) ? bios_cfg->cmd.cmd_off 226 : bios_cfg->cmd.cmd_auto; 227 fanstate = state; 228 229 ec_write(bios_cfg->fanreg, cmd); 230 } 231 232 static void acerhdf_check_param(struct thermal_zone_device *thermal) 233 { 234 if (fanon > ACERHDF_MAX_FANON) { 235 pr_err("fanon temperature too high, set to %d\n", 236 ACERHDF_MAX_FANON); 237 fanon = ACERHDF_MAX_FANON; 238 } 239 240 if (kernelmode && prev_interval != interval) { 241 if (interval > ACERHDF_MAX_INTERVAL) { 242 pr_err("interval too high, set to %d\n", 243 ACERHDF_MAX_INTERVAL); 244 interval = ACERHDF_MAX_INTERVAL; 245 } 246 if (verbose) 247 pr_notice("interval changed to: %d\n", 248 interval); 249 thermal->polling_delay = interval*1000; 250 prev_interval = interval; 251 } 252 } 253 254 /* 255 * This is the thermal zone callback which does the delayed polling of the fan 256 * state. We do check /sysfs-originating settings here in acerhdf_check_param() 257 * as late as the polling interval is since we can't do that in the respective 258 * accessors of the module parameters. 259 */ 260 static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, 261 unsigned long *t) 262 { 263 int temp, err = 0; 264 265 acerhdf_check_param(thermal); 266 267 err = acerhdf_get_temp(&temp); 268 if (err) 269 return err; 270 271 if (verbose) 272 pr_notice("temp %d\n", temp); 273 274 *t = temp; 275 return 0; 276 } 277 278 static int acerhdf_bind(struct thermal_zone_device *thermal, 279 struct thermal_cooling_device *cdev) 280 { 281 /* if the cooling device is the one from acerhdf bind it */ 282 if (cdev != cl_dev) 283 return 0; 284 285 if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) { 286 pr_err("error binding cooling dev\n"); 287 return -EINVAL; 288 } 289 return 0; 290 } 291 292 static int acerhdf_unbind(struct thermal_zone_device *thermal, 293 struct thermal_cooling_device *cdev) 294 { 295 if (cdev != cl_dev) 296 return 0; 297 298 if (thermal_zone_unbind_cooling_device(thermal, 0, cdev)) { 299 pr_err("error unbinding cooling dev\n"); 300 return -EINVAL; 301 } 302 return 0; 303 } 304 305 static inline void acerhdf_revert_to_bios_mode(void) 306 { 307 acerhdf_change_fanstate(ACERHDF_FAN_AUTO); 308 kernelmode = 0; 309 if (thz_dev) 310 thz_dev->polling_delay = 0; 311 pr_notice("kernel mode fan control OFF\n"); 312 } 313 static inline void acerhdf_enable_kernelmode(void) 314 { 315 kernelmode = 1; 316 317 thz_dev->polling_delay = interval*1000; 318 thermal_zone_device_update(thz_dev); 319 pr_notice("kernel mode fan control ON\n"); 320 } 321 322 static int acerhdf_get_mode(struct thermal_zone_device *thermal, 323 enum thermal_device_mode *mode) 324 { 325 if (verbose) 326 pr_notice("kernel mode fan control %d\n", kernelmode); 327 328 *mode = (kernelmode) ? THERMAL_DEVICE_ENABLED 329 : THERMAL_DEVICE_DISABLED; 330 331 return 0; 332 } 333 334 /* 335 * set operation mode; 336 * enabled: the thermal layer of the kernel takes care about 337 * the temperature and the fan. 338 * disabled: the BIOS takes control of the fan. 339 */ 340 static int acerhdf_set_mode(struct thermal_zone_device *thermal, 341 enum thermal_device_mode mode) 342 { 343 if (mode == THERMAL_DEVICE_DISABLED && kernelmode) 344 acerhdf_revert_to_bios_mode(); 345 else if (mode == THERMAL_DEVICE_ENABLED && !kernelmode) 346 acerhdf_enable_kernelmode(); 347 348 return 0; 349 } 350 351 static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip, 352 enum thermal_trip_type *type) 353 { 354 if (trip == 0) 355 *type = THERMAL_TRIP_ACTIVE; 356 357 return 0; 358 } 359 360 static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip, 361 unsigned long *temp) 362 { 363 if (trip == 0) 364 *temp = fanon; 365 366 return 0; 367 } 368 369 static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal, 370 unsigned long *temperature) 371 { 372 *temperature = ACERHDF_TEMP_CRIT; 373 return 0; 374 } 375 376 /* bind callback functions to thermalzone */ 377 struct thermal_zone_device_ops acerhdf_dev_ops = { 378 .bind = acerhdf_bind, 379 .unbind = acerhdf_unbind, 380 .get_temp = acerhdf_get_ec_temp, 381 .get_mode = acerhdf_get_mode, 382 .set_mode = acerhdf_set_mode, 383 .get_trip_type = acerhdf_get_trip_type, 384 .get_trip_temp = acerhdf_get_trip_temp, 385 .get_crit_temp = acerhdf_get_crit_temp, 386 }; 387 388 389 /* 390 * cooling device callback functions 391 * get maximal fan cooling state 392 */ 393 static int acerhdf_get_max_state(struct thermal_cooling_device *cdev, 394 unsigned long *state) 395 { 396 *state = 1; 397 398 return 0; 399 } 400 401 static int acerhdf_get_cur_state(struct thermal_cooling_device *cdev, 402 unsigned long *state) 403 { 404 int err = 0, tmp; 405 406 err = acerhdf_get_fanstate(&tmp); 407 if (err) 408 return err; 409 410 *state = (tmp == ACERHDF_FAN_AUTO) ? 1 : 0; 411 return 0; 412 } 413 414 /* change current fan state - is overwritten when running in kernel mode */ 415 static int acerhdf_set_cur_state(struct thermal_cooling_device *cdev, 416 unsigned long state) 417 { 418 int cur_temp, cur_state, err = 0; 419 420 if (!kernelmode) 421 return 0; 422 423 err = acerhdf_get_temp(&cur_temp); 424 if (err) { 425 pr_err("error reading temperature, hand off control to BIOS\n"); 426 goto err_out; 427 } 428 429 err = acerhdf_get_fanstate(&cur_state); 430 if (err) { 431 pr_err("error reading fan state, hand off control to BIOS\n"); 432 goto err_out; 433 } 434 435 if (state == 0) { 436 /* turn fan off only if below fanoff temperature */ 437 if ((cur_state == ACERHDF_FAN_AUTO) && 438 (cur_temp < fanoff)) 439 acerhdf_change_fanstate(ACERHDF_FAN_OFF); 440 } else { 441 if (cur_state == ACERHDF_FAN_OFF) 442 acerhdf_change_fanstate(ACERHDF_FAN_AUTO); 443 } 444 return 0; 445 446 err_out: 447 acerhdf_revert_to_bios_mode(); 448 return -EINVAL; 449 } 450 451 /* bind fan callbacks to fan device */ 452 struct thermal_cooling_device_ops acerhdf_cooling_ops = { 453 .get_max_state = acerhdf_get_max_state, 454 .get_cur_state = acerhdf_get_cur_state, 455 .set_cur_state = acerhdf_set_cur_state, 456 }; 457 458 /* suspend / resume functionality */ 459 static int acerhdf_suspend(struct device *dev) 460 { 461 if (kernelmode) 462 acerhdf_change_fanstate(ACERHDF_FAN_AUTO); 463 464 if (verbose) 465 pr_notice("going suspend\n"); 466 467 return 0; 468 } 469 470 static int __devinit acerhdf_probe(struct platform_device *device) 471 { 472 return 0; 473 } 474 475 static int acerhdf_remove(struct platform_device *device) 476 { 477 return 0; 478 } 479 480 static const struct dev_pm_ops acerhdf_pm_ops = { 481 .suspend = acerhdf_suspend, 482 .freeze = acerhdf_suspend, 483 }; 484 485 static struct platform_driver acerhdf_driver = { 486 .driver = { 487 .name = "acerhdf", 488 .owner = THIS_MODULE, 489 .pm = &acerhdf_pm_ops, 490 }, 491 .probe = acerhdf_probe, 492 .remove = acerhdf_remove, 493 }; 494 495 /* checks if str begins with start */ 496 static int str_starts_with(const char *str, const char *start) 497 { 498 unsigned long str_len = 0, start_len = 0; 499 500 str_len = strlen(str); 501 start_len = strlen(start); 502 503 if (str_len >= start_len && 504 !strncmp(str, start, start_len)) 505 return 1; 506 507 return 0; 508 } 509 510 /* check hardware */ 511 static int acerhdf_check_hardware(void) 512 { 513 char const *vendor, *version, *product; 514 const struct bios_settings_t *bt = NULL; 515 516 /* get BIOS data */ 517 vendor = dmi_get_system_info(DMI_SYS_VENDOR); 518 version = dmi_get_system_info(DMI_BIOS_VERSION); 519 product = dmi_get_system_info(DMI_PRODUCT_NAME); 520 521 522 pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); 523 524 if (force_bios[0]) { 525 version = force_bios; 526 pr_info("forcing BIOS version: %s\n", version); 527 kernelmode = 0; 528 } 529 530 if (force_product[0]) { 531 product = force_product; 532 pr_info("forcing BIOS product: %s\n", product); 533 kernelmode = 0; 534 } 535 536 if (verbose) 537 pr_info("BIOS info: %s %s, product: %s\n", 538 vendor, version, product); 539 540 /* search BIOS version and vendor in BIOS settings table */ 541 for (bt = bios_tbl; bt->vendor[0]; bt++) { 542 /* 543 * check if actual hardware BIOS vendor, product and version 544 * IDs start with the strings of BIOS table entry 545 */ 546 if (str_starts_with(vendor, bt->vendor) && 547 str_starts_with(product, bt->product) && 548 str_starts_with(version, bt->version)) { 549 bios_cfg = bt; 550 break; 551 } 552 } 553 554 if (!bios_cfg) { 555 pr_err("unknown (unsupported) BIOS version %s/%s/%s, " 556 "please report, aborting!\n", vendor, product, version); 557 return -EINVAL; 558 } 559 560 /* 561 * if started with kernel mode off, prevent the kernel from switching 562 * off the fan 563 */ 564 if (!kernelmode) { 565 pr_notice("Fan control off, to enable do:\n"); 566 pr_notice("echo -n \"enabled\" > " 567 "/sys/class/thermal/thermal_zone0/mode\n"); 568 } 569 570 return 0; 571 } 572 573 static int acerhdf_register_platform(void) 574 { 575 int err = 0; 576 577 err = platform_driver_register(&acerhdf_driver); 578 if (err) 579 return err; 580 581 acerhdf_dev = platform_device_alloc("acerhdf", -1); 582 platform_device_add(acerhdf_dev); 583 584 return 0; 585 } 586 587 static void acerhdf_unregister_platform(void) 588 { 589 if (!acerhdf_dev) 590 return; 591 592 platform_device_del(acerhdf_dev); 593 platform_driver_unregister(&acerhdf_driver); 594 } 595 596 static int acerhdf_register_thermal(void) 597 { 598 cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL, 599 &acerhdf_cooling_ops); 600 601 if (IS_ERR(cl_dev)) 602 return -EINVAL; 603 604 thz_dev = thermal_zone_device_register("acerhdf", 1, NULL, 605 &acerhdf_dev_ops, 0, 0, 0, 606 (kernelmode) ? interval*1000 : 0); 607 if (IS_ERR(thz_dev)) 608 return -EINVAL; 609 610 return 0; 611 } 612 613 static void acerhdf_unregister_thermal(void) 614 { 615 if (cl_dev) { 616 thermal_cooling_device_unregister(cl_dev); 617 cl_dev = NULL; 618 } 619 620 if (thz_dev) { 621 thermal_zone_device_unregister(thz_dev); 622 thz_dev = NULL; 623 } 624 } 625 626 static int __init acerhdf_init(void) 627 { 628 int err = 0; 629 630 err = acerhdf_check_hardware(); 631 if (err) 632 goto out_err; 633 634 err = acerhdf_register_platform(); 635 if (err) 636 goto err_unreg; 637 638 err = acerhdf_register_thermal(); 639 if (err) 640 goto err_unreg; 641 642 return 0; 643 644 err_unreg: 645 acerhdf_unregister_thermal(); 646 acerhdf_unregister_platform(); 647 648 out_err: 649 return -ENODEV; 650 } 651 652 static void __exit acerhdf_exit(void) 653 { 654 acerhdf_change_fanstate(ACERHDF_FAN_AUTO); 655 acerhdf_unregister_thermal(); 656 acerhdf_unregister_platform(); 657 } 658 659 MODULE_LICENSE("GPL"); 660 MODULE_AUTHOR("Peter Feuerer"); 661 MODULE_DESCRIPTION("Aspire One temperature and fan driver"); 662 MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); 663 MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:"); 664 MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:"); 665 MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); 666 MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:"); 667 MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); 668 MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); 669 MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:"); 670 671 module_init(acerhdf_init); 672 module_exit(acerhdf_exit); 673