xref: /linux/drivers/video/backlight/hp680_bl.c (revision de2fe5e07d58424bc286fff3fd3c1b0bf933cd58)
1 /*
2  *  Backlight Driver for HP Jornada 680
3  *
4  *  Copyright (c) 2005 Andriy Skulysh
5  *
6  *  Based on Sharp's Corgi Backlight Driver
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11  */
12 
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/device.h>
17 #include <linux/spinlock.h>
18 #include <linux/fb.h>
19 #include <linux/backlight.h>
20 
21 #include <asm/cpu/dac.h>
22 #include <asm/hp6xx/hp6xx.h>
23 #include <asm/hd64461/hd64461.h>
24 
25 #define HP680_MAX_INTENSITY 255
26 #define HP680_DEFAULT_INTENSITY 10
27 
28 static int hp680bl_powermode = FB_BLANK_UNBLANK;
29 static int current_intensity = 0;
30 static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
31 
32 static void hp680bl_send_intensity(int intensity)
33 {
34 	unsigned long flags;
35 
36 	if (hp680bl_powermode != FB_BLANK_UNBLANK)
37 		intensity = 0;
38 
39 	spin_lock_irqsave(&bl_lock, flags);
40 	sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
41 	spin_unlock_irqrestore(&bl_lock, flags);
42 }
43 
44 static void hp680bl_blank(int blank)
45 {
46 	u16 v;
47 
48 	switch(blank) {
49 
50 	case FB_BLANK_NORMAL:
51 	case FB_BLANK_VSYNC_SUSPEND:
52 	case FB_BLANK_HSYNC_SUSPEND:
53 	case FB_BLANK_POWERDOWN:
54 		if (hp680bl_powermode == FB_BLANK_UNBLANK) {
55 			hp680bl_send_intensity(0);
56 			hp680bl_powermode = blank;
57 			sh_dac_disable(DAC_LCD_BRIGHTNESS);
58 			v = inw(HD64461_GPBDR);
59 			v |= HD64461_GPBDR_LCDOFF;
60 			outw(v, HD64461_GPBDR);
61 		}
62 		break;
63 	case FB_BLANK_UNBLANK:
64 		if (hp680bl_powermode != FB_BLANK_UNBLANK) {
65 			sh_dac_enable(DAC_LCD_BRIGHTNESS);
66 			v = inw(HD64461_GPBDR);
67 			v &= ~HD64461_GPBDR_LCDOFF;
68 			outw(v, HD64461_GPBDR);
69 			hp680bl_powermode = blank;
70 			hp680bl_send_intensity(current_intensity);
71 		}
72 		break;
73 	}
74 }
75 
76 #ifdef CONFIG_PM
77 static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level)
78 {
79 	if (level == SUSPEND_POWER_DOWN)
80 		hp680bl_blank(FB_BLANK_POWERDOWN);
81 	return 0;
82 }
83 
84 static int hp680bl_resume(struct device *dev, u32 level)
85 {
86 	if (level == RESUME_POWER_ON)
87 		hp680bl_blank(FB_BLANK_UNBLANK);
88 	return 0;
89 }
90 #else
91 #define hp680bl_suspend	NULL
92 #define hp680bl_resume	NULL
93 #endif
94 
95 
96 static int hp680bl_set_power(struct backlight_device *bd, int state)
97 {
98 	hp680bl_blank(state);
99 	return 0;
100 }
101 
102 static int hp680bl_get_power(struct backlight_device *bd)
103 {
104 	return hp680bl_powermode;
105 }
106 
107 static int hp680bl_set_intensity(struct backlight_device *bd, int intensity)
108 {
109 	if (intensity > HP680_MAX_INTENSITY)
110 		intensity = HP680_MAX_INTENSITY;
111 	hp680bl_send_intensity(intensity);
112 	current_intensity = intensity;
113 	return 0;
114 }
115 
116 static int hp680bl_get_intensity(struct backlight_device *bd)
117 {
118 	return current_intensity;
119 }
120 
121 static struct backlight_properties hp680bl_data = {
122 	.owner		= THIS_MODULE,
123 	.get_power      = hp680bl_get_power,
124 	.set_power      = hp680bl_set_power,
125 	.max_brightness = HP680_MAX_INTENSITY,
126 	.get_brightness = hp680bl_get_intensity,
127 	.set_brightness = hp680bl_set_intensity,
128 };
129 
130 static struct backlight_device *hp680_backlight_device;
131 
132 static int __init hp680bl_probe(struct device *dev)
133 {
134 	hp680_backlight_device = backlight_device_register ("hp680-bl",
135 		NULL, &hp680bl_data);
136 	if (IS_ERR (hp680_backlight_device))
137 		return PTR_ERR (hp680_backlight_device);
138 
139 	hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY);
140 
141 	return 0;
142 }
143 
144 static int hp680bl_remove(struct device *dev)
145 {
146 	backlight_device_unregister(hp680_backlight_device);
147 
148 	return 0;
149 }
150 
151 static struct device_driver hp680bl_driver = {
152 	.name		= "hp680-bl",
153 	.bus		= &platform_bus_type,
154 	.probe		= hp680bl_probe,
155 	.remove		= hp680bl_remove,
156 	.suspend	= hp680bl_suspend,
157 	.resume		= hp680bl_resume,
158 };
159 
160 static struct platform_device hp680bl_device = {
161 	.name	= "hp680-bl",
162 	.id	= -1,
163 };
164 
165 static int __init hp680bl_init(void)
166 {
167 	int ret;
168 
169 	ret=driver_register(&hp680bl_driver);
170 	if (!ret) {
171 		ret = platform_device_register(&hp680bl_device);
172 		if (ret)
173 			driver_unregister(&hp680bl_driver);
174 	}
175 	return ret;
176 }
177 
178 static void __exit hp680bl_exit(void)
179 {
180 	platform_device_unregister(&hp680bl_device);
181  	driver_unregister(&hp680bl_driver);
182 }
183 
184 module_init(hp680bl_init);
185 module_exit(hp680bl_exit);
186 
187 MODULE_AUTHOR("Andriy Skulysh <askulysh@image.kiev.ua>");
188 MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver");
189 MODULE_LICENSE("GPL");
190