--- src/rhd_acpi.c.orig 2009-10-06 07:36:07.000000000 -0400 +++ src/rhd_acpi.c 2009-10-27 16:38:26.000000000 -0400 @@ -47,6 +47,96 @@ #include "rhd_acpi.h" +#if defined(__FreeBSD__) || defined(__DragonFly__) + +#include +#include + +#define ACPI_VIDEO_LEVELS "hw.acpi.video.lcd0.levels" +#define ACPI_VIDEO_BRIGHTNESS "hw.acpi.video.lcd0.brightness" + +#define RHD_BL_ROUNDDOWN(x, y) (((x) / (y)) * (y)) +#define RHD_BL_ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) + +/* + * Get/Set LCD backlight brightness via acpi_video(4). + */ +static Bool +rhdDoBacklight(struct rhdOutput *Output, Bool do_write, int *val) +{ + int *levels; + size_t len; + int level, step; + int num_levels; + int d1, d2; + int max, min; + int rd, ru; + int i, j; + + if (sysctlbyname(ACPI_VIDEO_LEVELS, NULL, &len, NULL, 0) != 0 || len == 0) + return FALSE; + levels = (int *)malloc(len); + if (levels == NULL) + return FALSE; + if (sysctlbyname(ACPI_VIDEO_LEVELS, levels, &len, NULL, 0) != 0) { + free(levels); + return FALSE; + } + + num_levels = len / sizeof(*levels); + for (i = 1, max = 0, min = 0; i < num_levels; i++) { + if (levels[i] < levels[min]) + min = i; + if (levels[i] > levels[max]) + max = i; + } + step = levels[max] - levels[min] + 1; + + if (do_write) { + if (*val < step) + level = levels[min]; + else if (*val > RHD_BACKLIGHT_PROPERTY_MAX - step) + level = levels[max]; + else { + d1 = step; + rd = RHD_BL_ROUNDDOWN(*val, step); + ru = RHD_BL_ROUNDUP(*val, step); + for (i = 0; i < num_levels; i++) { + j = levels[i] * (RHD_BACKLIGHT_PROPERTY_MAX + 1) / step; + if (j >= rd && j <= ru) { + d2 = j - rd; + if (d1 > d2) { + level = levels[i]; + d1 = d2; + } + } + } + if (d1 >= step) { + free(levels); + return FALSE; + } + } + free(levels); + if (sysctlbyname(ACPI_VIDEO_BRIGHTNESS, NULL, 0, &level, sizeof(level)) != 0) + return FALSE; + } else { + len = sizeof(level); + if (sysctlbyname(ACPI_VIDEO_BRIGHTNESS, &level, &len, NULL, 0) != 0) + return FALSE; + if (level <= levels[min]) + *val = 0; + else if (level >= levels[max]) + *val = RHD_BACKLIGHT_PROPERTY_MAX; + else + *val = level * (RHD_BACKLIGHT_PROPERTY_MAX + 1) / step; + free(levels); + } + + return TRUE; +} + +#elif defined(__linux__) + #define ACPI_PATH "/sys/class/backlight" /* @@ -120,6 +210,7 @@ return FALSE; } +#endif /* * RhdACPIGetBacklightControl(): return backlight value in range 0..255; @@ -128,7 +219,7 @@ int RhdACPIGetBacklightControl(struct rhdOutput *Output) { -#ifdef __linux__ +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) int ret; RHDFUNC(Output); if (rhdDoBacklight(Output, FALSE, &ret)) @@ -144,7 +235,7 @@ RhdACPISetBacklightControl(struct rhdOutput *Output, int val) { RHDFUNC(Output); -#ifdef __linux__ +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) rhdDoBacklight(Output, TRUE, &val); #endif }