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.
This commit is contained in:
Jung-uk Kim 2010-03-10 17:58:32 +00:00
parent 50819829d3
commit 0cd9e69dae
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/stable/8/; revision=204963

View File

@ -83,6 +83,7 @@ static struct acpi_video_output *acpi_video_vo_init(UINT32);
static void acpi_video_vo_bind(struct acpi_video_output *, ACPI_HANDLE); static void acpi_video_vo_bind(struct acpi_video_output *, ACPI_HANDLE);
static void acpi_video_vo_destroy(struct acpi_video_output *); static void acpi_video_vo_destroy(struct acpi_video_output *);
static int acpi_video_vo_check_level(struct acpi_video_output *, int); 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_active_sysctl(SYSCTL_HANDLER_ARGS);
static int acpi_video_vo_bright_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_video_vo_bright_sysctl(SYSCTL_HANDLER_ARGS);
static int acpi_video_vo_presets_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_video_vo_presets_sysctl(SYSCTL_HANDLER_ARGS);
@ -93,56 +94,61 @@ static void vid_set_switch_policy(ACPI_HANDLE, UINT32);
static int vid_enum_outputs(ACPI_HANDLE, static int vid_enum_outputs(ACPI_HANDLE,
void(*)(ACPI_HANDLE, UINT32, void *), void *); void(*)(ACPI_HANDLE, UINT32, void *), void *);
static int vo_get_brightness_levels(ACPI_HANDLE, int **); 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 void vo_set_brightness(ACPI_HANDLE, int);
static UINT32 vo_get_device_status(ACPI_HANDLE); static UINT32 vo_get_device_status(ACPI_HANDLE);
static UINT32 vo_get_graphics_state(ACPI_HANDLE); static UINT32 vo_get_graphics_state(ACPI_HANDLE);
static void vo_set_device_state(ACPI_HANDLE, UINT32); static void vo_set_device_state(ACPI_HANDLE, UINT32);
/* events */ /* events */
#define VID_NOTIFY_SWITCHED 0x80 #define VID_NOTIFY_SWITCHED 0x80
#define VID_NOTIFY_REPROBE 0x81 #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 */ /* _DOS (Enable/Disable Output Switching) argument bits */
#define DOS_SWITCH_MASK 3 #define DOS_SWITCH_MASK 3
#define DOS_SWITCH_BY_OSPM 0 #define DOS_SWITCH_BY_OSPM 0
#define DOS_SWITCH_BY_BIOS 1 #define DOS_SWITCH_BY_BIOS 1
#define DOS_SWITCH_LOCKED 2 #define DOS_SWITCH_LOCKED 2
#define DOS_BRIGHTNESS_BY_BIOS (1 << 2) #define DOS_BRIGHTNESS_BY_OSPM (1 << 2)
/* _DOD and subdev's _ADR */ /* _DOD and subdev's _ADR */
#define DOD_DEVID_MASK 0x0f00 #define DOD_DEVID_MASK 0x0f00
#define DOD_DEVID_MASK_FULL 0xffff #define DOD_DEVID_MASK_FULL 0xffff
#define DOD_DEVID_MASK_DISPIDX 0x000f #define DOD_DEVID_MASK_DISPIDX 0x000f
#define DOD_DEVID_MASK_DISPPORT 0x00f0 #define DOD_DEVID_MASK_DISPPORT 0x00f0
#define DOD_DEVID_MONITOR 0x0100 #define DOD_DEVID_MONITOR 0x0100
#define DOD_DEVID_LCD 0x0110 #define DOD_DEVID_LCD 0x0110
#define DOD_DEVID_TV 0x0200 #define DOD_DEVID_TV 0x0200
#define DOD_DEVID_EXT 0x0300 #define DOD_DEVID_EXT 0x0300
#define DOD_DEVID_INTDFP 0x0400 #define DOD_DEVID_INTDFP 0x0400
#define DOD_BIOS (1 << 16) #define DOD_BIOS (1 << 16)
#define DOD_NONVGA (1 << 17) #define DOD_NONVGA (1 << 17)
#define DOD_HEAD_ID_SHIFT 18 #define DOD_HEAD_ID_SHIFT 18
#define DOD_HEAD_ID_BITS 3 #define DOD_HEAD_ID_BITS 3
#define DOD_HEAD_ID_MASK \ #define DOD_HEAD_ID_MASK \
(((1 << DOD_HEAD_ID_BITS) - 1) << DOD_HEAD_ID_SHIFT) (((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 */ /* _BCL related constants */
#define BCL_FULLPOWER 0 #define BCL_FULLPOWER 0
#define BCL_ECONOMY 1 #define BCL_ECONOMY 1
/* _DCS (Device Currrent Status) value bits and masks. */ /* _DCS (Device Currrent Status) value bits and masks. */
#define DCS_EXISTS (1 << 0) #define DCS_EXISTS (1 << 0)
#define DCS_ACTIVE (1 << 1) #define DCS_ACTIVE (1 << 1)
#define DCS_READY (1 << 2) #define DCS_READY (1 << 2)
#define DCS_FUNCTIONAL (1 << 3) #define DCS_FUNCTIONAL (1 << 3)
#define DCS_ATTACHED (1 << 4) #define DCS_ATTACHED (1 << 4)
/* _DSS (Device Set Status) argument bits and masks. */ /* _DSS (Device Set Status) argument bits and masks. */
#define DSS_INACTIVE 0 #define DSS_INACTIVE 0
#define DSS_ACTIVE (1 << 0) #define DSS_ACTIVE (1 << 0)
#define DSS_SETNEXT (1 << 30) #define DSS_SETNEXT (1 << 30)
#define DSS_COMMIT (1 << 31) #define DSS_COMMIT (1 << 31)
static device_method_t acpi_video_methods[] = { static device_method_t acpi_video_methods[] = {
DEVMETHOD(device_identify, acpi_video_identify), DEVMETHOD(device_identify, acpi_video_identify),
@ -269,7 +275,7 @@ acpi_video_attach(device_t dev)
* brightness levels. * brightness levels.
*/ */
vid_set_switch_policy(sc->handle, DOS_SWITCH_BY_OSPM | vid_set_switch_policy(sc->handle, DOS_SWITCH_BY_OSPM |
DOS_BRIGHTNESS_BY_BIOS); DOS_BRIGHTNESS_BY_OSPM);
acpi_video_power_profile(sc); acpi_video_power_profile(sc);
@ -290,8 +296,7 @@ acpi_video_detach(device_t dev)
acpi_video_notify_handler); acpi_video_notify_handler);
ACPI_SERIAL_BEGIN(video); ACPI_SERIAL_BEGIN(video);
for (vo = STAILQ_FIRST(&sc->vid_outputs); vo != NULL; vo = vn) { STAILQ_FOREACH_SAFE(vo, &sc->vid_outputs, vo_next, vn) {
vn = STAILQ_NEXT(vo, vo_next);
acpi_video_vo_destroy(vo); acpi_video_vo_destroy(vo);
} }
ACPI_SERIAL_END(video); ACPI_SERIAL_END(video);
@ -578,6 +583,9 @@ acpi_video_vo_bind(struct acpi_video_output *vo, ACPI_HANDLE handle)
/* XXX - see above. */ /* XXX - see above. */
vo->vo_economy = vo->vo_levels[BCL_ECONOMY]; 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); ACPI_SERIAL_END(video_output);
} }
@ -591,8 +599,11 @@ acpi_video_vo_destroy(struct acpi_video_output *vo)
vo->vo_sysctl_tree = NULL; vo->vo_sysctl_tree = NULL;
sysctl_ctx_free(&vo->vo_sysctl_ctx); 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); AcpiOsFree(vo->vo_levels);
}
switch (vo->adr & DOD_DEVID_MASK) { switch (vo->adr & DOD_DEVID_MASK) {
case DOD_DEVID_MONITOR: case DOD_DEVID_MONITOR:
@ -628,6 +639,79 @@ acpi_video_vo_check_level(struct acpi_video_output *vo, int level)
return (EINVAL); 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 */ /* ARGSUSED */
static int static int
acpi_video_vo_active_sysctl(SYSCTL_HANDLER_ARGS) acpi_video_vo_active_sysctl(SYSCTL_HANDLER_ARGS)
@ -901,6 +985,25 @@ vo_get_brightness_levels(ACPI_HANDLE handle, int **levelp)
return (num); 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 static void
vo_set_brightness(ACPI_HANDLE handle, int level) vo_set_brightness(ACPI_HANDLE handle, int level)
{ {