Home | History | Annotate | Line # | Download | only in acpi
      1 /*	$NetBSD: valz_acpi.c,v 1.9 2021/01/29 15:49:55 thorpej 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.9 2021/01/29 15:49:55 thorpej 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		("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 
    229 struct valz_acpi_softc {
    230 	device_t sc_dev;		/* base device glue */
    231 	struct acpi_devnode *sc_node;	/* our ACPI devnode */
    232 };
    233 
    234 static const struct device_compatible_entry compat_data[] = {
    235 	{ .compat = "TOS6208" },
    236 	DEVICE_COMPAT_EOL
    237 };
    238 
    239 static int	valz_acpi_match(device_t, cfdata_t, void *);
    240 static void	valz_acpi_attach(device_t, device_t, void *);
    241 
    242 static void	valz_acpi_event(void *);
    243 static 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 */
    250 static ACPI_STATUS	hci_op(struct valz_acpi_softc *,
    251 				uint32_t *, uint32_t *);
    252 static ACPI_STATUS	valz_acpi_hci_get(struct valz_acpi_softc *, uint32_t,
    253 					uint32_t, uint32_t *, uint32_t *);
    254 static ACPI_STATUS	valz_acpi_hci_set(struct valz_acpi_softc *, uint32_t,
    255 					uint32_t, uint32_t, uint32_t *);
    256 
    257 static ACPI_STATUS	sci_open(struct valz_acpi_softc *);
    258 static ACPI_STATUS	sci_close(struct valz_acpi_softc *);
    259 
    260 static ACPI_STATUS	valz_acpi_touchpad_toggle(struct valz_acpi_softc *);
    261 static ACPI_STATUS	valz_acpi_lcd_backlight_toggle(
    262 					struct valz_acpi_softc *sc);
    263 
    264 CFATTACH_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  */
    272 static int
    273 valz_acpi_match(device_t parent, cfdata_t match, void *aux)
    274 {
    275 	struct acpi_attach_args *aa = aux;
    276 
    277 	return acpi_compatible_match(aa, compat_data);
    278 }
    279 
    280 /*
    281  * valz_acpi_attach:
    282  *
    283  *	Autoconfiguration `attach' routine.
    284  */
    285 static void
    286 valz_acpi_attach(device_t parent, device_t self, void *aux)
    287 {
    288 	struct valz_acpi_softc *sc = device_private(self);
    289 	struct acpi_attach_args *aa = aux;
    290 	ACPI_STATUS rv;
    291 
    292 	aprint_naive(": Toshiba VALZ\n");
    293 	aprint_normal(": Toshiba VALZ\n");
    294 
    295 	sc->sc_node = aa->aa_node;
    296 	sc->sc_dev = self;
    297 
    298 	/* enable valz notify */
    299 	rv = AcpiEvaluateObject(sc->sc_node->ad_handle, METHOD_HCI_ENABLE,
    300 				NULL, NULL);
    301 	if (ACPI_FAILURE(rv)) {
    302 		aprint_error("Cannot enable VALZ.\n");
    303 	} else {
    304 		(void)acpi_register_notify(sc->sc_node,
    305 		    valz_acpi_notify_handler);
    306 	}
    307 }
    308 
    309 /*
    310  * valz_acpi_notify_handler:
    311  *
    312  *	Notify handler.
    313  */
    314 static void
    315 valz_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context)
    316 {
    317 	struct valz_acpi_softc *sc;
    318 	device_t self = context;
    319 
    320 	sc = device_private(self);
    321 
    322 	switch (notify) {
    323 	case ACPI_NOTIFY_ValzHotkeyPressed:
    324 		(void)AcpiOsExecute(OSL_NOTIFY_HANDLER, valz_acpi_event, sc);
    325 		break;
    326 
    327 	case ACPI_NOTIFY_ValzLidClosed:
    328 		/* Lid closed */
    329 		break;
    330 
    331 	case ACPI_NOTIFY_ValzKbdBLChanges:
    332 		/* Keyboard backlight mode changed */
    333 		break;
    334 
    335 	default:
    336 		aprint_debug_dev(sc->sc_dev,
    337 		    "unknown notify 0x%02X\n", notify);
    338 		break;
    339 	}
    340 }
    341 
    342 /*
    343  * valz_acpi_event:
    344  *
    345  *	Check hotkey event and do it, if event occur.
    346  */
    347 static void
    348 valz_acpi_event(void *arg)
    349 {
    350 	struct valz_acpi_softc *sc = arg;
    351 	ACPI_STATUS rv;
    352 	uint32_t value, result;
    353 
    354 	for (;;) {
    355 		rv = valz_acpi_hci_get(sc, HCI_GET, HCI_SYSTEM_EVENT_FIFO,
    356 			&value, &result);
    357 		if (ACPI_SUCCESS(rv) && result == 0) {
    358 			switch (value) {
    359 			case FN_F9_PRESS:
    360 				valz_acpi_touchpad_toggle(sc);
    361 				break;
    362 			case FN_TAB_PRESS:
    363 				valz_acpi_lcd_backlight_toggle(sc);
    364 				break;
    365 
    366 			default:
    367 				/* Many unused buttons */
    368 				aprint_debug("Pressed: 0x%x\n", value);
    369 				break;
    370 			}
    371 		}
    372 		if (ACPI_FAILURE(rv) || result == HCI_NOT_SUPPORTED ||
    373 			result == HCI_FIFO_EMPTY)
    374 			break;
    375 	}
    376 }
    377 
    378 /*
    379  * HCI/SCI operation
    380  */
    381 static ACPI_STATUS
    382 hci_op(struct valz_acpi_softc *sc, uint32_t *input, uint32_t *output)
    383 {
    384 	ACPI_STATUS rv;
    385 	ACPI_OBJECT Arg[HCI_WORDS];
    386 	ACPI_OBJECT_LIST ArgList;
    387 	ACPI_OBJECT *param, *PrtElement;
    388 	ACPI_BUFFER buf;
    389 	int		i;
    390 
    391 	for (i = 0; i < HCI_WORDS; i++) {
    392 		Arg[i].Type = ACPI_TYPE_INTEGER;
    393 		Arg[i].Integer.Value = 0;
    394 	}
    395 
    396 	for (i = 0; i < HCI_WORDS; i++) {
    397 		Arg[i].Integer.Value = input[i];
    398 	}
    399 
    400 	ArgList.Count = HCI_WORDS;
    401 	ArgList.Pointer = Arg;
    402 
    403 	buf.Pointer = NULL;
    404 	buf.Length = ACPI_ALLOCATE_BUFFER;
    405 
    406 	rv = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle,
    407 	    METHOD_HCI, &ArgList, &buf, ACPI_TYPE_PACKAGE);
    408 	if (ACPI_FAILURE(rv)) {
    409 		aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n",
    410 		    AcpiFormatException(rv));
    411 		return rv;
    412 	}
    413 
    414 	param = (ACPI_OBJECT *)buf.Pointer;
    415 	PrtElement = param->Package.Elements;
    416 	for (i = 0; i < HCI_WORDS; i++) {
    417 		output[i] = PrtElement[i].Type == ACPI_TYPE_INTEGER ?
    418 		    PrtElement[i].Integer.Value : 0;
    419 	}
    420 
    421 	ACPI_FREE(buf.Pointer);
    422 
    423 	return rv;
    424 }
    425 
    426 /*
    427  * valz_acpi_hci_get:
    428  *
    429  *	Get value via "GHCI" Method.
    430  */
    431 static ACPI_STATUS
    432 valz_acpi_hci_get(struct valz_acpi_softc *sc, uint32_t function,
    433     uint32_t reg, uint32_t *value, uint32_t *result)
    434 {
    435 	ACPI_STATUS rv;
    436 
    437 	uint32_t input[HCI_WORDS];
    438 	uint32_t output[HCI_WORDS];
    439 
    440 	input[HCI_REG_AX] = function;
    441 	input[HCI_REG_BX] = reg;
    442 	input[HCI_REG_CX] = 0;
    443 	input[HCI_REG_DX] = 0;
    444 	input[HCI_REG_SI] = 0;
    445 	input[HCI_REG_DI] = 0;
    446 
    447 	rv = hci_op(sc, input, output);
    448 
    449 	*result = output[HCI_REG_AX];
    450 	*value = output[HCI_REG_CX];
    451 
    452 	return rv;
    453 }
    454 
    455 /*
    456  * valz_acpi_hci_set:
    457  *
    458  *	Set value via "GHCI" Method.
    459  */
    460 static ACPI_STATUS
    461 valz_acpi_hci_set(struct valz_acpi_softc *sc, uint32_t function,
    462     uint32_t reg, uint32_t value, uint32_t *result)
    463 {
    464 	ACPI_STATUS rv;
    465 
    466 	uint32_t input[HCI_WORDS];
    467 	uint32_t output[HCI_WORDS];
    468 
    469 	input[HCI_REG_AX] = function;
    470 	input[HCI_REG_BX] = reg;
    471 	input[HCI_REG_CX] = value;
    472 	input[HCI_REG_DX] = 0;
    473 	input[HCI_REG_SI] = 0;
    474 	input[HCI_REG_DI] = 0;
    475 
    476 	rv = hci_op(sc, input, output);
    477 
    478 	*result = output[HCI_REG_AX];
    479 
    480 	return rv;
    481 }
    482 
    483 /*
    484  * Open SCI
    485  */
    486 static ACPI_STATUS
    487 sci_open(struct valz_acpi_softc *sc)
    488 {
    489 	ACPI_STATUS rv;
    490 	uint32_t result;
    491 
    492 	rv = valz_acpi_hci_set(sc, SCI_OPEN, 0, 0, &result);
    493 	if (ACPI_FAILURE(rv)) {
    494 		aprint_error("SCI: ACPI set error\n");
    495 	} else {
    496 		switch (result) {
    497 		case SCI_OPENCLOSE_OK:
    498 			aprint_debug("Opening SCI\n");
    499 			break;
    500 		case SCI_ALREADY_OPEN:
    501 			aprint_error("SCI already open\n");
    502 			break;
    503 		case SCI_NOT_SUPPORTED:
    504 			aprint_error("SCI is not supported\n");
    505 			break;
    506 		case SCI_NOT_PRESENT:
    507 			aprint_error("SCI is not present\n");
    508 			break;
    509 		default:
    510 			aprint_error("SCI: undefined behavior\n");
    511 			break;
    512 		}
    513 	}
    514 
    515 	return rv;
    516 }
    517 
    518 /*
    519  * Close SCI
    520  */
    521 static ACPI_STATUS
    522 sci_close(struct valz_acpi_softc *sc)
    523 {
    524 	ACPI_STATUS rv;
    525 	uint32_t result;
    526 
    527 	rv = valz_acpi_hci_set(sc, SCI_CLOSE, 0, 0, &result);
    528 	if (ACPI_FAILURE(rv)) {
    529 		aprint_error("SCI: ACPI set error\n");
    530 	} else {
    531 		switch (result) {
    532 		case SCI_OPENCLOSE_OK:
    533 			aprint_debug("Closing SCI\n");
    534 			break;
    535 		case SCI_NOT_OPEN:
    536 			aprint_error("SCI is not opened\n");
    537 			break;
    538 		case SCI_NOT_SUPPORTED:
    539 			aprint_error("SCI is not supported\n");
    540 			break;
    541 		case SCI_NOT_PRESENT:
    542 			aprint_error("SCI is not present\n");
    543 			break;
    544 		default:
    545 			aprint_error("SCI: undefined behavior\n");
    546 			break;
    547 		}
    548 	}
    549 
    550 	return rv;
    551 }
    552 
    553 /*
    554  * Enable/disable touchpad and trackpoint with HCI_ENABLE/HCI_DISABLE
    555  */
    556 static ACPI_STATUS
    557 valz_acpi_touchpad_toggle(struct valz_acpi_softc *sc)
    558 {
    559 	ACPI_STATUS rv;
    560 	uint32_t result, status, value;
    561 
    562 	rv = sci_open(sc);
    563 	if (ACPI_FAILURE(rv))
    564 		aprint_error_dev(sc->sc_dev,
    565 				"Cannot open SCI: %s\n",
    566 				AcpiFormatException(rv));
    567 
    568 	rv = valz_acpi_hci_get(sc, SCI_GET, SCI_TOUCHPAD, &value, &result);
    569 	if (ACPI_FAILURE(rv))
    570 		aprint_error_dev(sc->sc_dev,
    571 				"Cannot get SCI touchpad status: %s\n",
    572 				AcpiFormatException(rv));
    573 
    574 	switch (value) {
    575 	case HCI_ENABLE:
    576 		status = HCI_DISABLE;
    577 		break;
    578 	case HCI_DISABLE:
    579 		status = HCI_ENABLE;
    580 		break;
    581 	default:
    582 		status = HCI_ENABLE;
    583 		break;
    584 	}
    585 
    586 	rv = valz_acpi_hci_set(sc, SCI_SET, SCI_TOUCHPAD, status, &result);
    587 	if (ACPI_FAILURE(rv))
    588 		aprint_error_dev(sc->sc_dev,
    589 				"Cannot set SCI touchpad status: %s\n",
    590 				AcpiFormatException(rv));
    591 
    592 	rv = sci_close(sc);
    593 	if (ACPI_FAILURE(rv))
    594 		aprint_error_dev(sc->sc_dev,
    595 				"Cannot close SCI: %s\n",
    596 				AcpiFormatException(rv));
    597 
    598 	return rv;
    599 }
    600 
    601 /*
    602  * Enable/disable LCD backlight with HCI_ENABLE/HCI_DISABLE
    603  */
    604 static ACPI_STATUS
    605 valz_acpi_lcd_backlight_toggle(struct valz_acpi_softc *sc)
    606 {
    607 	ACPI_STATUS rv;
    608 	uint32_t result, status, value;
    609 
    610 	rv = valz_acpi_hci_get(sc, HCI_GET, HCI_LCD_BACKLIGHT, &value, &result);
    611 	if (ACPI_FAILURE(rv))
    612 		aprint_error_dev(sc->sc_dev,
    613 				"Cannot get HCI LCD backlight status: %s\n",
    614 				AcpiFormatException(rv));
    615 
    616 	switch (value) {
    617 	case HCI_ON:
    618 		status = HCI_OFF;
    619 		break;
    620 	case HCI_OFF:
    621 		status = HCI_ON;
    622 		break;
    623 	default:
    624 		status = HCI_ON;
    625 		break;
    626 	}
    627 
    628 	rv = valz_acpi_hci_set(sc, HCI_SET, HCI_LCD_BACKLIGHT, status, &result);
    629 	if (ACPI_FAILURE(rv))
    630 		aprint_error_dev(sc->sc_dev,
    631 				"Cannot set HCI LCD backlight status: %s\n",
    632 				AcpiFormatException(rv));
    633 
    634 	return rv;
    635 }
    636