Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Backlight Driver for Sharp Corgi | |
3 | * | |
4 | * Copyright (c) 2004-2005 Richard Purdie | |
5 | * | |
6 | * Based on Sharp's 2.4 Backlight Driver | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | */ | |
13 | ||
14 | #include <linux/module.h> | |
15 | #include <linux/kernel.h> | |
16 | #include <linux/init.h> | |
d052d1be | 17 | #include <linux/platform_device.h> |
1da177e4 LT |
18 | #include <linux/spinlock.h> |
19 | #include <linux/fb.h> | |
20 | #include <linux/backlight.h> | |
21 | ||
12e87808 | 22 | #include <asm/arch/sharpsl.h> |
1da177e4 | 23 | |
1da177e4 | 24 | #define CORGI_DEFAULT_INTENSITY 0x1f |
12e87808 | 25 | #define CORGI_LIMIT_MASK 0x0b |
1da177e4 LT |
26 | |
27 | static int corgibl_powermode = FB_BLANK_UNBLANK; | |
28 | static int current_intensity = 0; | |
29 | static int corgibl_limit = 0; | |
12e87808 | 30 | static void (*corgibl_mach_set_intensity)(int intensity); |
1da177e4 | 31 | static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; |
12e87808 | 32 | static struct backlight_properties corgibl_data; |
1da177e4 LT |
33 | |
34 | static void corgibl_send_intensity(int intensity) | |
35 | { | |
36 | unsigned long flags; | |
37 | void (*corgi_kick_batt)(void); | |
38 | ||
39 | if (corgibl_powermode != FB_BLANK_UNBLANK) { | |
40 | intensity = 0; | |
41 | } else { | |
42 | if (corgibl_limit) | |
43 | intensity &= CORGI_LIMIT_MASK; | |
44 | } | |
45 | ||
1da177e4 | 46 | spin_lock_irqsave(&bl_lock, flags); |
1351e6e0 RP |
47 | |
48 | corgibl_mach_set_intensity(intensity); | |
49 | ||
1da177e4 LT |
50 | spin_unlock_irqrestore(&bl_lock, flags); |
51 | } | |
52 | ||
53 | static void corgibl_blank(int blank) | |
54 | { | |
55 | switch(blank) { | |
56 | ||
57 | case FB_BLANK_NORMAL: | |
58 | case FB_BLANK_VSYNC_SUSPEND: | |
59 | case FB_BLANK_HSYNC_SUSPEND: | |
60 | case FB_BLANK_POWERDOWN: | |
61 | if (corgibl_powermode == FB_BLANK_UNBLANK) { | |
62 | corgibl_send_intensity(0); | |
63 | corgibl_powermode = blank; | |
64 | } | |
65 | break; | |
66 | case FB_BLANK_UNBLANK: | |
67 | if (corgibl_powermode != FB_BLANK_UNBLANK) { | |
68 | corgibl_powermode = blank; | |
69 | corgibl_send_intensity(current_intensity); | |
70 | } | |
71 | break; | |
72 | } | |
73 | } | |
74 | ||
75 | #ifdef CONFIG_PM | |
9480e307 | 76 | static int corgibl_suspend(struct device *dev, pm_message_t state) |
1da177e4 | 77 | { |
9480e307 | 78 | corgibl_blank(FB_BLANK_POWERDOWN); |
1da177e4 LT |
79 | return 0; |
80 | } | |
81 | ||
9480e307 | 82 | static int corgibl_resume(struct device *dev) |
1da177e4 | 83 | { |
9480e307 | 84 | corgibl_blank(FB_BLANK_UNBLANK); |
1da177e4 LT |
85 | return 0; |
86 | } | |
87 | #else | |
88 | #define corgibl_suspend NULL | |
89 | #define corgibl_resume NULL | |
90 | #endif | |
91 | ||
92 | ||
93 | static int corgibl_set_power(struct backlight_device *bd, int state) | |
94 | { | |
95 | corgibl_blank(state); | |
96 | return 0; | |
97 | } | |
98 | ||
99 | static int corgibl_get_power(struct backlight_device *bd) | |
100 | { | |
101 | return corgibl_powermode; | |
102 | } | |
103 | ||
104 | static int corgibl_set_intensity(struct backlight_device *bd, int intensity) | |
105 | { | |
1351e6e0 RP |
106 | if (intensity > corgibl_data.max_brightness) |
107 | intensity = corgibl_data.max_brightness; | |
1da177e4 LT |
108 | corgibl_send_intensity(intensity); |
109 | current_intensity=intensity; | |
110 | return 0; | |
111 | } | |
112 | ||
113 | static int corgibl_get_intensity(struct backlight_device *bd) | |
114 | { | |
115 | return current_intensity; | |
116 | } | |
117 | ||
118 | /* | |
119 | * Called when the battery is low to limit the backlight intensity. | |
120 | * If limit==0 clear any limit, otherwise limit the intensity | |
121 | */ | |
122 | void corgibl_limit_intensity(int limit) | |
123 | { | |
124 | corgibl_limit = (limit ? 1 : 0); | |
125 | corgibl_send_intensity(current_intensity); | |
126 | } | |
127 | EXPORT_SYMBOL(corgibl_limit_intensity); | |
128 | ||
129 | ||
130 | static struct backlight_properties corgibl_data = { | |
131 | .owner = THIS_MODULE, | |
132 | .get_power = corgibl_get_power, | |
133 | .set_power = corgibl_set_power, | |
1da177e4 LT |
134 | .get_brightness = corgibl_get_intensity, |
135 | .set_brightness = corgibl_set_intensity, | |
136 | }; | |
137 | ||
138 | static struct backlight_device *corgi_backlight_device; | |
139 | ||
140 | static int __init corgibl_probe(struct device *dev) | |
141 | { | |
1351e6e0 RP |
142 | struct corgibl_machinfo *machinfo = dev->platform_data; |
143 | ||
144 | corgibl_data.max_brightness = machinfo->max_intensity; | |
145 | corgibl_mach_set_intensity = machinfo->set_bl_intensity; | |
146 | ||
1da177e4 LT |
147 | corgi_backlight_device = backlight_device_register ("corgi-bl", |
148 | NULL, &corgibl_data); | |
149 | if (IS_ERR (corgi_backlight_device)) | |
150 | return PTR_ERR (corgi_backlight_device); | |
151 | ||
152 | corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY); | |
1351e6e0 | 153 | corgibl_limit_intensity(0); |
1da177e4 LT |
154 | |
155 | printk("Corgi Backlight Driver Initialized.\n"); | |
156 | return 0; | |
157 | } | |
158 | ||
159 | static int corgibl_remove(struct device *dev) | |
160 | { | |
161 | backlight_device_unregister(corgi_backlight_device); | |
162 | ||
163 | corgibl_set_intensity(NULL, 0); | |
164 | ||
165 | printk("Corgi Backlight Driver Unloaded\n"); | |
166 | return 0; | |
167 | } | |
168 | ||
169 | static struct device_driver corgibl_driver = { | |
170 | .name = "corgi-bl", | |
171 | .bus = &platform_bus_type, | |
172 | .probe = corgibl_probe, | |
173 | .remove = corgibl_remove, | |
174 | .suspend = corgibl_suspend, | |
175 | .resume = corgibl_resume, | |
176 | }; | |
177 | ||
178 | static int __init corgibl_init(void) | |
179 | { | |
180 | return driver_register(&corgibl_driver); | |
181 | } | |
182 | ||
183 | static void __exit corgibl_exit(void) | |
184 | { | |
185 | driver_unregister(&corgibl_driver); | |
186 | } | |
187 | ||
188 | module_init(corgibl_init); | |
189 | module_exit(corgibl_exit); | |
190 | ||
191 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | |
192 | MODULE_DESCRIPTION("Corgi Backlight Driver"); | |
193 | MODULE_LICENSE("GPLv2"); |