Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Michael Hanselmann and committed by
Linus Torvalds
5474c120 17660bdd

+1533 -715
+12 -3
arch/powerpc/kernel/traps.c
··· 32 32 #include <linux/delay.h> 33 33 #include <linux/kprobes.h> 34 34 #include <linux/kexec.h> 35 + #include <linux/backlight.h> 35 36 36 37 #include <asm/kdebug.h> 37 38 #include <asm/pgtable.h> ··· 106 105 spin_lock_irq(&die_lock); 107 106 bust_spinlocks(1); 108 107 #ifdef CONFIG_PMAC_BACKLIGHT 109 - if (machine_is(powermac)) { 110 - set_backlight_enable(1); 111 - set_backlight_level(BACKLIGHT_MAX); 108 + mutex_lock(&pmac_backlight_mutex); 109 + if (machine_is(powermac) && pmac_backlight) { 110 + struct backlight_properties *props; 111 + 112 + down(&pmac_backlight->sem); 113 + props = pmac_backlight->props; 114 + props->brightness = props->max_brightness; 115 + props->power = FB_BLANK_UNBLANK; 116 + props->update_status(pmac_backlight); 117 + up(&pmac_backlight->sem); 112 118 } 119 + mutex_unlock(&pmac_backlight_mutex); 113 120 #endif 114 121 printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); 115 122 #ifdef CONFIG_PREEMPT
+113 -165
arch/powerpc/platforms/powermac/backlight.c
··· 3 3 * Contains support for the backlight. 4 4 * 5 5 * Copyright (C) 2000 Benjamin Herrenschmidt 6 + * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> 6 7 * 7 8 */ 8 9 9 10 #include <linux/config.h> 10 11 #include <linux/kernel.h> 11 - #include <linux/module.h> 12 - #include <linux/stddef.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> 12 + #include <linux/fb.h> 13 + #include <linux/backlight.h> 21 14 #include <asm/prom.h> 22 - #include <asm/machdep.h> 23 - #include <asm/nvram.h> 24 15 #include <asm/backlight.h> 25 16 26 - #include <linux/adb.h> 27 - #include <linux/pmu.h> 17 + #define OLD_BACKLIGHT_MAX 15 28 18 29 - static struct backlight_controller *backlighter; 30 - static void* backlighter_data; 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; 19 + /* Protect the pmac_backlight variable */ 20 + DEFINE_MUTEX(pmac_backlight_mutex); 36 21 37 - static void backlight_callback(void *); 38 - static DECLARE_WORK(backlight_work, backlight_callback, NULL); 22 + /* Main backlight storage 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, 41 - void *data, char *type) 37 + int pmac_has_backlight_type(const char *type) 42 38 { 43 - struct device_node* bk_node; 44 - char *prop; 45 - int valid = 0; 39 + struct device_node* bk_node = find_devices("backlight"); 46 40 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 41 if (bk_node) { 64 - prop = get_property(bk_node, "backlight-control", NULL); 65 - if (prop && !strncmp(prop, type, strlen(type))) 66 - valid = 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; 42 + char *prop = get_property(bk_node, "backlight-control", NULL); 43 + if (prop && strncmp(prop, type, strlen(type)) == 0) 44 + return 1; 81 45 } 82 46 83 - #ifdef CONFIG_ADB_PMU 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 - } 100 - EXPORT_SYMBOL(register_backlight_controller); 101 - 102 - void unregister_backlight_controller(struct backlight_controller 103 - *ctrler, void *data) 104 - { 105 - /* We keep the current backlight level (for now) */ 106 - if (ctrler == backlighter && data == backlighter_data) 107 - backlighter = NULL; 108 - } 109 - EXPORT_SYMBOL(unregister_backlight_controller); 110 - 111 - static int __set_backlight_enable(int enable) 112 - { 113 - int rc; 114 - 115 - if (!backlighter) 116 - return -ENODEV; 117 - acquire_console_sem(); 118 - rc = backlighter->set_enable(enable, backlight_level, 119 - backlighter_data); 120 - if (!rc) 121 - backlight_enabled = enable; 122 - release_console_sem(); 123 - return rc; 124 - } 125 - int set_backlight_enable(int enable) 126 - { 127 - if (!backlighter) 128 - return -ENODEV; 129 - backlight_req_enable = enable; 130 - schedule_work(&backlight_work); 131 47 return 0; 132 48 } 133 49 134 - EXPORT_SYMBOL(set_backlight_enable); 135 - 136 - int get_backlight_enable(void) 50 + int pmac_backlight_curve_lookup(struct fb_info *info, int value) 137 51 { 138 - if (!backlighter) 139 - return -ENODEV; 140 - return backlight_enabled; 141 - } 142 - EXPORT_SYMBOL(get_backlight_enable); 52 + int level = (FB_BACKLIGHT_LEVELS - 1); 143 53 144 - static int __set_backlight_level(int level) 145 - { 146 - int rc = 0; 54 + if (info && info->bl_dev) { 55 + int i, max = 0; 147 56 148 - if (!backlighter) 149 - return -ENODEV; 150 - if (level < BACKLIGHT_MIN) 151 - level = BACKLIGHT_OFF; 152 - if (level > BACKLIGHT_MAX) 153 - level = BACKLIGHT_MAX; 154 - acquire_console_sem(); 155 - if (backlight_enabled) 156 - rc = backlighter->set_level(level, backlighter_data); 157 - if (!rc) 158 - backlight_level = level; 159 - release_console_sem(); 160 - if (!rc && !backlight_autosave) { 161 - level <<=1; 162 - if (level & 0x10) 163 - level |= 0x01; 164 - // -- todo: save to property "bklt" 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 + 165 70 } 166 - return rc; 167 - } 168 - int set_backlight_level(int level) 169 - { 170 - if (!backlighter) 171 - return -ENODEV; 172 - backlight_req_level = level; 173 - schedule_work(&backlight_work); 174 - return 0; 71 + 72 + return level; 175 73 } 176 74 177 - EXPORT_SYMBOL(set_backlight_level); 178 - 179 - int get_backlight_level(void) 75 + static void pmac_backlight_key(int direction) 180 76 { 181 - if (!backlighter) 182 - return -ENODEV; 183 - return backlight_level; 77 + mutex_lock(&pmac_backlight_mutex); 78 + if (pmac_backlight) { 79 + struct backlight_properties *props; 80 + int brightness; 81 + 82 + down(&pmac_backlight->sem); 83 + props = pmac_backlight->props; 84 + 85 + brightness = props->brightness + 86 + ((direction?-1:1) * (props->max_brightness / 15)); 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); 184 99 } 185 - EXPORT_SYMBOL(get_backlight_level); 186 100 187 - static void backlight_callback(void *dummy) 101 + void pmac_backlight_key_up() 188 102 { 189 - int level, enable; 103 + pmac_backlight_key(0); 104 + } 190 105 191 - do { 192 - level = backlight_req_level; 193 - enable = backlight_req_enable; 194 - mb(); 106 + void pmac_backlight_key_down() 107 + { 108 + pmac_backlight_key(1); 109 + } 195 110 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); 111 + int pmac_backlight_set_legacy_brightness(int brightness) 112 + { 113 + int error = -ENXIO; 114 + 115 + mutex_lock(&pmac_backlight_mutex); 116 + if (pmac_backlight) { 117 + struct backlight_properties *props; 118 + 119 + down(&pmac_backlight->sem); 120 + props = pmac_backlight->props; 121 + props->brightness = brightness * 122 + props->max_brightness / OLD_BACKLIGHT_MAX; 123 + props->update_status(pmac_backlight); 124 + up(&pmac_backlight->sem); 125 + 126 + error = 0; 127 + } 128 + mutex_unlock(&pmac_backlight_mutex); 129 + 130 + return error; 131 + } 132 + 133 + int pmac_backlight_get_legacy_brightness() 134 + { 135 + int result = -ENXIO; 136 + 137 + mutex_lock(&pmac_backlight_mutex); 138 + if (pmac_backlight) { 139 + struct backlight_properties *props; 140 + 141 + down(&pmac_backlight->sem); 142 + props = pmac_backlight->props; 143 + result = props->brightness * 144 + OLD_BACKLIGHT_MAX / props->max_brightness; 145 + up(&pmac_backlight->sem); 146 + } 147 + mutex_unlock(&pmac_backlight_mutex); 148 + 149 + return result; 202 150 }
-3
arch/powerpc/xmon/xmon.c
··· 26 26 #include <asm/prom.h> 27 27 #include <asm/machdep.h> 28 28 #include <asm/xmon.h> 29 - #ifdef CONFIG_PMAC_BACKLIGHT 30 - #include <asm/backlight.h> 31 - #endif 32 29 #include <asm/processor.h> 33 30 #include <asm/pgtable.h> 34 31 #include <asm/mmu.h>
+12 -7
drivers/macintosh/Kconfig
··· 99 99 devices are not fully supported in the bay as I never had one to 100 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 102 config PMAC_BACKLIGHT 105 103 bool "Backlight control for LCD screens" 106 104 depends on ADB_PMU && (BROKEN || !PPC64) 107 105 help 108 - Say Y here to build in code to manage the LCD backlight on a 109 - Macintosh PowerBook. With this code, the backlight will be turned 110 - on and off appropriately on power-management and lid-open/lid-closed 111 - events; also, the PowerBook button device will be enabled so you can 112 - change the screen brightness. 106 + Say Y here to enable Macintosh specific extensions of the generic 107 + backlight code. With this enabled, the brightness keys on older 108 + PowerBooks will be enabled so you can change the screen brightness. 109 + Newer models should use an userspace daemon like pbbuttonsd. 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 119 config ADB_MACIO 115 120 bool "Include MacIO (CHRP) ADB driver"
+1
drivers/macintosh/Makefile
··· 12 12 obj-$(CONFIG_ANSLCD) += ans-lcd.o 13 13 14 14 obj-$(CONFIG_ADB_PMU) += via-pmu.o 15 + obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o 15 16 obj-$(CONFIG_ADB_CUDA) += via-cuda.o 16 17 obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o 17 18 obj-$(CONFIG_PMAC_SMU) += smu.o
+7 -21
drivers/macintosh/adbhid.c
··· 503 503 case 0x1f: /* Powerbook button device */ 504 504 { 505 505 int down = (data[1] == (data[1] & 0xf)); 506 - #ifdef CONFIG_PMAC_BACKLIGHT 507 - int backlight = get_backlight_level(); 508 - #endif 506 + 509 507 /* 510 508 * XXX: Where is the contrast control for the passive? 511 509 * -- Cort ··· 528 530 529 531 case 0xa: /* brightness decrease */ 530 532 #ifdef CONFIG_PMAC_BACKLIGHT 531 - if (!disable_kernel_backlight) { 532 - if (down && backlight >= 0) { 533 - if (backlight > BACKLIGHT_OFF) 534 - set_backlight_level(backlight-1); 535 - else 536 - set_backlight_level(BACKLIGHT_OFF); 537 - } 538 - } 539 - #endif /* CONFIG_PMAC_BACKLIGHT */ 533 + if (!disable_kernel_backlight && down) 534 + pmac_backlight_key_down(); 535 + #endif 540 536 input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); 541 537 break; 542 538 543 539 case 0x9: /* brightness increase */ 544 540 #ifdef CONFIG_PMAC_BACKLIGHT 545 - if (!disable_kernel_backlight) { 546 - if (down && backlight >= 0) { 547 - if (backlight < BACKLIGHT_MAX) 548 - set_backlight_level(backlight+1); 549 - else 550 - set_backlight_level(BACKLIGHT_MAX); 551 - } 552 - } 553 - #endif /* CONFIG_PMAC_BACKLIGHT */ 541 + if (!disable_kernel_backlight && down) 542 + pmac_backlight_key_up(); 543 + #endif 554 544 input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); 555 545 break; 556 546
+150
drivers/macintosh/via-pmu-backlight.c
··· 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 + }
+29 -91
drivers/macintosh/via-pmu.c
··· 144 144 static int data_len; 145 145 static volatile int adb_int_pending; 146 146 static volatile int disable_poll; 147 - static struct adb_request bright_req_1, bright_req_2; 148 147 static struct device_node *vias; 149 148 static int pmu_kind = PMU_UNKNOWN; 150 149 static int pmu_fully_inited = 0; ··· 160 161 #if defined(CONFIG_PM) && defined(CONFIG_PPC32) 161 162 static int option_lid_wakeup = 1; 162 163 #endif /* CONFIG_PM && CONFIG_PPC32 */ 163 - #if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT) 164 + #if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY) 164 165 static int sleep_in_progress; 165 166 #endif 166 167 static unsigned long async_req_locks; ··· 207 208 int count, int *eof, void *data); 208 209 static int proc_get_irqstats(char *page, char **start, off_t off, 209 210 int count, int *eof, void *data); 210 - #ifdef CONFIG_PMAC_BACKLIGHT 211 - static int pmu_set_backlight_level(int level, void* data); 212 - static int pmu_set_backlight_enable(int on, int level, void* data); 213 - #endif /* CONFIG_PMAC_BACKLIGHT */ 214 211 static void pmu_pass_intr(unsigned char *data, int len); 215 212 static int proc_get_batt(char *page, char **start, off_t off, 216 213 int count, int *eof, void *data); ··· 286 291 "1999 PowerBook G3", 287 292 "Core99" 288 293 }; 289 - 290 - #ifdef CONFIG_PMAC_BACKLIGHT 291 - static struct backlight_controller pmu_backlight_controller = { 292 - pmu_set_backlight_enable, 293 - pmu_set_backlight_level 294 - }; 295 - #endif /* CONFIG_PMAC_BACKLIGHT */ 296 294 297 295 int __init find_via_pmu(void) 298 296 { ··· 405 417 if (vias == NULL) 406 418 return -ENODEV; 407 419 408 - bright_req_1.complete = 1; 409 - bright_req_2.complete = 1; 410 420 batt_req.complete = 1; 411 421 412 422 #ifndef CONFIG_PPC_MERGE ··· 469 483 return -ENODEV; 470 484 471 485 #ifdef CONFIG_PMAC_BACKLIGHT 472 - /* Enable backlight */ 473 - register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); 474 - #endif /* CONFIG_PMAC_BACKLIGHT */ 486 + /* Initialize backlight */ 487 + pmu_backlight_init(vias); 488 + #endif 475 489 476 490 #ifdef CONFIG_PPC32 477 491 if (machine_is_compatible("AAPL,3400/2400") || ··· 1410 1424 #ifdef CONFIG_INPUT_ADBHID 1411 1425 if (!disable_kernel_backlight) 1412 1426 #endif /* CONFIG_INPUT_ADBHID */ 1413 - set_backlight_level(data[1] >> 4); 1427 + pmac_backlight_set_legacy_brightness(data[1] >> 4); 1414 1428 #endif /* CONFIG_PMAC_BACKLIGHT */ 1415 1429 } 1416 1430 /* Tick interrupt */ ··· 1659 1673 } 1660 1674 return IRQ_NONE; 1661 1675 } 1662 - 1663 - #ifdef CONFIG_PMAC_BACKLIGHT 1664 - static int backlight_to_bright[] = { 1665 - 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e, 1666 - 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e 1667 - }; 1668 - 1669 - static int 1670 - pmu_set_backlight_enable(int on, int level, void* data) 1671 - { 1672 - struct adb_request req; 1673 - 1674 - if (vias == NULL) 1675 - return -ENODEV; 1676 - 1677 - if (on) { 1678 - pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, 1679 - backlight_to_bright[level]); 1680 - pmu_wait_complete(&req); 1681 - } 1682 - pmu_request(&req, NULL, 2, PMU_POWER_CTRL, 1683 - PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF)); 1684 - pmu_wait_complete(&req); 1685 - 1686 - return 0; 1687 - } 1688 - 1689 - static void 1690 - pmu_bright_complete(struct adb_request *req) 1691 - { 1692 - if (req == &bright_req_1) 1693 - clear_bit(1, &async_req_locks); 1694 - if (req == &bright_req_2) 1695 - clear_bit(2, &async_req_locks); 1696 - } 1697 - 1698 - static int 1699 - pmu_set_backlight_level(int level, void* data) 1700 - { 1701 - if (vias == NULL) 1702 - return -ENODEV; 1703 - 1704 - if (test_and_set_bit(1, &async_req_locks)) 1705 - return -EAGAIN; 1706 - pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT, 1707 - backlight_to_bright[level]); 1708 - if (test_and_set_bit(2, &async_req_locks)) 1709 - return -EAGAIN; 1710 - pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL, 1711 - PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ? 1712 - PMU_POW_ON : PMU_POW_OFF)); 1713 - 1714 - return 0; 1715 - } 1716 - #endif /* CONFIG_PMAC_BACKLIGHT */ 1717 1676 1718 1677 void 1719 1678 pmu_enable_irled(int on) ··· 2076 2145 return -EBUSY; 2077 2146 } 2078 2147 2079 - /* Wait for completion of async backlight requests */ 2080 - while (!bright_req_1.complete || !bright_req_2.complete || 2081 - !batt_req.complete) 2148 + /* Wait for completion of async requests */ 2149 + while (!batt_req.complete) 2082 2150 pmu_poll(); 2083 2151 2084 2152 /* Giveup the lazy FPU & vec so we don't have to back them ··· 2608 2678 return put_user(1, argp); 2609 2679 #endif /* CONFIG_PM && CONFIG_PPC32 */ 2610 2680 2611 - #ifdef CONFIG_PMAC_BACKLIGHT 2612 - /* Backlight should have its own device or go via 2613 - * the fbdev 2614 - */ 2681 + #ifdef CONFIG_PMAC_BACKLIGHT_LEGACY 2682 + /* Compatibility ioctl's for backlight */ 2615 2683 case PMU_IOC_GET_BACKLIGHT: 2684 + { 2685 + int brightness; 2686 + 2616 2687 if (sleep_in_progress) 2617 2688 return -EBUSY; 2618 - error = get_backlight_level(); 2619 - if (error < 0) 2620 - return error; 2621 - return put_user(error, argp); 2689 + 2690 + brightness = pmac_backlight_get_legacy_brightness(); 2691 + if (brightness < 0) 2692 + return brightness; 2693 + else 2694 + return put_user(brightness, argp); 2695 + 2696 + } 2622 2697 case PMU_IOC_SET_BACKLIGHT: 2623 2698 { 2624 - __u32 value; 2699 + int brightness; 2700 + 2625 2701 if (sleep_in_progress) 2626 2702 return -EBUSY; 2627 - error = get_user(value, argp); 2628 - if (!error) 2629 - error = set_backlight_level(value); 2630 - break; 2703 + 2704 + error = get_user(brightness, argp); 2705 + if (error) 2706 + return error; 2707 + 2708 + return pmac_backlight_set_legacy_brightness(brightness); 2631 2709 } 2632 2710 #ifdef CONFIG_INPUT_ADBHID 2633 2711 case PMU_IOC_GRAB_BACKLIGHT: { ··· 2651 2713 return 0; 2652 2714 } 2653 2715 #endif /* CONFIG_INPUT_ADBHID */ 2654 - #endif /* CONFIG_PMAC_BACKLIGHT */ 2716 + #endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */ 2655 2717 case PMU_IOC_GET_MODEL: 2656 2718 return put_user(pmu_kind, argp); 2657 2719 case PMU_IOC_HAS_ADB:
+56
drivers/video/Kconfig
··· 86 86 combination with certain motherboards and monitors are known to 87 87 suffer from this problem. 88 88 89 + config FB_BACKLIGHT 90 + bool 91 + depends on FB 92 + default n 93 + 89 94 config FB_MODE_HELPERS 90 95 bool "Enable Video Mode Handling Helpers" 91 96 depends on FB ··· 722 717 independently validate video mode parameters, you should say Y 723 718 here. 724 719 720 + config FB_NVIDIA_BACKLIGHT 721 + bool "Support for backlight control" 722 + depends on FB_NVIDIA && PPC_PMAC 723 + select FB_BACKLIGHT 724 + select BACKLIGHT_LCD_SUPPORT 725 + select BACKLIGHT_CLASS_DEVICE 726 + default y 727 + help 728 + Say Y here if you want to control the backlight of your display. 729 + 725 730 config FB_RIVA 726 731 tristate "nVidia Riva support" 727 732 depends on FB && PCI ··· 769 754 Say Y here if you want the Riva driver to output all sorts 770 755 of debugging informations to provide to the maintainer when 771 756 something goes wrong. 757 + 758 + config FB_RIVA_BACKLIGHT 759 + bool "Support for backlight control" 760 + depends on FB_RIVA && PPC_PMAC 761 + select FB_BACKLIGHT 762 + select BACKLIGHT_LCD_SUPPORT 763 + select BACKLIGHT_CLASS_DEVICE 764 + default y 765 + help 766 + Say Y here if you want to control the backlight of your display. 772 767 773 768 config FB_I810 774 769 tristate "Intel 810/815 support (EXPERIMENTAL)" ··· 1018 993 1019 994 There is a product page at 1020 995 http://apps.ati.com/ATIcompare/ 996 + 1021 997 config FB_RADEON_I2C 1022 998 bool "DDC/I2C for ATI Radeon support" 1023 999 depends on FB_RADEON 1024 1000 default y 1025 1001 help 1026 1002 Say Y here if you want DDC/I2C support for your Radeon board. 1003 + 1004 + config FB_RADEON_BACKLIGHT 1005 + bool "Support for backlight control" 1006 + depends on FB_RADEON && PPC_PMAC 1007 + select FB_BACKLIGHT 1008 + select BACKLIGHT_LCD_SUPPORT 1009 + select BACKLIGHT_CLASS_DEVICE 1010 + default y 1011 + help 1012 + Say Y here if you want to control the backlight of your display. 1027 1013 1028 1014 config FB_RADEON_DEBUG 1029 1015 bool "Lots of debug output from Radeon driver" ··· 1059 1023 1060 1024 To compile this driver as a module, choose M here: the 1061 1025 module will be called aty128fb. 1026 + 1027 + config FB_ATY128_BACKLIGHT 1028 + bool "Support for backlight control" 1029 + depends on FB_ATY128 && PPC_PMAC 1030 + select FB_BACKLIGHT 1031 + select BACKLIGHT_LCD_SUPPORT 1032 + select BACKLIGHT_CLASS_DEVICE 1033 + default y 1034 + help 1035 + Say Y here if you want to control the backlight of your display. 1062 1036 1063 1037 config FB_ATY 1064 1038 tristate "ATI Mach64 display support" if PCI || ATARI ··· 1111 1065 framebuffer device. The ATI product support page for these boards 1112 1066 is at 1113 1067 <http://support.ati.com/products/pc/mach64/graphics_xpression.html>. 1068 + 1069 + config FB_ATY_BACKLIGHT 1070 + bool "Support for backlight control" 1071 + depends on FB_ATY && PPC_PMAC 1072 + select FB_BACKLIGHT 1073 + select BACKLIGHT_LCD_SUPPORT 1074 + select BACKLIGHT_CLASS_DEVICE 1075 + default y 1076 + help 1077 + Say Y here if you want to control the backlight of your display. 1114 1078 1115 1079 config FB_S3TRIO 1116 1080 bool "S3 Trio display support"
+1
drivers/video/aty/Makefile
··· 10 10 11 11 radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o 12 12 radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o 13 + radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT) += radeon_backlight.o 13 14 radeonfb-objs := $(radeonfb-y) 14 15
+225 -97
drivers/video/aty/aty128fb.c
··· 64 64 #include <linux/pci.h> 65 65 #include <linux/ioport.h> 66 66 #include <linux/console.h> 67 + #include <linux/backlight.h> 67 68 #include <asm/io.h> 68 69 69 70 #ifdef CONFIG_PPC_PMAC ··· 480 479 .fb_copyarea = cfb_copyarea, 481 480 .fb_imageblit = cfb_imageblit, 482 481 }; 483 - 484 - #ifdef CONFIG_PMAC_BACKLIGHT 485 - static int aty128_set_backlight_enable(int on, int level, void* data); 486 - static int aty128_set_backlight_level(int level, void* data); 487 - 488 - static struct backlight_controller aty128_backlight_controller = { 489 - aty128_set_backlight_enable, 490 - aty128_set_backlight_level 491 - }; 492 - #endif /* CONFIG_PMAC_BACKLIGHT */ 493 482 494 483 /* 495 484 * Functions to read from/write to the mmio registers ··· 1249 1258 static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) 1250 1259 { 1251 1260 u32 reg; 1261 + #ifdef CONFIG_FB_ATY128_BACKLIGHT 1262 + struct fb_info *info = pci_get_drvdata(par->pdev); 1263 + #endif 1252 1264 1253 1265 if (on) { 1254 1266 reg = aty_ld_le32(LVDS_GEN_CNTL); 1255 1267 reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION; 1256 1268 reg &= ~LVDS_DISPLAY_DIS; 1257 1269 aty_st_le32(LVDS_GEN_CNTL, reg); 1258 - #ifdef CONFIG_PMAC_BACKLIGHT 1259 - aty128_set_backlight_enable(get_backlight_enable(), 1260 - get_backlight_level(), par); 1270 + #ifdef CONFIG_FB_ATY128_BACKLIGHT 1271 + mutex_lock(&info->bl_mutex); 1272 + if (info->bl_dev) { 1273 + down(&info->bl_dev->sem); 1274 + info->bl_dev->props->update_status(info->bl_dev); 1275 + up(&info->bl_dev->sem); 1276 + } 1277 + mutex_unlock(&info->bl_mutex); 1261 1278 #endif 1262 1279 } else { 1263 - #ifdef CONFIG_PMAC_BACKLIGHT 1264 - aty128_set_backlight_enable(0, 0, par); 1280 + #ifdef CONFIG_FB_ATY128_BACKLIGHT 1281 + mutex_lock(&info->bl_mutex); 1282 + if (info->bl_dev) { 1283 + down(&info->bl_dev->sem); 1284 + info->bl_dev->props->brightness = 0; 1285 + info->bl_dev->props->power = FB_BLANK_POWERDOWN; 1286 + info->bl_dev->props->update_status(info->bl_dev); 1287 + up(&info->bl_dev->sem); 1288 + } 1289 + mutex_unlock(&info->bl_mutex); 1265 1290 #endif 1266 1291 reg = aty_ld_le32(LVDS_GEN_CNTL); 1267 1292 reg |= LVDS_DISPLAY_DIS; ··· 1698 1691 } 1699 1692 #endif /* MODULE */ 1700 1693 1694 + /* Backlight */ 1695 + #ifdef CONFIG_FB_ATY128_BACKLIGHT 1696 + #define MAX_LEVEL 0xFF 1697 + 1698 + static struct backlight_properties aty128_bl_data; 1699 + 1700 + static int aty128_bl_get_level_brightness(struct aty128fb_par *par, 1701 + int level) 1702 + { 1703 + struct fb_info *info = pci_get_drvdata(par->pdev); 1704 + int atylevel; 1705 + 1706 + /* Get and convert the value */ 1707 + mutex_lock(&info->bl_mutex); 1708 + atylevel = MAX_LEVEL - 1709 + (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); 1710 + mutex_unlock(&info->bl_mutex); 1711 + 1712 + if (atylevel < 0) 1713 + atylevel = 0; 1714 + else if (atylevel > MAX_LEVEL) 1715 + atylevel = MAX_LEVEL; 1716 + 1717 + return atylevel; 1718 + } 1719 + 1720 + /* We turn off the LCD completely instead of just dimming the backlight. 1721 + * This provides greater power saving and the display is useless without 1722 + * backlight anyway 1723 + */ 1724 + #define BACKLIGHT_LVDS_OFF 1725 + /* That one prevents proper CRT output with LCD off */ 1726 + #undef BACKLIGHT_DAC_OFF 1727 + 1728 + static int aty128_bl_update_status(struct backlight_device *bd) 1729 + { 1730 + struct aty128fb_par *par = class_get_devdata(&bd->class_dev); 1731 + unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); 1732 + int level; 1733 + 1734 + if (bd->props->power != FB_BLANK_UNBLANK || 1735 + bd->props->fb_blank != FB_BLANK_UNBLANK || 1736 + !par->lcd_on) 1737 + level = 0; 1738 + else 1739 + level = bd->props->brightness; 1740 + 1741 + reg |= LVDS_BL_MOD_EN | LVDS_BLON; 1742 + if (level > 0) { 1743 + reg |= LVDS_DIGION; 1744 + if (!(reg & LVDS_ON)) { 1745 + reg &= ~LVDS_BLON; 1746 + aty_st_le32(LVDS_GEN_CNTL, reg); 1747 + aty_ld_le32(LVDS_GEN_CNTL); 1748 + mdelay(10); 1749 + reg |= LVDS_BLON; 1750 + aty_st_le32(LVDS_GEN_CNTL, reg); 1751 + } 1752 + reg &= ~LVDS_BL_MOD_LEVEL_MASK; 1753 + reg |= (aty128_bl_get_level_brightness(par, level) << LVDS_BL_MOD_LEVEL_SHIFT); 1754 + #ifdef BACKLIGHT_LVDS_OFF 1755 + reg |= LVDS_ON | LVDS_EN; 1756 + reg &= ~LVDS_DISPLAY_DIS; 1757 + #endif 1758 + aty_st_le32(LVDS_GEN_CNTL, reg); 1759 + #ifdef BACKLIGHT_DAC_OFF 1760 + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); 1761 + #endif 1762 + } else { 1763 + reg &= ~LVDS_BL_MOD_LEVEL_MASK; 1764 + reg |= (aty128_bl_get_level_brightness(par, 0) << LVDS_BL_MOD_LEVEL_SHIFT); 1765 + #ifdef BACKLIGHT_LVDS_OFF 1766 + reg |= LVDS_DISPLAY_DIS; 1767 + aty_st_le32(LVDS_GEN_CNTL, reg); 1768 + aty_ld_le32(LVDS_GEN_CNTL); 1769 + udelay(10); 1770 + reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); 1771 + #endif 1772 + aty_st_le32(LVDS_GEN_CNTL, reg); 1773 + #ifdef BACKLIGHT_DAC_OFF 1774 + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); 1775 + #endif 1776 + } 1777 + 1778 + return 0; 1779 + } 1780 + 1781 + static int aty128_bl_get_brightness(struct backlight_device *bd) 1782 + { 1783 + return bd->props->brightness; 1784 + } 1785 + 1786 + static struct backlight_properties aty128_bl_data = { 1787 + .owner = THIS_MODULE, 1788 + .get_brightness = aty128_bl_get_brightness, 1789 + .update_status = aty128_bl_update_status, 1790 + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), 1791 + }; 1792 + 1793 + static void aty128_bl_init(struct aty128fb_par *par) 1794 + { 1795 + struct fb_info *info = pci_get_drvdata(par->pdev); 1796 + struct backlight_device *bd; 1797 + char name[12]; 1798 + 1799 + /* Could be extended to Rage128Pro LVDS output too */ 1800 + if (par->chip_gen != rage_M3) 1801 + return; 1802 + 1803 + #ifdef CONFIG_PMAC_BACKLIGHT 1804 + if (!pmac_has_backlight_type("ati")) 1805 + return; 1806 + #endif 1807 + 1808 + snprintf(name, sizeof(name), "aty128bl%d", info->node); 1809 + 1810 + bd = backlight_device_register(name, par, &aty128_bl_data); 1811 + if (IS_ERR(bd)) { 1812 + info->bl_dev = NULL; 1813 + printk("aty128: Backlight registration failed\n"); 1814 + goto error; 1815 + } 1816 + 1817 + mutex_lock(&info->bl_mutex); 1818 + info->bl_dev = bd; 1819 + fb_bl_default_curve(info, 0, 1820 + 63 * FB_BACKLIGHT_MAX / MAX_LEVEL, 1821 + 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); 1822 + mutex_unlock(&info->bl_mutex); 1823 + 1824 + up(&bd->sem); 1825 + bd->props->brightness = aty128_bl_data.max_brightness; 1826 + bd->props->power = FB_BLANK_UNBLANK; 1827 + bd->props->update_status(bd); 1828 + down(&bd->sem); 1829 + 1830 + #ifdef CONFIG_PMAC_BACKLIGHT 1831 + mutex_lock(&pmac_backlight_mutex); 1832 + if (!pmac_backlight) 1833 + pmac_backlight = bd; 1834 + mutex_unlock(&pmac_backlight_mutex); 1835 + #endif 1836 + 1837 + printk("aty128: Backlight initialized (%s)\n", name); 1838 + 1839 + return; 1840 + 1841 + error: 1842 + return; 1843 + } 1844 + 1845 + static void aty128_bl_exit(struct aty128fb_par *par) 1846 + { 1847 + struct fb_info *info = pci_get_drvdata(par->pdev); 1848 + 1849 + #ifdef CONFIG_PMAC_BACKLIGHT 1850 + mutex_lock(&pmac_backlight_mutex); 1851 + #endif 1852 + 1853 + mutex_lock(&info->bl_mutex); 1854 + if (info->bl_dev) { 1855 + #ifdef CONFIG_PMAC_BACKLIGHT 1856 + if (pmac_backlight == info->bl_dev) 1857 + pmac_backlight = NULL; 1858 + #endif 1859 + 1860 + backlight_device_unregister(info->bl_dev); 1861 + info->bl_dev = NULL; 1862 + 1863 + printk("aty128: Backlight unloaded\n"); 1864 + } 1865 + mutex_unlock(&info->bl_mutex); 1866 + 1867 + #ifdef CONFIG_PMAC_BACKLIGHT 1868 + mutex_unlock(&pmac_backlight_mutex); 1869 + #endif 1870 + } 1871 + #endif /* CONFIG_FB_ATY128_BACKLIGHT */ 1701 1872 1702 1873 /* 1703 1874 * Initialisation ··· 2020 1835 if (register_framebuffer(info) < 0) 2021 1836 return 0; 2022 1837 2023 - #ifdef CONFIG_PMAC_BACKLIGHT 2024 - /* Could be extended to Rage128Pro LVDS output too */ 2025 - if (par->chip_gen == rage_M3) 2026 - register_backlight_controller(&aty128_backlight_controller, par, "ati"); 2027 - #endif /* CONFIG_PMAC_BACKLIGHT */ 2028 - 2029 1838 par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); 2030 1839 par->pdev = pdev; 2031 1840 par->asleep = 0; 2032 1841 par->lock_blank = 0; 2033 - 1842 + 1843 + #ifdef CONFIG_FB_ATY128_BACKLIGHT 1844 + aty128_bl_init(par); 1845 + #endif 1846 + 2034 1847 printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", 2035 1848 info->node, info->fix.id, video_card); 2036 1849 ··· 2164 1981 2165 1982 par = info->par; 2166 1983 1984 + #ifdef CONFIG_FB_ATY128_BACKLIGHT 1985 + aty128_bl_exit(par); 1986 + #endif 1987 + 2167 1988 unregister_framebuffer(info); 2168 1989 #ifdef CONFIG_MTRR 2169 1990 if (par->mtrr.vram_valid) ··· 2198 2011 if (par->lock_blank || par->asleep) 2199 2012 return 0; 2200 2013 2201 - #ifdef CONFIG_PMAC_BACKLIGHT 2202 - if (machine_is(powermac) && blank) 2203 - set_backlight_enable(0); 2204 - #endif /* CONFIG_PMAC_BACKLIGHT */ 2014 + #ifdef CONFIG_FB_ATY128_BACKLIGHT 2015 + if (machine_is(powermac) && blank) { 2016 + down(&fb->bl_dev->sem); 2017 + fb->bl_dev->props->power = FB_BLANK_POWERDOWN; 2018 + fb->bl_dev->props->update_status(fb->bl_dev); 2019 + up(&fb->bl_dev->sem); 2020 + } 2021 + #endif 2205 2022 2206 2023 if (blank & FB_BLANK_VSYNC_SUSPEND) 2207 2024 state |= 2; ··· 2220 2029 aty128_set_crt_enable(par, par->crt_on && !blank); 2221 2030 aty128_set_lcd_enable(par, par->lcd_on && !blank); 2222 2031 } 2223 - #ifdef CONFIG_PMAC_BACKLIGHT 2224 - if (machine_is(powermac) && !blank) 2225 - set_backlight_enable(1); 2226 - #endif /* CONFIG_PMAC_BACKLIGHT */ 2032 + #ifdef CONFIG_FB_ATY128_BACKLIGHT 2033 + if (machine_is(powermac) && !blank) { 2034 + down(&fb->bl_dev->sem); 2035 + fb->bl_dev->props->power = FB_BLANK_UNBLANK; 2036 + fb->bl_dev->props->update_status(fb->bl_dev); 2037 + up(&fb->bl_dev->sem); 2038 + } 2039 + #endif 2227 2040 return 0; 2228 2041 } 2229 2042 ··· 2332 2137 } 2333 2138 return -EINVAL; 2334 2139 } 2335 - 2336 - #ifdef CONFIG_PMAC_BACKLIGHT 2337 - static int backlight_conv[] = { 2338 - 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, 2339 - 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 2340 - }; 2341 - 2342 - /* We turn off the LCD completely instead of just dimming the backlight. 2343 - * This provides greater power saving and the display is useless without 2344 - * backlight anyway 2345 - */ 2346 - #define BACKLIGHT_LVDS_OFF 2347 - /* That one prevents proper CRT output with LCD off */ 2348 - #undef BACKLIGHT_DAC_OFF 2349 - 2350 - static int aty128_set_backlight_enable(int on, int level, void *data) 2351 - { 2352 - struct aty128fb_par *par = data; 2353 - unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); 2354 - 2355 - if (!par->lcd_on) 2356 - on = 0; 2357 - reg |= LVDS_BL_MOD_EN | LVDS_BLON; 2358 - if (on && level > BACKLIGHT_OFF) { 2359 - reg |= LVDS_DIGION; 2360 - if (!(reg & LVDS_ON)) { 2361 - reg &= ~LVDS_BLON; 2362 - aty_st_le32(LVDS_GEN_CNTL, reg); 2363 - (void)aty_ld_le32(LVDS_GEN_CNTL); 2364 - mdelay(10); 2365 - reg |= LVDS_BLON; 2366 - aty_st_le32(LVDS_GEN_CNTL, reg); 2367 - } 2368 - reg &= ~LVDS_BL_MOD_LEVEL_MASK; 2369 - reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT); 2370 - #ifdef BACKLIGHT_LVDS_OFF 2371 - reg |= LVDS_ON | LVDS_EN; 2372 - reg &= ~LVDS_DISPLAY_DIS; 2373 - #endif 2374 - aty_st_le32(LVDS_GEN_CNTL, reg); 2375 - #ifdef BACKLIGHT_DAC_OFF 2376 - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); 2377 - #endif 2378 - } else { 2379 - reg &= ~LVDS_BL_MOD_LEVEL_MASK; 2380 - reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT); 2381 - #ifdef BACKLIGHT_LVDS_OFF 2382 - reg |= LVDS_DISPLAY_DIS; 2383 - aty_st_le32(LVDS_GEN_CNTL, reg); 2384 - (void)aty_ld_le32(LVDS_GEN_CNTL); 2385 - udelay(10); 2386 - reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); 2387 - #endif 2388 - aty_st_le32(LVDS_GEN_CNTL, reg); 2389 - #ifdef BACKLIGHT_DAC_OFF 2390 - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); 2391 - #endif 2392 - } 2393 - 2394 - return 0; 2395 - } 2396 - 2397 - static int aty128_set_backlight_level(int level, void* data) 2398 - { 2399 - return aty128_set_backlight_enable(1, level, data); 2400 - } 2401 - #endif /* CONFIG_PMAC_BACKLIGHT */ 2402 2140 2403 2141 #if 0 2404 2142 /*
+1
drivers/video/aty/atyfb.h
··· 151 151 int lock_blank; 152 152 unsigned long res_start; 153 153 unsigned long res_size; 154 + struct pci_dev *pdev; 154 155 #ifdef __sparc__ 155 156 struct pci_mmap_map *mmap_map; 156 157 u8 mmaped;
+152 -28
drivers/video/aty/atyfb_base.c
··· 66 66 #include <linux/interrupt.h> 67 67 #include <linux/spinlock.h> 68 68 #include <linux/wait.h> 69 + #include <linux/backlight.h> 69 70 70 71 #include <asm/io.h> 71 72 #include <asm/uaccess.h> ··· 2116 2115 2117 2116 #endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */ 2118 2117 2119 - #ifdef CONFIG_PMAC_BACKLIGHT 2118 + /* Backlight */ 2119 + #ifdef CONFIG_FB_ATY_BACKLIGHT 2120 + #define MAX_LEVEL 0xFF 2120 2121 2121 - /* 2122 - * LCD backlight control 2123 - */ 2122 + static struct backlight_properties aty_bl_data; 2124 2123 2125 - static int backlight_conv[] = { 2126 - 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d, 2127 - 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff 2128 - }; 2129 - 2130 - static int aty_set_backlight_enable(int on, int level, void *data) 2124 + static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) 2131 2125 { 2132 - struct fb_info *info = (struct fb_info *) data; 2133 - struct atyfb_par *par = (struct atyfb_par *) info->par; 2126 + struct fb_info *info = pci_get_drvdata(par->pdev); 2127 + int atylevel; 2128 + 2129 + /* Get and convert the value */ 2130 + mutex_lock(&info->bl_mutex); 2131 + atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; 2132 + mutex_unlock(&info->bl_mutex); 2133 + 2134 + if (atylevel < 0) 2135 + atylevel = 0; 2136 + else if (atylevel > MAX_LEVEL) 2137 + atylevel = MAX_LEVEL; 2138 + 2139 + return atylevel; 2140 + } 2141 + 2142 + static int aty_bl_update_status(struct backlight_device *bd) 2143 + { 2144 + struct atyfb_par *par = class_get_devdata(&bd->class_dev); 2134 2145 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); 2146 + int level; 2147 + 2148 + if (bd->props->power != FB_BLANK_UNBLANK || 2149 + bd->props->fb_blank != FB_BLANK_UNBLANK) 2150 + level = 0; 2151 + else 2152 + level = bd->props->brightness; 2135 2153 2136 2154 reg |= (BLMOD_EN | BIASMOD_EN); 2137 - if (on && level > BACKLIGHT_OFF) { 2155 + if (level > 0) { 2138 2156 reg &= ~BIAS_MOD_LEVEL_MASK; 2139 - reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT); 2157 + reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT); 2140 2158 } else { 2141 2159 reg &= ~BIAS_MOD_LEVEL_MASK; 2142 - reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT); 2160 + reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT); 2143 2161 } 2144 2162 aty_st_lcd(LCD_MISC_CNTL, reg, par); 2163 + 2145 2164 return 0; 2146 2165 } 2147 2166 2148 - static int aty_set_backlight_level(int level, void *data) 2167 + static int aty_bl_get_brightness(struct backlight_device *bd) 2149 2168 { 2150 - return aty_set_backlight_enable(1, level, data); 2169 + return bd->props->brightness; 2151 2170 } 2152 2171 2153 - static struct backlight_controller aty_backlight_controller = { 2154 - aty_set_backlight_enable, 2155 - aty_set_backlight_level 2172 + static struct backlight_properties aty_bl_data = { 2173 + .owner = THIS_MODULE, 2174 + .get_brightness = aty_bl_get_brightness, 2175 + .update_status = aty_bl_update_status, 2176 + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), 2156 2177 }; 2157 - #endif /* CONFIG_PMAC_BACKLIGHT */ 2178 + 2179 + static void aty_bl_init(struct atyfb_par *par) 2180 + { 2181 + struct fb_info *info = pci_get_drvdata(par->pdev); 2182 + struct backlight_device *bd; 2183 + char name[12]; 2184 + 2185 + #ifdef CONFIG_PMAC_BACKLIGHT 2186 + if (!pmac_has_backlight_type("ati")) 2187 + return; 2188 + #endif 2189 + 2190 + snprintf(name, sizeof(name), "atybl%d", info->node); 2191 + 2192 + bd = backlight_device_register(name, par, &aty_bl_data); 2193 + if (IS_ERR(bd)) { 2194 + info->bl_dev = NULL; 2195 + printk("aty: Backlight registration failed\n"); 2196 + goto error; 2197 + } 2198 + 2199 + mutex_lock(&info->bl_mutex); 2200 + info->bl_dev = bd; 2201 + fb_bl_default_curve(info, 0, 2202 + 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, 2203 + 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); 2204 + mutex_unlock(&info->bl_mutex); 2205 + 2206 + up(&bd->sem); 2207 + bd->props->brightness = aty_bl_data.max_brightness; 2208 + bd->props->power = FB_BLANK_UNBLANK; 2209 + bd->props->update_status(bd); 2210 + down(&bd->sem); 2211 + 2212 + #ifdef CONFIG_PMAC_BACKLIGHT 2213 + mutex_lock(&pmac_backlight_mutex); 2214 + if (!pmac_backlight) 2215 + pmac_backlight = bd; 2216 + mutex_unlock(&pmac_backlight_mutex); 2217 + #endif 2218 + 2219 + printk("aty: Backlight initialized (%s)\n", name); 2220 + 2221 + return; 2222 + 2223 + error: 2224 + return; 2225 + } 2226 + 2227 + static void aty_bl_exit(struct atyfb_par *par) 2228 + { 2229 + struct fb_info *info = pci_get_drvdata(par->pdev); 2230 + 2231 + #ifdef CONFIG_PMAC_BACKLIGHT 2232 + mutex_lock(&pmac_backlight_mutex); 2233 + #endif 2234 + 2235 + mutex_lock(&info->bl_mutex); 2236 + if (info->bl_dev) { 2237 + #ifdef CONFIG_PMAC_BACKLIGHT 2238 + if (pmac_backlight == info->bl_dev) 2239 + pmac_backlight = NULL; 2240 + #endif 2241 + 2242 + backlight_device_unregister(info->bl_dev); 2243 + 2244 + printk("aty: Backlight unloaded\n"); 2245 + } 2246 + mutex_unlock(&info->bl_mutex); 2247 + 2248 + #ifdef CONFIG_PMAC_BACKLIGHT 2249 + mutex_unlock(&pmac_backlight_mutex); 2250 + #endif 2251 + } 2252 + 2253 + #endif /* CONFIG_FB_ATY_BACKLIGHT */ 2158 2254 2159 2255 static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) 2160 2256 { ··· 2611 2513 /* these bits let the 101 powerbook wake up from sleep -- paulus */ 2612 2514 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) 2613 2515 | (USE_F32KHZ | TRISTATE_MEM_EN), par); 2614 - } else if (M64_HAS(MOBIL_BUS)) 2615 - register_backlight_controller(&aty_backlight_controller, info, "ati"); 2616 - #endif /* CONFIG_PMAC_BACKLIGHT */ 2516 + } else 2517 + #endif 2518 + if (M64_HAS(MOBIL_BUS)) { 2519 + #ifdef CONFIG_FB_ATY_BACKLIGHT 2520 + aty_bl_init (par); 2521 + #endif 2522 + } 2617 2523 2618 2524 memset(&var, 0, sizeof(var)); 2619 2525 #ifdef CONFIG_PPC ··· 2776 2674 return 0; 2777 2675 2778 2676 #ifdef CONFIG_PMAC_BACKLIGHT 2779 - if (machine_is(powermac) && blank > FB_BLANK_NORMAL) 2780 - set_backlight_enable(0); 2677 + if (machine_is(powermac) && blank > FB_BLANK_NORMAL) { 2678 + mutex_lock(&info->bl_mutex); 2679 + if (info->bl_dev) { 2680 + down(&info->bl_dev->sem); 2681 + info->bl_dev->props->power = FB_BLANK_POWERDOWN; 2682 + info->bl_dev->props->update_status(info->bl_dev); 2683 + up(&info->bl_dev->sem); 2684 + } 2685 + mutex_unlock(&info->bl_mutex); 2686 + } 2781 2687 #elif defined(CONFIG_FB_ATY_GENERIC_LCD) 2782 2688 if (par->lcd_table && blank > FB_BLANK_NORMAL && 2783 2689 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { ··· 2816 2706 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); 2817 2707 2818 2708 #ifdef CONFIG_PMAC_BACKLIGHT 2819 - if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) 2820 - set_backlight_enable(1); 2709 + if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) { 2710 + mutex_lock(&info->bl_mutex); 2711 + if (info->bl_dev) { 2712 + down(&info->bl_dev->sem); 2713 + info->bl_dev->props->power = FB_BLANK_UNBLANK; 2714 + info->bl_dev->props->update_status(info->bl_dev); 2715 + up(&info->bl_dev->sem); 2716 + } 2717 + mutex_unlock(&info->bl_mutex); 2718 + } 2821 2719 #elif defined(CONFIG_FB_ATY_GENERIC_LCD) 2822 2720 if (par->lcd_table && blank <= FB_BLANK_NORMAL && 2823 2721 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { ··· 3558 3440 par->res_start = res_start; 3559 3441 par->res_size = res_size; 3560 3442 par->irq = pdev->irq; 3443 + par->pdev = pdev; 3561 3444 3562 3445 /* Setup "info" structure */ 3563 3446 #ifdef __sparc__ ··· 3689 3570 /* restore video mode */ 3690 3571 aty_set_crtc(par, &saved_crtc); 3691 3572 par->pll_ops->set_pll(info, &saved_pll); 3573 + 3574 + #ifdef CONFIG_FB_ATY_BACKLIGHT 3575 + if (M64_HAS(MOBIL_BUS)) 3576 + aty_bl_exit(par); 3577 + #endif 3692 3578 3693 3579 unregister_framebuffer(info); 3694 3580
+247
drivers/video/aty/radeon_backlight.c
··· 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 + }
+3 -137
drivers/video/aty/radeon_base.c
··· 78 78 #include <asm/pci-bridge.h> 79 79 #include "../macmodes.h" 80 80 81 - #ifdef CONFIG_PMAC_BACKLIGHT 82 - #include <asm/backlight.h> 83 - #endif 84 - 85 81 #ifdef CONFIG_BOOTX_TEXT 86 82 #include <asm/btext.h> 87 83 #endif ··· 272 276 /* 273 277 * prototypes 274 278 */ 275 - 276 - 277 - #ifdef CONFIG_PPC_OF 278 - 279 - #ifdef CONFIG_PMAC_BACKLIGHT 280 - static int radeon_set_backlight_enable(int on, int level, void *data); 281 - static int radeon_set_backlight_level(int level, void *data); 282 - static struct backlight_controller radeon_backlight_controller = { 283 - radeon_set_backlight_enable, 284 - radeon_set_backlight_level 285 - }; 286 - #endif /* CONFIG_PMAC_BACKLIGHT */ 287 - 288 - #endif /* CONFIG_PPC_OF */ 289 279 290 280 static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) 291 281 { ··· 1895 1913 return 0; 1896 1914 } 1897 1915 1898 - 1899 - #ifdef CONFIG_PMAC_BACKLIGHT 1900 - 1901 - /* TODO: Dbl check these tables, we don't go up to full ON backlight 1902 - * in these, possibly because we noticed MacOS doesn't, but I'd prefer 1903 - * having some more official numbers from ATI 1904 - */ 1905 - static int backlight_conv_m6[] = { 1906 - 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, 1907 - 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 1908 - }; 1909 - static int backlight_conv_m7[] = { 1910 - 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81, 1911 - 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9 1912 - }; 1913 - 1914 - #define BACKLIGHT_LVDS_OFF 1915 - #undef BACKLIGHT_DAC_OFF 1916 - 1917 - /* We turn off the LCD completely instead of just dimming the backlight. 1918 - * This provides some greater power saving and the display is useless 1919 - * without backlight anyway. 1920 - */ 1921 - static int radeon_set_backlight_enable(int on, int level, void *data) 1922 - { 1923 - struct radeonfb_info *rinfo = (struct radeonfb_info *)data; 1924 - u32 lvds_gen_cntl, tmpPixclksCntl; 1925 - int* conv_table; 1926 - 1927 - if (rinfo->mon1_type != MT_LCD) 1928 - return 0; 1929 - 1930 - /* Pardon me for that hack... maybe some day we can figure 1931 - * out in what direction backlight should work on a given 1932 - * panel ? 1933 - */ 1934 - if ((rinfo->family == CHIP_FAMILY_RV200 || 1935 - rinfo->family == CHIP_FAMILY_RV250 || 1936 - rinfo->family == CHIP_FAMILY_RV280 || 1937 - rinfo->family == CHIP_FAMILY_RV350) && 1938 - !machine_is_compatible("PowerBook4,3") && 1939 - !machine_is_compatible("PowerBook6,3") && 1940 - !machine_is_compatible("PowerBook6,5")) 1941 - conv_table = backlight_conv_m7; 1942 - else 1943 - conv_table = backlight_conv_m6; 1944 - 1945 - del_timer_sync(&rinfo->lvds_timer); 1946 - radeon_engine_idle(); 1947 - 1948 - lvds_gen_cntl = INREG(LVDS_GEN_CNTL); 1949 - if (on && (level > BACKLIGHT_OFF)) { 1950 - lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; 1951 - if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { 1952 - lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); 1953 - lvds_gen_cntl |= LVDS_BLON | LVDS_EN; 1954 - OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); 1955 - lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; 1956 - lvds_gen_cntl |= (conv_table[level] << 1957 - LVDS_BL_MOD_LEVEL_SHIFT); 1958 - lvds_gen_cntl |= LVDS_ON; 1959 - lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); 1960 - rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; 1961 - mod_timer(&rinfo->lvds_timer, 1962 - jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); 1963 - } else { 1964 - lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; 1965 - lvds_gen_cntl |= (conv_table[level] << 1966 - LVDS_BL_MOD_LEVEL_SHIFT); 1967 - OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); 1968 - } 1969 - rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; 1970 - rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl 1971 - & LVDS_STATE_MASK; 1972 - } else { 1973 - /* Asic bug, when turning off LVDS_ON, we have to make sure 1974 - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off 1975 - */ 1976 - tmpPixclksCntl = INPLL(PIXCLKS_CNTL); 1977 - if (rinfo->is_mobility || rinfo->is_IGP) 1978 - OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); 1979 - lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); 1980 - lvds_gen_cntl |= (conv_table[0] << 1981 - LVDS_BL_MOD_LEVEL_SHIFT); 1982 - lvds_gen_cntl |= LVDS_DISPLAY_DIS; 1983 - OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); 1984 - udelay(100); 1985 - lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); 1986 - OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); 1987 - lvds_gen_cntl &= ~(LVDS_DIGON); 1988 - rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; 1989 - mod_timer(&rinfo->lvds_timer, 1990 - jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); 1991 - if (rinfo->is_mobility || rinfo->is_IGP) 1992 - OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); 1993 - } 1994 - rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; 1995 - rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); 1996 - 1997 - return 0; 1998 - } 1999 - 2000 - 2001 - static int radeon_set_backlight_level(int level, void *data) 2002 - { 2003 - return radeon_set_backlight_enable(1, level, data); 2004 - } 2005 - #endif /* CONFIG_PMAC_BACKLIGHT */ 2006 - 2007 - 2008 1916 /* 2009 1917 * This reconfigure the card's internal memory map. In theory, we'd like 2010 1918 * to setup the card's memory at the same address as it's PCI bus address, ··· 2349 2477 MTRR_TYPE_WRCOMB, 1); 2350 2478 #endif 2351 2479 2352 - #ifdef CONFIG_PMAC_BACKLIGHT 2353 - if (rinfo->mon1_type == MT_LCD) { 2354 - register_backlight_controller(&radeon_backlight_controller, 2355 - rinfo, "ati"); 2356 - register_backlight_controller(&radeon_backlight_controller, 2357 - rinfo, "mnca"); 2358 - } 2359 - #endif 2480 + radeonfb_bl_init(rinfo); 2360 2481 2361 2482 printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); 2362 2483 ··· 2393 2528 2394 2529 if (!rinfo) 2395 2530 return; 2396 - 2531 + 2532 + radeonfb_bl_exit(rinfo); 2397 2533 radeonfb_pm_exit(rinfo); 2398 2534 2399 2535 if (rinfo->mon1_EDID)
+9
drivers/video/aty/radeonfb.h
··· 625 625 extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, 626 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 637 #endif /* __RADEONFB_H__ */
+26 -4
drivers/video/chipsfb.c
··· 148 148 static int chipsfb_blank(int blank, struct fb_info *info) 149 149 { 150 150 #ifdef CONFIG_PMAC_BACKLIGHT 151 - // used to disable backlight only for blank > 1, but it seems 152 - // useful at blank = 1 too (saves battery, extends backlight life) 153 - set_backlight_enable(!blank); 151 + mutex_lock(&pmac_backlight_mutex); 152 + 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 169 #endif /* CONFIG_PMAC_BACKLIGHT */ 155 170 156 171 return 1; /* get fb_blank to set the colormap to all black */ ··· 416 401 417 402 #ifdef CONFIG_PMAC_BACKLIGHT 418 403 /* turn on the backlight */ 419 - set_backlight_enable(1); 404 + mutex_lock(&pmac_backlight_mutex); 405 + if (pmac_backlight) { 406 + down(&pmac_backlight->sem); 407 + pmac_backlight->props->power = FB_BLANK_UNBLANK; 408 + pmac_backlight->props->update_status(pmac_backlight); 409 + up(&pmac_backlight->sem); 410 + } 411 + mutex_unlock(&pmac_backlight_mutex); 420 412 #endif /* CONFIG_PMAC_BACKLIGHT */ 421 413 422 414 #ifdef CONFIG_PPC
+88
drivers/video/fbsysfs.c
··· 18 18 #include <linux/kernel.h> 19 19 #include <linux/fb.h> 20 20 #include <linux/console.h> 21 + #include <linux/module.h> 21 22 22 23 /** 23 24 * framebuffer_alloc - creates a new frame buffer info structure ··· 55 54 info->par = p + fb_info_size; 56 55 57 56 info->device = dev; 57 + 58 + #ifdef CONFIG_FB_BACKLIGHT 59 + mutex_init(&info->bl_mutex); 60 + #endif 58 61 59 62 return info; 60 63 #undef PADDING ··· 419 414 return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); 420 415 } 421 416 417 + #ifdef CONFIG_FB_BACKLIGHT 418 + static ssize_t store_bl_curve(struct class_device *class_device, 419 + const char *buf, size_t count) 420 + { 421 + struct fb_info *fb_info = class_get_devdata(class_device); 422 + u8 tmp_curve[FB_BACKLIGHT_LEVELS]; 423 + unsigned int i; 424 + 425 + if (count != (FB_BACKLIGHT_LEVELS / 8 * 24)) 426 + return -EINVAL; 427 + 428 + for (i = 0; i < (FB_BACKLIGHT_LEVELS / 8); ++i) 429 + if (sscanf(&buf[i * 24], 430 + "%2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx\n", 431 + &tmp_curve[i * 8 + 0], 432 + &tmp_curve[i * 8 + 1], 433 + &tmp_curve[i * 8 + 2], 434 + &tmp_curve[i * 8 + 3], 435 + &tmp_curve[i * 8 + 4], 436 + &tmp_curve[i * 8 + 5], 437 + &tmp_curve[i * 8 + 6], 438 + &tmp_curve[i * 8 + 7]) != 8) 439 + return -EINVAL; 440 + 441 + /* If there has been an error in the input data, we won't 442 + * reach this loop. 443 + */ 444 + mutex_lock(&fb_info->bl_mutex); 445 + for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i) 446 + fb_info->bl_curve[i] = tmp_curve[i]; 447 + mutex_unlock(&fb_info->bl_mutex); 448 + 449 + return count; 450 + } 451 + 452 + static ssize_t show_bl_curve(struct class_device *class_device, char *buf) 453 + { 454 + struct fb_info *fb_info = class_get_devdata(class_device); 455 + ssize_t len = 0; 456 + unsigned int i; 457 + 458 + mutex_lock(&fb_info->bl_mutex); 459 + for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8) 460 + len += snprintf(&buf[len], PAGE_SIZE, 461 + "%02x %02x %02x %02x %02x %02x %02x %02x\n", 462 + fb_info->bl_curve[i + 0], 463 + fb_info->bl_curve[i + 1], 464 + fb_info->bl_curve[i + 2], 465 + fb_info->bl_curve[i + 3], 466 + fb_info->bl_curve[i + 4], 467 + fb_info->bl_curve[i + 5], 468 + fb_info->bl_curve[i + 6], 469 + fb_info->bl_curve[i + 7]); 470 + mutex_unlock(&fb_info->bl_mutex); 471 + 472 + return len; 473 + } 474 + #endif 475 + 422 476 /* When cmap is added back in it should be a binary attribute 423 477 * not a text one. Consideration should also be given to converting 424 478 * fbdev to use configfs instead of sysfs */ ··· 496 432 __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), 497 433 __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), 498 434 __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate), 435 + #ifdef CONFIG_FB_BACKLIGHT 436 + __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve), 437 + #endif 499 438 }; 500 439 501 440 int fb_init_class_device(struct fb_info *fb_info) ··· 521 454 &class_device_attrs[i]); 522 455 } 523 456 457 + #ifdef CONFIG_FB_BACKLIGHT 458 + /* This function generates a linear backlight curve 459 + * 460 + * 0: off 461 + * 1-7: min 462 + * 8-127: linear from min to max 463 + */ 464 + void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max) 465 + { 466 + unsigned int i, flat, count, range = (max - min); 524 467 468 + fb_info->bl_curve[0] = off; 469 + 470 + for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) 471 + fb_info->bl_curve[flat] = min; 472 + 473 + count = FB_BACKLIGHT_LEVELS * 15 / 16; 474 + for (i = 0; i < count; ++i) 475 + fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count); 476 + } 477 + EXPORT_SYMBOL_GPL(fb_bl_default_curve); 478 + #endif
+1
drivers/video/nvidia/Makefile
··· 7 7 nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \ 8 8 nv_accel.o 9 9 nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o 10 + nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT) += nv_backlight.o 10 11 nvidiafb-$(CONFIG_PPC_OF) += nv_of.o 11 12 12 13 nvidiafb-objs := $(nvidiafb-y)
+175
drivers/video/nvidia/nv_backlight.c
··· 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 + }
+10
drivers/video/nvidia/nv_proto.h
··· 63 63 const struct fb_image *image); 64 64 extern int nvidiafb_sync(struct fb_info *info); 65 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 76 #endif /* __NV_PROTO_H__ */
+14 -81
drivers/video/nvidia/nvidia.c
··· 22 22 #include <linux/init.h> 23 23 #include <linux/pci.h> 24 24 #include <linux/console.h> 25 + #include <linux/backlight.h> 25 26 #ifdef CONFIG_MTRR 26 27 #include <asm/mtrr.h> 27 28 #endif 28 29 #ifdef CONFIG_PPC_OF 29 30 #include <asm/prom.h> 30 31 #include <asm/pci-bridge.h> 31 - #endif 32 - #ifdef CONFIG_PMAC_BACKLIGHT 33 - #include <asm/machdep.h> 34 - #include <asm/backlight.h> 35 32 #endif 36 33 37 34 #include "nv_local.h" ··· 466 469 .vsync_len = 2, 467 470 .vmode = FB_VMODE_NONINTERLACED 468 471 }; 469 - 470 - /* 471 - * Backlight control 472 - */ 473 - #ifdef CONFIG_PMAC_BACKLIGHT 474 - 475 - static int nvidia_backlight_levels[] = { 476 - 0x158, 477 - 0x192, 478 - 0x1c6, 479 - 0x200, 480 - 0x234, 481 - 0x268, 482 - 0x2a2, 483 - 0x2d6, 484 - 0x310, 485 - 0x344, 486 - 0x378, 487 - 0x3b2, 488 - 0x3e6, 489 - 0x41a, 490 - 0x454, 491 - 0x534, 492 - }; 493 - 494 - /* ------------------------------------------------------------------------- * 495 - * 496 - * Backlight operations 497 - * 498 - * ------------------------------------------------------------------------- */ 499 - 500 - static int nvidia_set_backlight_enable(int on, int level, void *data) 501 - { 502 - struct nvidia_par *par = data; 503 - u32 tmp_pcrt, tmp_pmc, fpcontrol; 504 - 505 - tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; 506 - tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; 507 - fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC; 508 - 509 - if (on && (level > BACKLIGHT_OFF)) { 510 - tmp_pcrt |= 0x1; 511 - tmp_pmc |= (1 << 31); // backlight bit 512 - tmp_pmc |= nvidia_backlight_levels[level - 1] << 16; 513 - } 514 - 515 - if (on) 516 - fpcontrol |= par->fpSyncs; 517 - else 518 - fpcontrol |= 0x20000022; 519 - 520 - NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt); 521 - NV_WR32(par->PMC, 0x10F0, tmp_pmc); 522 - NV_WR32(par->PRAMDAC, 0x848, fpcontrol); 523 - 524 - return 0; 525 - } 526 - 527 - static int nvidia_set_backlight_level(int level, void *data) 528 - { 529 - return nvidia_set_backlight_enable(1, level, data); 530 - } 531 - 532 - static struct backlight_controller nvidia_backlight_controller = { 533 - nvidia_set_backlight_enable, 534 - nvidia_set_backlight_level 535 - }; 536 - 537 - #endif /* CONFIG_PMAC_BACKLIGHT */ 538 472 539 473 static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8, 540 474 u16 bg, u16 fg, u32 w, u32 h) ··· 1283 1355 NVWriteSeq(par, 0x01, tmp); 1284 1356 NVWriteCrtc(par, 0x1a, vesa); 1285 1357 1286 - #ifdef CONFIG_PMAC_BACKLIGHT 1287 - if (par->FlatPanel && machine_is(powermac)) { 1288 - set_backlight_enable(!blank); 1358 + #ifdef CONFIG_FB_NVIDIA_BACKLIGHT 1359 + mutex_lock(&info->bl_mutex); 1360 + if (info->bl_dev) { 1361 + down(&info->bl_dev->sem); 1362 + info->bl_dev->props->power = blank; 1363 + info->bl_dev->props->update_status(info->bl_dev); 1364 + up(&info->bl_dev->sem); 1289 1365 } 1366 + mutex_unlock(&info->bl_mutex); 1290 1367 #endif 1291 1368 1292 1369 NVTRACE_LEAVE(); ··· 1674 1741 "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n", 1675 1742 info->fix.id, 1676 1743 par->FbMapSize / (1024 * 1024), info->fix.smem_start); 1677 - #ifdef CONFIG_PMAC_BACKLIGHT 1678 - if (par->FlatPanel && machine_is(powermac)) 1679 - register_backlight_controller(&nvidia_backlight_controller, 1680 - par, "mnca"); 1681 - #endif 1744 + 1745 + nvidia_bl_init(par); 1746 + 1682 1747 NVTRACE_LEAVE(); 1683 1748 return 0; 1684 1749 ··· 1705 1774 struct nvidia_par *par = info->par; 1706 1775 1707 1776 NVTRACE_ENTER(); 1777 + 1778 + nvidia_bl_exit(par); 1708 1779 1709 1780 unregister_framebuffer(info); 1710 1781 #ifdef CONFIG_MTRR
+159 -63
drivers/video/riva/fbdev.c
··· 41 41 #include <linux/fb.h> 42 42 #include <linux/init.h> 43 43 #include <linux/pci.h> 44 + #include <linux/backlight.h> 44 45 #ifdef CONFIG_MTRR 45 46 #include <asm/mtrr.h> 46 47 #endif ··· 273 272 /* 274 273 * Backlight control 275 274 */ 275 + #ifdef CONFIG_FB_RIVA_BACKLIGHT 276 + /* We do not have any information about which values are allowed, thus 277 + * we used safe values. 278 + */ 279 + #define MIN_LEVEL 0x158 280 + #define MAX_LEVEL 0x534 281 + 282 + static struct backlight_properties riva_bl_data; 283 + 284 + static int riva_bl_get_level_brightness(struct riva_par *par, 285 + int level) 286 + { 287 + struct fb_info *info = pci_get_drvdata(par->pdev); 288 + int nlevel; 289 + 290 + /* Get and convert the value */ 291 + mutex_lock(&info->bl_mutex); 292 + nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; 293 + mutex_unlock(&info->bl_mutex); 294 + 295 + if (nlevel < 0) 296 + nlevel = 0; 297 + else if (nlevel < MIN_LEVEL) 298 + nlevel = MIN_LEVEL; 299 + else if (nlevel > MAX_LEVEL) 300 + nlevel = MAX_LEVEL; 301 + 302 + return nlevel; 303 + } 304 + 305 + static int riva_bl_update_status(struct backlight_device *bd) 306 + { 307 + struct riva_par *par = class_get_devdata(&bd->class_dev); 308 + U032 tmp_pcrt, tmp_pmc; 309 + int level; 310 + 311 + if (bd->props->power != FB_BLANK_UNBLANK || 312 + bd->props->fb_blank != FB_BLANK_UNBLANK) 313 + level = 0; 314 + else 315 + level = bd->props->brightness; 316 + 317 + tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; 318 + tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC; 319 + if(level > 0) { 320 + tmp_pcrt |= 0x1; 321 + tmp_pmc |= (1 << 31); /* backlight bit */ 322 + tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */ 323 + } 324 + par->riva.PCRTC0[0x081C/4] = tmp_pcrt; 325 + par->riva.PMC[0x10F0/4] = tmp_pmc; 326 + 327 + return 0; 328 + } 329 + 330 + static int riva_bl_get_brightness(struct backlight_device *bd) 331 + { 332 + return bd->props->brightness; 333 + } 334 + 335 + static struct backlight_properties riva_bl_data = { 336 + .owner = THIS_MODULE, 337 + .get_brightness = riva_bl_get_brightness, 338 + .update_status = riva_bl_update_status, 339 + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), 340 + }; 341 + 342 + static void riva_bl_init(struct riva_par *par) 343 + { 344 + struct fb_info *info = pci_get_drvdata(par->pdev); 345 + struct backlight_device *bd; 346 + char name[12]; 347 + 348 + if (!par->FlatPanel) 349 + return; 350 + 276 351 #ifdef CONFIG_PMAC_BACKLIGHT 352 + if (!machine_is(powermac) || 353 + !pmac_has_backlight_type("mnca")) 354 + return; 355 + #endif 277 356 278 - static int riva_backlight_levels[] = { 279 - 0x158, 280 - 0x192, 281 - 0x1c6, 282 - 0x200, 283 - 0x234, 284 - 0x268, 285 - 0x2a2, 286 - 0x2d6, 287 - 0x310, 288 - 0x344, 289 - 0x378, 290 - 0x3b2, 291 - 0x3e6, 292 - 0x41a, 293 - 0x454, 294 - 0x534, 295 - }; 357 + snprintf(name, sizeof(name), "rivabl%d", info->node); 296 358 297 - static int riva_set_backlight_enable(int on, int level, void *data); 298 - static int riva_set_backlight_level(int level, void *data); 299 - static struct backlight_controller riva_backlight_controller = { 300 - riva_set_backlight_enable, 301 - riva_set_backlight_level 302 - }; 303 - #endif /* CONFIG_PMAC_BACKLIGHT */ 359 + bd = backlight_device_register(name, par, &riva_bl_data); 360 + if (IS_ERR(bd)) { 361 + info->bl_dev = NULL; 362 + printk("riva: Backlight registration failed\n"); 363 + goto error; 364 + } 365 + 366 + mutex_lock(&info->bl_mutex); 367 + info->bl_dev = bd; 368 + fb_bl_default_curve(info, 0, 369 + 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, 370 + 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); 371 + mutex_unlock(&info->bl_mutex); 372 + 373 + up(&bd->sem); 374 + bd->props->brightness = riva_bl_data.max_brightness; 375 + bd->props->power = FB_BLANK_UNBLANK; 376 + bd->props->update_status(bd); 377 + down(&bd->sem); 378 + 379 + #ifdef CONFIG_PMAC_BACKLIGHT 380 + mutex_lock(&pmac_backlight_mutex); 381 + if (!pmac_backlight) 382 + pmac_backlight = bd; 383 + mutex_unlock(&pmac_backlight_mutex); 384 + #endif 385 + 386 + printk("riva: Backlight initialized (%s)\n", name); 387 + 388 + return; 389 + 390 + error: 391 + return; 392 + } 393 + 394 + static void riva_bl_exit(struct riva_par *par) 395 + { 396 + struct fb_info *info = pci_get_drvdata(par->pdev); 397 + 398 + #ifdef CONFIG_PMAC_BACKLIGHT 399 + mutex_lock(&pmac_backlight_mutex); 400 + #endif 401 + 402 + mutex_lock(&info->bl_mutex); 403 + if (info->bl_dev) { 404 + #ifdef CONFIG_PMAC_BACKLIGHT 405 + if (pmac_backlight == info->bl_dev) 406 + pmac_backlight = NULL; 407 + #endif 408 + 409 + backlight_device_unregister(info->bl_dev); 410 + 411 + printk("riva: Backlight unloaded\n"); 412 + } 413 + mutex_unlock(&info->bl_mutex); 414 + 415 + #ifdef CONFIG_PMAC_BACKLIGHT 416 + mutex_unlock(&pmac_backlight_mutex); 417 + #endif 418 + } 419 + #else 420 + static inline void riva_bl_init(struct riva_par *par) {} 421 + static inline void riva_bl_exit(struct riva_par *par) {} 422 + #endif /* CONFIG_FB_RIVA_BACKLIGHT */ 304 423 305 424 /* ------------------------------------------------------------------------- * 306 425 * ··· 1094 973 1095 974 /* ------------------------------------------------------------------------- * 1096 975 * 1097 - * Backlight operations 1098 - * 1099 - * ------------------------------------------------------------------------- */ 1100 - 1101 - #ifdef CONFIG_PMAC_BACKLIGHT 1102 - static int riva_set_backlight_enable(int on, int level, void *data) 1103 - { 1104 - struct riva_par *par = data; 1105 - U032 tmp_pcrt, tmp_pmc; 1106 - 1107 - tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; 1108 - tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC; 1109 - if(on && (level > BACKLIGHT_OFF)) { 1110 - tmp_pcrt |= 0x1; 1111 - tmp_pmc |= (1 << 31); // backlight bit 1112 - tmp_pmc |= riva_backlight_levels[level-1] << 16; // level 1113 - } 1114 - par->riva.PCRTC0[0x081C/4] = tmp_pcrt; 1115 - par->riva.PMC[0x10F0/4] = tmp_pmc; 1116 - return 0; 1117 - } 1118 - 1119 - static int riva_set_backlight_level(int level, void *data) 1120 - { 1121 - return riva_set_backlight_enable(1, level, data); 1122 - } 1123 - #endif /* CONFIG_PMAC_BACKLIGHT */ 1124 - 1125 - /* ------------------------------------------------------------------------- * 1126 - * 1127 976 * framebuffer operations 1128 977 * 1129 978 * ------------------------------------------------------------------------- */ ··· 1338 1247 SEQout(par, 0x01, tmp); 1339 1248 CRTCout(par, 0x1a, vesa); 1340 1249 1341 - #ifdef CONFIG_PMAC_BACKLIGHT 1342 - if ( par->FlatPanel && machine_is(powermac)) { 1343 - set_backlight_enable(!blank); 1250 + #ifdef CONFIG_FB_RIVA_BACKLIGHT 1251 + mutex_lock(&info->bl_mutex); 1252 + if (info->bl_dev) { 1253 + down(&info->bl_dev->sem); 1254 + info->bl_dev->props->power = blank; 1255 + info->bl_dev->props->update_status(info->bl_dev); 1256 + up(&info->bl_dev->sem); 1344 1257 } 1258 + mutex_unlock(&info->bl_mutex); 1345 1259 #endif 1346 1260 1347 1261 NVTRACE_LEAVE(); ··· 2133 2037 RIVAFB_VERSION, 2134 2038 info->fix.smem_len / (1024 * 1024), 2135 2039 info->fix.smem_start); 2136 - #ifdef CONFIG_PMAC_BACKLIGHT 2137 - if (default_par->FlatPanel && machine_is(powermac)) 2138 - register_backlight_controller(&riva_backlight_controller, 2139 - default_par, "mnca"); 2140 - #endif 2040 + 2041 + riva_bl_init(info->par); 2042 + 2141 2043 NVTRACE_LEAVE(); 2142 2044 return 0; 2143 2045 ··· 2167 2073 struct riva_par *par = info->par; 2168 2074 2169 2075 NVTRACE_ENTER(); 2076 + 2077 + riva_bl_exit(par); 2170 2078 2171 2079 #ifdef CONFIG_FB_RIVA_I2C 2172 2080 riva_delete_i2c_busses(par);
+15 -15
include/asm-powerpc/backlight.h
··· 2 2 * Routines for handling backlight control on PowerBooks 3 3 * 4 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 8 #ifndef __ASM_POWERPC_BACKLIGHT_H 9 9 #define __ASM_POWERPC_BACKLIGHT_H 10 10 #ifdef __KERNEL__ 11 11 12 - /* Abstract values */ 13 - #define BACKLIGHT_OFF 0 14 - #define BACKLIGHT_MIN 1 15 - #define BACKLIGHT_MAX 0xf 12 + #include <linux/fb.h> 13 + #include <linux/mutex.h> 16 14 17 - struct backlight_controller { 18 - int (*set_enable)(int enable, int level, void *data); 19 - int (*set_level)(int level, void *data); 20 - }; 15 + /* For locking instructions, see the implementation file */ 16 + extern struct backlight_device *pmac_backlight; 17 + extern struct mutex pmac_backlight_mutex; 21 18 22 - extern void register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type); 23 - extern void unregister_backlight_controller(struct backlight_controller *ctrler, void *data); 19 + extern void pmac_backlight_calc_curve(struct fb_info*); 20 + extern int pmac_backlight_curve_lookup(struct fb_info *info, int value); 24 21 25 - extern int set_backlight_enable(int enable); 26 - extern int get_backlight_enable(void); 27 - extern int set_backlight_level(int level); 28 - extern int get_backlight_level(void); 22 + extern int pmac_has_backlight_type(const char *type); 23 + 24 + extern void pmac_backlight_key_up(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 30 #endif /* __KERNEL__ */ 31 31 #endif
+23
include/linux/fb.h
··· 1 1 #ifndef _LINUX_FB_H 2 2 #define _LINUX_FB_H 3 3 4 + #include <linux/backlight.h> 4 5 #include <asm/types.h> 5 6 6 7 /* Definitions of frame buffers */ ··· 366 365 struct fbcurpos hot; /* cursor hot spot */ 367 366 struct fb_image image; /* Cursor image */ 368 367 }; 368 + 369 + #ifdef CONFIG_FB_BACKLIGHT 370 + /* Settings for the generic backlight code */ 371 + #define FB_BACKLIGHT_LEVELS 128 372 + #define FB_BACKLIGHT_MAX 0xFF 373 + #endif 369 374 370 375 #ifdef __KERNEL__ 371 376 ··· 763 756 struct fb_cmap cmap; /* Current cmap */ 764 757 struct list_head modelist; /* mode list */ 765 758 struct fb_videomode *mode; /* current mode */ 759 + 760 + #ifdef CONFIG_FB_BACKLIGHT 761 + /* Lock ordering: 762 + * bl_mutex (protects bl_dev and bl_curve) 763 + * bl_dev->sem (backlight class) 764 + */ 765 + struct mutex bl_mutex; 766 + 767 + /* assigned backlight device */ 768 + struct backlight_device *bl_dev; 769 + 770 + /* Backlight level curve */ 771 + u8 bl_curve[FB_BACKLIGHT_LEVELS]; 772 + #endif 773 + 766 774 struct fb_ops *fbops; 767 775 struct device *device; 768 776 struct class_device *class_device; /* sysfs per device attrs */ ··· 917 895 extern void framebuffer_release(struct fb_info *info); 918 896 extern int fb_init_class_device(struct fb_info *fb_info); 919 897 extern void fb_cleanup_class_device(struct fb_info *head); 898 + extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max); 920 899 921 900 /* drivers/video/fbmon.c */ 922 901 #define FB_MAXTIMINGS 0
+4
include/linux/pmu.h
··· 230 230 extern struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; 231 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 237 #endif /* __KERNEL__ */