2 * Miscellaneous procedures for dealing with the PowerMac hardware.
3 * Contains support for the backlight.
5 * Copyright (C) 2000 Benjamin Herrenschmidt
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>
19 #include <asm/pgtable.h>
20 #include <asm/system.h>
22 #include <asm/machdep.h>
23 #include <asm/nvram.h>
24 #include <asm/backlight.h>
26 #include <linux/adb.h>
27 #include <linux/pmu.h>
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;
37 static void backlight_callback(void *);
38 static DECLARE_WORK(backlight_work
, backlight_callback
, NULL
);
40 void __pmac
register_backlight_controller(struct backlight_controller
*ctrler
,
41 void *data
, char *type
)
43 struct device_node
* bk_node
;
47 /* There's already a matching controller, bail out */
48 if (backlighter
!= NULL
)
51 bk_node
= find_devices("backlight");
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"))
64 prop
= get_property(bk_node
, "backlight-control", NULL
);
65 if (prop
&& !strncmp(prop
, type
, strlen(type
)))
71 backlighter_data
= data
;
73 if (bk_node
&& !backlight_autosave
)
74 prop
= get_property(bk_node
, "bklt", NULL
);
78 backlight_level
= ((*prop
)+1) >> 1;
79 if (backlight_level
> BACKLIGHT_MAX
)
80 backlight_level
= BACKLIGHT_MAX
;
84 if (backlight_autosave
) {
85 struct adb_request req
;
86 pmu_request(&req
, NULL
, 2, 0xd9, 0);
89 backlight_level
= req
.reply
[0] >> 4;
92 acquire_console_sem();
93 if (!backlighter
->set_enable(1, backlight_level
, data
))
94 backlight_enabled
= 1;
95 release_console_sem();
97 printk(KERN_INFO
"Registered \"%s\" backlight controller,"
98 "level: %d/15\n", type
, backlight_level
);
100 EXPORT_SYMBOL(register_backlight_controller
);
102 void __pmac
unregister_backlight_controller(struct backlight_controller
105 /* We keep the current backlight level (for now) */
106 if (ctrler
== backlighter
&& data
== backlighter_data
)
109 EXPORT_SYMBOL(unregister_backlight_controller
);
111 static int __pmac
__set_backlight_enable(int enable
)
117 acquire_console_sem();
118 rc
= backlighter
->set_enable(enable
, backlight_level
,
121 backlight_enabled
= enable
;
122 release_console_sem();
125 int __pmac
set_backlight_enable(int enable
)
129 backlight_req_enable
= enable
;
130 schedule_work(&backlight_work
);
134 EXPORT_SYMBOL(set_backlight_enable
);
136 int __pmac
get_backlight_enable(void)
140 return backlight_enabled
;
142 EXPORT_SYMBOL(get_backlight_enable
);
144 static int __pmac
__set_backlight_level(int level
)
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
);
158 backlight_level
= level
;
159 release_console_sem();
160 if (!rc
&& !backlight_autosave
) {
164 // -- todo: save to property "bklt"
168 int __pmac
set_backlight_level(int level
)
172 backlight_req_level
= level
;
173 schedule_work(&backlight_work
);
177 EXPORT_SYMBOL(set_backlight_level
);
179 int __pmac
get_backlight_level(void)
183 return backlight_level
;
185 EXPORT_SYMBOL(get_backlight_level
);
187 static void backlight_callback(void *dummy
)
192 level
= backlight_req_level
;
193 enable
= backlight_req_enable
;
197 __set_backlight_level(level
);
199 __set_backlight_enable(enable
);
200 } while(cmpxchg(&backlight_req_level
, level
, -1) != level
||
201 cmpxchg(&backlight_req_enable
, enable
, -1) != enable
);