xref: /netbsd-src/sys/dev/acpi/valz_acpi.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*	$NetBSD: valz_acpi.c,v 1.8 2017/11/09 23:51:54 ryoon 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.8 2017/11/09 23:51:54 ryoon 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 char * const valz_acpi_hids[] = {
235 	"TOS6208",
236 	NULL
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 	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  */
288 static void
289 valz_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  */
317 static void
318 valz_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_debug_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  */
350 static void
351 valz_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  */
384 static ACPI_STATUS
385 hci_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  */
434 static ACPI_STATUS
435 valz_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  */
463 static ACPI_STATUS
464 valz_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  */
489 static ACPI_STATUS
490 sci_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  */
524 static ACPI_STATUS
525 sci_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  */
559 static ACPI_STATUS
560 valz_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  */
607 static ACPI_STATUS
608 valz_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