sync hh.org
[hh.org.git] / arch / arm / mach-pxa / asus716 / a716_lcd.c
bloba171bb46ba88b975f5d865b8ee77e943b38d4737
1 /*
2 * Asus MyPal 716 LCD and Backlight driver
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * Copyright (C) 2005 Pawel Kolodziejski
9 * Copyright (C) 2004 Vitaliy Sardyko
10 * Copyright (c) 2003 Adam Turowski
12 * 2003-12-03: Adam Turowski
13 * initial code.
14 * 2004-11-07: Vitaliy Sardyko
15 * updated to 2.6.7
19 #include <linux/module.h>
20 #include <linux/init.h>
21 #include <linux/notifier.h>
22 #include <linux/lcd.h>
23 #include <linux/backlight.h>
24 #include <linux/delay.h>
25 #include <linux/platform_device.h>
27 #include <asm/mach/arch.h>
28 #include <asm/mach/map.h>
29 #include <asm/mach-types.h>
31 #include <asm/hardware.h>
32 #include <asm/arch/pxa-regs.h>
33 #include <asm/arch/asus716-gpio.h>
34 #include <linux/fb.h>
35 #include <asm/arch/pxafb.h>
37 static int lcd_power;
38 static int backlight_power;
40 int a716_lcd_set_power(struct lcd_device *lm, int level)
42 switch (level) {
43 case FB_BLANK_UNBLANK:
44 case FB_BLANK_NORMAL:
45 a716_gpo_set(GPO_A716_LCD_ENABLE);
46 a716_gpo_set(GPO_A716_LCD_POWER3);
47 mdelay(30);
48 a716_gpo_set(GPO_A716_LCD_POWER1);
49 mdelay(30);
50 break;
51 case FB_BLANK_VSYNC_SUSPEND:
52 case FB_BLANK_HSYNC_SUSPEND:
53 break;
54 case FB_BLANK_POWERDOWN:
55 a716_gpo_clear(GPO_A716_LCD_POWER1);
56 mdelay(65);
57 a716_gpo_clear(GPO_A716_LCD_POWER3);
58 a716_gpo_clear(GPO_A716_LCD_ENABLE);
59 break;
62 lcd_power = level;
64 return 0;
67 static int a716_lcd_get_power(struct lcd_device *lm)
69 return lcd_power;
72 struct lcd_properties a716_lcd_properties =
74 .owner = THIS_MODULE,
75 .set_power = a716_lcd_set_power,
76 .get_power = a716_lcd_get_power,
77 };
79 int a716_backlight_set_power(struct backlight_device *bm, int level)
81 switch (level) {
82 case FB_BLANK_UNBLANK:
83 case FB_BLANK_NORMAL:
84 CKEN |= CKEN0_PWM0;
85 a716_gpo_set(GPO_A716_BACKLIGHT);
86 break;
87 case FB_BLANK_VSYNC_SUSPEND:
88 case FB_BLANK_HSYNC_SUSPEND:
89 break;
90 case FB_BLANK_POWERDOWN:
91 CKEN &= ~CKEN0_PWM0;
92 a716_gpo_clear(GPO_A716_BACKLIGHT);
93 mdelay(30);
94 break;
97 backlight_power = level;
99 return 0;
102 static int a716_backlight_get_power(struct backlight_device *bm)
104 return backlight_power;
107 int a716_backlight_set_brightness(struct backlight_device *bm, int value)
109 if (value == 0) {
110 PWM_PWDUTY0 = 0;
111 PWM_PERVAL0 = 255;
112 } else {
113 PWM_PWDUTY0 = ((value * 220) / 255) + 35;
114 PWM_PERVAL0 = 255;
117 return 0;
120 int a716_backlight_get_brightness(struct backlight_device *bm)
122 int value;
124 value = PWM_PWDUTY0 - 35;
125 if (value < 0)
126 return 0;
128 return (value * 255) / 220;
131 static struct backlight_properties a716_backlight_properties =
133 .owner = THIS_MODULE,
134 .max_brightness = 255,
135 .set_power = a716_backlight_set_power,
136 .get_power = a716_backlight_get_power,
137 .set_brightness = a716_backlight_set_brightness,
138 .get_brightness = a716_backlight_get_brightness,
141 static struct lcd_device *pxafb_lcd_device;
142 static struct backlight_device *pxafb_backlight_device;
144 int a716_lcd_probe(struct device *dev)
146 if (!machine_is_a716())
147 return -ENODEV;
149 pxafb_lcd_device = lcd_device_register("pxafb", NULL, &a716_lcd_properties);
151 if (IS_ERR(pxafb_lcd_device))
152 return PTR_ERR(pxafb_lcd_device);
153 pxafb_backlight_device = backlight_device_register("pxafb", NULL, &a716_backlight_properties);
154 if (IS_ERR(pxafb_backlight_device)) {
155 lcd_device_unregister(pxafb_lcd_device);
156 return PTR_ERR(pxafb_backlight_device);
159 a716_backlight_set_brightness(pxafb_backlight_device, 100);
161 return 0;
164 static int a716_lcd_remove(struct device *dev)
166 lcd_device_unregister(pxafb_lcd_device);
167 backlight_device_unregister(pxafb_backlight_device);
169 return 0;
172 #ifdef CONFIG_PM
173 struct pm_save_data {
174 int brightness;
177 static int a716_lcd_suspend(struct device *dev, pm_message_t state)
179 struct pm_save_data *save;
181 if (!dev->power.saved_state)
182 dev->power.saved_state = kmalloc(sizeof(struct pm_save_data), GFP_KERNEL);
183 if (!dev->power.saved_state)
184 return -ENOMEM;
185 save = dev->power.saved_state;
186 save->brightness = a716_backlight_get_brightness(NULL);
188 return 0;
191 static int a716_lcd_resume(struct device *dev)
193 if (dev->power.saved_state) {
194 struct pm_save_data *save = dev->power.saved_state;
195 a716_backlight_set_brightness(NULL, save->brightness);
196 kfree(dev->power.saved_state);
197 dev->power.saved_state = NULL;
200 return 0;
202 #endif
204 static struct device_driver a716_lcd_driver = {
205 .name = "a716-lcd",
206 .bus = &platform_bus_type,
207 .probe = a716_lcd_probe,
208 .remove = a716_lcd_remove,
209 #ifdef CONFIG_PM
210 .suspend = a716_lcd_suspend,
211 .resume = a716_lcd_resume,
212 #endif
215 static int a716_lcd_init(void)
217 if (!machine_is_a716())
218 return -ENODEV;
220 return driver_register(&a716_lcd_driver);
223 static void a716_lcd_exit(void)
225 lcd_device_unregister(pxafb_lcd_device);
226 backlight_device_unregister(pxafb_backlight_device);
227 driver_unregister(&a716_lcd_driver);
230 module_init(a716_lcd_init);
231 module_exit(a716_lcd_exit);
233 MODULE_AUTHOR("Adam Turowski, Nicolas Pouillon, Pawel Kolodziejski");
234 MODULE_DESCRIPTION("LCD driver for Asus MyPal A716");
235 MODULE_LICENSE("GPL");