valz_acpi.c revision 1.7
1/* $NetBSD: valz_acpi.c,v 1.7 2015/10/05 15:57:50 christos 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 VALZ Driver for Toshiba dynabook R63/PS 67 * This driver is based on vald_acpi.c 68 */ 69 70/* 71 * Obtain information of Toshiba "GHCI" Method from next URL. 72 * http://www.buzzard.me.uk/toshiba/docs.html 73 * http://memebeam.org/toys/ToshibaAcpiDriver 74 */ 75 76#include <sys/cdefs.h> 77__KERNEL_RCSID(0, "$NetBSD: valz_acpi.c,v 1.7 2015/10/05 15:57:50 christos 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 88ACPI_MODULE_NAME ("valz_acpi") 89 90#define METHOD_HCI "GHCI" 91#define METHOD_HCI_ENABLE "ENAB" 92 93/* Operations */ 94/* Get */ 95#define HCI_GET 0xfe00 96#define SCI_CHECK 0xf000 97#define SCI_GET 0xf300 98 99/* Set */ 100#define HCI_SET 0xff00 101#define SCI_OPEN 0xf100 102#define SCI_CLOSE 0xf200 103#define SCI_SET 0xf400 104 105/* Return codes */ 106#define HCI_SUCCESS 0x0000 107#define HCI_FAILURE 0x1000 108#define HCI_NOT_SUPPORTED 0x8000 109#define HCI_INPUT_ERROR 0x8300 110#define HCI_FIFO_EMPTY 0x8c00 111 112#define SCI_OPENCLOSE_OK 0x0044 113#define SCI_NOT_SUPPORTED 0x8000 114#define SCI_ALREADY_OPEN 0x8100 115#define SCI_NOT_OPEN 0x8200 116#define SCI_NOT_PRESENT 0x8600 117 118/* Functions */ 119#define HCI_LCD_BACKLIGHT 0x0002 120#define HCI_ACADAPTOR 0x0003 121#define HCI_SYSTEM_EVENT_FIFO 0x0016 122#define HCI_KBD_BACKLIGHT 0x0017 123#define HCI_DISPLAY_DEV 0x001c 124#define HCI_HOTKEY_EVENT 0x001e 125#define HCI_LCD_BRIGHTNESS 0x002a 126#define HCI_CPU_SPEED 0x0032 127 128#define SCI_USB_OFF_CHARGE 0x0150 129#define SCI_TOUCHPAD 0x050e 130#define SCI_KBD_BACKLIGHT_STS 0x015c 131#define SCI_KBD_BACKLIGHT 0x0095 132 133#define SCI_KBD_BL_TIME_SHIFT 0x10 134 135/* Field definitions */ 136#define HCI_LCD_BRIGHTNESS_BITS 3 137#define HCI_LCD_BRIGHTNESS_SFT (16 - HCI_LCD_BRIGHTNESS_BITS) 138#define HCI_LCD_BRIGHTNESS_MIN 0 139#define HCI_LCD_BRIGHTNESS_MAX 7 140#define HCI_VIDEO_DEVICE_FLG 0x0100 141#define HCI_CPU_SPEED_BITS 3 142#define HCI_CPU_SPEED_SFT (16 - HCI_CPU_SPEED_BITS) 143#define HCI_CPU_SPEED_MAX ((1 << HCI_CPU_SPEED_BITS) - 1) 144 145/* Key press/release events */ 146 147/* Key press/release events */ 148#define FN_RELEASE_OFFSET 0x80 149# if 0 150/* Not used */ 151#define FN_PRESS 0x01ff 152#define FN_RELEASE 0x0100 153# endif 154#define FN_ESC_PRESS 0x0101 155#define FN_ESC_RELEASE (FN_ESC_PRESS + FN_RELEASE_OFFSET) 156#define FN_F1_PRESS 0x013b 157#define FN_F1_RELEASE (FN_F1_PRESS + FN_RELEASE_OFFSET) 158#define FN_F2_PRESS 0x013c 159#define FN_F2_RELEASE (FN_F2_PRESS + FN_RELEASE_OFFSET) 160#define FN_F3_PRESS 0x013d 161#define FN_F3_RELEASE (FN_F3_PRESS + FN_RELEASE_OFFSET) 162#define FN_F4_PRESS 0x013e 163#define FN_F4_RELEASE (FN_F4_PRESS + FN_RELEASE_OFFSET) 164#define FN_F5_PRESS 0x013f 165#define FN_F5_RELEASE (FN_F5_PRESS + FN_RELEASE_OFFSET) 166#define FN_F6_PRESS 0x0140 167#define FN_F6_RELEASE (FN_F6_PRESS + FN_RELEASE_OFFSET) 168#define FN_F7_PRESS 0x0141 169#define FN_F7_RELEASE (FN_F7_PRESS + FN_RELEASE_OFFSET) 170#define FN_F8_PRESS 0x0142 171#define FN_F8_RELEASE (FN_F8_PRESS + FN_RELEASE_OFFSET) 172#define FN_F9_PRESS 0x0143 173#define FN_F9_RELEASE (FN_F9_PRESS + FN_RELEASE_OFFSET) 174/* Toggle, they are controlled by hardware */ 175#define FN_F10_ON 0x1bb0 176#define FN_F10_OFF 0x1bb1 177#define FN_F11_ON 0x1bb2 178#define FN_F11_OFF 0x1bb3 179/* Fn+F12 does not emit keycode */ 180/* dynabook R63/PS does not have KANJI keytop print */ 181#define FN_KNJ_PRESS 0x0129 182#define FN_KNJ_RELEASE (FN_KNJ_PRESS + FN_RELEASE_OFFSET) 183#define FN_1_PRESS 0x0102 184#define FN_1_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) 185#define FN_2_PRESS 0x0103 186#define FN_2_RELEASE (FN_2_PRESS + FN_RELEASE_OFFSET) 187/* Fn+3 and Fn+4 do not emit keybode */ 188#define FN_Z_PRESS 0x012c 189#define FN_Z_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) 190#define FN_SPACE_PRESS 0x0139 191#define FN_SPACE_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) 192#define FN_TAB_PRESS 0x010f 193#define FN_TAB_RELEASE (FN_TAB_PRESS + FN_RELEASE_OFFSET) 194#define FN_CAPS_PRESS 0x013a 195#define FN_CAPS_RELEASE (FN_CAPS_PRESS + FN_RELEASE_OFFSET) 196#define FN_BACKSPACE_PRESS 0x010e 197#define FN_BACKSPACE_RELEASE (FN_BACKSPACE_PRESS + FN_RELEASE_OFFSET) 198#define FN_INS_PRESS 0x0152 199#define FN_INS_RELEASE (FN_INS_PRESS + FN_RELEASE_OFFSET) 200#define FN_DEL_PRESS 0x0153 201#define FN_DEL_RELEASE (FN_DEL_PRESS + FN_RELEASE_OFFSET) 202#define FN_PRTSC_PRESS 0x0137 203#define FN_PRTSC_RELEASE (FN_PRTSC_PRESS + FN_RELEASE_OFFSET) 204 205/* HCI register definitions */ 206#define HCI_WORDS 6 /* number of registers */ 207#define HCI_REG_AX 0 /* Operation -> return value */ 208#define HCI_REG_BX 1 /* Function */ 209#define HCI_REG_CX 2 /* Argument (in or out) */ 210#define HCI_REG_DX 3 /* unused */ 211#define HCI_REG_SI 4 /* unused */ 212#define HCI_REG_DI 5 /* unused */ 213 214#define HCI_ON 0x0001 215#define HCI_OFF 0x0000 216#define HCI_ENABLE 0x0001 217#define HCI_DISABLE 0x0000 218 219#define HCI_LCD 0x1 220#define HCI_CRT 0x2 221#define HCI_TV 0x4 222 223#define SCI_KBD_BL_MODE_MASK 0x1f 224#define SCI_KBD_BL_TIMO_SFT 0x10 225#define SCI_KBD_BL_MODE_AUTO 0x2 226#define SCI_KBD_BL_MODE_ON 0x8 227#define SCI_KBD_BL_MODE_OFF 0x10 228 229struct valz_acpi_softc { 230 device_t sc_dev; /* base device glue */ 231 struct acpi_devnode *sc_node; /* our ACPI devnode */ 232}; 233 234static const char * const valz_acpi_hids[] = { 235 "TOS6208", 236 NULL 237}; 238 239static int valz_acpi_match(device_t, cfdata_t, void *); 240static void valz_acpi_attach(device_t, device_t, void *); 241 242static void valz_acpi_event(void *); 243static void valz_acpi_notify_handler(ACPI_HANDLE, uint32_t, void *); 244 245#define ACPI_NOTIFY_ValzHotkeyPressed 0x80 246#define ACPI_NOTIFY_ValzLidClosed 0x8f 247#define ACPI_NOTIFY_ValzKbdBLChanges 0x92 248 249/* HCI manipulation */ 250static ACPI_STATUS hci_op(struct valz_acpi_softc *, 251 uint32_t *, uint32_t *); 252static ACPI_STATUS valz_acpi_hci_get(struct valz_acpi_softc *, uint32_t, 253 uint32_t, uint32_t *, uint32_t *); 254static ACPI_STATUS valz_acpi_hci_set(struct valz_acpi_softc *, uint32_t, 255 uint32_t, uint32_t, uint32_t *); 256 257static ACPI_STATUS sci_open(struct valz_acpi_softc *); 258static ACPI_STATUS sci_close(struct valz_acpi_softc *); 259 260static ACPI_STATUS valz_acpi_touchpad_toggle(struct valz_acpi_softc *); 261static ACPI_STATUS valz_acpi_lcd_backlight_toggle( 262 struct valz_acpi_softc *sc); 263 264CFATTACH_DECL_NEW(valz_acpi, sizeof(struct valz_acpi_softc), 265 valz_acpi_match, valz_acpi_attach, NULL, NULL); 266 267/* 268 * valz_acpi_match: 269 * 270 * Autoconfiguration `match' routine. 271 */ 272static int 273valz_acpi_match(device_t parent, cfdata_t match, void *aux) 274{ 275 struct acpi_attach_args *aa = aux; 276 277 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 278 return (0); 279 280 return (acpi_match_hid(aa->aa_node->ad_devinfo, valz_acpi_hids)); 281} 282 283/* 284 * valz_acpi_attach: 285 * 286 * Autoconfiguration `attach' routine. 287 */ 288static void 289valz_acpi_attach(device_t parent, device_t self, void *aux) 290{ 291 struct valz_acpi_softc *sc = device_private(self); 292 struct acpi_attach_args *aa = aux; 293 ACPI_STATUS rv; 294 295 aprint_naive(": Toshiba VALZ\n"); 296 aprint_normal(": Toshiba VALZ\n"); 297 298 sc->sc_node = aa->aa_node; 299 sc->sc_dev = self; 300 301 /* enable valz notify */ 302 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, METHOD_HCI_ENABLE, 303 NULL, NULL); 304 if (ACPI_FAILURE(rv)) { 305 aprint_error("Cannot enable VALZ.\n"); 306 } else { 307 (void)acpi_register_notify(sc->sc_node, 308 valz_acpi_notify_handler); 309 } 310} 311 312/* 313 * valz_acpi_notify_handler: 314 * 315 * Notify handler. 316 */ 317static void 318valz_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) 319{ 320 struct valz_acpi_softc *sc; 321 device_t self = context; 322 323 sc = device_private(self); 324 325 switch (notify) { 326 case ACPI_NOTIFY_ValzHotkeyPressed: 327 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, valz_acpi_event, sc); 328 break; 329 330 case ACPI_NOTIFY_ValzLidClosed: 331 /* Lid closed */ 332 break; 333 334 case ACPI_NOTIFY_ValzKbdBLChanges: 335 /* Keyboard backlight mode changed */ 336 break; 337 338 default: 339 aprint_error_dev(sc->sc_dev, 340 "unknown notify 0x%02X\n", notify); 341 break; 342 } 343} 344 345/* 346 * valz_acpi_event: 347 * 348 * Check hotkey event and do it, if event occur. 349 */ 350static void 351valz_acpi_event(void *arg) 352{ 353 struct valz_acpi_softc *sc = arg; 354 ACPI_STATUS rv; 355 uint32_t value, result; 356 357 for (;;) { 358 rv = valz_acpi_hci_get(sc, HCI_GET, HCI_SYSTEM_EVENT_FIFO, 359 &value, &result); 360 if (ACPI_SUCCESS(rv) && result == 0) { 361 switch (value) { 362 case FN_F9_PRESS: 363 valz_acpi_touchpad_toggle(sc); 364 break; 365 case FN_TAB_PRESS: 366 valz_acpi_lcd_backlight_toggle(sc); 367 break; 368 369 default: 370 /* Many unused buttons */ 371 aprint_debug("Pressed: 0x%x\n", value); 372 break; 373 } 374 } 375 if (ACPI_FAILURE(rv) || result == HCI_NOT_SUPPORTED || 376 result == HCI_FIFO_EMPTY) 377 break; 378 } 379} 380 381/* 382 * HCI/SCI operation 383 */ 384static ACPI_STATUS 385hci_op(struct valz_acpi_softc *sc, uint32_t *input, uint32_t *output) 386{ 387 ACPI_STATUS rv; 388 ACPI_OBJECT Arg[HCI_WORDS]; 389 ACPI_OBJECT_LIST ArgList; 390 ACPI_OBJECT *param, *PrtElement; 391 ACPI_BUFFER buf; 392 int i; 393 394 for (i = 0; i < HCI_WORDS; i++) { 395 Arg[i].Type = ACPI_TYPE_INTEGER; 396 Arg[i].Integer.Value = 0; 397 } 398 399 for (i = 0; i < HCI_WORDS; i++) { 400 Arg[i].Integer.Value = input[i]; 401 } 402 403 ArgList.Count = HCI_WORDS; 404 ArgList.Pointer = Arg; 405 406 buf.Pointer = NULL; 407 buf.Length = ACPI_ALLOCATE_BUFFER; 408 409 rv = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle, 410 METHOD_HCI, &ArgList, &buf, ACPI_TYPE_PACKAGE); 411 if (ACPI_FAILURE(rv)) { 412 aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n", 413 AcpiFormatException(rv)); 414 return rv; 415 } 416 417 param = (ACPI_OBJECT *)buf.Pointer; 418 PrtElement = param->Package.Elements; 419 for (i = 0; i < HCI_WORDS; i++) { 420 output[i] = PrtElement[i].Type == ACPI_TYPE_INTEGER ? 421 PrtElement[i].Integer.Value : 0; 422 } 423 424 ACPI_FREE(buf.Pointer); 425 426 return rv; 427} 428 429/* 430 * valz_acpi_hci_get: 431 * 432 * Get value via "GHCI" Method. 433 */ 434static ACPI_STATUS 435valz_acpi_hci_get(struct valz_acpi_softc *sc, uint32_t function, 436 uint32_t reg, uint32_t *value, uint32_t *result) 437{ 438 ACPI_STATUS rv; 439 440 uint32_t input[HCI_WORDS]; 441 uint32_t output[HCI_WORDS]; 442 443 input[HCI_REG_AX] = function; 444 input[HCI_REG_BX] = reg; 445 input[HCI_REG_CX] = 0; 446 input[HCI_REG_DX] = 0; 447 input[HCI_REG_SI] = 0; 448 input[HCI_REG_DI] = 0; 449 450 rv = hci_op(sc, input, output); 451 452 *result = output[HCI_REG_AX]; 453 *value = output[HCI_REG_CX]; 454 455 return rv; 456} 457 458/* 459 * valz_acpi_hci_set: 460 * 461 * Set value via "GHCI" Method. 462 */ 463static ACPI_STATUS 464valz_acpi_hci_set(struct valz_acpi_softc *sc, uint32_t function, 465 uint32_t reg, uint32_t value, uint32_t *result) 466{ 467 ACPI_STATUS rv; 468 469 uint32_t input[HCI_WORDS]; 470 uint32_t output[HCI_WORDS]; 471 472 input[HCI_REG_AX] = function; 473 input[HCI_REG_BX] = reg; 474 input[HCI_REG_CX] = value; 475 input[HCI_REG_DX] = 0; 476 input[HCI_REG_SI] = 0; 477 input[HCI_REG_DI] = 0; 478 479 rv = hci_op(sc, input, output); 480 481 *result = output[HCI_REG_AX]; 482 483 return rv; 484} 485 486/* 487 * Open SCI 488 */ 489static ACPI_STATUS 490sci_open(struct valz_acpi_softc *sc) 491{ 492 ACPI_STATUS rv; 493 uint32_t result; 494 495 rv = valz_acpi_hci_set(sc, SCI_OPEN, 0, 0, &result); 496 if (ACPI_FAILURE(rv)) { 497 aprint_error("SCI: ACPI set error\n"); 498 } else { 499 switch (result) { 500 case SCI_OPENCLOSE_OK: 501 aprint_debug("Opening SCI\n"); 502 break; 503 case SCI_ALREADY_OPEN: 504 aprint_error("SCI already open\n"); 505 break; 506 case SCI_NOT_SUPPORTED: 507 aprint_error("SCI is not supported\n"); 508 break; 509 case SCI_NOT_PRESENT: 510 aprint_error("SCI is not present\n"); 511 break; 512 default: 513 aprint_error("SCI: undefined behavior\n"); 514 break; 515 } 516 } 517 518 return rv; 519} 520 521/* 522 * Close SCI 523 */ 524static ACPI_STATUS 525sci_close(struct valz_acpi_softc *sc) 526{ 527 ACPI_STATUS rv; 528 uint32_t result; 529 530 rv = valz_acpi_hci_set(sc, SCI_CLOSE, 0, 0, &result); 531 if (ACPI_FAILURE(rv)) { 532 aprint_error("SCI: ACPI set error\n"); 533 } else { 534 switch (result) { 535 case SCI_OPENCLOSE_OK: 536 aprint_debug("Closing SCI\n"); 537 break; 538 case SCI_NOT_OPEN: 539 aprint_error("SCI is not opened\n"); 540 break; 541 case SCI_NOT_SUPPORTED: 542 aprint_error("SCI is not supported\n"); 543 break; 544 case SCI_NOT_PRESENT: 545 aprint_error("SCI is not present\n"); 546 break; 547 default: 548 aprint_error("SCI: undefined behavior\n"); 549 break; 550 } 551 } 552 553 return rv; 554} 555 556/* 557 * Enable/disable touchpad and trackpoint with HCI_ENABLE/HCI_DISABLE 558 */ 559static ACPI_STATUS 560valz_acpi_touchpad_toggle(struct valz_acpi_softc *sc) 561{ 562 ACPI_STATUS rv; 563 uint32_t result, status, value; 564 565 rv = sci_open(sc); 566 if (ACPI_FAILURE(rv)) 567 aprint_error_dev(sc->sc_dev, 568 "Cannot open SCI: %s\n", 569 AcpiFormatException(rv)); 570 571 rv = valz_acpi_hci_get(sc, SCI_GET, SCI_TOUCHPAD, &value, &result); 572 if (ACPI_FAILURE(rv)) 573 aprint_error_dev(sc->sc_dev, 574 "Cannot get SCI touchpad status: %s\n", 575 AcpiFormatException(rv)); 576 577 switch (value) { 578 case HCI_ENABLE: 579 status = HCI_DISABLE; 580 break; 581 case HCI_DISABLE: 582 status = HCI_ENABLE; 583 break; 584 default: 585 status = HCI_ENABLE; 586 break; 587 } 588 589 rv = valz_acpi_hci_set(sc, SCI_SET, SCI_TOUCHPAD, status, &result); 590 if (ACPI_FAILURE(rv)) 591 aprint_error_dev(sc->sc_dev, 592 "Cannot set SCI touchpad status: %s\n", 593 AcpiFormatException(rv)); 594 595 rv = sci_close(sc); 596 if (ACPI_FAILURE(rv)) 597 aprint_error_dev(sc->sc_dev, 598 "Cannot close SCI: %s\n", 599 AcpiFormatException(rv)); 600 601 return rv; 602} 603 604/* 605 * Enable/disable LCD backlight with HCI_ENABLE/HCI_DISABLE 606 */ 607static ACPI_STATUS 608valz_acpi_lcd_backlight_toggle(struct valz_acpi_softc *sc) 609{ 610 ACPI_STATUS rv; 611 uint32_t result, status, value; 612 613 rv = valz_acpi_hci_get(sc, HCI_GET, HCI_LCD_BACKLIGHT, &value, &result); 614 if (ACPI_FAILURE(rv)) 615 aprint_error_dev(sc->sc_dev, 616 "Cannot get HCI LCD backlight status: %s\n", 617 AcpiFormatException(rv)); 618 619 switch (value) { 620 case HCI_ON: 621 status = HCI_OFF; 622 break; 623 case HCI_OFF: 624 status = HCI_ON; 625 break; 626 default: 627 status = HCI_ON; 628 break; 629 } 630 631 rv = valz_acpi_hci_set(sc, HCI_SET, HCI_LCD_BACKLIGHT, status, &result); 632 if (ACPI_FAILURE(rv)) 633 aprint_error_dev(sc->sc_dev, 634 "Cannot set HCI LCD backlight status: %s\n", 635 AcpiFormatException(rv)); 636 637 return rv; 638} 639