diff options
-rw-r--r-- | drivers/video/backlight/backlight.c | 84 | ||||
-rw-r--r-- | drivers/video/backlight/corgi_bl.c | 99 | ||||
-rw-r--r-- | include/linux/backlight.h | 25 |
3 files changed, 107 insertions, 101 deletions
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 151fda8dded0..334b1db1bd7c 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -16,14 +16,12 @@ | |||
16 | 16 | ||
17 | static ssize_t backlight_show_power(struct class_device *cdev, char *buf) | 17 | static ssize_t backlight_show_power(struct class_device *cdev, char *buf) |
18 | { | 18 | { |
19 | int rc; | 19 | int rc = -ENXIO; |
20 | struct backlight_device *bd = to_backlight_device(cdev); | 20 | struct backlight_device *bd = to_backlight_device(cdev); |
21 | 21 | ||
22 | down(&bd->sem); | 22 | down(&bd->sem); |
23 | if (likely(bd->props && bd->props->get_power)) | 23 | if (likely(bd->props)) |
24 | rc = sprintf(buf, "%d\n", bd->props->get_power(bd)); | 24 | rc = sprintf(buf, "%d\n", bd->props->power); |
25 | else | ||
26 | rc = -ENXIO; | ||
27 | up(&bd->sem); | 25 | up(&bd->sem); |
28 | 26 | ||
29 | return rc; | 27 | return rc; |
@@ -31,7 +29,7 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf) | |||
31 | 29 | ||
32 | static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count) | 30 | static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count) |
33 | { | 31 | { |
34 | int rc, power; | 32 | int rc = -ENXIO, power; |
35 | char *endp; | 33 | char *endp; |
36 | struct backlight_device *bd = to_backlight_device(cdev); | 34 | struct backlight_device *bd = to_backlight_device(cdev); |
37 | 35 | ||
@@ -40,12 +38,13 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, | |||
40 | return -EINVAL; | 38 | return -EINVAL; |
41 | 39 | ||
42 | down(&bd->sem); | 40 | down(&bd->sem); |
43 | if (likely(bd->props && bd->props->set_power)) { | 41 | if (likely(bd->props)) { |
44 | pr_debug("backlight: set power to %d\n", power); | 42 | pr_debug("backlight: set power to %d\n", power); |
45 | bd->props->set_power(bd, power); | 43 | bd->props->power = power; |
44 | if (likely(bd->props->update_status)) | ||
45 | bd->props->update_status(bd); | ||
46 | rc = count; | 46 | rc = count; |
47 | } else | 47 | } |
48 | rc = -ENXIO; | ||
49 | up(&bd->sem); | 48 | up(&bd->sem); |
50 | 49 | ||
51 | return rc; | 50 | return rc; |
@@ -53,14 +52,12 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, | |||
53 | 52 | ||
54 | static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) | 53 | static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) |
55 | { | 54 | { |
56 | int rc; | 55 | int rc = -ENXIO; |
57 | struct backlight_device *bd = to_backlight_device(cdev); | 56 | struct backlight_device *bd = to_backlight_device(cdev); |
58 | 57 | ||
59 | down(&bd->sem); | 58 | down(&bd->sem); |
60 | if (likely(bd->props && bd->props->get_brightness)) | 59 | if (likely(bd->props)) |
61 | rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd)); | 60 | rc = sprintf(buf, "%d\n", bd->props->brightness); |
62 | else | ||
63 | rc = -ENXIO; | ||
64 | up(&bd->sem); | 61 | up(&bd->sem); |
65 | 62 | ||
66 | return rc; | 63 | return rc; |
@@ -68,7 +65,7 @@ static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) | |||
68 | 65 | ||
69 | static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count) | 66 | static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count) |
70 | { | 67 | { |
71 | int rc, brightness; | 68 | int rc = -ENXIO, brightness; |
72 | char *endp; | 69 | char *endp; |
73 | struct backlight_device *bd = to_backlight_device(cdev); | 70 | struct backlight_device *bd = to_backlight_device(cdev); |
74 | 71 | ||
@@ -77,12 +74,18 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char | |||
77 | return -EINVAL; | 74 | return -EINVAL; |
78 | 75 | ||
79 | down(&bd->sem); | 76 | down(&bd->sem); |
80 | if (likely(bd->props && bd->props->set_brightness)) { | 77 | if (likely(bd->props)) { |
81 | pr_debug("backlight: set brightness to %d\n", brightness); | 78 | if (brightness > bd->props->max_brightness) |
82 | bd->props->set_brightness(bd, brightness); | 79 | rc = -EINVAL; |
83 | rc = count; | 80 | else { |
84 | } else | 81 | pr_debug("backlight: set brightness to %d\n", |
85 | rc = -ENXIO; | 82 | brightness); |
83 | bd->props->brightness = brightness; | ||
84 | if (likely(bd->props->update_status)) | ||
85 | bd->props->update_status(bd); | ||
86 | rc = count; | ||
87 | } | ||
88 | } | ||
86 | up(&bd->sem); | 89 | up(&bd->sem); |
87 | 90 | ||
88 | return rc; | 91 | return rc; |
@@ -90,14 +93,26 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char | |||
90 | 93 | ||
91 | static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf) | 94 | static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf) |
92 | { | 95 | { |
93 | int rc; | 96 | int rc = -ENXIO; |
94 | struct backlight_device *bd = to_backlight_device(cdev); | 97 | struct backlight_device *bd = to_backlight_device(cdev); |
95 | 98 | ||
96 | down(&bd->sem); | 99 | down(&bd->sem); |
97 | if (likely(bd->props)) | 100 | if (likely(bd->props)) |
98 | rc = sprintf(buf, "%d\n", bd->props->max_brightness); | 101 | rc = sprintf(buf, "%d\n", bd->props->max_brightness); |
99 | else | 102 | up(&bd->sem); |
100 | rc = -ENXIO; | 103 | |
104 | return rc; | ||
105 | } | ||
106 | |||
107 | static ssize_t backlight_show_actual_brightness(struct class_device *cdev, | ||
108 | char *buf) | ||
109 | { | ||
110 | int rc = -ENXIO; | ||
111 | struct backlight_device *bd = to_backlight_device(cdev); | ||
112 | |||
113 | down(&bd->sem); | ||
114 | if (likely(bd->props && bd->props->get_brightness)) | ||
115 | rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd)); | ||
101 | up(&bd->sem); | 116 | up(&bd->sem); |
102 | 117 | ||
103 | return rc; | 118 | return rc; |
@@ -123,7 +138,10 @@ static struct class backlight_class = { | |||
123 | 138 | ||
124 | static struct class_device_attribute bl_class_device_attributes[] = { | 139 | static struct class_device_attribute bl_class_device_attributes[] = { |
125 | DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), | 140 | DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), |
126 | DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness), | 141 | DECLARE_ATTR(brightness, 0644, backlight_show_brightness, |
142 | backlight_store_brightness), | ||
143 | DECLARE_ATTR(actual_brightness, 0444, backlight_show_actual_brightness, | ||
144 | NULL), | ||
127 | DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), | 145 | DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), |
128 | }; | 146 | }; |
129 | 147 | ||
@@ -144,8 +162,12 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
144 | bd = container_of(self, struct backlight_device, fb_notif); | 162 | bd = container_of(self, struct backlight_device, fb_notif); |
145 | down(&bd->sem); | 163 | down(&bd->sem); |
146 | if (bd->props) | 164 | if (bd->props) |
147 | if (!bd->props->check_fb || bd->props->check_fb(evdata->info)) | 165 | if (!bd->props->check_fb || |
148 | bd->props->set_power(bd, *(int *)evdata->data); | 166 | bd->props->check_fb(evdata->info)) { |
167 | bd->props->fb_blank = *(int *)evdata->data; | ||
168 | if (likely(bd->props && bd->props->update_status)) | ||
169 | bd->props->update_status(bd); | ||
170 | } | ||
149 | up(&bd->sem); | 171 | up(&bd->sem); |
150 | return 0; | 172 | return 0; |
151 | } | 173 | } |
@@ -231,6 +253,12 @@ void backlight_device_unregister(struct backlight_device *bd) | |||
231 | &bl_class_device_attributes[i]); | 253 | &bl_class_device_attributes[i]); |
232 | 254 | ||
233 | down(&bd->sem); | 255 | down(&bd->sem); |
256 | if (likely(bd->props && bd->props->update_status)) { | ||
257 | bd->props->brightness = 0; | ||
258 | bd->props->power = 0; | ||
259 | bd->props->update_status(bd); | ||
260 | } | ||
261 | |||
234 | bd->props = NULL; | 262 | bd->props = NULL; |
235 | up(&bd->sem); | 263 | up(&bd->sem); |
236 | 264 | ||
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index d0aaf450e8c7..f86213b4a8fb 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c | |||
@@ -25,24 +25,30 @@ | |||
25 | #define CORGI_DEFAULT_INTENSITY 0x1f | 25 | #define CORGI_DEFAULT_INTENSITY 0x1f |
26 | #define CORGI_LIMIT_MASK 0x0b | 26 | #define CORGI_LIMIT_MASK 0x0b |
27 | 27 | ||
28 | static int corgibl_powermode = FB_BLANK_UNBLANK; | 28 | static int corgibl_intensity; |
29 | static int current_intensity = 0; | ||
30 | static int corgibl_limit = 0; | ||
31 | static void (*corgibl_mach_set_intensity)(int intensity); | 29 | static void (*corgibl_mach_set_intensity)(int intensity); |
32 | static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; | 30 | static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; |
33 | static struct backlight_properties corgibl_data; | 31 | static struct backlight_properties corgibl_data; |
32 | static struct backlight_device *corgi_backlight_device; | ||
33 | |||
34 | static unsigned long corgibl_flags; | ||
35 | #define CORGIBL_SUSPENDED 0x01 | ||
36 | #define CORGIBL_BATTLOW 0x02 | ||
34 | 37 | ||
35 | static void corgibl_send_intensity(int intensity) | 38 | static int corgibl_send_intensity(struct backlight_device *bd) |
36 | { | 39 | { |
37 | unsigned long flags; | 40 | unsigned long flags; |
38 | void (*corgi_kick_batt)(void); | 41 | void (*corgi_kick_batt)(void); |
42 | int intensity = bd->props->brightness; | ||
39 | 43 | ||
40 | if (corgibl_powermode != FB_BLANK_UNBLANK) { | 44 | if (bd->props->power != FB_BLANK_UNBLANK) |
45 | intensity = 0; | ||
46 | if (bd->props->fb_blank != FB_BLANK_UNBLANK) | ||
41 | intensity = 0; | 47 | intensity = 0; |
42 | } else { | 48 | if (corgibl_flags & CORGIBL_SUSPENDED) |
43 | if (corgibl_limit) | 49 | intensity = 0; |
44 | intensity &= CORGI_LIMIT_MASK; | 50 | if (corgibl_flags & CORGIBL_BATTLOW) |
45 | } | 51 | intensity &= CORGI_LIMIT_MASK; |
46 | 52 | ||
47 | spin_lock_irqsave(&bl_lock, flags); | 53 | spin_lock_irqsave(&bl_lock, flags); |
48 | 54 | ||
@@ -50,45 +56,29 @@ static void corgibl_send_intensity(int intensity) | |||
50 | 56 | ||
51 | spin_unlock_irqrestore(&bl_lock, flags); | 57 | spin_unlock_irqrestore(&bl_lock, flags); |
52 | 58 | ||
59 | corgibl_intensity = intensity; | ||
60 | |||
53 | corgi_kick_batt = symbol_get(sharpsl_battery_kick); | 61 | corgi_kick_batt = symbol_get(sharpsl_battery_kick); |
54 | if (corgi_kick_batt) { | 62 | if (corgi_kick_batt) { |
55 | corgi_kick_batt(); | 63 | corgi_kick_batt(); |
56 | symbol_put(sharpsl_battery_kick); | 64 | symbol_put(sharpsl_battery_kick); |
57 | } | 65 | } |
58 | } | ||
59 | 66 | ||
60 | static void corgibl_blank(int blank) | 67 | return 0; |
61 | { | ||
62 | switch(blank) { | ||
63 | |||
64 | case FB_BLANK_NORMAL: | ||
65 | case FB_BLANK_VSYNC_SUSPEND: | ||
66 | case FB_BLANK_HSYNC_SUSPEND: | ||
67 | case FB_BLANK_POWERDOWN: | ||
68 | if (corgibl_powermode == FB_BLANK_UNBLANK) { | ||
69 | corgibl_send_intensity(0); | ||
70 | corgibl_powermode = blank; | ||
71 | } | ||
72 | break; | ||
73 | case FB_BLANK_UNBLANK: | ||
74 | if (corgibl_powermode != FB_BLANK_UNBLANK) { | ||
75 | corgibl_powermode = blank; | ||
76 | corgibl_send_intensity(current_intensity); | ||
77 | } | ||
78 | break; | ||
79 | } | ||
80 | } | 68 | } |
81 | 69 | ||
82 | #ifdef CONFIG_PM | 70 | #ifdef CONFIG_PM |
83 | static int corgibl_suspend(struct platform_device *dev, pm_message_t state) | 71 | static int corgibl_suspend(struct platform_device *dev, pm_message_t state) |
84 | { | 72 | { |
85 | corgibl_blank(FB_BLANK_POWERDOWN); | 73 | corgibl_flags |= CORGIBL_SUSPENDED; |
74 | corgibl_send_intensity(corgi_backlight_device); | ||
86 | return 0; | 75 | return 0; |
87 | } | 76 | } |
88 | 77 | ||
89 | static int corgibl_resume(struct platform_device *dev) | 78 | static int corgibl_resume(struct platform_device *dev) |
90 | { | 79 | { |
91 | corgibl_blank(FB_BLANK_UNBLANK); | 80 | corgibl_flags &= ~CORGIBL_SUSPENDED; |
81 | corgibl_send_intensity(corgi_backlight_device); | ||
92 | return 0; | 82 | return 0; |
93 | } | 83 | } |
94 | #else | 84 | #else |
@@ -96,54 +86,38 @@ static int corgibl_resume(struct platform_device *dev) | |||
96 | #define corgibl_resume NULL | 86 | #define corgibl_resume NULL |
97 | #endif | 87 | #endif |
98 | 88 | ||
99 | 89 | static int corgibl_get_intensity(struct backlight_device *bd) | |
100 | static int corgibl_set_power(struct backlight_device *bd, int state) | ||
101 | { | ||
102 | corgibl_blank(state); | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int corgibl_get_power(struct backlight_device *bd) | ||
107 | { | 90 | { |
108 | return corgibl_powermode; | 91 | return corgibl_intensity; |
109 | } | 92 | } |
110 | 93 | ||
111 | static int corgibl_set_intensity(struct backlight_device *bd, int intensity) | 94 | static int corgibl_set_intensity(struct backlight_device *bd) |
112 | { | 95 | { |
113 | if (intensity > corgibl_data.max_brightness) | 96 | corgibl_send_intensity(corgi_backlight_device); |
114 | intensity = corgibl_data.max_brightness; | ||
115 | corgibl_send_intensity(intensity); | ||
116 | current_intensity=intensity; | ||
117 | return 0; | 97 | return 0; |
118 | } | 98 | } |
119 | 99 | ||
120 | static int corgibl_get_intensity(struct backlight_device *bd) | ||
121 | { | ||
122 | return current_intensity; | ||
123 | } | ||
124 | |||
125 | /* | 100 | /* |
126 | * Called when the battery is low to limit the backlight intensity. | 101 | * Called when the battery is low to limit the backlight intensity. |
127 | * If limit==0 clear any limit, otherwise limit the intensity | 102 | * If limit==0 clear any limit, otherwise limit the intensity |
128 | */ | 103 | */ |
129 | void corgibl_limit_intensity(int limit) | 104 | void corgibl_limit_intensity(int limit) |
130 | { | 105 | { |
131 | corgibl_limit = (limit ? 1 : 0); | 106 | if (limit) |
132 | corgibl_send_intensity(current_intensity); | 107 | corgibl_flags |= CORGIBL_BATTLOW; |
108 | else | ||
109 | corgibl_flags &= ~CORGIBL_BATTLOW; | ||
110 | corgibl_send_intensity(corgi_backlight_device); | ||
133 | } | 111 | } |
134 | EXPORT_SYMBOL(corgibl_limit_intensity); | 112 | EXPORT_SYMBOL(corgibl_limit_intensity); |
135 | 113 | ||
136 | 114 | ||
137 | static struct backlight_properties corgibl_data = { | 115 | static struct backlight_properties corgibl_data = { |
138 | .owner = THIS_MODULE, | 116 | .owner = THIS_MODULE, |
139 | .get_power = corgibl_get_power, | ||
140 | .set_power = corgibl_set_power, | ||
141 | .get_brightness = corgibl_get_intensity, | 117 | .get_brightness = corgibl_get_intensity, |
142 | .set_brightness = corgibl_set_intensity, | 118 | .update_status = corgibl_set_intensity, |
143 | }; | 119 | }; |
144 | 120 | ||
145 | static struct backlight_device *corgi_backlight_device; | ||
146 | |||
147 | static int __init corgibl_probe(struct platform_device *pdev) | 121 | static int __init corgibl_probe(struct platform_device *pdev) |
148 | { | 122 | { |
149 | struct corgibl_machinfo *machinfo = pdev->dev.platform_data; | 123 | struct corgibl_machinfo *machinfo = pdev->dev.platform_data; |
@@ -156,8 +130,9 @@ static int __init corgibl_probe(struct platform_device *pdev) | |||
156 | if (IS_ERR (corgi_backlight_device)) | 130 | if (IS_ERR (corgi_backlight_device)) |
157 | return PTR_ERR (corgi_backlight_device); | 131 | return PTR_ERR (corgi_backlight_device); |
158 | 132 | ||
159 | corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY); | 133 | corgibl_data.power = FB_BLANK_UNBLANK; |
160 | corgibl_limit_intensity(0); | 134 | corgibl_data.brightness = CORGI_DEFAULT_INTENSITY; |
135 | corgibl_send_intensity(corgi_backlight_device); | ||
161 | 136 | ||
162 | printk("Corgi Backlight Driver Initialized.\n"); | 137 | printk("Corgi Backlight Driver Initialized.\n"); |
163 | return 0; | 138 | return 0; |
@@ -167,8 +142,6 @@ static int corgibl_remove(struct platform_device *dev) | |||
167 | { | 142 | { |
168 | backlight_device_unregister(corgi_backlight_device); | 143 | backlight_device_unregister(corgi_backlight_device); |
169 | 144 | ||
170 | corgibl_set_intensity(NULL, 0); | ||
171 | |||
172 | printk("Corgi Backlight Driver Unloaded\n"); | 145 | printk("Corgi Backlight Driver Unloaded\n"); |
173 | return 0; | 146 | return 0; |
174 | } | 147 | } |
diff --git a/include/linux/backlight.h b/include/linux/backlight.h index bb9e54322322..75e91f5b6a04 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h | |||
@@ -19,20 +19,25 @@ struct fb_info; | |||
19 | struct backlight_properties { | 19 | struct backlight_properties { |
20 | /* Owner module */ | 20 | /* Owner module */ |
21 | struct module *owner; | 21 | struct module *owner; |
22 | /* Get the backlight power status (0: full on, 1..3: power saving | 22 | |
23 | modes; 4: full off), see FB_BLANK_XXX */ | 23 | /* Notify the backlight driver some property has changed */ |
24 | int (*get_power)(struct backlight_device *); | 24 | int (*update_status)(struct backlight_device *); |
25 | /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */ | 25 | /* Return the current backlight brightness (accounting for power, |
26 | int (*set_power)(struct backlight_device *, int power); | 26 | fb_blank etc.) */ |
27 | /* Maximal value for brightness (read-only) */ | ||
28 | int max_brightness; | ||
29 | /* Get current backlight brightness */ | ||
30 | int (*get_brightness)(struct backlight_device *); | 27 | int (*get_brightness)(struct backlight_device *); |
31 | /* Set backlight brightness (0..max_brightness) */ | ||
32 | int (*set_brightness)(struct backlight_device *, int brightness); | ||
33 | /* Check if given framebuffer device is the one bound to this backlight; | 28 | /* Check if given framebuffer device is the one bound to this backlight; |
34 | return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */ | 29 | return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */ |
35 | int (*check_fb)(struct fb_info *); | 30 | int (*check_fb)(struct fb_info *); |
31 | |||
32 | /* Current User requested brightness (0 - max_brightness) */ | ||
33 | int brightness; | ||
34 | /* Maximal value for brightness (read-only) */ | ||
35 | int max_brightness; | ||
36 | /* Current FB Power mode (0: full on, 1..3: power saving | ||
37 | modes; 4: full off), see FB_BLANK_XXX */ | ||
38 | int power; | ||
39 | /* FB Blanking active? (values as for power) */ | ||
40 | int fb_blank; | ||
36 | }; | 41 | }; |
37 | 42 | ||
38 | struct backlight_device { | 43 | struct backlight_device { |