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
valz_acpi_match(device_t parent,cfdata_t match,void * aux)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
valz_acpi_attach(device_t parent,device_t self,void * aux)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
valz_acpi_notify_handler(ACPI_HANDLE handle,uint32_t notify,void * context)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
valz_acpi_event(void * arg)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
hci_op(struct valz_acpi_softc * sc,uint32_t * input,uint32_t * output)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
valz_acpi_hci_get(struct valz_acpi_softc * sc,uint32_t function,uint32_t reg,uint32_t * value,uint32_t * result)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
valz_acpi_hci_set(struct valz_acpi_softc * sc,uint32_t function,uint32_t reg,uint32_t value,uint32_t * result)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
sci_open(struct valz_acpi_softc * sc)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
sci_close(struct valz_acpi_softc * sc)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
valz_acpi_touchpad_toggle(struct valz_acpi_softc * sc)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
valz_acpi_lcd_backlight_toggle(struct valz_acpi_softc * sc)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