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

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.12 202 lines 4.7 kB view raw
1/* 2 * Miscellaneous procedures for dealing with the PowerMac hardware. 3 * Contains support for the backlight. 4 * 5 * Copyright (C) 2000 Benjamin Herrenschmidt 6 * 7 */ 8 9#include <linux/config.h> 10#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> 21#include <asm/prom.h> 22#include <asm/machdep.h> 23#include <asm/nvram.h> 24#include <asm/backlight.h> 25 26#include <linux/adb.h> 27#include <linux/pmu.h> 28 29static struct backlight_controller *backlighter; 30static void* backlighter_data; 31static int backlight_autosave; 32static int backlight_level = BACKLIGHT_MAX; 33static int backlight_enabled = 1; 34static int backlight_req_level = -1; 35static int backlight_req_enable = -1; 36 37static void backlight_callback(void *); 38static DECLARE_WORK(backlight_work, backlight_callback, NULL); 39 40void __pmac register_backlight_controller(struct backlight_controller *ctrler, 41 void *data, char *type) 42{ 43 struct device_node* bk_node; 44 char *prop; 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) { 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; 81 } 82 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} 100EXPORT_SYMBOL(register_backlight_controller); 101 102void __pmac 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} 109EXPORT_SYMBOL(unregister_backlight_controller); 110 111static int __pmac __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} 125int __pmac set_backlight_enable(int enable) 126{ 127 if (!backlighter) 128 return -ENODEV; 129 backlight_req_enable = enable; 130 schedule_work(&backlight_work); 131 return 0; 132} 133 134EXPORT_SYMBOL(set_backlight_enable); 135 136int __pmac get_backlight_enable(void) 137{ 138 if (!backlighter) 139 return -ENODEV; 140 return backlight_enabled; 141} 142EXPORT_SYMBOL(get_backlight_enable); 143 144static int __pmac __set_backlight_level(int level) 145{ 146 int rc = 0; 147 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" 165 } 166 return rc; 167} 168int __pmac 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; 175} 176 177EXPORT_SYMBOL(set_backlight_level); 178 179int __pmac get_backlight_level(void) 180{ 181 if (!backlighter) 182 return -ENODEV; 183 return backlight_level; 184} 185EXPORT_SYMBOL(get_backlight_level); 186 187static void backlight_callback(void *dummy) 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}