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