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
88ACPI_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
110struct 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
123static 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
132static int	vald_acpi_match(device_t, cfdata_t, void *);
133static void	vald_acpi_attach(device_t, device_t, void *);
134
135static void	vald_acpi_event(void *);
136static void	vald_acpi_notify_handler(ACPI_HANDLE, uint32_t, void *);
137
138#define ACPI_NOTIFY_ValdStatusChanged	0x80
139
140
141static ACPI_STATUS	vald_acpi_ghci_get(struct vald_acpi_softc *, uint32_t,
142					uint32_t *, uint32_t *);
143static ACPI_STATUS	vald_acpi_ghci_set(struct vald_acpi_softc *, uint32_t,
144					uint32_t, uint32_t *);
145
146static ACPI_STATUS	vald_acpi_libright_get_bus(ACPI_HANDLE, uint32_t,
147					void *, void **);
148static void		vald_acpi_libright_get(struct vald_acpi_softc *);
149static void		vald_acpi_libright_set(struct vald_acpi_softc *, int);
150
151static void		vald_acpi_video_switch(struct vald_acpi_softc *);
152static void		vald_acpi_fan_switch(struct vald_acpi_softc *);
153
154static ACPI_STATUS	vald_acpi_bcm_set(ACPI_HANDLE, uint32_t);
155static ACPI_STATUS	vald_acpi_dssx_set(uint32_t);
156
157CFATTACH_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 */
165static int
166vald_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 */
178static void
179vald_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 */
247static void
248vald_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 */
273static void
274vald_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 */
314static ACPI_STATUS
315vald_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 */
371static ACPI_STATUS
372vald_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 */
425static ACPI_STATUS
426vald_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 */
487static void
488vald_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 */
511static void
512vald_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 */
589static void
590vald_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 */
633static ACPI_STATUS
634vald_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 */
655static ACPI_STATUS
656vald_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 */
666static void
667vald_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