2 * Backlight Driver for FIC GTA01 (Neo1973) GSM Phone
4 * Copyright (C) 2006-2007 by Openmoko, Inc.
5 * Author: Harald Welte <laforge@openmoko.org>
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,
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>
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
;
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
)
79 if (bd
->props
.fb_blank
!= FB_BLANK_UNBLANK
)
81 if (gta01bl_flags
& GTA01BL_SUSPENDED
)
83 if (gta01bl_flags
& GTA01BL_BATTLOW
)
84 intensity
&= bl_machinfo
->limit_mask
;
86 mutex_lock(>a01bl
.mutex
);
87 #ifdef GTA01_BACKLIGHT_ONOFF_ONLY
89 neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT
, 1);
91 neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT
, 0);
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
);
97 s3c2410_pwm_duty_cycle(intensity
& 0xffff, >a01bl
.pwm
);
98 s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT
, S3C2410_GPB0_TOUT0
);
101 mutex_unlock(>a01bl
.mutex
);
103 gta01bl
.intensity
= intensity
;
107 static int gta01bl_init_hw(void)
111 rc
= s3c2410_pwm_init(>a01bl
.pwm
);
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(>a01bl
.pwm
);
125 s3c2410_pwm_start(>a01bl
.pwm
);
127 gta01bl_prop
.max_brightness
= gta01bl
.pwm
.counter
;
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
);
142 void gta01bl_deferred_resume(void)
144 mutex_lock(>a01bl
.mutex
);
146 mutex_unlock(>a01bl
.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();
160 #define gta01bl_suspend NULL
161 #define gta01bl_resume NULL
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
);
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
)
182 gta01bl_flags
|= GTA01BL_BATTLOW
;
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
;
200 #ifdef GTA01_BACKLIGHT_ONOFF_ONLY
201 s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT
, S3C2410_GPIO_OUTPUT
);
202 gta01bl_prop
.max_brightness
= 1;
204 rc
= gta01bl_init_hw();
208 mutex_init(>a01bl
.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",
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(>a01_backlight_device
->props
,
224 >a01bl_prop
, sizeof(gta01bl_prop
));
225 gta01bl_send_intensity(gta01_backlight_device
);
230 static int gta01bl_remove(struct platform_device
*dev
)
232 #ifndef GTA01_BACKLIGHT_ONOFF_ONLY
233 s3c2410_pwm_disable(>a01bl
.pwm
);
235 backlight_device_unregister(gta01_backlight_device
);
236 mutex_destroy(>a01bl
.mutex
);
238 s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT
, S3C2410_GPIO_OUTPUT
);
239 neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT
, 1);
244 static struct platform_driver gta01bl_driver
= {
245 .probe
= gta01bl_probe
,
246 .remove
= gta01bl_remove
,
247 .suspend
= gta01bl_suspend
,
248 .resume
= gta01bl_resume
,
254 static int __init
gta01bl_init(void)
256 return platform_driver_register(>a01bl_driver
);
259 static void __exit
gta01bl_exit(void)
261 platform_driver_unregister(>a01bl_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");