LCOV - code coverage report
Current view: top level - dev/acpi - acpithinkpad.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 306 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: acpithinkpad.c,v 1.61 2018/07/01 19:40:49 mlarkin Exp $       */
       2             : /*
       3             :  * Copyright (c) 2008 joshua stein <jcs@openbsd.org>
       4             :  *
       5             :  * Permission to use, copy, modify, and distribute this software for any
       6             :  * purpose with or without fee is hereby granted, provided that the above
       7             :  * copyright notice and this permission notice appear in all copies.
       8             :  *
       9             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      10             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      12             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      15             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16             :  */
      17             : 
      18             : #include <sys/param.h>
      19             : #include <sys/systm.h>
      20             : 
      21             : #include <dev/acpi/acpireg.h>
      22             : #include <dev/acpi/acpivar.h>
      23             : #include <dev/acpi/acpidev.h>
      24             : #include <dev/acpi/amltypes.h>
      25             : #include <dev/acpi/dsdt.h>
      26             : #include <dev/wscons/wsconsio.h>
      27             : 
      28             : #include <machine/apmvar.h>
      29             : 
      30             : #include "audio.h"
      31             : #include "wskbd.h"
      32             : 
      33             : /* #define ACPITHINKPAD_DEBUG */
      34             : 
      35             : #ifdef ACPITHINKPAD_DEBUG
      36             : #define DPRINTF(x) printf x
      37             : #else
      38             : #define DPRINTF(x)
      39             : #endif
      40             : 
      41             : #define THINKPAD_HKEY_VERSION1          0x0100
      42             : #define THINKPAD_HKEY_VERSION2          0x0200
      43             : 
      44             : #define THINKPAD_CMOS_VOLUME_DOWN       0x00
      45             : #define THINKPAD_CMOS_VOLUME_UP         0x01
      46             : #define THINKPAD_CMOS_VOLUME_MUTE       0x02
      47             : #define THINKPAD_CMOS_BRIGHTNESS_UP     0x04
      48             : #define THINKPAD_CMOS_BRIGHTNESS_DOWN   0x05
      49             : 
      50             : #define THINKPAD_BLUETOOTH_PRESENT      0x01
      51             : #define THINKPAD_BLUETOOTH_ENABLED      0x02
      52             : 
      53             : /* wan (not wifi) card */
      54             : #define THINKPAD_WAN_PRESENT            0x01
      55             : #define THINKPAD_WAN_ENABLED            0x02
      56             : 
      57             : #define THINKPAD_BUTTON_FN_F1           0x1001
      58             : #define THINKPAD_BUTTON_LOCK_SCREEN     0x1002
      59             : #define THINKPAD_BUTTON_BATTERY_INFO    0x1003
      60             : #define THINKPAD_BUTTON_SUSPEND         0x1004
      61             : #define THINKPAD_BUTTON_WIRELESS        0x1005
      62             : #define THINKPAD_BUTTON_FN_F6           0x1006
      63             : #define THINKPAD_BUTTON_EXTERNAL_SCREEN 0x1007
      64             : #define THINKPAD_BUTTON_POINTER_SWITCH  0x1008
      65             : #define THINKPAD_BUTTON_EJECT           0x1009
      66             : #define THINKPAD_BUTTON_FN_F11          0x100b
      67             : #define THINKPAD_BUTTON_HIBERNATE       0x100c
      68             : #define THINKPAD_BUTTON_BRIGHTNESS_UP   0x1010
      69             : #define THINKPAD_BUTTON_BRIGHTNESS_DOWN 0x1011
      70             : #define THINKPAD_BUTTON_THINKLIGHT      0x1012
      71             : #define THINKPAD_BUTTON_FN_SPACE        0x1014
      72             : #define THINKPAD_BUTTON_VOLUME_UP       0x1015
      73             : #define THINKPAD_BUTTON_VOLUME_DOWN     0x1016
      74             : #define THINKPAD_BUTTON_VOLUME_MUTE     0x1017
      75             : #define THINKPAD_BUTTON_THINKVANTAGE    0x1018
      76             : #define THINKPAD_BUTTON_BLACK           0x101a
      77             : #define THINKPAD_BUTTON_MICROPHONE_MUTE 0x101b
      78             : #define THINKPAD_KEYLIGHT_CHANGED       0x101c
      79             : #define THINKPAD_BUTTON_CONFIG          0x101d
      80             : #define THINKPAD_BUTTON_FIND            0x101e
      81             : #define THINKPAD_BUTTON_ALL_ACTIVEPROGS 0x101f
      82             : #define THINKPAD_BUTTON_ALL_PROGS       0x1020
      83             : 
      84             : #define THINKPAD_ADAPTIVE_NEXT          0x1101
      85             : #define THINKPAD_ADAPTIVE_QUICK         0x1102
      86             : #define THINKPAD_ADAPTIVE_SNIP          0x1105
      87             : #define THINKPAD_ADAPTIVE_VOICE         0x1108
      88             : #define THINKPAD_ADAPTIVE_GESTURES      0x110a
      89             : #define THINKPAD_ADAPTIVE_SETTINGS      0x110e
      90             : #define THINKPAD_ADAPTIVE_TAB           0x110f
      91             : #define THINKPAD_ADAPTIVE_REFRESH       0x1110
      92             : #define THINKPAD_ADAPTIVE_BACK          0x1111
      93             : #define THINKPAD_PORT_REPL_DOCKED       0x4010
      94             : #define THINKPAD_PORT_REPL_UNDOCKED     0x4011
      95             : #define THINKPAD_TABLET_DOCKED          0x4012
      96             : #define THINKPAD_TABLET_UNDOCKED        0x4013
      97             : #define THINKPAD_LID_OPEN               0x5001
      98             : #define THINKPAD_LID_CLOSED             0x5002
      99             : #define THINKPAD_TABLET_SCREEN_NORMAL   0x500a
     100             : #define THINKPAD_TABLET_SCREEN_ROTATED  0x5009
     101             : #define THINKPAD_BRIGHTNESS_CHANGED     0x5010
     102             : #define THINKPAD_TABLET_PEN_INSERTED    0x500b
     103             : #define THINKPAD_TABLET_PEN_REMOVED     0x500c
     104             : #define THINKPAD_SWITCH_NUMLOCK         0x6000
     105             : #define THINKPAD_BUTTON_ROTATION_LOCK   0x6020
     106             : #define THINKPAD_THERMAL_TABLE_CHANGED  0x6030
     107             : #define THINKPAD_POWER_CHANGED          0x6040
     108             : #define THINKPAD_BACKLIGHT_CHANGED      0x6050
     109             : #define THINKPAD_BUTTON_FN_TOGGLE       0x6060
     110             : #define THINKPAD_TABLET_SCREEN_CHANGED  0x60c0
     111             : #define THINKPAD_SWITCH_WIRELESS        0x7000
     112             : 
     113             : #define THINKPAD_NSENSORS 10
     114             : #define THINKPAD_NTEMPSENSORS 8
     115             : 
     116             : #define THINKPAD_SENSOR_FANRPM          THINKPAD_NTEMPSENSORS
     117             : #define THINKPAD_SENSOR_PORTREPL        THINKPAD_NTEMPSENSORS + 1
     118             : 
     119             : #define THINKPAD_ECOFFSET_VOLUME        0x30
     120             : #define THINKPAD_ECOFFSET_VOLUME_MUTE_MASK 0x40
     121             : #define THINKPAD_ECOFFSET_FANLO         0x84
     122             : #define THINKPAD_ECOFFSET_FANHI         0x85
     123             : 
     124             : #define THINKPAD_ADAPTIVE_MODE_HOME     1
     125             : #define THINKPAD_ADAPTIVE_MODE_FUNCTION 3
     126             : 
     127             : struct acpithinkpad_softc {
     128             :         struct device            sc_dev;
     129             : 
     130             :         struct acpiec_softc     *sc_ec;
     131             :         struct acpi_softc       *sc_acpi;
     132             :         struct aml_node         *sc_devnode;
     133             : 
     134             :         struct ksensor           sc_sens[THINKPAD_NSENSORS];
     135             :         struct ksensordev        sc_sensdev;
     136             : 
     137             :         uint64_t                 sc_thinklight;
     138             :         const char              *sc_thinklight_get;
     139             :         const char              *sc_thinklight_set;
     140             : 
     141             :         uint64_t                 sc_brightness;
     142             : };
     143             : 
     144             : extern void acpiec_read(struct acpiec_softc *, uint8_t, int, uint8_t *);
     145             : 
     146             : int     thinkpad_match(struct device *, void *, void *);
     147             : void    thinkpad_attach(struct device *, struct device *, void *);
     148             : int     thinkpad_hotkey(struct aml_node *, int, void *);
     149             : int     thinkpad_enable_events(struct acpithinkpad_softc *);
     150             : int     thinkpad_toggle_bluetooth(struct acpithinkpad_softc *);
     151             : int     thinkpad_toggle_wan(struct acpithinkpad_softc *);
     152             : int     thinkpad_cmos(struct acpithinkpad_softc *sc, uint8_t);
     153             : int     thinkpad_volume_down(struct acpithinkpad_softc *);
     154             : int     thinkpad_volume_up(struct acpithinkpad_softc *);
     155             : int     thinkpad_volume_mute(struct acpithinkpad_softc *);
     156             : int     thinkpad_brightness_up(struct acpithinkpad_softc *);
     157             : int     thinkpad_brightness_down(struct acpithinkpad_softc *);
     158             : int     thinkpad_adaptive_change(struct acpithinkpad_softc *);
     159             : int     thinkpad_activate(struct device *, int);
     160             : 
     161             : /* wscons hook functions */
     162             : void    thinkpad_get_thinklight(struct acpithinkpad_softc *);
     163             : void    thinkpad_set_thinklight(void *, int);
     164             : int     thinkpad_get_backlight(struct wskbd_backlight *);
     165             : int     thinkpad_set_backlight(struct wskbd_backlight *);
     166             : extern int (*wskbd_get_backlight)(struct wskbd_backlight *);
     167             : extern int (*wskbd_set_backlight)(struct wskbd_backlight *);
     168             : void    thinkpad_get_brightness(struct acpithinkpad_softc *);
     169             : void    thinkpad_set_brightness(void *, int);
     170             : int     thinkpad_get_param(struct wsdisplay_param *);
     171             : int     thinkpad_set_param(struct wsdisplay_param *);
     172             : extern int (*ws_get_param)(struct wsdisplay_param *);
     173             : extern int (*ws_set_param)(struct wsdisplay_param *);
     174             : 
     175             : void    thinkpad_sensor_attach(struct acpithinkpad_softc *sc);
     176             : void    thinkpad_sensor_refresh(void *);
     177             : 
     178             : #if NAUDIO > 0 && NWSKBD > 0
     179             : void thinkpad_attach_deferred(void *);
     180             : int thinkpad_get_volume_mute(struct acpithinkpad_softc *);
     181             : extern int wskbd_set_mixermute(long, long);
     182             : extern int wskbd_set_mixervolume(long, long);
     183             : #endif
     184             : 
     185             : struct cfattach acpithinkpad_ca = {
     186             :         sizeof(struct acpithinkpad_softc), thinkpad_match, thinkpad_attach,
     187             :         NULL, thinkpad_activate
     188             : };
     189             : 
     190             : struct cfdriver acpithinkpad_cd = {
     191             :         NULL, "acpithinkpad", DV_DULL
     192             : };
     193             : 
     194             : const char *acpithinkpad_hids[] = {
     195             :         "IBM0068",
     196             :         "LEN0068",
     197             :         "LEN0268",
     198             :         NULL
     199             : };
     200             : 
     201             : int
     202           0 : thinkpad_match(struct device *parent, void *match, void *aux)
     203             : {
     204           0 :         struct acpi_attach_args *aa = aux;
     205           0 :         struct cfdata *cf = match;
     206           0 :         int64_t res;
     207             : 
     208           0 :         if (!acpi_matchhids(aa, acpithinkpad_hids, cf->cf_driver->cd_name))
     209           0 :                 return (0);
     210             : 
     211           0 :         if (aml_evalinteger((struct acpi_softc *)parent, aa->aaa_node,
     212             :             "MHKV", 0, NULL, &res))
     213           0 :                 return (0);
     214             : 
     215           0 :         if (!(res == THINKPAD_HKEY_VERSION1 || res == THINKPAD_HKEY_VERSION2))
     216           0 :                 return (0);
     217             : 
     218           0 :         return (1);
     219           0 : }
     220             : 
     221             : void
     222           0 : thinkpad_sensor_attach(struct acpithinkpad_softc *sc)
     223             : {
     224             :         int i;
     225             : 
     226           0 :         if (sc->sc_acpi->sc_ec == NULL)
     227           0 :                 return;
     228           0 :         sc->sc_ec = sc->sc_acpi->sc_ec;
     229             : 
     230             :         /* Add temperature probes */
     231           0 :         strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
     232             :             sizeof(sc->sc_sensdev.xname));
     233           0 :         for (i=0; i<THINKPAD_NTEMPSENSORS; i++) {
     234           0 :                 sc->sc_sens[i].type = SENSOR_TEMP;
     235           0 :                 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[i]);
     236             :         }
     237             : 
     238             :         /* Add fan probe */
     239           0 :         sc->sc_sens[THINKPAD_SENSOR_FANRPM].type = SENSOR_FANRPM;
     240           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[THINKPAD_SENSOR_FANRPM]);
     241             : 
     242             :         /* Add port replicator indicator */
     243           0 :         sc->sc_sens[THINKPAD_SENSOR_PORTREPL].type = SENSOR_INDICATOR;
     244           0 :         sc->sc_sens[THINKPAD_SENSOR_PORTREPL].status = SENSOR_S_UNKNOWN;
     245           0 :         strlcpy(sc->sc_sens[THINKPAD_SENSOR_PORTREPL].desc, "port replicator",
     246             :                 sizeof(sc->sc_sens[THINKPAD_SENSOR_PORTREPL].desc));
     247           0 :         sensor_attach(&sc->sc_sensdev, &sc->sc_sens[THINKPAD_SENSOR_PORTREPL]);
     248             : 
     249           0 :         sensordev_install(&sc->sc_sensdev);
     250           0 : }
     251             : 
     252             : void
     253           0 : thinkpad_sensor_refresh(void *arg)
     254             : {
     255           0 :         struct acpithinkpad_softc *sc = arg;
     256           0 :         uint8_t lo, hi, i;
     257           0 :         int64_t tmp;
     258           0 :         char sname[5];
     259             : 
     260             :         /* Refresh sensor readings */
     261           0 :         for (i=0; i<THINKPAD_NTEMPSENSORS; i++) {
     262           0 :                 snprintf(sname, sizeof(sname), "TMP%d", i);
     263           0 :                 aml_evalinteger(sc->sc_acpi, sc->sc_ec->sc_devnode,
     264             :                     sname, 0, 0, &tmp);
     265           0 :                 sc->sc_sens[i].value = (tmp * 1000000) + 273150000;
     266           0 :                 if (tmp > 127 || tmp < -127)
     267           0 :                         sc->sc_sens[i].flags = SENSOR_FINVALID;
     268             :         }
     269             : 
     270             :         /* Read fan RPM */
     271           0 :         acpiec_read(sc->sc_ec, THINKPAD_ECOFFSET_FANLO, 1, &lo);
     272           0 :         acpiec_read(sc->sc_ec, THINKPAD_ECOFFSET_FANHI, 1, &hi);
     273           0 :         sc->sc_sens[THINKPAD_SENSOR_FANRPM].value = ((hi << 8L) + lo);
     274           0 : }
     275             : 
     276             : void
     277           0 : thinkpad_attach(struct device *parent, struct device *self, void *aux)
     278             : {
     279           0 :         struct acpithinkpad_softc *sc = (struct acpithinkpad_softc *)self;
     280           0 :         struct acpi_attach_args *aa = aux;
     281             : 
     282           0 :         sc->sc_acpi = (struct acpi_softc *)parent;
     283           0 :         sc->sc_devnode = aa->aaa_node;
     284             : 
     285           0 :         printf("\n");
     286             : 
     287             : #if NAUDIO > 0 && NWSKBD > 0
     288             :         /* Defer speaker mute */
     289           0 :         if (thinkpad_get_volume_mute(sc) == 1)
     290           0 :                 startuphook_establish(thinkpad_attach_deferred, sc);
     291             : #endif
     292             : 
     293             :         /* Set event mask to receive everything */
     294           0 :         thinkpad_enable_events(sc);
     295           0 :         thinkpad_sensor_attach(sc);
     296             : 
     297             :         /* Check for ThinkLight or keyboard backlight */
     298           0 :         if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "KLCG",
     299           0 :             0, NULL, &sc->sc_thinklight) == 0) {
     300           0 :                 sc->sc_thinklight_get = "KLCG";
     301           0 :                 sc->sc_thinklight_set = "KLCS";
     302           0 :                 wskbd_get_backlight = thinkpad_get_backlight;
     303           0 :                 wskbd_set_backlight = thinkpad_set_backlight;
     304           0 :         } else if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "MLCG",
     305           0 :             0, NULL, &sc->sc_thinklight) == 0) {
     306           0 :                 sc->sc_thinklight_get = "MLCG";
     307           0 :                 sc->sc_thinklight_set = "MLCS";
     308           0 :                 wskbd_get_backlight = thinkpad_get_backlight;
     309           0 :                 wskbd_set_backlight = thinkpad_set_backlight;
     310           0 :         }
     311             : 
     312           0 :         if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "PBLG",
     313           0 :             0, NULL, &sc->sc_brightness) == 0) {
     314           0 :                 ws_get_param = thinkpad_get_param;
     315           0 :                 ws_set_param = thinkpad_set_param;
     316           0 :         }
     317             : 
     318             :         /* Run thinkpad_hotkey on button presses */
     319           0 :         aml_register_notify(sc->sc_devnode, aa->aaa_dev,
     320           0 :             thinkpad_hotkey, sc, ACPIDEV_POLL);
     321           0 : }
     322             : 
     323             : int
     324           0 : thinkpad_enable_events(struct acpithinkpad_softc *sc)
     325             : {
     326           0 :         struct aml_value arg, args[2];
     327           0 :         int64_t mask;
     328             :         int i;
     329             : 
     330             :         /* Get the supported event mask */
     331           0 :         if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "MHKA",
     332             :             0, NULL, &mask)) {
     333           0 :                 printf("%s: no MHKA\n", DEVNAME(sc));
     334           0 :                 return (1);
     335             :         }
     336             : 
     337             :         /* Update hotkey mask */
     338           0 :         bzero(args, sizeof(args));
     339           0 :         args[0].type = args[1].type = AML_OBJTYPE_INTEGER;
     340           0 :         for (i = 0; i < 32; i++) {
     341           0 :                 args[0].v_integer = i + 1;
     342           0 :                 args[1].v_integer = (((1 << i) & mask) != 0);
     343             : 
     344           0 :                 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKM",
     345             :                     2, args, NULL)) {
     346           0 :                         printf("%s: couldn't toggle MHKM\n", DEVNAME(sc));
     347           0 :                         return (1);
     348             :                 }
     349             :         }
     350             : 
     351             :         /* Enable hotkeys */
     352           0 :         bzero(&arg, sizeof(arg));
     353           0 :         arg.type = AML_OBJTYPE_INTEGER;
     354           0 :         arg.v_integer = 1;
     355           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "MHKC",
     356             :             1, &arg, NULL)) {
     357           0 :                 printf("%s: couldn't enable hotkeys\n", DEVNAME(sc));
     358           0 :                 return (1);
     359             :         }
     360             : 
     361           0 :         return (0);
     362           0 : }
     363             : 
     364             : int
     365           0 : thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg)
     366             : {
     367           0 :         struct acpithinkpad_softc *sc = arg;
     368           0 :         int64_t event;
     369             : 
     370           0 :         if (notify_type == 0x00) {
     371             :                 /* Poll sensors */
     372           0 :                 thinkpad_sensor_refresh(sc);
     373           0 :                 return (0);
     374             :         }
     375             : 
     376           0 :         if (notify_type != 0x80)
     377           0 :                 return (1);
     378             : 
     379           0 :         for (;;) {
     380           0 :                 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "MHKP",
     381             :                     0, NULL, &event))
     382             :                         break;
     383           0 :                 if (event == 0)
     384             :                         break;
     385             : 
     386           0 :                 switch (event) {
     387             :                 case THINKPAD_BUTTON_BRIGHTNESS_UP:
     388           0 :                         thinkpad_brightness_up(sc);
     389           0 :                         break;
     390             :                 case THINKPAD_BUTTON_BRIGHTNESS_DOWN:
     391           0 :                         thinkpad_brightness_down(sc);
     392           0 :                         break;
     393             :                 case THINKPAD_BUTTON_WIRELESS:
     394           0 :                         thinkpad_toggle_bluetooth(sc);
     395           0 :                         break;
     396             :                 case THINKPAD_BUTTON_SUSPEND:
     397             : #ifndef SMALL_KERNEL
     398           0 :                         if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ))
     399           0 :                                 acpi_addtask(sc->sc_acpi, acpi_sleep_task, 
     400           0 :                                     sc->sc_acpi, ACPI_SLEEP_SUSPEND);
     401             : #endif
     402             :                         break;
     403             :                 case THINKPAD_BUTTON_VOLUME_MUTE:
     404           0 :                         thinkpad_volume_mute(sc);
     405           0 :                         break;
     406             :                 case THINKPAD_BUTTON_VOLUME_DOWN:
     407           0 :                         thinkpad_volume_down(sc);
     408           0 :                         break;
     409             :                 case THINKPAD_BUTTON_VOLUME_UP:
     410           0 :                         thinkpad_volume_up(sc);
     411           0 :                         break;
     412             :                 case THINKPAD_BUTTON_MICROPHONE_MUTE:
     413             : #if NAUDIO > 0 && NWSKBD > 0
     414           0 :                         wskbd_set_mixervolume(0, 0);
     415             : #endif
     416           0 :                         break;
     417             :                 case THINKPAD_BUTTON_HIBERNATE:
     418             : #if defined(HIBERNATE) && !defined(SMALL_KERNEL)
     419           0 :                         if (acpi_record_event(sc->sc_acpi, APM_USER_HIBERNATE_REQ))
     420           0 :                                 acpi_addtask(sc->sc_acpi, acpi_sleep_task, 
     421           0 :                                     sc->sc_acpi, ACPI_SLEEP_HIBERNATE);
     422             : #endif
     423             :                         break;
     424             :                 case THINKPAD_BUTTON_THINKLIGHT:
     425           0 :                         thinkpad_get_thinklight(sc);
     426           0 :                         break;
     427             :                 case THINKPAD_ADAPTIVE_NEXT:
     428             :                 case THINKPAD_ADAPTIVE_QUICK:
     429           0 :                         thinkpad_adaptive_change(sc);
     430           0 :                         break;
     431             :                 case THINKPAD_BACKLIGHT_CHANGED:
     432           0 :                         thinkpad_get_brightness(sc);
     433           0 :                         break;
     434             :                 case THINKPAD_PORT_REPL_DOCKED:
     435           0 :                         sc->sc_sens[THINKPAD_SENSOR_PORTREPL].value = 1;
     436           0 :                         sc->sc_sens[THINKPAD_SENSOR_PORTREPL].status = 
     437             :                             SENSOR_S_OK;
     438           0 :                         break;
     439             :                 case THINKPAD_PORT_REPL_UNDOCKED:
     440           0 :                         sc->sc_sens[THINKPAD_SENSOR_PORTREPL].value = 0;
     441           0 :                         sc->sc_sens[THINKPAD_SENSOR_PORTREPL].status = 
     442             :                             SENSOR_S_OK;
     443           0 :                         break;
     444             :                 default:
     445             :                         /* unknown or boring event */
     446             :                         DPRINTF(("%s: unhandled event 0x%03llx\n", DEVNAME(sc),
     447             :                             event));
     448             :                         break;
     449             :                 }
     450             :         }
     451             : 
     452           0 :         return (0);
     453           0 : }
     454             : 
     455             : int
     456           0 : thinkpad_toggle_bluetooth(struct acpithinkpad_softc *sc)
     457             : {
     458           0 :         struct aml_value arg;
     459           0 :         int64_t bluetooth;
     460             : 
     461           0 :         if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "GBDC",
     462             :             0, NULL, &bluetooth))
     463           0 :                 return (1);
     464             : 
     465           0 :         if (!(bluetooth & THINKPAD_BLUETOOTH_PRESENT))
     466           0 :                 return (1);
     467             : 
     468           0 :         bzero(&arg, sizeof(arg));
     469           0 :         arg.type = AML_OBJTYPE_INTEGER;
     470           0 :         arg.v_integer = bluetooth ^ THINKPAD_BLUETOOTH_ENABLED;
     471           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SBDC",
     472             :             1, &arg, NULL)) {
     473           0 :                 printf("%s: couldn't toggle bluetooth\n", DEVNAME(sc));
     474           0 :                 return (1);
     475             :         }
     476             : 
     477           0 :         return (0);
     478           0 : }
     479             : 
     480             : int
     481           0 : thinkpad_toggle_wan(struct acpithinkpad_softc *sc)
     482             : {
     483           0 :         struct aml_value arg;
     484           0 :         int64_t wan;
     485             : 
     486           0 :         if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "GWAN",
     487             :             0, NULL, &wan))
     488           0 :                 return (1);
     489             : 
     490           0 :         if (!(wan & THINKPAD_WAN_PRESENT))
     491           0 :                 return (1);
     492             : 
     493           0 :         bzero(&arg, sizeof(arg));
     494           0 :         arg.type = AML_OBJTYPE_INTEGER;
     495           0 :         arg.v_integer = wan ^ THINKPAD_WAN_ENABLED;
     496           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SWAN",
     497             :             1, &arg, NULL)) {
     498           0 :                 printf("%s: couldn't toggle wan\n", DEVNAME(sc));
     499           0 :                 return (1);
     500             :         }
     501             : 
     502           0 :         return (0);
     503           0 : }
     504             : 
     505             : int
     506           0 : thinkpad_cmos(struct acpithinkpad_softc *sc, uint8_t cmd)
     507             : {
     508           0 :         struct aml_value arg;
     509             : 
     510           0 :         bzero(&arg, sizeof(arg));
     511           0 :         arg.type = AML_OBJTYPE_INTEGER;
     512           0 :         arg.v_integer = cmd;
     513           0 :         aml_evalname(sc->sc_acpi, sc->sc_devnode, "\\UCMS", 1, &arg, NULL);
     514           0 :         return (0);
     515           0 : }
     516             : 
     517             : int
     518           0 : thinkpad_volume_down(struct acpithinkpad_softc *sc)
     519             : {
     520           0 :         return (thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_DOWN));
     521             : }
     522             : 
     523             : int
     524           0 : thinkpad_volume_up(struct acpithinkpad_softc *sc)
     525             : {
     526           0 :         return (thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_UP));
     527             : }
     528             : 
     529             : int
     530           0 : thinkpad_volume_mute(struct acpithinkpad_softc *sc)
     531             : {
     532           0 :         return (thinkpad_cmos(sc, THINKPAD_CMOS_VOLUME_MUTE));
     533             : }
     534             : 
     535             : int
     536           0 : thinkpad_brightness_up(struct acpithinkpad_softc *sc)
     537             : {
     538           0 :         return (thinkpad_cmos(sc, THINKPAD_CMOS_BRIGHTNESS_UP));
     539             : }
     540             : 
     541             : int
     542           0 : thinkpad_brightness_down(struct acpithinkpad_softc *sc)
     543             : {
     544           0 :         return (thinkpad_cmos(sc, THINKPAD_CMOS_BRIGHTNESS_DOWN));
     545             : }
     546             : 
     547             : int
     548           0 : thinkpad_adaptive_change(struct acpithinkpad_softc *sc)
     549             : {
     550           0 :         struct aml_value arg;
     551           0 :         int64_t mode;
     552             : 
     553           0 :         if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "GTRW",
     554             :             0, NULL, &mode)) {
     555           0 :                 printf("%s: couldn't get adaptive keyboard mode\n", DEVNAME(sc));
     556           0 :                 return (1);
     557             :         }
     558             : 
     559           0 :         bzero(&arg, sizeof(arg));
     560           0 :         arg.type = AML_OBJTYPE_INTEGER;
     561             : 
     562           0 :         if (mode == THINKPAD_ADAPTIVE_MODE_FUNCTION)
     563           0 :                 arg.v_integer = THINKPAD_ADAPTIVE_MODE_HOME;
     564             :         else
     565           0 :                 arg.v_integer = THINKPAD_ADAPTIVE_MODE_FUNCTION;
     566             : 
     567           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "STRW",
     568             :             1, &arg, NULL)) {
     569           0 :                 printf("%s: couldn't set adaptive keyboard mode\n", DEVNAME(sc));
     570           0 :                 return (1);
     571             :         }
     572             : 
     573           0 :         return (0);
     574           0 : }
     575             : 
     576             : int
     577           0 : thinkpad_activate(struct device *self, int act)
     578             : {
     579             : 
     580           0 :         struct acpithinkpad_softc *sc = (struct acpithinkpad_softc *)self;
     581           0 :         int64_t res;
     582             : #if NAUDIO > 0 && NWSKBD > 0
     583             :         int mute;
     584             : #endif
     585             : 
     586           0 :         switch (act) {
     587             :         case DVACT_WAKEUP:
     588           0 :                 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "GTRW",
     589           0 :                     0, NULL, &res) == 0)
     590           0 :                         thinkpad_adaptive_change(sc);
     591             : #if NAUDIO > 0 && NWSKBD > 0
     592           0 :                 mute = thinkpad_get_volume_mute(sc);
     593           0 :                 if (mute != -1)
     594           0 :                         wskbd_set_mixermute(mute, 1);
     595             : #endif
     596             :                 break;
     597             :         }
     598           0 :         return (0);
     599           0 : }
     600             : 
     601             : void
     602           0 : thinkpad_get_thinklight(struct acpithinkpad_softc *sc)
     603             : {
     604           0 :         if (sc->sc_thinklight_get)
     605           0 :                 aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
     606           0 :                     sc->sc_thinklight_get, 0, NULL, &sc->sc_thinklight);
     607           0 : }
     608             : 
     609             : void
     610           0 : thinkpad_set_thinklight(void *arg0, int arg1)
     611             : {
     612           0 :         struct acpithinkpad_softc *sc = arg0;
     613           0 :         struct aml_value arg;
     614             : 
     615           0 :         memset(&arg, 0, sizeof(arg));
     616           0 :         arg.type = AML_OBJTYPE_INTEGER;
     617           0 :         arg.v_integer = sc->sc_thinklight & 0x0f;
     618           0 :         aml_evalname(sc->sc_acpi, sc->sc_devnode,
     619           0 :             sc->sc_thinklight_set, 1, &arg, NULL);
     620           0 : }
     621             : 
     622             : int
     623           0 : thinkpad_get_backlight(struct wskbd_backlight *kbl)
     624             : {
     625           0 :         struct acpithinkpad_softc *sc = acpithinkpad_cd.cd_devs[0];
     626             : 
     627           0 :         KASSERT(sc != NULL);
     628             : 
     629           0 :         kbl->min = 0;
     630           0 :         kbl->max = (sc->sc_thinklight >> 8) & 0x0f;
     631           0 :         kbl->curval = sc->sc_thinklight & 0x0f;
     632             : 
     633           0 :         if (kbl->max == 0)
     634           0 :                 return (ENOTTY);
     635             : 
     636           0 :         return 0;
     637           0 : }
     638             : 
     639             : int
     640           0 : thinkpad_set_backlight(struct wskbd_backlight *kbl)
     641             : {
     642           0 :         struct acpithinkpad_softc *sc = acpithinkpad_cd.cd_devs[0];
     643             :         int maxval;
     644             : 
     645           0 :         KASSERT(sc != NULL);
     646             : 
     647           0 :         maxval = (sc->sc_thinklight >> 8) & 0x0f;
     648             : 
     649           0 :         if (maxval == 0)
     650           0 :                 return (ENOTTY);
     651             : 
     652           0 :         if (kbl->curval > maxval)
     653           0 :                 return EINVAL;
     654             : 
     655           0 :         sc->sc_thinklight &= ~0xff;
     656           0 :         sc->sc_thinklight |= kbl->curval;
     657           0 :         acpi_addtask(sc->sc_acpi, thinkpad_set_thinklight, sc, 0);
     658           0 :         acpi_wakeup(sc->sc_acpi);
     659           0 :         return 0;
     660           0 : }
     661             : 
     662             : void
     663           0 : thinkpad_get_brightness(struct acpithinkpad_softc *sc)
     664             : {
     665           0 :         aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
     666           0 :             "PBLG", 0, NULL, &sc->sc_brightness);
     667           0 : }
     668             : 
     669             : void
     670           0 : thinkpad_set_brightness(void *arg0, int arg1)
     671             : {
     672           0 :         struct acpithinkpad_softc *sc = arg0;
     673           0 :         struct aml_value arg;
     674             : 
     675           0 :         memset(&arg, 0, sizeof(arg));
     676           0 :         arg.type = AML_OBJTYPE_INTEGER;
     677           0 :         arg.v_integer = sc->sc_brightness & 0xff;
     678           0 :         aml_evalname(sc->sc_acpi, sc->sc_devnode,
     679             :             "PBLS", 1, &arg, NULL);
     680           0 : }
     681             : 
     682             : int
     683           0 : thinkpad_get_param(struct wsdisplay_param *dp)
     684             : {
     685           0 :         struct acpithinkpad_softc *sc = acpithinkpad_cd.cd_devs[0];
     686             : 
     687           0 :         if (sc == NULL)
     688           0 :                 return -1;
     689             : 
     690           0 :         switch (dp->param) {
     691             :         case WSDISPLAYIO_PARAM_BRIGHTNESS:
     692           0 :                 dp->min = 0;
     693           0 :                 dp->max = (sc->sc_brightness >> 8) & 0xff;
     694           0 :                 dp->curval = sc->sc_brightness & 0xff;
     695           0 :                 return 0;
     696             :         default:
     697           0 :                 return -1;
     698             :         }
     699           0 : }
     700             : 
     701             : int
     702           0 : thinkpad_set_param(struct wsdisplay_param *dp)
     703             : {
     704           0 :         struct acpithinkpad_softc *sc = acpithinkpad_cd.cd_devs[0];
     705             :         int maxval;
     706             : 
     707           0 :         if (sc == NULL)
     708           0 :                 return -1;
     709             : 
     710           0 :         maxval = (sc->sc_brightness >> 8) & 0xff;
     711             : 
     712           0 :         switch (dp->param) {
     713             :         case WSDISPLAYIO_PARAM_BRIGHTNESS:
     714           0 :                 if (dp->curval < 0)
     715           0 :                         dp->curval = 0;
     716           0 :                 if (dp->curval > maxval)
     717           0 :                         dp->curval = maxval;
     718           0 :                 sc->sc_brightness &= ~0xff;
     719           0 :                 sc->sc_brightness |= dp->curval;
     720           0 :                 acpi_addtask(sc->sc_acpi, thinkpad_set_brightness, sc, 0);
     721           0 :                 acpi_wakeup(sc->sc_acpi);
     722           0 :                 return 0;
     723             :         default:
     724           0 :                 return -1;
     725             :         }
     726           0 : }
     727             : 
     728             : #if NAUDIO > 0 && NWSKBD > 0
     729             : void
     730           0 : thinkpad_attach_deferred(void *v __unused)
     731             : {
     732           0 :         wskbd_set_mixermute(1, 1);
     733           0 : }
     734             : 
     735             : int
     736           0 : thinkpad_get_volume_mute(struct acpithinkpad_softc *sc)
     737             : {
     738           0 :         uint8_t vol = 0;
     739             : 
     740           0 :         if (sc->sc_acpi->sc_ec == NULL)
     741           0 :                 return (-1);
     742             : 
     743           0 :         acpiec_read(sc->sc_acpi->sc_ec, THINKPAD_ECOFFSET_VOLUME, 1, &vol);
     744           0 :         return ((vol & THINKPAD_ECOFFSET_VOLUME_MUTE_MASK) ==
     745             :             THINKPAD_ECOFFSET_VOLUME_MUTE_MASK);
     746           0 : }
     747             : #endif

Generated by: LCOV version 1.13