1 /* 2 * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $) 3 * 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 6 * 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * 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. 13 * 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. 18 * 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20 */ 21 22 #include <linux/kernel.h> 23 #include <linux/module.h> 24 #include <linux/slab.h> 25 #include <linux/init.h> 26 #include <linux/types.h> 27 #include <linux/hardirq.h> 28 #include <linux/acpi.h> 29 #include <linux/dynamic_debug.h> 30 31 #include "internal.h" 32 #include "sleep.h" 33 34 #define _COMPONENT ACPI_BUS_COMPONENT 35 ACPI_MODULE_NAME("utils"); 36 37 /* -------------------------------------------------------------------------- 38 Object Evaluation Helpers 39 -------------------------------------------------------------------------- */ 40 static void 41 acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s) 42 { 43 #ifdef ACPI_DEBUG_OUTPUT 44 char prefix[80] = {'\0'}; 45 struct acpi_buffer buffer = {sizeof(prefix), prefix}; 46 acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer); 47 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n", 48 (char *) prefix, p, acpi_format_exception(s))); 49 #else 50 return; 51 #endif 52 } 53 54 acpi_status 55 acpi_extract_package(union acpi_object *package, 56 struct acpi_buffer *format, struct acpi_buffer *buffer) 57 { 58 u32 size_required = 0; 59 u32 tail_offset = 0; 60 char *format_string = NULL; 61 u32 format_count = 0; 62 u32 i = 0; 63 u8 *head = NULL; 64 u8 *tail = NULL; 65 66 67 if (!package || (package->type != ACPI_TYPE_PACKAGE) 68 || (package->package.count < 1)) { 69 printk(KERN_WARNING PREFIX "Invalid package argument\n"); 70 return AE_BAD_PARAMETER; 71 } 72 73 if (!format || !format->pointer || (format->length < 1)) { 74 printk(KERN_WARNING PREFIX "Invalid format argument\n"); 75 return AE_BAD_PARAMETER; 76 } 77 78 if (!buffer) { 79 printk(KERN_WARNING PREFIX "Invalid buffer argument\n"); 80 return AE_BAD_PARAMETER; 81 } 82 83 format_count = (format->length / sizeof(char)) - 1; 84 if (format_count > package->package.count) { 85 printk(KERN_WARNING PREFIX "Format specifies more objects [%d]" 86 " than exist in package [%d].\n", 87 format_count, package->package.count); 88 return AE_BAD_DATA; 89 } 90 91 format_string = format->pointer; 92 93 /* 94 * Calculate size_required. 95 */ 96 for (i = 0; i < format_count; i++) { 97 98 union acpi_object *element = &(package->package.elements[i]); 99 100 switch (element->type) { 101 102 case ACPI_TYPE_INTEGER: 103 switch (format_string[i]) { 104 case 'N': 105 size_required += sizeof(u64); 106 tail_offset += sizeof(u64); 107 break; 108 case 'S': 109 size_required += 110 sizeof(char *) + sizeof(u64) + 111 sizeof(char); 112 tail_offset += sizeof(char *); 113 break; 114 default: 115 printk(KERN_WARNING PREFIX "Invalid package element" 116 " [%d]: got number, expecting" 117 " [%c]\n", 118 i, format_string[i]); 119 return AE_BAD_DATA; 120 break; 121 } 122 break; 123 124 case ACPI_TYPE_STRING: 125 case ACPI_TYPE_BUFFER: 126 switch (format_string[i]) { 127 case 'S': 128 size_required += 129 sizeof(char *) + 130 (element->string.length * sizeof(char)) + 131 sizeof(char); 132 tail_offset += sizeof(char *); 133 break; 134 case 'B': 135 size_required += 136 sizeof(u8 *) + element->buffer.length; 137 tail_offset += sizeof(u8 *); 138 break; 139 default: 140 printk(KERN_WARNING PREFIX "Invalid package element" 141 " [%d] got string/buffer," 142 " expecting [%c]\n", 143 i, format_string[i]); 144 return AE_BAD_DATA; 145 break; 146 } 147 break; 148 case ACPI_TYPE_LOCAL_REFERENCE: 149 switch (format_string[i]) { 150 case 'R': 151 size_required += sizeof(void *); 152 tail_offset += sizeof(void *); 153 break; 154 default: 155 printk(KERN_WARNING PREFIX "Invalid package element" 156 " [%d] got reference," 157 " expecting [%c]\n", 158 i, format_string[i]); 159 return AE_BAD_DATA; 160 break; 161 } 162 break; 163 164 case ACPI_TYPE_PACKAGE: 165 default: 166 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 167 "Found unsupported element at index=%d\n", 168 i)); 169 /* TBD: handle nested packages... */ 170 return AE_SUPPORT; 171 break; 172 } 173 } 174 175 /* 176 * Validate output buffer. 177 */ 178 if (buffer->length == ACPI_ALLOCATE_BUFFER) { 179 buffer->pointer = ACPI_ALLOCATE_ZEROED(size_required); 180 if (!buffer->pointer) 181 return AE_NO_MEMORY; 182 buffer->length = size_required; 183 } else { 184 if (buffer->length < size_required) { 185 buffer->length = size_required; 186 return AE_BUFFER_OVERFLOW; 187 } else if (buffer->length != size_required || 188 !buffer->pointer) { 189 return AE_BAD_PARAMETER; 190 } 191 } 192 193 head = buffer->pointer; 194 tail = buffer->pointer + tail_offset; 195 196 /* 197 * Extract package data. 198 */ 199 for (i = 0; i < format_count; i++) { 200 201 u8 **pointer = NULL; 202 union acpi_object *element = &(package->package.elements[i]); 203 204 switch (element->type) { 205 206 case ACPI_TYPE_INTEGER: 207 switch (format_string[i]) { 208 case 'N': 209 *((u64 *) head) = 210 element->integer.value; 211 head += sizeof(u64); 212 break; 213 case 'S': 214 pointer = (u8 **) head; 215 *pointer = tail; 216 *((u64 *) tail) = 217 element->integer.value; 218 head += sizeof(u64 *); 219 tail += sizeof(u64); 220 /* NULL terminate string */ 221 *tail = (char)0; 222 tail += sizeof(char); 223 break; 224 default: 225 /* Should never get here */ 226 break; 227 } 228 break; 229 230 case ACPI_TYPE_STRING: 231 case ACPI_TYPE_BUFFER: 232 switch (format_string[i]) { 233 case 'S': 234 pointer = (u8 **) head; 235 *pointer = tail; 236 memcpy(tail, element->string.pointer, 237 element->string.length); 238 head += sizeof(char *); 239 tail += element->string.length * sizeof(char); 240 /* NULL terminate string */ 241 *tail = (char)0; 242 tail += sizeof(char); 243 break; 244 case 'B': 245 pointer = (u8 **) head; 246 *pointer = tail; 247 memcpy(tail, element->buffer.pointer, 248 element->buffer.length); 249 head += sizeof(u8 *); 250 tail += element->buffer.length; 251 break; 252 default: 253 /* Should never get here */ 254 break; 255 } 256 break; 257 case ACPI_TYPE_LOCAL_REFERENCE: 258 switch (format_string[i]) { 259 case 'R': 260 *(void **)head = 261 (void *)element->reference.handle; 262 head += sizeof(void *); 263 break; 264 default: 265 /* Should never get here */ 266 break; 267 } 268 break; 269 case ACPI_TYPE_PACKAGE: 270 /* TBD: handle nested packages... */ 271 default: 272 /* Should never get here */ 273 break; 274 } 275 } 276 277 return AE_OK; 278 } 279 280 EXPORT_SYMBOL(acpi_extract_package); 281 282 acpi_status 283 acpi_evaluate_integer(acpi_handle handle, 284 acpi_string pathname, 285 struct acpi_object_list *arguments, unsigned long long *data) 286 { 287 acpi_status status = AE_OK; 288 union acpi_object element; 289 struct acpi_buffer buffer = { 0, NULL }; 290 291 if (!data) 292 return AE_BAD_PARAMETER; 293 294 buffer.length = sizeof(union acpi_object); 295 buffer.pointer = &element; 296 status = acpi_evaluate_object(handle, pathname, arguments, &buffer); 297 if (ACPI_FAILURE(status)) { 298 acpi_util_eval_error(handle, pathname, status); 299 return status; 300 } 301 302 if (element.type != ACPI_TYPE_INTEGER) { 303 acpi_util_eval_error(handle, pathname, AE_BAD_DATA); 304 return AE_BAD_DATA; 305 } 306 307 *data = element.integer.value; 308 309 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); 310 311 return AE_OK; 312 } 313 314 EXPORT_SYMBOL(acpi_evaluate_integer); 315 316 acpi_status 317 acpi_evaluate_reference(acpi_handle handle, 318 acpi_string pathname, 319 struct acpi_object_list *arguments, 320 struct acpi_handle_list *list) 321 { 322 acpi_status status = AE_OK; 323 union acpi_object *package = NULL; 324 union acpi_object *element = NULL; 325 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 326 u32 i = 0; 327 328 329 if (!list) { 330 return AE_BAD_PARAMETER; 331 } 332 333 /* Evaluate object. */ 334 335 status = acpi_evaluate_object(handle, pathname, arguments, &buffer); 336 if (ACPI_FAILURE(status)) 337 goto end; 338 339 package = buffer.pointer; 340 341 if ((buffer.length == 0) || !package) { 342 status = AE_BAD_DATA; 343 acpi_util_eval_error(handle, pathname, status); 344 goto end; 345 } 346 if (package->type != ACPI_TYPE_PACKAGE) { 347 status = AE_BAD_DATA; 348 acpi_util_eval_error(handle, pathname, status); 349 goto end; 350 } 351 if (!package->package.count) { 352 status = AE_BAD_DATA; 353 acpi_util_eval_error(handle, pathname, status); 354 goto end; 355 } 356 357 if (package->package.count > ACPI_MAX_HANDLES) { 358 return AE_NO_MEMORY; 359 } 360 list->count = package->package.count; 361 362 /* Extract package data. */ 363 364 for (i = 0; i < list->count; i++) { 365 366 element = &(package->package.elements[i]); 367 368 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { 369 status = AE_BAD_DATA; 370 acpi_util_eval_error(handle, pathname, status); 371 break; 372 } 373 374 if (!element->reference.handle) { 375 status = AE_NULL_ENTRY; 376 acpi_util_eval_error(handle, pathname, status); 377 break; 378 } 379 /* Get the acpi_handle. */ 380 381 list->handles[i] = element->reference.handle; 382 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n", 383 list->handles[i])); 384 } 385 386 end: 387 if (ACPI_FAILURE(status)) { 388 list->count = 0; 389 //kfree(list->handles); 390 } 391 392 kfree(buffer.pointer); 393 394 return status; 395 } 396 397 EXPORT_SYMBOL(acpi_evaluate_reference); 398 399 acpi_status 400 acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld) 401 { 402 acpi_status status; 403 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 404 union acpi_object *output; 405 406 status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer); 407 408 if (ACPI_FAILURE(status)) 409 return status; 410 411 output = buffer.pointer; 412 413 if (!output || output->type != ACPI_TYPE_PACKAGE 414 || !output->package.count 415 || output->package.elements[0].type != ACPI_TYPE_BUFFER 416 || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) { 417 status = AE_TYPE; 418 goto out; 419 } 420 421 status = acpi_decode_pld_buffer( 422 output->package.elements[0].buffer.pointer, 423 output->package.elements[0].buffer.length, 424 pld); 425 426 out: 427 kfree(buffer.pointer); 428 return status; 429 } 430 EXPORT_SYMBOL(acpi_get_physical_device_location); 431 432 /** 433 * acpi_evaluate_ost: Evaluate _OST for hotplug operations 434 * @handle: ACPI device handle 435 * @source_event: source event code 436 * @status_code: status code 437 * @status_buf: optional detailed information (NULL if none) 438 * 439 * Evaluate _OST for hotplug operations. All ACPI hotplug handlers 440 * must call this function when evaluating _OST for hotplug operations. 441 * When the platform does not support _OST, this function has no effect. 442 */ 443 acpi_status 444 acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code, 445 struct acpi_buffer *status_buf) 446 { 447 union acpi_object params[3] = { 448 {.type = ACPI_TYPE_INTEGER,}, 449 {.type = ACPI_TYPE_INTEGER,}, 450 {.type = ACPI_TYPE_BUFFER,} 451 }; 452 struct acpi_object_list arg_list = {3, params}; 453 454 params[0].integer.value = source_event; 455 params[1].integer.value = status_code; 456 if (status_buf != NULL) { 457 params[2].buffer.pointer = status_buf->pointer; 458 params[2].buffer.length = status_buf->length; 459 } else { 460 params[2].buffer.pointer = NULL; 461 params[2].buffer.length = 0; 462 } 463 464 return acpi_evaluate_object(handle, "_OST", &arg_list, NULL); 465 } 466 EXPORT_SYMBOL(acpi_evaluate_ost); 467 468 /** 469 * acpi_handle_path: Return the object path of handle 470 * 471 * Caller must free the returned buffer 472 */ 473 static char *acpi_handle_path(acpi_handle handle) 474 { 475 struct acpi_buffer buffer = { 476 .length = ACPI_ALLOCATE_BUFFER, 477 .pointer = NULL 478 }; 479 480 if (in_interrupt() || 481 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK) 482 return NULL; 483 return buffer.pointer; 484 } 485 486 /** 487 * acpi_handle_printk: Print message with ACPI prefix and object path 488 * 489 * This function is called through acpi_handle_<level> macros and prints 490 * a message with ACPI prefix and object path. This function acquires 491 * the global namespace mutex to obtain an object path. In interrupt 492 * context, it shows the object path as <n/a>. 493 */ 494 void 495 acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...) 496 { 497 struct va_format vaf; 498 va_list args; 499 const char *path; 500 501 va_start(args, fmt); 502 vaf.fmt = fmt; 503 vaf.va = &args; 504 505 path = acpi_handle_path(handle); 506 printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf); 507 508 va_end(args); 509 kfree(path); 510 } 511 EXPORT_SYMBOL(acpi_handle_printk); 512 513 #if defined(CONFIG_DYNAMIC_DEBUG) 514 /** 515 * __acpi_handle_debug: pr_debug with ACPI prefix and object path 516 * 517 * This function is called through acpi_handle_debug macro and debug 518 * prints a message with ACPI prefix and object path. This function 519 * acquires the global namespace mutex to obtain an object path. In 520 * interrupt context, it shows the object path as <n/a>. 521 */ 522 void 523 __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, 524 const char *fmt, ...) 525 { 526 struct va_format vaf; 527 va_list args; 528 const char *path; 529 530 va_start(args, fmt); 531 vaf.fmt = fmt; 532 vaf.va = &args; 533 534 path = acpi_handle_path(handle); 535 __dynamic_pr_debug(descriptor, "ACPI: %s: %pV", path ? path : "<n/a>", &vaf); 536 537 va_end(args); 538 kfree(path); 539 } 540 EXPORT_SYMBOL(__acpi_handle_debug); 541 #endif 542 543 /** 544 * acpi_has_method: Check whether @handle has a method named @name 545 * @handle: ACPI device handle 546 * @name: name of object or method 547 * 548 * Check whether @handle has a method named @name. 549 */ 550 bool acpi_has_method(acpi_handle handle, char *name) 551 { 552 acpi_handle tmp; 553 554 return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp)); 555 } 556 EXPORT_SYMBOL(acpi_has_method); 557 558 acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, 559 u64 arg) 560 { 561 union acpi_object obj = { .type = ACPI_TYPE_INTEGER }; 562 struct acpi_object_list arg_list = { .count = 1, .pointer = &obj, }; 563 564 obj.integer.value = arg; 565 566 return acpi_evaluate_object(handle, method, &arg_list, NULL); 567 } 568 EXPORT_SYMBOL(acpi_execute_simple_method); 569 570 /** 571 * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations 572 * @handle: ACPI device handle 573 * 574 * Evaluate device's _EJ0 method for hotplug operations. 575 */ 576 acpi_status acpi_evaluate_ej0(acpi_handle handle) 577 { 578 acpi_status status; 579 580 status = acpi_execute_simple_method(handle, "_EJ0", 1); 581 if (status == AE_NOT_FOUND) 582 acpi_handle_warn(handle, "No _EJ0 support for device\n"); 583 else if (ACPI_FAILURE(status)) 584 acpi_handle_warn(handle, "Eject failed (0x%x)\n", status); 585 586 return status; 587 } 588 589 /** 590 * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device 591 * @handle: ACPI device handle 592 * @lock: lock device if non-zero, otherwise unlock device 593 * 594 * Evaluate device's _LCK method if present to lock/unlock device 595 */ 596 acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) 597 { 598 acpi_status status; 599 600 status = acpi_execute_simple_method(handle, "_LCK", !!lock); 601 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 602 if (lock) 603 acpi_handle_warn(handle, 604 "Locking device failed (0x%x)\n", status); 605 else 606 acpi_handle_warn(handle, 607 "Unlocking device failed (0x%x)\n", status); 608 } 609 610 return status; 611 } 612 613 /** 614 * acpi_evaluate_dsm - evaluate device's _DSM method 615 * @handle: ACPI device handle 616 * @uuid: UUID of requested functions, should be 16 bytes 617 * @rev: revision number of requested function 618 * @func: requested function number 619 * @argv4: the function specific parameter 620 * 621 * Evaluate device's _DSM method with specified UUID, revision id and 622 * function number. Caller needs to free the returned object. 623 * 624 * Though ACPI defines the fourth parameter for _DSM should be a package, 625 * some old BIOSes do expect a buffer or an integer etc. 626 */ 627 union acpi_object * 628 acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 func, 629 union acpi_object *argv4) 630 { 631 acpi_status ret; 632 struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; 633 union acpi_object params[4]; 634 struct acpi_object_list input = { 635 .count = 4, 636 .pointer = params, 637 }; 638 639 params[0].type = ACPI_TYPE_BUFFER; 640 params[0].buffer.length = 16; 641 params[0].buffer.pointer = (char *)uuid; 642 params[1].type = ACPI_TYPE_INTEGER; 643 params[1].integer.value = rev; 644 params[2].type = ACPI_TYPE_INTEGER; 645 params[2].integer.value = func; 646 if (argv4) { 647 params[3] = *argv4; 648 } else { 649 params[3].type = ACPI_TYPE_PACKAGE; 650 params[3].package.count = 0; 651 params[3].package.elements = NULL; 652 } 653 654 ret = acpi_evaluate_object(handle, "_DSM", &input, &buf); 655 if (ACPI_SUCCESS(ret)) 656 return (union acpi_object *)buf.pointer; 657 658 if (ret != AE_NOT_FOUND) 659 acpi_handle_warn(handle, 660 "failed to evaluate _DSM (0x%x)\n", ret); 661 662 return NULL; 663 } 664 EXPORT_SYMBOL(acpi_evaluate_dsm); 665 666 /** 667 * acpi_check_dsm - check if _DSM method supports requested functions. 668 * @handle: ACPI device handle 669 * @uuid: UUID of requested functions, should be 16 bytes at least 670 * @rev: revision number of requested functions 671 * @funcs: bitmap of requested functions 672 * 673 * Evaluate device's _DSM method to check whether it supports requested 674 * functions. Currently only support 64 functions at maximum, should be 675 * enough for now. 676 */ 677 bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs) 678 { 679 int i; 680 u64 mask = 0; 681 union acpi_object *obj; 682 683 if (funcs == 0) 684 return false; 685 686 obj = acpi_evaluate_dsm(handle, uuid, rev, 0, NULL); 687 if (!obj) 688 return false; 689 690 /* For compatibility, old BIOSes may return an integer */ 691 if (obj->type == ACPI_TYPE_INTEGER) 692 mask = obj->integer.value; 693 else if (obj->type == ACPI_TYPE_BUFFER) 694 for (i = 0; i < obj->buffer.length && i < 8; i++) 695 mask |= (((u64)obj->buffer.pointer[i]) << (i * 8)); 696 ACPI_FREE(obj); 697 698 /* 699 * Bit 0 indicates whether there's support for any functions other than 700 * function 0 for the specified UUID and revision. 701 */ 702 if ((mask & 0x1) && (mask & funcs) == funcs) 703 return true; 704 705 return false; 706 } 707 EXPORT_SYMBOL(acpi_check_dsm); 708 709 /** 710 * acpi_dev_found - Detect presence of a given ACPI device in the namespace. 711 * @hid: Hardware ID of the device. 712 * 713 * Return %true if the device was present at the moment of invocation. 714 * Note that if the device is pluggable, it may since have disappeared. 715 * 716 * For this function to work, acpi_bus_scan() must have been executed 717 * which happens in the subsys_initcall() subsection. Hence, do not 718 * call from a subsys_initcall() or earlier (use acpi_get_devices() 719 * instead). Calling from module_init() is fine (which is synonymous 720 * with device_initcall()). 721 */ 722 bool acpi_dev_found(const char *hid) 723 { 724 struct acpi_device_bus_id *acpi_device_bus_id; 725 bool found = false; 726 727 mutex_lock(&acpi_device_lock); 728 list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) 729 if (!strcmp(acpi_device_bus_id->bus_id, hid)) { 730 found = true; 731 break; 732 } 733 mutex_unlock(&acpi_device_lock); 734 735 return found; 736 } 737 EXPORT_SYMBOL(acpi_dev_found); 738 739 /* 740 * acpi_backlight= handling, this is done here rather then in video_detect.c 741 * because __setup cannot be used in modules. 742 */ 743 char acpi_video_backlight_string[16]; 744 EXPORT_SYMBOL(acpi_video_backlight_string); 745 746 static int __init acpi_backlight(char *str) 747 { 748 strlcpy(acpi_video_backlight_string, str, 749 sizeof(acpi_video_backlight_string)); 750 return 1; 751 } 752 __setup("acpi_backlight=", acpi_backlight); 753