Home | History | Annotate | Line # | Download | only in acpi
vald_acpi.c revision 1.4
      1  1.4  jruoho /*	$NetBSD: vald_acpi.c,v 1.4 2010/04/15 07:02:24 jruoho Exp $ */
      2  1.1  jruoho 
      3  1.1  jruoho /*-
      4  1.1  jruoho  * Copyright (c) 2002 The NetBSD Foundation, Inc.
      5  1.1  jruoho  * All rights reserved.
      6  1.1  jruoho  *
      7  1.1  jruoho  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  jruoho  * by Masanori Kanaoka.
      9  1.1  jruoho  *
     10  1.1  jruoho  * Redistribution and use in source and binary forms, with or without
     11  1.1  jruoho  * modification, are permitted provided that the following conditions
     12  1.1  jruoho  * are met:
     13  1.1  jruoho  * 1. Redistributions of source code must retain the above copyright
     14  1.1  jruoho  *    notice, this list of conditions and the following disclaimer.
     15  1.1  jruoho  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  jruoho  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  jruoho  *    documentation and/or other materials provided with the distribution.
     18  1.1  jruoho  *
     19  1.1  jruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1  jruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1  jruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1  jruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1  jruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1  jruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1  jruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1  jruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1  jruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1  jruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1  jruoho  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1  jruoho  */
     31  1.1  jruoho 
     32  1.1  jruoho /*
     33  1.1  jruoho  * Copyright 2001 Bill Sommerfeld.
     34  1.1  jruoho  * All rights reserved.
     35  1.1  jruoho  *
     36  1.1  jruoho  * Redistribution and use in source and binary forms, with or without
     37  1.1  jruoho  * modification, are permitted provided that the following conditions
     38  1.1  jruoho  * are met:
     39  1.1  jruoho  * 1. Redistributions of source code must retain the above copyright
     40  1.1  jruoho  *    notice, this list of conditions and the following disclaimer.
     41  1.1  jruoho  * 2. Redistributions in binary form must reproduce the above copyright
     42  1.1  jruoho  *    notice, this list of conditions and the following disclaimer in the
     43  1.1  jruoho  *    documentation and/or other materials provided with the distribution.
     44  1.1  jruoho  * 3. All advertising materials mentioning features or use of this software
     45  1.1  jruoho  *    must display the following acknowledgement:
     46  1.1  jruoho  *	This product includes software developed for the NetBSD Project by
     47  1.1  jruoho  *	Wasabi Systems, Inc.
     48  1.1  jruoho  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     49  1.1  jruoho  *    or promote products derived from this software without specific prior
     50  1.1  jruoho  *    written permission.
     51  1.1  jruoho  *
     52  1.1  jruoho  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     53  1.1  jruoho  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     54  1.1  jruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     55  1.1  jruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     56  1.1  jruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     57  1.1  jruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     58  1.1  jruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     59  1.1  jruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     60  1.1  jruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     61  1.1  jruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     62  1.1  jruoho  * POSSIBILITY OF SUCH DAMAGE.
     63  1.1  jruoho  */
     64  1.1  jruoho 
     65  1.1  jruoho /*
     66  1.1  jruoho  * ACPI VALD Driver for Toshiba Libretto L3.
     67  1.1  jruoho  *	This driver is based on acpibat driver.
     68  1.1  jruoho  */
     69  1.1  jruoho 
     70  1.1  jruoho /*
     71  1.1  jruoho  * Obtain information of Toshiba "GHCI" Method from next URL.
     72  1.1  jruoho  *           http://www.buzzard.org.uk/toshiba/docs.html
     73  1.1  jruoho  *           http://memebeam.org/toys/ToshibaAcpiDriver
     74  1.1  jruoho  */
     75  1.1  jruoho 
     76  1.1  jruoho #include <sys/cdefs.h>
     77  1.4  jruoho __KERNEL_RCSID(0, "$NetBSD: vald_acpi.c,v 1.4 2010/04/15 07:02:24 jruoho Exp $");
     78  1.1  jruoho 
     79  1.1  jruoho #include <sys/param.h>
     80  1.1  jruoho #include <sys/systm.h>
     81  1.1  jruoho #include <sys/device.h>
     82  1.1  jruoho 
     83  1.1  jruoho #include <dev/acpi/acpica.h>
     84  1.1  jruoho #include <dev/acpi/acpireg.h>
     85  1.1  jruoho #include <dev/acpi/acpivar.h>
     86  1.1  jruoho 
     87  1.1  jruoho #define _COMPONENT          ACPI_RESOURCE_COMPONENT
     88  1.1  jruoho ACPI_MODULE_NAME            ("vald_acpi")
     89  1.1  jruoho 
     90  1.1  jruoho #define GHCI_WORDS 6
     91  1.1  jruoho #define GHCI_FIFO_EMPTY  0x8c00
     92  1.1  jruoho #define GHCI_NOT_SUPPORT  0x8000
     93  1.1  jruoho 
     94  1.1  jruoho #define GHCI_BACKLIGHT		0x0002
     95  1.1  jruoho #define GHCI_ACADAPTOR		0x0003
     96  1.1  jruoho #define GHCI_FAN		0x0004
     97  1.1  jruoho #define GHCI_SYSTEM_EVENT_FIFO	0x0016
     98  1.1  jruoho #define GHCI_DISPLAY_DEVICE	0x001C
     99  1.1  jruoho #define GHCI_HOTKEY_EVENT	0x001E
    100  1.1  jruoho 
    101  1.1  jruoho #define GHCI_ON			0x0001
    102  1.1  jruoho #define GHCI_OFF		0x0000
    103  1.1  jruoho #define GHCI_ENABLE		0x0001
    104  1.1  jruoho #define GHCI_DISABLE		0x0000
    105  1.1  jruoho 
    106  1.1  jruoho #define GHCI_CRT		0x0002
    107  1.1  jruoho #define GHCI_LCD		0x0001
    108  1.1  jruoho 
    109  1.1  jruoho 
    110  1.1  jruoho struct vald_acpi_softc {
    111  1.1  jruoho 	device_t sc_dev;		/* base device glue */
    112  1.1  jruoho 	struct acpi_devnode *sc_node;	/* our ACPI devnode */
    113  1.1  jruoho 	int sc_flags;			/* see below */
    114  1.1  jruoho 
    115  1.1  jruoho 	ACPI_HANDLE lcd_handle;		/* lcd handle */
    116  1.1  jruoho 	int *lcd_level;			/* lcd brightness table */
    117  1.1  jruoho 	int lcd_num;			/* size of lcd brightness table */
    118  1.1  jruoho 	int lcd_index;			/* index of lcd brightness table */
    119  1.1  jruoho 
    120  1.1  jruoho 	ACPI_INTEGER sc_ac_status;	/* AC adaptor status when attach */
    121  1.1  jruoho };
    122  1.1  jruoho 
    123  1.1  jruoho static const char * const vald_acpi_hids[] = {
    124  1.1  jruoho 	"TOS6200",
    125  1.1  jruoho 	NULL
    126  1.1  jruoho };
    127  1.1  jruoho 
    128  1.1  jruoho #define LIBRIGHT_HOLD	0x00
    129  1.1  jruoho #define LIBRIGHT_UP	0x01
    130  1.1  jruoho #define LIBRIGHT_DOWN	0x02
    131  1.1  jruoho 
    132  1.1  jruoho static int	vald_acpi_match(device_t, cfdata_t, void *);
    133  1.1  jruoho static void	vald_acpi_attach(device_t, device_t, void *);
    134  1.1  jruoho 
    135  1.1  jruoho static void	vald_acpi_event(void *);
    136  1.3  jruoho static void	vald_acpi_notify_handler(ACPI_HANDLE, uint32_t, void *);
    137  1.1  jruoho 
    138  1.1  jruoho #define ACPI_NOTIFY_ValdStatusChanged	0x80
    139  1.1  jruoho 
    140  1.1  jruoho 
    141  1.3  jruoho static ACPI_STATUS	vald_acpi_ghci_get(struct vald_acpi_softc *, uint32_t,
    142  1.3  jruoho 					uint32_t *, uint32_t *);
    143  1.3  jruoho static ACPI_STATUS	vald_acpi_ghci_set(struct vald_acpi_softc *, uint32_t,
    144  1.3  jruoho 					uint32_t, uint32_t *);
    145  1.1  jruoho 
    146  1.3  jruoho static ACPI_STATUS	vald_acpi_libright_get_bus(ACPI_HANDLE, uint32_t,
    147  1.3  jruoho 					void *, void **);
    148  1.1  jruoho static void		vald_acpi_libright_get(struct vald_acpi_softc *);
    149  1.1  jruoho static void		vald_acpi_libright_set(struct vald_acpi_softc *, int);
    150  1.1  jruoho 
    151  1.1  jruoho static void		vald_acpi_video_switch(struct vald_acpi_softc *);
    152  1.1  jruoho static void		vald_acpi_fan_switch(struct vald_acpi_softc *);
    153  1.1  jruoho 
    154  1.3  jruoho static ACPI_STATUS	vald_acpi_bcm_set(ACPI_HANDLE, uint32_t);
    155  1.3  jruoho static ACPI_STATUS	vald_acpi_dssx_set(uint32_t);
    156  1.1  jruoho 
    157  1.1  jruoho CFATTACH_DECL_NEW(vald_acpi, sizeof(struct vald_acpi_softc),
    158  1.1  jruoho     vald_acpi_match, vald_acpi_attach, NULL, NULL);
    159  1.1  jruoho 
    160  1.1  jruoho /*
    161  1.1  jruoho  * vald_acpi_match:
    162  1.1  jruoho  *
    163  1.1  jruoho  *	Autoconfiguration `match' routine.
    164  1.1  jruoho  */
    165  1.1  jruoho static int
    166  1.1  jruoho vald_acpi_match(device_t parent, cfdata_t match, void *aux)
    167  1.1  jruoho {
    168  1.1  jruoho 	struct acpi_attach_args *aa = aux;
    169  1.1  jruoho 
    170  1.1  jruoho 	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
    171  1.1  jruoho 		return (0);
    172  1.1  jruoho 
    173  1.1  jruoho 	return (acpi_match_hid(aa->aa_node->ad_devinfo, vald_acpi_hids));
    174  1.1  jruoho }
    175  1.1  jruoho 
    176  1.1  jruoho /*
    177  1.1  jruoho  * vald_acpi_attach:
    178  1.1  jruoho  *
    179  1.1  jruoho  *	Autoconfiguration `attach' routine.
    180  1.1  jruoho  */
    181  1.1  jruoho static void
    182  1.1  jruoho vald_acpi_attach(device_t parent, device_t self, void *aux)
    183  1.1  jruoho {
    184  1.1  jruoho 	struct vald_acpi_softc *sc = device_private(self);
    185  1.1  jruoho 	struct acpi_attach_args *aa = aux;
    186  1.1  jruoho 	ACPI_STATUS rv;
    187  1.3  jruoho 	uint32_t value, result;
    188  1.1  jruoho 
    189  1.1  jruoho 	aprint_naive(": Toshiba VALD\n");
    190  1.1  jruoho 	aprint_normal(": Toshiba VALD\n");
    191  1.1  jruoho 
    192  1.1  jruoho 	sc->sc_node = aa->aa_node;
    193  1.1  jruoho 	sc->sc_dev = self;
    194  1.1  jruoho 
    195  1.1  jruoho 	/* Get AC adaptor status via _PSR. */
    196  1.1  jruoho 	rv = acpi_eval_integer(ACPI_ROOT_OBJECT, "\\_SB_.ADP1._PSR",
    197  1.1  jruoho 	    &sc->sc_ac_status);
    198  1.1  jruoho 	if (ACPI_FAILURE(rv))
    199  1.1  jruoho 		aprint_error_dev(self, "Unable to evaluate _PSR: %s\n",
    200  1.1  jruoho 		    AcpiFormatException(rv));
    201  1.1  jruoho 	else
    202  1.1  jruoho 		aprint_verbose_dev(self, "AC adaptor %sconnected\n",
    203  1.1  jruoho 		    (sc->sc_ac_status == 0 ? "not ": ""));
    204  1.1  jruoho 
    205  1.1  jruoho 	/* Get LCD backlight status. */
    206  1.1  jruoho 	rv = vald_acpi_ghci_get(sc, GHCI_BACKLIGHT, &value, &result);
    207  1.1  jruoho 	if (ACPI_SUCCESS(rv)) {
    208  1.1  jruoho 		if (result != 0)
    209  1.1  jruoho 			aprint_error_dev(self, "can't get backlight status error=%d\n",
    210  1.1  jruoho 			    result);
    211  1.1  jruoho 		else
    212  1.1  jruoho 			aprint_verbose_dev(self, "LCD backlight %s\n",
    213  1.1  jruoho 			    ((value == GHCI_ON) ? "on" : "off"));
    214  1.1  jruoho 	}
    215  1.1  jruoho 
    216  1.1  jruoho 	/* Enable SystemEventFIFO,HotkeyEvent */
    217  1.1  jruoho 	rv = vald_acpi_ghci_set(sc, GHCI_SYSTEM_EVENT_FIFO, GHCI_ENABLE,
    218  1.1  jruoho 	    &result);
    219  1.1  jruoho 	if (ACPI_SUCCESS(rv) && result != 0)
    220  1.1  jruoho 		aprint_error_dev(self, "can't enable SystemEventFIFO error=%d\n",
    221  1.1  jruoho 		    result);
    222  1.1  jruoho 
    223  1.1  jruoho 	rv = vald_acpi_ghci_set(sc, GHCI_HOTKEY_EVENT, GHCI_ENABLE, &result);
    224  1.1  jruoho 	if (ACPI_SUCCESS(rv) && result != 0)
    225  1.1  jruoho 		aprint_error_dev(self, "can't enable HotkeyEvent error=%d\n",
    226  1.1  jruoho 		    result);
    227  1.1  jruoho 
    228  1.1  jruoho 	/* Check SystemFIFO events. */
    229  1.1  jruoho 	vald_acpi_event(sc);
    230  1.1  jruoho 
    231  1.1  jruoho 	/* Get LCD brightness level via _BCL. */
    232  1.1  jruoho 	vald_acpi_libright_get(sc);
    233  1.1  jruoho 
    234  1.1  jruoho 	/* Set LCD brightness level via _BCM. */
    235  1.1  jruoho 	vald_acpi_libright_set(sc, LIBRIGHT_HOLD);
    236  1.1  jruoho 
    237  1.1  jruoho 	/* enable vald notify */
    238  1.4  jruoho 	rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "ENAB", NULL, NULL);
    239  1.4  jruoho 
    240  1.4  jruoho 	if (ACPI_SUCCESS(rv))
    241  1.4  jruoho 		(void)acpi_register_notify(sc->sc_node,
    242  1.4  jruoho 		    vald_acpi_notify_handler);
    243  1.1  jruoho }
    244  1.1  jruoho 
    245  1.1  jruoho /*
    246  1.1  jruoho  * vald_acpi_notify_handler:
    247  1.1  jruoho  *
    248  1.1  jruoho  *	Notify handler.
    249  1.1  jruoho  */
    250  1.1  jruoho static void
    251  1.3  jruoho vald_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context)
    252  1.1  jruoho {
    253  1.4  jruoho 	struct vald_acpi_softc *sc;
    254  1.4  jruoho 	device_t self = context;
    255  1.4  jruoho 
    256  1.4  jruoho 	sc = device_private(self);
    257  1.1  jruoho 
    258  1.1  jruoho 	switch (notify) {
    259  1.1  jruoho 
    260  1.1  jruoho 	case ACPI_NOTIFY_ValdStatusChanged:
    261  1.1  jruoho 		(void)AcpiOsExecute(OSL_NOTIFY_HANDLER, vald_acpi_event, sc);
    262  1.1  jruoho 		break;
    263  1.1  jruoho 
    264  1.1  jruoho 	default:
    265  1.1  jruoho 		aprint_error_dev(sc->sc_dev,
    266  1.1  jruoho 		    "unknown notify 0x%02X\n", notify);
    267  1.1  jruoho 		break;
    268  1.1  jruoho 	}
    269  1.1  jruoho }
    270  1.1  jruoho 
    271  1.1  jruoho /*
    272  1.1  jruoho  * vald_acpi_event:
    273  1.1  jruoho  *
    274  1.1  jruoho  *	Check hotkey event and do it, if event occur.
    275  1.1  jruoho  */
    276  1.1  jruoho static void
    277  1.1  jruoho vald_acpi_event(void *arg)
    278  1.1  jruoho {
    279  1.1  jruoho 	struct vald_acpi_softc *sc = arg;
    280  1.1  jruoho 	ACPI_STATUS rv;
    281  1.3  jruoho 	uint32_t value, result;
    282  1.1  jruoho 
    283  1.1  jruoho 	while(1) {
    284  1.1  jruoho 		rv = vald_acpi_ghci_get(sc, GHCI_SYSTEM_EVENT_FIFO, &value,
    285  1.1  jruoho 		    &result);
    286  1.1  jruoho 		if (ACPI_SUCCESS(rv) && result == 0) {
    287  1.1  jruoho 
    288  1.1  jruoho 			switch (value) {
    289  1.1  jruoho 			case 0x1c3: /* Fn + F9 */
    290  1.1  jruoho 				break;
    291  1.1  jruoho 			case 0x1c2: /* Fn + F8 */
    292  1.1  jruoho 				vald_acpi_fan_switch(sc);
    293  1.1  jruoho 				break;
    294  1.1  jruoho 			case 0x1c1: /* Fn + F7 */
    295  1.1  jruoho 				vald_acpi_libright_set(sc, LIBRIGHT_UP);
    296  1.1  jruoho 				break;
    297  1.1  jruoho 			case 0x1c0: /* Fn + F6 */
    298  1.1  jruoho 				vald_acpi_libright_set(sc, LIBRIGHT_DOWN);
    299  1.1  jruoho 				break;
    300  1.1  jruoho 			case 0x1bf: /* Fn + F5 */
    301  1.1  jruoho 				vald_acpi_video_switch(sc);
    302  1.1  jruoho 				break;
    303  1.1  jruoho 			default:
    304  1.1  jruoho 				break;
    305  1.1  jruoho 			}
    306  1.1  jruoho 		}
    307  1.1  jruoho 		if (ACPI_FAILURE(rv) || result == GHCI_FIFO_EMPTY)
    308  1.1  jruoho 			break;
    309  1.1  jruoho 	}
    310  1.1  jruoho }
    311  1.1  jruoho 
    312  1.1  jruoho /*
    313  1.1  jruoho  * vald_acpi_ghci_get:
    314  1.1  jruoho  *
    315  1.1  jruoho  *	Get value via "GHCI" Method.
    316  1.1  jruoho  */
    317  1.1  jruoho static ACPI_STATUS
    318  1.1  jruoho vald_acpi_ghci_get(struct vald_acpi_softc *sc,
    319  1.3  jruoho     uint32_t reg, uint32_t *value, uint32_t *result)
    320  1.1  jruoho {
    321  1.1  jruoho 	ACPI_STATUS rv;
    322  1.1  jruoho 	ACPI_OBJECT Arg[GHCI_WORDS];
    323  1.1  jruoho 	ACPI_OBJECT_LIST ArgList;
    324  1.1  jruoho 	ACPI_OBJECT *param, *PrtElement;
    325  1.1  jruoho 	ACPI_BUFFER buf;
    326  1.1  jruoho 	int		i;
    327  1.1  jruoho 
    328  1.1  jruoho 	for (i = 0; i < GHCI_WORDS; i++) {
    329  1.1  jruoho 		Arg[i].Type = ACPI_TYPE_INTEGER;
    330  1.1  jruoho 		Arg[i].Integer.Value = 0;
    331  1.1  jruoho 	}
    332  1.1  jruoho 
    333  1.1  jruoho 	Arg[0].Integer.Value = 0xfe00;
    334  1.1  jruoho 	Arg[1].Integer.Value = reg;
    335  1.1  jruoho 	Arg[2].Integer.Value = 0;
    336  1.1  jruoho 
    337  1.1  jruoho 	ArgList.Count = GHCI_WORDS;
    338  1.1  jruoho 	ArgList.Pointer = Arg;
    339  1.1  jruoho 
    340  1.1  jruoho 	buf.Pointer = NULL;
    341  1.1  jruoho 	buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    342  1.1  jruoho 
    343  1.1  jruoho 	rv = AcpiEvaluateObject(sc->sc_node->ad_handle,
    344  1.1  jruoho 	    "GHCI", &ArgList, &buf);
    345  1.1  jruoho 	if (ACPI_FAILURE(rv)) {
    346  1.1  jruoho 		aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n",
    347  1.1  jruoho 		    AcpiFormatException(rv));
    348  1.1  jruoho 		return (rv);
    349  1.1  jruoho 	}
    350  1.1  jruoho 
    351  1.1  jruoho 	*result = GHCI_NOT_SUPPORT;
    352  1.1  jruoho 	*value = 0;
    353  1.2  jruoho 	param = buf.Pointer;
    354  1.1  jruoho 	if (param->Type == ACPI_TYPE_PACKAGE) {
    355  1.1  jruoho 		PrtElement = param->Package.Elements;
    356  1.1  jruoho 		if (PrtElement->Type == ACPI_TYPE_INTEGER)
    357  1.1  jruoho 			*result = PrtElement->Integer.Value;
    358  1.1  jruoho 		PrtElement++;
    359  1.1  jruoho 		PrtElement++;
    360  1.1  jruoho 		if (PrtElement->Type == ACPI_TYPE_INTEGER)
    361  1.1  jruoho 			*value = PrtElement->Integer.Value;
    362  1.1  jruoho 	}
    363  1.1  jruoho 
    364  1.1  jruoho 	if (buf.Pointer)
    365  1.1  jruoho 		ACPI_FREE(buf.Pointer);
    366  1.1  jruoho 	return (rv);
    367  1.1  jruoho }
    368  1.1  jruoho 
    369  1.1  jruoho /*
    370  1.1  jruoho  * vald_acpi_ghci_set:
    371  1.1  jruoho  *
    372  1.1  jruoho  *	Set value via "GHCI" Method.
    373  1.1  jruoho  */
    374  1.1  jruoho static ACPI_STATUS
    375  1.1  jruoho vald_acpi_ghci_set(struct vald_acpi_softc *sc,
    376  1.3  jruoho     uint32_t reg, uint32_t value, uint32_t *result)
    377  1.1  jruoho {
    378  1.1  jruoho 	ACPI_STATUS rv;
    379  1.1  jruoho 	ACPI_OBJECT Arg[GHCI_WORDS];
    380  1.1  jruoho 	ACPI_OBJECT_LIST ArgList;
    381  1.1  jruoho 	ACPI_OBJECT *param, *PrtElement;
    382  1.1  jruoho 	ACPI_BUFFER buf;
    383  1.1  jruoho 	int	i;
    384  1.1  jruoho 
    385  1.1  jruoho 
    386  1.1  jruoho 	for (i = 0; i < GHCI_WORDS; i++) {
    387  1.1  jruoho 		Arg[i].Type = ACPI_TYPE_INTEGER;
    388  1.1  jruoho 		Arg[i].Integer.Value = 0;
    389  1.1  jruoho 	}
    390  1.1  jruoho 
    391  1.1  jruoho 	Arg[0].Integer.Value = 0xff00;
    392  1.1  jruoho 	Arg[1].Integer.Value = reg;
    393  1.1  jruoho 	Arg[2].Integer.Value = value;
    394  1.1  jruoho 
    395  1.1  jruoho 	ArgList.Count = GHCI_WORDS;
    396  1.1  jruoho 	ArgList.Pointer = Arg;
    397  1.1  jruoho 
    398  1.1  jruoho 	buf.Pointer = NULL;
    399  1.1  jruoho 	buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    400  1.1  jruoho 
    401  1.1  jruoho 	rv = AcpiEvaluateObject(sc->sc_node->ad_handle,
    402  1.1  jruoho 	    "GHCI", &ArgList, &buf);
    403  1.1  jruoho 	if (ACPI_FAILURE(rv)) {
    404  1.1  jruoho 		aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n",
    405  1.1  jruoho 		    AcpiFormatException(rv));
    406  1.1  jruoho 		return (rv);
    407  1.1  jruoho 	}
    408  1.1  jruoho 
    409  1.1  jruoho 	*result = GHCI_NOT_SUPPORT;
    410  1.2  jruoho 	param = buf.Pointer;
    411  1.1  jruoho 	if (param->Type == ACPI_TYPE_PACKAGE) {
    412  1.1  jruoho 		PrtElement = param->Package.Elements;
    413  1.1  jruoho 	    	if (PrtElement->Type == ACPI_TYPE_INTEGER)
    414  1.1  jruoho 			*result = PrtElement->Integer.Value;
    415  1.1  jruoho 	}
    416  1.1  jruoho 
    417  1.1  jruoho 	if (buf.Pointer)
    418  1.1  jruoho 		ACPI_FREE(buf.Pointer);
    419  1.1  jruoho 	return (rv);
    420  1.1  jruoho }
    421  1.1  jruoho 
    422  1.1  jruoho /*
    423  1.1  jruoho  * vald_acpi_libright_get_bus:
    424  1.1  jruoho  *
    425  1.1  jruoho  *	Get LCD brightness level via "_BCL" Method,
    426  1.1  jruoho  *	and save this handle.
    427  1.1  jruoho  */
    428  1.1  jruoho static ACPI_STATUS
    429  1.3  jruoho vald_acpi_libright_get_bus(ACPI_HANDLE handle, uint32_t level,
    430  1.1  jruoho     void *context, void **status)
    431  1.1  jruoho {
    432  1.1  jruoho 	struct vald_acpi_softc *sc = context;
    433  1.1  jruoho 	ACPI_STATUS rv;
    434  1.1  jruoho 	ACPI_BUFFER buf;
    435  1.1  jruoho 	ACPI_OBJECT *param, *PrtElement;
    436  1.1  jruoho 	int i, *pi;
    437  1.1  jruoho 
    438  1.1  jruoho 	rv = acpi_eval_struct(handle, "_BCL", &buf);
    439  1.1  jruoho 	if (ACPI_FAILURE(rv))
    440  1.1  jruoho 		return (AE_OK);
    441  1.1  jruoho 
    442  1.1  jruoho 	sc->lcd_handle = handle;
    443  1.2  jruoho 	param = buf.Pointer;
    444  1.1  jruoho 	if (param->Type == ACPI_TYPE_PACKAGE) {
    445  1.1  jruoho 		printf("_BCL retrun: %d packages\n", param->Package.Count);
    446  1.1  jruoho 
    447  1.1  jruoho 		sc->lcd_num = param->Package.Count;
    448  1.1  jruoho 		sc->lcd_level = ACPI_ALLOCATE(sizeof(int) * sc->lcd_num);
    449  1.1  jruoho 		if (sc->lcd_level == NULL) {
    450  1.1  jruoho 			if (buf.Pointer)
    451  1.1  jruoho 				ACPI_FREE(buf.Pointer);
    452  1.1  jruoho 			return (AE_NO_MEMORY);
    453  1.1  jruoho 		}
    454  1.1  jruoho 
    455  1.1  jruoho 		PrtElement = param->Package.Elements;
    456  1.1  jruoho 		pi = sc->lcd_level;
    457  1.1  jruoho 		for (i = 0; i < param->Package.Count; i++) {
    458  1.1  jruoho 			if (PrtElement->Type == ACPI_TYPE_INTEGER) {
    459  1.1  jruoho 				*pi = (unsigned)PrtElement->Integer.Value;
    460  1.1  jruoho 				PrtElement++;
    461  1.1  jruoho 				pi++;
    462  1.1  jruoho 			}
    463  1.1  jruoho 		}
    464  1.1  jruoho 		if (sc->sc_ac_status == 1) /* AC adaptor on when attach */
    465  1.1  jruoho 			sc->lcd_index = sc->lcd_num -1; /* MAX Brightness */
    466  1.1  jruoho 		else
    467  1.1  jruoho 			sc->lcd_index = 3;
    468  1.1  jruoho 
    469  1.1  jruoho #ifdef ACPI_DEBUG
    470  1.1  jruoho 		pi = sc->lcd_level;
    471  1.1  jruoho 		printf("\t Full Power Level: %d\n", *pi);
    472  1.1  jruoho 		printf("\t on Battery Level: %d\n", *(pi+1));
    473  1.1  jruoho 		printf("\t Possible Level: ");
    474  1.1  jruoho 		for (i = 2;i < sc->lcd_num; i++)
    475  1.1  jruoho 			printf(" %d", *(pi+i));
    476  1.1  jruoho 		printf("\n");
    477  1.1  jruoho #endif
    478  1.1  jruoho 	}
    479  1.1  jruoho 
    480  1.1  jruoho 	if (buf.Pointer)
    481  1.1  jruoho 		ACPI_FREE(buf.Pointer);
    482  1.1  jruoho 	return (AE_OK);
    483  1.1  jruoho }
    484  1.1  jruoho 
    485  1.1  jruoho /*
    486  1.1  jruoho  * vald_acpi_libright_get:
    487  1.1  jruoho  *
    488  1.1  jruoho  *	Search node that have "_BCL" Method.
    489  1.1  jruoho  */
    490  1.1  jruoho static void
    491  1.1  jruoho vald_acpi_libright_get(struct vald_acpi_softc *sc)
    492  1.1  jruoho {
    493  1.1  jruoho 	ACPI_HANDLE parent;
    494  1.1  jruoho 	ACPI_STATUS rv;
    495  1.1  jruoho 
    496  1.1  jruoho 	aprint_verbose_dev(sc->sc_dev, "get LCD brightness via _BCL\n");
    497  1.1  jruoho 
    498  1.1  jruoho #ifdef ACPI_DEBUG
    499  1.1  jruoho 	printf("acpi_libright_get: start\n");
    500  1.1  jruoho #endif
    501  1.1  jruoho 	rv = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent);
    502  1.1  jruoho 	if (ACPI_FAILURE(rv))
    503  1.1  jruoho 		return;
    504  1.1  jruoho 
    505  1.1  jruoho 	AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100,
    506  1.1  jruoho 	    vald_acpi_libright_get_bus, NULL, sc, NULL);
    507  1.1  jruoho }
    508  1.1  jruoho 
    509  1.1  jruoho /*
    510  1.1  jruoho  * vald_acpi_libright_set:
    511  1.1  jruoho  *
    512  1.1  jruoho  *	Figure up next status and set it.
    513  1.1  jruoho  */
    514  1.1  jruoho static void
    515  1.1  jruoho vald_acpi_libright_set(struct vald_acpi_softc *sc, int UpDown)
    516  1.1  jruoho {
    517  1.3  jruoho 	uint32_t backlight, backlight_new, result, bright;
    518  1.1  jruoho 	ACPI_STATUS rv;
    519  1.1  jruoho 	int *pi;
    520  1.1  jruoho 
    521  1.1  jruoho 	/* Skip,if it does not support _BCL. */
    522  1.1  jruoho 	if (sc->lcd_handle == NULL)
    523  1.1  jruoho 		return;
    524  1.1  jruoho 
    525  1.1  jruoho 	/* Get LCD backlight status. */
    526  1.1  jruoho 	rv = vald_acpi_ghci_get(sc, GHCI_BACKLIGHT, &backlight, &result);
    527  1.1  jruoho 	if (ACPI_FAILURE(rv) || result != 0)
    528  1.1  jruoho 		return;
    529  1.1  jruoho 
    530  1.1  jruoho 	/* Figure up next status. */
    531  1.1  jruoho 	backlight_new = backlight;
    532  1.1  jruoho 	if (UpDown == LIBRIGHT_UP) {
    533  1.1  jruoho 		if (backlight == 1)
    534  1.1  jruoho 			sc->lcd_index++;
    535  1.1  jruoho 		else {
    536  1.1  jruoho 			/* backlight on */
    537  1.1  jruoho 			backlight_new = 1;
    538  1.1  jruoho 			sc->lcd_index = 2;
    539  1.1  jruoho 		}
    540  1.1  jruoho 	} else if (UpDown == LIBRIGHT_DOWN) {
    541  1.1  jruoho 		if ((backlight == 1) && (sc->lcd_index > 2))
    542  1.1  jruoho 			sc->lcd_index--;
    543  1.1  jruoho 		else {
    544  1.1  jruoho 			/* backlight off */
    545  1.1  jruoho 			backlight_new = 0;
    546  1.1  jruoho 			sc->lcd_index = 2;
    547  1.1  jruoho 		}
    548  1.1  jruoho 	}
    549  1.1  jruoho 
    550  1.1  jruoho 	/* Check index value. */
    551  1.1  jruoho 	if (sc->lcd_index < 2)
    552  1.1  jruoho 		sc->lcd_index = 2; /* index Minium Value */
    553  1.1  jruoho 	if (sc->lcd_index >= sc->lcd_num)
    554  1.1  jruoho 		sc->lcd_index = sc->lcd_num - 1;
    555  1.1  jruoho 
    556  1.1  jruoho 	/* Set LCD backlight,if status is changed. */
    557  1.1  jruoho 	if (backlight_new != backlight) {
    558  1.1  jruoho 		rv = vald_acpi_ghci_set(sc, GHCI_BACKLIGHT, backlight_new,
    559  1.1  jruoho 		    &result);
    560  1.1  jruoho 		if (ACPI_SUCCESS(rv) && result != 0)
    561  1.1  jruoho 			aprint_error_dev(sc->sc_dev, "can't set LCD backlight %s error=%x\n",
    562  1.1  jruoho 			    ((backlight_new == 1) ? "on" : "off"), result);
    563  1.1  jruoho 	}
    564  1.1  jruoho 
    565  1.1  jruoho 	if (backlight_new == 1) {
    566  1.1  jruoho 
    567  1.1  jruoho 		pi = sc->lcd_level;
    568  1.1  jruoho 		bright = *(pi + sc->lcd_index);
    569  1.1  jruoho 
    570  1.1  jruoho 		rv = vald_acpi_bcm_set(sc->lcd_handle, bright);
    571  1.1  jruoho 		if (ACPI_FAILURE(rv))
    572  1.1  jruoho 			aprint_error_dev(sc->sc_dev, "unable to evaluate _BCM: %s\n",
    573  1.1  jruoho 			    AcpiFormatException(rv));
    574  1.1  jruoho 	} else {
    575  1.1  jruoho 		bright = 0;
    576  1.1  jruoho 	}
    577  1.1  jruoho #ifdef ACPI_DEBUG
    578  1.1  jruoho 	printf("LCD bright");
    579  1.1  jruoho 	printf(" %s", ((UpDown == LIBRIGHT_UP) ? "up":""));
    580  1.1  jruoho 	printf("%s\n", ((UpDown == LIBRIGHT_DOWN) ? "down":""));
    581  1.1  jruoho 	printf("\t acpi_libright_set: Set brightness to %d%%\n", bright);
    582  1.1  jruoho #endif
    583  1.1  jruoho }
    584  1.1  jruoho 
    585  1.1  jruoho /*
    586  1.1  jruoho  * vald_acpi_video_switch:
    587  1.1  jruoho  *
    588  1.1  jruoho  *	Get video status(LCD/CRT) and set new video status.
    589  1.1  jruoho  */
    590  1.1  jruoho static void
    591  1.1  jruoho vald_acpi_video_switch(struct vald_acpi_softc *sc)
    592  1.1  jruoho {
    593  1.1  jruoho 	ACPI_STATUS	rv;
    594  1.3  jruoho 	uint32_t	value, result;
    595  1.1  jruoho 
    596  1.1  jruoho 	/* Get video status. */
    597  1.1  jruoho 	rv = vald_acpi_ghci_get(sc, GHCI_DISPLAY_DEVICE, &value, &result);
    598  1.1  jruoho 	if (ACPI_FAILURE(rv))
    599  1.1  jruoho 		return;
    600  1.1  jruoho 	if (result != 0) {
    601  1.1  jruoho 		aprint_error_dev(sc->sc_dev, "can't get video status  error=%x\n",
    602  1.1  jruoho 		    result);
    603  1.1  jruoho 		return;
    604  1.1  jruoho 	}
    605  1.1  jruoho 
    606  1.1  jruoho #ifdef ACPI_DEBUG
    607  1.1  jruoho 	printf("Toggle LCD/CRT\n");
    608  1.1  jruoho 	printf("\t Before switch, video status:   %s",
    609  1.1  jruoho 	    (((value & GHCI_LCD) == GHCI_LCD) ? "LCD" : ""));
    610  1.1  jruoho 	printf("%s\n", (((value & GHCI_CRT) == GHCI_CRT) ? "CRT": ""));
    611  1.1  jruoho #endif
    612  1.1  jruoho 
    613  1.1  jruoho 	/* Toggle LCD/CRT */
    614  1.1  jruoho 	if (value & GHCI_LCD) {
    615  1.1  jruoho 		value &= ~GHCI_LCD;
    616  1.1  jruoho 		value |= GHCI_CRT;
    617  1.1  jruoho 	} else if (value & GHCI_CRT){
    618  1.1  jruoho 		value &= ~GHCI_CRT;
    619  1.1  jruoho 		value |= GHCI_LCD;
    620  1.1  jruoho 	}
    621  1.1  jruoho 
    622  1.1  jruoho 	rv = vald_acpi_dssx_set(value);
    623  1.1  jruoho 	if (ACPI_FAILURE(rv))
    624  1.1  jruoho 		aprint_error_dev(sc->sc_dev, "unable to evaluate DSSX: %s\n",
    625  1.1  jruoho 		    AcpiFormatException(rv));
    626  1.1  jruoho 
    627  1.1  jruoho }
    628  1.1  jruoho 
    629  1.1  jruoho /*
    630  1.1  jruoho  * vald_acpi_bcm_set:
    631  1.1  jruoho  *
    632  1.1  jruoho  *	Set LCD brightness via "_BCM" Method.
    633  1.1  jruoho  */
    634  1.1  jruoho static ACPI_STATUS
    635  1.3  jruoho vald_acpi_bcm_set(ACPI_HANDLE handle, uint32_t bright)
    636  1.1  jruoho {
    637  1.1  jruoho 	ACPI_STATUS rv;
    638  1.1  jruoho 	ACPI_OBJECT Arg;
    639  1.1  jruoho 	ACPI_OBJECT_LIST ArgList;
    640  1.1  jruoho 
    641  1.1  jruoho 	ArgList.Count = 1;
    642  1.1  jruoho 	ArgList.Pointer = &Arg;
    643  1.1  jruoho 
    644  1.1  jruoho 	Arg.Type = ACPI_TYPE_INTEGER;
    645  1.1  jruoho 	Arg.Integer.Value = bright;
    646  1.1  jruoho 
    647  1.1  jruoho 	rv = AcpiEvaluateObject(handle, "_BCM", &ArgList, NULL);
    648  1.1  jruoho 	return (rv);
    649  1.1  jruoho }
    650  1.1  jruoho 
    651  1.1  jruoho /*
    652  1.1  jruoho  * vald_acpi_dssx_set:
    653  1.1  jruoho  *
    654  1.1  jruoho  *	Set value via "\\_SB_.VALX.DSSX" Method.
    655  1.1  jruoho  */
    656  1.1  jruoho static ACPI_STATUS
    657  1.3  jruoho vald_acpi_dssx_set(uint32_t value)
    658  1.1  jruoho {
    659  1.1  jruoho 	return acpi_eval_set_integer(NULL, "\\_SB_.VALX.DSSX", value);
    660  1.1  jruoho }
    661  1.1  jruoho 
    662  1.1  jruoho /*
    663  1.1  jruoho  * vald_acpi_fan_switch:
    664  1.1  jruoho  *
    665  1.1  jruoho  *	Get FAN status and set new FAN status.
    666  1.1  jruoho  */
    667  1.1  jruoho static void
    668  1.1  jruoho vald_acpi_fan_switch(struct vald_acpi_softc *sc)
    669  1.1  jruoho {
    670  1.1  jruoho 	ACPI_STATUS rv;
    671  1.3  jruoho 	uint32_t value, result;
    672  1.1  jruoho 
    673  1.1  jruoho 	/* Get FAN status */
    674  1.1  jruoho 	rv = vald_acpi_ghci_get(sc, GHCI_FAN, &value, &result);
    675  1.1  jruoho 	if (ACPI_FAILURE(rv))
    676  1.1  jruoho 		return;
    677  1.1  jruoho 	if (result != 0) {
    678  1.1  jruoho 		aprint_error_dev(sc->sc_dev, "can't get FAN status error=%d\n",
    679  1.1  jruoho 		    result);
    680  1.1  jruoho 		return;
    681  1.1  jruoho 	}
    682  1.1  jruoho 
    683  1.1  jruoho #ifdef ACPI_DEBUG
    684  1.1  jruoho 	printf("Toggle FAN on/off\n");
    685  1.1  jruoho 	printf("\t Before toggle, FAN status %s\n",
    686  1.1  jruoho 	    (value == GHCI_OFF ? "off" : "on"));
    687  1.1  jruoho #endif
    688  1.1  jruoho 
    689  1.1  jruoho 	/* Toggle FAN on/off */
    690  1.1  jruoho 	if (value == GHCI_OFF)
    691  1.1  jruoho 		value = GHCI_ON;
    692  1.1  jruoho 	else
    693  1.1  jruoho 		value = GHCI_OFF;
    694  1.1  jruoho 
    695  1.1  jruoho 	/* Set FAN new status. */
    696  1.1  jruoho 	rv = vald_acpi_ghci_set(sc, GHCI_FAN, value, &result);
    697  1.1  jruoho 	if (ACPI_FAILURE(rv))
    698  1.1  jruoho 		return;
    699  1.1  jruoho 	if (result != 0) {
    700  1.1  jruoho 		aprint_error_dev(sc->sc_dev, "can't set FAN status error=%d\n",
    701  1.1  jruoho 		    result);
    702  1.1  jruoho 		return;
    703  1.1  jruoho 	}
    704  1.1  jruoho 
    705  1.1  jruoho #ifdef ACPI_DEBUG
    706  1.1  jruoho 	printf("\t After toggle, FAN status %s\n",
    707  1.1  jruoho 	    (value == GHCI_OFF ? "off" : "on"));
    708  1.1  jruoho #endif
    709  1.1  jruoho }
    710