xref: /openbmc/linux/drivers/video/backlight/hp680_bl.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
106c6f900SAndriy Skulysh /*
206c6f900SAndriy Skulysh  *  Backlight Driver for HP Jornada 680
306c6f900SAndriy Skulysh  *
406c6f900SAndriy Skulysh  *  Copyright (c) 2005 Andriy Skulysh
506c6f900SAndriy Skulysh  *
606c6f900SAndriy Skulysh  *  Based on Sharp's Corgi Backlight Driver
706c6f900SAndriy Skulysh  *
806c6f900SAndriy Skulysh  * This file is subject to the terms and conditions of the GNU General Public
906c6f900SAndriy Skulysh  * License.  See the file "COPYING" in the main directory of this archive
1006c6f900SAndriy Skulysh  * for more details.
1106c6f900SAndriy Skulysh  */
1206c6f900SAndriy Skulysh 
1306c6f900SAndriy Skulysh #include <linux/module.h>
1406c6f900SAndriy Skulysh #include <linux/kernel.h>
1506c6f900SAndriy Skulysh #include <linux/init.h>
165f27a27bSRichard Purdie #include <linux/platform_device.h>
1706c6f900SAndriy Skulysh #include <linux/spinlock.h>
1806c6f900SAndriy Skulysh #include <linux/fb.h>
1906c6f900SAndriy Skulysh #include <linux/backlight.h>
2006c6f900SAndriy Skulysh 
21193f3c2fSPaul Mundt #include <cpu/dac.h>
227639a454SPaul Mundt #include <mach/hp6xx.h>
23848dd265SAndriy Skulysh #include <asm/hd64461.h>
2406c6f900SAndriy Skulysh 
2506c6f900SAndriy Skulysh #define HP680_MAX_INTENSITY 255
2606c6f900SAndriy Skulysh #define HP680_DEFAULT_INTENSITY 10
2706c6f900SAndriy Skulysh 
285f27a27bSRichard Purdie static int hp680bl_suspended;
29ff10b074SJingoo Han static int current_intensity;
3034af946aSIngo Molnar static DEFINE_SPINLOCK(bl_lock);
3106c6f900SAndriy Skulysh 
hp680bl_send_intensity(struct backlight_device * bd)325f27a27bSRichard Purdie static void hp680bl_send_intensity(struct backlight_device *bd)
3306c6f900SAndriy Skulysh {
3406c6f900SAndriy Skulysh 	unsigned long flags;
355f27a27bSRichard Purdie 	u16 v;
3651d53e5bSSam Ravnborg 	int intensity = backlight_get_brightness(bd);
3706c6f900SAndriy Skulysh 
385f27a27bSRichard Purdie 	if (hp680bl_suspended)
3906c6f900SAndriy Skulysh 		intensity = 0;
4006c6f900SAndriy Skulysh 
4106c6f900SAndriy Skulysh 	spin_lock_irqsave(&bl_lock, flags);
425f27a27bSRichard Purdie 	if (intensity && current_intensity == 0) {
4306c6f900SAndriy Skulysh 		sh_dac_enable(DAC_LCD_BRIGHTNESS);
4406c6f900SAndriy Skulysh 		v = inw(HD64461_GPBDR);
4506c6f900SAndriy Skulysh 		v &= ~HD64461_GPBDR_LCDOFF;
4606c6f900SAndriy Skulysh 		outw(v, HD64461_GPBDR);
475f27a27bSRichard Purdie 		sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
485f27a27bSRichard Purdie 	} else if (intensity == 0 && current_intensity != 0) {
495f27a27bSRichard Purdie 		sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
505f27a27bSRichard Purdie 		sh_dac_disable(DAC_LCD_BRIGHTNESS);
515f27a27bSRichard Purdie 		v = inw(HD64461_GPBDR);
525f27a27bSRichard Purdie 		v |= HD64461_GPBDR_LCDOFF;
535f27a27bSRichard Purdie 		outw(v, HD64461_GPBDR);
545f27a27bSRichard Purdie 	} else if (intensity) {
555f27a27bSRichard Purdie 		sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS);
5606c6f900SAndriy Skulysh 	}
575f27a27bSRichard Purdie 	spin_unlock_irqrestore(&bl_lock, flags);
585f27a27bSRichard Purdie 
595f27a27bSRichard Purdie 	current_intensity = intensity;
6006c6f900SAndriy Skulysh }
6106c6f900SAndriy Skulysh 
625f27a27bSRichard Purdie 
63b55bb78dSJingoo Han #ifdef CONFIG_PM_SLEEP
hp680bl_suspend(struct device * dev)64b55bb78dSJingoo Han static int hp680bl_suspend(struct device *dev)
6506c6f900SAndriy Skulysh {
66b55bb78dSJingoo Han 	struct backlight_device *bd = dev_get_drvdata(dev);
67a8db3c19SRichard Purdie 
685f27a27bSRichard Purdie 	hp680bl_suspended = 1;
69a8db3c19SRichard Purdie 	hp680bl_send_intensity(bd);
7006c6f900SAndriy Skulysh 	return 0;
7106c6f900SAndriy Skulysh }
7206c6f900SAndriy Skulysh 
hp680bl_resume(struct device * dev)73b55bb78dSJingoo Han static int hp680bl_resume(struct device *dev)
7406c6f900SAndriy Skulysh {
75b55bb78dSJingoo Han 	struct backlight_device *bd = dev_get_drvdata(dev);
76a8db3c19SRichard Purdie 
775f27a27bSRichard Purdie 	hp680bl_suspended = 0;
78a8db3c19SRichard Purdie 	hp680bl_send_intensity(bd);
7906c6f900SAndriy Skulysh 	return 0;
8006c6f900SAndriy Skulysh }
8106c6f900SAndriy Skulysh #endif
8206c6f900SAndriy Skulysh 
83b55bb78dSJingoo Han static SIMPLE_DEV_PM_OPS(hp680bl_pm_ops, hp680bl_suspend, hp680bl_resume);
84b55bb78dSJingoo Han 
hp680bl_set_intensity(struct backlight_device * bd)855f27a27bSRichard Purdie static int hp680bl_set_intensity(struct backlight_device *bd)
8606c6f900SAndriy Skulysh {
875f27a27bSRichard Purdie 	hp680bl_send_intensity(bd);
8806c6f900SAndriy Skulysh 	return 0;
8906c6f900SAndriy Skulysh }
9006c6f900SAndriy Skulysh 
hp680bl_get_intensity(struct backlight_device * bd)9106c6f900SAndriy Skulysh static int hp680bl_get_intensity(struct backlight_device *bd)
9206c6f900SAndriy Skulysh {
9306c6f900SAndriy Skulysh 	return current_intensity;
9406c6f900SAndriy Skulysh }
9506c6f900SAndriy Skulysh 
969905a43bSEmese Revfy static const struct backlight_ops hp680bl_ops = {
9706c6f900SAndriy Skulysh 	.get_brightness = hp680bl_get_intensity,
985f27a27bSRichard Purdie 	.update_status  = hp680bl_set_intensity,
9906c6f900SAndriy Skulysh };
10006c6f900SAndriy Skulysh 
hp680bl_probe(struct platform_device * pdev)1011b9e450dSBill Pemberton static int hp680bl_probe(struct platform_device *pdev)
10206c6f900SAndriy Skulysh {
103a19a6ee6SMatthew Garrett 	struct backlight_properties props;
104a8db3c19SRichard Purdie 	struct backlight_device *bd;
10506c6f900SAndriy Skulysh 
106a19a6ee6SMatthew Garrett 	memset(&props, 0, sizeof(struct backlight_properties));
107bb7ca747SMatthew Garrett 	props.type = BACKLIGHT_RAW;
108a19a6ee6SMatthew Garrett 	props.max_brightness = HP680_MAX_INTENSITY;
1090561c179SJingoo Han 	bd = devm_backlight_device_register(&pdev->dev, "hp680-bl", &pdev->dev,
1100561c179SJingoo Han 					NULL, &hp680bl_ops, &props);
111a8db3c19SRichard Purdie 	if (IS_ERR(bd))
112a8db3c19SRichard Purdie 		return PTR_ERR(bd);
113a8db3c19SRichard Purdie 
114a8db3c19SRichard Purdie 	platform_set_drvdata(pdev, bd);
115a8db3c19SRichard Purdie 
116599a52d1SRichard Purdie 	bd->props.brightness = HP680_DEFAULT_INTENSITY;
117a8db3c19SRichard Purdie 	hp680bl_send_intensity(bd);
11806c6f900SAndriy Skulysh 
11906c6f900SAndriy Skulysh 	return 0;
12006c6f900SAndriy Skulysh }
12106c6f900SAndriy Skulysh 
hp680bl_remove(struct platform_device * pdev)122*7150f8c2SUwe Kleine-König static void hp680bl_remove(struct platform_device *pdev)
12306c6f900SAndriy Skulysh {
124a8db3c19SRichard Purdie 	struct backlight_device *bd = platform_get_drvdata(pdev);
125a8db3c19SRichard Purdie 
126eb650d67SKristoffer Ericson 	bd->props.brightness = 0;
127eb650d67SKristoffer Ericson 	bd->props.power = 0;
128a8db3c19SRichard Purdie 	hp680bl_send_intensity(bd);
12906c6f900SAndriy Skulysh }
13006c6f900SAndriy Skulysh 
1315f27a27bSRichard Purdie static struct platform_driver hp680bl_driver = {
13206c6f900SAndriy Skulysh 	.probe		= hp680bl_probe,
133*7150f8c2SUwe Kleine-König 	.remove_new	= hp680bl_remove,
1345f27a27bSRichard Purdie 	.driver		= {
1355f27a27bSRichard Purdie 		.name	= "hp680-bl",
136b55bb78dSJingoo Han 		.pm	= &hp680bl_pm_ops,
1375f27a27bSRichard Purdie 	},
13806c6f900SAndriy Skulysh };
13906c6f900SAndriy Skulysh 
1405f27a27bSRichard Purdie static struct platform_device *hp680bl_device;
14106c6f900SAndriy Skulysh 
hp680bl_init(void)14206c6f900SAndriy Skulysh static int __init hp680bl_init(void)
14306c6f900SAndriy Skulysh {
14406c6f900SAndriy Skulysh 	int ret;
14506c6f900SAndriy Skulysh 
1465f27a27bSRichard Purdie 	ret = platform_driver_register(&hp680bl_driver);
1473bcdcc0eSAkinobu Mita 	if (ret)
14806c6f900SAndriy Skulysh 		return ret;
1493bcdcc0eSAkinobu Mita 	hp680bl_device = platform_device_register_simple("hp680-bl", -1,
1503bcdcc0eSAkinobu Mita 							NULL, 0);
1513bcdcc0eSAkinobu Mita 	if (IS_ERR(hp680bl_device)) {
1523bcdcc0eSAkinobu Mita 		platform_driver_unregister(&hp680bl_driver);
1533bcdcc0eSAkinobu Mita 		return PTR_ERR(hp680bl_device);
1543bcdcc0eSAkinobu Mita 	}
1553bcdcc0eSAkinobu Mita 	return 0;
15606c6f900SAndriy Skulysh }
15706c6f900SAndriy Skulysh 
hp680bl_exit(void)15806c6f900SAndriy Skulysh static void __exit hp680bl_exit(void)
15906c6f900SAndriy Skulysh {
1605f27a27bSRichard Purdie 	platform_device_unregister(hp680bl_device);
1615f27a27bSRichard Purdie 	platform_driver_unregister(&hp680bl_driver);
16206c6f900SAndriy Skulysh }
16306c6f900SAndriy Skulysh 
16406c6f900SAndriy Skulysh module_init(hp680bl_init);
16506c6f900SAndriy Skulysh module_exit(hp680bl_exit);
16606c6f900SAndriy Skulysh 
167848dd265SAndriy Skulysh MODULE_AUTHOR("Andriy Skulysh <askulysh@gmail.com>");
16806c6f900SAndriy Skulysh MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver");
16906c6f900SAndriy Skulysh MODULE_LICENSE("GPL");
170