ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ppc / platforms / pmac_backlight.c
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 <asm/sections.h>
16 #include <asm/ptrace.h>
17 #include <asm/io.h>
18 #include <asm/pgtable.h>
19 #include <asm/system.h>
20 #include <asm/prom.h>
21 #include <asm/machdep.h>
22 #include <asm/nvram.h>
23 #include <asm/backlight.h>
24
25 #include <linux/adb.h>
26 #include <linux/pmu.h>
27
28 static struct backlight_controller *backlighter = NULL;
29 static void* backlighter_data = NULL;
30 static int backlight_autosave = 0;
31 static int backlight_level = BACKLIGHT_MAX;
32 static int backlight_enabled = 1;
33
34 void __pmac
35 register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type)
36 {
37         struct device_node* bk_node;
38         char *prop;
39         int valid = 0;
40
41         /* There's already a matching controller, bail out */
42         if (backlighter != NULL)
43                 return;
44
45         bk_node = find_devices("backlight");
46
47 #ifdef CONFIG_ADB_PMU
48         /* Special case for the old PowerBook since I can't test on it */
49         backlight_autosave = machine_is_compatible("AAPL,3400/2400")
50                 || machine_is_compatible("AAPL,3500");
51         if ((backlight_autosave
52              || machine_is_compatible("AAPL,PowerBook1998")
53              || machine_is_compatible("PowerBook1,1"))
54             && !strcmp(type, "pmu"))
55                 valid = 1;
56 #endif
57         if (bk_node) {
58                 prop = get_property(bk_node, "backlight-control", NULL);
59                 if (prop && !strncmp(prop, type, strlen(type)))
60                         valid = 1;
61         }
62         if (!valid)
63                 return;
64         backlighter = ctrler;
65         backlighter_data = data;
66
67         if (bk_node && !backlight_autosave)
68                 prop = get_property(bk_node, "bklt", NULL);
69         else
70                 prop = NULL;
71         if (prop) {
72                 backlight_level = ((*prop)+1) >> 1;
73                 if (backlight_level > BACKLIGHT_MAX)
74                         backlight_level = BACKLIGHT_MAX;
75         }
76
77 #ifdef CONFIG_ADB_PMU
78         if (backlight_autosave) {
79                 struct adb_request req;
80                 pmu_request(&req, NULL, 2, 0xd9, 0);
81                 while (!req.complete)
82                         pmu_poll();
83                 backlight_level = req.reply[0] >> 4;
84         }
85 #endif
86         if (!backlighter->set_enable(1, backlight_level, data))
87                 backlight_enabled = 1;
88
89         printk(KERN_INFO "Registered \"%s\" backlight controller, level: %d/15\n",
90                 type, backlight_level);
91 }
92 EXPORT_SYMBOL(register_backlight_controller);
93
94 void __pmac
95 unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
96 {
97         /* We keep the current backlight level (for now) */
98         if (ctrler == backlighter && data == backlighter_data)
99                 backlighter = NULL;
100 }
101 EXPORT_SYMBOL(unregister_backlight_controller);
102
103 int __pmac
104 set_backlight_enable(int enable)
105 {
106         int rc;
107
108         if (!backlighter)
109                 return -ENODEV;
110         rc = backlighter->set_enable(enable, backlight_level, backlighter_data);
111         if (!rc)
112                 backlight_enabled = enable;
113         return rc;
114 }
115 EXPORT_SYMBOL(set_backlight_enable);
116
117 int __pmac
118 get_backlight_enable(void)
119 {
120         if (!backlighter)
121                 return -ENODEV;
122         return backlight_enabled;
123 }
124 EXPORT_SYMBOL(get_backlight_enable);
125
126 int __pmac
127 set_backlight_level(int level)
128 {
129         int rc = 0;
130
131         if (!backlighter)
132                 return -ENODEV;
133         if (level < BACKLIGHT_MIN)
134                 level = BACKLIGHT_OFF;
135         if (level > BACKLIGHT_MAX)
136                 level = BACKLIGHT_MAX;
137         if (backlight_enabled)
138                 rc = backlighter->set_level(level, backlighter_data);
139         if (!rc)
140                 backlight_level = level;
141         if (!rc && !backlight_autosave) {
142                 level <<=1;
143                 if (level & 0x10)
144                         level |= 0x01;
145                 // -- todo: save to property "bklt"
146         }
147         return rc;
148 }
149 EXPORT_SYMBOL(set_backlight_level);
150
151 int __pmac
152 get_backlight_level(void)
153 {
154         if (!backlighter)
155                 return -ENODEV;
156         return backlight_level;
157 }
158 EXPORT_SYMBOL(get_backlight_level);