xref: /linux/drivers/video/backlight/hp680_bl.c (revision 2d8ad8719591fa803b0d589ed057fa46f49b7155)
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/platform_device.h>
17  #include <linux/spinlock.h>
18  #include <linux/fb.h>
19  #include <linux/backlight.h>
20  
21  #include <cpu/dac.h>
22  #include <mach/hp6xx.h>
23  #include <asm/hd64461.h>
24  
25  #define HP680_MAX_INTENSITY 255
26  #define HP680_DEFAULT_INTENSITY 10
27  
28  static int hp680bl_suspended;
29  static int current_intensity = 0;
30  static DEFINE_SPINLOCK(bl_lock);
31  
32  static void hp680bl_send_intensity(struct backlight_device *bd)
33  {
34  	unsigned long flags;
35  	u16 v;
36  	int intensity = bd->props.brightness;
37  
38  	if (bd->props.power != FB_BLANK_UNBLANK)
39  		intensity = 0;
40  	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
41  		intensity = 0;
42  	if (hp680bl_suspended)
43  		intensity = 0;
44  
45  	spin_lock_irqsave(&bl_lock, flags);
46  	if (intensity && current_intensity == 0) {
47  		sh_dac_enable(DAC_LCD_BRIGHTNESS);
48  		v = inw(HD64461_GPBDR);
49  		v &= ~HD64461_GPBDR_LCDOFF;
50  		outw(v, HD64461_GPBDR);
51  		sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
52  	} else if (intensity == 0 && current_intensity != 0) {
53  		sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
54  		sh_dac_disable(DAC_LCD_BRIGHTNESS);
55  		v = inw(HD64461_GPBDR);
56  		v |= HD64461_GPBDR_LCDOFF;
57  		outw(v, HD64461_GPBDR);
58  	} else if (intensity) {
59  		sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
60  	}
61  	spin_unlock_irqrestore(&bl_lock, flags);
62  
63  	current_intensity = intensity;
64  }
65  
66  
67  #ifdef CONFIG_PM
68  static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state)
69  {
70  	struct backlight_device *bd = platform_get_drvdata(pdev);
71  
72  	hp680bl_suspended = 1;
73  	hp680bl_send_intensity(bd);
74  	return 0;
75  }
76  
77  static int hp680bl_resume(struct platform_device *pdev)
78  {
79  	struct backlight_device *bd = platform_get_drvdata(pdev);
80  
81  	hp680bl_suspended = 0;
82  	hp680bl_send_intensity(bd);
83  	return 0;
84  }
85  #else
86  #define hp680bl_suspend	NULL
87  #define hp680bl_resume	NULL
88  #endif
89  
90  static int hp680bl_set_intensity(struct backlight_device *bd)
91  {
92  	hp680bl_send_intensity(bd);
93  	return 0;
94  }
95  
96  static int hp680bl_get_intensity(struct backlight_device *bd)
97  {
98  	return current_intensity;
99  }
100  
101  static const struct backlight_ops hp680bl_ops = {
102  	.get_brightness = hp680bl_get_intensity,
103  	.update_status  = hp680bl_set_intensity,
104  };
105  
106  static int __devinit hp680bl_probe(struct platform_device *pdev)
107  {
108  	struct backlight_properties props;
109  	struct backlight_device *bd;
110  
111  	memset(&props, 0, sizeof(struct backlight_properties));
112  	props.max_brightness = HP680_MAX_INTENSITY;
113  	bd = backlight_device_register("hp680-bl", &pdev->dev, NULL,
114  				       &hp680bl_ops, &props);
115  	if (IS_ERR(bd))
116  		return PTR_ERR(bd);
117  
118  	platform_set_drvdata(pdev, bd);
119  
120  	bd->props.brightness = HP680_DEFAULT_INTENSITY;
121  	hp680bl_send_intensity(bd);
122  
123  	return 0;
124  }
125  
126  static int hp680bl_remove(struct platform_device *pdev)
127  {
128  	struct backlight_device *bd = platform_get_drvdata(pdev);
129  
130  	bd->props.brightness = 0;
131  	bd->props.power = 0;
132  	hp680bl_send_intensity(bd);
133  
134  	backlight_device_unregister(bd);
135  
136  	return 0;
137  }
138  
139  static struct platform_driver hp680bl_driver = {
140  	.probe		= hp680bl_probe,
141  	.remove		= hp680bl_remove,
142  	.suspend	= hp680bl_suspend,
143  	.resume		= hp680bl_resume,
144  	.driver		= {
145  		.name	= "hp680-bl",
146  	},
147  };
148  
149  static struct platform_device *hp680bl_device;
150  
151  static int __init hp680bl_init(void)
152  {
153  	int ret;
154  
155  	ret = platform_driver_register(&hp680bl_driver);
156  	if (ret)
157  		return ret;
158  	hp680bl_device = platform_device_register_simple("hp680-bl", -1,
159  							NULL, 0);
160  	if (IS_ERR(hp680bl_device)) {
161  		platform_driver_unregister(&hp680bl_driver);
162  		return PTR_ERR(hp680bl_device);
163  	}
164  	return 0;
165  }
166  
167  static void __exit hp680bl_exit(void)
168  {
169  	platform_device_unregister(hp680bl_device);
170   	platform_driver_unregister(&hp680bl_driver);
171  }
172  
173  module_init(hp680bl_init);
174  module_exit(hp680bl_exit);
175  
176  MODULE_AUTHOR("Andriy Skulysh <askulysh@gmail.com>");
177  MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver");
178  MODULE_LICENSE("GPL");
179