/* * Miscellaneous procedures for dealing with the PowerMac hardware. * Contains support for the backlight. * * Copyright (C) 2000 Benjamin Herrenschmidt * Copyright (C) 2006 Michael Hanselmann * */ #include #include #include #include #include #include #define OLD_BACKLIGHT_MAX 15 /* Protect the pmac_backlight variable */ DEFINE_MUTEX(pmac_backlight_mutex); /* Main backlight storage * * Backlight drivers in this variable are required to have the "props" * attribute set and to have an update_status function. * * We can only store one backlight here, but since Apple laptops have only one * internal display, it doesn't matter. Other backlight drivers can be used * independently. * * Lock ordering: * pmac_backlight_mutex (global, main backlight) * pmac_backlight->sem (backlight class) */ struct backlight_device *pmac_backlight; int pmac_has_backlight_type(const char *type) { struct device_node* bk_node = find_devices("backlight"); if (bk_node) { char *prop = get_property(bk_node, "backlight-control", NULL); if (prop && strncmp(prop, type, strlen(type)) == 0) return 1; } return 0; } int pmac_backlight_curve_lookup(struct fb_info *info, int value) { int level = (FB_BACKLIGHT_LEVELS - 1); if (info && info->bl_dev) { int i, max = 0; /* Look for biggest value */ for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) max = max((int)info->bl_curve[i], max); /* Look for nearest value */ for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { int diff = abs(info->bl_curve[i] - value); if (diff < max) { max = diff; level = i; } } } return level; } static void pmac_backlight_key(int direction) { mutex_lock(&pmac_backlight_mutex); if (pmac_backlight) { struct backlight_properties *props; int brightness; down(&pmac_backlight->sem); props = pmac_backlight->props; brightness = props->brightness + ((direction?-1:1) * (props->max_brightness / 15)); if (brightness < 0) brightness = 0; else if (brightness > props->max_brightness) brightness = props->max_brightness; props->brightness = brightness; props->update_status(pmac_backlight); up(&pmac_backlight->sem); } mutex_unlock(&pmac_backlight_mutex); } void pmac_backlight_key_up() { pmac_backlight_key(0); } void pmac_backlight_key_down() { pmac_backlight_key(1); } int pmac_backlight_set_legacy_brightness(int brightness) { int error = -ENXIO; mutex_lock(&pmac_backlight_mutex); if (pmac_backlight) { struct backlight_properties *props; down(&pmac_backlight->sem); props = pmac_backlight->props; props->brightness = brightness * (props->max_brightness + 1) / (OLD_BACKLIGHT_MAX + 1); if (props->brightness > props->max_brightness) props->brightness = props->max_brightness; else if (props->brightness < 0) props->brightness = 0; props->update_status(pmac_backlight); up(&pmac_backlight->sem); error = 0; } mutex_unlock(&pmac_backlight_mutex); return error; } int pmac_backlight_get_legacy_brightness() { int result = -ENXIO; mutex_lock(&pmac_backlight_mutex); if (pmac_backlight) { struct backlight_properties *props; down(&pmac_backlight->sem); props = pmac_backlight->props; result = props->brightness * (OLD_BACKLIGHT_MAX + 1) / (props->max_brightness + 1); up(&pmac_backlight->sem); } mutex_unlock(&pmac_backlight_mutex); return result; }