The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/acpica/acpi_asus.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2004 Philip Paeps <philip@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/5.4/sys/i386/acpica/acpi_asus.c 139342 2004-12-27 05:54:13Z njl $");
   30 
   31 /*
   32  * Driver for extra ACPI-controlled gadgets (hotkeys, leds, etc) found on
   33  * recent Asus (and Medion) laptops.  Inspired by the acpi4asus project which
   34  * implements these features in the Linux kernel.
   35  *
   36  *   <http://sourceforge.net/projects/acpi4asus/>
   37  *
   38  * Currently should support most features, but could use some more testing.
   39  * Particularly the display-switching stuff is a bit hairy.  If you have an
   40  * Asus laptop which doesn't appear to be supported, or strange things happen
   41  * when using this driver, please report to <acpi@FreeBSD.org>.
   42  *
   43  */
   44 
   45 #include "opt_acpi.h"
   46 #include <sys/param.h>
   47 #include <sys/kernel.h>
   48 #include <sys/module.h>
   49 #include <sys/bus.h>
   50 #include <sys/sbuf.h>
   51 
   52 #include "acpi.h"
   53 #include <dev/acpica/acpivar.h>
   54 #include <dev/led/led.h>
   55 
   56 #define _COMPONENT      ACPI_OEM
   57 ACPI_MODULE_NAME("ASUS")
   58 
   59 struct acpi_asus_model {
   60         char    *name;
   61 
   62         char    *mled_set;
   63         char    *tled_set;
   64         char    *wled_set;
   65 
   66         char    *brn_get;
   67         char    *brn_set;
   68         char    *brn_up;
   69         char    *brn_dn;
   70 
   71         char    *lcd_get;
   72         char    *lcd_set;
   73 
   74         char    *disp_get;
   75         char    *disp_set;
   76 };
   77 
   78 struct acpi_asus_led {
   79         struct cdev     *cdev;
   80         device_t        dev;
   81         enum {
   82                 ACPI_ASUS_LED_MLED,
   83                 ACPI_ASUS_LED_TLED,
   84                 ACPI_ASUS_LED_WLED,
   85         } type;
   86 };
   87 
   88 struct acpi_asus_softc {
   89         device_t                dev;
   90         ACPI_HANDLE             handle;
   91 
   92         struct acpi_asus_model  *model;
   93         struct sysctl_ctx_list  sysctl_ctx;
   94         struct sysctl_oid       *sysctl_tree;
   95 
   96         struct acpi_asus_led    s_mled;
   97         struct acpi_asus_led    s_tled;
   98         struct acpi_asus_led    s_wled;
   99 
  100         int                     s_brn;
  101         int                     s_disp;
  102         int                     s_lcd;
  103 };
  104 
  105 /*
  106  * We can identify Asus laptops from the string they return
  107  * as a result of calling the ATK0100 'INIT' method.
  108  */
  109 static struct acpi_asus_model acpi_asus_models[] = {
  110         {
  111                 .name           = "L2D",
  112                 .mled_set       = "MLED",
  113                 .wled_set       = "WLED",
  114                 .brn_up         = "\\Q0E",
  115                 .brn_dn         = "\\Q0F",
  116                 .lcd_get        = "\\SGP0",
  117                 .lcd_set        = "\\Q10"
  118         },
  119         {
  120                 .name           = "L3C",
  121                 .mled_set       = "MLED",
  122                 .wled_set       = "WLED",
  123                 .brn_get        = "GPLV",
  124                 .brn_set        = "SPLV",
  125                 .lcd_get        = "\\GL32",
  126                 .lcd_set        = "\\_SB.PCI0.PX40.ECD0._Q10"
  127         },
  128         {
  129                 .name           = "L3D",
  130                 .mled_set       = "MLED",
  131                 .wled_set       = "WLED",
  132                 .brn_get        = "GPLV",
  133                 .brn_set        = "SPLV",
  134                 .lcd_get        = "\\BKLG",
  135                 .lcd_set        = "\\Q10"
  136         },
  137         {
  138                 .name           = "L3H",
  139                 .mled_set       = "MLED",
  140                 .wled_set       = "WLED",
  141                 .brn_get        = "GPLV",
  142                 .brn_set        = "SPLV",
  143                 .lcd_get        = "\\_SB.PCI0.PM.PBC",
  144                 .lcd_set        = "EHK",
  145                 .disp_get       = "\\_SB.INFB",
  146                 .disp_set       = "SDSP"
  147         },
  148         {
  149                 .name           = "L8L"
  150                 /* Only has hotkeys, apparantly */
  151         },
  152         {
  153                 .name           = "M1A",
  154                 .mled_set       = "MLED",
  155                 .brn_up         = "\\_SB.PCI0.PX40.EC0.Q0E",
  156                 .brn_dn         = "\\_SB.PCI0.PX40.EC0.Q0F",
  157                 .lcd_get        = "\\PNOF",
  158                 .lcd_set        = "\\_SB.PCI0.PX40.EC0.Q10"
  159         },
  160         {
  161                 .name           = "M2E",
  162                 .mled_set       = "MLED",
  163                 .wled_set       = "WLED",
  164                 .brn_get        = "GPLV",
  165                 .brn_set        = "SPLV",
  166                 .lcd_get        = "\\GP06",
  167                 .lcd_set        = "\\Q10"
  168         },
  169 
  170         { .name = NULL }
  171 };
  172 
  173 /*
  174  * Samsung P30/P35 laptops have an Asus ATK0100 gadget interface,
  175  * but they can't be probed quite the same way as Asus laptops.
  176  */
  177 static struct acpi_asus_model acpi_samsung_models[] = {
  178         {
  179                 .name           = "P30",
  180                 .wled_set       = "WLED",
  181                 .brn_up         = "\\_SB.PCI0.LPCB.EC0._Q68",
  182                 .brn_dn         = "\\_SB.PCI0.LPCB.EC0._Q69",
  183                 .lcd_get        = "\\BKLT",
  184                 .lcd_set        = "\\_SB.PCI0.LPCB.EC0._Q0E"
  185         },
  186 
  187         { .name = NULL }
  188 };
  189 
  190 ACPI_SERIAL_DECL(asus, "ACPI ASUS extras");
  191 
  192 /* Function prototypes */
  193 static int      acpi_asus_probe(device_t dev);
  194 static int      acpi_asus_attach(device_t dev);
  195 static int      acpi_asus_detach(device_t dev);
  196 
  197 static void     acpi_asus_led(struct acpi_asus_led *led, int state);
  198 
  199 static int      acpi_asus_sysctl_brn(SYSCTL_HANDLER_ARGS);
  200 static int      acpi_asus_sysctl_lcd(SYSCTL_HANDLER_ARGS);
  201 static int      acpi_asus_sysctl_disp(SYSCTL_HANDLER_ARGS);
  202 
  203 static void     acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context);
  204 
  205 static device_method_t acpi_asus_methods[] = {
  206         DEVMETHOD(device_probe,  acpi_asus_probe),
  207         DEVMETHOD(device_attach, acpi_asus_attach),
  208         DEVMETHOD(device_detach, acpi_asus_detach),
  209 
  210         { 0, 0 }
  211 };
  212 
  213 static driver_t acpi_asus_driver = {
  214         "acpi_asus",
  215         acpi_asus_methods,
  216         sizeof(struct acpi_asus_softc)
  217 };
  218 
  219 static devclass_t acpi_asus_devclass;
  220 
  221 DRIVER_MODULE(acpi_asus, acpi, acpi_asus_driver, acpi_asus_devclass, 0, 0);
  222 MODULE_DEPEND(acpi_asus, acpi, 1, 1, 1);
  223 
  224 static int
  225 acpi_asus_probe(device_t dev)
  226 {
  227         struct acpi_asus_model  *model;
  228         struct acpi_asus_softc  *sc;
  229         struct sbuf             *sb;
  230         ACPI_BUFFER             Buf;
  231         ACPI_OBJECT             Arg, *Obj;
  232         ACPI_OBJECT_LIST        Args;
  233         static char             *asus_ids[] = { "ATK0100", NULL };
  234 
  235         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  236 
  237         if (!acpi_disabled("asus") &&
  238             ACPI_ID_PROBE(device_get_parent(dev), dev, asus_ids)) {
  239                 sc = device_get_softc(dev);
  240                 sc->dev = dev;
  241                 sc->handle = acpi_get_handle(dev);
  242         
  243                 Arg.Type = ACPI_TYPE_INTEGER;
  244                 Arg.Integer.Value = 0;
  245 
  246                 Args.Count = 1;
  247                 Args.Pointer = &Arg;
  248 
  249                 Buf.Pointer = NULL;
  250                 Buf.Length = ACPI_ALLOCATE_BUFFER;
  251         
  252                 AcpiEvaluateObject(sc->handle, "INIT", &Args, &Buf);
  253                 Obj = Buf.Pointer;
  254 
  255                 /*
  256                  * The Samsung P30 returns a null-pointer from INIT, we
  257                  * can identify it from the 'ODEM' string in the DSDT.
  258                  */
  259                 if (Obj->String.Pointer == NULL) {
  260                         ACPI_STATUS             status;
  261                         ACPI_TABLE_HEADER       th;
  262 
  263                         status = AcpiGetTableHeader(ACPI_TABLE_DSDT, 1, &th);
  264                         if (ACPI_FAILURE(status)) {
  265                                 device_printf(dev, "Unsupported laptop\n");
  266                                 AcpiOsFree(Buf.Pointer);
  267                                 return (ENXIO);
  268                         }
  269 
  270                         if (strncmp("ODEM", th.OemTableId, 4) == 0) {
  271                                 sc->model = &acpi_samsung_models[0];
  272                                 device_set_desc(dev,
  273                                     "Samsung P30 Laptop Extras");
  274                                 AcpiOsFree(Buf.Pointer);
  275                                 return (0);
  276                         }
  277                 }
  278 
  279                 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
  280                                 
  281                 if (sb == NULL)
  282                         return (ENOMEM);
  283 
  284                 /*
  285                  * Asus laptops are simply identified by name, easy!
  286                  */
  287                 for (model = acpi_asus_models; model->name != NULL; model++)
  288                         if (strcmp(Obj->String.Pointer, model->name) == 0) {
  289                                 sbuf_printf(sb, "Asus %s Laptop Extras",
  290                                     Obj->String.Pointer);
  291                                 sbuf_finish(sb);
  292                                 
  293                                 sc->model = model;
  294                                 device_set_desc(dev, sbuf_data(sb));
  295 
  296                                 sbuf_delete(sb);
  297                                 AcpiOsFree(Buf.Pointer);
  298                                 return (0);
  299                         }
  300 
  301                 sbuf_printf(sb, "Unsupported Asus laptop detected: %s\n",
  302                     Obj->String.Pointer);
  303                 sbuf_finish(sb);
  304 
  305                 device_printf(dev, sbuf_data(sb));
  306 
  307                 sbuf_delete(sb);
  308                 AcpiOsFree(Buf.Pointer);
  309         }
  310 
  311         return (ENXIO);
  312 }
  313 
  314 static int
  315 acpi_asus_attach(device_t dev)
  316 {
  317         struct acpi_asus_softc  *sc;
  318         struct acpi_softc       *acpi_sc;
  319 
  320         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  321 
  322         sc = device_get_softc(dev);
  323         acpi_sc = acpi_device_get_parent_softc(dev);
  324 
  325         /* Build sysctl tree */
  326         sysctl_ctx_init(&sc->sysctl_ctx);
  327         sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
  328             SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
  329             OID_AUTO, "asus", CTLFLAG_RD, 0, "");
  330 
  331         /* Attach leds */
  332         if (sc->model->mled_set) {
  333                 sc->s_mled.dev = dev;
  334                 sc->s_mled.type = ACPI_ASUS_LED_MLED;
  335                 sc->s_mled.cdev =
  336                     led_create((led_t *)acpi_asus_led, &sc->s_mled, "mled");
  337         }
  338 
  339         if (sc->model->tled_set) {
  340                 sc->s_tled.dev = dev;
  341                 sc->s_tled.type = ACPI_ASUS_LED_TLED;
  342                 sc->s_tled.cdev =
  343                     led_create((led_t *)acpi_asus_led, &sc->s_tled, "tled");
  344         }
  345 
  346         if (sc->model->wled_set) {
  347                 sc->s_wled.dev = dev;
  348                 sc->s_wled.type = ACPI_ASUS_LED_WLED;
  349                 sc->s_wled.cdev =
  350                     led_create((led_t *)acpi_asus_led, &sc->s_wled, "wled");
  351         }
  352 
  353         /* Attach brightness for GPLV/SPLV models */
  354         if (sc->model->brn_get && ACPI_SUCCESS(acpi_GetInteger(sc->handle,
  355             sc->model->brn_get, &sc->s_brn)))
  356                 SYSCTL_ADD_PROC(&sc->sysctl_ctx,
  357                     SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  358                     "lcd_brightness", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
  359                     acpi_asus_sysctl_brn, "I", "brightness of the lcd panel");
  360 
  361         /* Attach brightness for other models */
  362         if (sc->model->brn_up &&
  363             ACPI_SUCCESS(AcpiEvaluateObject(sc->handle, sc->model->brn_up,
  364             NULL, NULL)) &&
  365             ACPI_SUCCESS(AcpiEvaluateObject(sc->handle, sc->model->brn_dn,
  366             NULL, NULL)))
  367                 SYSCTL_ADD_PROC(&sc->sysctl_ctx,
  368                     SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  369                     "lcd_brightness", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
  370                     acpi_asus_sysctl_brn, "I", "brightness of the lcd panel");
  371 
  372         /* Attach display switching */
  373         if (sc->model->disp_get && ACPI_SUCCESS(acpi_GetInteger(sc->handle,
  374             sc->model->disp_get, &sc->s_disp)))
  375                 SYSCTL_ADD_PROC(&sc->sysctl_ctx,
  376                     SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  377                     "video_output", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
  378                     acpi_asus_sysctl_disp, "I", "display output state");
  379 
  380         /* Attach LCD state, easy for most models... */
  381         if (sc->model->lcd_get && strncmp(sc->model->name, "L3H", 3) != 0 &&
  382             ACPI_SUCCESS(acpi_GetInteger(sc->handle, sc->model->lcd_get,
  383             &sc->s_lcd))) {
  384                 SYSCTL_ADD_PROC(&sc->sysctl_ctx,
  385                     SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  386                     "lcd_backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
  387                     acpi_asus_sysctl_lcd, "I", "state of the lcd backlight");
  388         } else if (sc->model->lcd_get) {
  389                 ACPI_BUFFER             Buf;
  390                 ACPI_OBJECT             Arg[2], Obj;
  391                 ACPI_OBJECT_LIST        Args;
  392 
  393                 /* ...a nightmare for the L3H */
  394                 Arg[0].Type = ACPI_TYPE_INTEGER;
  395                 Arg[0].Integer.Value = 0x02;
  396                 Arg[1].Type = ACPI_TYPE_INTEGER;
  397                 Arg[1].Integer.Value = 0x03;
  398 
  399                 Args.Count = 2;
  400                 Args.Pointer = Arg;
  401 
  402                 Buf.Length = sizeof(Obj);
  403                 Buf.Pointer = &Obj;
  404 
  405                 if (ACPI_SUCCESS(AcpiEvaluateObject(sc->handle,
  406                     sc->model->lcd_get, &Args, &Buf)) &&
  407                     Obj.Type == ACPI_TYPE_INTEGER) {
  408                         sc->s_lcd = Obj.Integer.Value >> 8;
  409 
  410                         SYSCTL_ADD_PROC(&sc->sysctl_ctx,
  411                             SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
  412                             "lcd_backlight", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
  413                             acpi_asus_sysctl_lcd, "I",
  414                             "state of the lcd backlight");
  415                 }
  416         }
  417 
  418         /* Activate hotkeys */
  419         AcpiEvaluateObject(sc->handle, "BSTS", NULL, NULL);
  420 
  421         /* Handle notifies */
  422         AcpiInstallNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
  423             acpi_asus_notify, dev);
  424         
  425         return (0);
  426 }
  427 
  428 static int
  429 acpi_asus_detach(device_t dev)
  430 {
  431         struct acpi_asus_softc  *sc;
  432         
  433         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  434 
  435         sc = device_get_softc(dev);
  436 
  437         /* Turn the lights off */
  438         if (sc->model->mled_set)
  439                 led_destroy(sc->s_mled.cdev);
  440 
  441         if (sc->model->tled_set)
  442                 led_destroy(sc->s_tled.cdev);
  443 
  444         if (sc->model->wled_set)
  445                 led_destroy(sc->s_wled.cdev);
  446 
  447         /* Remove notify handler */
  448         AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
  449             acpi_asus_notify);
  450 
  451         /* Free sysctl tree */
  452         sysctl_ctx_free(&sc->sysctl_ctx);
  453 
  454         return (0);
  455 }
  456 
  457 static void
  458 acpi_asus_led(struct acpi_asus_led *led, int state)
  459 {
  460         struct acpi_asus_softc  *sc;
  461         char                    *method;
  462 
  463         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  464 
  465         sc = device_get_softc(led->dev);
  466 
  467         switch (led->type) {
  468                 case ACPI_ASUS_LED_MLED:
  469                         method = sc->model->mled_set;
  470 
  471                         /* Note: inverted */
  472                         state = !state;
  473                         break;
  474                 case ACPI_ASUS_LED_TLED:
  475                         method = sc->model->tled_set;
  476                         break;
  477                 case ACPI_ASUS_LED_WLED:
  478                         method = sc->model->wled_set;
  479                         break;
  480                 default:
  481                         printf("acpi_asus_led: invalid LED type %d\n",
  482                             (int)led->type);
  483                         return;
  484         }
  485 
  486         acpi_SetInteger(sc->handle, method, state);
  487 }
  488 
  489 static int
  490 acpi_asus_sysctl_brn(SYSCTL_HANDLER_ARGS)
  491 {
  492         struct acpi_asus_softc  *sc;
  493         int                     brn, err;
  494 
  495         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  496 
  497         sc = (struct acpi_asus_softc *)oidp->oid_arg1;
  498         ACPI_SERIAL_BEGIN(asus);
  499 
  500         /* Sanity check */
  501         brn = sc->s_brn;
  502         err = sysctl_handle_int(oidp, &brn, 0, req);
  503 
  504         if (err != 0 || req->newptr == NULL)
  505                 goto out;
  506 
  507         if (brn < 0 || brn > 15) {
  508                 err = EINVAL;
  509                 goto out;
  510         }
  511 
  512         /* Keep track and update */
  513         sc->s_brn = brn;
  514 
  515         if (sc->model->brn_set)
  516                 acpi_SetInteger(sc->handle, sc->model->brn_set, brn);
  517         else {
  518                 brn -= sc->s_brn;
  519 
  520                 while (brn != 0) {
  521                         AcpiEvaluateObject(sc->handle, (brn > 0) ?
  522                             sc->model->brn_up : sc->model->brn_dn,
  523                             NULL, NULL);
  524                         (brn > 0) ? brn-- : brn++;
  525                 }
  526         }
  527 
  528 out:
  529         ACPI_SERIAL_END(asus);
  530         return (err);
  531 }
  532 
  533 static int
  534 acpi_asus_sysctl_lcd(SYSCTL_HANDLER_ARGS)
  535 {
  536         struct acpi_asus_softc  *sc;
  537         int                     lcd, err;
  538 
  539         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  540 
  541         sc = (struct acpi_asus_softc *)oidp->oid_arg1;
  542         ACPI_SERIAL_BEGIN(asus);
  543 
  544         /* Sanity check */
  545         lcd = sc->s_lcd;
  546         err = sysctl_handle_int(oidp, &lcd, 0, req);
  547 
  548         if (err != 0 || req->newptr == NULL)
  549                 goto out;
  550 
  551         if (lcd < 0 || lcd > 1) {
  552                 err = EINVAL;
  553                 goto out;
  554         }
  555 
  556         /* Keep track and update */
  557         sc->s_lcd = lcd;
  558 
  559         /* Most models just need a lcd_set evaluated, the L3H is trickier */
  560         if (strncmp(sc->model->name, "L3H", 3) != 0)
  561                 AcpiEvaluateObject(sc->handle, sc->model->lcd_set, NULL, NULL);
  562         else
  563                 acpi_SetInteger(sc->handle, sc->model->lcd_set, 0x7);
  564 
  565 out:
  566         ACPI_SERIAL_END(asus);
  567         return (err);
  568 }
  569 
  570 static int
  571 acpi_asus_sysctl_disp(SYSCTL_HANDLER_ARGS)
  572 {
  573         struct acpi_asus_softc  *sc;
  574         int                     disp, err;
  575 
  576         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  577 
  578         sc = (struct acpi_asus_softc *)oidp->oid_arg1;
  579 
  580         /* Sanity check */
  581         ACPI_SERIAL_BEGIN(asus);
  582         disp = sc->s_disp;
  583         err = sysctl_handle_int(oidp, &disp, 0, req);
  584 
  585         if (err != 0 || req->newptr == NULL)
  586                 goto out;
  587 
  588         if (disp < 0 || disp > 7) {
  589                 err = EINVAL;
  590                 goto out;
  591         }
  592 
  593         /* Keep track and update */
  594         sc->s_disp = disp;
  595         acpi_SetInteger(sc->handle, sc->model->disp_set, disp);
  596 
  597 out:
  598         ACPI_SERIAL_END(asus);
  599         return (err);
  600 }
  601 
  602 static void
  603 acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context)
  604 {
  605         struct acpi_asus_softc  *sc;
  606         struct acpi_softc       *acpi_sc;
  607 
  608         ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  609 
  610         sc = device_get_softc((device_t)context);
  611         acpi_sc = acpi_device_get_parent_softc(sc->dev);
  612 
  613         ACPI_SERIAL_BEGIN(asus);
  614         if ((notify & ~0x10) <= 15) {
  615                 sc->s_brn = notify & ~0x10;
  616                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
  617         } else if ((notify & ~0x20) <= 15) {
  618                 sc->s_brn = notify & ~0x20;
  619                 ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
  620         } else if (notify == 0x33) {
  621                 sc->s_lcd = 1;
  622                 ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned on\n");
  623         } else if (notify == 0x34) {
  624                 sc->s_lcd = 0;
  625                 ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned off\n");
  626         } else {
  627                 /* Notify devd(8) */
  628                 acpi_UserNotify("ASUS", h, notify);
  629         }
  630         ACPI_SERIAL_END(asus);
  631 }

Cache object: 9c48fe78c46596d61dd8397e5441dd2b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.