1 | /* $NetBSD: valz_acpi.c,v 1.7 2015/10/05 15:57:50 christos 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 VALZ Driver for Toshiba dynabook R63/PS |
67 | * This driver is based on vald_acpi.c |
68 | */ |
69 | |
70 | /* |
71 | * Obtain information of Toshiba "GHCI" Method from next URL. |
72 | * http://www.buzzard.me.uk/toshiba/docs.html |
73 | * http://memebeam.org/toys/ToshibaAcpiDriver |
74 | */ |
75 | |
76 | #include <sys/cdefs.h> |
77 | __KERNEL_RCSID(0, "$NetBSD: valz_acpi.c,v 1.7 2015/10/05 15:57:50 christos 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 ("valz_acpi" ) |
89 | |
90 | #define METHOD_HCI "GHCI" |
91 | #define METHOD_HCI_ENABLE "ENAB" |
92 | |
93 | /* Operations */ |
94 | /* Get */ |
95 | #define HCI_GET 0xfe00 |
96 | #define SCI_CHECK 0xf000 |
97 | #define SCI_GET 0xf300 |
98 | |
99 | /* Set */ |
100 | #define HCI_SET 0xff00 |
101 | #define SCI_OPEN 0xf100 |
102 | #define SCI_CLOSE 0xf200 |
103 | #define SCI_SET 0xf400 |
104 | |
105 | /* Return codes */ |
106 | #define HCI_SUCCESS 0x0000 |
107 | #define HCI_FAILURE 0x1000 |
108 | #define HCI_NOT_SUPPORTED 0x8000 |
109 | #define HCI_INPUT_ERROR 0x8300 |
110 | #define HCI_FIFO_EMPTY 0x8c00 |
111 | |
112 | #define SCI_OPENCLOSE_OK 0x0044 |
113 | #define SCI_NOT_SUPPORTED 0x8000 |
114 | #define SCI_ALREADY_OPEN 0x8100 |
115 | #define SCI_NOT_OPEN 0x8200 |
116 | #define SCI_NOT_PRESENT 0x8600 |
117 | |
118 | /* Functions */ |
119 | #define HCI_LCD_BACKLIGHT 0x0002 |
120 | #define HCI_ACADAPTOR 0x0003 |
121 | #define HCI_SYSTEM_EVENT_FIFO 0x0016 |
122 | #define HCI_KBD_BACKLIGHT 0x0017 |
123 | #define HCI_DISPLAY_DEV 0x001c |
124 | #define HCI_HOTKEY_EVENT 0x001e |
125 | #define HCI_LCD_BRIGHTNESS 0x002a |
126 | #define HCI_CPU_SPEED 0x0032 |
127 | |
128 | #define SCI_USB_OFF_CHARGE 0x0150 |
129 | #define SCI_TOUCHPAD 0x050e |
130 | #define SCI_KBD_BACKLIGHT_STS 0x015c |
131 | #define SCI_KBD_BACKLIGHT 0x0095 |
132 | |
133 | #define SCI_KBD_BL_TIME_SHIFT 0x10 |
134 | |
135 | /* Field definitions */ |
136 | #define HCI_LCD_BRIGHTNESS_BITS 3 |
137 | #define HCI_LCD_BRIGHTNESS_SFT (16 - HCI_LCD_BRIGHTNESS_BITS) |
138 | #define HCI_LCD_BRIGHTNESS_MIN 0 |
139 | #define HCI_LCD_BRIGHTNESS_MAX 7 |
140 | #define HCI_VIDEO_DEVICE_FLG 0x0100 |
141 | #define HCI_CPU_SPEED_BITS 3 |
142 | #define HCI_CPU_SPEED_SFT (16 - HCI_CPU_SPEED_BITS) |
143 | #define HCI_CPU_SPEED_MAX ((1 << HCI_CPU_SPEED_BITS) - 1) |
144 | |
145 | /* Key press/release events */ |
146 | |
147 | /* Key press/release events */ |
148 | #define FN_RELEASE_OFFSET 0x80 |
149 | # if 0 |
150 | /* Not used */ |
151 | #define FN_PRESS 0x01ff |
152 | #define FN_RELEASE 0x0100 |
153 | # endif |
154 | #define FN_ESC_PRESS 0x0101 |
155 | #define FN_ESC_RELEASE (FN_ESC_PRESS + FN_RELEASE_OFFSET) |
156 | #define FN_F1_PRESS 0x013b |
157 | #define FN_F1_RELEASE (FN_F1_PRESS + FN_RELEASE_OFFSET) |
158 | #define FN_F2_PRESS 0x013c |
159 | #define FN_F2_RELEASE (FN_F2_PRESS + FN_RELEASE_OFFSET) |
160 | #define FN_F3_PRESS 0x013d |
161 | #define FN_F3_RELEASE (FN_F3_PRESS + FN_RELEASE_OFFSET) |
162 | #define FN_F4_PRESS 0x013e |
163 | #define FN_F4_RELEASE (FN_F4_PRESS + FN_RELEASE_OFFSET) |
164 | #define FN_F5_PRESS 0x013f |
165 | #define FN_F5_RELEASE (FN_F5_PRESS + FN_RELEASE_OFFSET) |
166 | #define FN_F6_PRESS 0x0140 |
167 | #define FN_F6_RELEASE (FN_F6_PRESS + FN_RELEASE_OFFSET) |
168 | #define FN_F7_PRESS 0x0141 |
169 | #define FN_F7_RELEASE (FN_F7_PRESS + FN_RELEASE_OFFSET) |
170 | #define FN_F8_PRESS 0x0142 |
171 | #define FN_F8_RELEASE (FN_F8_PRESS + FN_RELEASE_OFFSET) |
172 | #define FN_F9_PRESS 0x0143 |
173 | #define FN_F9_RELEASE (FN_F9_PRESS + FN_RELEASE_OFFSET) |
174 | /* Toggle, they are controlled by hardware */ |
175 | #define FN_F10_ON 0x1bb0 |
176 | #define FN_F10_OFF 0x1bb1 |
177 | #define FN_F11_ON 0x1bb2 |
178 | #define FN_F11_OFF 0x1bb3 |
179 | /* Fn+F12 does not emit keycode */ |
180 | /* dynabook R63/PS does not have KANJI keytop print */ |
181 | #define FN_KNJ_PRESS 0x0129 |
182 | #define FN_KNJ_RELEASE (FN_KNJ_PRESS + FN_RELEASE_OFFSET) |
183 | #define FN_1_PRESS 0x0102 |
184 | #define FN_1_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) |
185 | #define FN_2_PRESS 0x0103 |
186 | #define FN_2_RELEASE (FN_2_PRESS + FN_RELEASE_OFFSET) |
187 | /* Fn+3 and Fn+4 do not emit keybode */ |
188 | #define FN_Z_PRESS 0x012c |
189 | #define FN_Z_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) |
190 | #define FN_SPACE_PRESS 0x0139 |
191 | #define FN_SPACE_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) |
192 | #define FN_TAB_PRESS 0x010f |
193 | #define FN_TAB_RELEASE (FN_TAB_PRESS + FN_RELEASE_OFFSET) |
194 | #define FN_CAPS_PRESS 0x013a |
195 | #define FN_CAPS_RELEASE (FN_CAPS_PRESS + FN_RELEASE_OFFSET) |
196 | #define FN_BACKSPACE_PRESS 0x010e |
197 | #define FN_BACKSPACE_RELEASE (FN_BACKSPACE_PRESS + FN_RELEASE_OFFSET) |
198 | #define FN_INS_PRESS 0x0152 |
199 | #define FN_INS_RELEASE (FN_INS_PRESS + FN_RELEASE_OFFSET) |
200 | #define FN_DEL_PRESS 0x0153 |
201 | #define FN_DEL_RELEASE (FN_DEL_PRESS + FN_RELEASE_OFFSET) |
202 | #define FN_PRTSC_PRESS 0x0137 |
203 | #define FN_PRTSC_RELEASE (FN_PRTSC_PRESS + FN_RELEASE_OFFSET) |
204 | |
205 | /* HCI register definitions */ |
206 | #define HCI_WORDS 6 /* number of registers */ |
207 | #define HCI_REG_AX 0 /* Operation -> return value */ |
208 | #define HCI_REG_BX 1 /* Function */ |
209 | #define HCI_REG_CX 2 /* Argument (in or out) */ |
210 | #define HCI_REG_DX 3 /* unused */ |
211 | #define HCI_REG_SI 4 /* unused */ |
212 | #define HCI_REG_DI 5 /* unused */ |
213 | |
214 | #define HCI_ON 0x0001 |
215 | #define HCI_OFF 0x0000 |
216 | #define HCI_ENABLE 0x0001 |
217 | #define HCI_DISABLE 0x0000 |
218 | |
219 | #define HCI_LCD 0x1 |
220 | #define HCI_CRT 0x2 |
221 | #define HCI_TV 0x4 |
222 | |
223 | #define SCI_KBD_BL_MODE_MASK 0x1f |
224 | #define SCI_KBD_BL_TIMO_SFT 0x10 |
225 | #define SCI_KBD_BL_MODE_AUTO 0x2 |
226 | #define SCI_KBD_BL_MODE_ON 0x8 |
227 | #define SCI_KBD_BL_MODE_OFF 0x10 |
228 | |
229 | struct valz_acpi_softc { |
230 | device_t sc_dev; /* base device glue */ |
231 | struct acpi_devnode *sc_node; /* our ACPI devnode */ |
232 | }; |
233 | |
234 | static const char * const valz_acpi_hids[] = { |
235 | "TOS6208" , |
236 | NULL |
237 | }; |
238 | |
239 | static int valz_acpi_match(device_t, cfdata_t, void *); |
240 | static void valz_acpi_attach(device_t, device_t, void *); |
241 | |
242 | static void valz_acpi_event(void *); |
243 | static void valz_acpi_notify_handler(ACPI_HANDLE, uint32_t, void *); |
244 | |
245 | #define ACPI_NOTIFY_ValzHotkeyPressed 0x80 |
246 | #define ACPI_NOTIFY_ValzLidClosed 0x8f |
247 | #define ACPI_NOTIFY_ValzKbdBLChanges 0x92 |
248 | |
249 | /* HCI manipulation */ |
250 | static ACPI_STATUS hci_op(struct valz_acpi_softc *, |
251 | uint32_t *, uint32_t *); |
252 | static ACPI_STATUS valz_acpi_hci_get(struct valz_acpi_softc *, uint32_t, |
253 | uint32_t, uint32_t *, uint32_t *); |
254 | static ACPI_STATUS valz_acpi_hci_set(struct valz_acpi_softc *, uint32_t, |
255 | uint32_t, uint32_t, uint32_t *); |
256 | |
257 | static ACPI_STATUS sci_open(struct valz_acpi_softc *); |
258 | static ACPI_STATUS sci_close(struct valz_acpi_softc *); |
259 | |
260 | static ACPI_STATUS valz_acpi_touchpad_toggle(struct valz_acpi_softc *); |
261 | static ACPI_STATUS valz_acpi_lcd_backlight_toggle( |
262 | struct valz_acpi_softc *sc); |
263 | |
264 | CFATTACH_DECL_NEW(valz_acpi, sizeof(struct valz_acpi_softc), |
265 | valz_acpi_match, valz_acpi_attach, NULL, NULL); |
266 | |
267 | /* |
268 | * valz_acpi_match: |
269 | * |
270 | * Autoconfiguration `match' routine. |
271 | */ |
272 | static int |
273 | valz_acpi_match(device_t parent, cfdata_t match, void *aux) |
274 | { |
275 | struct acpi_attach_args *aa = aux; |
276 | |
277 | if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) |
278 | return (0); |
279 | |
280 | return (acpi_match_hid(aa->aa_node->ad_devinfo, valz_acpi_hids)); |
281 | } |
282 | |
283 | /* |
284 | * valz_acpi_attach: |
285 | * |
286 | * Autoconfiguration `attach' routine. |
287 | */ |
288 | static void |
289 | valz_acpi_attach(device_t parent, device_t self, void *aux) |
290 | { |
291 | struct valz_acpi_softc *sc = device_private(self); |
292 | struct acpi_attach_args *aa = aux; |
293 | ACPI_STATUS rv; |
294 | |
295 | aprint_naive(": Toshiba VALZ\n" ); |
296 | aprint_normal(": Toshiba VALZ\n" ); |
297 | |
298 | sc->sc_node = aa->aa_node; |
299 | sc->sc_dev = self; |
300 | |
301 | /* enable valz notify */ |
302 | rv = AcpiEvaluateObject(sc->sc_node->ad_handle, METHOD_HCI_ENABLE, |
303 | NULL, NULL); |
304 | if (ACPI_FAILURE(rv)) { |
305 | aprint_error("Cannot enable VALZ.\n" ); |
306 | } else { |
307 | (void)acpi_register_notify(sc->sc_node, |
308 | valz_acpi_notify_handler); |
309 | } |
310 | } |
311 | |
312 | /* |
313 | * valz_acpi_notify_handler: |
314 | * |
315 | * Notify handler. |
316 | */ |
317 | static void |
318 | valz_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) |
319 | { |
320 | struct valz_acpi_softc *sc; |
321 | device_t self = context; |
322 | |
323 | sc = device_private(self); |
324 | |
325 | switch (notify) { |
326 | case ACPI_NOTIFY_ValzHotkeyPressed: |
327 | (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, valz_acpi_event, sc); |
328 | break; |
329 | |
330 | case ACPI_NOTIFY_ValzLidClosed: |
331 | /* Lid closed */ |
332 | break; |
333 | |
334 | case ACPI_NOTIFY_ValzKbdBLChanges: |
335 | /* Keyboard backlight mode changed */ |
336 | break; |
337 | |
338 | default: |
339 | aprint_error_dev(sc->sc_dev, |
340 | "unknown notify 0x%02X\n" , notify); |
341 | break; |
342 | } |
343 | } |
344 | |
345 | /* |
346 | * valz_acpi_event: |
347 | * |
348 | * Check hotkey event and do it, if event occur. |
349 | */ |
350 | static void |
351 | valz_acpi_event(void *arg) |
352 | { |
353 | struct valz_acpi_softc *sc = arg; |
354 | ACPI_STATUS rv; |
355 | uint32_t value, result; |
356 | |
357 | for (;;) { |
358 | rv = valz_acpi_hci_get(sc, HCI_GET, HCI_SYSTEM_EVENT_FIFO, |
359 | &value, &result); |
360 | if (ACPI_SUCCESS(rv) && result == 0) { |
361 | switch (value) { |
362 | case FN_F9_PRESS: |
363 | valz_acpi_touchpad_toggle(sc); |
364 | break; |
365 | case FN_TAB_PRESS: |
366 | valz_acpi_lcd_backlight_toggle(sc); |
367 | break; |
368 | |
369 | default: |
370 | /* Many unused buttons */ |
371 | aprint_debug("Pressed: 0x%x\n" , value); |
372 | break; |
373 | } |
374 | } |
375 | if (ACPI_FAILURE(rv) || result == HCI_NOT_SUPPORTED || |
376 | result == HCI_FIFO_EMPTY) |
377 | break; |
378 | } |
379 | } |
380 | |
381 | /* |
382 | * HCI/SCI operation |
383 | */ |
384 | static ACPI_STATUS |
385 | hci_op(struct valz_acpi_softc *sc, uint32_t *input, uint32_t *output) |
386 | { |
387 | ACPI_STATUS rv; |
388 | ACPI_OBJECT Arg[HCI_WORDS]; |
389 | ACPI_OBJECT_LIST ArgList; |
390 | ACPI_OBJECT *param, *PrtElement; |
391 | ACPI_BUFFER buf; |
392 | int i; |
393 | |
394 | for (i = 0; i < HCI_WORDS; i++) { |
395 | Arg[i].Type = ACPI_TYPE_INTEGER; |
396 | Arg[i].Integer.Value = 0; |
397 | } |
398 | |
399 | for (i = 0; i < HCI_WORDS; i++) { |
400 | Arg[i].Integer.Value = input[i]; |
401 | } |
402 | |
403 | ArgList.Count = HCI_WORDS; |
404 | ArgList.Pointer = Arg; |
405 | |
406 | buf.Pointer = NULL; |
407 | buf.Length = ACPI_ALLOCATE_BUFFER; |
408 | |
409 | rv = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle, |
410 | METHOD_HCI, &ArgList, &buf, ACPI_TYPE_PACKAGE); |
411 | if (ACPI_FAILURE(rv)) { |
412 | aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n" , |
413 | AcpiFormatException(rv)); |
414 | return rv; |
415 | } |
416 | |
417 | param = (ACPI_OBJECT *)buf.Pointer; |
418 | PrtElement = param->Package.Elements; |
419 | for (i = 0; i < HCI_WORDS; i++) { |
420 | output[i] = PrtElement[i].Type == ACPI_TYPE_INTEGER ? |
421 | PrtElement[i].Integer.Value : 0; |
422 | } |
423 | |
424 | ACPI_FREE(buf.Pointer); |
425 | |
426 | return rv; |
427 | } |
428 | |
429 | /* |
430 | * valz_acpi_hci_get: |
431 | * |
432 | * Get value via "GHCI" Method. |
433 | */ |
434 | static ACPI_STATUS |
435 | valz_acpi_hci_get(struct valz_acpi_softc *sc, uint32_t function, |
436 | uint32_t reg, uint32_t *value, uint32_t *result) |
437 | { |
438 | ACPI_STATUS rv; |
439 | |
440 | uint32_t input[HCI_WORDS]; |
441 | uint32_t output[HCI_WORDS]; |
442 | |
443 | input[HCI_REG_AX] = function; |
444 | input[HCI_REG_BX] = reg; |
445 | input[HCI_REG_CX] = 0; |
446 | input[HCI_REG_DX] = 0; |
447 | input[HCI_REG_SI] = 0; |
448 | input[HCI_REG_DI] = 0; |
449 | |
450 | rv = hci_op(sc, input, output); |
451 | |
452 | *result = output[HCI_REG_AX]; |
453 | *value = output[HCI_REG_CX]; |
454 | |
455 | return rv; |
456 | } |
457 | |
458 | /* |
459 | * valz_acpi_hci_set: |
460 | * |
461 | * Set value via "GHCI" Method. |
462 | */ |
463 | static ACPI_STATUS |
464 | valz_acpi_hci_set(struct valz_acpi_softc *sc, uint32_t function, |
465 | uint32_t reg, uint32_t value, uint32_t *result) |
466 | { |
467 | ACPI_STATUS rv; |
468 | |
469 | uint32_t input[HCI_WORDS]; |
470 | uint32_t output[HCI_WORDS]; |
471 | |
472 | input[HCI_REG_AX] = function; |
473 | input[HCI_REG_BX] = reg; |
474 | input[HCI_REG_CX] = value; |
475 | input[HCI_REG_DX] = 0; |
476 | input[HCI_REG_SI] = 0; |
477 | input[HCI_REG_DI] = 0; |
478 | |
479 | rv = hci_op(sc, input, output); |
480 | |
481 | *result = output[HCI_REG_AX]; |
482 | |
483 | return rv; |
484 | } |
485 | |
486 | /* |
487 | * Open SCI |
488 | */ |
489 | static ACPI_STATUS |
490 | sci_open(struct valz_acpi_softc *sc) |
491 | { |
492 | ACPI_STATUS rv; |
493 | uint32_t result; |
494 | |
495 | rv = valz_acpi_hci_set(sc, SCI_OPEN, 0, 0, &result); |
496 | if (ACPI_FAILURE(rv)) { |
497 | aprint_error("SCI: ACPI set error\n" ); |
498 | } else { |
499 | switch (result) { |
500 | case SCI_OPENCLOSE_OK: |
501 | aprint_debug("Opening SCI\n" ); |
502 | break; |
503 | case SCI_ALREADY_OPEN: |
504 | aprint_error("SCI already open\n" ); |
505 | break; |
506 | case SCI_NOT_SUPPORTED: |
507 | aprint_error("SCI is not supported\n" ); |
508 | break; |
509 | case SCI_NOT_PRESENT: |
510 | aprint_error("SCI is not present\n" ); |
511 | break; |
512 | default: |
513 | aprint_error("SCI: undefined behavior\n" ); |
514 | break; |
515 | } |
516 | } |
517 | |
518 | return rv; |
519 | } |
520 | |
521 | /* |
522 | * Close SCI |
523 | */ |
524 | static ACPI_STATUS |
525 | sci_close(struct valz_acpi_softc *sc) |
526 | { |
527 | ACPI_STATUS rv; |
528 | uint32_t result; |
529 | |
530 | rv = valz_acpi_hci_set(sc, SCI_CLOSE, 0, 0, &result); |
531 | if (ACPI_FAILURE(rv)) { |
532 | aprint_error("SCI: ACPI set error\n" ); |
533 | } else { |
534 | switch (result) { |
535 | case SCI_OPENCLOSE_OK: |
536 | aprint_debug("Closing SCI\n" ); |
537 | break; |
538 | case SCI_NOT_OPEN: |
539 | aprint_error("SCI is not opened\n" ); |
540 | break; |
541 | case SCI_NOT_SUPPORTED: |
542 | aprint_error("SCI is not supported\n" ); |
543 | break; |
544 | case SCI_NOT_PRESENT: |
545 | aprint_error("SCI is not present\n" ); |
546 | break; |
547 | default: |
548 | aprint_error("SCI: undefined behavior\n" ); |
549 | break; |
550 | } |
551 | } |
552 | |
553 | return rv; |
554 | } |
555 | |
556 | /* |
557 | * Enable/disable touchpad and trackpoint with HCI_ENABLE/HCI_DISABLE |
558 | */ |
559 | static ACPI_STATUS |
560 | valz_acpi_touchpad_toggle(struct valz_acpi_softc *sc) |
561 | { |
562 | ACPI_STATUS rv; |
563 | uint32_t result, status, value; |
564 | |
565 | rv = sci_open(sc); |
566 | if (ACPI_FAILURE(rv)) |
567 | aprint_error_dev(sc->sc_dev, |
568 | "Cannot open SCI: %s\n" , |
569 | AcpiFormatException(rv)); |
570 | |
571 | rv = valz_acpi_hci_get(sc, SCI_GET, SCI_TOUCHPAD, &value, &result); |
572 | if (ACPI_FAILURE(rv)) |
573 | aprint_error_dev(sc->sc_dev, |
574 | "Cannot get SCI touchpad status: %s\n" , |
575 | AcpiFormatException(rv)); |
576 | |
577 | switch (value) { |
578 | case HCI_ENABLE: |
579 | status = HCI_DISABLE; |
580 | break; |
581 | case HCI_DISABLE: |
582 | status = HCI_ENABLE; |
583 | break; |
584 | default: |
585 | status = HCI_ENABLE; |
586 | break; |
587 | } |
588 | |
589 | rv = valz_acpi_hci_set(sc, SCI_SET, SCI_TOUCHPAD, status, &result); |
590 | if (ACPI_FAILURE(rv)) |
591 | aprint_error_dev(sc->sc_dev, |
592 | "Cannot set SCI touchpad status: %s\n" , |
593 | AcpiFormatException(rv)); |
594 | |
595 | rv = sci_close(sc); |
596 | if (ACPI_FAILURE(rv)) |
597 | aprint_error_dev(sc->sc_dev, |
598 | "Cannot close SCI: %s\n" , |
599 | AcpiFormatException(rv)); |
600 | |
601 | return rv; |
602 | } |
603 | |
604 | /* |
605 | * Enable/disable LCD backlight with HCI_ENABLE/HCI_DISABLE |
606 | */ |
607 | static ACPI_STATUS |
608 | valz_acpi_lcd_backlight_toggle(struct valz_acpi_softc *sc) |
609 | { |
610 | ACPI_STATUS rv; |
611 | uint32_t result, status, value; |
612 | |
613 | rv = valz_acpi_hci_get(sc, HCI_GET, HCI_LCD_BACKLIGHT, &value, &result); |
614 | if (ACPI_FAILURE(rv)) |
615 | aprint_error_dev(sc->sc_dev, |
616 | "Cannot get HCI LCD backlight status: %s\n" , |
617 | AcpiFormatException(rv)); |
618 | |
619 | switch (value) { |
620 | case HCI_ON: |
621 | status = HCI_OFF; |
622 | break; |
623 | case HCI_OFF: |
624 | status = HCI_ON; |
625 | break; |
626 | default: |
627 | status = HCI_ON; |
628 | break; |
629 | } |
630 | |
631 | rv = valz_acpi_hci_set(sc, HCI_SET, HCI_LCD_BACKLIGHT, status, &result); |
632 | if (ACPI_FAILURE(rv)) |
633 | aprint_error_dev(sc->sc_dev, |
634 | "Cannot set HCI LCD backlight status: %s\n" , |
635 | AcpiFormatException(rv)); |
636 | |
637 | return rv; |
638 | } |
639 | |