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