1 /* $NetBSD: vald_acpi.c,v 1.4 2010/04/15 07:02:24 jruoho Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Masanori Kanaoka. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright 2001 Bill Sommerfeld. 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed for the NetBSD Project by 47 * Wasabi Systems, Inc. 48 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 49 * or promote products derived from this software without specific prior 50 * written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 54 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 55 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 56 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 57 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 62 * POSSIBILITY OF SUCH DAMAGE. 63 */ 64 65 /* 66 * ACPI VALD Driver for Toshiba Libretto L3. 67 * This driver is based on acpibat driver. 68 */ 69 70 /* 71 * Obtain information of Toshiba "GHCI" Method from next URL. 72 * http://www.buzzard.org.uk/toshiba/docs.html 73 * http://memebeam.org/toys/ToshibaAcpiDriver 74 */ 75 76 #include <sys/cdefs.h> 77 __KERNEL_RCSID(0, "$NetBSD: vald_acpi.c,v 1.4 2010/04/15 07:02:24 jruoho Exp $"); 78 79 #include <sys/param.h> 80 #include <sys/systm.h> 81 #include <sys/device.h> 82 83 #include <dev/acpi/acpica.h> 84 #include <dev/acpi/acpireg.h> 85 #include <dev/acpi/acpivar.h> 86 87 #define _COMPONENT ACPI_RESOURCE_COMPONENT 88 ACPI_MODULE_NAME ("vald_acpi") 89 90 #define GHCI_WORDS 6 91 #define GHCI_FIFO_EMPTY 0x8c00 92 #define GHCI_NOT_SUPPORT 0x8000 93 94 #define GHCI_BACKLIGHT 0x0002 95 #define GHCI_ACADAPTOR 0x0003 96 #define GHCI_FAN 0x0004 97 #define GHCI_SYSTEM_EVENT_FIFO 0x0016 98 #define GHCI_DISPLAY_DEVICE 0x001C 99 #define GHCI_HOTKEY_EVENT 0x001E 100 101 #define GHCI_ON 0x0001 102 #define GHCI_OFF 0x0000 103 #define GHCI_ENABLE 0x0001 104 #define GHCI_DISABLE 0x0000 105 106 #define GHCI_CRT 0x0002 107 #define GHCI_LCD 0x0001 108 109 110 struct vald_acpi_softc { 111 device_t sc_dev; /* base device glue */ 112 struct acpi_devnode *sc_node; /* our ACPI devnode */ 113 int sc_flags; /* see below */ 114 115 ACPI_HANDLE lcd_handle; /* lcd handle */ 116 int *lcd_level; /* lcd brightness table */ 117 int lcd_num; /* size of lcd brightness table */ 118 int lcd_index; /* index of lcd brightness table */ 119 120 ACPI_INTEGER sc_ac_status; /* AC adaptor status when attach */ 121 }; 122 123 static const char * const vald_acpi_hids[] = { 124 "TOS6200", 125 NULL 126 }; 127 128 #define LIBRIGHT_HOLD 0x00 129 #define LIBRIGHT_UP 0x01 130 #define LIBRIGHT_DOWN 0x02 131 132 static int vald_acpi_match(device_t, cfdata_t, void *); 133 static void vald_acpi_attach(device_t, device_t, void *); 134 135 static void vald_acpi_event(void *); 136 static void vald_acpi_notify_handler(ACPI_HANDLE, uint32_t, void *); 137 138 #define ACPI_NOTIFY_ValdStatusChanged 0x80 139 140 141 static ACPI_STATUS vald_acpi_ghci_get(struct vald_acpi_softc *, uint32_t, 142 uint32_t *, uint32_t *); 143 static ACPI_STATUS vald_acpi_ghci_set(struct vald_acpi_softc *, uint32_t, 144 uint32_t, uint32_t *); 145 146 static ACPI_STATUS vald_acpi_libright_get_bus(ACPI_HANDLE, uint32_t, 147 void *, void **); 148 static void vald_acpi_libright_get(struct vald_acpi_softc *); 149 static void vald_acpi_libright_set(struct vald_acpi_softc *, int); 150 151 static void vald_acpi_video_switch(struct vald_acpi_softc *); 152 static void vald_acpi_fan_switch(struct vald_acpi_softc *); 153 154 static ACPI_STATUS vald_acpi_bcm_set(ACPI_HANDLE, uint32_t); 155 static ACPI_STATUS vald_acpi_dssx_set(uint32_t); 156 157 CFATTACH_DECL_NEW(vald_acpi, sizeof(struct vald_acpi_softc), 158 vald_acpi_match, vald_acpi_attach, NULL, NULL); 159 160 /* 161 * vald_acpi_match: 162 * 163 * Autoconfiguration `match' routine. 164 */ 165 static int 166 vald_acpi_match(device_t parent, cfdata_t match, void *aux) 167 { 168 struct acpi_attach_args *aa = aux; 169 170 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 171 return (0); 172 173 return (acpi_match_hid(aa->aa_node->ad_devinfo, vald_acpi_hids)); 174 } 175 176 /* 177 * vald_acpi_attach: 178 * 179 * Autoconfiguration `attach' routine. 180 */ 181 static void 182 vald_acpi_attach(device_t parent, device_t self, void *aux) 183 { 184 struct vald_acpi_softc *sc = device_private(self); 185 struct acpi_attach_args *aa = aux; 186 ACPI_STATUS rv; 187 uint32_t value, result; 188 189 aprint_naive(": Toshiba VALD\n"); 190 aprint_normal(": Toshiba VALD\n"); 191 192 sc->sc_node = aa->aa_node; 193 sc->sc_dev = self; 194 195 /* Get AC adaptor status via _PSR. */ 196 rv = acpi_eval_integer(ACPI_ROOT_OBJECT, "\\_SB_.ADP1._PSR", 197 &sc->sc_ac_status); 198 if (ACPI_FAILURE(rv)) 199 aprint_error_dev(self, "Unable to evaluate _PSR: %s\n", 200 AcpiFormatException(rv)); 201 else 202 aprint_verbose_dev(self, "AC adaptor %sconnected\n", 203 (sc->sc_ac_status == 0 ? "not ": "")); 204 205 /* Get LCD backlight status. */ 206 rv = vald_acpi_ghci_get(sc, GHCI_BACKLIGHT, &value, &result); 207 if (ACPI_SUCCESS(rv)) { 208 if (result != 0) 209 aprint_error_dev(self, "can't get backlight status error=%d\n", 210 result); 211 else 212 aprint_verbose_dev(self, "LCD backlight %s\n", 213 ((value == GHCI_ON) ? "on" : "off")); 214 } 215 216 /* Enable SystemEventFIFO,HotkeyEvent */ 217 rv = vald_acpi_ghci_set(sc, GHCI_SYSTEM_EVENT_FIFO, GHCI_ENABLE, 218 &result); 219 if (ACPI_SUCCESS(rv) && result != 0) 220 aprint_error_dev(self, "can't enable SystemEventFIFO error=%d\n", 221 result); 222 223 rv = vald_acpi_ghci_set(sc, GHCI_HOTKEY_EVENT, GHCI_ENABLE, &result); 224 if (ACPI_SUCCESS(rv) && result != 0) 225 aprint_error_dev(self, "can't enable HotkeyEvent error=%d\n", 226 result); 227 228 /* Check SystemFIFO events. */ 229 vald_acpi_event(sc); 230 231 /* Get LCD brightness level via _BCL. */ 232 vald_acpi_libright_get(sc); 233 234 /* Set LCD brightness level via _BCM. */ 235 vald_acpi_libright_set(sc, LIBRIGHT_HOLD); 236 237 /* enable vald notify */ 238 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "ENAB", NULL, NULL); 239 240 if (ACPI_SUCCESS(rv)) 241 (void)acpi_register_notify(sc->sc_node, 242 vald_acpi_notify_handler); 243 } 244 245 /* 246 * vald_acpi_notify_handler: 247 * 248 * Notify handler. 249 */ 250 static void 251 vald_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) 252 { 253 struct vald_acpi_softc *sc; 254 device_t self = context; 255 256 sc = device_private(self); 257 258 switch (notify) { 259 260 case ACPI_NOTIFY_ValdStatusChanged: 261 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, vald_acpi_event, sc); 262 break; 263 264 default: 265 aprint_error_dev(sc->sc_dev, 266 "unknown notify 0x%02X\n", notify); 267 break; 268 } 269 } 270 271 /* 272 * vald_acpi_event: 273 * 274 * Check hotkey event and do it, if event occur. 275 */ 276 static void 277 vald_acpi_event(void *arg) 278 { 279 struct vald_acpi_softc *sc = arg; 280 ACPI_STATUS rv; 281 uint32_t value, result; 282 283 while(1) { 284 rv = vald_acpi_ghci_get(sc, GHCI_SYSTEM_EVENT_FIFO, &value, 285 &result); 286 if (ACPI_SUCCESS(rv) && result == 0) { 287 288 switch (value) { 289 case 0x1c3: /* Fn + F9 */ 290 break; 291 case 0x1c2: /* Fn + F8 */ 292 vald_acpi_fan_switch(sc); 293 break; 294 case 0x1c1: /* Fn + F7 */ 295 vald_acpi_libright_set(sc, LIBRIGHT_UP); 296 break; 297 case 0x1c0: /* Fn + F6 */ 298 vald_acpi_libright_set(sc, LIBRIGHT_DOWN); 299 break; 300 case 0x1bf: /* Fn + F5 */ 301 vald_acpi_video_switch(sc); 302 break; 303 default: 304 break; 305 } 306 } 307 if (ACPI_FAILURE(rv) || result == GHCI_FIFO_EMPTY) 308 break; 309 } 310 } 311 312 /* 313 * vald_acpi_ghci_get: 314 * 315 * Get value via "GHCI" Method. 316 */ 317 static ACPI_STATUS 318 vald_acpi_ghci_get(struct vald_acpi_softc *sc, 319 uint32_t reg, uint32_t *value, uint32_t *result) 320 { 321 ACPI_STATUS rv; 322 ACPI_OBJECT Arg[GHCI_WORDS]; 323 ACPI_OBJECT_LIST ArgList; 324 ACPI_OBJECT *param, *PrtElement; 325 ACPI_BUFFER buf; 326 int i; 327 328 for (i = 0; i < GHCI_WORDS; i++) { 329 Arg[i].Type = ACPI_TYPE_INTEGER; 330 Arg[i].Integer.Value = 0; 331 } 332 333 Arg[0].Integer.Value = 0xfe00; 334 Arg[1].Integer.Value = reg; 335 Arg[2].Integer.Value = 0; 336 337 ArgList.Count = GHCI_WORDS; 338 ArgList.Pointer = Arg; 339 340 buf.Pointer = NULL; 341 buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 342 343 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, 344 "GHCI", &ArgList, &buf); 345 if (ACPI_FAILURE(rv)) { 346 aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n", 347 AcpiFormatException(rv)); 348 return (rv); 349 } 350 351 *result = GHCI_NOT_SUPPORT; 352 *value = 0; 353 param = buf.Pointer; 354 if (param->Type == ACPI_TYPE_PACKAGE) { 355 PrtElement = param->Package.Elements; 356 if (PrtElement->Type == ACPI_TYPE_INTEGER) 357 *result = PrtElement->Integer.Value; 358 PrtElement++; 359 PrtElement++; 360 if (PrtElement->Type == ACPI_TYPE_INTEGER) 361 *value = PrtElement->Integer.Value; 362 } 363 364 if (buf.Pointer) 365 ACPI_FREE(buf.Pointer); 366 return (rv); 367 } 368 369 /* 370 * vald_acpi_ghci_set: 371 * 372 * Set value via "GHCI" Method. 373 */ 374 static ACPI_STATUS 375 vald_acpi_ghci_set(struct vald_acpi_softc *sc, 376 uint32_t reg, uint32_t value, uint32_t *result) 377 { 378 ACPI_STATUS rv; 379 ACPI_OBJECT Arg[GHCI_WORDS]; 380 ACPI_OBJECT_LIST ArgList; 381 ACPI_OBJECT *param, *PrtElement; 382 ACPI_BUFFER buf; 383 int i; 384 385 386 for (i = 0; i < GHCI_WORDS; i++) { 387 Arg[i].Type = ACPI_TYPE_INTEGER; 388 Arg[i].Integer.Value = 0; 389 } 390 391 Arg[0].Integer.Value = 0xff00; 392 Arg[1].Integer.Value = reg; 393 Arg[2].Integer.Value = value; 394 395 ArgList.Count = GHCI_WORDS; 396 ArgList.Pointer = Arg; 397 398 buf.Pointer = NULL; 399 buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 400 401 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, 402 "GHCI", &ArgList, &buf); 403 if (ACPI_FAILURE(rv)) { 404 aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n", 405 AcpiFormatException(rv)); 406 return (rv); 407 } 408 409 *result = GHCI_NOT_SUPPORT; 410 param = buf.Pointer; 411 if (param->Type == ACPI_TYPE_PACKAGE) { 412 PrtElement = param->Package.Elements; 413 if (PrtElement->Type == ACPI_TYPE_INTEGER) 414 *result = PrtElement->Integer.Value; 415 } 416 417 if (buf.Pointer) 418 ACPI_FREE(buf.Pointer); 419 return (rv); 420 } 421 422 /* 423 * vald_acpi_libright_get_bus: 424 * 425 * Get LCD brightness level via "_BCL" Method, 426 * and save this handle. 427 */ 428 static ACPI_STATUS 429 vald_acpi_libright_get_bus(ACPI_HANDLE handle, uint32_t level, 430 void *context, void **status) 431 { 432 struct vald_acpi_softc *sc = context; 433 ACPI_STATUS rv; 434 ACPI_BUFFER buf; 435 ACPI_OBJECT *param, *PrtElement; 436 int i, *pi; 437 438 rv = acpi_eval_struct(handle, "_BCL", &buf); 439 if (ACPI_FAILURE(rv)) 440 return (AE_OK); 441 442 sc->lcd_handle = handle; 443 param = buf.Pointer; 444 if (param->Type == ACPI_TYPE_PACKAGE) { 445 printf("_BCL retrun: %d packages\n", param->Package.Count); 446 447 sc->lcd_num = param->Package.Count; 448 sc->lcd_level = ACPI_ALLOCATE(sizeof(int) * sc->lcd_num); 449 if (sc->lcd_level == NULL) { 450 if (buf.Pointer) 451 ACPI_FREE(buf.Pointer); 452 return (AE_NO_MEMORY); 453 } 454 455 PrtElement = param->Package.Elements; 456 pi = sc->lcd_level; 457 for (i = 0; i < param->Package.Count; i++) { 458 if (PrtElement->Type == ACPI_TYPE_INTEGER) { 459 *pi = (unsigned)PrtElement->Integer.Value; 460 PrtElement++; 461 pi++; 462 } 463 } 464 if (sc->sc_ac_status == 1) /* AC adaptor on when attach */ 465 sc->lcd_index = sc->lcd_num -1; /* MAX Brightness */ 466 else 467 sc->lcd_index = 3; 468 469 #ifdef ACPI_DEBUG 470 pi = sc->lcd_level; 471 printf("\t Full Power Level: %d\n", *pi); 472 printf("\t on Battery Level: %d\n", *(pi+1)); 473 printf("\t Possible Level: "); 474 for (i = 2;i < sc->lcd_num; i++) 475 printf(" %d", *(pi+i)); 476 printf("\n"); 477 #endif 478 } 479 480 if (buf.Pointer) 481 ACPI_FREE(buf.Pointer); 482 return (AE_OK); 483 } 484 485 /* 486 * vald_acpi_libright_get: 487 * 488 * Search node that have "_BCL" Method. 489 */ 490 static void 491 vald_acpi_libright_get(struct vald_acpi_softc *sc) 492 { 493 ACPI_HANDLE parent; 494 ACPI_STATUS rv; 495 496 aprint_verbose_dev(sc->sc_dev, "get LCD brightness via _BCL\n"); 497 498 #ifdef ACPI_DEBUG 499 printf("acpi_libright_get: start\n"); 500 #endif 501 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent); 502 if (ACPI_FAILURE(rv)) 503 return; 504 505 AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100, 506 vald_acpi_libright_get_bus, NULL, sc, NULL); 507 } 508 509 /* 510 * vald_acpi_libright_set: 511 * 512 * Figure up next status and set it. 513 */ 514 static void 515 vald_acpi_libright_set(struct vald_acpi_softc *sc, int UpDown) 516 { 517 uint32_t backlight, backlight_new, result, bright; 518 ACPI_STATUS rv; 519 int *pi; 520 521 /* Skip,if it does not support _BCL. */ 522 if (sc->lcd_handle == NULL) 523 return; 524 525 /* Get LCD backlight status. */ 526 rv = vald_acpi_ghci_get(sc, GHCI_BACKLIGHT, &backlight, &result); 527 if (ACPI_FAILURE(rv) || result != 0) 528 return; 529 530 /* Figure up next status. */ 531 backlight_new = backlight; 532 if (UpDown == LIBRIGHT_UP) { 533 if (backlight == 1) 534 sc->lcd_index++; 535 else { 536 /* backlight on */ 537 backlight_new = 1; 538 sc->lcd_index = 2; 539 } 540 } else if (UpDown == LIBRIGHT_DOWN) { 541 if ((backlight == 1) && (sc->lcd_index > 2)) 542 sc->lcd_index--; 543 else { 544 /* backlight off */ 545 backlight_new = 0; 546 sc->lcd_index = 2; 547 } 548 } 549 550 /* Check index value. */ 551 if (sc->lcd_index < 2) 552 sc->lcd_index = 2; /* index Minium Value */ 553 if (sc->lcd_index >= sc->lcd_num) 554 sc->lcd_index = sc->lcd_num - 1; 555 556 /* Set LCD backlight,if status is changed. */ 557 if (backlight_new != backlight) { 558 rv = vald_acpi_ghci_set(sc, GHCI_BACKLIGHT, backlight_new, 559 &result); 560 if (ACPI_SUCCESS(rv) && result != 0) 561 aprint_error_dev(sc->sc_dev, "can't set LCD backlight %s error=%x\n", 562 ((backlight_new == 1) ? "on" : "off"), result); 563 } 564 565 if (backlight_new == 1) { 566 567 pi = sc->lcd_level; 568 bright = *(pi + sc->lcd_index); 569 570 rv = vald_acpi_bcm_set(sc->lcd_handle, bright); 571 if (ACPI_FAILURE(rv)) 572 aprint_error_dev(sc->sc_dev, "unable to evaluate _BCM: %s\n", 573 AcpiFormatException(rv)); 574 } else { 575 bright = 0; 576 } 577 #ifdef ACPI_DEBUG 578 printf("LCD bright"); 579 printf(" %s", ((UpDown == LIBRIGHT_UP) ? "up":"")); 580 printf("%s\n", ((UpDown == LIBRIGHT_DOWN) ? "down":"")); 581 printf("\t acpi_libright_set: Set brightness to %d%%\n", bright); 582 #endif 583 } 584 585 /* 586 * vald_acpi_video_switch: 587 * 588 * Get video status(LCD/CRT) and set new video status. 589 */ 590 static void 591 vald_acpi_video_switch(struct vald_acpi_softc *sc) 592 { 593 ACPI_STATUS rv; 594 uint32_t value, result; 595 596 /* Get video status. */ 597 rv = vald_acpi_ghci_get(sc, GHCI_DISPLAY_DEVICE, &value, &result); 598 if (ACPI_FAILURE(rv)) 599 return; 600 if (result != 0) { 601 aprint_error_dev(sc->sc_dev, "can't get video status error=%x\n", 602 result); 603 return; 604 } 605 606 #ifdef ACPI_DEBUG 607 printf("Toggle LCD/CRT\n"); 608 printf("\t Before switch, video status: %s", 609 (((value & GHCI_LCD) == GHCI_LCD) ? "LCD" : "")); 610 printf("%s\n", (((value & GHCI_CRT) == GHCI_CRT) ? "CRT": "")); 611 #endif 612 613 /* Toggle LCD/CRT */ 614 if (value & GHCI_LCD) { 615 value &= ~GHCI_LCD; 616 value |= GHCI_CRT; 617 } else if (value & GHCI_CRT){ 618 value &= ~GHCI_CRT; 619 value |= GHCI_LCD; 620 } 621 622 rv = vald_acpi_dssx_set(value); 623 if (ACPI_FAILURE(rv)) 624 aprint_error_dev(sc->sc_dev, "unable to evaluate DSSX: %s\n", 625 AcpiFormatException(rv)); 626 627 } 628 629 /* 630 * vald_acpi_bcm_set: 631 * 632 * Set LCD brightness via "_BCM" Method. 633 */ 634 static ACPI_STATUS 635 vald_acpi_bcm_set(ACPI_HANDLE handle, uint32_t bright) 636 { 637 ACPI_STATUS rv; 638 ACPI_OBJECT Arg; 639 ACPI_OBJECT_LIST ArgList; 640 641 ArgList.Count = 1; 642 ArgList.Pointer = &Arg; 643 644 Arg.Type = ACPI_TYPE_INTEGER; 645 Arg.Integer.Value = bright; 646 647 rv = AcpiEvaluateObject(handle, "_BCM", &ArgList, NULL); 648 return (rv); 649 } 650 651 /* 652 * vald_acpi_dssx_set: 653 * 654 * Set value via "\\_SB_.VALX.DSSX" Method. 655 */ 656 static ACPI_STATUS 657 vald_acpi_dssx_set(uint32_t value) 658 { 659 return acpi_eval_set_integer(NULL, "\\_SB_.VALX.DSSX", value); 660 } 661 662 /* 663 * vald_acpi_fan_switch: 664 * 665 * Get FAN status and set new FAN status. 666 */ 667 static void 668 vald_acpi_fan_switch(struct vald_acpi_softc *sc) 669 { 670 ACPI_STATUS rv; 671 uint32_t value, result; 672 673 /* Get FAN status */ 674 rv = vald_acpi_ghci_get(sc, GHCI_FAN, &value, &result); 675 if (ACPI_FAILURE(rv)) 676 return; 677 if (result != 0) { 678 aprint_error_dev(sc->sc_dev, "can't get FAN status error=%d\n", 679 result); 680 return; 681 } 682 683 #ifdef ACPI_DEBUG 684 printf("Toggle FAN on/off\n"); 685 printf("\t Before toggle, FAN status %s\n", 686 (value == GHCI_OFF ? "off" : "on")); 687 #endif 688 689 /* Toggle FAN on/off */ 690 if (value == GHCI_OFF) 691 value = GHCI_ON; 692 else 693 value = GHCI_OFF; 694 695 /* Set FAN new status. */ 696 rv = vald_acpi_ghci_set(sc, GHCI_FAN, value, &result); 697 if (ACPI_FAILURE(rv)) 698 return; 699 if (result != 0) { 700 aprint_error_dev(sc->sc_dev, "can't set FAN status error=%d\n", 701 result); 702 return; 703 } 704 705 #ifdef ACPI_DEBUG 706 printf("\t After toggle, FAN status %s\n", 707 (value == GHCI_OFF ? "off" : "on")); 708 #endif 709 } 710