diff options
Diffstat (limited to 'drivers/video/backlight/backlight.c')
-rw-r--r-- | drivers/video/backlight/backlight.c | 87 |
1 files changed, 55 insertions, 32 deletions
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index f439a588394a..1dac9e743427 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -14,6 +14,59 @@ | |||
14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
15 | #include <linux/fb.h> | 15 | #include <linux/fb.h> |
16 | 16 | ||
17 | |||
18 | #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ | ||
19 | defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) | ||
20 | /* This callback gets called when something important happens inside a | ||
21 | * framebuffer driver. We're looking if that important event is blanking, | ||
22 | * and if it is, we're switching backlight power as well ... | ||
23 | */ | ||
24 | static int fb_notifier_callback(struct notifier_block *self, | ||
25 | unsigned long event, void *data) | ||
26 | { | ||
27 | struct backlight_device *bd; | ||
28 | struct fb_event *evdata = data; | ||
29 | |||
30 | /* If we aren't interested in this event, skip it immediately ... */ | ||
31 | if (event != FB_EVENT_BLANK) | ||
32 | return 0; | ||
33 | |||
34 | bd = container_of(self, struct backlight_device, fb_notif); | ||
35 | down(&bd->sem); | ||
36 | if (bd->props) | ||
37 | if (!bd->props->check_fb || | ||
38 | bd->props->check_fb(evdata->info)) { | ||
39 | bd->props->fb_blank = *(int *)evdata->data; | ||
40 | if (likely(bd->props && bd->props->update_status)) | ||
41 | bd->props->update_status(bd); | ||
42 | } | ||
43 | up(&bd->sem); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static int backlight_register_fb(struct backlight_device *bd) | ||
48 | { | ||
49 | memset(&bd->fb_notif, 0, sizeof(bd->fb_notif)); | ||
50 | bd->fb_notif.notifier_call = fb_notifier_callback; | ||
51 | |||
52 | return fb_register_client(&bd->fb_notif); | ||
53 | } | ||
54 | |||
55 | static void backlight_unregister_fb(struct backlight_device *bd) | ||
56 | { | ||
57 | fb_unregister_client(&bd->fb_notif); | ||
58 | } | ||
59 | #else | ||
60 | static inline int backlight_register_fb(struct backlight_device *bd) | ||
61 | { | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static inline void backlight_unregister_fb(struct backlight_device *bd) | ||
66 | { | ||
67 | } | ||
68 | #endif /* CONFIG_FB */ | ||
69 | |||
17 | static ssize_t backlight_show_power(struct class_device *cdev, char *buf) | 70 | static ssize_t backlight_show_power(struct class_device *cdev, char *buf) |
18 | { | 71 | { |
19 | int rc = -ENXIO; | 72 | int rc = -ENXIO; |
@@ -151,33 +204,6 @@ static const struct class_device_attribute bl_class_device_attributes[] = { | |||
151 | DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), | 204 | DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), |
152 | }; | 205 | }; |
153 | 206 | ||
154 | /* This callback gets called when something important happens inside a | ||
155 | * framebuffer driver. We're looking if that important event is blanking, | ||
156 | * and if it is, we're switching backlight power as well ... | ||
157 | */ | ||
158 | static int fb_notifier_callback(struct notifier_block *self, | ||
159 | unsigned long event, void *data) | ||
160 | { | ||
161 | struct backlight_device *bd; | ||
162 | struct fb_event *evdata =(struct fb_event *)data; | ||
163 | |||
164 | /* If we aren't interested in this event, skip it immediately ... */ | ||
165 | if (event != FB_EVENT_BLANK) | ||
166 | return 0; | ||
167 | |||
168 | bd = container_of(self, struct backlight_device, fb_notif); | ||
169 | down(&bd->sem); | ||
170 | if (bd->props) | ||
171 | if (!bd->props->check_fb || | ||
172 | bd->props->check_fb(evdata->info)) { | ||
173 | bd->props->fb_blank = *(int *)evdata->data; | ||
174 | if (likely(bd->props && bd->props->update_status)) | ||
175 | bd->props->update_status(bd); | ||
176 | } | ||
177 | up(&bd->sem); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | /** | 207 | /** |
182 | * backlight_device_register - create and register a new object of | 208 | * backlight_device_register - create and register a new object of |
183 | * backlight_device class. | 209 | * backlight_device class. |
@@ -215,10 +241,7 @@ error: kfree(new_bd); | |||
215 | return ERR_PTR(rc); | 241 | return ERR_PTR(rc); |
216 | } | 242 | } |
217 | 243 | ||
218 | memset(&new_bd->fb_notif, 0, sizeof(new_bd->fb_notif)); | 244 | rc = backlight_register_fb(new_bd); |
219 | new_bd->fb_notif.notifier_call = fb_notifier_callback; | ||
220 | |||
221 | rc = fb_register_client(&new_bd->fb_notif); | ||
222 | if (unlikely(rc)) | 245 | if (unlikely(rc)) |
223 | goto error; | 246 | goto error; |
224 | 247 | ||
@@ -268,7 +291,7 @@ void backlight_device_unregister(struct backlight_device *bd) | |||
268 | bd->props = NULL; | 291 | bd->props = NULL; |
269 | up(&bd->sem); | 292 | up(&bd->sem); |
270 | 293 | ||
271 | fb_unregister_client(&bd->fb_notif); | 294 | backlight_unregister_fb(bd); |
272 | 295 | ||
273 | class_device_unregister(&bd->class_dev); | 296 | class_device_unregister(&bd->class_dev); |
274 | } | 297 | } |