valz_acpi.c revision 1.6
1/*	$NetBSD: valz_acpi.c,v 1.6 2015/09/26 13:04:10 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.6 2015/09/26 13:04:10 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	for (i = 0; i < HCI_WORDS; i++) {
418		output[i] = 0;
419	}
420	param = (ACPI_OBJECT *)buf.Pointer;
421	PrtElement = param->Package.Elements;
422	for (i = 0; i < HCI_WORDS; i++) {
423		if (PrtElement->Type == ACPI_TYPE_INTEGER) {
424			output[i] = PrtElement->Integer.Value;
425			PrtElement++;
426		}
427	}
428
429	ACPI_FREE(buf.Pointer);
430
431	return rv;
432}
433
434/*
435 * valz_acpi_hci_get:
436 *
437 *	Get value via "GHCI" Method.
438 */
439static ACPI_STATUS
440valz_acpi_hci_get(struct valz_acpi_softc *sc, uint32_t function,
441    uint32_t reg, uint32_t *value, uint32_t *result)
442{
443	ACPI_STATUS rv;
444
445	uint32_t input[HCI_WORDS];
446	uint32_t output[HCI_WORDS];
447
448	input[HCI_REG_AX] = function;
449	input[HCI_REG_BX] = reg;
450	input[HCI_REG_CX] = 0;
451	input[HCI_REG_DX] = 0;
452	input[HCI_REG_SI] = 0;
453	input[HCI_REG_DI] = 0;
454
455	rv = hci_op(sc, input, output);
456
457	*result = output[HCI_REG_AX];
458	*value = output[HCI_REG_CX];
459
460	return rv;
461}
462
463/*
464 * valz_acpi_hci_set:
465 *
466 *	Set value via "GHCI" Method.
467 */
468static ACPI_STATUS
469valz_acpi_hci_set(struct valz_acpi_softc *sc, uint32_t function,
470    uint32_t reg, uint32_t value, uint32_t *result)
471{
472	ACPI_STATUS rv;
473
474	uint32_t input[HCI_WORDS];
475	uint32_t output[HCI_WORDS];
476
477	input[HCI_REG_AX] = function;
478	input[HCI_REG_BX] = reg;
479	input[HCI_REG_CX] = value;
480	input[HCI_REG_DX] = 0;
481	input[HCI_REG_SI] = 0;
482	input[HCI_REG_DI] = 0;
483
484	rv = hci_op(sc, input, output);
485
486	*result = output[HCI_REG_AX];
487
488	return rv;
489}
490
491/*
492 * Open SCI
493 */
494static ACPI_STATUS
495sci_open(struct valz_acpi_softc *sc)
496{
497	ACPI_STATUS rv;
498	uint32_t result;
499
500	rv = valz_acpi_hci_set(sc, SCI_OPEN, 0, 0, &result);
501	if (ACPI_FAILURE(rv)) {
502		aprint_error("SCI: ACPI set error\n");
503	} else {
504		switch (result) {
505		case SCI_OPENCLOSE_OK:
506			aprint_debug("Opening SCI\n");
507			break;
508		case SCI_ALREADY_OPEN:
509			aprint_error("SCI already open\n");
510			break;
511		case SCI_NOT_SUPPORTED:
512			aprint_error("SCI is not supported\n");
513			break;
514		case SCI_NOT_PRESENT:
515			aprint_error("SCI is not present\n");
516			break;
517		default:
518			aprint_error("SCI: undefined behavior\n");
519			break;
520		}
521	}
522
523	return rv;
524}
525
526/*
527 * Close SCI
528 */
529static ACPI_STATUS
530sci_close(struct valz_acpi_softc *sc)
531{
532	ACPI_STATUS rv;
533	uint32_t result;
534
535	rv = valz_acpi_hci_set(sc, SCI_CLOSE, 0, 0, &result);
536	if (ACPI_FAILURE(rv)) {
537		aprint_error("SCI: ACPI set error\n");
538	} else {
539		switch (result) {
540		case SCI_OPENCLOSE_OK:
541			aprint_debug("Closing SCI\n");
542			break;
543		case SCI_NOT_OPEN:
544			aprint_error("SCI is not opened\n");
545			break;
546		case SCI_NOT_SUPPORTED:
547			aprint_error("SCI is not supported\n");
548			break;
549		case SCI_NOT_PRESENT:
550			aprint_error("SCI is not present\n");
551			break;
552		default:
553			aprint_error("SCI: undefined behavior\n");
554			break;
555		}
556	}
557
558	return rv;
559}
560
561/*
562 * Enable/disable touchpad and trackpoint with HCI_ENABLE/HCI_DISABLE
563 */
564static ACPI_STATUS
565valz_acpi_touchpad_toggle(struct valz_acpi_softc *sc)
566{
567	ACPI_STATUS rv;
568	uint32_t result, status, value;
569
570	rv = sci_open(sc);
571	if (ACPI_FAILURE(rv))
572		aprint_error_dev(sc->sc_dev,
573				"Cannot open SCI: %s\n",
574				AcpiFormatException(rv));
575
576	rv = valz_acpi_hci_get(sc, SCI_GET, SCI_TOUCHPAD, &value, &result);
577	if (ACPI_FAILURE(rv))
578		aprint_error_dev(sc->sc_dev,
579				"Cannot get SCI touchpad status: %s\n",
580				AcpiFormatException(rv));
581
582	switch (value) {
583	case HCI_ENABLE:
584		status = HCI_DISABLE;
585		break;
586	case HCI_DISABLE:
587		status = HCI_ENABLE;
588		break;
589	default:
590		status = HCI_ENABLE;
591		break;
592	}
593
594	rv = valz_acpi_hci_set(sc, SCI_SET, SCI_TOUCHPAD, status, &result);
595	if (ACPI_FAILURE(rv))
596		aprint_error_dev(sc->sc_dev,
597				"Cannot set SCI touchpad status: %s\n",
598				AcpiFormatException(rv));
599
600	rv = sci_close(sc);
601	if (ACPI_FAILURE(rv))
602		aprint_error_dev(sc->sc_dev,
603				"Cannot close SCI: %s\n",
604				AcpiFormatException(rv));
605
606	return rv;
607}
608
609/*
610 * Enable/disable LCD backlight with HCI_ENABLE/HCI_DISABLE
611 */
612static ACPI_STATUS
613valz_acpi_lcd_backlight_toggle(struct valz_acpi_softc *sc)
614{
615	ACPI_STATUS rv;
616	uint32_t result, status, value;
617
618	rv = valz_acpi_hci_get(sc, HCI_GET, HCI_LCD_BACKLIGHT, &value, &result);
619	if (ACPI_FAILURE(rv))
620		aprint_error_dev(sc->sc_dev,
621				"Cannot get HCI LCD backlight status: %s\n",
622				AcpiFormatException(rv));
623
624	switch (value) {
625	case HCI_ON:
626		status = HCI_OFF;
627		break;
628	case HCI_OFF:
629		status = HCI_ON;
630		break;
631	default:
632		status = HCI_ON;
633		break;
634	}
635
636	rv = valz_acpi_hci_set(sc, HCI_SET, HCI_LCD_BACKLIGHT, status, &result);
637	if (ACPI_FAILURE(rv))
638		aprint_error_dev(sc->sc_dev,
639				"Cannot set HCI LCD backlight status: %s\n",
640				AcpiFormatException(rv));
641
642	return rv;
643}
644