xref: /openbsd-src/sys/dev/acpi/acpitoshiba.c (revision 3b9d585e0ce86bc6eed0b4493f3c73d741778f91)
1*3b9d585eSjsg /* $OpenBSD: acpitoshiba.c,v 1.17 2024/04/13 23:44:11 jsg Exp $ */
2a1b92009Spirofti /*-
3a1b92009Spirofti  * Copyright (c) 2003 Hiroyuki Aizu <aizu@navi.org>
4a1b92009Spirofti  * All rights reserved.
5a1b92009Spirofti  *
6a1b92009Spirofti  * Redistribution and use in source and binary forms, with or without
7a1b92009Spirofti  * modification, are permitted provided that the following conditions
8a1b92009Spirofti  * are met:
9a1b92009Spirofti  * 1. Redistributions of source code must retain the above copyright
10a1b92009Spirofti  *    notice, this list of conditions and the following disclaimer.
11a1b92009Spirofti  * 2. Redistributions in binary form must reproduce the above copyright
12a1b92009Spirofti  *    notice, this list of conditions and the following disclaimer in the
13a1b92009Spirofti  *    documentation and/or other materials provided with the distribution.
14a1b92009Spirofti  *
15a1b92009Spirofti  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16a1b92009Spirofti  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17a1b92009Spirofti  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18a1b92009Spirofti  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19a1b92009Spirofti  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20a1b92009Spirofti  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21a1b92009Spirofti  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22a1b92009Spirofti  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23a1b92009Spirofti  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24a1b92009Spirofti  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25a1b92009Spirofti  * SUCH DAMAGE.
26a1b92009Spirofti  *
27a1b92009Spirofti  */
28a1b92009Spirofti #include <sys/param.h>
29a1b92009Spirofti #include <sys/systm.h>
30a1b92009Spirofti 
31a1b92009Spirofti #include <dev/acpi/acpivar.h>
32a1b92009Spirofti #include <dev/acpi/acpidev.h>
33a1b92009Spirofti #include <dev/acpi/amltypes.h>
34a1b92009Spirofti #include <dev/acpi/dsdt.h>
35a1b92009Spirofti 
36a1b92009Spirofti #include <machine/apmvar.h>
37a1b92009Spirofti #include <dev/wscons/wsconsio.h>
38d95a16b0Skettenis #include <dev/wscons/wsdisplayvar.h>
39a1b92009Spirofti 
40a1b92009Spirofti /*
41a1b92009Spirofti  * Toshiba HCI interface definitions
42a1b92009Spirofti  *
43a1b92009Spirofti  * HCI is Toshiba's "Hardware Control Interface" which is supposed to
44a1b92009Spirofti  * be uniform across all their models.	Ideally we would just call
45a1b92009Spirofti  * dedicated ACPI methods instead of using this primitive interface.
46a1b92009Spirofti  * However, the ACPI methods seem to be incomplete in some areas (for
47a1b92009Spirofti  * example they allow setting, but not reading, the LCD brightness
48a1b92009Spirofti  * value), so this is still useful.
49a1b92009Spirofti  */
50a1b92009Spirofti #define	METHOD_HCI			"GHCI"
51a1b92009Spirofti #define	METHOD_HCI_ENABLE		"ENAB"
52a1b92009Spirofti 
53a1b92009Spirofti /* Operations */
54a1b92009Spirofti #define	HCI_SET				0xFF00
55a1b92009Spirofti #define	HCI_GET				0xFE00
56a1b92009Spirofti 
57a1b92009Spirofti /* Functions */
58a1b92009Spirofti #define	HCI_REG_SYSTEM_EVENT		0x0016
59a1b92009Spirofti #define	HCI_REG_VIDEO_OUTPUT		0x001C
60a1b92009Spirofti #define	HCI_REG_LCD_BRIGHTNESS		0x002A
61a1b92009Spirofti 
62a1b92009Spirofti /* Field definitions */
63a1b92009Spirofti #define	HCI_LCD_BRIGHTNESS_BITS		3
64a1b92009Spirofti #define	HCI_LCD_BRIGHTNESS_SHIFT	(16 - HCI_LCD_BRIGHTNESS_BITS)
65a1b92009Spirofti #define	HCI_LCD_BRIGHTNESS_MAX		((1 << HCI_LCD_BRIGHTNESS_BITS) - 1)
66a1b92009Spirofti #define	HCI_LCD_BRIGHTNESS_MIN		0
67a1b92009Spirofti #define	HCI_VIDEO_OUTPUT_FLAG		0x0100
68a1b92009Spirofti #define	HCI_VIDEO_OUTPUT_CYCLE_MIN	0
69a1b92009Spirofti #define	HCI_VIDEO_OUTPUT_CYCLE_MAX	7
70a1b92009Spirofti 
71a1b92009Spirofti /* HCI register definitions */
72a1b92009Spirofti #define	HCI_WORDS			6 /* Number of register */
73a1b92009Spirofti #define	HCI_REG_AX			0 /* Operation, then return value */
74a1b92009Spirofti #define	HCI_REG_BX			1 /* Function */
75a1b92009Spirofti #define	HCI_REG_CX			2 /* Argument (in or out) */
76a1b92009Spirofti 
77a1b92009Spirofti /* Return codes */
78a1b92009Spirofti #define	HCI_FAILURE			-1
79a1b92009Spirofti #define	HCI_SUCCESS			0
80a1b92009Spirofti 
81a1b92009Spirofti /* Toshiba fn_keys events */
82aed231a4Sgiovanni #define	FN_KEY_SUSPEND			0x01BD
83aed231a4Sgiovanni #define	FN_KEY_HIBERNATE		0x01BE
84a1b92009Spirofti #define	FN_KEY_VIDEO_OUTPUT		0x01BF
85a1b92009Spirofti #define	FN_KEY_BRIGHTNESS_DOWN		0x01C0
86a1b92009Spirofti #define	FN_KEY_BRIGHTNESS_UP		0x01C1
87a1b92009Spirofti 
88a1b92009Spirofti struct acpitoshiba_softc {
89a1b92009Spirofti 	struct device		 sc_dev;
90a1b92009Spirofti 	struct acpi_softc	*sc_acpi;
91a1b92009Spirofti 	struct aml_node		*sc_devnode;
924aff7db4Skettenis 
934aff7db4Skettenis 	uint32_t		 sc_brightness;
94a1b92009Spirofti };
95a1b92009Spirofti 
96a1b92009Spirofti int	toshiba_enable_events(struct acpitoshiba_softc *);
97a1b92009Spirofti int	toshiba_read_events(struct acpitoshiba_softc *);
98a1b92009Spirofti int	toshiba_match(struct device *, void *, void *);
99a1b92009Spirofti void	toshiba_attach(struct device *, struct device *, void *);
100a1b92009Spirofti int	toshiba_hotkey(struct aml_node *, int, void *);
101d2eaebe9Skettenis int	toshiba_get_brightness(struct acpitoshiba_softc *, uint32_t *);
102d2eaebe9Skettenis int	toshiba_set_brightness(struct acpitoshiba_softc *, uint32_t *);
103d2eaebe9Skettenis int	toshiba_get_video_output(struct acpitoshiba_softc *, uint32_t *);
104d2eaebe9Skettenis int	toshiba_set_video_output(struct acpitoshiba_softc *, uint32_t *);
1054aff7db4Skettenis void	toshiba_update_brightness(void *, int);
106a1b92009Spirofti int	toshiba_fn_key_brightness_up(struct acpitoshiba_softc *);
107a1b92009Spirofti int	toshiba_fn_key_brightness_down(struct acpitoshiba_softc *);
108a1b92009Spirofti int	toshiba_fn_key_video_output(struct acpitoshiba_softc *);
109a1b92009Spirofti 
110a1b92009Spirofti /* wconsole hook functions */
111a1b92009Spirofti int	acpitoshiba_get_param(struct wsdisplay_param *);
112a1b92009Spirofti int	acpitoshiba_set_param(struct wsdisplay_param *);
113a1b92009Spirofti int	get_param_brightness(struct wsdisplay_param *);
114a1b92009Spirofti int	set_param_brightness(struct wsdisplay_param *);
115a1b92009Spirofti 
116471aeecfSnaddy const struct cfattach acpitoshiba_ca = {
117a1b92009Spirofti 	sizeof(struct acpitoshiba_softc), toshiba_match, toshiba_attach
118a1b92009Spirofti };
119a1b92009Spirofti 
120a1b92009Spirofti struct cfdriver acpitoshiba_cd = {
121a1b92009Spirofti 	NULL, "acpitoshiba", DV_DULL
122a1b92009Spirofti };
123a1b92009Spirofti 
124882e55bfSgiovanni const char *acpitoshiba_hids[] = {
1256bf9874fSjcs 	"TOS6200",	/* Libretto */
1266bf9874fSjcs 	"TOS6207",	/* Dynabook */
1276bf9874fSjcs 	"TOS6208",	/* SPA40 */
128128e94b2Smlarkin 	NULL
129882e55bfSgiovanni };
130882e55bfSgiovanni 
131a1b92009Spirofti int
get_param_brightness(struct wsdisplay_param * dp)132a1b92009Spirofti get_param_brightness(struct wsdisplay_param *dp)
133a1b92009Spirofti {
1344aff7db4Skettenis 	struct acpitoshiba_softc *sc = acpitoshiba_cd.cd_devs[0];
135a1b92009Spirofti 
136a1b92009Spirofti 	if (sc != NULL) {
137a1b92009Spirofti 		/* default settings */
138a1b92009Spirofti 		dp->min = HCI_LCD_BRIGHTNESS_MIN;
139a1b92009Spirofti 		dp->max = HCI_LCD_BRIGHTNESS_MAX;
1404aff7db4Skettenis 		dp->curval = sc->sc_brightness;
141a1b92009Spirofti 		return (0);
142a1b92009Spirofti 	}
143a1b92009Spirofti 
144a1b92009Spirofti 	return (1);
145a1b92009Spirofti }
146a1b92009Spirofti 
147a1b92009Spirofti int
acpitoshiba_get_param(struct wsdisplay_param * dp)148a1b92009Spirofti acpitoshiba_get_param(struct wsdisplay_param *dp)
149a1b92009Spirofti {
150a1b92009Spirofti 	int ret;
151a1b92009Spirofti 
152a1b92009Spirofti 	switch (dp->param) {
153a1b92009Spirofti 	case WSDISPLAYIO_PARAM_BRIGHTNESS:
154a1b92009Spirofti 		ret = get_param_brightness(dp);
155a1b92009Spirofti 		return (ret);
156a1b92009Spirofti 	default:
157a1b92009Spirofti 		return (1);
158a1b92009Spirofti 	}
159a1b92009Spirofti }
160a1b92009Spirofti 
161a1b92009Spirofti int
set_param_brightness(struct wsdisplay_param * dp)162a1b92009Spirofti set_param_brightness(struct wsdisplay_param *dp)
163a1b92009Spirofti {
1644aff7db4Skettenis 	struct acpitoshiba_softc *sc = acpitoshiba_cd.cd_devs[0];
165a1b92009Spirofti 
166a1b92009Spirofti 	if (sc != NULL) {
1674aff7db4Skettenis 		if (dp->curval < HCI_LCD_BRIGHTNESS_MIN)
1684aff7db4Skettenis 			dp->curval = HCI_LCD_BRIGHTNESS_MIN;
1694aff7db4Skettenis 		if (dp->curval > HCI_LCD_BRIGHTNESS_MAX)
1704aff7db4Skettenis 			dp->curval = HCI_LCD_BRIGHTNESS_MAX;
1714aff7db4Skettenis 		sc->sc_brightness = dp->curval;
1724aff7db4Skettenis 		acpi_addtask(sc->sc_acpi, toshiba_update_brightness, sc, 0);
1734aff7db4Skettenis 		acpi_wakeup(sc->sc_acpi);
174a1b92009Spirofti 		return (0);
175a1b92009Spirofti 	}
176a1b92009Spirofti 
177a1b92009Spirofti 	return (1);
178a1b92009Spirofti }
179a1b92009Spirofti 
180a1b92009Spirofti int
acpitoshiba_set_param(struct wsdisplay_param * dp)181a1b92009Spirofti acpitoshiba_set_param(struct wsdisplay_param *dp)
182a1b92009Spirofti {
183a1b92009Spirofti 	int ret;
184a1b92009Spirofti 
185a1b92009Spirofti 	switch (dp->param) {
186a1b92009Spirofti 	case WSDISPLAYIO_PARAM_BRIGHTNESS:
187a1b92009Spirofti 		ret = set_param_brightness(dp);
188a1b92009Spirofti 		return (ret);
189a1b92009Spirofti 	default:
190a1b92009Spirofti 		return (1);
191a1b92009Spirofti 	}
192a1b92009Spirofti }
193a1b92009Spirofti 
1944aff7db4Skettenis void
toshiba_update_brightness(void * arg0,int arg1)1954aff7db4Skettenis toshiba_update_brightness(void *arg0, int arg1)
196a1b92009Spirofti {
1974aff7db4Skettenis 	struct acpitoshiba_softc *sc = arg0;
198a1b92009Spirofti 
1994aff7db4Skettenis 	toshiba_set_brightness(sc, &sc->sc_brightness);
200a1b92009Spirofti }
201a1b92009Spirofti 
202a1b92009Spirofti int
toshiba_match(struct device * parent,void * match,void * aux)203a1b92009Spirofti toshiba_match(struct device *parent, void *match, void *aux)
204a1b92009Spirofti {
205a1b92009Spirofti 	struct acpi_attach_args *aa = aux;
206a1b92009Spirofti 	struct cfdata	      *cf = match;
207a1b92009Spirofti 
208882e55bfSgiovanni 	if (acpi_matchhids(aa, acpitoshiba_hids, cf->cf_driver->cd_name))
209882e55bfSgiovanni 		return (1);
210882e55bfSgiovanni 
211a1b92009Spirofti 	if (aa->aaa_name == NULL ||
212a1b92009Spirofti 	    strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
213a1b92009Spirofti 	    aa->aaa_table != NULL)
214a1b92009Spirofti 		return (0);
215a1b92009Spirofti 
216a1b92009Spirofti 	return (1);
217a1b92009Spirofti }
218a1b92009Spirofti 
219a1b92009Spirofti int
toshiba_enable_events(struct acpitoshiba_softc * sc)220a1b92009Spirofti toshiba_enable_events(struct acpitoshiba_softc *sc)
221a1b92009Spirofti {
222a1b92009Spirofti 	if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI_ENABLE,
223a1b92009Spirofti 		    0, NULL, NULL)) {
224a1b92009Spirofti 		printf("%s: couldn't toggle METHOD_HCI_ENABLE\n", DEVNAME(sc));
225a1b92009Spirofti 		return (HCI_FAILURE);
226a1b92009Spirofti 	}
227a1b92009Spirofti 
228a1b92009Spirofti 	return (HCI_SUCCESS);
229a1b92009Spirofti }
230a1b92009Spirofti 
231a1b92009Spirofti int
toshiba_read_events(struct acpitoshiba_softc * sc)232a1b92009Spirofti toshiba_read_events(struct acpitoshiba_softc *sc)
233a1b92009Spirofti {
234a1b92009Spirofti 	struct aml_value args[HCI_WORDS];
235a1b92009Spirofti 	struct aml_value res;
236a1b92009Spirofti 	int i, val;
237a1b92009Spirofti 
238a1b92009Spirofti 	bzero(args, sizeof(args));
239a1b92009Spirofti 	bzero(&res, sizeof(res));
240a1b92009Spirofti 
241a1b92009Spirofti 	for (i = 0; i < HCI_WORDS; ++i)
242a1b92009Spirofti 		args[i].type = AML_OBJTYPE_INTEGER;
243a1b92009Spirofti 
244a1b92009Spirofti 	args[HCI_REG_AX].v_integer = HCI_GET;
245a1b92009Spirofti 	args[HCI_REG_BX].v_integer = HCI_REG_SYSTEM_EVENT;
246a1b92009Spirofti 
247a1b92009Spirofti 	if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI,
248a1b92009Spirofti 		    i, args, &res)) {
249a1b92009Spirofti 		printf("%s: couldn't toggle METHOD_HCI\n", DEVNAME(sc));
250a1b92009Spirofti 		return (HCI_FAILURE);
251a1b92009Spirofti 	}
252a1b92009Spirofti 
253a1b92009Spirofti 	/*
254a1b92009Spirofti 	 * We receive a package type so we need to get the event
255a1b92009Spirofti 	 * value from the HCI_REG_CX.
256a1b92009Spirofti 	 */
257a1b92009Spirofti 	val = aml_val2int(res.v_package[HCI_REG_CX]);
258a1b92009Spirofti 	aml_freevalue(&res);
259a1b92009Spirofti 
260a1b92009Spirofti 	return (val);
261a1b92009Spirofti }
262a1b92009Spirofti 
263a1b92009Spirofti void
toshiba_attach(struct device * parent,struct device * self,void * aux)264a1b92009Spirofti toshiba_attach(struct device *parent, struct device *self, void *aux)
265a1b92009Spirofti {
266a1b92009Spirofti 	struct acpitoshiba_softc *sc = (struct acpitoshiba_softc *)self;
267a1b92009Spirofti 	struct acpi_attach_args *aa = aux;
268a1b92009Spirofti 	int ret;
269a1b92009Spirofti 
270a1b92009Spirofti 	sc->sc_acpi = (struct acpi_softc *)parent;
271a1b92009Spirofti 	sc->sc_devnode = aa->aaa_node;
272a1b92009Spirofti 
273a1b92009Spirofti 	printf("\n");
274a1b92009Spirofti 
275a1b92009Spirofti 	/* enable events and hotkeys */
276a1b92009Spirofti 	ret = toshiba_enable_events(sc);
277a1b92009Spirofti 	if (ret != HCI_FAILURE) {
278a1b92009Spirofti 		/* Run toshiba_hotkey on button presses */
279a1b92009Spirofti 		aml_register_notify(sc->sc_devnode, aa->aaa_dev,
280a1b92009Spirofti 				toshiba_hotkey, sc, ACPIDEV_NOPOLL);
2814aff7db4Skettenis 	}
282a1b92009Spirofti 
2834aff7db4Skettenis 	ret = toshiba_get_brightness(sc, &sc->sc_brightness);
2844aff7db4Skettenis 	if (ret != HCI_FAILURE) {
285a1b92009Spirofti 		/* wsconsctl purpose */
286a1b92009Spirofti 		ws_get_param = acpitoshiba_get_param;
287a1b92009Spirofti 		ws_set_param = acpitoshiba_set_param;
288a1b92009Spirofti 	}
289a1b92009Spirofti }
290a1b92009Spirofti 
291a1b92009Spirofti int
toshiba_fn_key_brightness_up(struct acpitoshiba_softc * sc)292a1b92009Spirofti toshiba_fn_key_brightness_up(struct acpitoshiba_softc *sc)
293a1b92009Spirofti {
294d2eaebe9Skettenis 	uint32_t brightness_level;
295a1b92009Spirofti 	int ret;
296a1b92009Spirofti 
297a1b92009Spirofti 	ret = toshiba_get_brightness(sc, &brightness_level);
298a1b92009Spirofti 	if (ret != HCI_FAILURE) {
299a1b92009Spirofti 
300a1b92009Spirofti 		if (brightness_level++ == HCI_LCD_BRIGHTNESS_MAX)
301a1b92009Spirofti 			brightness_level = HCI_LCD_BRIGHTNESS_MAX;
302a1b92009Spirofti 		else
303a1b92009Spirofti 			ret = toshiba_set_brightness(sc, &brightness_level);
304a1b92009Spirofti 	}
305a1b92009Spirofti 
306a1b92009Spirofti 	return (ret);
307a1b92009Spirofti }
308a1b92009Spirofti 
309a1b92009Spirofti int
toshiba_fn_key_brightness_down(struct acpitoshiba_softc * sc)310a1b92009Spirofti toshiba_fn_key_brightness_down(struct acpitoshiba_softc *sc)
311a1b92009Spirofti {
312d2eaebe9Skettenis 	uint32_t brightness_level;
313a1b92009Spirofti 	int ret;
314a1b92009Spirofti 
315a1b92009Spirofti 	ret = toshiba_get_brightness(sc, &brightness_level);
316a1b92009Spirofti 	if (ret != HCI_FAILURE) {
317a1b92009Spirofti 		if (brightness_level-- == HCI_LCD_BRIGHTNESS_MIN)
318a1b92009Spirofti 			brightness_level = HCI_LCD_BRIGHTNESS_MIN;
319a1b92009Spirofti 		else
320a1b92009Spirofti 			ret = toshiba_set_brightness(sc, &brightness_level);
321a1b92009Spirofti 	}
322a1b92009Spirofti 
323a1b92009Spirofti 	return (ret);
324a1b92009Spirofti }
325a1b92009Spirofti 
326a1b92009Spirofti int
toshiba_fn_key_video_output(struct acpitoshiba_softc * sc)327a1b92009Spirofti toshiba_fn_key_video_output(struct acpitoshiba_softc *sc)
328a1b92009Spirofti {
329d2eaebe9Skettenis 	uint32_t video_output;
330a1b92009Spirofti 	int ret;
331a1b92009Spirofti 
332a1b92009Spirofti 	ret = toshiba_get_video_output(sc, &video_output);
333a1b92009Spirofti 	if (ret != HCI_FAILURE) {
334a1b92009Spirofti 		video_output = (video_output + 1) % HCI_VIDEO_OUTPUT_CYCLE_MAX;
335a1b92009Spirofti 
336a1b92009Spirofti 		ret = toshiba_set_video_output(sc, &video_output);
337a1b92009Spirofti 	}
338a1b92009Spirofti 
339a1b92009Spirofti 	return (ret);
340a1b92009Spirofti }
341a1b92009Spirofti 
342a1b92009Spirofti int
toshiba_hotkey(struct aml_node * node,int notify,void * arg)343a1b92009Spirofti toshiba_hotkey(struct aml_node *node, int notify, void *arg)
344a1b92009Spirofti {
345a1b92009Spirofti 	struct acpitoshiba_softc *sc = arg;
3468a66542aSbluhm 	int event, ret = HCI_FAILURE;
347a1b92009Spirofti 
348a1b92009Spirofti 	event = toshiba_read_events(sc);
349a1b92009Spirofti 	if (!event)
350a1b92009Spirofti 		return (0);
351a1b92009Spirofti 
352a1b92009Spirofti 	switch (event) {
353a1b92009Spirofti 	case FN_KEY_BRIGHTNESS_UP:
354a1b92009Spirofti 		/* Increase brightness */
355a1b92009Spirofti 		ret = toshiba_fn_key_brightness_up(sc);
356a1b92009Spirofti 		break;
357a1b92009Spirofti 	case FN_KEY_BRIGHTNESS_DOWN:
358a1b92009Spirofti 		/* Decrease brightness */
359a1b92009Spirofti 		ret = toshiba_fn_key_brightness_down(sc);
360a1b92009Spirofti 		break;
361aed231a4Sgiovanni 	case FN_KEY_SUSPEND:
362aed231a4Sgiovanni #ifndef SMALL_KERNEL
363aed231a4Sgiovanni 		if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ)) {
364aed231a4Sgiovanni 			acpi_addtask(sc->sc_acpi, acpi_sleep_task,
365ad814436Sderaadt 			    sc->sc_acpi, SLEEP_SUSPEND);
366aed231a4Sgiovanni 			ret = HCI_SUCCESS;
367aed231a4Sgiovanni 		}
368aed231a4Sgiovanni #endif
369aed231a4Sgiovanni 		break;
370aed231a4Sgiovanni 	case FN_KEY_HIBERNATE:
371aed231a4Sgiovanni #if defined(HIBERNATE) && !defined(SMALL_KERNEL)
372aed231a4Sgiovanni 		if (acpi_record_event(sc->sc_acpi, APM_USER_HIBERNATE_REQ)) {
373aed231a4Sgiovanni 			acpi_addtask(sc->sc_acpi, acpi_sleep_task,
374ad814436Sderaadt 			    sc->sc_acpi, SLEEP_HIBERNATE);
375aed231a4Sgiovanni 			ret = HCI_SUCCESS;
376aed231a4Sgiovanni 		}
377aed231a4Sgiovanni #endif
378aed231a4Sgiovanni 		break;
379a1b92009Spirofti 	case FN_KEY_VIDEO_OUTPUT:
380a1b92009Spirofti 		/* Cycle through video outputs. */
381a1b92009Spirofti 		ret = toshiba_fn_key_video_output(sc);
382a1b92009Spirofti 		break;
383a1b92009Spirofti 	default:
384a1b92009Spirofti 		break;
385a1b92009Spirofti 	}
386a1b92009Spirofti 
387a1b92009Spirofti 	if (ret != HCI_SUCCESS)
388a1b92009Spirofti 		return (1);
389a1b92009Spirofti 
390a1b92009Spirofti 	return (0);
391a1b92009Spirofti }
392a1b92009Spirofti 
393a1b92009Spirofti int
toshiba_set_brightness(struct acpitoshiba_softc * sc,uint32_t * brightness)394d2eaebe9Skettenis toshiba_set_brightness(struct acpitoshiba_softc *sc, uint32_t *brightness)
395a1b92009Spirofti {
396a1b92009Spirofti 	struct aml_value args[HCI_WORDS];
397a1b92009Spirofti 	int i;
398a1b92009Spirofti 
399a1b92009Spirofti 	bzero(args, sizeof(args));
400a1b92009Spirofti 
401a1b92009Spirofti 	for (i = 0; i < HCI_WORDS; ++i)
402a1b92009Spirofti 		args[i].type = AML_OBJTYPE_INTEGER;
403a1b92009Spirofti 
404a1b92009Spirofti 	if ((*brightness < HCI_LCD_BRIGHTNESS_MIN) ||
405a1b92009Spirofti 	    (*brightness > HCI_LCD_BRIGHTNESS_MAX))
406a1b92009Spirofti 		return (HCI_FAILURE);
407a1b92009Spirofti 
408a1b92009Spirofti 	*brightness <<= HCI_LCD_BRIGHTNESS_SHIFT;
409a1b92009Spirofti 
410a1b92009Spirofti 	args[HCI_REG_AX].v_integer = HCI_SET;
411a1b92009Spirofti 	args[HCI_REG_BX].v_integer = HCI_REG_LCD_BRIGHTNESS;
412a1b92009Spirofti 	args[HCI_REG_CX].v_integer = *brightness;
413a1b92009Spirofti 
414a1b92009Spirofti 	if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI,
415a1b92009Spirofti 	    i, args, NULL)) {
416a1b92009Spirofti 		printf("%s: set brightness failed\n", DEVNAME(sc));
417a1b92009Spirofti 		return (HCI_FAILURE);
418a1b92009Spirofti 	}
419a1b92009Spirofti 
4204aff7db4Skettenis 	sc->sc_brightness = *brightness;
421a1b92009Spirofti 	return (HCI_SUCCESS);
422a1b92009Spirofti }
423a1b92009Spirofti 
424a1b92009Spirofti int
toshiba_get_brightness(struct acpitoshiba_softc * sc,uint32_t * brightness)425d2eaebe9Skettenis toshiba_get_brightness(struct acpitoshiba_softc *sc, uint32_t *brightness)
426a1b92009Spirofti {
427a1b92009Spirofti 	struct aml_value args[HCI_WORDS];
428a1b92009Spirofti 	struct aml_value res;
429a1b92009Spirofti 	int i;
430a1b92009Spirofti 
431a1b92009Spirofti 	bzero(args, sizeof(args));
432a1b92009Spirofti 	bzero(&res, sizeof(res));
433a1b92009Spirofti 
434a1b92009Spirofti 	for (i = 0; i < HCI_WORDS; ++i)
435a1b92009Spirofti 		args[i].type = AML_OBJTYPE_INTEGER;
436a1b92009Spirofti 
437a1b92009Spirofti 	args[HCI_REG_AX].v_integer = HCI_GET;
438a1b92009Spirofti 	args[HCI_REG_BX].v_integer = HCI_REG_LCD_BRIGHTNESS;
439a1b92009Spirofti 
440a1b92009Spirofti 	if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI,
441a1b92009Spirofti 	    i, args, &res)) {
442a1b92009Spirofti 		printf("%s: get brightness failed\n", DEVNAME(sc));
443a1b92009Spirofti 		return (HCI_FAILURE);
444a1b92009Spirofti 	}
445a1b92009Spirofti 
446a1b92009Spirofti 	/*
447a1b92009Spirofti 	 * We receive a package type so we need to get the event
448a1b92009Spirofti 	 * value from the HCI_REG_CX.
449a1b92009Spirofti 	 */
450a1b92009Spirofti 	*brightness = aml_val2int(res.v_package[HCI_REG_CX]);
451a1b92009Spirofti 
452a1b92009Spirofti 	*brightness >>= HCI_LCD_BRIGHTNESS_SHIFT;
453a1b92009Spirofti 
454a1b92009Spirofti 	aml_freevalue(&res);
455a1b92009Spirofti 
456a1b92009Spirofti 	return (HCI_SUCCESS);
457a1b92009Spirofti }
458a1b92009Spirofti 
459a1b92009Spirofti int
toshiba_get_video_output(struct acpitoshiba_softc * sc,uint32_t * video_output)460d2eaebe9Skettenis toshiba_get_video_output(struct acpitoshiba_softc *sc, uint32_t *video_output)
461a1b92009Spirofti {
462a1b92009Spirofti 	struct aml_value res, args[HCI_WORDS];
463a1b92009Spirofti 	int i;
464a1b92009Spirofti 
465a1b92009Spirofti 	bzero(args, sizeof(args));
466a1b92009Spirofti 	bzero(&res, sizeof(res));
467a1b92009Spirofti 
468a1b92009Spirofti 	for (i = 0; i < HCI_WORDS; ++i)
469a1b92009Spirofti 		args[i].type = AML_OBJTYPE_INTEGER;
470a1b92009Spirofti 
471a1b92009Spirofti 	args[HCI_REG_AX].v_integer = HCI_GET;
472a1b92009Spirofti 	args[HCI_REG_BX].v_integer = HCI_REG_VIDEO_OUTPUT;
473a1b92009Spirofti 
474a1b92009Spirofti 	if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI,
475a1b92009Spirofti 	    i, args, &res)) {
476a1b92009Spirofti 		printf("%s: get video output failed\n", DEVNAME(sc));
477a1b92009Spirofti 		return (HCI_FAILURE);
478a1b92009Spirofti 	}
479a1b92009Spirofti 
480a1b92009Spirofti 	/*
481a1b92009Spirofti 	 * We receive a package type so we need to get the event
482a1b92009Spirofti 	 * value from the HCI_REG_CX.
483a1b92009Spirofti 	 */
484a1b92009Spirofti 	*video_output = aml_val2int(res.v_package[HCI_REG_CX]);
485a1b92009Spirofti 
486a1b92009Spirofti 	*video_output &= 0xff;
487a1b92009Spirofti 
488a1b92009Spirofti 	aml_freevalue(&res);
489a1b92009Spirofti 
490a1b92009Spirofti 	return (HCI_SUCCESS);
491a1b92009Spirofti }
492a1b92009Spirofti 
493a1b92009Spirofti int
toshiba_set_video_output(struct acpitoshiba_softc * sc,uint32_t * video_output)494d2eaebe9Skettenis toshiba_set_video_output(struct acpitoshiba_softc *sc, uint32_t *video_output)
495a1b92009Spirofti {
496a1b92009Spirofti 	struct aml_value args[HCI_WORDS];
497a1b92009Spirofti 	int i;
498a1b92009Spirofti 
499a1b92009Spirofti 	bzero(args, sizeof(args));
500a1b92009Spirofti 
501a1b92009Spirofti 	if ((*video_output < HCI_VIDEO_OUTPUT_CYCLE_MIN) ||
502a1b92009Spirofti 	    (*video_output > HCI_VIDEO_OUTPUT_CYCLE_MAX))
503a1b92009Spirofti 		return (HCI_FAILURE);
504a1b92009Spirofti 
505a1b92009Spirofti 	*video_output |= HCI_VIDEO_OUTPUT_FLAG;
506a1b92009Spirofti 
507a1b92009Spirofti 	for (i = 0; i < HCI_WORDS; ++i)
508a1b92009Spirofti 		args[i].type = AML_OBJTYPE_INTEGER;
509a1b92009Spirofti 
510a1b92009Spirofti 	args[HCI_REG_AX].v_integer = HCI_SET;
511a1b92009Spirofti 	args[HCI_REG_BX].v_integer = HCI_REG_VIDEO_OUTPUT;
512a1b92009Spirofti 	args[HCI_REG_CX].v_integer = *video_output;
513a1b92009Spirofti 
514a1b92009Spirofti 	if (aml_evalname(sc->sc_acpi, sc->sc_devnode, METHOD_HCI,
515a1b92009Spirofti 	    i, args, NULL)) {
516a1b92009Spirofti 		printf("%s: set video output failed\n", DEVNAME(sc));
517a1b92009Spirofti 		return (HCI_FAILURE);
518a1b92009Spirofti 	}
519a1b92009Spirofti 
520a1b92009Spirofti 	return (HCI_SUCCESS);
521a1b92009Spirofti }
522