clean-move-defconfigs-stable.patch
[linux-2.6/openmoko-kernel/knife-kernel.git] / drivers / video / backlight / gta01_bl.c
bloba7170dffc7b15d267031935f361f62609df3f6a5
1 /*
2 * Backlight Driver for FIC GTA01 (Neo1973) GSM Phone
4 * Copyright (C) 2006-2007 by Openmoko, Inc.
5 * Author: Harald Welte <laforge@openmoko.org>
6 * All rights reserved.
8 * based on corgi_cl.c, Copyright (c) 2004-2006 Richard Purdie
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
24 * Javi Roman <javiroman@kernel-labs.org>:
25 * implement PWM, instead of simple on/off switching
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/init.h>
32 #include <linux/platform_device.h>
33 #include <linux/mutex.h>
34 #include <linux/fb.h>
35 #include <linux/backlight.h>
36 #include <linux/clk.h>
38 #include <asm/arch/hardware.h>
39 #include <asm/arch/gta01.h>
40 #include <asm/arch/pwm.h>
42 #include <asm/plat-s3c/regs-timer.h>
43 #include <asm/plat-s3c24xx/neo1973.h>
45 static struct backlight_properties gta01bl_prop;
46 static struct backlight_device *gta01_backlight_device;
47 static struct gta01bl_machinfo *bl_machinfo;
49 static unsigned long gta01bl_flags;
51 struct gta01bl_data {
52 int intensity;
53 struct mutex mutex;
54 struct clk *clk;
55 struct s3c2410_pwm pwm;
58 static struct gta01bl_data gta01bl;
60 static int gta01bl_defer_resume_backlight;
62 #define GTA01BL_SUSPENDED 0x01
63 #define GTA01BL_BATTLOW 0x02
65 /* On the GTA01 / Neo1973, we use a 50 or 66MHz PCLK, which gives
66 * us a 6.25..8.25MHz DIV8 clock, which is further divided by a
67 * prescaler of 4, resulting in a 1.56..2.06MHz tick. This results in a
68 * minimum frequency of 24..31Hz. At 400Hz, we need to set the count
69 * to something like 3906..5156, providing us a way sufficient resolution
70 * for display brightness adjustment. */
71 #define GTA01BL_COUNTER 5156
73 static int gta01bl_send_intensity(struct backlight_device *bd)
75 int intensity = bd->props.brightness;
77 if (bd->props.power != FB_BLANK_UNBLANK)
78 intensity = 0;
79 if (bd->props.fb_blank != FB_BLANK_UNBLANK)
80 intensity = 0;
81 if (gta01bl_flags & GTA01BL_SUSPENDED)
82 intensity = 0;
83 if (gta01bl_flags & GTA01BL_BATTLOW)
84 intensity &= bl_machinfo->limit_mask;
86 mutex_lock(&gta01bl.mutex);
87 #ifdef GTA01_BACKLIGHT_ONOFF_ONLY
88 if (intensity)
89 neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 1);
90 else
91 neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 0);
92 #else
93 if (intensity == bd->props.max_brightness) {
94 neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 1);
95 s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
96 } else {
97 s3c2410_pwm_duty_cycle(intensity & 0xffff, &gta01bl.pwm);
98 s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPB0_TOUT0);
100 #endif
101 mutex_unlock(&gta01bl.mutex);
103 gta01bl.intensity = intensity;
104 return 0;
107 static int gta01bl_init_hw(void)
109 int rc;
111 rc = s3c2410_pwm_init(&gta01bl.pwm);
112 if (rc)
113 return rc;
115 gta01bl.pwm.timerid = PWM0;
116 gta01bl.pwm.prescaler = (4 - 1);
117 gta01bl.pwm.divider = S3C2410_TCFG1_MUX0_DIV8;
118 gta01bl.pwm.counter = GTA01BL_COUNTER;
119 gta01bl.pwm.comparer = gta01bl.pwm.counter;
121 rc = s3c2410_pwm_enable(&gta01bl.pwm);
122 if (rc)
123 return rc;
125 s3c2410_pwm_start(&gta01bl.pwm);
127 gta01bl_prop.max_brightness = gta01bl.pwm.counter;
129 return 0;
132 #ifdef CONFIG_PM
133 static int gta01bl_suspend(struct platform_device *dev, pm_message_t state)
135 gta01bl_flags |= GTA01BL_SUSPENDED;
136 gta01bl_send_intensity(gta01_backlight_device);
137 neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 0);
138 s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
139 return 0;
142 void gta01bl_deferred_resume(void)
144 mutex_lock(&gta01bl.mutex);
145 gta01bl_init_hw();
146 mutex_unlock(&gta01bl.mutex);
148 gta01bl_flags &= ~GTA01BL_SUSPENDED;
149 gta01bl_send_intensity(gta01_backlight_device);
151 EXPORT_SYMBOL_GPL(gta01bl_deferred_resume);
153 static int gta01bl_resume(struct platform_device *dev)
155 if (!gta01bl_defer_resume_backlight)
156 gta01bl_deferred_resume();
157 return 0;
159 #else
160 #define gta01bl_suspend NULL
161 #define gta01bl_resume NULL
162 #endif
164 static int gta01bl_get_intensity(struct backlight_device *bd)
166 return gta01bl.intensity;
169 static int gta01bl_set_intensity(struct backlight_device *bd)
171 gta01bl_send_intensity(gta01_backlight_device);
172 return 0;
176 * Called when the battery is low to limit the backlight intensity.
177 * If limit==0 clear any limit, otherwise limit the intensity
179 void gta01bl_limit_intensity(int limit)
181 if (limit)
182 gta01bl_flags |= GTA01BL_BATTLOW;
183 else
184 gta01bl_flags &= ~GTA01BL_BATTLOW;
185 gta01bl_send_intensity(gta01_backlight_device);
187 EXPORT_SYMBOL_GPL(gta01bl_limit_intensity);
190 static struct backlight_ops gta01bl_ops = {
191 .get_brightness = gta01bl_get_intensity,
192 .update_status = gta01bl_set_intensity,
195 static int __init gta01bl_probe(struct platform_device *pdev)
197 struct gta01bl_machinfo *machinfo = pdev->dev.platform_data;
198 int rc;
200 #ifdef GTA01_BACKLIGHT_ONOFF_ONLY
201 s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
202 gta01bl_prop.max_brightness = 1;
203 #else
204 rc = gta01bl_init_hw();
205 if (rc < 0)
206 return rc;
207 #endif
208 mutex_init(&gta01bl.mutex);
210 if (!machinfo->limit_mask)
211 machinfo->limit_mask = -1;
213 gta01bl_defer_resume_backlight = machinfo->defer_resume_backlight;
215 gta01_backlight_device = backlight_device_register("gta01-bl",
216 &pdev->dev, NULL,
217 &gta01bl_ops);
218 if (IS_ERR(gta01_backlight_device))
219 return PTR_ERR(gta01_backlight_device);
221 gta01bl_prop.power = FB_BLANK_UNBLANK;
222 gta01bl_prop.brightness = gta01bl_prop.max_brightness;
223 memcpy(&gta01_backlight_device->props,
224 &gta01bl_prop, sizeof(gta01bl_prop));
225 gta01bl_send_intensity(gta01_backlight_device);
227 return 0;
230 static int gta01bl_remove(struct platform_device *dev)
232 #ifndef GTA01_BACKLIGHT_ONOFF_ONLY
233 s3c2410_pwm_disable(&gta01bl.pwm);
234 #endif
235 backlight_device_unregister(gta01_backlight_device);
236 mutex_destroy(&gta01bl.mutex);
238 s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
239 neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 1);
241 return 0;
244 static struct platform_driver gta01bl_driver = {
245 .probe = gta01bl_probe,
246 .remove = gta01bl_remove,
247 .suspend = gta01bl_suspend,
248 .resume = gta01bl_resume,
249 .driver = {
250 .name = "gta01-bl",
254 static int __init gta01bl_init(void)
256 return platform_driver_register(&gta01bl_driver);
259 static void __exit gta01bl_exit(void)
261 platform_driver_unregister(&gta01bl_driver);
264 module_init(gta01bl_init);
265 module_exit(gta01bl_exit);
267 MODULE_DESCRIPTION("FIC GTA01 (Neo1973) Backlight Driver");
268 MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
269 MODULE_LICENSE("GPL");