1 /* $NetBSD: vald_acpi.c,v 1.8 2021/12/07 21:37:36 andvar 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 VALD Driver for Toshiba Libretto L3.
67 * This driver is based on acpibat driver.
68 */
69
70 /*
71 * Obtain information of Toshiba "GHCI" Method from next URL.
72 * http://www.buzzard.org.uk/toshiba/docs.html
73 * http://memebeam.org/toys/ToshibaAcpiDriver
74 */
75
76 #include <sys/cdefs.h>
77 __KERNEL_RCSID(0, "$NetBSD: vald_acpi.c,v 1.8 2021/12/07 21:37:36 andvar 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 ("vald_acpi")
89
90 #define GHCI_WORDS 6
91 #define GHCI_FIFO_EMPTY 0x8c00
92 #define GHCI_NOT_SUPPORT 0x8000
93
94 #define GHCI_BACKLIGHT 0x0002
95 #define GHCI_ACADAPTOR 0x0003
96 #define GHCI_FAN 0x0004
97 #define GHCI_SYSTEM_EVENT_FIFO 0x0016
98 #define GHCI_DISPLAY_DEVICE 0x001C
99 #define GHCI_HOTKEY_EVENT 0x001E
100
101 #define GHCI_ON 0x0001
102 #define GHCI_OFF 0x0000
103 #define GHCI_ENABLE 0x0001
104 #define GHCI_DISABLE 0x0000
105
106 #define GHCI_CRT 0x0002
107 #define GHCI_LCD 0x0001
108
109
110 struct vald_acpi_softc {
111 device_t sc_dev; /* base device glue */
112 struct acpi_devnode *sc_node; /* our ACPI devnode */
113 int sc_flags; /* see below */
114
115 ACPI_HANDLE lcd_handle; /* lcd handle */
116 int *lcd_level; /* lcd brightness table */
117 int lcd_num; /* size of lcd brightness table */
118 int lcd_index; /* index of lcd brightness table */
119
120 ACPI_INTEGER sc_ac_status; /* AC adaptor status when attach */
121 };
122
123 static const struct device_compatible_entry compat_data[] = {
124 { .compat = "TOS6200" },
125 DEVICE_COMPAT_EOL
126 };
127
128 #define LIBRIGHT_HOLD 0x00
129 #define LIBRIGHT_UP 0x01
130 #define LIBRIGHT_DOWN 0x02
131
132 static int vald_acpi_match(device_t, cfdata_t, void *);
133 static void vald_acpi_attach(device_t, device_t, void *);
134
135 static void vald_acpi_event(void *);
136 static void vald_acpi_notify_handler(ACPI_HANDLE, uint32_t, void *);
137
138 #define ACPI_NOTIFY_ValdStatusChanged 0x80
139
140
141 static ACPI_STATUS vald_acpi_ghci_get(struct vald_acpi_softc *, uint32_t,
142 uint32_t *, uint32_t *);
143 static ACPI_STATUS vald_acpi_ghci_set(struct vald_acpi_softc *, uint32_t,
144 uint32_t, uint32_t *);
145
146 static ACPI_STATUS vald_acpi_libright_get_bus(ACPI_HANDLE, uint32_t,
147 void *, void **);
148 static void vald_acpi_libright_get(struct vald_acpi_softc *);
149 static void vald_acpi_libright_set(struct vald_acpi_softc *, int);
150
151 static void vald_acpi_video_switch(struct vald_acpi_softc *);
152 static void vald_acpi_fan_switch(struct vald_acpi_softc *);
153
154 static ACPI_STATUS vald_acpi_bcm_set(ACPI_HANDLE, uint32_t);
155 static ACPI_STATUS vald_acpi_dssx_set(uint32_t);
156
157 CFATTACH_DECL_NEW(vald_acpi, sizeof(struct vald_acpi_softc),
158 vald_acpi_match, vald_acpi_attach, NULL, NULL);
159
160 /*
161 * vald_acpi_match:
162 *
163 * Autoconfiguration `match' routine.
164 */
165 static int
vald_acpi_match(device_t parent,cfdata_t match,void * aux)166 vald_acpi_match(device_t parent, cfdata_t match, void *aux)
167 {
168 struct acpi_attach_args *aa = aux;
169
170 return acpi_compatible_match(aa, compat_data);
171 }
172
173 /*
174 * vald_acpi_attach:
175 *
176 * Autoconfiguration `attach' routine.
177 */
178 static void
vald_acpi_attach(device_t parent,device_t self,void * aux)179 vald_acpi_attach(device_t parent, device_t self, void *aux)
180 {
181 struct vald_acpi_softc *sc = device_private(self);
182 struct acpi_attach_args *aa = aux;
183 ACPI_STATUS rv;
184 uint32_t value, result;
185
186 aprint_naive(": Toshiba VALD\n");
187 aprint_normal(": Toshiba VALD\n");
188
189 sc->sc_node = aa->aa_node;
190 sc->sc_dev = self;
191
192 /* Get AC adaptor status via _PSR. */
193 rv = acpi_eval_integer(ACPI_ROOT_OBJECT, "\\_SB_.ADP1._PSR",
194 &sc->sc_ac_status);
195 if (ACPI_FAILURE(rv))
196 aprint_error_dev(self, "Unable to evaluate _PSR: %s\n",
197 AcpiFormatException(rv));
198 else
199 aprint_verbose_dev(self, "AC adaptor %sconnected\n",
200 (sc->sc_ac_status == 0 ? "not ": ""));
201
202 /* Get LCD backlight status. */
203 rv = vald_acpi_ghci_get(sc, GHCI_BACKLIGHT, &value, &result);
204 if (ACPI_SUCCESS(rv)) {
205 if (result != 0)
206 aprint_error_dev(self,
207 "can't get backlight status error=%d\n", result);
208 else
209 aprint_verbose_dev(self, "LCD backlight %s\n",
210 ((value == GHCI_ON) ? "on" : "off"));
211 }
212
213 /* Enable SystemEventFIFO,HotkeyEvent */
214 rv = vald_acpi_ghci_set(sc, GHCI_SYSTEM_EVENT_FIFO, GHCI_ENABLE,
215 &result);
216 if (ACPI_SUCCESS(rv) && result != 0)
217 aprint_error_dev(self,
218 "can't enable SystemEventFIFO error=%d\n", result);
219
220 rv = vald_acpi_ghci_set(sc, GHCI_HOTKEY_EVENT, GHCI_ENABLE, &result);
221 if (ACPI_SUCCESS(rv) && result != 0)
222 aprint_error_dev(self, "can't enable HotkeyEvent error=%d\n",
223 result);
224
225 /* Check SystemFIFO events. */
226 vald_acpi_event(sc);
227
228 /* Get LCD brightness level via _BCL. */
229 vald_acpi_libright_get(sc);
230
231 /* Set LCD brightness level via _BCM. */
232 vald_acpi_libright_set(sc, LIBRIGHT_HOLD);
233
234 /* enable vald notify */
235 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "ENAB", NULL, NULL);
236
237 if (ACPI_SUCCESS(rv))
238 (void)acpi_register_notify(sc->sc_node,
239 vald_acpi_notify_handler);
240 }
241
242 /*
243 * vald_acpi_notify_handler:
244 *
245 * Notify handler.
246 */
247 static void
vald_acpi_notify_handler(ACPI_HANDLE handle,uint32_t notify,void * context)248 vald_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context)
249 {
250 struct vald_acpi_softc *sc;
251 device_t self = context;
252
253 sc = device_private(self);
254
255 switch (notify) {
256
257 case ACPI_NOTIFY_ValdStatusChanged:
258 (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, vald_acpi_event, sc);
259 break;
260
261 default:
262 aprint_error_dev(sc->sc_dev,
263 "unknown notify 0x%02X\n", notify);
264 break;
265 }
266 }
267
268 /*
269 * vald_acpi_event:
270 *
271 * Check hotkey event and do it, if event occur.
272 */
273 static void
vald_acpi_event(void * arg)274 vald_acpi_event(void *arg)
275 {
276 struct vald_acpi_softc *sc = arg;
277 ACPI_STATUS rv;
278 uint32_t value, result;
279
280 while(1) {
281 rv = vald_acpi_ghci_get(sc, GHCI_SYSTEM_EVENT_FIFO, &value,
282 &result);
283 if (ACPI_SUCCESS(rv) && result == 0) {
284
285 switch (value) {
286 case 0x1c3: /* Fn + F9 */
287 break;
288 case 0x1c2: /* Fn + F8 */
289 vald_acpi_fan_switch(sc);
290 break;
291 case 0x1c1: /* Fn + F7 */
292 vald_acpi_libright_set(sc, LIBRIGHT_UP);
293 break;
294 case 0x1c0: /* Fn + F6 */
295 vald_acpi_libright_set(sc, LIBRIGHT_DOWN);
296 break;
297 case 0x1bf: /* Fn + F5 */
298 vald_acpi_video_switch(sc);
299 break;
300 default:
301 break;
302 }
303 }
304 if (ACPI_FAILURE(rv) || result == GHCI_FIFO_EMPTY)
305 break;
306 }
307 }
308
309 /*
310 * vald_acpi_ghci_get:
311 *
312 * Get value via "GHCI" Method.
313 */
314 static ACPI_STATUS
vald_acpi_ghci_get(struct vald_acpi_softc * sc,uint32_t reg,uint32_t * value,uint32_t * result)315 vald_acpi_ghci_get(struct vald_acpi_softc *sc,
316 uint32_t reg, uint32_t *value, uint32_t *result)
317 {
318 ACPI_STATUS rv;
319 ACPI_OBJECT Arg[GHCI_WORDS];
320 ACPI_OBJECT_LIST ArgList;
321 ACPI_OBJECT *param, *PrtElement;
322 ACPI_BUFFER buf;
323 int i;
324
325 for (i = 0; i < GHCI_WORDS; i++) {
326 Arg[i].Type = ACPI_TYPE_INTEGER;
327 Arg[i].Integer.Value = 0;
328 }
329
330 Arg[0].Integer.Value = 0xfe00;
331 Arg[1].Integer.Value = reg;
332 Arg[2].Integer.Value = 0;
333
334 ArgList.Count = GHCI_WORDS;
335 ArgList.Pointer = Arg;
336
337 buf.Pointer = NULL;
338 buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
339
340 rv = AcpiEvaluateObject(sc->sc_node->ad_handle,
341 "GHCI", &ArgList, &buf);
342 if (ACPI_FAILURE(rv)) {
343 aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n",
344 AcpiFormatException(rv));
345 return (rv);
346 }
347
348 *result = GHCI_NOT_SUPPORT;
349 *value = 0;
350 param = buf.Pointer;
351 if (param->Type == ACPI_TYPE_PACKAGE) {
352 PrtElement = param->Package.Elements;
353 if (PrtElement->Type == ACPI_TYPE_INTEGER)
354 *result = PrtElement->Integer.Value;
355 PrtElement++;
356 PrtElement++;
357 if (PrtElement->Type == ACPI_TYPE_INTEGER)
358 *value = PrtElement->Integer.Value;
359 }
360
361 if (buf.Pointer)
362 ACPI_FREE(buf.Pointer);
363 return (rv);
364 }
365
366 /*
367 * vald_acpi_ghci_set:
368 *
369 * Set value via "GHCI" Method.
370 */
371 static ACPI_STATUS
vald_acpi_ghci_set(struct vald_acpi_softc * sc,uint32_t reg,uint32_t value,uint32_t * result)372 vald_acpi_ghci_set(struct vald_acpi_softc *sc,
373 uint32_t reg, uint32_t value, uint32_t *result)
374 {
375 ACPI_STATUS rv;
376 ACPI_OBJECT Arg[GHCI_WORDS];
377 ACPI_OBJECT_LIST ArgList;
378 ACPI_OBJECT *param, *PrtElement;
379 ACPI_BUFFER buf;
380 int i;
381
382
383 for (i = 0; i < GHCI_WORDS; i++) {
384 Arg[i].Type = ACPI_TYPE_INTEGER;
385 Arg[i].Integer.Value = 0;
386 }
387
388 Arg[0].Integer.Value = 0xff00;
389 Arg[1].Integer.Value = reg;
390 Arg[2].Integer.Value = value;
391
392 ArgList.Count = GHCI_WORDS;
393 ArgList.Pointer = Arg;
394
395 buf.Pointer = NULL;
396 buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
397
398 rv = AcpiEvaluateObject(sc->sc_node->ad_handle,
399 "GHCI", &ArgList, &buf);
400 if (ACPI_FAILURE(rv)) {
401 aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n",
402 AcpiFormatException(rv));
403 return (rv);
404 }
405
406 *result = GHCI_NOT_SUPPORT;
407 param = buf.Pointer;
408 if (param->Type == ACPI_TYPE_PACKAGE) {
409 PrtElement = param->Package.Elements;
410 if (PrtElement->Type == ACPI_TYPE_INTEGER)
411 *result = PrtElement->Integer.Value;
412 }
413
414 if (buf.Pointer)
415 ACPI_FREE(buf.Pointer);
416 return (rv);
417 }
418
419 /*
420 * vald_acpi_libright_get_bus:
421 *
422 * Get LCD brightness level via "_BCL" Method,
423 * and save this handle.
424 */
425 static ACPI_STATUS
vald_acpi_libright_get_bus(ACPI_HANDLE handle,uint32_t level,void * context,void ** status)426 vald_acpi_libright_get_bus(ACPI_HANDLE handle, uint32_t level,
427 void *context, void **status)
428 {
429 struct vald_acpi_softc *sc = context;
430 ACPI_STATUS rv;
431 ACPI_BUFFER buf;
432 ACPI_OBJECT *param, *PrtElement;
433 int i, *pi;
434
435 rv = acpi_eval_struct(handle, "_BCL", &buf);
436 if (ACPI_FAILURE(rv))
437 return (AE_OK);
438
439 sc->lcd_handle = handle;
440 param = buf.Pointer;
441 if (param->Type == ACPI_TYPE_PACKAGE) {
442 printf("_BCL return: %d packages\n", param->Package.Count);
443
444 sc->lcd_num = param->Package.Count;
445 sc->lcd_level = ACPI_ALLOCATE(sizeof(int) * sc->lcd_num);
446 if (sc->lcd_level == NULL) {
447 if (buf.Pointer)
448 ACPI_FREE(buf.Pointer);
449 return (AE_NO_MEMORY);
450 }
451
452 PrtElement = param->Package.Elements;
453 pi = sc->lcd_level;
454 for (i = 0; i < param->Package.Count; i++) {
455 if (PrtElement->Type == ACPI_TYPE_INTEGER) {
456 *pi = (unsigned)PrtElement->Integer.Value;
457 PrtElement++;
458 pi++;
459 }
460 }
461 if (sc->sc_ac_status == 1) /* AC adaptor on when attach */
462 sc->lcd_index = sc->lcd_num -1; /* MAX Brightness */
463 else
464 sc->lcd_index = 3;
465
466 #ifdef ACPI_DEBUG
467 pi = sc->lcd_level;
468 printf("\t Full Power Level: %d\n", *pi);
469 printf("\t on Battery Level: %d\n", *(pi+1));
470 printf("\t Possible Level: ");
471 for (i = 2;i < sc->lcd_num; i++)
472 printf(" %d", *(pi+i));
473 printf("\n");
474 #endif
475 }
476
477 if (buf.Pointer)
478 ACPI_FREE(buf.Pointer);
479 return (AE_OK);
480 }
481
482 /*
483 * vald_acpi_libright_get:
484 *
485 * Search node that have "_BCL" Method.
486 */
487 static void
vald_acpi_libright_get(struct vald_acpi_softc * sc)488 vald_acpi_libright_get(struct vald_acpi_softc *sc)
489 {
490 ACPI_HANDLE parent;
491 ACPI_STATUS rv;
492
493 aprint_verbose_dev(sc->sc_dev, "get LCD brightness via _BCL\n");
494
495 #ifdef ACPI_DEBUG
496 printf("acpi_libright_get: start\n");
497 #endif
498 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent);
499 if (ACPI_FAILURE(rv))
500 return;
501
502 AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100,
503 vald_acpi_libright_get_bus, NULL, sc, NULL);
504 }
505
506 /*
507 * vald_acpi_libright_set:
508 *
509 * Figure up next status and set it.
510 */
511 static void
vald_acpi_libright_set(struct vald_acpi_softc * sc,int UpDown)512 vald_acpi_libright_set(struct vald_acpi_softc *sc, int UpDown)
513 {
514 uint32_t backlight, backlight_new, result, bright;
515 ACPI_STATUS rv;
516 int *pi;
517
518 /* Skip,if it does not support _BCL. */
519 if (sc->lcd_handle == NULL)
520 return;
521
522 /* Get LCD backlight status. */
523 rv = vald_acpi_ghci_get(sc, GHCI_BACKLIGHT, &backlight, &result);
524 if (ACPI_FAILURE(rv) || result != 0)
525 return;
526
527 /* Figure up next status. */
528 backlight_new = backlight;
529 if (UpDown == LIBRIGHT_UP) {
530 if (backlight == 1)
531 sc->lcd_index++;
532 else {
533 /* backlight on */
534 backlight_new = 1;
535 sc->lcd_index = 2;
536 }
537 } else if (UpDown == LIBRIGHT_DOWN) {
538 if ((backlight == 1) && (sc->lcd_index > 2))
539 sc->lcd_index--;
540 else {
541 /* backlight off */
542 backlight_new = 0;
543 sc->lcd_index = 2;
544 }
545 }
546
547 /* Check index value. */
548 if (sc->lcd_index < 2)
549 sc->lcd_index = 2; /* index Minimum Value */
550 if (sc->lcd_index >= sc->lcd_num)
551 sc->lcd_index = sc->lcd_num - 1;
552
553 /* Set LCD backlight,if status is changed. */
554 if (backlight_new != backlight) {
555 rv = vald_acpi_ghci_set(sc, GHCI_BACKLIGHT, backlight_new,
556 &result);
557 if (ACPI_SUCCESS(rv) && result != 0)
558 aprint_error_dev(sc->sc_dev,
559 "can't set LCD backlight %s error=%x\n",
560 ((backlight_new == 1) ? "on" : "off"), result);
561 }
562
563 if (backlight_new == 1) {
564
565 pi = sc->lcd_level;
566 bright = *(pi + sc->lcd_index);
567
568 rv = vald_acpi_bcm_set(sc->lcd_handle, bright);
569 if (ACPI_FAILURE(rv))
570 aprint_error_dev(sc->sc_dev,
571 "unable to evaluate _BCM: %s\n",
572 AcpiFormatException(rv));
573 } else {
574 bright = 0;
575 }
576 #ifdef ACPI_DEBUG
577 printf("LCD bright");
578 printf(" %s", ((UpDown == LIBRIGHT_UP) ? "up":""));
579 printf("%s\n", ((UpDown == LIBRIGHT_DOWN) ? "down":""));
580 printf("\t acpi_libright_set: Set brightness to %d%%\n", bright);
581 #endif
582 }
583
584 /*
585 * vald_acpi_video_switch:
586 *
587 * Get video status(LCD/CRT) and set new video status.
588 */
589 static void
vald_acpi_video_switch(struct vald_acpi_softc * sc)590 vald_acpi_video_switch(struct vald_acpi_softc *sc)
591 {
592 ACPI_STATUS rv;
593 uint32_t value, result;
594
595 /* Get video status. */
596 rv = vald_acpi_ghci_get(sc, GHCI_DISPLAY_DEVICE, &value, &result);
597 if (ACPI_FAILURE(rv))
598 return;
599 if (result != 0) {
600 aprint_error_dev(sc->sc_dev,
601 "can't get video status error=%x\n", result);
602 return;
603 }
604
605 #ifdef ACPI_DEBUG
606 printf("Toggle LCD/CRT\n");
607 printf("\t Before switch, video status: %s",
608 (((value & GHCI_LCD) == GHCI_LCD) ? "LCD" : ""));
609 printf("%s\n", (((value & GHCI_CRT) == GHCI_CRT) ? "CRT": ""));
610 #endif
611
612 /* Toggle LCD/CRT */
613 if (value & GHCI_LCD) {
614 value &= ~GHCI_LCD;
615 value |= GHCI_CRT;
616 } else if (value & GHCI_CRT){
617 value &= ~GHCI_CRT;
618 value |= GHCI_LCD;
619 }
620
621 rv = vald_acpi_dssx_set(value);
622 if (ACPI_FAILURE(rv))
623 aprint_error_dev(sc->sc_dev, "unable to evaluate DSSX: %s\n",
624 AcpiFormatException(rv));
625
626 }
627
628 /*
629 * vald_acpi_bcm_set:
630 *
631 * Set LCD brightness via "_BCM" Method.
632 */
633 static ACPI_STATUS
vald_acpi_bcm_set(ACPI_HANDLE handle,uint32_t bright)634 vald_acpi_bcm_set(ACPI_HANDLE handle, uint32_t bright)
635 {
636 ACPI_STATUS rv;
637 ACPI_OBJECT Arg;
638 ACPI_OBJECT_LIST ArgList;
639
640 ArgList.Count = 1;
641 ArgList.Pointer = &Arg;
642
643 Arg.Type = ACPI_TYPE_INTEGER;
644 Arg.Integer.Value = bright;
645
646 rv = AcpiEvaluateObject(handle, "_BCM", &ArgList, NULL);
647 return (rv);
648 }
649
650 /*
651 * vald_acpi_dssx_set:
652 *
653 * Set value via "\\_SB_.VALX.DSSX" Method.
654 */
655 static ACPI_STATUS
vald_acpi_dssx_set(uint32_t value)656 vald_acpi_dssx_set(uint32_t value)
657 {
658 return acpi_eval_set_integer(NULL, "\\_SB_.VALX.DSSX", value);
659 }
660
661 /*
662 * vald_acpi_fan_switch:
663 *
664 * Get FAN status and set new FAN status.
665 */
666 static void
vald_acpi_fan_switch(struct vald_acpi_softc * sc)667 vald_acpi_fan_switch(struct vald_acpi_softc *sc)
668 {
669 ACPI_STATUS rv;
670 uint32_t value, result;
671
672 /* Get FAN status */
673 rv = vald_acpi_ghci_get(sc, GHCI_FAN, &value, &result);
674 if (ACPI_FAILURE(rv))
675 return;
676 if (result != 0) {
677 aprint_error_dev(sc->sc_dev, "can't get FAN status error=%d\n",
678 result);
679 return;
680 }
681
682 #ifdef ACPI_DEBUG
683 printf("Toggle FAN on/off\n");
684 printf("\t Before toggle, FAN status %s\n",
685 (value == GHCI_OFF ? "off" : "on"));
686 #endif
687
688 /* Toggle FAN on/off */
689 if (value == GHCI_OFF)
690 value = GHCI_ON;
691 else
692 value = GHCI_OFF;
693
694 /* Set FAN new status. */
695 rv = vald_acpi_ghci_set(sc, GHCI_FAN, value, &result);
696 if (ACPI_FAILURE(rv))
697 return;
698 if (result != 0) {
699 aprint_error_dev(sc->sc_dev, "can't set FAN status error=%d\n",
700 result);
701 return;
702 }
703
704 #ifdef ACPI_DEBUG
705 printf("\t After toggle, FAN status %s\n",
706 (value == GHCI_OFF ? "off" : "on"));
707 #endif
708 }
709