Author: jkim
Date: Wed Mar 10 18:13:17 2010
New Revision: 204964
URL: http://svn.freebsd.org/changeset/base/204964

Log:
  MFC:  r197438, r203810, r203813, r203935, r203936
  
  Sync acpi_video(4) with HEAD.
  
  r197438:
  Uninline an instance of STAILQ_FOREACH_SAFE().
  
  r203810:
  Implement LCD brightness control notify handler.
  
  r203813:
  Make sanity check slightly more useful and tweak an error message.
  
  r203935:
  Add support for `cycle' and `zero' events for LCD brightness control.
  
  r203936:
  Rename some macros to clarify their intentions and fix style nits.

Modified:
  stable/7/sys/dev/acpica/acpi_video.c
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/dev/acpica/acpi_video.c
==============================================================================
--- stable/7/sys/dev/acpica/acpi_video.c        Wed Mar 10 17:58:32 2010        
(r204963)
+++ stable/7/sys/dev/acpica/acpi_video.c        Wed Mar 10 18:13:17 2010        
(r204964)
@@ -82,6 +82,7 @@ static struct acpi_video_output *acpi_vi
 static void    acpi_video_vo_bind(struct acpi_video_output *, ACPI_HANDLE);
 static void    acpi_video_vo_destroy(struct acpi_video_output *);
 static int     acpi_video_vo_check_level(struct acpi_video_output *, int);
+static void    acpi_video_vo_notify_handler(ACPI_HANDLE, UINT32, void *);
 static int     acpi_video_vo_active_sysctl(SYSCTL_HANDLER_ARGS);
 static int     acpi_video_vo_bright_sysctl(SYSCTL_HANDLER_ARGS);
 static int     acpi_video_vo_presets_sysctl(SYSCTL_HANDLER_ARGS);
@@ -92,56 +93,61 @@ static void vid_set_switch_policy(ACPI_H
 static int     vid_enum_outputs(ACPI_HANDLE,
                    void(*)(ACPI_HANDLE, UINT32, void *), void *);
 static int     vo_get_brightness_levels(ACPI_HANDLE, int **);
+static int     vo_get_brightness(ACPI_HANDLE);
 static void    vo_set_brightness(ACPI_HANDLE, int);
 static UINT32  vo_get_device_status(ACPI_HANDLE);
 static UINT32  vo_get_graphics_state(ACPI_HANDLE);
 static void    vo_set_device_state(ACPI_HANDLE, UINT32);
 
 /* events */
-#define VID_NOTIFY_SWITCHED    0x80
-#define VID_NOTIFY_REPROBE     0x81
+#define        VID_NOTIFY_SWITCHED     0x80
+#define        VID_NOTIFY_REPROBE      0x81
+#define        VID_NOTIFY_CYCLE_BRN    0x85
+#define        VID_NOTIFY_INC_BRN      0x86
+#define        VID_NOTIFY_DEC_BRN      0x87
+#define        VID_NOTIFY_ZERO_BRN     0x88
 
 /* _DOS (Enable/Disable Output Switching) argument bits */
-#define DOS_SWITCH_MASK                3
-#define DOS_SWITCH_BY_OSPM     0
-#define DOS_SWITCH_BY_BIOS     1
-#define DOS_SWITCH_LOCKED      2
-#define DOS_BRIGHTNESS_BY_BIOS (1 << 2)
+#define        DOS_SWITCH_MASK         3
+#define        DOS_SWITCH_BY_OSPM      0
+#define        DOS_SWITCH_BY_BIOS      1
+#define        DOS_SWITCH_LOCKED       2
+#define        DOS_BRIGHTNESS_BY_OSPM  (1 << 2)
 
 /* _DOD and subdev's _ADR */
-#define DOD_DEVID_MASK         0x0f00
-#define DOD_DEVID_MASK_FULL    0xffff
-#define DOD_DEVID_MASK_DISPIDX 0x000f
-#define DOD_DEVID_MASK_DISPPORT        0x00f0
-#define DOD_DEVID_MONITOR      0x0100
-#define DOD_DEVID_LCD          0x0110
-#define DOD_DEVID_TV           0x0200
-#define DOD_DEVID_EXT          0x0300
-#define DOD_DEVID_INTDFP       0x0400
-#define DOD_BIOS               (1 << 16)
-#define DOD_NONVGA             (1 << 17)
-#define DOD_HEAD_ID_SHIFT      18
-#define DOD_HEAD_ID_BITS       3
-#define DOD_HEAD_ID_MASK \
+#define        DOD_DEVID_MASK          0x0f00
+#define        DOD_DEVID_MASK_FULL     0xffff
+#define        DOD_DEVID_MASK_DISPIDX  0x000f
+#define        DOD_DEVID_MASK_DISPPORT 0x00f0
+#define        DOD_DEVID_MONITOR       0x0100
+#define        DOD_DEVID_LCD           0x0110
+#define        DOD_DEVID_TV            0x0200
+#define        DOD_DEVID_EXT           0x0300
+#define        DOD_DEVID_INTDFP        0x0400
+#define        DOD_BIOS                (1 << 16)
+#define        DOD_NONVGA              (1 << 17)
+#define        DOD_HEAD_ID_SHIFT       18
+#define        DOD_HEAD_ID_BITS        3
+#define        DOD_HEAD_ID_MASK \
                (((1 << DOD_HEAD_ID_BITS) - 1) << DOD_HEAD_ID_SHIFT)
-#define DOD_DEVID_SCHEME_STD   (1 << 31)
+#define        DOD_DEVID_SCHEME_STD    (1 << 31)
 
 /* _BCL related constants */
-#define BCL_FULLPOWER          0
-#define BCL_ECONOMY            1
+#define        BCL_FULLPOWER           0
+#define        BCL_ECONOMY             1
 
 /* _DCS (Device Currrent Status) value bits and masks. */
-#define DCS_EXISTS             (1 << 0)
-#define DCS_ACTIVE             (1 << 1)
-#define DCS_READY              (1 << 2)
-#define DCS_FUNCTIONAL         (1 << 3)
-#define DCS_ATTACHED           (1 << 4)
+#define        DCS_EXISTS              (1 << 0)
+#define        DCS_ACTIVE              (1 << 1)
+#define        DCS_READY               (1 << 2)
+#define        DCS_FUNCTIONAL          (1 << 3)
+#define        DCS_ATTACHED            (1 << 4)
 
 /* _DSS (Device Set Status) argument bits and masks. */
-#define DSS_INACTIVE           0
-#define DSS_ACTIVE             (1 << 0)
-#define DSS_SETNEXT            (1 << 30)
-#define DSS_COMMIT             (1 << 31)
+#define        DSS_INACTIVE            0
+#define        DSS_ACTIVE              (1 << 0)
+#define        DSS_SETNEXT             (1 << 30)
+#define        DSS_COMMIT              (1 << 31)
 
 static device_method_t acpi_video_methods[] = {
        DEVMETHOD(device_identify, acpi_video_identify),
@@ -268,7 +274,7 @@ acpi_video_attach(device_t dev)
         * brightness levels.
         */
        vid_set_switch_policy(sc->handle, DOS_SWITCH_BY_OSPM |
-           DOS_BRIGHTNESS_BY_BIOS);
+           DOS_BRIGHTNESS_BY_OSPM);
 
        acpi_video_power_profile(sc);
 
@@ -289,8 +295,7 @@ acpi_video_detach(device_t dev)
                                acpi_video_notify_handler);
 
        ACPI_SERIAL_BEGIN(video);
-       for (vo = STAILQ_FIRST(&sc->vid_outputs); vo != NULL; vo = vn) {
-               vn = STAILQ_NEXT(vo, vo_next);
+       STAILQ_FOREACH_SAFE(vo, &sc->vid_outputs, vo_next, vn) {
                acpi_video_vo_destroy(vo);
        }
        ACPI_SERIAL_END(video);
@@ -577,6 +582,9 @@ acpi_video_vo_bind(struct acpi_video_out
                        /* XXX - see above. */
                        vo->vo_economy = vo->vo_levels[BCL_ECONOMY];
        }
+       if (vo->vo_levels != NULL)
+           AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY,
+               acpi_video_vo_notify_handler, vo);
        ACPI_SERIAL_END(video_output);
 }
 
@@ -590,8 +598,11 @@ acpi_video_vo_destroy(struct acpi_video_
                vo->vo_sysctl_tree = NULL;
                sysctl_ctx_free(&vo->vo_sysctl_ctx);
        }
-       if (vo->vo_levels != NULL)
+       if (vo->vo_levels != NULL) {
+               AcpiRemoveNotifyHandler(vo->handle, ACPI_DEVICE_NOTIFY,
+                   acpi_video_vo_notify_handler);
                AcpiOsFree(vo->vo_levels);
+       }
 
        switch (vo->adr & DOD_DEVID_MASK) {
        case DOD_DEVID_MONITOR:
@@ -627,6 +638,79 @@ acpi_video_vo_check_level(struct acpi_vi
        return (EINVAL);
 }
 
+static void
+acpi_video_vo_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context)
+{
+       struct acpi_video_output *vo;
+       int i, j, level, new_level;
+
+       vo = context;
+       ACPI_SERIAL_BEGIN(video_output);
+       if (vo->handle != handle)
+               goto out;
+
+       switch (notify) {
+       case VID_NOTIFY_CYCLE_BRN:
+               if (vo->vo_numlevels <= 3)
+                       goto out;
+               /* FALLTHROUGH */
+       case VID_NOTIFY_INC_BRN:
+       case VID_NOTIFY_DEC_BRN:
+       case VID_NOTIFY_ZERO_BRN:
+               if (vo->vo_levels == NULL)
+                       goto out;
+               level = vo_get_brightness(handle);
+               if (level < 0)
+                       goto out;
+               break;
+       default:
+               printf("unknown notify event 0x%x from %s\n",
+                   notify, acpi_name(handle));
+               goto out;
+       }
+
+       new_level = level;
+       switch (notify) {
+       case VID_NOTIFY_CYCLE_BRN:
+               for (i = 2; i < vo->vo_numlevels; i++)
+                       if (vo->vo_levels[i] == level) {
+                               new_level = vo->vo_numlevels > i + 1 ?
+                                    vo->vo_levels[i + 1] : vo->vo_levels[2];
+                               break;
+                       }
+               break;
+       case VID_NOTIFY_INC_BRN:
+       case VID_NOTIFY_DEC_BRN:
+               for (i = 0; i < vo->vo_numlevels; i++) {
+                       j = vo->vo_levels[i];
+                       if (notify == VID_NOTIFY_INC_BRN) {
+                               if (j > level &&
+                                   (j < new_level || level == new_level))
+                                       new_level = j;
+                       } else {
+                               if (j < level &&
+                                   (j > new_level || level == new_level))
+                                       new_level = j;
+                       }
+               }
+               break;
+       case VID_NOTIFY_ZERO_BRN:
+               for (i = 0; i < vo->vo_numlevels; i++)
+                       if (vo->vo_levels[i] == 0) {
+                               new_level = 0;
+                               break;
+                       }
+               break;
+       }
+       if (new_level != level) {
+               vo_set_brightness(handle, new_level);
+               vo->vo_brightness = new_level;
+       }
+
+out:
+       ACPI_SERIAL_END(video_output);
+}
+
 /* ARGSUSED */
 static int
 acpi_video_vo_active_sysctl(SYSCTL_HANDLER_ARGS)
@@ -900,6 +984,25 @@ out:
        return (num);
 }
 
+static int
+vo_get_brightness(ACPI_HANDLE handle)
+{
+       UINT32 level;
+       ACPI_STATUS status;
+
+       ACPI_SERIAL_ASSERT(video_output);
+       status = acpi_GetInteger(handle, "_BQC", &level);
+       if (ACPI_FAILURE(status)) {
+               printf("can't evaluate %s._BQC - %s\n", acpi_name(handle),
+                   AcpiFormatException(status));
+               return (-1);
+       }
+       if (level > 100)
+               return (-1);
+
+       return (level);
+}
+
 static void
 vo_set_brightness(ACPI_HANDLE handle, int level)
 {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to