diff options
author | Michael Hanselmann <linux-kernel@hansmi.ch> | 2006-06-25 08:47:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:00:59 -0400 |
commit | 5474c120aafe78ca54bf272f7a01107c42da2b21 (patch) | |
tree | c1b002a27703ce92c816bfb9844752186e33d403 /drivers/video/fbsysfs.c | |
parent | 17660bdd5c1f1a165273c1a59cb5b87670a81cc4 (diff) |
[PATCH] Rewritten backlight infrastructure for portable Apple computers
This patch contains a total rewrite of the backlight infrastructure for
portable Apple computers. Backward compatibility is retained. A sysfs
interface allows userland to control the brightness with more steps than
before. Userland is allowed to upload a brightness curve for different
monitors, similar to Mac OS X.
[akpm@osdl.org: add needed exports]
Signed-off-by: Michael Hanselmann <linux-kernel@hansmi.ch>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/fbsysfs.c')
-rw-r--r-- | drivers/video/fbsysfs.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 34e07399756b..3ceb8c1b392e 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/fb.h> | 19 | #include <linux/fb.h> |
20 | #include <linux/console.h> | 20 | #include <linux/console.h> |
21 | #include <linux/module.h> | ||
21 | 22 | ||
22 | /** | 23 | /** |
23 | * framebuffer_alloc - creates a new frame buffer info structure | 24 | * framebuffer_alloc - creates a new frame buffer info structure |
@@ -55,6 +56,10 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) | |||
55 | 56 | ||
56 | info->device = dev; | 57 | info->device = dev; |
57 | 58 | ||
59 | #ifdef CONFIG_FB_BACKLIGHT | ||
60 | mutex_init(&info->bl_mutex); | ||
61 | #endif | ||
62 | |||
58 | return info; | 63 | return info; |
59 | #undef PADDING | 64 | #undef PADDING |
60 | #undef BYTES_PER_LONG | 65 | #undef BYTES_PER_LONG |
@@ -414,6 +419,65 @@ static ssize_t show_fbstate(struct class_device *class_device, char *buf) | |||
414 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); | 419 | return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); |
415 | } | 420 | } |
416 | 421 | ||
422 | #ifdef CONFIG_FB_BACKLIGHT | ||
423 | static ssize_t store_bl_curve(struct class_device *class_device, | ||
424 | const char *buf, size_t count) | ||
425 | { | ||
426 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
427 | u8 tmp_curve[FB_BACKLIGHT_LEVELS]; | ||
428 | unsigned int i; | ||
429 | |||
430 | if (count != (FB_BACKLIGHT_LEVELS / 8 * 24)) | ||
431 | return -EINVAL; | ||
432 | |||
433 | for (i = 0; i < (FB_BACKLIGHT_LEVELS / 8); ++i) | ||
434 | if (sscanf(&buf[i * 24], | ||
435 | "%2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx\n", | ||
436 | &tmp_curve[i * 8 + 0], | ||
437 | &tmp_curve[i * 8 + 1], | ||
438 | &tmp_curve[i * 8 + 2], | ||
439 | &tmp_curve[i * 8 + 3], | ||
440 | &tmp_curve[i * 8 + 4], | ||
441 | &tmp_curve[i * 8 + 5], | ||
442 | &tmp_curve[i * 8 + 6], | ||
443 | &tmp_curve[i * 8 + 7]) != 8) | ||
444 | return -EINVAL; | ||
445 | |||
446 | /* If there has been an error in the input data, we won't | ||
447 | * reach this loop. | ||
448 | */ | ||
449 | mutex_lock(&fb_info->bl_mutex); | ||
450 | for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i) | ||
451 | fb_info->bl_curve[i] = tmp_curve[i]; | ||
452 | mutex_unlock(&fb_info->bl_mutex); | ||
453 | |||
454 | return count; | ||
455 | } | ||
456 | |||
457 | static ssize_t show_bl_curve(struct class_device *class_device, char *buf) | ||
458 | { | ||
459 | struct fb_info *fb_info = class_get_devdata(class_device); | ||
460 | ssize_t len = 0; | ||
461 | unsigned int i; | ||
462 | |||
463 | mutex_lock(&fb_info->bl_mutex); | ||
464 | for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8) | ||
465 | len += snprintf(&buf[len], PAGE_SIZE, | ||
466 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
467 | fb_info->bl_curve[i + 0], | ||
468 | fb_info->bl_curve[i + 1], | ||
469 | fb_info->bl_curve[i + 2], | ||
470 | fb_info->bl_curve[i + 3], | ||
471 | fb_info->bl_curve[i + 4], | ||
472 | fb_info->bl_curve[i + 5], | ||
473 | fb_info->bl_curve[i + 6], | ||
474 | fb_info->bl_curve[i + 7]); | ||
475 | mutex_unlock(&fb_info->bl_mutex); | ||
476 | |||
477 | return len; | ||
478 | } | ||
479 | #endif | ||
480 | |||
417 | /* When cmap is added back in it should be a binary attribute | 481 | /* When cmap is added back in it should be a binary attribute |
418 | * not a text one. Consideration should also be given to converting | 482 | * not a text one. Consideration should also be given to converting |
419 | * fbdev to use configfs instead of sysfs */ | 483 | * fbdev to use configfs instead of sysfs */ |
@@ -432,6 +496,9 @@ static struct class_device_attribute class_device_attrs[] = { | |||
432 | __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), | 496 | __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), |
433 | __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), | 497 | __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), |
434 | __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate), | 498 | __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate), |
499 | #ifdef CONFIG_FB_BACKLIGHT | ||
500 | __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve), | ||
501 | #endif | ||
435 | }; | 502 | }; |
436 | 503 | ||
437 | int fb_init_class_device(struct fb_info *fb_info) | 504 | int fb_init_class_device(struct fb_info *fb_info) |
@@ -454,4 +521,25 @@ void fb_cleanup_class_device(struct fb_info *fb_info) | |||
454 | &class_device_attrs[i]); | 521 | &class_device_attrs[i]); |
455 | } | 522 | } |
456 | 523 | ||
524 | #ifdef CONFIG_FB_BACKLIGHT | ||
525 | /* This function generates a linear backlight curve | ||
526 | * | ||
527 | * 0: off | ||
528 | * 1-7: min | ||
529 | * 8-127: linear from min to max | ||
530 | */ | ||
531 | void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max) | ||
532 | { | ||
533 | unsigned int i, flat, count, range = (max - min); | ||
534 | |||
535 | fb_info->bl_curve[0] = off; | ||
457 | 536 | ||
537 | for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) | ||
538 | fb_info->bl_curve[flat] = min; | ||
539 | |||
540 | count = FB_BACKLIGHT_LEVELS * 15 / 16; | ||
541 | for (i = 0; i < count; ++i) | ||
542 | fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count); | ||
543 | } | ||
544 | EXPORT_SYMBOL_GPL(fb_bl_default_curve); | ||
545 | #endif | ||