1 /* $NetBSD: vald_acpi.c,v 1.8 2021/12/07 21:37:36 andvar 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.8 2021/12/07 21:37:36 andvar 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 struct device_compatible_entry compat_data[] = { 124 { .compat = "TOS6200" }, 125 DEVICE_COMPAT_EOL 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 return acpi_compatible_match(aa, compat_data); 171 } 172 173 /* 174 * vald_acpi_attach: 175 * 176 * Autoconfiguration `attach' routine. 177 */ 178 static void 179 vald_acpi_attach(device_t parent, device_t self, void *aux) 180 { 181 struct vald_acpi_softc *sc = device_private(self); 182 struct acpi_attach_args *aa = aux; 183 ACPI_STATUS rv; 184 uint32_t value, result; 185 186 aprint_naive(": Toshiba VALD\n"); 187 aprint_normal(": Toshiba VALD\n"); 188 189 sc->sc_node = aa->aa_node; 190 sc->sc_dev = self; 191 192 /* Get AC adaptor status via _PSR. */ 193 rv = acpi_eval_integer(ACPI_ROOT_OBJECT, "\\_SB_.ADP1._PSR", 194 &sc->sc_ac_status); 195 if (ACPI_FAILURE(rv)) 196 aprint_error_dev(self, "Unable to evaluate _PSR: %s\n", 197 AcpiFormatException(rv)); 198 else 199 aprint_verbose_dev(self, "AC adaptor %sconnected\n", 200 (sc->sc_ac_status == 0 ? "not ": "")); 201 202 /* Get LCD backlight status. */ 203 rv = vald_acpi_ghci_get(sc, GHCI_BACKLIGHT, &value, &result); 204 if (ACPI_SUCCESS(rv)) { 205 if (result != 0) 206 aprint_error_dev(self, 207 "can't get backlight status error=%d\n", result); 208 else 209 aprint_verbose_dev(self, "LCD backlight %s\n", 210 ((value == GHCI_ON) ? "on" : "off")); 211 } 212 213 /* Enable SystemEventFIFO,HotkeyEvent */ 214 rv = vald_acpi_ghci_set(sc, GHCI_SYSTEM_EVENT_FIFO, GHCI_ENABLE, 215 &result); 216 if (ACPI_SUCCESS(rv) && result != 0) 217 aprint_error_dev(self, 218 "can't enable SystemEventFIFO error=%d\n", result); 219 220 rv = vald_acpi_ghci_set(sc, GHCI_HOTKEY_EVENT, GHCI_ENABLE, &result); 221 if (ACPI_SUCCESS(rv) && result != 0) 222 aprint_error_dev(self, "can't enable HotkeyEvent error=%d\n", 223 result); 224 225 /* Check SystemFIFO events. */ 226 vald_acpi_event(sc); 227 228 /* Get LCD brightness level via _BCL. */ 229 vald_acpi_libright_get(sc); 230 231 /* Set LCD brightness level via _BCM. */ 232 vald_acpi_libright_set(sc, LIBRIGHT_HOLD); 233 234 /* enable vald notify */ 235 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "ENAB", NULL, NULL); 236 237 if (ACPI_SUCCESS(rv)) 238 (void)acpi_register_notify(sc->sc_node, 239 vald_acpi_notify_handler); 240 } 241 242 /* 243 * vald_acpi_notify_handler: 244 * 245 * Notify handler. 246 */ 247 static void 248 vald_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) 249 { 250 struct vald_acpi_softc *sc; 251 device_t self = context; 252 253 sc = device_private(self); 254 255 switch (notify) { 256 257 case ACPI_NOTIFY_ValdStatusChanged: 258 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, vald_acpi_event, sc); 259 break; 260 261 default: 262 aprint_error_dev(sc->sc_dev, 263 "unknown notify 0x%02X\n", notify); 264 break; 265 } 266 } 267 268 /* 269 * vald_acpi_event: 270 * 271 * Check hotkey event and do it, if event occur. 272 */ 273 static void 274 vald_acpi_event(void *arg) 275 { 276 struct vald_acpi_softc *sc = arg; 277 ACPI_STATUS rv; 278 uint32_t value, result; 279 280 while(1) { 281 rv = vald_acpi_ghci_get(sc, GHCI_SYSTEM_EVENT_FIFO, &value, 282 &result); 283 if (ACPI_SUCCESS(rv) && result == 0) { 284 285 switch (value) { 286 case 0x1c3: /* Fn + F9 */ 287 break; 288 case 0x1c2: /* Fn + F8 */ 289 vald_acpi_fan_switch(sc); 290 break; 291 case 0x1c1: /* Fn + F7 */ 292 vald_acpi_libright_set(sc, LIBRIGHT_UP); 293 break; 294 case 0x1c0: /* Fn + F6 */ 295 vald_acpi_libright_set(sc, LIBRIGHT_DOWN); 296 break; 297 case 0x1bf: /* Fn + F5 */ 298 vald_acpi_video_switch(sc); 299 break; 300 default: 301 break; 302 } 303 } 304 if (ACPI_FAILURE(rv) || result == GHCI_FIFO_EMPTY) 305 break; 306 } 307 } 308 309 /* 310 * vald_acpi_ghci_get: 311 * 312 * Get value via "GHCI" Method. 313 */ 314 static ACPI_STATUS 315 vald_acpi_ghci_get(struct vald_acpi_softc *sc, 316 uint32_t reg, uint32_t *value, uint32_t *result) 317 { 318 ACPI_STATUS rv; 319 ACPI_OBJECT Arg[GHCI_WORDS]; 320 ACPI_OBJECT_LIST ArgList; 321 ACPI_OBJECT *param, *PrtElement; 322 ACPI_BUFFER buf; 323 int i; 324 325 for (i = 0; i < GHCI_WORDS; i++) { 326 Arg[i].Type = ACPI_TYPE_INTEGER; 327 Arg[i].Integer.Value = 0; 328 } 329 330 Arg[0].Integer.Value = 0xfe00; 331 Arg[1].Integer.Value = reg; 332 Arg[2].Integer.Value = 0; 333 334 ArgList.Count = GHCI_WORDS; 335 ArgList.Pointer = Arg; 336 337 buf.Pointer = NULL; 338 buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 339 340 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, 341 "GHCI", &ArgList, &buf); 342 if (ACPI_FAILURE(rv)) { 343 aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n", 344 AcpiFormatException(rv)); 345 return (rv); 346 } 347 348 *result = GHCI_NOT_SUPPORT; 349 *value = 0; 350 param = buf.Pointer; 351 if (param->Type == ACPI_TYPE_PACKAGE) { 352 PrtElement = param->Package.Elements; 353 if (PrtElement->Type == ACPI_TYPE_INTEGER) 354 *result = PrtElement->Integer.Value; 355 PrtElement++; 356 PrtElement++; 357 if (PrtElement->Type == ACPI_TYPE_INTEGER) 358 *value = PrtElement->Integer.Value; 359 } 360 361 if (buf.Pointer) 362 ACPI_FREE(buf.Pointer); 363 return (rv); 364 } 365 366 /* 367 * vald_acpi_ghci_set: 368 * 369 * Set value via "GHCI" Method. 370 */ 371 static ACPI_STATUS 372 vald_acpi_ghci_set(struct vald_acpi_softc *sc, 373 uint32_t reg, uint32_t value, uint32_t *result) 374 { 375 ACPI_STATUS rv; 376 ACPI_OBJECT Arg[GHCI_WORDS]; 377 ACPI_OBJECT_LIST ArgList; 378 ACPI_OBJECT *param, *PrtElement; 379 ACPI_BUFFER buf; 380 int i; 381 382 383 for (i = 0; i < GHCI_WORDS; i++) { 384 Arg[i].Type = ACPI_TYPE_INTEGER; 385 Arg[i].Integer.Value = 0; 386 } 387 388 Arg[0].Integer.Value = 0xff00; 389 Arg[1].Integer.Value = reg; 390 Arg[2].Integer.Value = value; 391 392 ArgList.Count = GHCI_WORDS; 393 ArgList.Pointer = Arg; 394 395 buf.Pointer = NULL; 396 buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 397 398 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, 399 "GHCI", &ArgList, &buf); 400 if (ACPI_FAILURE(rv)) { 401 aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n", 402 AcpiFormatException(rv)); 403 return (rv); 404 } 405 406 *result = GHCI_NOT_SUPPORT; 407 param = buf.Pointer; 408 if (param->Type == ACPI_TYPE_PACKAGE) { 409 PrtElement = param->Package.Elements; 410 if (PrtElement->Type == ACPI_TYPE_INTEGER) 411 *result = PrtElement->Integer.Value; 412 } 413 414 if (buf.Pointer) 415 ACPI_FREE(buf.Pointer); 416 return (rv); 417 } 418 419 /* 420 * vald_acpi_libright_get_bus: 421 * 422 * Get LCD brightness level via "_BCL" Method, 423 * and save this handle. 424 */ 425 static ACPI_STATUS 426 vald_acpi_libright_get_bus(ACPI_HANDLE handle, uint32_t level, 427 void *context, void **status) 428 { 429 struct vald_acpi_softc *sc = context; 430 ACPI_STATUS rv; 431 ACPI_BUFFER buf; 432 ACPI_OBJECT *param, *PrtElement; 433 int i, *pi; 434 435 rv = acpi_eval_struct(handle, "_BCL", &buf); 436 if (ACPI_FAILURE(rv)) 437 return (AE_OK); 438 439 sc->lcd_handle = handle; 440 param = buf.Pointer; 441 if (param->Type == ACPI_TYPE_PACKAGE) { 442 printf("_BCL return: %d packages\n", param->Package.Count); 443 444 sc->lcd_num = param->Package.Count; 445 sc->lcd_level = ACPI_ALLOCATE(sizeof(int) * sc->lcd_num); 446 if (sc->lcd_level == NULL) { 447 if (buf.Pointer) 448 ACPI_FREE(buf.Pointer); 449 return (AE_NO_MEMORY); 450 } 451 452 PrtElement = param->Package.Elements; 453 pi = sc->lcd_level; 454 for (i = 0; i < param->Package.Count; i++) { 455 if (PrtElement->Type == ACPI_TYPE_INTEGER) { 456 *pi = (unsigned)PrtElement->Integer.Value; 457 PrtElement++; 458 pi++; 459 } 460 } 461 if (sc->sc_ac_status == 1) /* AC adaptor on when attach */ 462 sc->lcd_index = sc->lcd_num -1; /* MAX Brightness */ 463 else 464 sc->lcd_index = 3; 465 466 #ifdef ACPI_DEBUG 467 pi = sc->lcd_level; 468 printf("\t Full Power Level: %d\n", *pi); 469 printf("\t on Battery Level: %d\n", *(pi+1)); 470 printf("\t Possible Level: "); 471 for (i = 2;i < sc->lcd_num; i++) 472 printf(" %d", *(pi+i)); 473 printf("\n"); 474 #endif 475 } 476 477 if (buf.Pointer) 478 ACPI_FREE(buf.Pointer); 479 return (AE_OK); 480 } 481 482 /* 483 * vald_acpi_libright_get: 484 * 485 * Search node that have "_BCL" Method. 486 */ 487 static void 488 vald_acpi_libright_get(struct vald_acpi_softc *sc) 489 { 490 ACPI_HANDLE parent; 491 ACPI_STATUS rv; 492 493 aprint_verbose_dev(sc->sc_dev, "get LCD brightness via _BCL\n"); 494 495 #ifdef ACPI_DEBUG 496 printf("acpi_libright_get: start\n"); 497 #endif 498 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent); 499 if (ACPI_FAILURE(rv)) 500 return; 501 502 AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100, 503 vald_acpi_libright_get_bus, NULL, sc, NULL); 504 } 505 506 /* 507 * vald_acpi_libright_set: 508 * 509 * Figure up next status and set it. 510 */ 511 static void 512 vald_acpi_libright_set(struct vald_acpi_softc *sc, int UpDown) 513 { 514 uint32_t backlight, backlight_new, result, bright; 515 ACPI_STATUS rv; 516 int *pi; 517 518 /* Skip,if it does not support _BCL. */ 519 if (sc->lcd_handle == NULL) 520 return; 521 522 /* Get LCD backlight status. */ 523 rv = vald_acpi_ghci_get(sc, GHCI_BACKLIGHT, &backlight, &result); 524 if (ACPI_FAILURE(rv) || result != 0) 525 return; 526 527 /* Figure up next status. */ 528 backlight_new = backlight; 529 if (UpDown == LIBRIGHT_UP) { 530 if (backlight == 1) 531 sc->lcd_index++; 532 else { 533 /* backlight on */ 534 backlight_new = 1; 535 sc->lcd_index = 2; 536 } 537 } else if (UpDown == LIBRIGHT_DOWN) { 538 if ((backlight == 1) && (sc->lcd_index > 2)) 539 sc->lcd_index--; 540 else { 541 /* backlight off */ 542 backlight_new = 0; 543 sc->lcd_index = 2; 544 } 545 } 546 547 /* Check index value. */ 548 if (sc->lcd_index < 2) 549 sc->lcd_index = 2; /* index Minimum Value */ 550 if (sc->lcd_index >= sc->lcd_num) 551 sc->lcd_index = sc->lcd_num - 1; 552 553 /* Set LCD backlight,if status is changed. */ 554 if (backlight_new != backlight) { 555 rv = vald_acpi_ghci_set(sc, GHCI_BACKLIGHT, backlight_new, 556 &result); 557 if (ACPI_SUCCESS(rv) && result != 0) 558 aprint_error_dev(sc->sc_dev, 559 "can't set LCD backlight %s error=%x\n", 560 ((backlight_new == 1) ? "on" : "off"), result); 561 } 562 563 if (backlight_new == 1) { 564 565 pi = sc->lcd_level; 566 bright = *(pi + sc->lcd_index); 567 568 rv = vald_acpi_bcm_set(sc->lcd_handle, bright); 569 if (ACPI_FAILURE(rv)) 570 aprint_error_dev(sc->sc_dev, 571 "unable to evaluate _BCM: %s\n", 572 AcpiFormatException(rv)); 573 } else { 574 bright = 0; 575 } 576 #ifdef ACPI_DEBUG 577 printf("LCD bright"); 578 printf(" %s", ((UpDown == LIBRIGHT_UP) ? "up":"")); 579 printf("%s\n", ((UpDown == LIBRIGHT_DOWN) ? "down":"")); 580 printf("\t acpi_libright_set: Set brightness to %d%%\n", bright); 581 #endif 582 } 583 584 /* 585 * vald_acpi_video_switch: 586 * 587 * Get video status(LCD/CRT) and set new video status. 588 */ 589 static void 590 vald_acpi_video_switch(struct vald_acpi_softc *sc) 591 { 592 ACPI_STATUS rv; 593 uint32_t value, result; 594 595 /* Get video status. */ 596 rv = vald_acpi_ghci_get(sc, GHCI_DISPLAY_DEVICE, &value, &result); 597 if (ACPI_FAILURE(rv)) 598 return; 599 if (result != 0) { 600 aprint_error_dev(sc->sc_dev, 601 "can't get video status error=%x\n", result); 602 return; 603 } 604 605 #ifdef ACPI_DEBUG 606 printf("Toggle LCD/CRT\n"); 607 printf("\t Before switch, video status: %s", 608 (((value & GHCI_LCD) == GHCI_LCD) ? "LCD" : "")); 609 printf("%s\n", (((value & GHCI_CRT) == GHCI_CRT) ? "CRT": "")); 610 #endif 611 612 /* Toggle LCD/CRT */ 613 if (value & GHCI_LCD) { 614 value &= ~GHCI_LCD; 615 value |= GHCI_CRT; 616 } else if (value & GHCI_CRT){ 617 value &= ~GHCI_CRT; 618 value |= GHCI_LCD; 619 } 620 621 rv = vald_acpi_dssx_set(value); 622 if (ACPI_FAILURE(rv)) 623 aprint_error_dev(sc->sc_dev, "unable to evaluate DSSX: %s\n", 624 AcpiFormatException(rv)); 625 626 } 627 628 /* 629 * vald_acpi_bcm_set: 630 * 631 * Set LCD brightness via "_BCM" Method. 632 */ 633 static ACPI_STATUS 634 vald_acpi_bcm_set(ACPI_HANDLE handle, uint32_t bright) 635 { 636 ACPI_STATUS rv; 637 ACPI_OBJECT Arg; 638 ACPI_OBJECT_LIST ArgList; 639 640 ArgList.Count = 1; 641 ArgList.Pointer = &Arg; 642 643 Arg.Type = ACPI_TYPE_INTEGER; 644 Arg.Integer.Value = bright; 645 646 rv = AcpiEvaluateObject(handle, "_BCM", &ArgList, NULL); 647 return (rv); 648 } 649 650 /* 651 * vald_acpi_dssx_set: 652 * 653 * Set value via "\\_SB_.VALX.DSSX" Method. 654 */ 655 static ACPI_STATUS 656 vald_acpi_dssx_set(uint32_t value) 657 { 658 return acpi_eval_set_integer(NULL, "\\_SB_.VALX.DSSX", value); 659 } 660 661 /* 662 * vald_acpi_fan_switch: 663 * 664 * Get FAN status and set new FAN status. 665 */ 666 static void 667 vald_acpi_fan_switch(struct vald_acpi_softc *sc) 668 { 669 ACPI_STATUS rv; 670 uint32_t value, result; 671 672 /* Get FAN status */ 673 rv = vald_acpi_ghci_get(sc, GHCI_FAN, &value, &result); 674 if (ACPI_FAILURE(rv)) 675 return; 676 if (result != 0) { 677 aprint_error_dev(sc->sc_dev, "can't get FAN status error=%d\n", 678 result); 679 return; 680 } 681 682 #ifdef ACPI_DEBUG 683 printf("Toggle FAN on/off\n"); 684 printf("\t Before toggle, FAN status %s\n", 685 (value == GHCI_OFF ? "off" : "on")); 686 #endif 687 688 /* Toggle FAN on/off */ 689 if (value == GHCI_OFF) 690 value = GHCI_ON; 691 else 692 value = GHCI_OFF; 693 694 /* Set FAN new status. */ 695 rv = vald_acpi_ghci_set(sc, GHCI_FAN, value, &result); 696 if (ACPI_FAILURE(rv)) 697 return; 698 if (result != 0) { 699 aprint_error_dev(sc->sc_dev, "can't set FAN status error=%d\n", 700 result); 701 return; 702 } 703 704 #ifdef ACPI_DEBUG 705 printf("\t After toggle, FAN status %s\n", 706 (value == GHCI_OFF ? "off" : "on")); 707 #endif 708 } 709