valz_acpi.c revision 1.8
11.8Sryoon/* $NetBSD: valz_acpi.c,v 1.8 2017/11/09 23:51:54 ryoon Exp $ */ 21.5Snonaka 31.5Snonaka/*- 41.5Snonaka * Copyright (c) 2002 The NetBSD Foundation, Inc. 51.5Snonaka * All rights reserved. 61.5Snonaka * 71.5Snonaka * This code is derived from software contributed to The NetBSD Foundation 81.5Snonaka * by Masanori Kanaoka. 91.5Snonaka * 101.5Snonaka * Redistribution and use in source and binary forms, with or without 111.5Snonaka * modification, are permitted provided that the following conditions 121.5Snonaka * are met: 131.5Snonaka * 1. Redistributions of source code must retain the above copyright 141.5Snonaka * notice, this list of conditions and the following disclaimer. 151.5Snonaka * 2. Redistributions in binary form must reproduce the above copyright 161.5Snonaka * notice, this list of conditions and the following disclaimer in the 171.5Snonaka * documentation and/or other materials provided with the distribution. 181.5Snonaka * 191.5Snonaka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201.5Snonaka * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211.5Snonaka * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221.5Snonaka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 231.5Snonaka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 241.5Snonaka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251.5Snonaka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261.5Snonaka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271.5Snonaka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281.5Snonaka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291.5Snonaka * POSSIBILITY OF SUCH DAMAGE. 301.5Snonaka */ 311.1Sjakllsch 321.1Sjakllsch/* 331.5Snonaka * Copyright 2001 Bill Sommerfeld. 341.1Sjakllsch * All rights reserved. 351.1Sjakllsch * 361.1Sjakllsch * Redistribution and use in source and binary forms, with or without 371.1Sjakllsch * modification, are permitted provided that the following conditions 381.1Sjakllsch * are met: 391.1Sjakllsch * 1. Redistributions of source code must retain the above copyright 401.1Sjakllsch * notice, this list of conditions and the following disclaimer. 411.1Sjakllsch * 2. Redistributions in binary form must reproduce the above copyright 421.1Sjakllsch * notice, this list of conditions and the following disclaimer in the 431.1Sjakllsch * documentation and/or other materials provided with the distribution. 441.5Snonaka * 3. All advertising materials mentioning features or use of this software 451.5Snonaka * must display the following acknowledgement: 461.5Snonaka * This product includes software developed for the NetBSD Project by 471.5Snonaka * Wasabi Systems, Inc. 481.5Snonaka * 4. The name of Wasabi Systems, Inc. may not be used to endorse 491.5Snonaka * or promote products derived from this software without specific prior 501.5Snonaka * written permission. 511.1Sjakllsch * 521.5Snonaka * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 531.5Snonaka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 541.1Sjakllsch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 551.5Snonaka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 561.5Snonaka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 571.5Snonaka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 581.5Snonaka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 591.5Snonaka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 601.5Snonaka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 611.5Snonaka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 621.5Snonaka * POSSIBILITY OF SUCH DAMAGE. 631.5Snonaka */ 641.5Snonaka 651.5Snonaka/* 661.5Snonaka * ACPI VALZ Driver for Toshiba dynabook R63/PS 671.5Snonaka * This driver is based on vald_acpi.c 681.5Snonaka */ 691.5Snonaka 701.5Snonaka/* 711.5Snonaka * Obtain information of Toshiba "GHCI" Method from next URL. 721.5Snonaka * http://www.buzzard.me.uk/toshiba/docs.html 731.5Snonaka * http://memebeam.org/toys/ToshibaAcpiDriver 741.1Sjakllsch */ 751.1Sjakllsch 761.1Sjakllsch#include <sys/cdefs.h> 771.8Sryoon__KERNEL_RCSID(0, "$NetBSD: valz_acpi.c,v 1.8 2017/11/09 23:51:54 ryoon Exp $"); 781.1Sjakllsch 791.1Sjakllsch#include <sys/param.h> 801.1Sjakllsch#include <sys/systm.h> 811.5Snonaka#include <sys/device.h> 821.1Sjakllsch 831.5Snonaka#include <dev/acpi/acpica.h> 841.1Sjakllsch#include <dev/acpi/acpireg.h> 851.1Sjakllsch#include <dev/acpi/acpivar.h> 861.1Sjakllsch 871.5Snonaka#define _COMPONENT ACPI_RESOURCE_COMPONENT 881.5SnonakaACPI_MODULE_NAME ("valz_acpi") 891.5Snonaka 901.5Snonaka#define METHOD_HCI "GHCI" 911.5Snonaka#define METHOD_HCI_ENABLE "ENAB" 921.1Sjakllsch 931.5Snonaka/* Operations */ 941.5Snonaka/* Get */ 951.5Snonaka#define HCI_GET 0xfe00 961.5Snonaka#define SCI_CHECK 0xf000 971.5Snonaka#define SCI_GET 0xf300 981.5Snonaka 991.5Snonaka/* Set */ 1001.5Snonaka#define HCI_SET 0xff00 1011.5Snonaka#define SCI_OPEN 0xf100 1021.5Snonaka#define SCI_CLOSE 0xf200 1031.5Snonaka#define SCI_SET 0xf400 1041.5Snonaka 1051.5Snonaka/* Return codes */ 1061.5Snonaka#define HCI_SUCCESS 0x0000 1071.5Snonaka#define HCI_FAILURE 0x1000 1081.5Snonaka#define HCI_NOT_SUPPORTED 0x8000 1091.5Snonaka#define HCI_INPUT_ERROR 0x8300 1101.5Snonaka#define HCI_FIFO_EMPTY 0x8c00 1111.5Snonaka 1121.5Snonaka#define SCI_OPENCLOSE_OK 0x0044 1131.5Snonaka#define SCI_NOT_SUPPORTED 0x8000 1141.5Snonaka#define SCI_ALREADY_OPEN 0x8100 1151.5Snonaka#define SCI_NOT_OPEN 0x8200 1161.5Snonaka#define SCI_NOT_PRESENT 0x8600 1171.5Snonaka 1181.5Snonaka/* Functions */ 1191.5Snonaka#define HCI_LCD_BACKLIGHT 0x0002 1201.5Snonaka#define HCI_ACADAPTOR 0x0003 1211.5Snonaka#define HCI_SYSTEM_EVENT_FIFO 0x0016 1221.5Snonaka#define HCI_KBD_BACKLIGHT 0x0017 1231.5Snonaka#define HCI_DISPLAY_DEV 0x001c 1241.5Snonaka#define HCI_HOTKEY_EVENT 0x001e 1251.5Snonaka#define HCI_LCD_BRIGHTNESS 0x002a 1261.5Snonaka#define HCI_CPU_SPEED 0x0032 1271.5Snonaka 1281.5Snonaka#define SCI_USB_OFF_CHARGE 0x0150 1291.5Snonaka#define SCI_TOUCHPAD 0x050e 1301.5Snonaka#define SCI_KBD_BACKLIGHT_STS 0x015c 1311.5Snonaka#define SCI_KBD_BACKLIGHT 0x0095 1321.5Snonaka 1331.5Snonaka#define SCI_KBD_BL_TIME_SHIFT 0x10 1341.5Snonaka 1351.5Snonaka/* Field definitions */ 1361.5Snonaka#define HCI_LCD_BRIGHTNESS_BITS 3 1371.5Snonaka#define HCI_LCD_BRIGHTNESS_SFT (16 - HCI_LCD_BRIGHTNESS_BITS) 1381.5Snonaka#define HCI_LCD_BRIGHTNESS_MIN 0 1391.5Snonaka#define HCI_LCD_BRIGHTNESS_MAX 7 1401.5Snonaka#define HCI_VIDEO_DEVICE_FLG 0x0100 1411.5Snonaka#define HCI_CPU_SPEED_BITS 3 1421.5Snonaka#define HCI_CPU_SPEED_SFT (16 - HCI_CPU_SPEED_BITS) 1431.5Snonaka#define HCI_CPU_SPEED_MAX ((1 << HCI_CPU_SPEED_BITS) - 1) 1441.5Snonaka 1451.5Snonaka/* Key press/release events */ 1461.5Snonaka 1471.5Snonaka/* Key press/release events */ 1481.5Snonaka#define FN_RELEASE_OFFSET 0x80 1491.5Snonaka# if 0 1501.5Snonaka/* Not used */ 1511.5Snonaka#define FN_PRESS 0x01ff 1521.5Snonaka#define FN_RELEASE 0x0100 1531.5Snonaka# endif 1541.5Snonaka#define FN_ESC_PRESS 0x0101 1551.5Snonaka#define FN_ESC_RELEASE (FN_ESC_PRESS + FN_RELEASE_OFFSET) 1561.5Snonaka#define FN_F1_PRESS 0x013b 1571.5Snonaka#define FN_F1_RELEASE (FN_F1_PRESS + FN_RELEASE_OFFSET) 1581.5Snonaka#define FN_F2_PRESS 0x013c 1591.5Snonaka#define FN_F2_RELEASE (FN_F2_PRESS + FN_RELEASE_OFFSET) 1601.5Snonaka#define FN_F3_PRESS 0x013d 1611.5Snonaka#define FN_F3_RELEASE (FN_F3_PRESS + FN_RELEASE_OFFSET) 1621.5Snonaka#define FN_F4_PRESS 0x013e 1631.5Snonaka#define FN_F4_RELEASE (FN_F4_PRESS + FN_RELEASE_OFFSET) 1641.5Snonaka#define FN_F5_PRESS 0x013f 1651.5Snonaka#define FN_F5_RELEASE (FN_F5_PRESS + FN_RELEASE_OFFSET) 1661.5Snonaka#define FN_F6_PRESS 0x0140 1671.5Snonaka#define FN_F6_RELEASE (FN_F6_PRESS + FN_RELEASE_OFFSET) 1681.5Snonaka#define FN_F7_PRESS 0x0141 1691.5Snonaka#define FN_F7_RELEASE (FN_F7_PRESS + FN_RELEASE_OFFSET) 1701.5Snonaka#define FN_F8_PRESS 0x0142 1711.5Snonaka#define FN_F8_RELEASE (FN_F8_PRESS + FN_RELEASE_OFFSET) 1721.5Snonaka#define FN_F9_PRESS 0x0143 1731.5Snonaka#define FN_F9_RELEASE (FN_F9_PRESS + FN_RELEASE_OFFSET) 1741.5Snonaka/* Toggle, they are controlled by hardware */ 1751.5Snonaka#define FN_F10_ON 0x1bb0 1761.5Snonaka#define FN_F10_OFF 0x1bb1 1771.5Snonaka#define FN_F11_ON 0x1bb2 1781.5Snonaka#define FN_F11_OFF 0x1bb3 1791.5Snonaka/* Fn+F12 does not emit keycode */ 1801.5Snonaka/* dynabook R63/PS does not have KANJI keytop print */ 1811.5Snonaka#define FN_KNJ_PRESS 0x0129 1821.5Snonaka#define FN_KNJ_RELEASE (FN_KNJ_PRESS + FN_RELEASE_OFFSET) 1831.5Snonaka#define FN_1_PRESS 0x0102 1841.5Snonaka#define FN_1_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) 1851.5Snonaka#define FN_2_PRESS 0x0103 1861.5Snonaka#define FN_2_RELEASE (FN_2_PRESS + FN_RELEASE_OFFSET) 1871.5Snonaka/* Fn+3 and Fn+4 do not emit keybode */ 1881.5Snonaka#define FN_Z_PRESS 0x012c 1891.5Snonaka#define FN_Z_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) 1901.5Snonaka#define FN_SPACE_PRESS 0x0139 1911.5Snonaka#define FN_SPACE_RELEASE (FN_1_PRESS + FN_RELEASE_OFFSET) 1921.5Snonaka#define FN_TAB_PRESS 0x010f 1931.5Snonaka#define FN_TAB_RELEASE (FN_TAB_PRESS + FN_RELEASE_OFFSET) 1941.5Snonaka#define FN_CAPS_PRESS 0x013a 1951.5Snonaka#define FN_CAPS_RELEASE (FN_CAPS_PRESS + FN_RELEASE_OFFSET) 1961.5Snonaka#define FN_BACKSPACE_PRESS 0x010e 1971.5Snonaka#define FN_BACKSPACE_RELEASE (FN_BACKSPACE_PRESS + FN_RELEASE_OFFSET) 1981.5Snonaka#define FN_INS_PRESS 0x0152 1991.5Snonaka#define FN_INS_RELEASE (FN_INS_PRESS + FN_RELEASE_OFFSET) 2001.5Snonaka#define FN_DEL_PRESS 0x0153 2011.5Snonaka#define FN_DEL_RELEASE (FN_DEL_PRESS + FN_RELEASE_OFFSET) 2021.5Snonaka#define FN_PRTSC_PRESS 0x0137 2031.5Snonaka#define FN_PRTSC_RELEASE (FN_PRTSC_PRESS + FN_RELEASE_OFFSET) 2041.5Snonaka 2051.5Snonaka/* HCI register definitions */ 2061.5Snonaka#define HCI_WORDS 6 /* number of registers */ 2071.5Snonaka#define HCI_REG_AX 0 /* Operation -> return value */ 2081.5Snonaka#define HCI_REG_BX 1 /* Function */ 2091.5Snonaka#define HCI_REG_CX 2 /* Argument (in or out) */ 2101.5Snonaka#define HCI_REG_DX 3 /* unused */ 2111.5Snonaka#define HCI_REG_SI 4 /* unused */ 2121.5Snonaka#define HCI_REG_DI 5 /* unused */ 2131.5Snonaka 2141.5Snonaka#define HCI_ON 0x0001 2151.5Snonaka#define HCI_OFF 0x0000 2161.5Snonaka#define HCI_ENABLE 0x0001 2171.5Snonaka#define HCI_DISABLE 0x0000 2181.5Snonaka 2191.5Snonaka#define HCI_LCD 0x1 2201.5Snonaka#define HCI_CRT 0x2 2211.5Snonaka#define HCI_TV 0x4 2221.5Snonaka 2231.5Snonaka#define SCI_KBD_BL_MODE_MASK 0x1f 2241.5Snonaka#define SCI_KBD_BL_TIMO_SFT 0x10 2251.5Snonaka#define SCI_KBD_BL_MODE_AUTO 0x2 2261.5Snonaka#define SCI_KBD_BL_MODE_ON 0x8 2271.5Snonaka#define SCI_KBD_BL_MODE_OFF 0x10 2281.5Snonaka 2291.5Snonakastruct valz_acpi_softc { 2301.5Snonaka device_t sc_dev; /* base device glue */ 2311.5Snonaka struct acpi_devnode *sc_node; /* our ACPI devnode */ 2321.1Sjakllsch}; 2331.1Sjakllsch 2341.5Snonakastatic const char * const valz_acpi_hids[] = { 2351.5Snonaka "TOS6208", 2361.1Sjakllsch NULL 2371.1Sjakllsch}; 2381.1Sjakllsch 2391.5Snonakastatic int valz_acpi_match(device_t, cfdata_t, void *); 2401.5Snonakastatic void valz_acpi_attach(device_t, device_t, void *); 2411.1Sjakllsch 2421.5Snonakastatic void valz_acpi_event(void *); 2431.5Snonakastatic void valz_acpi_notify_handler(ACPI_HANDLE, uint32_t, void *); 2441.1Sjakllsch 2451.5Snonaka#define ACPI_NOTIFY_ValzHotkeyPressed 0x80 2461.5Snonaka#define ACPI_NOTIFY_ValzLidClosed 0x8f 2471.5Snonaka#define ACPI_NOTIFY_ValzKbdBLChanges 0x92 2481.5Snonaka 2491.5Snonaka/* HCI manipulation */ 2501.5Snonakastatic ACPI_STATUS hci_op(struct valz_acpi_softc *, 2511.5Snonaka uint32_t *, uint32_t *); 2521.5Snonakastatic ACPI_STATUS valz_acpi_hci_get(struct valz_acpi_softc *, uint32_t, 2531.5Snonaka uint32_t, uint32_t *, uint32_t *); 2541.5Snonakastatic ACPI_STATUS valz_acpi_hci_set(struct valz_acpi_softc *, uint32_t, 2551.5Snonaka uint32_t, uint32_t, uint32_t *); 2561.5Snonaka 2571.5Snonakastatic ACPI_STATUS sci_open(struct valz_acpi_softc *); 2581.5Snonakastatic ACPI_STATUS sci_close(struct valz_acpi_softc *); 2591.5Snonaka 2601.5Snonakastatic ACPI_STATUS valz_acpi_touchpad_toggle(struct valz_acpi_softc *); 2611.5Snonakastatic ACPI_STATUS valz_acpi_lcd_backlight_toggle( 2621.5Snonaka struct valz_acpi_softc *sc); 2631.5Snonaka 2641.5SnonakaCFATTACH_DECL_NEW(valz_acpi, sizeof(struct valz_acpi_softc), 2651.5Snonaka valz_acpi_match, valz_acpi_attach, NULL, NULL); 2661.5Snonaka 2671.5Snonaka/* 2681.5Snonaka * valz_acpi_match: 2691.5Snonaka * 2701.5Snonaka * Autoconfiguration `match' routine. 2711.5Snonaka */ 2721.1Sjakllschstatic int 2731.5Snonakavalz_acpi_match(device_t parent, cfdata_t match, void *aux) 2741.1Sjakllsch{ 2751.1Sjakllsch struct acpi_attach_args *aa = aux; 2761.1Sjakllsch 2771.1Sjakllsch if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 2781.5Snonaka return (0); 2791.1Sjakllsch 2801.5Snonaka return (acpi_match_hid(aa->aa_node->ad_devinfo, valz_acpi_hids)); 2811.1Sjakllsch} 2821.1Sjakllsch 2831.5Snonaka/* 2841.5Snonaka * valz_acpi_attach: 2851.5Snonaka * 2861.5Snonaka * Autoconfiguration `attach' routine. 2871.5Snonaka */ 2881.1Sjakllschstatic void 2891.5Snonakavalz_acpi_attach(device_t parent, device_t self, void *aux) 2901.1Sjakllsch{ 2911.5Snonaka struct valz_acpi_softc *sc = device_private(self); 2921.5Snonaka struct acpi_attach_args *aa = aux; 2931.1Sjakllsch ACPI_STATUS rv; 2941.1Sjakllsch 2951.5Snonaka aprint_naive(": Toshiba VALZ\n"); 2961.5Snonaka aprint_normal(": Toshiba VALZ\n"); 2971.1Sjakllsch 2981.5Snonaka sc->sc_node = aa->aa_node; 2991.1Sjakllsch sc->sc_dev = self; 3001.1Sjakllsch 3011.5Snonaka /* enable valz notify */ 3021.5Snonaka rv = AcpiEvaluateObject(sc->sc_node->ad_handle, METHOD_HCI_ENABLE, 3031.5Snonaka NULL, NULL); 3041.5Snonaka if (ACPI_FAILURE(rv)) { 3051.5Snonaka aprint_error("Cannot enable VALZ.\n"); 3061.5Snonaka } else { 3071.5Snonaka (void)acpi_register_notify(sc->sc_node, 3081.5Snonaka valz_acpi_notify_handler); 3091.5Snonaka } 3101.1Sjakllsch} 3111.1Sjakllsch 3121.5Snonaka/* 3131.5Snonaka * valz_acpi_notify_handler: 3141.5Snonaka * 3151.5Snonaka * Notify handler. 3161.5Snonaka */ 3171.1Sjakllschstatic void 3181.5Snonakavalz_acpi_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) 3191.1Sjakllsch{ 3201.5Snonaka struct valz_acpi_softc *sc; 3211.5Snonaka device_t self = context; 3221.5Snonaka 3231.5Snonaka sc = device_private(self); 3241.1Sjakllsch 3251.1Sjakllsch switch (notify) { 3261.5Snonaka case ACPI_NOTIFY_ValzHotkeyPressed: 3271.5Snonaka (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, valz_acpi_event, sc); 3281.1Sjakllsch break; 3291.5Snonaka 3301.5Snonaka case ACPI_NOTIFY_ValzLidClosed: 3311.5Snonaka /* Lid closed */ 3321.1Sjakllsch break; 3331.5Snonaka 3341.5Snonaka case ACPI_NOTIFY_ValzKbdBLChanges: 3351.5Snonaka /* Keyboard backlight mode changed */ 3361.5Snonaka break; 3371.5Snonaka 3381.1Sjakllsch default: 3391.8Sryoon aprint_debug_dev(sc->sc_dev, 3401.5Snonaka "unknown notify 0x%02X\n", notify); 3411.1Sjakllsch break; 3421.1Sjakllsch } 3431.1Sjakllsch} 3441.1Sjakllsch 3451.5Snonaka/* 3461.5Snonaka * valz_acpi_event: 3471.5Snonaka * 3481.5Snonaka * Check hotkey event and do it, if event occur. 3491.5Snonaka */ 3501.1Sjakllschstatic void 3511.5Snonakavalz_acpi_event(void *arg) 3521.1Sjakllsch{ 3531.5Snonaka struct valz_acpi_softc *sc = arg; 3541.1Sjakllsch ACPI_STATUS rv; 3551.5Snonaka uint32_t value, result; 3561.1Sjakllsch 3571.5Snonaka for (;;) { 3581.5Snonaka rv = valz_acpi_hci_get(sc, HCI_GET, HCI_SYSTEM_EVENT_FIFO, 3591.5Snonaka &value, &result); 3601.5Snonaka if (ACPI_SUCCESS(rv) && result == 0) { 3611.5Snonaka switch (value) { 3621.5Snonaka case FN_F9_PRESS: 3631.5Snonaka valz_acpi_touchpad_toggle(sc); 3641.5Snonaka break; 3651.5Snonaka case FN_TAB_PRESS: 3661.5Snonaka valz_acpi_lcd_backlight_toggle(sc); 3671.5Snonaka break; 3681.5Snonaka 3691.5Snonaka default: 3701.5Snonaka /* Many unused buttons */ 3711.5Snonaka aprint_debug("Pressed: 0x%x\n", value); 3721.5Snonaka break; 3731.5Snonaka } 3741.5Snonaka } 3751.5Snonaka if (ACPI_FAILURE(rv) || result == HCI_NOT_SUPPORTED || 3761.5Snonaka result == HCI_FIFO_EMPTY) 3771.5Snonaka break; 3781.5Snonaka } 3791.1Sjakllsch} 3801.1Sjakllsch 3811.5Snonaka/* 3821.5Snonaka * HCI/SCI operation 3831.5Snonaka */ 3841.1Sjakllschstatic ACPI_STATUS 3851.5Snonakahci_op(struct valz_acpi_softc *sc, uint32_t *input, uint32_t *output) 3861.1Sjakllsch{ 3871.1Sjakllsch ACPI_STATUS rv; 3881.5Snonaka ACPI_OBJECT Arg[HCI_WORDS]; 3891.5Snonaka ACPI_OBJECT_LIST ArgList; 3901.5Snonaka ACPI_OBJECT *param, *PrtElement; 3911.1Sjakllsch ACPI_BUFFER buf; 3921.5Snonaka int i; 3931.1Sjakllsch 3941.5Snonaka for (i = 0; i < HCI_WORDS; i++) { 3951.5Snonaka Arg[i].Type = ACPI_TYPE_INTEGER; 3961.5Snonaka Arg[i].Integer.Value = 0; 3971.5Snonaka } 3981.5Snonaka 3991.5Snonaka for (i = 0; i < HCI_WORDS; i++) { 4001.5Snonaka Arg[i].Integer.Value = input[i]; 4011.5Snonaka } 4021.5Snonaka 4031.5Snonaka ArgList.Count = HCI_WORDS; 4041.5Snonaka ArgList.Pointer = Arg; 4051.5Snonaka 4061.5Snonaka buf.Pointer = NULL; 4071.5Snonaka buf.Length = ACPI_ALLOCATE_BUFFER; 4081.5Snonaka 4091.5Snonaka rv = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle, 4101.5Snonaka METHOD_HCI, &ArgList, &buf, ACPI_TYPE_PACKAGE); 4111.5Snonaka if (ACPI_FAILURE(rv)) { 4121.5Snonaka aprint_error_dev(sc->sc_dev, "failed to evaluate GHCI: %s\n", 4131.5Snonaka AcpiFormatException(rv)); 4141.5Snonaka return rv; 4151.5Snonaka } 4161.1Sjakllsch 4171.5Snonaka param = (ACPI_OBJECT *)buf.Pointer; 4181.5Snonaka PrtElement = param->Package.Elements; 4191.5Snonaka for (i = 0; i < HCI_WORDS; i++) { 4201.7Schristos output[i] = PrtElement[i].Type == ACPI_TYPE_INTEGER ? 4211.7Schristos PrtElement[i].Integer.Value : 0; 4221.5Snonaka } 4231.1Sjakllsch 4241.6Schristos ACPI_FREE(buf.Pointer); 4251.1Sjakllsch 4261.5Snonaka return rv; 4271.1Sjakllsch} 4281.1Sjakllsch 4291.5Snonaka/* 4301.5Snonaka * valz_acpi_hci_get: 4311.5Snonaka * 4321.5Snonaka * Get value via "GHCI" Method. 4331.5Snonaka */ 4341.5Snonakastatic ACPI_STATUS 4351.5Snonakavalz_acpi_hci_get(struct valz_acpi_softc *sc, uint32_t function, 4361.5Snonaka uint32_t reg, uint32_t *value, uint32_t *result) 4371.5Snonaka{ 4381.5Snonaka ACPI_STATUS rv; 4391.5Snonaka 4401.5Snonaka uint32_t input[HCI_WORDS]; 4411.5Snonaka uint32_t output[HCI_WORDS]; 4421.5Snonaka 4431.5Snonaka input[HCI_REG_AX] = function; 4441.5Snonaka input[HCI_REG_BX] = reg; 4451.5Snonaka input[HCI_REG_CX] = 0; 4461.5Snonaka input[HCI_REG_DX] = 0; 4471.5Snonaka input[HCI_REG_SI] = 0; 4481.5Snonaka input[HCI_REG_DI] = 0; 4491.5Snonaka 4501.5Snonaka rv = hci_op(sc, input, output); 4511.5Snonaka 4521.5Snonaka *result = output[HCI_REG_AX]; 4531.5Snonaka *value = output[HCI_REG_CX]; 4541.5Snonaka 4551.5Snonaka return rv; 4561.5Snonaka} 4571.5Snonaka 4581.5Snonaka/* 4591.5Snonaka * valz_acpi_hci_set: 4601.5Snonaka * 4611.5Snonaka * Set value via "GHCI" Method. 4621.5Snonaka */ 4631.5Snonakastatic ACPI_STATUS 4641.5Snonakavalz_acpi_hci_set(struct valz_acpi_softc *sc, uint32_t function, 4651.5Snonaka uint32_t reg, uint32_t value, uint32_t *result) 4661.5Snonaka{ 4671.5Snonaka ACPI_STATUS rv; 4681.5Snonaka 4691.5Snonaka uint32_t input[HCI_WORDS]; 4701.5Snonaka uint32_t output[HCI_WORDS]; 4711.5Snonaka 4721.5Snonaka input[HCI_REG_AX] = function; 4731.5Snonaka input[HCI_REG_BX] = reg; 4741.5Snonaka input[HCI_REG_CX] = value; 4751.5Snonaka input[HCI_REG_DX] = 0; 4761.5Snonaka input[HCI_REG_SI] = 0; 4771.5Snonaka input[HCI_REG_DI] = 0; 4781.5Snonaka 4791.5Snonaka rv = hci_op(sc, input, output); 4801.5Snonaka 4811.5Snonaka *result = output[HCI_REG_AX]; 4821.5Snonaka 4831.5Snonaka return rv; 4841.5Snonaka} 4851.5Snonaka 4861.5Snonaka/* 4871.5Snonaka * Open SCI 4881.5Snonaka */ 4891.5Snonakastatic ACPI_STATUS 4901.5Snonakasci_open(struct valz_acpi_softc *sc) 4911.1Sjakllsch{ 4921.1Sjakllsch ACPI_STATUS rv; 4931.5Snonaka uint32_t result; 4941.1Sjakllsch 4951.5Snonaka rv = valz_acpi_hci_set(sc, SCI_OPEN, 0, 0, &result); 4961.5Snonaka if (ACPI_FAILURE(rv)) { 4971.5Snonaka aprint_error("SCI: ACPI set error\n"); 4981.5Snonaka } else { 4991.5Snonaka switch (result) { 5001.5Snonaka case SCI_OPENCLOSE_OK: 5011.5Snonaka aprint_debug("Opening SCI\n"); 5021.5Snonaka break; 5031.5Snonaka case SCI_ALREADY_OPEN: 5041.5Snonaka aprint_error("SCI already open\n"); 5051.5Snonaka break; 5061.5Snonaka case SCI_NOT_SUPPORTED: 5071.5Snonaka aprint_error("SCI is not supported\n"); 5081.5Snonaka break; 5091.5Snonaka case SCI_NOT_PRESENT: 5101.5Snonaka aprint_error("SCI is not present\n"); 5111.5Snonaka break; 5121.5Snonaka default: 5131.5Snonaka aprint_error("SCI: undefined behavior\n"); 5141.5Snonaka break; 5151.5Snonaka } 5161.5Snonaka } 5171.5Snonaka 5181.5Snonaka return rv; 5191.5Snonaka} 5201.5Snonaka 5211.5Snonaka/* 5221.5Snonaka * Close SCI 5231.5Snonaka */ 5241.5Snonakastatic ACPI_STATUS 5251.5Snonakasci_close(struct valz_acpi_softc *sc) 5261.5Snonaka{ 5271.5Snonaka ACPI_STATUS rv; 5281.5Snonaka uint32_t result; 5291.1Sjakllsch 5301.5Snonaka rv = valz_acpi_hci_set(sc, SCI_CLOSE, 0, 0, &result); 5311.1Sjakllsch if (ACPI_FAILURE(rv)) { 5321.5Snonaka aprint_error("SCI: ACPI set error\n"); 5331.5Snonaka } else { 5341.5Snonaka switch (result) { 5351.5Snonaka case SCI_OPENCLOSE_OK: 5361.5Snonaka aprint_debug("Closing SCI\n"); 5371.5Snonaka break; 5381.5Snonaka case SCI_NOT_OPEN: 5391.5Snonaka aprint_error("SCI is not opened\n"); 5401.5Snonaka break; 5411.5Snonaka case SCI_NOT_SUPPORTED: 5421.5Snonaka aprint_error("SCI is not supported\n"); 5431.5Snonaka break; 5441.5Snonaka case SCI_NOT_PRESENT: 5451.5Snonaka aprint_error("SCI is not present\n"); 5461.5Snonaka break; 5471.5Snonaka default: 5481.5Snonaka aprint_error("SCI: undefined behavior\n"); 5491.5Snonaka break; 5501.5Snonaka } 5511.1Sjakllsch } 5521.1Sjakllsch 5531.5Snonaka return rv; 5541.5Snonaka} 5551.5Snonaka 5561.5Snonaka/* 5571.5Snonaka * Enable/disable touchpad and trackpoint with HCI_ENABLE/HCI_DISABLE 5581.5Snonaka */ 5591.5Snonakastatic ACPI_STATUS 5601.5Snonakavalz_acpi_touchpad_toggle(struct valz_acpi_softc *sc) 5611.5Snonaka{ 5621.5Snonaka ACPI_STATUS rv; 5631.5Snonaka uint32_t result, status, value; 5641.1Sjakllsch 5651.5Snonaka rv = sci_open(sc); 5661.5Snonaka if (ACPI_FAILURE(rv)) 5671.5Snonaka aprint_error_dev(sc->sc_dev, 5681.5Snonaka "Cannot open SCI: %s\n", 5691.5Snonaka AcpiFormatException(rv)); 5701.5Snonaka 5711.5Snonaka rv = valz_acpi_hci_get(sc, SCI_GET, SCI_TOUCHPAD, &value, &result); 5721.5Snonaka if (ACPI_FAILURE(rv)) 5731.5Snonaka aprint_error_dev(sc->sc_dev, 5741.5Snonaka "Cannot get SCI touchpad status: %s\n", 5751.5Snonaka AcpiFormatException(rv)); 5761.5Snonaka 5771.5Snonaka switch (value) { 5781.5Snonaka case HCI_ENABLE: 5791.5Snonaka status = HCI_DISABLE; 5801.1Sjakllsch break; 5811.5Snonaka case HCI_DISABLE: 5821.5Snonaka status = HCI_ENABLE; 5831.1Sjakllsch break; 5841.1Sjakllsch default: 5851.5Snonaka status = HCI_ENABLE; 5861.5Snonaka break; 5871.1Sjakllsch } 5881.1Sjakllsch 5891.5Snonaka rv = valz_acpi_hci_set(sc, SCI_SET, SCI_TOUCHPAD, status, &result); 5901.5Snonaka if (ACPI_FAILURE(rv)) 5911.5Snonaka aprint_error_dev(sc->sc_dev, 5921.5Snonaka "Cannot set SCI touchpad status: %s\n", 5931.5Snonaka AcpiFormatException(rv)); 5941.1Sjakllsch 5951.5Snonaka rv = sci_close(sc); 5961.1Sjakllsch if (ACPI_FAILURE(rv)) 5971.5Snonaka aprint_error_dev(sc->sc_dev, 5981.5Snonaka "Cannot close SCI: %s\n", 5991.5Snonaka AcpiFormatException(rv)); 6001.5Snonaka 6011.5Snonaka return rv; 6021.1Sjakllsch} 6031.1Sjakllsch 6041.5Snonaka/* 6051.5Snonaka * Enable/disable LCD backlight with HCI_ENABLE/HCI_DISABLE 6061.5Snonaka */ 6071.5Snonakastatic ACPI_STATUS 6081.5Snonakavalz_acpi_lcd_backlight_toggle(struct valz_acpi_softc *sc) 6091.1Sjakllsch{ 6101.5Snonaka ACPI_STATUS rv; 6111.5Snonaka uint32_t result, status, value; 6121.5Snonaka 6131.5Snonaka rv = valz_acpi_hci_get(sc, HCI_GET, HCI_LCD_BACKLIGHT, &value, &result); 6141.5Snonaka if (ACPI_FAILURE(rv)) 6151.5Snonaka aprint_error_dev(sc->sc_dev, 6161.5Snonaka "Cannot get HCI LCD backlight status: %s\n", 6171.5Snonaka AcpiFormatException(rv)); 6181.5Snonaka 6191.5Snonaka switch (value) { 6201.5Snonaka case HCI_ON: 6211.5Snonaka status = HCI_OFF; 6221.5Snonaka break; 6231.5Snonaka case HCI_OFF: 6241.5Snonaka status = HCI_ON; 6251.5Snonaka break; 6261.5Snonaka default: 6271.5Snonaka status = HCI_ON; 6281.5Snonaka break; 6291.5Snonaka } 6301.5Snonaka 6311.5Snonaka rv = valz_acpi_hci_set(sc, HCI_SET, HCI_LCD_BACKLIGHT, status, &result); 6321.5Snonaka if (ACPI_FAILURE(rv)) 6331.5Snonaka aprint_error_dev(sc->sc_dev, 6341.5Snonaka "Cannot set HCI LCD backlight status: %s\n", 6351.5Snonaka AcpiFormatException(rv)); 6361.1Sjakllsch 6371.5Snonaka return rv; 6381.1Sjakllsch} 639