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 | |
| 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>
26 files changed, 1529 insertions, 711 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 91a6e04d9741..52f5659534f4 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | #include <linux/kprobes.h> | 33 | #include <linux/kprobes.h> |
| 34 | #include <linux/kexec.h> | 34 | #include <linux/kexec.h> |
| 35 | #include <linux/backlight.h> | ||
| 35 | 36 | ||
| 36 | #include <asm/kdebug.h> | 37 | #include <asm/kdebug.h> |
| 37 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
| @@ -105,10 +106,18 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
| 105 | spin_lock_irq(&die_lock); | 106 | spin_lock_irq(&die_lock); |
| 106 | bust_spinlocks(1); | 107 | bust_spinlocks(1); |
| 107 | #ifdef CONFIG_PMAC_BACKLIGHT | 108 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 108 | if (machine_is(powermac)) { | 109 | mutex_lock(&pmac_backlight_mutex); |
| 109 | set_backlight_enable(1); | 110 | if (machine_is(powermac) && pmac_backlight) { |
| 110 | set_backlight_level(BACKLIGHT_MAX); | 111 | struct backlight_properties *props; |
| 112 | |||
| 113 | down(&pmac_backlight->sem); | ||
| 114 | props = pmac_backlight->props; | ||
| 115 | props->brightness = props->max_brightness; | ||
| 116 | props->power = FB_BLANK_UNBLANK; | ||
| 117 | props->update_status(pmac_backlight); | ||
| 118 | up(&pmac_backlight->sem); | ||
| 111 | } | 119 | } |
| 120 | mutex_unlock(&pmac_backlight_mutex); | ||
| 112 | #endif | 121 | #endif |
| 113 | printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); | 122 | printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); |
| 114 | #ifdef CONFIG_PREEMPT | 123 | #ifdef CONFIG_PREEMPT |
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c index 8be2f7d071f0..498b042e1837 100644 --- a/arch/powerpc/platforms/powermac/backlight.c +++ b/arch/powerpc/platforms/powermac/backlight.c | |||
| @@ -3,200 +3,148 @@ | |||
| 3 | * Contains support for the backlight. | 3 | * Contains support for the backlight. |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2000 Benjamin Herrenschmidt | 5 | * Copyright (C) 2000 Benjamin Herrenschmidt |
| 6 | * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> | ||
| 6 | * | 7 | * |
| 7 | */ | 8 | */ |
| 8 | 9 | ||
| 9 | #include <linux/config.h> | 10 | #include <linux/config.h> |
| 10 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 11 | #include <linux/module.h> | 12 | #include <linux/fb.h> |
| 12 | #include <linux/stddef.h> | 13 | #include <linux/backlight.h> |
| 13 | #include <linux/reboot.h> | ||
| 14 | #include <linux/nvram.h> | ||
| 15 | #include <linux/console.h> | ||
| 16 | #include <asm/sections.h> | ||
| 17 | #include <asm/ptrace.h> | ||
| 18 | #include <asm/io.h> | ||
| 19 | #include <asm/pgtable.h> | ||
| 20 | #include <asm/system.h> | ||
| 21 | #include <asm/prom.h> | 14 | #include <asm/prom.h> |
| 22 | #include <asm/machdep.h> | ||
| 23 | #include <asm/nvram.h> | ||
| 24 | #include <asm/backlight.h> | 15 | #include <asm/backlight.h> |
| 25 | 16 | ||
| 26 | #include <linux/adb.h> | 17 | #define OLD_BACKLIGHT_MAX 15 |
| 27 | #include <linux/pmu.h> | ||
| 28 | 18 | ||
| 29 | static struct backlight_controller *backlighter; | 19 | /* Protect the pmac_backlight variable */ |
| 30 | static void* backlighter_data; | 20 | DEFINE_MUTEX(pmac_backlight_mutex); |
| 31 | static int backlight_autosave; | ||
| 32 | static int backlight_level = BACKLIGHT_MAX; | ||
| 33 | static int backlight_enabled = 1; | ||
| 34 | static int backlight_req_level = -1; | ||
| 35 | static int backlight_req_enable = -1; | ||
| 36 | 21 | ||
| 37 | static void backlight_callback(void *); | 22 | /* Main backlight storage |
| 38 | static DECLARE_WORK(backlight_work, backlight_callback, NULL); | 23 | * |
| 24 | * Backlight drivers in this variable are required to have the "props" | ||
| 25 | * attribute set and to have an update_status function. | ||
| 26 | * | ||
| 27 | * We can only store one backlight here, but since Apple laptops have only one | ||
| 28 | * internal display, it doesn't matter. Other backlight drivers can be used | ||
| 29 | * independently. | ||
| 30 | * | ||
| 31 | * Lock ordering: | ||
| 32 | * pmac_backlight_mutex (global, main backlight) | ||
| 33 | * pmac_backlight->sem (backlight class) | ||
| 34 | */ | ||
| 35 | struct backlight_device *pmac_backlight; | ||
| 39 | 36 | ||
| 40 | void register_backlight_controller(struct backlight_controller *ctrler, | 37 | int pmac_has_backlight_type(const char *type) |
| 41 | void *data, char *type) | ||
| 42 | { | 38 | { |
| 43 | struct device_node* bk_node; | 39 | struct device_node* bk_node = find_devices("backlight"); |
| 44 | char *prop; | 40 | |
| 45 | int valid = 0; | ||
| 46 | |||
| 47 | /* There's already a matching controller, bail out */ | ||
| 48 | if (backlighter != NULL) | ||
| 49 | return; | ||
| 50 | |||
| 51 | bk_node = find_devices("backlight"); | ||
| 52 | |||
| 53 | #ifdef CONFIG_ADB_PMU | ||
| 54 | /* Special case for the old PowerBook since I can't test on it */ | ||
| 55 | backlight_autosave = machine_is_compatible("AAPL,3400/2400") | ||
| 56 | || machine_is_compatible("AAPL,3500"); | ||
| 57 | if ((backlight_autosave | ||
| 58 | || machine_is_compatible("AAPL,PowerBook1998") | ||
| 59 | || machine_is_compatible("PowerBook1,1")) | ||
| 60 | && !strcmp(type, "pmu")) | ||
| 61 | valid = 1; | ||
| 62 | #endif | ||
| 63 | if (bk_node) { | 41 | if (bk_node) { |
| 64 | prop = get_property(bk_node, "backlight-control", NULL); | 42 | char *prop = get_property(bk_node, "backlight-control", NULL); |
| 65 | if (prop && !strncmp(prop, type, strlen(type))) | 43 | if (prop && strncmp(prop, type, strlen(type)) == 0) |
| 66 | valid = 1; | 44 | return 1; |
| 67 | } | ||
| 68 | if (!valid) | ||
| 69 | return; | ||
| 70 | backlighter = ctrler; | ||
| 71 | backlighter_data = data; | ||
| 72 | |||
| 73 | if (bk_node && !backlight_autosave) | ||
| 74 | prop = get_property(bk_node, "bklt", NULL); | ||
| 75 | else | ||
| 76 | prop = NULL; | ||
| 77 | if (prop) { | ||
| 78 | backlight_level = ((*prop)+1) >> 1; | ||
| 79 | if (backlight_level > BACKLIGHT_MAX) | ||
| 80 | backlight_level = BACKLIGHT_MAX; | ||
| 81 | } | 45 | } |
| 82 | 46 | ||
| 83 | #ifdef CONFIG_ADB_PMU | 47 | return 0; |
| 84 | if (backlight_autosave) { | ||
| 85 | struct adb_request req; | ||
| 86 | pmu_request(&req, NULL, 2, 0xd9, 0); | ||
| 87 | while (!req.complete) | ||
| 88 | pmu_poll(); | ||
| 89 | backlight_level = req.reply[0] >> 4; | ||
| 90 | } | ||
| 91 | #endif | ||
| 92 | acquire_console_sem(); | ||
| 93 | if (!backlighter->set_enable(1, backlight_level, data)) | ||
| 94 | backlight_enabled = 1; | ||
| 95 | release_console_sem(); | ||
| 96 | |||
| 97 | printk(KERN_INFO "Registered \"%s\" backlight controller," | ||
| 98 | "level: %d/15\n", type, backlight_level); | ||
| 99 | } | 48 | } |
| 100 | EXPORT_SYMBOL(register_backlight_controller); | ||
| 101 | 49 | ||
| 102 | void unregister_backlight_controller(struct backlight_controller | 50 | int pmac_backlight_curve_lookup(struct fb_info *info, int value) |
| 103 | *ctrler, void *data) | ||
| 104 | { | 51 | { |
| 105 | /* We keep the current backlight level (for now) */ | 52 | int level = (FB_BACKLIGHT_LEVELS - 1); |
| 106 | if (ctrler == backlighter && data == backlighter_data) | 53 | |
| 107 | backlighter = NULL; | 54 | if (info && info->bl_dev) { |
| 55 | int i, max = 0; | ||
| 56 | |||
| 57 | /* Look for biggest value */ | ||
| 58 | for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) | ||
| 59 | max = max((int)info->bl_curve[i], max); | ||
| 60 | |||
| 61 | /* Look for nearest value */ | ||
| 62 | for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { | ||
| 63 | int diff = abs(info->bl_curve[i] - value); | ||
| 64 | if (diff < max) { | ||
| 65 | max = diff; | ||
| 66 | level = i; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | } | ||
| 71 | |||
| 72 | return level; | ||
| 108 | } | 73 | } |
| 109 | EXPORT_SYMBOL(unregister_backlight_controller); | ||
| 110 | 74 | ||
| 111 | static int __set_backlight_enable(int enable) | 75 | static void pmac_backlight_key(int direction) |
| 112 | { | 76 | { |
| 113 | int rc; | 77 | mutex_lock(&pmac_backlight_mutex); |
| 114 | 78 | if (pmac_backlight) { | |
| 115 | if (!backlighter) | 79 | struct backlight_properties *props; |
| 116 | return -ENODEV; | 80 | int brightness; |
| 117 | acquire_console_sem(); | 81 | |
| 118 | rc = backlighter->set_enable(enable, backlight_level, | 82 | down(&pmac_backlight->sem); |
| 119 | backlighter_data); | 83 | props = pmac_backlight->props; |
| 120 | if (!rc) | 84 | |
| 121 | backlight_enabled = enable; | 85 | brightness = props->brightness + |
| 122 | release_console_sem(); | 86 | ((direction?-1:1) * (props->max_brightness / 15)); |
| 123 | return rc; | 87 | |
| 88 | if (brightness < 0) | ||
| 89 | brightness = 0; | ||
| 90 | else if (brightness > props->max_brightness) | ||
| 91 | brightness = props->max_brightness; | ||
| 92 | |||
| 93 | props->brightness = brightness; | ||
| 94 | props->update_status(pmac_backlight); | ||
| 95 | |||
| 96 | up(&pmac_backlight->sem); | ||
| 97 | } | ||
| 98 | mutex_unlock(&pmac_backlight_mutex); | ||
| 124 | } | 99 | } |
| 125 | int set_backlight_enable(int enable) | 100 | |
| 101 | void pmac_backlight_key_up() | ||
| 126 | { | 102 | { |
| 127 | if (!backlighter) | 103 | pmac_backlight_key(0); |
| 128 | return -ENODEV; | ||
| 129 | backlight_req_enable = enable; | ||
| 130 | schedule_work(&backlight_work); | ||
| 131 | return 0; | ||
| 132 | } | 104 | } |
| 133 | 105 | ||
| 134 | EXPORT_SYMBOL(set_backlight_enable); | 106 | void pmac_backlight_key_down() |
| 135 | |||
| 136 | int get_backlight_enable(void) | ||
| 137 | { | 107 | { |
| 138 | if (!backlighter) | 108 | pmac_backlight_key(1); |
| 139 | return -ENODEV; | ||
| 140 | return backlight_enabled; | ||
| 141 | } | 109 | } |
| 142 | EXPORT_SYMBOL(get_backlight_enable); | ||
| 143 | 110 | ||
| 144 | static int __set_backlight_level(int level) | 111 | int pmac_backlight_set_legacy_brightness(int brightness) |
| 145 | { | 112 | { |
| 146 | int rc = 0; | 113 | int error = -ENXIO; |
| 147 | 114 | ||
| 148 | if (!backlighter) | 115 | mutex_lock(&pmac_backlight_mutex); |
| 149 | return -ENODEV; | 116 | if (pmac_backlight) { |
| 150 | if (level < BACKLIGHT_MIN) | 117 | struct backlight_properties *props; |
| 151 | level = BACKLIGHT_OFF; | 118 | |
| 152 | if (level > BACKLIGHT_MAX) | 119 | down(&pmac_backlight->sem); |
| 153 | level = BACKLIGHT_MAX; | 120 | props = pmac_backlight->props; |
| 154 | acquire_console_sem(); | 121 | props->brightness = brightness * |
| 155 | if (backlight_enabled) | 122 | props->max_brightness / OLD_BACKLIGHT_MAX; |
| 156 | rc = backlighter->set_level(level, backlighter_data); | 123 | props->update_status(pmac_backlight); |
| 157 | if (!rc) | 124 | up(&pmac_backlight->sem); |
| 158 | backlight_level = level; | 125 | |
| 159 | release_console_sem(); | 126 | error = 0; |
| 160 | if (!rc && !backlight_autosave) { | ||
| 161 | level <<=1; | ||
| 162 | if (level & 0x10) | ||
| 163 | level |= 0x01; | ||
| 164 | // -- todo: save to property "bklt" | ||
| 165 | } | 127 | } |
| 166 | return rc; | 128 | mutex_unlock(&pmac_backlight_mutex); |
| 129 | |||
| 130 | return error; | ||
| 167 | } | 131 | } |
| 168 | int set_backlight_level(int level) | 132 | |
| 133 | int pmac_backlight_get_legacy_brightness() | ||
| 169 | { | 134 | { |
| 170 | if (!backlighter) | 135 | int result = -ENXIO; |
| 171 | return -ENODEV; | ||
| 172 | backlight_req_level = level; | ||
| 173 | schedule_work(&backlight_work); | ||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | 136 | ||
| 177 | EXPORT_SYMBOL(set_backlight_level); | 137 | mutex_lock(&pmac_backlight_mutex); |
| 138 | if (pmac_backlight) { | ||
| 139 | struct backlight_properties *props; | ||
| 178 | 140 | ||
| 179 | int get_backlight_level(void) | 141 | down(&pmac_backlight->sem); |
| 180 | { | 142 | props = pmac_backlight->props; |
| 181 | if (!backlighter) | 143 | result = props->brightness * |
| 182 | return -ENODEV; | 144 | OLD_BACKLIGHT_MAX / props->max_brightness; |
| 183 | return backlight_level; | 145 | up(&pmac_backlight->sem); |
| 184 | } | 146 | } |
| 185 | EXPORT_SYMBOL(get_backlight_level); | 147 | mutex_unlock(&pmac_backlight_mutex); |
| 186 | 148 | ||
| 187 | static void backlight_callback(void *dummy) | 149 | return result; |
| 188 | { | ||
| 189 | int level, enable; | ||
| 190 | |||
| 191 | do { | ||
| 192 | level = backlight_req_level; | ||
| 193 | enable = backlight_req_enable; | ||
| 194 | mb(); | ||
| 195 | |||
| 196 | if (level >= 0) | ||
| 197 | __set_backlight_level(level); | ||
| 198 | if (enable >= 0) | ||
| 199 | __set_backlight_enable(enable); | ||
| 200 | } while(cmpxchg(&backlight_req_level, level, -1) != level || | ||
| 201 | cmpxchg(&backlight_req_enable, enable, -1) != enable); | ||
| 202 | } | 150 | } |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 4735b41c113c..0741df8c41b7 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
| @@ -26,9 +26,6 @@ | |||
| 26 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
| 27 | #include <asm/machdep.h> | 27 | #include <asm/machdep.h> |
| 28 | #include <asm/xmon.h> | 28 | #include <asm/xmon.h> |
| 29 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 30 | #include <asm/backlight.h> | ||
| 31 | #endif | ||
| 32 | #include <asm/processor.h> | 29 | #include <asm/processor.h> |
| 33 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
| 34 | #include <asm/mmu.h> | 31 | #include <asm/mmu.h> |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index ccf5df44cde4..37cd6ee4586b 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
| @@ -99,17 +99,22 @@ config PMAC_MEDIABAY | |||
| 99 | devices are not fully supported in the bay as I never had one to | 99 | devices are not fully supported in the bay as I never had one to |
| 100 | try with | 100 | try with |
| 101 | 101 | ||
| 102 | # made a separate option since backlight may end up beeing used | ||
| 103 | # on non-powerbook machines (but only on PMU based ones AFAIK) | ||
| 104 | config PMAC_BACKLIGHT | 102 | config PMAC_BACKLIGHT |
| 105 | bool "Backlight control for LCD screens" | 103 | bool "Backlight control for LCD screens" |
| 106 | depends on ADB_PMU && (BROKEN || !PPC64) | 104 | depends on ADB_PMU && (BROKEN || !PPC64) |
| 107 | help | 105 | help |
| 108 | Say Y here to build in code to manage the LCD backlight on a | 106 | Say Y here to enable Macintosh specific extensions of the generic |
| 109 | Macintosh PowerBook. With this code, the backlight will be turned | 107 | backlight code. With this enabled, the brightness keys on older |
| 110 | on and off appropriately on power-management and lid-open/lid-closed | 108 | PowerBooks will be enabled so you can change the screen brightness. |
| 111 | events; also, the PowerBook button device will be enabled so you can | 109 | Newer models should use an userspace daemon like pbbuttonsd. |
| 112 | change the screen brightness. | 110 | |
| 111 | config PMAC_BACKLIGHT_LEGACY | ||
| 112 | bool "Provide legacy ioctl's on /dev/pmu for the backlight" | ||
| 113 | depends on PMAC_BACKLIGHT && (BROKEN || !PPC64) | ||
| 114 | help | ||
| 115 | Say Y if you want to enable legacy ioctl's on /dev/pmu. This is for | ||
| 116 | programs which use this old interface. New and updated programs | ||
| 117 | should use the backlight classes in sysfs. | ||
| 113 | 118 | ||
| 114 | config ADB_MACIO | 119 | config ADB_MACIO |
| 115 | bool "Include MacIO (CHRP) ADB driver" | 120 | bool "Include MacIO (CHRP) ADB driver" |
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index 6081acdea404..8972e53d2dcb 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile | |||
| @@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID) += adbhid.o | |||
| 12 | obj-$(CONFIG_ANSLCD) += ans-lcd.o | 12 | obj-$(CONFIG_ANSLCD) += ans-lcd.o |
| 13 | 13 | ||
| 14 | obj-$(CONFIG_ADB_PMU) += via-pmu.o | 14 | obj-$(CONFIG_ADB_PMU) += via-pmu.o |
| 15 | obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o | ||
| 15 | obj-$(CONFIG_ADB_CUDA) += via-cuda.o | 16 | obj-$(CONFIG_ADB_CUDA) += via-cuda.o |
| 16 | obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o | 17 | obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o |
| 17 | obj-$(CONFIG_PMAC_SMU) += smu.o | 18 | obj-$(CONFIG_PMAC_SMU) += smu.o |
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 394334ec5765..c26e1236b275 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c | |||
| @@ -503,9 +503,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto | |||
| 503 | case 0x1f: /* Powerbook button device */ | 503 | case 0x1f: /* Powerbook button device */ |
| 504 | { | 504 | { |
| 505 | int down = (data[1] == (data[1] & 0xf)); | 505 | int down = (data[1] == (data[1] & 0xf)); |
| 506 | #ifdef CONFIG_PMAC_BACKLIGHT | 506 | |
| 507 | int backlight = get_backlight_level(); | ||
| 508 | #endif | ||
| 509 | /* | 507 | /* |
| 510 | * XXX: Where is the contrast control for the passive? | 508 | * XXX: Where is the contrast control for the passive? |
| 511 | * -- Cort | 509 | * -- Cort |
| @@ -530,29 +528,17 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto | |||
| 530 | 528 | ||
| 531 | case 0xa: /* brightness decrease */ | 529 | case 0xa: /* brightness decrease */ |
| 532 | #ifdef CONFIG_PMAC_BACKLIGHT | 530 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 533 | if (!disable_kernel_backlight) { | 531 | if (!disable_kernel_backlight && down) |
| 534 | if (down && backlight >= 0) { | 532 | pmac_backlight_key_down(); |
| 535 | if (backlight > BACKLIGHT_OFF) | 533 | #endif |
| 536 | set_backlight_level(backlight-1); | ||
| 537 | else | ||
| 538 | set_backlight_level(BACKLIGHT_OFF); | ||
| 539 | } | ||
| 540 | } | ||
| 541 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 542 | input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); | 534 | input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); |
| 543 | break; | 535 | break; |
| 544 | 536 | ||
| 545 | case 0x9: /* brightness increase */ | 537 | case 0x9: /* brightness increase */ |
| 546 | #ifdef CONFIG_PMAC_BACKLIGHT | 538 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 547 | if (!disable_kernel_backlight) { | 539 | if (!disable_kernel_backlight && down) |
| 548 | if (down && backlight >= 0) { | 540 | pmac_backlight_key_up(); |
| 549 | if (backlight < BACKLIGHT_MAX) | 541 | #endif |
| 550 | set_backlight_level(backlight+1); | ||
| 551 | else | ||
| 552 | set_backlight_level(BACKLIGHT_MAX); | ||
| 553 | } | ||
| 554 | } | ||
| 555 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 556 | input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); | 542 | input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); |
| 557 | break; | 543 | break; |
| 558 | 544 | ||
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c new file mode 100644 index 000000000000..b42d05f2aaff --- /dev/null +++ b/drivers/macintosh/via-pmu-backlight.c | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | /* | ||
| 2 | * Backlight code for via-pmu | ||
| 3 | * | ||
| 4 | * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi. | ||
| 5 | * Copyright (C) 2001-2002 Benjamin Herrenschmidt | ||
| 6 | * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <asm/ptrace.h> | ||
| 11 | #include <linux/adb.h> | ||
| 12 | #include <linux/pmu.h> | ||
| 13 | #include <asm/backlight.h> | ||
| 14 | #include <asm/prom.h> | ||
| 15 | |||
| 16 | #define MAX_PMU_LEVEL 0xFF | ||
| 17 | |||
| 18 | static struct device_node *vias; | ||
| 19 | static struct backlight_properties pmu_backlight_data; | ||
| 20 | |||
| 21 | static int pmu_backlight_get_level_brightness(struct fb_info *info, | ||
| 22 | int level) | ||
| 23 | { | ||
| 24 | int pmulevel; | ||
| 25 | |||
| 26 | /* Get and convert the value */ | ||
| 27 | mutex_lock(&info->bl_mutex); | ||
| 28 | pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; | ||
| 29 | mutex_unlock(&info->bl_mutex); | ||
| 30 | |||
| 31 | if (pmulevel < 0) | ||
| 32 | pmulevel = 0; | ||
| 33 | else if (pmulevel > MAX_PMU_LEVEL) | ||
| 34 | pmulevel = MAX_PMU_LEVEL; | ||
| 35 | |||
| 36 | return pmulevel; | ||
| 37 | } | ||
| 38 | |||
| 39 | static int pmu_backlight_update_status(struct backlight_device *bd) | ||
| 40 | { | ||
| 41 | struct fb_info *info = class_get_devdata(&bd->class_dev); | ||
| 42 | struct adb_request req; | ||
| 43 | int pmulevel, level = bd->props->brightness; | ||
| 44 | |||
| 45 | if (vias == NULL) | ||
| 46 | return -ENODEV; | ||
| 47 | |||
| 48 | if (bd->props->power != FB_BLANK_UNBLANK || | ||
| 49 | bd->props->fb_blank != FB_BLANK_UNBLANK) | ||
| 50 | level = 0; | ||
| 51 | |||
| 52 | pmulevel = pmu_backlight_get_level_brightness(info, level); | ||
| 53 | |||
| 54 | pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); | ||
| 55 | pmu_wait_complete(&req); | ||
| 56 | |||
| 57 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | ||
| 58 | PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF)); | ||
| 59 | pmu_wait_complete(&req); | ||
| 60 | |||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int pmu_backlight_get_brightness(struct backlight_device *bd) | ||
| 65 | { | ||
| 66 | return bd->props->brightness; | ||
| 67 | } | ||
| 68 | |||
| 69 | static struct backlight_properties pmu_backlight_data = { | ||
| 70 | .owner = THIS_MODULE, | ||
| 71 | .get_brightness = pmu_backlight_get_brightness, | ||
| 72 | .update_status = pmu_backlight_update_status, | ||
| 73 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | ||
| 74 | }; | ||
| 75 | |||
| 76 | void __init pmu_backlight_init(struct device_node *in_vias) | ||
| 77 | { | ||
| 78 | struct backlight_device *bd; | ||
| 79 | struct fb_info *info; | ||
| 80 | char name[10]; | ||
| 81 | int level, autosave; | ||
| 82 | |||
| 83 | vias = in_vias; | ||
| 84 | |||
| 85 | /* Special case for the old PowerBook since I can't test on it */ | ||
| 86 | autosave = | ||
| 87 | machine_is_compatible("AAPL,3400/2400") || | ||
| 88 | machine_is_compatible("AAPL,3500"); | ||
| 89 | |||
| 90 | if (!autosave && | ||
| 91 | !pmac_has_backlight_type("pmu") && | ||
| 92 | !machine_is_compatible("AAPL,PowerBook1998") && | ||
| 93 | !machine_is_compatible("PowerBook1,1")) | ||
| 94 | return; | ||
| 95 | |||
| 96 | /* Actually, this is a hack, but I don't know of a better way | ||
| 97 | * to get the first framebuffer device. | ||
| 98 | */ | ||
| 99 | info = registered_fb[0]; | ||
| 100 | if (!info) { | ||
| 101 | printk("pmubl: No framebuffer found\n"); | ||
| 102 | goto error; | ||
| 103 | } | ||
| 104 | |||
| 105 | snprintf(name, sizeof(name), "pmubl%d", info->node); | ||
| 106 | |||
| 107 | bd = backlight_device_register(name, info, &pmu_backlight_data); | ||
| 108 | if (IS_ERR(bd)) { | ||
| 109 | printk("pmubl: Backlight registration failed\n"); | ||
| 110 | goto error; | ||
| 111 | } | ||
| 112 | |||
| 113 | mutex_lock(&info->bl_mutex); | ||
| 114 | info->bl_dev = bd; | ||
| 115 | fb_bl_default_curve(info, 0x7F, 0x46, 0x0E); | ||
| 116 | mutex_unlock(&info->bl_mutex); | ||
| 117 | |||
| 118 | level = pmu_backlight_data.max_brightness; | ||
| 119 | |||
| 120 | if (autosave) { | ||
| 121 | /* read autosaved value if available */ | ||
| 122 | struct adb_request req; | ||
| 123 | pmu_request(&req, NULL, 2, 0xd9, 0); | ||
| 124 | pmu_wait_complete(&req); | ||
| 125 | |||
| 126 | mutex_lock(&info->bl_mutex); | ||
| 127 | level = pmac_backlight_curve_lookup(info, | ||
| 128 | (req.reply[0] >> 4) * | ||
| 129 | pmu_backlight_data.max_brightness / 15); | ||
| 130 | mutex_unlock(&info->bl_mutex); | ||
| 131 | } | ||
| 132 | |||
| 133 | up(&bd->sem); | ||
| 134 | bd->props->brightness = level; | ||
| 135 | bd->props->power = FB_BLANK_UNBLANK; | ||
| 136 | bd->props->update_status(bd); | ||
| 137 | down(&bd->sem); | ||
| 138 | |||
| 139 | mutex_lock(&pmac_backlight_mutex); | ||
| 140 | if (!pmac_backlight) | ||
| 141 | pmac_backlight = bd; | ||
| 142 | mutex_unlock(&pmac_backlight_mutex); | ||
| 143 | |||
| 144 | printk("pmubl: Backlight initialized (%s)\n", name); | ||
| 145 | |||
| 146 | return; | ||
| 147 | |||
| 148 | error: | ||
| 149 | return; | ||
| 150 | } | ||
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index c63d4e7984be..2a355ae59562 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
| @@ -144,7 +144,6 @@ static int data_index; | |||
| 144 | static int data_len; | 144 | static int data_len; |
| 145 | static volatile int adb_int_pending; | 145 | static volatile int adb_int_pending; |
| 146 | static volatile int disable_poll; | 146 | static volatile int disable_poll; |
| 147 | static struct adb_request bright_req_1, bright_req_2; | ||
| 148 | static struct device_node *vias; | 147 | static struct device_node *vias; |
| 149 | static int pmu_kind = PMU_UNKNOWN; | 148 | static int pmu_kind = PMU_UNKNOWN; |
| 150 | static int pmu_fully_inited = 0; | 149 | static int pmu_fully_inited = 0; |
| @@ -161,7 +160,7 @@ static int drop_interrupts; | |||
| 161 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) | 160 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) |
| 162 | static int option_lid_wakeup = 1; | 161 | static int option_lid_wakeup = 1; |
| 163 | #endif /* CONFIG_PM && CONFIG_PPC32 */ | 162 | #endif /* CONFIG_PM && CONFIG_PPC32 */ |
| 164 | #if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT) | 163 | #if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY) |
| 165 | static int sleep_in_progress; | 164 | static int sleep_in_progress; |
| 166 | #endif | 165 | #endif |
| 167 | static unsigned long async_req_locks; | 166 | static unsigned long async_req_locks; |
| @@ -208,10 +207,6 @@ static int proc_get_info(char *page, char **start, off_t off, | |||
| 208 | int count, int *eof, void *data); | 207 | int count, int *eof, void *data); |
| 209 | static int proc_get_irqstats(char *page, char **start, off_t off, | 208 | static int proc_get_irqstats(char *page, char **start, off_t off, |
| 210 | int count, int *eof, void *data); | 209 | int count, int *eof, void *data); |
| 211 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 212 | static int pmu_set_backlight_level(int level, void* data); | ||
| 213 | static int pmu_set_backlight_enable(int on, int level, void* data); | ||
| 214 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 215 | static void pmu_pass_intr(unsigned char *data, int len); | 210 | static void pmu_pass_intr(unsigned char *data, int len); |
| 216 | static int proc_get_batt(char *page, char **start, off_t off, | 211 | static int proc_get_batt(char *page, char **start, off_t off, |
| 217 | int count, int *eof, void *data); | 212 | int count, int *eof, void *data); |
| @@ -292,13 +287,6 @@ static char *pbook_type[] = { | |||
| 292 | "Core99" | 287 | "Core99" |
| 293 | }; | 288 | }; |
| 294 | 289 | ||
| 295 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 296 | static struct backlight_controller pmu_backlight_controller = { | ||
| 297 | pmu_set_backlight_enable, | ||
| 298 | pmu_set_backlight_level | ||
| 299 | }; | ||
| 300 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 301 | |||
| 302 | int __init find_via_pmu(void) | 290 | int __init find_via_pmu(void) |
| 303 | { | 291 | { |
| 304 | u64 taddr; | 292 | u64 taddr; |
| @@ -417,8 +405,6 @@ static int __init via_pmu_start(void) | |||
| 417 | if (vias == NULL) | 405 | if (vias == NULL) |
| 418 | return -ENODEV; | 406 | return -ENODEV; |
| 419 | 407 | ||
| 420 | bright_req_1.complete = 1; | ||
| 421 | bright_req_2.complete = 1; | ||
| 422 | batt_req.complete = 1; | 408 | batt_req.complete = 1; |
| 423 | 409 | ||
| 424 | #ifndef CONFIG_PPC_MERGE | 410 | #ifndef CONFIG_PPC_MERGE |
| @@ -483,9 +469,9 @@ static int __init via_pmu_dev_init(void) | |||
| 483 | return -ENODEV; | 469 | return -ENODEV; |
| 484 | 470 | ||
| 485 | #ifdef CONFIG_PMAC_BACKLIGHT | 471 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 486 | /* Enable backlight */ | 472 | /* Initialize backlight */ |
| 487 | register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); | 473 | pmu_backlight_init(vias); |
| 488 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 474 | #endif |
| 489 | 475 | ||
| 490 | #ifdef CONFIG_PPC32 | 476 | #ifdef CONFIG_PPC32 |
| 491 | if (machine_is_compatible("AAPL,3400/2400") || | 477 | if (machine_is_compatible("AAPL,3400/2400") || |
| @@ -1424,7 +1410,7 @@ next: | |||
| 1424 | #ifdef CONFIG_INPUT_ADBHID | 1410 | #ifdef CONFIG_INPUT_ADBHID |
| 1425 | if (!disable_kernel_backlight) | 1411 | if (!disable_kernel_backlight) |
| 1426 | #endif /* CONFIG_INPUT_ADBHID */ | 1412 | #endif /* CONFIG_INPUT_ADBHID */ |
| 1427 | set_backlight_level(data[1] >> 4); | 1413 | pmac_backlight_set_legacy_brightness(data[1] >> 4); |
| 1428 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 1414 | #endif /* CONFIG_PMAC_BACKLIGHT */ |
| 1429 | } | 1415 | } |
| 1430 | /* Tick interrupt */ | 1416 | /* Tick interrupt */ |
| @@ -1674,61 +1660,6 @@ gpio1_interrupt(int irq, void *arg, struct pt_regs *regs) | |||
| 1674 | return IRQ_NONE; | 1660 | return IRQ_NONE; |
| 1675 | } | 1661 | } |
| 1676 | 1662 | ||
| 1677 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 1678 | static int backlight_to_bright[] = { | ||
| 1679 | 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e, | ||
| 1680 | 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e | ||
| 1681 | }; | ||
| 1682 | |||
| 1683 | static int | ||
| 1684 | pmu_set_backlight_enable(int on, int level, void* data) | ||
| 1685 | { | ||
| 1686 | struct adb_request req; | ||
| 1687 | |||
| 1688 | if (vias == NULL) | ||
| 1689 | return -ENODEV; | ||
| 1690 | |||
| 1691 | if (on) { | ||
| 1692 | pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, | ||
| 1693 | backlight_to_bright[level]); | ||
| 1694 | pmu_wait_complete(&req); | ||
| 1695 | } | ||
| 1696 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL, | ||
| 1697 | PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF)); | ||
| 1698 | pmu_wait_complete(&req); | ||
| 1699 | |||
| 1700 | return 0; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | static void | ||
| 1704 | pmu_bright_complete(struct adb_request *req) | ||
| 1705 | { | ||
| 1706 | if (req == &bright_req_1) | ||
| 1707 | clear_bit(1, &async_req_locks); | ||
| 1708 | if (req == &bright_req_2) | ||
| 1709 | clear_bit(2, &async_req_locks); | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | static int | ||
| 1713 | pmu_set_backlight_level(int level, void* data) | ||
| 1714 | { | ||
| 1715 | if (vias == NULL) | ||
| 1716 | return -ENODEV; | ||
| 1717 | |||
| 1718 | if (test_and_set_bit(1, &async_req_locks)) | ||
| 1719 | return -EAGAIN; | ||
| 1720 | pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT, | ||
| 1721 | backlight_to_bright[level]); | ||
| 1722 | if (test_and_set_bit(2, &async_req_locks)) | ||
| 1723 | return -EAGAIN; | ||
| 1724 | pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL, | ||
| 1725 | PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ? | ||
| 1726 | PMU_POW_ON : PMU_POW_OFF)); | ||
| 1727 | |||
| 1728 | return 0; | ||
| 1729 | } | ||
| 1730 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 1731 | |||
| 1732 | void | 1663 | void |
| 1733 | pmu_enable_irled(int on) | 1664 | pmu_enable_irled(int on) |
| 1734 | { | 1665 | { |
| @@ -2145,9 +2076,8 @@ pmac_suspend_devices(void) | |||
| 2145 | return -EBUSY; | 2076 | return -EBUSY; |
| 2146 | } | 2077 | } |
| 2147 | 2078 | ||
| 2148 | /* Wait for completion of async backlight requests */ | 2079 | /* Wait for completion of async requests */ |
| 2149 | while (!bright_req_1.complete || !bright_req_2.complete || | 2080 | while (!batt_req.complete) |
| 2150 | !batt_req.complete) | ||
| 2151 | pmu_poll(); | 2081 | pmu_poll(); |
| 2152 | 2082 | ||
| 2153 | /* Giveup the lazy FPU & vec so we don't have to back them | 2083 | /* Giveup the lazy FPU & vec so we don't have to back them |
| @@ -2678,26 +2608,34 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
| 2678 | return put_user(1, argp); | 2608 | return put_user(1, argp); |
| 2679 | #endif /* CONFIG_PM && CONFIG_PPC32 */ | 2609 | #endif /* CONFIG_PM && CONFIG_PPC32 */ |
| 2680 | 2610 | ||
| 2681 | #ifdef CONFIG_PMAC_BACKLIGHT | 2611 | #ifdef CONFIG_PMAC_BACKLIGHT_LEGACY |
| 2682 | /* Backlight should have its own device or go via | 2612 | /* Compatibility ioctl's for backlight */ |
| 2683 | * the fbdev | ||
| 2684 | */ | ||
| 2685 | case PMU_IOC_GET_BACKLIGHT: | 2613 | case PMU_IOC_GET_BACKLIGHT: |
| 2614 | { | ||
| 2615 | int brightness; | ||
| 2616 | |||
| 2686 | if (sleep_in_progress) | 2617 | if (sleep_in_progress) |
| 2687 | return -EBUSY; | 2618 | return -EBUSY; |
| 2688 | error = get_backlight_level(); | 2619 | |
| 2689 | if (error < 0) | 2620 | brightness = pmac_backlight_get_legacy_brightness(); |
| 2690 | return error; | 2621 | if (brightness < 0) |
| 2691 | return put_user(error, argp); | 2622 | return brightness; |
| 2623 | else | ||
| 2624 | return put_user(brightness, argp); | ||
| 2625 | |||
| 2626 | } | ||
| 2692 | case PMU_IOC_SET_BACKLIGHT: | 2627 | case PMU_IOC_SET_BACKLIGHT: |
| 2693 | { | 2628 | { |
| 2694 | __u32 value; | 2629 | int brightness; |
| 2630 | |||
| 2695 | if (sleep_in_progress) | 2631 | if (sleep_in_progress) |
| 2696 | return -EBUSY; | 2632 | return -EBUSY; |
| 2697 | error = get_user(value, argp); | 2633 | |
| 2698 | if (!error) | 2634 | error = get_user(brightness, argp); |
| 2699 | error = set_backlight_level(value); | 2635 | if (error) |
| 2700 | break; | 2636 | return error; |
| 2637 | |||
| 2638 | return pmac_backlight_set_legacy_brightness(brightness); | ||
| 2701 | } | 2639 | } |
| 2702 | #ifdef CONFIG_INPUT_ADBHID | 2640 | #ifdef CONFIG_INPUT_ADBHID |
| 2703 | case PMU_IOC_GRAB_BACKLIGHT: { | 2641 | case PMU_IOC_GRAB_BACKLIGHT: { |
| @@ -2713,7 +2651,7 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
| 2713 | return 0; | 2651 | return 0; |
| 2714 | } | 2652 | } |
| 2715 | #endif /* CONFIG_INPUT_ADBHID */ | 2653 | #endif /* CONFIG_INPUT_ADBHID */ |
| 2716 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 2654 | #endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */ |
| 2717 | case PMU_IOC_GET_MODEL: | 2655 | case PMU_IOC_GET_MODEL: |
| 2718 | return put_user(pmu_kind, argp); | 2656 | return put_user(pmu_kind, argp); |
| 2719 | case PMU_IOC_HAS_ADB: | 2657 | case PMU_IOC_HAS_ADB: |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 5a2840aeb547..168ede7902bd 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -86,6 +86,11 @@ config FB_FIRMWARE_EDID | |||
| 86 | combination with certain motherboards and monitors are known to | 86 | combination with certain motherboards and monitors are known to |
| 87 | suffer from this problem. | 87 | suffer from this problem. |
| 88 | 88 | ||
| 89 | config FB_BACKLIGHT | ||
| 90 | bool | ||
| 91 | depends on FB | ||
| 92 | default n | ||
| 93 | |||
| 89 | config FB_MODE_HELPERS | 94 | config FB_MODE_HELPERS |
| 90 | bool "Enable Video Mode Handling Helpers" | 95 | bool "Enable Video Mode Handling Helpers" |
| 91 | depends on FB | 96 | depends on FB |
| @@ -717,6 +722,16 @@ config FB_NVIDIA_I2C | |||
| 717 | independently validate video mode parameters, you should say Y | 722 | independently validate video mode parameters, you should say Y |
| 718 | here. | 723 | here. |
| 719 | 724 | ||
| 725 | config FB_NVIDIA_BACKLIGHT | ||
| 726 | bool "Support for backlight control" | ||
| 727 | depends on FB_NVIDIA && PPC_PMAC | ||
| 728 | select FB_BACKLIGHT | ||
| 729 | select BACKLIGHT_LCD_SUPPORT | ||
| 730 | select BACKLIGHT_CLASS_DEVICE | ||
| 731 | default y | ||
| 732 | help | ||
| 733 | Say Y here if you want to control the backlight of your display. | ||
| 734 | |||
| 720 | config FB_RIVA | 735 | config FB_RIVA |
| 721 | tristate "nVidia Riva support" | 736 | tristate "nVidia Riva support" |
| 722 | depends on FB && PCI | 737 | depends on FB && PCI |
| @@ -755,6 +770,16 @@ config FB_RIVA_DEBUG | |||
| 755 | of debugging informations to provide to the maintainer when | 770 | of debugging informations to provide to the maintainer when |
| 756 | something goes wrong. | 771 | something goes wrong. |
| 757 | 772 | ||
| 773 | config FB_RIVA_BACKLIGHT | ||
| 774 | bool "Support for backlight control" | ||
| 775 | depends on FB_RIVA && PPC_PMAC | ||
| 776 | select FB_BACKLIGHT | ||
| 777 | select BACKLIGHT_LCD_SUPPORT | ||
| 778 | select BACKLIGHT_CLASS_DEVICE | ||
| 779 | default y | ||
| 780 | help | ||
| 781 | Say Y here if you want to control the backlight of your display. | ||
| 782 | |||
| 758 | config FB_I810 | 783 | config FB_I810 |
| 759 | tristate "Intel 810/815 support (EXPERIMENTAL)" | 784 | tristate "Intel 810/815 support (EXPERIMENTAL)" |
| 760 | depends on FB && EXPERIMENTAL && PCI && X86_32 | 785 | depends on FB && EXPERIMENTAL && PCI && X86_32 |
| @@ -993,6 +1018,7 @@ config FB_RADEON | |||
| 993 | 1018 | ||
| 994 | There is a product page at | 1019 | There is a product page at |
| 995 | http://apps.ati.com/ATIcompare/ | 1020 | http://apps.ati.com/ATIcompare/ |
| 1021 | |||
| 996 | config FB_RADEON_I2C | 1022 | config FB_RADEON_I2C |
| 997 | bool "DDC/I2C for ATI Radeon support" | 1023 | bool "DDC/I2C for ATI Radeon support" |
| 998 | depends on FB_RADEON | 1024 | depends on FB_RADEON |
| @@ -1000,6 +1026,16 @@ config FB_RADEON_I2C | |||
| 1000 | help | 1026 | help |
| 1001 | Say Y here if you want DDC/I2C support for your Radeon board. | 1027 | Say Y here if you want DDC/I2C support for your Radeon board. |
| 1002 | 1028 | ||
| 1029 | config FB_RADEON_BACKLIGHT | ||
| 1030 | bool "Support for backlight control" | ||
| 1031 | depends on FB_RADEON && PPC_PMAC | ||
| 1032 | select FB_BACKLIGHT | ||
| 1033 | select BACKLIGHT_LCD_SUPPORT | ||
| 1034 | select BACKLIGHT_CLASS_DEVICE | ||
| 1035 | default y | ||
| 1036 | help | ||
| 1037 | Say Y here if you want to control the backlight of your display. | ||
| 1038 | |||
| 1003 | config FB_RADEON_DEBUG | 1039 | config FB_RADEON_DEBUG |
| 1004 | bool "Lots of debug output from Radeon driver" | 1040 | bool "Lots of debug output from Radeon driver" |
| 1005 | depends on FB_RADEON | 1041 | depends on FB_RADEON |
| @@ -1024,6 +1060,16 @@ config FB_ATY128 | |||
| 1024 | To compile this driver as a module, choose M here: the | 1060 | To compile this driver as a module, choose M here: the |
| 1025 | module will be called aty128fb. | 1061 | module will be called aty128fb. |
| 1026 | 1062 | ||
| 1063 | config FB_ATY128_BACKLIGHT | ||
| 1064 | bool "Support for backlight control" | ||
| 1065 | depends on FB_ATY128 && PPC_PMAC | ||
| 1066 | select FB_BACKLIGHT | ||
| 1067 | select BACKLIGHT_LCD_SUPPORT | ||
| 1068 | select BACKLIGHT_CLASS_DEVICE | ||
| 1069 | default y | ||
| 1070 | help | ||
| 1071 | Say Y here if you want to control the backlight of your display. | ||
| 1072 | |||
| 1027 | config FB_ATY | 1073 | config FB_ATY |
| 1028 | tristate "ATI Mach64 display support" if PCI || ATARI | 1074 | tristate "ATI Mach64 display support" if PCI || ATARI |
| 1029 | depends on FB && !SPARC32 | 1075 | depends on FB && !SPARC32 |
| @@ -1066,6 +1112,16 @@ config FB_ATY_GX | |||
| 1066 | is at | 1112 | is at |
| 1067 | <http://support.ati.com/products/pc/mach64/graphics_xpression.html>. | 1113 | <http://support.ati.com/products/pc/mach64/graphics_xpression.html>. |
| 1068 | 1114 | ||
| 1115 | config FB_ATY_BACKLIGHT | ||
| 1116 | bool "Support for backlight control" | ||
| 1117 | depends on FB_ATY && PPC_PMAC | ||
| 1118 | select FB_BACKLIGHT | ||
| 1119 | select BACKLIGHT_LCD_SUPPORT | ||
| 1120 | select BACKLIGHT_CLASS_DEVICE | ||
| 1121 | default y | ||
| 1122 | help | ||
| 1123 | Say Y here if you want to control the backlight of your display. | ||
| 1124 | |||
| 1069 | config FB_S3TRIO | 1125 | config FB_S3TRIO |
| 1070 | bool "S3 Trio display support" | 1126 | bool "S3 Trio display support" |
| 1071 | depends on (FB = y) && PPC && BROKEN | 1127 | depends on (FB = y) && PPC && BROKEN |
diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile index 18521397a6e3..a6cc0e9ec790 100644 --- a/drivers/video/aty/Makefile +++ b/drivers/video/aty/Makefile | |||
| @@ -10,5 +10,6 @@ atyfb-objs := $(atyfb-y) | |||
| 10 | 10 | ||
| 11 | radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o | 11 | radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o |
| 12 | radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o | 12 | radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o |
| 13 | radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT) += radeon_backlight.o | ||
| 13 | radeonfb-objs := $(radeonfb-y) | 14 | radeonfb-objs := $(radeonfb-y) |
| 14 | 15 | ||
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index f7bbff4ddc6a..db878fd55fb2 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
| @@ -64,6 +64,7 @@ | |||
| 64 | #include <linux/pci.h> | 64 | #include <linux/pci.h> |
| 65 | #include <linux/ioport.h> | 65 | #include <linux/ioport.h> |
| 66 | #include <linux/console.h> | 66 | #include <linux/console.h> |
| 67 | #include <linux/backlight.h> | ||
| 67 | #include <asm/io.h> | 68 | #include <asm/io.h> |
| 68 | 69 | ||
| 69 | #ifdef CONFIG_PPC_PMAC | 70 | #ifdef CONFIG_PPC_PMAC |
| @@ -480,16 +481,6 @@ static struct fb_ops aty128fb_ops = { | |||
| 480 | .fb_imageblit = cfb_imageblit, | 481 | .fb_imageblit = cfb_imageblit, |
| 481 | }; | 482 | }; |
| 482 | 483 | ||
| 483 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 484 | static int aty128_set_backlight_enable(int on, int level, void* data); | ||
| 485 | static int aty128_set_backlight_level(int level, void* data); | ||
| 486 | |||
| 487 | static struct backlight_controller aty128_backlight_controller = { | ||
| 488 | aty128_set_backlight_enable, | ||
| 489 | aty128_set_backlight_level | ||
| 490 | }; | ||
| 491 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 492 | |||
| 493 | /* | 484 | /* |
| 494 | * Functions to read from/write to the mmio registers | 485 | * Functions to read from/write to the mmio registers |
| 495 | * - endian conversions may possibly be avoided by | 486 | * - endian conversions may possibly be avoided by |
| @@ -1258,19 +1249,35 @@ static void aty128_set_crt_enable(struct aty128fb_par *par, int on) | |||
| 1258 | static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) | 1249 | static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) |
| 1259 | { | 1250 | { |
| 1260 | u32 reg; | 1251 | u32 reg; |
| 1252 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | ||
| 1253 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 1254 | #endif | ||
| 1261 | 1255 | ||
| 1262 | if (on) { | 1256 | if (on) { |
| 1263 | reg = aty_ld_le32(LVDS_GEN_CNTL); | 1257 | reg = aty_ld_le32(LVDS_GEN_CNTL); |
| 1264 | reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION; | 1258 | reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION; |
| 1265 | reg &= ~LVDS_DISPLAY_DIS; | 1259 | reg &= ~LVDS_DISPLAY_DIS; |
| 1266 | aty_st_le32(LVDS_GEN_CNTL, reg); | 1260 | aty_st_le32(LVDS_GEN_CNTL, reg); |
| 1267 | #ifdef CONFIG_PMAC_BACKLIGHT | 1261 | #ifdef CONFIG_FB_ATY128_BACKLIGHT |
| 1268 | aty128_set_backlight_enable(get_backlight_enable(), | 1262 | mutex_lock(&info->bl_mutex); |
| 1269 | get_backlight_level(), par); | 1263 | if (info->bl_dev) { |
| 1264 | down(&info->bl_dev->sem); | ||
| 1265 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 1266 | up(&info->bl_dev->sem); | ||
| 1267 | } | ||
| 1268 | mutex_unlock(&info->bl_mutex); | ||
| 1270 | #endif | 1269 | #endif |
| 1271 | } else { | 1270 | } else { |
| 1272 | #ifdef CONFIG_PMAC_BACKLIGHT | 1271 | #ifdef CONFIG_FB_ATY128_BACKLIGHT |
| 1273 | aty128_set_backlight_enable(0, 0, par); | 1272 | mutex_lock(&info->bl_mutex); |
| 1273 | if (info->bl_dev) { | ||
| 1274 | down(&info->bl_dev->sem); | ||
| 1275 | info->bl_dev->props->brightness = 0; | ||
| 1276 | info->bl_dev->props->power = FB_BLANK_POWERDOWN; | ||
| 1277 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 1278 | up(&info->bl_dev->sem); | ||
| 1279 | } | ||
| 1280 | mutex_unlock(&info->bl_mutex); | ||
| 1274 | #endif | 1281 | #endif |
| 1275 | reg = aty_ld_le32(LVDS_GEN_CNTL); | 1282 | reg = aty_ld_le32(LVDS_GEN_CNTL); |
| 1276 | reg |= LVDS_DISPLAY_DIS; | 1283 | reg |= LVDS_DISPLAY_DIS; |
| @@ -1691,6 +1698,184 @@ static int __init aty128fb_setup(char *options) | |||
| 1691 | } | 1698 | } |
| 1692 | #endif /* MODULE */ | 1699 | #endif /* MODULE */ |
| 1693 | 1700 | ||
| 1701 | /* Backlight */ | ||
| 1702 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | ||
| 1703 | #define MAX_LEVEL 0xFF | ||
| 1704 | |||
| 1705 | static struct backlight_properties aty128_bl_data; | ||
| 1706 | |||
| 1707 | static int aty128_bl_get_level_brightness(struct aty128fb_par *par, | ||
| 1708 | int level) | ||
| 1709 | { | ||
| 1710 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 1711 | int atylevel; | ||
| 1712 | |||
| 1713 | /* Get and convert the value */ | ||
| 1714 | mutex_lock(&info->bl_mutex); | ||
| 1715 | atylevel = MAX_LEVEL - | ||
| 1716 | (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); | ||
| 1717 | mutex_unlock(&info->bl_mutex); | ||
| 1718 | |||
| 1719 | if (atylevel < 0) | ||
| 1720 | atylevel = 0; | ||
| 1721 | else if (atylevel > MAX_LEVEL) | ||
| 1722 | atylevel = MAX_LEVEL; | ||
| 1723 | |||
| 1724 | return atylevel; | ||
| 1725 | } | ||
| 1726 | |||
| 1727 | /* We turn off the LCD completely instead of just dimming the backlight. | ||
| 1728 | * This provides greater power saving and the display is useless without | ||
| 1729 | * backlight anyway | ||
| 1730 | */ | ||
| 1731 | #define BACKLIGHT_LVDS_OFF | ||
| 1732 | /* That one prevents proper CRT output with LCD off */ | ||
| 1733 | #undef BACKLIGHT_DAC_OFF | ||
| 1734 | |||
| 1735 | static int aty128_bl_update_status(struct backlight_device *bd) | ||
| 1736 | { | ||
| 1737 | struct aty128fb_par *par = class_get_devdata(&bd->class_dev); | ||
| 1738 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); | ||
| 1739 | int level; | ||
| 1740 | |||
| 1741 | if (bd->props->power != FB_BLANK_UNBLANK || | ||
| 1742 | bd->props->fb_blank != FB_BLANK_UNBLANK || | ||
| 1743 | !par->lcd_on) | ||
| 1744 | level = 0; | ||
| 1745 | else | ||
| 1746 | level = bd->props->brightness; | ||
| 1747 | |||
| 1748 | reg |= LVDS_BL_MOD_EN | LVDS_BLON; | ||
| 1749 | if (level > 0) { | ||
| 1750 | reg |= LVDS_DIGION; | ||
| 1751 | if (!(reg & LVDS_ON)) { | ||
| 1752 | reg &= ~LVDS_BLON; | ||
| 1753 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 1754 | aty_ld_le32(LVDS_GEN_CNTL); | ||
| 1755 | mdelay(10); | ||
| 1756 | reg |= LVDS_BLON; | ||
| 1757 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 1758 | } | ||
| 1759 | reg &= ~LVDS_BL_MOD_LEVEL_MASK; | ||
| 1760 | reg |= (aty128_bl_get_level_brightness(par, level) << LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 1761 | #ifdef BACKLIGHT_LVDS_OFF | ||
| 1762 | reg |= LVDS_ON | LVDS_EN; | ||
| 1763 | reg &= ~LVDS_DISPLAY_DIS; | ||
| 1764 | #endif | ||
| 1765 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 1766 | #ifdef BACKLIGHT_DAC_OFF | ||
| 1767 | aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); | ||
| 1768 | #endif | ||
| 1769 | } else { | ||
| 1770 | reg &= ~LVDS_BL_MOD_LEVEL_MASK; | ||
| 1771 | reg |= (aty128_bl_get_level_brightness(par, 0) << LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 1772 | #ifdef BACKLIGHT_LVDS_OFF | ||
| 1773 | reg |= LVDS_DISPLAY_DIS; | ||
| 1774 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 1775 | aty_ld_le32(LVDS_GEN_CNTL); | ||
| 1776 | udelay(10); | ||
| 1777 | reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); | ||
| 1778 | #endif | ||
| 1779 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 1780 | #ifdef BACKLIGHT_DAC_OFF | ||
| 1781 | aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); | ||
| 1782 | #endif | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | return 0; | ||
| 1786 | } | ||
| 1787 | |||
| 1788 | static int aty128_bl_get_brightness(struct backlight_device *bd) | ||
| 1789 | { | ||
| 1790 | return bd->props->brightness; | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | static struct backlight_properties aty128_bl_data = { | ||
| 1794 | .owner = THIS_MODULE, | ||
| 1795 | .get_brightness = aty128_bl_get_brightness, | ||
| 1796 | .update_status = aty128_bl_update_status, | ||
| 1797 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | ||
| 1798 | }; | ||
| 1799 | |||
| 1800 | static void aty128_bl_init(struct aty128fb_par *par) | ||
| 1801 | { | ||
| 1802 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 1803 | struct backlight_device *bd; | ||
| 1804 | char name[12]; | ||
| 1805 | |||
| 1806 | /* Could be extended to Rage128Pro LVDS output too */ | ||
| 1807 | if (par->chip_gen != rage_M3) | ||
| 1808 | return; | ||
| 1809 | |||
| 1810 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 1811 | if (!pmac_has_backlight_type("ati")) | ||
| 1812 | return; | ||
| 1813 | #endif | ||
| 1814 | |||
| 1815 | snprintf(name, sizeof(name), "aty128bl%d", info->node); | ||
| 1816 | |||
| 1817 | bd = backlight_device_register(name, par, &aty128_bl_data); | ||
| 1818 | if (IS_ERR(bd)) { | ||
| 1819 | info->bl_dev = NULL; | ||
| 1820 | printk("aty128: Backlight registration failed\n"); | ||
| 1821 | goto error; | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | mutex_lock(&info->bl_mutex); | ||
| 1825 | info->bl_dev = bd; | ||
| 1826 | fb_bl_default_curve(info, 0, | ||
| 1827 | 63 * FB_BACKLIGHT_MAX / MAX_LEVEL, | ||
| 1828 | 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); | ||
| 1829 | mutex_unlock(&info->bl_mutex); | ||
| 1830 | |||
| 1831 | up(&bd->sem); | ||
| 1832 | bd->props->brightness = aty128_bl_data.max_brightness; | ||
| 1833 | bd->props->power = FB_BLANK_UNBLANK; | ||
| 1834 | bd->props->update_status(bd); | ||
| 1835 | down(&bd->sem); | ||
| 1836 | |||
| 1837 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 1838 | mutex_lock(&pmac_backlight_mutex); | ||
| 1839 | if (!pmac_backlight) | ||
| 1840 | pmac_backlight = bd; | ||
| 1841 | mutex_unlock(&pmac_backlight_mutex); | ||
| 1842 | #endif | ||
| 1843 | |||
| 1844 | printk("aty128: Backlight initialized (%s)\n", name); | ||
| 1845 | |||
| 1846 | return; | ||
| 1847 | |||
| 1848 | error: | ||
| 1849 | return; | ||
| 1850 | } | ||
| 1851 | |||
| 1852 | static void aty128_bl_exit(struct aty128fb_par *par) | ||
| 1853 | { | ||
| 1854 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 1855 | |||
| 1856 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 1857 | mutex_lock(&pmac_backlight_mutex); | ||
| 1858 | #endif | ||
| 1859 | |||
| 1860 | mutex_lock(&info->bl_mutex); | ||
| 1861 | if (info->bl_dev) { | ||
| 1862 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 1863 | if (pmac_backlight == info->bl_dev) | ||
| 1864 | pmac_backlight = NULL; | ||
| 1865 | #endif | ||
| 1866 | |||
| 1867 | backlight_device_unregister(info->bl_dev); | ||
| 1868 | info->bl_dev = NULL; | ||
| 1869 | |||
| 1870 | printk("aty128: Backlight unloaded\n"); | ||
| 1871 | } | ||
| 1872 | mutex_unlock(&info->bl_mutex); | ||
| 1873 | |||
| 1874 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 1875 | mutex_unlock(&pmac_backlight_mutex); | ||
| 1876 | #endif | ||
| 1877 | } | ||
| 1878 | #endif /* CONFIG_FB_ATY128_BACKLIGHT */ | ||
| 1694 | 1879 | ||
| 1695 | /* | 1880 | /* |
| 1696 | * Initialisation | 1881 | * Initialisation |
| @@ -1835,17 +2020,15 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id * | |||
| 1835 | if (register_framebuffer(info) < 0) | 2020 | if (register_framebuffer(info) < 0) |
| 1836 | return 0; | 2021 | return 0; |
| 1837 | 2022 | ||
| 1838 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 1839 | /* Could be extended to Rage128Pro LVDS output too */ | ||
| 1840 | if (par->chip_gen == rage_M3) | ||
| 1841 | register_backlight_controller(&aty128_backlight_controller, par, "ati"); | ||
| 1842 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 1843 | |||
| 1844 | par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); | 2023 | par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); |
| 1845 | par->pdev = pdev; | 2024 | par->pdev = pdev; |
| 1846 | par->asleep = 0; | 2025 | par->asleep = 0; |
| 1847 | par->lock_blank = 0; | 2026 | par->lock_blank = 0; |
| 1848 | 2027 | ||
| 2028 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | ||
| 2029 | aty128_bl_init(par); | ||
| 2030 | #endif | ||
| 2031 | |||
| 1849 | printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", | 2032 | printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", |
| 1850 | info->node, info->fix.id, video_card); | 2033 | info->node, info->fix.id, video_card); |
| 1851 | 2034 | ||
| @@ -1981,6 +2164,10 @@ static void __devexit aty128_remove(struct pci_dev *pdev) | |||
| 1981 | 2164 | ||
| 1982 | par = info->par; | 2165 | par = info->par; |
| 1983 | 2166 | ||
| 2167 | #ifdef CONFIG_FB_ATY128_BACKLIGHT | ||
| 2168 | aty128_bl_exit(par); | ||
| 2169 | #endif | ||
| 2170 | |||
| 1984 | unregister_framebuffer(info); | 2171 | unregister_framebuffer(info); |
| 1985 | #ifdef CONFIG_MTRR | 2172 | #ifdef CONFIG_MTRR |
| 1986 | if (par->mtrr.vram_valid) | 2173 | if (par->mtrr.vram_valid) |
| @@ -2011,10 +2198,14 @@ static int aty128fb_blank(int blank, struct fb_info *fb) | |||
| 2011 | if (par->lock_blank || par->asleep) | 2198 | if (par->lock_blank || par->asleep) |
| 2012 | return 0; | 2199 | return 0; |
| 2013 | 2200 | ||
| 2014 | #ifdef CONFIG_PMAC_BACKLIGHT | 2201 | #ifdef CONFIG_FB_ATY128_BACKLIGHT |
| 2015 | if (machine_is(powermac) && blank) | 2202 | if (machine_is(powermac) && blank) { |
| 2016 | set_backlight_enable(0); | 2203 | down(&fb->bl_dev->sem); |
| 2017 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 2204 | fb->bl_dev->props->power = FB_BLANK_POWERDOWN; |
| 2205 | fb->bl_dev->props->update_status(fb->bl_dev); | ||
| 2206 | up(&fb->bl_dev->sem); | ||
| 2207 | } | ||
| 2208 | #endif | ||
| 2018 | 2209 | ||
| 2019 | if (blank & FB_BLANK_VSYNC_SUSPEND) | 2210 | if (blank & FB_BLANK_VSYNC_SUSPEND) |
| 2020 | state |= 2; | 2211 | state |= 2; |
| @@ -2029,10 +2220,14 @@ static int aty128fb_blank(int blank, struct fb_info *fb) | |||
| 2029 | aty128_set_crt_enable(par, par->crt_on && !blank); | 2220 | aty128_set_crt_enable(par, par->crt_on && !blank); |
| 2030 | aty128_set_lcd_enable(par, par->lcd_on && !blank); | 2221 | aty128_set_lcd_enable(par, par->lcd_on && !blank); |
| 2031 | } | 2222 | } |
| 2032 | #ifdef CONFIG_PMAC_BACKLIGHT | 2223 | #ifdef CONFIG_FB_ATY128_BACKLIGHT |
| 2033 | if (machine_is(powermac) && !blank) | 2224 | if (machine_is(powermac) && !blank) { |
| 2034 | set_backlight_enable(1); | 2225 | down(&fb->bl_dev->sem); |
| 2035 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 2226 | fb->bl_dev->props->power = FB_BLANK_UNBLANK; |
| 2227 | fb->bl_dev->props->update_status(fb->bl_dev); | ||
| 2228 | up(&fb->bl_dev->sem); | ||
| 2229 | } | ||
| 2230 | #endif | ||
| 2036 | return 0; | 2231 | return 0; |
| 2037 | } | 2232 | } |
| 2038 | 2233 | ||
| @@ -2138,73 +2333,6 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
| 2138 | return -EINVAL; | 2333 | return -EINVAL; |
| 2139 | } | 2334 | } |
| 2140 | 2335 | ||
| 2141 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 2142 | static int backlight_conv[] = { | ||
| 2143 | 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, | ||
| 2144 | 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 | ||
| 2145 | }; | ||
| 2146 | |||
| 2147 | /* We turn off the LCD completely instead of just dimming the backlight. | ||
| 2148 | * This provides greater power saving and the display is useless without | ||
| 2149 | * backlight anyway | ||
| 2150 | */ | ||
| 2151 | #define BACKLIGHT_LVDS_OFF | ||
| 2152 | /* That one prevents proper CRT output with LCD off */ | ||
| 2153 | #undef BACKLIGHT_DAC_OFF | ||
| 2154 | |||
| 2155 | static int aty128_set_backlight_enable(int on, int level, void *data) | ||
| 2156 | { | ||
| 2157 | struct aty128fb_par *par = data; | ||
| 2158 | unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); | ||
| 2159 | |||
| 2160 | if (!par->lcd_on) | ||
| 2161 | on = 0; | ||
| 2162 | reg |= LVDS_BL_MOD_EN | LVDS_BLON; | ||
| 2163 | if (on && level > BACKLIGHT_OFF) { | ||
| 2164 | reg |= LVDS_DIGION; | ||
| 2165 | if (!(reg & LVDS_ON)) { | ||
| 2166 | reg &= ~LVDS_BLON; | ||
| 2167 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 2168 | (void)aty_ld_le32(LVDS_GEN_CNTL); | ||
| 2169 | mdelay(10); | ||
| 2170 | reg |= LVDS_BLON; | ||
| 2171 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 2172 | } | ||
| 2173 | reg &= ~LVDS_BL_MOD_LEVEL_MASK; | ||
| 2174 | reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 2175 | #ifdef BACKLIGHT_LVDS_OFF | ||
| 2176 | reg |= LVDS_ON | LVDS_EN; | ||
| 2177 | reg &= ~LVDS_DISPLAY_DIS; | ||
| 2178 | #endif | ||
| 2179 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 2180 | #ifdef BACKLIGHT_DAC_OFF | ||
| 2181 | aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); | ||
| 2182 | #endif | ||
| 2183 | } else { | ||
| 2184 | reg &= ~LVDS_BL_MOD_LEVEL_MASK; | ||
| 2185 | reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 2186 | #ifdef BACKLIGHT_LVDS_OFF | ||
| 2187 | reg |= LVDS_DISPLAY_DIS; | ||
| 2188 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 2189 | (void)aty_ld_le32(LVDS_GEN_CNTL); | ||
| 2190 | udelay(10); | ||
| 2191 | reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); | ||
| 2192 | #endif | ||
| 2193 | aty_st_le32(LVDS_GEN_CNTL, reg); | ||
| 2194 | #ifdef BACKLIGHT_DAC_OFF | ||
| 2195 | aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); | ||
| 2196 | #endif | ||
| 2197 | } | ||
| 2198 | |||
| 2199 | return 0; | ||
| 2200 | } | ||
| 2201 | |||
| 2202 | static int aty128_set_backlight_level(int level, void* data) | ||
| 2203 | { | ||
| 2204 | return aty128_set_backlight_enable(1, level, data); | ||
| 2205 | } | ||
| 2206 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 2207 | |||
| 2208 | #if 0 | 2336 | #if 0 |
| 2209 | /* | 2337 | /* |
| 2210 | * Accelerated functions | 2338 | * Accelerated functions |
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index e9b7a64c1ac4..43d2cb58af87 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h | |||
| @@ -151,6 +151,7 @@ struct atyfb_par { | |||
| 151 | int lock_blank; | 151 | int lock_blank; |
| 152 | unsigned long res_start; | 152 | unsigned long res_start; |
| 153 | unsigned long res_size; | 153 | unsigned long res_size; |
| 154 | struct pci_dev *pdev; | ||
| 154 | #ifdef __sparc__ | 155 | #ifdef __sparc__ |
| 155 | struct pci_mmap_map *mmap_map; | 156 | struct pci_mmap_map *mmap_map; |
| 156 | u8 mmaped; | 157 | u8 mmaped; |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index c054bb28b1c4..c5185f7cf4ba 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #include <linux/interrupt.h> | 66 | #include <linux/interrupt.h> |
| 67 | #include <linux/spinlock.h> | 67 | #include <linux/spinlock.h> |
| 68 | #include <linux/wait.h> | 68 | #include <linux/wait.h> |
| 69 | #include <linux/backlight.h> | ||
| 69 | 70 | ||
| 70 | #include <asm/io.h> | 71 | #include <asm/io.h> |
| 71 | #include <asm/uaccess.h> | 72 | #include <asm/uaccess.h> |
| @@ -2115,45 +2116,142 @@ static int atyfb_pci_resume(struct pci_dev *pdev) | |||
| 2115 | 2116 | ||
| 2116 | #endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */ | 2117 | #endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */ |
| 2117 | 2118 | ||
| 2118 | #ifdef CONFIG_PMAC_BACKLIGHT | 2119 | /* Backlight */ |
| 2120 | #ifdef CONFIG_FB_ATY_BACKLIGHT | ||
| 2121 | #define MAX_LEVEL 0xFF | ||
| 2119 | 2122 | ||
| 2120 | /* | 2123 | static struct backlight_properties aty_bl_data; |
| 2121 | * LCD backlight control | ||
| 2122 | */ | ||
| 2123 | 2124 | ||
| 2124 | static int backlight_conv[] = { | 2125 | static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) |
| 2125 | 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d, | 2126 | { |
| 2126 | 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff | 2127 | struct fb_info *info = pci_get_drvdata(par->pdev); |
| 2127 | }; | 2128 | int atylevel; |
| 2129 | |||
| 2130 | /* Get and convert the value */ | ||
| 2131 | mutex_lock(&info->bl_mutex); | ||
| 2132 | atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; | ||
| 2133 | mutex_unlock(&info->bl_mutex); | ||
| 2134 | |||
| 2135 | if (atylevel < 0) | ||
| 2136 | atylevel = 0; | ||
| 2137 | else if (atylevel > MAX_LEVEL) | ||
| 2138 | atylevel = MAX_LEVEL; | ||
| 2128 | 2139 | ||
| 2129 | static int aty_set_backlight_enable(int on, int level, void *data) | 2140 | return atylevel; |
| 2141 | } | ||
| 2142 | |||
| 2143 | static int aty_bl_update_status(struct backlight_device *bd) | ||
| 2130 | { | 2144 | { |
| 2131 | struct fb_info *info = (struct fb_info *) data; | 2145 | struct atyfb_par *par = class_get_devdata(&bd->class_dev); |
| 2132 | struct atyfb_par *par = (struct atyfb_par *) info->par; | ||
| 2133 | unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); | 2146 | unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); |
| 2147 | int level; | ||
| 2148 | |||
| 2149 | if (bd->props->power != FB_BLANK_UNBLANK || | ||
| 2150 | bd->props->fb_blank != FB_BLANK_UNBLANK) | ||
| 2151 | level = 0; | ||
| 2152 | else | ||
| 2153 | level = bd->props->brightness; | ||
| 2134 | 2154 | ||
| 2135 | reg |= (BLMOD_EN | BIASMOD_EN); | 2155 | reg |= (BLMOD_EN | BIASMOD_EN); |
| 2136 | if (on && level > BACKLIGHT_OFF) { | 2156 | if (level > 0) { |
| 2137 | reg &= ~BIAS_MOD_LEVEL_MASK; | 2157 | reg &= ~BIAS_MOD_LEVEL_MASK; |
| 2138 | reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT); | 2158 | reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT); |
| 2139 | } else { | 2159 | } else { |
| 2140 | reg &= ~BIAS_MOD_LEVEL_MASK; | 2160 | reg &= ~BIAS_MOD_LEVEL_MASK; |
| 2141 | reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT); | 2161 | reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT); |
| 2142 | } | 2162 | } |
| 2143 | aty_st_lcd(LCD_MISC_CNTL, reg, par); | 2163 | aty_st_lcd(LCD_MISC_CNTL, reg, par); |
| 2164 | |||
| 2144 | return 0; | 2165 | return 0; |
| 2145 | } | 2166 | } |
| 2146 | 2167 | ||
| 2147 | static int aty_set_backlight_level(int level, void *data) | 2168 | static int aty_bl_get_brightness(struct backlight_device *bd) |
| 2148 | { | 2169 | { |
| 2149 | return aty_set_backlight_enable(1, level, data); | 2170 | return bd->props->brightness; |
| 2150 | } | 2171 | } |
| 2151 | 2172 | ||
| 2152 | static struct backlight_controller aty_backlight_controller = { | 2173 | static struct backlight_properties aty_bl_data = { |
| 2153 | aty_set_backlight_enable, | 2174 | .owner = THIS_MODULE, |
| 2154 | aty_set_backlight_level | 2175 | .get_brightness = aty_bl_get_brightness, |
| 2176 | .update_status = aty_bl_update_status, | ||
| 2177 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | ||
| 2155 | }; | 2178 | }; |
| 2156 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 2179 | |
| 2180 | static void aty_bl_init(struct atyfb_par *par) | ||
| 2181 | { | ||
| 2182 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 2183 | struct backlight_device *bd; | ||
| 2184 | char name[12]; | ||
| 2185 | |||
| 2186 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 2187 | if (!pmac_has_backlight_type("ati")) | ||
| 2188 | return; | ||
| 2189 | #endif | ||
| 2190 | |||
| 2191 | snprintf(name, sizeof(name), "atybl%d", info->node); | ||
| 2192 | |||
| 2193 | bd = backlight_device_register(name, par, &aty_bl_data); | ||
| 2194 | if (IS_ERR(bd)) { | ||
| 2195 | info->bl_dev = NULL; | ||
| 2196 | printk("aty: Backlight registration failed\n"); | ||
| 2197 | goto error; | ||
| 2198 | } | ||
| 2199 | |||
| 2200 | mutex_lock(&info->bl_mutex); | ||
| 2201 | info->bl_dev = bd; | ||
| 2202 | fb_bl_default_curve(info, 0, | ||
| 2203 | 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, | ||
| 2204 | 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); | ||
| 2205 | mutex_unlock(&info->bl_mutex); | ||
| 2206 | |||
| 2207 | up(&bd->sem); | ||
| 2208 | bd->props->brightness = aty_bl_data.max_brightness; | ||
| 2209 | bd->props->power = FB_BLANK_UNBLANK; | ||
| 2210 | bd->props->update_status(bd); | ||
| 2211 | down(&bd->sem); | ||
| 2212 | |||
| 2213 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 2214 | mutex_lock(&pmac_backlight_mutex); | ||
| 2215 | if (!pmac_backlight) | ||
| 2216 | pmac_backlight = bd; | ||
| 2217 | mutex_unlock(&pmac_backlight_mutex); | ||
| 2218 | #endif | ||
| 2219 | |||
| 2220 | printk("aty: Backlight initialized (%s)\n", name); | ||
| 2221 | |||
| 2222 | return; | ||
| 2223 | |||
| 2224 | error: | ||
| 2225 | return; | ||
| 2226 | } | ||
| 2227 | |||
| 2228 | static void aty_bl_exit(struct atyfb_par *par) | ||
| 2229 | { | ||
| 2230 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 2231 | |||
| 2232 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 2233 | mutex_lock(&pmac_backlight_mutex); | ||
| 2234 | #endif | ||
| 2235 | |||
| 2236 | mutex_lock(&info->bl_mutex); | ||
| 2237 | if (info->bl_dev) { | ||
| 2238 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 2239 | if (pmac_backlight == info->bl_dev) | ||
| 2240 | pmac_backlight = NULL; | ||
| 2241 | #endif | ||
| 2242 | |||
| 2243 | backlight_device_unregister(info->bl_dev); | ||
| 2244 | |||
| 2245 | printk("aty: Backlight unloaded\n"); | ||
| 2246 | } | ||
| 2247 | mutex_unlock(&info->bl_mutex); | ||
| 2248 | |||
| 2249 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 2250 | mutex_unlock(&pmac_backlight_mutex); | ||
| 2251 | #endif | ||
| 2252 | } | ||
| 2253 | |||
| 2254 | #endif /* CONFIG_FB_ATY_BACKLIGHT */ | ||
| 2157 | 2255 | ||
| 2158 | static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) | 2256 | static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) |
| 2159 | { | 2257 | { |
| @@ -2513,9 +2611,13 @@ static int __init aty_init(struct fb_info *info, const char *name) | |||
| 2513 | /* these bits let the 101 powerbook wake up from sleep -- paulus */ | 2611 | /* these bits let the 101 powerbook wake up from sleep -- paulus */ |
| 2514 | aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) | 2612 | aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) |
| 2515 | | (USE_F32KHZ | TRISTATE_MEM_EN), par); | 2613 | | (USE_F32KHZ | TRISTATE_MEM_EN), par); |
| 2516 | } else if (M64_HAS(MOBIL_BUS)) | 2614 | } else |
| 2517 | register_backlight_controller(&aty_backlight_controller, info, "ati"); | 2615 | #endif |
| 2518 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 2616 | if (M64_HAS(MOBIL_BUS)) { |
| 2617 | #ifdef CONFIG_FB_ATY_BACKLIGHT | ||
| 2618 | aty_bl_init (par); | ||
| 2619 | #endif | ||
| 2620 | } | ||
| 2519 | 2621 | ||
| 2520 | memset(&var, 0, sizeof(var)); | 2622 | memset(&var, 0, sizeof(var)); |
| 2521 | #ifdef CONFIG_PPC | 2623 | #ifdef CONFIG_PPC |
| @@ -2674,8 +2776,16 @@ static int atyfb_blank(int blank, struct fb_info *info) | |||
| 2674 | return 0; | 2776 | return 0; |
| 2675 | 2777 | ||
| 2676 | #ifdef CONFIG_PMAC_BACKLIGHT | 2778 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 2677 | if (machine_is(powermac) && blank > FB_BLANK_NORMAL) | 2779 | if (machine_is(powermac) && blank > FB_BLANK_NORMAL) { |
| 2678 | set_backlight_enable(0); | 2780 | mutex_lock(&info->bl_mutex); |
| 2781 | if (info->bl_dev) { | ||
| 2782 | down(&info->bl_dev->sem); | ||
| 2783 | info->bl_dev->props->power = FB_BLANK_POWERDOWN; | ||
| 2784 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 2785 | up(&info->bl_dev->sem); | ||
| 2786 | } | ||
| 2787 | mutex_unlock(&info->bl_mutex); | ||
| 2788 | } | ||
| 2679 | #elif defined(CONFIG_FB_ATY_GENERIC_LCD) | 2789 | #elif defined(CONFIG_FB_ATY_GENERIC_LCD) |
| 2680 | if (par->lcd_table && blank > FB_BLANK_NORMAL && | 2790 | if (par->lcd_table && blank > FB_BLANK_NORMAL && |
| 2681 | (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { | 2791 | (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { |
| @@ -2706,8 +2816,16 @@ static int atyfb_blank(int blank, struct fb_info *info) | |||
| 2706 | aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); | 2816 | aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); |
| 2707 | 2817 | ||
| 2708 | #ifdef CONFIG_PMAC_BACKLIGHT | 2818 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 2709 | if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) | 2819 | if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) { |
| 2710 | set_backlight_enable(1); | 2820 | mutex_lock(&info->bl_mutex); |
| 2821 | if (info->bl_dev) { | ||
| 2822 | down(&info->bl_dev->sem); | ||
| 2823 | info->bl_dev->props->power = FB_BLANK_UNBLANK; | ||
| 2824 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 2825 | up(&info->bl_dev->sem); | ||
| 2826 | } | ||
| 2827 | mutex_unlock(&info->bl_mutex); | ||
| 2828 | } | ||
| 2711 | #elif defined(CONFIG_FB_ATY_GENERIC_LCD) | 2829 | #elif defined(CONFIG_FB_ATY_GENERIC_LCD) |
| 2712 | if (par->lcd_table && blank <= FB_BLANK_NORMAL && | 2830 | if (par->lcd_table && blank <= FB_BLANK_NORMAL && |
| 2713 | (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { | 2831 | (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { |
| @@ -3440,6 +3558,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
| 3440 | par->res_start = res_start; | 3558 | par->res_start = res_start; |
| 3441 | par->res_size = res_size; | 3559 | par->res_size = res_size; |
| 3442 | par->irq = pdev->irq; | 3560 | par->irq = pdev->irq; |
| 3561 | par->pdev = pdev; | ||
| 3443 | 3562 | ||
| 3444 | /* Setup "info" structure */ | 3563 | /* Setup "info" structure */ |
| 3445 | #ifdef __sparc__ | 3564 | #ifdef __sparc__ |
| @@ -3571,6 +3690,11 @@ static void __devexit atyfb_remove(struct fb_info *info) | |||
| 3571 | aty_set_crtc(par, &saved_crtc); | 3690 | aty_set_crtc(par, &saved_crtc); |
| 3572 | par->pll_ops->set_pll(info, &saved_pll); | 3691 | par->pll_ops->set_pll(info, &saved_pll); |
| 3573 | 3692 | ||
| 3693 | #ifdef CONFIG_FB_ATY_BACKLIGHT | ||
| 3694 | if (M64_HAS(MOBIL_BUS)) | ||
| 3695 | aty_bl_exit(par); | ||
| 3696 | #endif | ||
| 3697 | |||
| 3574 | unregister_framebuffer(info); | 3698 | unregister_framebuffer(info); |
| 3575 | 3699 | ||
| 3576 | #ifdef CONFIG_MTRR | 3700 | #ifdef CONFIG_MTRR |
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c new file mode 100644 index 000000000000..7de66b855d4e --- /dev/null +++ b/drivers/video/aty/radeon_backlight.c | |||
| @@ -0,0 +1,247 @@ | |||
| 1 | /* | ||
| 2 | * Backlight code for ATI Radeon based graphic cards | ||
| 3 | * | ||
| 4 | * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org> | ||
| 5 | * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
| 6 | * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "radeonfb.h" | ||
| 14 | #include <linux/backlight.h> | ||
| 15 | |||
| 16 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 17 | #include <asm/backlight.h> | ||
| 18 | #endif | ||
| 19 | |||
| 20 | #define MAX_RADEON_LEVEL 0xFF | ||
| 21 | |||
| 22 | static struct backlight_properties radeon_bl_data; | ||
| 23 | |||
| 24 | struct radeon_bl_privdata { | ||
| 25 | struct radeonfb_info *rinfo; | ||
| 26 | uint8_t negative; | ||
| 27 | }; | ||
| 28 | |||
| 29 | static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata, | ||
| 30 | int level) | ||
| 31 | { | ||
| 32 | struct fb_info *info = pdata->rinfo->info; | ||
| 33 | int rlevel; | ||
| 34 | |||
| 35 | mutex_lock(&info->bl_mutex); | ||
| 36 | |||
| 37 | /* Get and convert the value */ | ||
| 38 | rlevel = pdata->rinfo->info->bl_curve[level] * | ||
| 39 | FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL; | ||
| 40 | |||
| 41 | mutex_unlock(&info->bl_mutex); | ||
| 42 | |||
| 43 | if (pdata->negative) | ||
| 44 | rlevel = MAX_RADEON_LEVEL - rlevel; | ||
| 45 | |||
| 46 | if (rlevel < 0) | ||
| 47 | rlevel = 0; | ||
| 48 | else if (rlevel > MAX_RADEON_LEVEL) | ||
| 49 | rlevel = MAX_RADEON_LEVEL; | ||
| 50 | |||
| 51 | return rlevel; | ||
| 52 | } | ||
| 53 | |||
| 54 | static int radeon_bl_update_status(struct backlight_device *bd) | ||
| 55 | { | ||
| 56 | struct radeon_bl_privdata *pdata = class_get_devdata(&bd->class_dev); | ||
| 57 | struct radeonfb_info *rinfo = pdata->rinfo; | ||
| 58 | u32 lvds_gen_cntl, tmpPixclksCntl; | ||
| 59 | int level; | ||
| 60 | |||
| 61 | if (rinfo->mon1_type != MT_LCD) | ||
| 62 | return 0; | ||
| 63 | |||
| 64 | /* We turn off the LCD completely instead of just dimming the | ||
| 65 | * backlight. This provides some greater power saving and the display | ||
| 66 | * is useless without backlight anyway. | ||
| 67 | */ | ||
| 68 | if (bd->props->power != FB_BLANK_UNBLANK || | ||
| 69 | bd->props->fb_blank != FB_BLANK_UNBLANK) | ||
| 70 | level = 0; | ||
| 71 | else | ||
| 72 | level = bd->props->brightness; | ||
| 73 | |||
| 74 | del_timer_sync(&rinfo->lvds_timer); | ||
| 75 | radeon_engine_idle(); | ||
| 76 | |||
| 77 | lvds_gen_cntl = INREG(LVDS_GEN_CNTL); | ||
| 78 | if (level > 0) { | ||
| 79 | lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; | ||
| 80 | if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { | ||
| 81 | lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); | ||
| 82 | lvds_gen_cntl |= LVDS_BLON | LVDS_EN; | ||
| 83 | OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 84 | lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; | ||
| 85 | lvds_gen_cntl |= | ||
| 86 | (radeon_bl_get_level_brightness(pdata, level) << | ||
| 87 | LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 88 | lvds_gen_cntl |= LVDS_ON; | ||
| 89 | lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); | ||
| 90 | rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; | ||
| 91 | mod_timer(&rinfo->lvds_timer, | ||
| 92 | jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); | ||
| 93 | } else { | ||
| 94 | lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; | ||
| 95 | lvds_gen_cntl |= | ||
| 96 | (radeon_bl_get_level_brightness(pdata, level) << | ||
| 97 | LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 98 | OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 99 | } | ||
| 100 | rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; | ||
| 101 | rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl | ||
| 102 | & LVDS_STATE_MASK; | ||
| 103 | } else { | ||
| 104 | /* Asic bug, when turning off LVDS_ON, we have to make sure | ||
| 105 | RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off | ||
| 106 | */ | ||
| 107 | tmpPixclksCntl = INPLL(PIXCLKS_CNTL); | ||
| 108 | if (rinfo->is_mobility || rinfo->is_IGP) | ||
| 109 | OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); | ||
| 110 | lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); | ||
| 111 | lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) << | ||
| 112 | LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 113 | lvds_gen_cntl |= LVDS_DISPLAY_DIS; | ||
| 114 | OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 115 | udelay(100); | ||
| 116 | lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); | ||
| 117 | OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 118 | lvds_gen_cntl &= ~(LVDS_DIGON); | ||
| 119 | rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; | ||
| 120 | mod_timer(&rinfo->lvds_timer, | ||
| 121 | jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); | ||
| 122 | if (rinfo->is_mobility || rinfo->is_IGP) | ||
| 123 | OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); | ||
| 124 | } | ||
| 125 | rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; | ||
| 126 | rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int radeon_bl_get_brightness(struct backlight_device *bd) | ||
| 132 | { | ||
| 133 | return bd->props->brightness; | ||
| 134 | } | ||
| 135 | |||
| 136 | static struct backlight_properties radeon_bl_data = { | ||
| 137 | .owner = THIS_MODULE, | ||
| 138 | .get_brightness = radeon_bl_get_brightness, | ||
| 139 | .update_status = radeon_bl_update_status, | ||
| 140 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | ||
| 141 | }; | ||
| 142 | |||
| 143 | void radeonfb_bl_init(struct radeonfb_info *rinfo) | ||
| 144 | { | ||
| 145 | struct backlight_device *bd; | ||
| 146 | struct radeon_bl_privdata *pdata; | ||
| 147 | char name[12]; | ||
| 148 | |||
| 149 | if (rinfo->mon1_type != MT_LCD) | ||
| 150 | return; | ||
| 151 | |||
| 152 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 153 | if (!pmac_has_backlight_type("ati") && | ||
| 154 | !pmac_has_backlight_type("mnca")) | ||
| 155 | return; | ||
| 156 | #endif | ||
| 157 | |||
| 158 | pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL); | ||
| 159 | if (!pdata) { | ||
| 160 | printk("radeonfb: Memory allocation failed\n"); | ||
| 161 | goto error; | ||
| 162 | } | ||
| 163 | |||
| 164 | snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node); | ||
| 165 | |||
| 166 | bd = backlight_device_register(name, pdata, &radeon_bl_data); | ||
| 167 | if (IS_ERR(bd)) { | ||
| 168 | rinfo->info->bl_dev = NULL; | ||
| 169 | printk("radeonfb: Backlight registration failed\n"); | ||
| 170 | goto error; | ||
| 171 | } | ||
| 172 | |||
| 173 | pdata->rinfo = rinfo; | ||
| 174 | |||
| 175 | /* Pardon me for that hack... maybe some day we can figure out in what | ||
| 176 | * direction backlight should work on a given panel? | ||
| 177 | */ | ||
| 178 | pdata->negative = | ||
| 179 | (rinfo->family != CHIP_FAMILY_RV200 && | ||
| 180 | rinfo->family != CHIP_FAMILY_RV250 && | ||
| 181 | rinfo->family != CHIP_FAMILY_RV280 && | ||
| 182 | rinfo->family != CHIP_FAMILY_RV350); | ||
| 183 | |||
| 184 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 185 | pdata->negative = pdata->negative || | ||
| 186 | machine_is_compatible("PowerBook4,3") || | ||
| 187 | machine_is_compatible("PowerBook6,3") || | ||
| 188 | machine_is_compatible("PowerBook6,5"); | ||
| 189 | #endif | ||
| 190 | |||
| 191 | mutex_lock(&rinfo->info->bl_mutex); | ||
| 192 | rinfo->info->bl_dev = bd; | ||
| 193 | fb_bl_default_curve(rinfo->info, 0, | ||
| 194 | 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL, | ||
| 195 | 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); | ||
| 196 | mutex_unlock(&rinfo->info->bl_mutex); | ||
| 197 | |||
| 198 | up(&bd->sem); | ||
| 199 | bd->props->brightness = radeon_bl_data.max_brightness; | ||
| 200 | bd->props->power = FB_BLANK_UNBLANK; | ||
| 201 | bd->props->update_status(bd); | ||
| 202 | down(&bd->sem); | ||
| 203 | |||
| 204 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 205 | mutex_lock(&pmac_backlight_mutex); | ||
| 206 | if (!pmac_backlight) | ||
| 207 | pmac_backlight = bd; | ||
| 208 | mutex_unlock(&pmac_backlight_mutex); | ||
| 209 | #endif | ||
| 210 | |||
| 211 | printk("radeonfb: Backlight initialized (%s)\n", name); | ||
| 212 | |||
| 213 | return; | ||
| 214 | |||
| 215 | error: | ||
| 216 | kfree(pdata); | ||
| 217 | return; | ||
| 218 | } | ||
| 219 | |||
| 220 | void radeonfb_bl_exit(struct radeonfb_info *rinfo) | ||
| 221 | { | ||
| 222 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 223 | mutex_lock(&pmac_backlight_mutex); | ||
| 224 | #endif | ||
| 225 | |||
| 226 | mutex_lock(&rinfo->info->bl_mutex); | ||
| 227 | if (rinfo->info->bl_dev) { | ||
| 228 | struct radeon_bl_privdata *pdata; | ||
| 229 | |||
| 230 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 231 | if (pmac_backlight == rinfo->info->bl_dev) | ||
| 232 | pmac_backlight = NULL; | ||
| 233 | #endif | ||
| 234 | |||
| 235 | pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev); | ||
| 236 | backlight_device_unregister(rinfo->info->bl_dev); | ||
| 237 | kfree(pdata); | ||
| 238 | rinfo->info->bl_dev = NULL; | ||
| 239 | |||
| 240 | printk("radeonfb: Backlight unloaded\n"); | ||
| 241 | } | ||
| 242 | mutex_unlock(&rinfo->info->bl_mutex); | ||
| 243 | |||
| 244 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 245 | mutex_unlock(&pmac_backlight_mutex); | ||
| 246 | #endif | ||
| 247 | } | ||
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 387a18a47ac2..c5ecbb02e01d 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
| @@ -78,10 +78,6 @@ | |||
| 78 | #include <asm/pci-bridge.h> | 78 | #include <asm/pci-bridge.h> |
| 79 | #include "../macmodes.h" | 79 | #include "../macmodes.h" |
| 80 | 80 | ||
| 81 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 82 | #include <asm/backlight.h> | ||
| 83 | #endif | ||
| 84 | |||
| 85 | #ifdef CONFIG_BOOTX_TEXT | 81 | #ifdef CONFIG_BOOTX_TEXT |
| 86 | #include <asm/btext.h> | 82 | #include <asm/btext.h> |
| 87 | #endif | 83 | #endif |
| @@ -277,20 +273,6 @@ static int nomtrr = 0; | |||
| 277 | * prototypes | 273 | * prototypes |
| 278 | */ | 274 | */ |
| 279 | 275 | ||
| 280 | |||
| 281 | #ifdef CONFIG_PPC_OF | ||
| 282 | |||
| 283 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 284 | static int radeon_set_backlight_enable(int on, int level, void *data); | ||
| 285 | static int radeon_set_backlight_level(int level, void *data); | ||
| 286 | static struct backlight_controller radeon_backlight_controller = { | ||
| 287 | radeon_set_backlight_enable, | ||
| 288 | radeon_set_backlight_level | ||
| 289 | }; | ||
| 290 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 291 | |||
| 292 | #endif /* CONFIG_PPC_OF */ | ||
| 293 | |||
| 294 | static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) | 276 | static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) |
| 295 | { | 277 | { |
| 296 | if (!rinfo->bios_seg) | 278 | if (!rinfo->bios_seg) |
| @@ -1913,116 +1895,6 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) | |||
| 1913 | return 0; | 1895 | return 0; |
| 1914 | } | 1896 | } |
| 1915 | 1897 | ||
| 1916 | |||
| 1917 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 1918 | |||
| 1919 | /* TODO: Dbl check these tables, we don't go up to full ON backlight | ||
| 1920 | * in these, possibly because we noticed MacOS doesn't, but I'd prefer | ||
| 1921 | * having some more official numbers from ATI | ||
| 1922 | */ | ||
| 1923 | static int backlight_conv_m6[] = { | ||
| 1924 | 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, | ||
| 1925 | 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 | ||
| 1926 | }; | ||
| 1927 | static int backlight_conv_m7[] = { | ||
| 1928 | 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81, | ||
| 1929 | 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9 | ||
| 1930 | }; | ||
| 1931 | |||
| 1932 | #define BACKLIGHT_LVDS_OFF | ||
| 1933 | #undef BACKLIGHT_DAC_OFF | ||
| 1934 | |||
| 1935 | /* We turn off the LCD completely instead of just dimming the backlight. | ||
| 1936 | * This provides some greater power saving and the display is useless | ||
| 1937 | * without backlight anyway. | ||
| 1938 | */ | ||
| 1939 | static int radeon_set_backlight_enable(int on, int level, void *data) | ||
| 1940 | { | ||
| 1941 | struct radeonfb_info *rinfo = (struct radeonfb_info *)data; | ||
| 1942 | u32 lvds_gen_cntl, tmpPixclksCntl; | ||
| 1943 | int* conv_table; | ||
| 1944 | |||
| 1945 | if (rinfo->mon1_type != MT_LCD) | ||
| 1946 | return 0; | ||
| 1947 | |||
| 1948 | /* Pardon me for that hack... maybe some day we can figure | ||
| 1949 | * out in what direction backlight should work on a given | ||
| 1950 | * panel ? | ||
| 1951 | */ | ||
| 1952 | if ((rinfo->family == CHIP_FAMILY_RV200 || | ||
| 1953 | rinfo->family == CHIP_FAMILY_RV250 || | ||
| 1954 | rinfo->family == CHIP_FAMILY_RV280 || | ||
| 1955 | rinfo->family == CHIP_FAMILY_RV350) && | ||
| 1956 | !machine_is_compatible("PowerBook4,3") && | ||
| 1957 | !machine_is_compatible("PowerBook6,3") && | ||
| 1958 | !machine_is_compatible("PowerBook6,5")) | ||
| 1959 | conv_table = backlight_conv_m7; | ||
| 1960 | else | ||
| 1961 | conv_table = backlight_conv_m6; | ||
| 1962 | |||
| 1963 | del_timer_sync(&rinfo->lvds_timer); | ||
| 1964 | radeon_engine_idle(); | ||
| 1965 | |||
| 1966 | lvds_gen_cntl = INREG(LVDS_GEN_CNTL); | ||
| 1967 | if (on && (level > BACKLIGHT_OFF)) { | ||
| 1968 | lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; | ||
| 1969 | if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { | ||
| 1970 | lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); | ||
| 1971 | lvds_gen_cntl |= LVDS_BLON | LVDS_EN; | ||
| 1972 | OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 1973 | lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; | ||
| 1974 | lvds_gen_cntl |= (conv_table[level] << | ||
| 1975 | LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 1976 | lvds_gen_cntl |= LVDS_ON; | ||
| 1977 | lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); | ||
| 1978 | rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; | ||
| 1979 | mod_timer(&rinfo->lvds_timer, | ||
| 1980 | jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); | ||
| 1981 | } else { | ||
| 1982 | lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; | ||
| 1983 | lvds_gen_cntl |= (conv_table[level] << | ||
| 1984 | LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 1985 | OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 1986 | } | ||
| 1987 | rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; | ||
| 1988 | rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl | ||
| 1989 | & LVDS_STATE_MASK; | ||
| 1990 | } else { | ||
| 1991 | /* Asic bug, when turning off LVDS_ON, we have to make sure | ||
| 1992 | RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off | ||
| 1993 | */ | ||
| 1994 | tmpPixclksCntl = INPLL(PIXCLKS_CNTL); | ||
| 1995 | if (rinfo->is_mobility || rinfo->is_IGP) | ||
| 1996 | OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); | ||
| 1997 | lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); | ||
| 1998 | lvds_gen_cntl |= (conv_table[0] << | ||
| 1999 | LVDS_BL_MOD_LEVEL_SHIFT); | ||
| 2000 | lvds_gen_cntl |= LVDS_DISPLAY_DIS; | ||
| 2001 | OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 2002 | udelay(100); | ||
| 2003 | lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); | ||
| 2004 | OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 2005 | lvds_gen_cntl &= ~(LVDS_DIGON); | ||
| 2006 | rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; | ||
| 2007 | mod_timer(&rinfo->lvds_timer, | ||
| 2008 | jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); | ||
| 2009 | if (rinfo->is_mobility || rinfo->is_IGP) | ||
| 2010 | OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); | ||
| 2011 | } | ||
| 2012 | rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; | ||
| 2013 | rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); | ||
| 2014 | |||
| 2015 | return 0; | ||
| 2016 | } | ||
| 2017 | |||
| 2018 | |||
| 2019 | static int radeon_set_backlight_level(int level, void *data) | ||
| 2020 | { | ||
| 2021 | return radeon_set_backlight_enable(1, level, data); | ||
| 2022 | } | ||
| 2023 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 2024 | |||
| 2025 | |||
| 2026 | /* | 1898 | /* |
| 2027 | * This reconfigure the card's internal memory map. In theory, we'd like | 1899 | * This reconfigure the card's internal memory map. In theory, we'd like |
| 2028 | * to setup the card's memory at the same address as it's PCI bus address, | 1900 | * to setup the card's memory at the same address as it's PCI bus address, |
| @@ -2477,14 +2349,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, | |||
| 2477 | MTRR_TYPE_WRCOMB, 1); | 2349 | MTRR_TYPE_WRCOMB, 1); |
| 2478 | #endif | 2350 | #endif |
| 2479 | 2351 | ||
| 2480 | #ifdef CONFIG_PMAC_BACKLIGHT | 2352 | radeonfb_bl_init(rinfo); |
| 2481 | if (rinfo->mon1_type == MT_LCD) { | ||
| 2482 | register_backlight_controller(&radeon_backlight_controller, | ||
| 2483 | rinfo, "ati"); | ||
| 2484 | register_backlight_controller(&radeon_backlight_controller, | ||
| 2485 | rinfo, "mnca"); | ||
| 2486 | } | ||
| 2487 | #endif | ||
| 2488 | 2353 | ||
| 2489 | printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); | 2354 | printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); |
| 2490 | 2355 | ||
| @@ -2528,7 +2393,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev) | |||
| 2528 | 2393 | ||
| 2529 | if (!rinfo) | 2394 | if (!rinfo) |
| 2530 | return; | 2395 | return; |
| 2531 | 2396 | ||
| 2397 | radeonfb_bl_exit(rinfo); | ||
| 2532 | radeonfb_pm_exit(rinfo); | 2398 | radeonfb_pm_exit(rinfo); |
| 2533 | 2399 | ||
| 2534 | if (rinfo->mon1_EDID) | 2400 | if (rinfo->mon1_EDID) |
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 217e00ab4a2d..1645943b1123 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h | |||
| @@ -625,4 +625,13 @@ extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_ | |||
| 625 | extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, | 625 | extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, |
| 626 | int reg_only); | 626 | int reg_only); |
| 627 | 627 | ||
| 628 | /* Backlight functions */ | ||
| 629 | #ifdef CONFIG_FB_RADEON_BACKLIGHT | ||
| 630 | extern void radeonfb_bl_init(struct radeonfb_info *rinfo); | ||
| 631 | extern void radeonfb_bl_exit(struct radeonfb_info *rinfo); | ||
| 632 | #else | ||
| 633 | static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {} | ||
| 634 | static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {} | ||
| 635 | #endif | ||
| 636 | |||
| 628 | #endif /* __RADEONFB_H__ */ | 637 | #endif /* __RADEONFB_H__ */ |
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 72ff6bf75e5e..d76bbfac92cc 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c | |||
| @@ -148,9 +148,24 @@ static int chipsfb_set_par(struct fb_info *info) | |||
| 148 | static int chipsfb_blank(int blank, struct fb_info *info) | 148 | static int chipsfb_blank(int blank, struct fb_info *info) |
| 149 | { | 149 | { |
| 150 | #ifdef CONFIG_PMAC_BACKLIGHT | 150 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 151 | // used to disable backlight only for blank > 1, but it seems | 151 | mutex_lock(&pmac_backlight_mutex); |
| 152 | // useful at blank = 1 too (saves battery, extends backlight life) | 152 | |
| 153 | set_backlight_enable(!blank); | 153 | if (pmac_backlight) { |
| 154 | down(&pmac_backlight->sem); | ||
| 155 | |||
| 156 | /* used to disable backlight only for blank > 1, but it seems | ||
| 157 | * useful at blank = 1 too (saves battery, extends backlight | ||
| 158 | * life) | ||
| 159 | */ | ||
| 160 | if (blank) | ||
| 161 | pmac_backlight->props->power = FB_BLANK_POWERDOWN; | ||
| 162 | else | ||
| 163 | pmac_backlight->props->power = FB_BLANK_UNBLANK; | ||
| 164 | pmac_backlight->props->update_status(pmac_backlight); | ||
| 165 | up(&pmac_backlight->sem); | ||
| 166 | } | ||
| 167 | |||
| 168 | mutex_unlock(&pmac_backlight_mutex); | ||
| 154 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 169 | #endif /* CONFIG_PMAC_BACKLIGHT */ |
| 155 | 170 | ||
| 156 | return 1; /* get fb_blank to set the colormap to all black */ | 171 | return 1; /* get fb_blank to set the colormap to all black */ |
| @@ -401,7 +416,14 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) | |||
| 401 | 416 | ||
| 402 | #ifdef CONFIG_PMAC_BACKLIGHT | 417 | #ifdef CONFIG_PMAC_BACKLIGHT |
| 403 | /* turn on the backlight */ | 418 | /* turn on the backlight */ |
| 404 | set_backlight_enable(1); | 419 | mutex_lock(&pmac_backlight_mutex); |
| 420 | if (pmac_backlight) { | ||
| 421 | down(&pmac_backlight->sem); | ||
| 422 | pmac_backlight->props->power = FB_BLANK_UNBLANK; | ||
| 423 | pmac_backlight->props->update_status(pmac_backlight); | ||
| 424 | up(&pmac_backlight->sem); | ||
| 425 | } | ||
| 426 | mutex_unlock(&pmac_backlight_mutex); | ||
| 405 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 427 | #endif /* CONFIG_PMAC_BACKLIGHT */ |
| 406 | 428 | ||
| 407 | #ifdef CONFIG_PPC | 429 | #ifdef CONFIG_PPC |
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 | ||
diff --git a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile index 690d37e8de5b..ca47432113e0 100644 --- a/drivers/video/nvidia/Makefile +++ b/drivers/video/nvidia/Makefile | |||
| @@ -7,6 +7,7 @@ obj-$(CONFIG_FB_NVIDIA) += nvidiafb.o | |||
| 7 | nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \ | 7 | nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \ |
| 8 | nv_accel.o | 8 | nv_accel.o |
| 9 | nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o | 9 | nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o |
| 10 | nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT) += nv_backlight.o | ||
| 10 | nvidiafb-$(CONFIG_PPC_OF) += nv_of.o | 11 | nvidiafb-$(CONFIG_PPC_OF) += nv_of.o |
| 11 | 12 | ||
| 12 | nvidiafb-objs := $(nvidiafb-y) \ No newline at end of file | 13 | nvidiafb-objs := $(nvidiafb-y) |
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c new file mode 100644 index 000000000000..1c1c10c699c5 --- /dev/null +++ b/drivers/video/nvidia/nv_backlight.c | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | /* | ||
| 2 | * Backlight code for nVidia based graphic cards | ||
| 3 | * | ||
| 4 | * Copyright 2004 Antonino Daplas <adaplas@pol.net> | ||
| 5 | * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/backlight.h> | ||
| 13 | #include <linux/fb.h> | ||
| 14 | #include <linux/pci.h> | ||
| 15 | #include "nv_local.h" | ||
| 16 | #include "nv_type.h" | ||
| 17 | #include "nv_proto.h" | ||
| 18 | |||
| 19 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 20 | #include <asm/backlight.h> | ||
| 21 | #include <asm/machdep.h> | ||
| 22 | #endif | ||
| 23 | |||
| 24 | /* We do not have any information about which values are allowed, thus | ||
| 25 | * we used safe values. | ||
| 26 | */ | ||
| 27 | #define MIN_LEVEL 0x158 | ||
| 28 | #define MAX_LEVEL 0x534 | ||
| 29 | |||
| 30 | static struct backlight_properties nvidia_bl_data; | ||
| 31 | |||
| 32 | static int nvidia_bl_get_level_brightness(struct nvidia_par *par, | ||
| 33 | int level) | ||
| 34 | { | ||
| 35 | struct fb_info *info = pci_get_drvdata(par->pci_dev); | ||
| 36 | int nlevel; | ||
| 37 | |||
| 38 | /* Get and convert the value */ | ||
| 39 | mutex_lock(&info->bl_mutex); | ||
| 40 | nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; | ||
| 41 | mutex_unlock(&info->bl_mutex); | ||
| 42 | |||
| 43 | if (nlevel < 0) | ||
| 44 | nlevel = 0; | ||
| 45 | else if (nlevel < MIN_LEVEL) | ||
| 46 | nlevel = MIN_LEVEL; | ||
| 47 | else if (nlevel > MAX_LEVEL) | ||
| 48 | nlevel = MAX_LEVEL; | ||
| 49 | |||
| 50 | return nlevel; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int nvidia_bl_update_status(struct backlight_device *bd) | ||
| 54 | { | ||
| 55 | struct nvidia_par *par = class_get_devdata(&bd->class_dev); | ||
| 56 | u32 tmp_pcrt, tmp_pmc, fpcontrol; | ||
| 57 | int level; | ||
| 58 | |||
| 59 | if (!par->FlatPanel) | ||
| 60 | return 0; | ||
| 61 | |||
| 62 | if (bd->props->power != FB_BLANK_UNBLANK || | ||
| 63 | bd->props->fb_blank != FB_BLANK_UNBLANK) | ||
| 64 | level = 0; | ||
| 65 | else | ||
| 66 | level = bd->props->brightness; | ||
| 67 | |||
| 68 | tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; | ||
| 69 | tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; | ||
| 70 | fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC; | ||
| 71 | |||
| 72 | if (level > 0) { | ||
| 73 | tmp_pcrt |= 0x1; | ||
| 74 | tmp_pmc |= (1 << 31); /* backlight bit */ | ||
| 75 | tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16; | ||
| 76 | fpcontrol |= par->fpSyncs; | ||
| 77 | } else | ||
| 78 | fpcontrol |= 0x20000022; | ||
| 79 | |||
| 80 | NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt); | ||
| 81 | NV_WR32(par->PMC, 0x10F0, tmp_pmc); | ||
| 82 | NV_WR32(par->PRAMDAC, 0x848, fpcontrol); | ||
| 83 | |||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int nvidia_bl_get_brightness(struct backlight_device *bd) | ||
| 88 | { | ||
| 89 | return bd->props->brightness; | ||
| 90 | } | ||
| 91 | |||
| 92 | static struct backlight_properties nvidia_bl_data = { | ||
| 93 | .owner = THIS_MODULE, | ||
| 94 | .get_brightness = nvidia_bl_get_brightness, | ||
| 95 | .update_status = nvidia_bl_update_status, | ||
| 96 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), | ||
| 97 | }; | ||
| 98 | |||
| 99 | void nvidia_bl_init(struct nvidia_par *par) | ||
| 100 | { | ||
| 101 | struct fb_info *info = pci_get_drvdata(par->pci_dev); | ||
| 102 | struct backlight_device *bd; | ||
| 103 | char name[12]; | ||
| 104 | |||
| 105 | if (!par->FlatPanel) | ||
| 106 | return; | ||
| 107 | |||
| 108 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 109 | if (!machine_is(powermac) || | ||
| 110 | !pmac_has_backlight_type("mnca")) | ||
| 111 | return; | ||
| 112 | #endif | ||
| 113 | |||
| 114 | snprintf(name, sizeof(name), "nvidiabl%d", info->node); | ||
| 115 | |||
| 116 | bd = backlight_device_register(name, par, &nvidia_bl_data); | ||
| 117 | if (IS_ERR(bd)) { | ||
| 118 | info->bl_dev = NULL; | ||
| 119 | printk("nvidia: Backlight registration failed\n"); | ||
| 120 | goto error; | ||
| 121 | } | ||
| 122 | |||
| 123 | mutex_lock(&info->bl_mutex); | ||
| 124 | info->bl_dev = bd; | ||
| 125 | fb_bl_default_curve(info, 0, | ||
| 126 | 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, | ||
| 127 | 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); | ||
| 128 | mutex_unlock(&info->bl_mutex); | ||
| 129 | |||
| 130 | up(&bd->sem); | ||
| 131 | bd->props->brightness = nvidia_bl_data.max_brightness; | ||
| 132 | bd->props->power = FB_BLANK_UNBLANK; | ||
| 133 | bd->props->update_status(bd); | ||
| 134 | down(&bd->sem); | ||
| 135 | |||
| 136 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 137 | mutex_lock(&pmac_backlight_mutex); | ||
| 138 | if (!pmac_backlight) | ||
| 139 | pmac_backlight = bd; | ||
| 140 | mutex_unlock(&pmac_backlight_mutex); | ||
| 141 | #endif | ||
| 142 | |||
| 143 | printk("nvidia: Backlight initialized (%s)\n", name); | ||
| 144 | |||
| 145 | return; | ||
| 146 | |||
| 147 | error: | ||
| 148 | return; | ||
| 149 | } | ||
| 150 | |||
| 151 | void nvidia_bl_exit(struct nvidia_par *par) | ||
| 152 | { | ||
| 153 | struct fb_info *info = pci_get_drvdata(par->pci_dev); | ||
| 154 | |||
| 155 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 156 | mutex_lock(&pmac_backlight_mutex); | ||
| 157 | #endif | ||
| 158 | |||
| 159 | mutex_lock(&info->bl_mutex); | ||
| 160 | if (info->bl_dev) { | ||
| 161 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 162 | if (pmac_backlight == info->bl_dev) | ||
| 163 | pmac_backlight = NULL; | ||
| 164 | #endif | ||
| 165 | |||
| 166 | backlight_device_unregister(info->bl_dev); | ||
| 167 | |||
| 168 | printk("nvidia: Backlight unloaded\n"); | ||
| 169 | } | ||
| 170 | mutex_unlock(&info->bl_mutex); | ||
| 171 | |||
| 172 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 173 | mutex_unlock(&pmac_backlight_mutex); | ||
| 174 | #endif | ||
| 175 | } | ||
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index b149a690ee0f..6fba656cd56b 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h | |||
| @@ -63,4 +63,14 @@ extern void nvidiafb_imageblit(struct fb_info *info, | |||
| 63 | const struct fb_image *image); | 63 | const struct fb_image *image); |
| 64 | extern int nvidiafb_sync(struct fb_info *info); | 64 | extern int nvidiafb_sync(struct fb_info *info); |
| 65 | extern u8 byte_rev[256]; | 65 | extern u8 byte_rev[256]; |
| 66 | |||
| 67 | /* in nv_backlight.h */ | ||
| 68 | #ifdef CONFIG_FB_NVIDIA_BACKLIGHT | ||
| 69 | extern void nvidia_bl_init(struct nvidia_par *par); | ||
| 70 | extern void nvidia_bl_exit(struct nvidia_par *par); | ||
| 71 | #else | ||
| 72 | static inline void nvidia_bl_init(struct nvidia_par *par) {} | ||
| 73 | static inline void nvidia_bl_exit(struct nvidia_par *par) {} | ||
| 74 | #endif | ||
| 75 | |||
| 66 | #endif /* __NV_PROTO_H__ */ | 76 | #endif /* __NV_PROTO_H__ */ |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 093ab9977c7c..03a7c1e9ce38 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| 24 | #include <linux/console.h> | 24 | #include <linux/console.h> |
| 25 | #include <linux/backlight.h> | ||
| 25 | #ifdef CONFIG_MTRR | 26 | #ifdef CONFIG_MTRR |
| 26 | #include <asm/mtrr.h> | 27 | #include <asm/mtrr.h> |
| 27 | #endif | 28 | #endif |
| @@ -29,10 +30,6 @@ | |||
| 29 | #include <asm/prom.h> | 30 | #include <asm/prom.h> |
| 30 | #include <asm/pci-bridge.h> | 31 | #include <asm/pci-bridge.h> |
| 31 | #endif | 32 | #endif |
| 32 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 33 | #include <asm/machdep.h> | ||
| 34 | #include <asm/backlight.h> | ||
| 35 | #endif | ||
| 36 | 33 | ||
| 37 | #include "nv_local.h" | 34 | #include "nv_local.h" |
| 38 | #include "nv_type.h" | 35 | #include "nv_type.h" |
| @@ -470,75 +467,6 @@ static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = { | |||
| 470 | .vmode = FB_VMODE_NONINTERLACED | 467 | .vmode = FB_VMODE_NONINTERLACED |
| 471 | }; | 468 | }; |
| 472 | 469 | ||
| 473 | /* | ||
| 474 | * Backlight control | ||
| 475 | */ | ||
| 476 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 477 | |||
| 478 | static int nvidia_backlight_levels[] = { | ||
| 479 | 0x158, | ||
| 480 | 0x192, | ||
| 481 | 0x1c6, | ||
| 482 | 0x200, | ||
| 483 | 0x234, | ||
| 484 | 0x268, | ||
| 485 | 0x2a2, | ||
| 486 | 0x2d6, | ||
| 487 | 0x310, | ||
| 488 | 0x344, | ||
| 489 | 0x378, | ||
| 490 | 0x3b2, | ||
| 491 | 0x3e6, | ||
| 492 | 0x41a, | ||
| 493 | 0x454, | ||
| 494 | 0x534, | ||
| 495 | }; | ||
| 496 | |||
| 497 | /* ------------------------------------------------------------------------- * | ||
| 498 | * | ||
| 499 | * Backlight operations | ||
| 500 | * | ||
| 501 | * ------------------------------------------------------------------------- */ | ||
| 502 | |||
| 503 | static int nvidia_set_backlight_enable(int on, int level, void *data) | ||
| 504 | { | ||
| 505 | struct nvidia_par *par = data; | ||
| 506 | u32 tmp_pcrt, tmp_pmc, fpcontrol; | ||
| 507 | |||
| 508 | tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; | ||
| 509 | tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; | ||
| 510 | fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC; | ||
| 511 | |||
| 512 | if (on && (level > BACKLIGHT_OFF)) { | ||
| 513 | tmp_pcrt |= 0x1; | ||
| 514 | tmp_pmc |= (1 << 31); // backlight bit | ||
| 515 | tmp_pmc |= nvidia_backlight_levels[level - 1] << 16; | ||
| 516 | } | ||
| 517 | |||
| 518 | if (on) | ||
| 519 | fpcontrol |= par->fpSyncs; | ||
| 520 | else | ||
| 521 | fpcontrol |= 0x20000022; | ||
| 522 | |||
| 523 | NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt); | ||
| 524 | NV_WR32(par->PMC, 0x10F0, tmp_pmc); | ||
| 525 | NV_WR32(par->PRAMDAC, 0x848, fpcontrol); | ||
| 526 | |||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | static int nvidia_set_backlight_level(int level, void *data) | ||
| 531 | { | ||
| 532 | return nvidia_set_backlight_enable(1, level, data); | ||
| 533 | } | ||
| 534 | |||
| 535 | static struct backlight_controller nvidia_backlight_controller = { | ||
| 536 | nvidia_set_backlight_enable, | ||
| 537 | nvidia_set_backlight_level | ||
| 538 | }; | ||
| 539 | |||
| 540 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 541 | |||
| 542 | static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8, | 470 | static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8, |
| 543 | u16 bg, u16 fg, u32 w, u32 h) | 471 | u16 bg, u16 fg, u32 w, u32 h) |
| 544 | { | 472 | { |
| @@ -1355,10 +1283,15 @@ static int nvidiafb_blank(int blank, struct fb_info *info) | |||
| 1355 | NVWriteSeq(par, 0x01, tmp); | 1283 | NVWriteSeq(par, 0x01, tmp); |
| 1356 | NVWriteCrtc(par, 0x1a, vesa); | 1284 | NVWriteCrtc(par, 0x1a, vesa); |
| 1357 | 1285 | ||
| 1358 | #ifdef CONFIG_PMAC_BACKLIGHT | 1286 | #ifdef CONFIG_FB_NVIDIA_BACKLIGHT |
| 1359 | if (par->FlatPanel && machine_is(powermac)) { | 1287 | mutex_lock(&info->bl_mutex); |
| 1360 | set_backlight_enable(!blank); | 1288 | if (info->bl_dev) { |
| 1289 | down(&info->bl_dev->sem); | ||
| 1290 | info->bl_dev->props->power = blank; | ||
| 1291 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 1292 | up(&info->bl_dev->sem); | ||
| 1361 | } | 1293 | } |
| 1294 | mutex_unlock(&info->bl_mutex); | ||
| 1362 | #endif | 1295 | #endif |
| 1363 | 1296 | ||
| 1364 | NVTRACE_LEAVE(); | 1297 | NVTRACE_LEAVE(); |
| @@ -1741,11 +1674,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, | |||
| 1741 | "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n", | 1674 | "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n", |
| 1742 | info->fix.id, | 1675 | info->fix.id, |
| 1743 | par->FbMapSize / (1024 * 1024), info->fix.smem_start); | 1676 | par->FbMapSize / (1024 * 1024), info->fix.smem_start); |
| 1744 | #ifdef CONFIG_PMAC_BACKLIGHT | 1677 | |
| 1745 | if (par->FlatPanel && machine_is(powermac)) | 1678 | nvidia_bl_init(par); |
| 1746 | register_backlight_controller(&nvidia_backlight_controller, | 1679 | |
| 1747 | par, "mnca"); | ||
| 1748 | #endif | ||
| 1749 | NVTRACE_LEAVE(); | 1680 | NVTRACE_LEAVE(); |
| 1750 | return 0; | 1681 | return 0; |
| 1751 | 1682 | ||
| @@ -1775,6 +1706,8 @@ static void __exit nvidiafb_remove(struct pci_dev *pd) | |||
| 1775 | 1706 | ||
| 1776 | NVTRACE_ENTER(); | 1707 | NVTRACE_ENTER(); |
| 1777 | 1708 | ||
| 1709 | nvidia_bl_exit(par); | ||
| 1710 | |||
| 1778 | unregister_framebuffer(info); | 1711 | unregister_framebuffer(info); |
| 1779 | #ifdef CONFIG_MTRR | 1712 | #ifdef CONFIG_MTRR |
| 1780 | if (par->mtrr.vram_valid) | 1713 | if (par->mtrr.vram_valid) |
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 3e9308f0f165..d4384ab1df65 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/fb.h> | 41 | #include <linux/fb.h> |
| 42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
| 43 | #include <linux/pci.h> | 43 | #include <linux/pci.h> |
| 44 | #include <linux/backlight.h> | ||
| 44 | #ifdef CONFIG_MTRR | 45 | #ifdef CONFIG_MTRR |
| 45 | #include <asm/mtrr.h> | 46 | #include <asm/mtrr.h> |
| 46 | #endif | 47 | #endif |
| @@ -272,34 +273,154 @@ static const struct riva_regs reg_template = { | |||
| 272 | /* | 273 | /* |
| 273 | * Backlight control | 274 | * Backlight control |
| 274 | */ | 275 | */ |
| 275 | #ifdef CONFIG_PMAC_BACKLIGHT | 276 | #ifdef CONFIG_FB_RIVA_BACKLIGHT |
| 277 | /* We do not have any information about which values are allowed, thus | ||
| 278 | * we used safe values. | ||
| 279 | */ | ||
| 280 | #define MIN_LEVEL 0x158 | ||
| 281 | #define MAX_LEVEL 0x534 | ||
| 276 | 282 | ||
| 277 | static int riva_backlight_levels[] = { | 283 | static struct backlight_properties riva_bl_data; |
| 278 | 0x158, | 284 | |
| 279 | 0x192, | 285 | static int riva_bl_get_level_brightness(struct riva_par *par, |
| 280 | 0x1c6, | 286 | int level) |
| 281 | 0x200, | 287 | { |
| 282 | 0x234, | 288 | struct fb_info *info = pci_get_drvdata(par->pdev); |
| 283 | 0x268, | 289 | int nlevel; |
| 284 | 0x2a2, | 290 | |
| 285 | 0x2d6, | 291 | /* Get and convert the value */ |
| 286 | 0x310, | 292 | mutex_lock(&info->bl_mutex); |
| 287 | 0x344, | 293 | nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; |
| 288 | 0x378, | 294 | mutex_unlock(&info->bl_mutex); |
| 289 | 0x3b2, | 295 | |
| 290 | 0x3e6, | 296 | if (nlevel < 0) |
| 291 | 0x41a, | 297 | nlevel = 0; |
| 292 | 0x454, | 298 | else if (nlevel < MIN_LEVEL) |
| 293 | 0x534, | 299 | nlevel = MIN_LEVEL; |
| 294 | }; | 300 | else if (nlevel > MAX_LEVEL) |
| 301 | nlevel = MAX_LEVEL; | ||
| 302 | |||
| 303 | return nlevel; | ||
| 304 | } | ||
| 305 | |||
| 306 | static int riva_bl_update_status(struct backlight_device *bd) | ||
| 307 | { | ||
| 308 | struct riva_par *par = class_get_devdata(&bd->class_dev); | ||
| 309 | U032 tmp_pcrt, tmp_pmc; | ||
| 310 | int level; | ||
| 311 | |||
| 312 | if (bd->props->power != FB_BLANK_UNBLANK || | ||
| 313 | bd->props->fb_blank != FB_BLANK_UNBLANK) | ||
| 314 | level = 0; | ||
| 315 | else | ||
| 316 | level = bd->props->brightness; | ||
| 317 | |||
| 318 | tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; | ||
| 319 | tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC; | ||
| 320 | if(level > 0) { | ||
| 321 | tmp_pcrt |= 0x1; | ||
| 322 | tmp_pmc |= (1 << 31); /* backlight bit */ | ||
| 323 | tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */ | ||
| 324 | } | ||
| 325 | par->riva.PCRTC0[0x081C/4] = tmp_pcrt; | ||
| 326 | par->riva.PMC[0x10F0/4] = tmp_pmc; | ||
| 327 | |||
| 328 | return 0; | ||
| 329 | } | ||
| 330 | |||
| 331 | static int riva_bl_get_brightness(struct backlight_device *bd) | ||
| 332 | { | ||
| 333 | return bd->props->brightness; | ||
| 334 | } | ||
| 295 | 335 | ||
| 296 | static int riva_set_backlight_enable(int on, int level, void *data); | 336 | static struct backlight_properties riva_bl_data = { |
| 297 | static int riva_set_backlight_level(int level, void *data); | 337 | .owner = THIS_MODULE, |
| 298 | static struct backlight_controller riva_backlight_controller = { | 338 | .get_brightness = riva_bl_get_brightness, |
| 299 | riva_set_backlight_enable, | 339 | .update_status = riva_bl_update_status, |
| 300 | riva_set_backlight_level | 340 | .max_brightness = (FB_BACKLIGHT_LEVELS - 1), |
| 301 | }; | 341 | }; |
| 302 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 342 | |
| 343 | static void riva_bl_init(struct riva_par *par) | ||
| 344 | { | ||
| 345 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 346 | struct backlight_device *bd; | ||
| 347 | char name[12]; | ||
| 348 | |||
| 349 | if (!par->FlatPanel) | ||
| 350 | return; | ||
| 351 | |||
| 352 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 353 | if (!machine_is(powermac) || | ||
| 354 | !pmac_has_backlight_type("mnca")) | ||
| 355 | return; | ||
| 356 | #endif | ||
| 357 | |||
| 358 | snprintf(name, sizeof(name), "rivabl%d", info->node); | ||
| 359 | |||
| 360 | bd = backlight_device_register(name, par, &riva_bl_data); | ||
| 361 | if (IS_ERR(bd)) { | ||
| 362 | info->bl_dev = NULL; | ||
| 363 | printk("riva: Backlight registration failed\n"); | ||
| 364 | goto error; | ||
| 365 | } | ||
| 366 | |||
| 367 | mutex_lock(&info->bl_mutex); | ||
| 368 | info->bl_dev = bd; | ||
| 369 | fb_bl_default_curve(info, 0, | ||
| 370 | 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, | ||
| 371 | 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); | ||
| 372 | mutex_unlock(&info->bl_mutex); | ||
| 373 | |||
| 374 | up(&bd->sem); | ||
| 375 | bd->props->brightness = riva_bl_data.max_brightness; | ||
| 376 | bd->props->power = FB_BLANK_UNBLANK; | ||
| 377 | bd->props->update_status(bd); | ||
| 378 | down(&bd->sem); | ||
| 379 | |||
| 380 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 381 | mutex_lock(&pmac_backlight_mutex); | ||
| 382 | if (!pmac_backlight) | ||
| 383 | pmac_backlight = bd; | ||
| 384 | mutex_unlock(&pmac_backlight_mutex); | ||
| 385 | #endif | ||
| 386 | |||
| 387 | printk("riva: Backlight initialized (%s)\n", name); | ||
| 388 | |||
| 389 | return; | ||
| 390 | |||
| 391 | error: | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | |||
| 395 | static void riva_bl_exit(struct riva_par *par) | ||
| 396 | { | ||
| 397 | struct fb_info *info = pci_get_drvdata(par->pdev); | ||
| 398 | |||
| 399 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 400 | mutex_lock(&pmac_backlight_mutex); | ||
| 401 | #endif | ||
| 402 | |||
| 403 | mutex_lock(&info->bl_mutex); | ||
| 404 | if (info->bl_dev) { | ||
| 405 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 406 | if (pmac_backlight == info->bl_dev) | ||
| 407 | pmac_backlight = NULL; | ||
| 408 | #endif | ||
| 409 | |||
| 410 | backlight_device_unregister(info->bl_dev); | ||
| 411 | |||
| 412 | printk("riva: Backlight unloaded\n"); | ||
| 413 | } | ||
| 414 | mutex_unlock(&info->bl_mutex); | ||
| 415 | |||
| 416 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 417 | mutex_unlock(&pmac_backlight_mutex); | ||
| 418 | #endif | ||
| 419 | } | ||
| 420 | #else | ||
| 421 | static inline void riva_bl_init(struct riva_par *par) {} | ||
| 422 | static inline void riva_bl_exit(struct riva_par *par) {} | ||
| 423 | #endif /* CONFIG_FB_RIVA_BACKLIGHT */ | ||
| 303 | 424 | ||
| 304 | /* ------------------------------------------------------------------------- * | 425 | /* ------------------------------------------------------------------------- * |
| 305 | * | 426 | * |
| @@ -973,36 +1094,6 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var) | |||
| 973 | 1094 | ||
| 974 | /* ------------------------------------------------------------------------- * | 1095 | /* ------------------------------------------------------------------------- * |
| 975 | * | 1096 | * |
| 976 | * Backlight operations | ||
| 977 | * | ||
| 978 | * ------------------------------------------------------------------------- */ | ||
| 979 | |||
| 980 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 981 | static int riva_set_backlight_enable(int on, int level, void *data) | ||
| 982 | { | ||
| 983 | struct riva_par *par = data; | ||
| 984 | U032 tmp_pcrt, tmp_pmc; | ||
| 985 | |||
| 986 | tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; | ||
| 987 | tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC; | ||
| 988 | if(on && (level > BACKLIGHT_OFF)) { | ||
| 989 | tmp_pcrt |= 0x1; | ||
| 990 | tmp_pmc |= (1 << 31); // backlight bit | ||
| 991 | tmp_pmc |= riva_backlight_levels[level-1] << 16; // level | ||
| 992 | } | ||
| 993 | par->riva.PCRTC0[0x081C/4] = tmp_pcrt; | ||
| 994 | par->riva.PMC[0x10F0/4] = tmp_pmc; | ||
| 995 | return 0; | ||
| 996 | } | ||
| 997 | |||
| 998 | static int riva_set_backlight_level(int level, void *data) | ||
| 999 | { | ||
| 1000 | return riva_set_backlight_enable(1, level, data); | ||
| 1001 | } | ||
| 1002 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 1003 | |||
| 1004 | /* ------------------------------------------------------------------------- * | ||
| 1005 | * | ||
| 1006 | * framebuffer operations | 1097 | * framebuffer operations |
| 1007 | * | 1098 | * |
| 1008 | * ------------------------------------------------------------------------- */ | 1099 | * ------------------------------------------------------------------------- */ |
| @@ -1247,10 +1338,15 @@ static int rivafb_blank(int blank, struct fb_info *info) | |||
| 1247 | SEQout(par, 0x01, tmp); | 1338 | SEQout(par, 0x01, tmp); |
| 1248 | CRTCout(par, 0x1a, vesa); | 1339 | CRTCout(par, 0x1a, vesa); |
| 1249 | 1340 | ||
| 1250 | #ifdef CONFIG_PMAC_BACKLIGHT | 1341 | #ifdef CONFIG_FB_RIVA_BACKLIGHT |
| 1251 | if ( par->FlatPanel && machine_is(powermac)) { | 1342 | mutex_lock(&info->bl_mutex); |
| 1252 | set_backlight_enable(!blank); | 1343 | if (info->bl_dev) { |
| 1344 | down(&info->bl_dev->sem); | ||
| 1345 | info->bl_dev->props->power = blank; | ||
| 1346 | info->bl_dev->props->update_status(info->bl_dev); | ||
| 1347 | up(&info->bl_dev->sem); | ||
| 1253 | } | 1348 | } |
| 1349 | mutex_unlock(&info->bl_mutex); | ||
| 1254 | #endif | 1350 | #endif |
| 1255 | 1351 | ||
| 1256 | NVTRACE_LEAVE(); | 1352 | NVTRACE_LEAVE(); |
| @@ -2037,11 +2133,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd, | |||
| 2037 | RIVAFB_VERSION, | 2133 | RIVAFB_VERSION, |
| 2038 | info->fix.smem_len / (1024 * 1024), | 2134 | info->fix.smem_len / (1024 * 1024), |
| 2039 | info->fix.smem_start); | 2135 | info->fix.smem_start); |
| 2040 | #ifdef CONFIG_PMAC_BACKLIGHT | 2136 | |
| 2041 | if (default_par->FlatPanel && machine_is(powermac)) | 2137 | riva_bl_init(info->par); |
| 2042 | register_backlight_controller(&riva_backlight_controller, | 2138 | |
| 2043 | default_par, "mnca"); | ||
| 2044 | #endif | ||
| 2045 | NVTRACE_LEAVE(); | 2139 | NVTRACE_LEAVE(); |
| 2046 | return 0; | 2140 | return 0; |
| 2047 | 2141 | ||
| @@ -2074,6 +2168,8 @@ static void __exit rivafb_remove(struct pci_dev *pd) | |||
| 2074 | 2168 | ||
| 2075 | NVTRACE_ENTER(); | 2169 | NVTRACE_ENTER(); |
| 2076 | 2170 | ||
| 2171 | riva_bl_exit(par); | ||
| 2172 | |||
| 2077 | #ifdef CONFIG_FB_RIVA_I2C | 2173 | #ifdef CONFIG_FB_RIVA_I2C |
| 2078 | riva_delete_i2c_busses(par); | 2174 | riva_delete_i2c_busses(par); |
| 2079 | kfree(par->EDID); | 2175 | kfree(par->EDID); |
diff --git a/include/asm-powerpc/backlight.h b/include/asm-powerpc/backlight.h index 1ba1f27a0b63..a5e9e656e332 100644 --- a/include/asm-powerpc/backlight.h +++ b/include/asm-powerpc/backlight.h | |||
| @@ -2,30 +2,30 @@ | |||
| 2 | * Routines for handling backlight control on PowerBooks | 2 | * Routines for handling backlight control on PowerBooks |
| 3 | * | 3 | * |
| 4 | * For now, implementation resides in | 4 | * For now, implementation resides in |
| 5 | * arch/powerpc/platforms/powermac/pmac_support.c | 5 | * arch/powerpc/platforms/powermac/backlight.c |
| 6 | * | 6 | * |
| 7 | */ | 7 | */ |
| 8 | #ifndef __ASM_POWERPC_BACKLIGHT_H | 8 | #ifndef __ASM_POWERPC_BACKLIGHT_H |
| 9 | #define __ASM_POWERPC_BACKLIGHT_H | 9 | #define __ASM_POWERPC_BACKLIGHT_H |
| 10 | #ifdef __KERNEL__ | 10 | #ifdef __KERNEL__ |
| 11 | 11 | ||
| 12 | /* Abstract values */ | 12 | #include <linux/fb.h> |
| 13 | #define BACKLIGHT_OFF 0 | 13 | #include <linux/mutex.h> |
| 14 | #define BACKLIGHT_MIN 1 | ||
| 15 | #define BACKLIGHT_MAX 0xf | ||
| 16 | 14 | ||
| 17 | struct backlight_controller { | 15 | /* For locking instructions, see the implementation file */ |
| 18 | int (*set_enable)(int enable, int level, void *data); | 16 | extern struct backlight_device *pmac_backlight; |
| 19 | int (*set_level)(int level, void *data); | 17 | extern struct mutex pmac_backlight_mutex; |
| 20 | }; | ||
| 21 | 18 | ||
| 22 | extern void register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type); | 19 | extern void pmac_backlight_calc_curve(struct fb_info*); |
| 23 | extern void unregister_backlight_controller(struct backlight_controller *ctrler, void *data); | 20 | extern int pmac_backlight_curve_lookup(struct fb_info *info, int value); |
| 24 | 21 | ||
| 25 | extern int set_backlight_enable(int enable); | 22 | extern int pmac_has_backlight_type(const char *type); |
| 26 | extern int get_backlight_enable(void); | 23 | |
| 27 | extern int set_backlight_level(int level); | 24 | extern void pmac_backlight_key_up(void); |
| 28 | extern int get_backlight_level(void); | 25 | extern void pmac_backlight_key_down(void); |
| 26 | |||
| 27 | extern int pmac_backlight_set_legacy_brightness(int brightness); | ||
| 28 | extern int pmac_backlight_get_legacy_brightness(void); | ||
| 29 | 29 | ||
| 30 | #endif /* __KERNEL__ */ | 30 | #endif /* __KERNEL__ */ |
| 31 | #endif | 31 | #endif |
diff --git a/include/linux/fb.h b/include/linux/fb.h index 315d89740ddf..f1281687e549 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #ifndef _LINUX_FB_H | 1 | #ifndef _LINUX_FB_H |
| 2 | #define _LINUX_FB_H | 2 | #define _LINUX_FB_H |
| 3 | 3 | ||
| 4 | #include <linux/backlight.h> | ||
| 4 | #include <asm/types.h> | 5 | #include <asm/types.h> |
| 5 | 6 | ||
| 6 | /* Definitions of frame buffers */ | 7 | /* Definitions of frame buffers */ |
| @@ -366,6 +367,12 @@ struct fb_cursor { | |||
| 366 | struct fb_image image; /* Cursor image */ | 367 | struct fb_image image; /* Cursor image */ |
| 367 | }; | 368 | }; |
| 368 | 369 | ||
| 370 | #ifdef CONFIG_FB_BACKLIGHT | ||
| 371 | /* Settings for the generic backlight code */ | ||
| 372 | #define FB_BACKLIGHT_LEVELS 128 | ||
| 373 | #define FB_BACKLIGHT_MAX 0xFF | ||
| 374 | #endif | ||
| 375 | |||
| 369 | #ifdef __KERNEL__ | 376 | #ifdef __KERNEL__ |
| 370 | 377 | ||
| 371 | #include <linux/fs.h> | 378 | #include <linux/fs.h> |
| @@ -756,6 +763,21 @@ struct fb_info { | |||
| 756 | struct fb_cmap cmap; /* Current cmap */ | 763 | struct fb_cmap cmap; /* Current cmap */ |
| 757 | struct list_head modelist; /* mode list */ | 764 | struct list_head modelist; /* mode list */ |
| 758 | struct fb_videomode *mode; /* current mode */ | 765 | struct fb_videomode *mode; /* current mode */ |
| 766 | |||
| 767 | #ifdef CONFIG_FB_BACKLIGHT | ||
| 768 | /* Lock ordering: | ||
| 769 | * bl_mutex (protects bl_dev and bl_curve) | ||
| 770 | * bl_dev->sem (backlight class) | ||
| 771 | */ | ||
| 772 | struct mutex bl_mutex; | ||
| 773 | |||
| 774 | /* assigned backlight device */ | ||
| 775 | struct backlight_device *bl_dev; | ||
| 776 | |||
| 777 | /* Backlight level curve */ | ||
| 778 | u8 bl_curve[FB_BACKLIGHT_LEVELS]; | ||
| 779 | #endif | ||
| 780 | |||
| 759 | struct fb_ops *fbops; | 781 | struct fb_ops *fbops; |
| 760 | struct device *device; | 782 | struct device *device; |
| 761 | struct class_device *class_device; /* sysfs per device attrs */ | 783 | struct class_device *class_device; /* sysfs per device attrs */ |
| @@ -895,6 +917,7 @@ extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); | |||
| 895 | extern void framebuffer_release(struct fb_info *info); | 917 | extern void framebuffer_release(struct fb_info *info); |
| 896 | extern int fb_init_class_device(struct fb_info *fb_info); | 918 | extern int fb_init_class_device(struct fb_info *fb_info); |
| 897 | extern void fb_cleanup_class_device(struct fb_info *head); | 919 | extern void fb_cleanup_class_device(struct fb_info *head); |
| 920 | extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max); | ||
| 898 | 921 | ||
| 899 | /* drivers/video/fbmon.c */ | 922 | /* drivers/video/fbmon.c */ |
| 900 | #define FB_MAXTIMINGS 0 | 923 | #define FB_MAXTIMINGS 0 |
diff --git a/include/linux/pmu.h b/include/linux/pmu.h index ecce5912f4d6..2ed807ddc08c 100644 --- a/include/linux/pmu.h +++ b/include/linux/pmu.h | |||
| @@ -230,4 +230,8 @@ extern int pmu_battery_count; | |||
| 230 | extern struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; | 230 | extern struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; |
| 231 | extern unsigned int pmu_power_flags; | 231 | extern unsigned int pmu_power_flags; |
| 232 | 232 | ||
| 233 | /* Backlight */ | ||
| 234 | extern int disable_kernel_backlight; | ||
| 235 | extern void pmu_backlight_init(struct device_node*); | ||
| 236 | |||
| 233 | #endif /* __KERNEL__ */ | 237 | #endif /* __KERNEL__ */ |
