1
/*
2
 *
3
 * Backlight driver for HP Jornada 700 series (710/720/728)
4
 * Copyright (C) 2006-2009 Kristoffer Ericson <kristoffer.ericson@gmail.com>
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License version
8
 * 2 or any later version as published by the Free Software Foundation.
9
 *
10
 */
11
12
#include <linux/backlight.h>
13
#include <linux/device.h>
14
#include <linux/fb.h>
15
#include <linux/kernel.h>
16
#include <linux/module.h>
17
#include <linux/platform_device.h>
18
19
#include <mach/jornada720.h>
20
#include <mach/hardware.h>
21
22
#include <video/s1d13xxxfb.h>
23
24
#define BL_MAX_BRIGHT	255
25
#define BL_DEF_BRIGHT	25
26
27
static int jornada_bl_get_brightness(struct backlight_device *bd)
28
{
29
	int ret;
30
31
	/* check if backlight is on */
32
	if (!(PPSR & PPC_LDD1))
33
		return 0;
34
35
	jornada_ssp_start();
36
37
	/* cmd should return txdummy */
38
	ret = jornada_ssp_byte(GETBRIGHTNESS);
39
40
	if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
41
		printk(KERN_ERR "bl : get brightness timeout\n");
42
		jornada_ssp_end();
43
		return -ETIMEDOUT;
44
	} else /* exchange txdummy for value */
45
		ret = jornada_ssp_byte(TXDUMMY);
46
47
	jornada_ssp_end();
48
49
	return (BL_MAX_BRIGHT - ret);
50
}
51
52
static int jornada_bl_update_status(struct backlight_device *bd)
53
{
54
	int ret = 0;
55
56
	jornada_ssp_start();
57
58
	/* If backlight is off then really turn it off */
59
	if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
60
		ret = jornada_ssp_byte(BRIGHTNESSOFF);
61
		if (ret != TXDUMMY) {
62
			printk(KERN_INFO "bl : brightness off timeout\n");
63
			/* turn off backlight */
64
			PPSR &= ~PPC_LDD1;
65
			PPDR |= PPC_LDD1;
66
			ret = -ETIMEDOUT;
67
		}
68
	} else  /* turn on backlight */
69
		PPSR |= PPC_LDD1;
70
71
		/* send command to our mcu */
72
		if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
73
			printk(KERN_INFO "bl : failed to set brightness\n");
74
			ret = -ETIMEDOUT;
75
			goto out;
76
		}
77
78
		/* at this point we expect that the mcu has accepted
79
		   our command and is waiting for our new value
80
		   please note that maximum brightness is 255,
81
		   but due to physical layout it is equal to 0, so we simply
82
		   invert the value (MAX VALUE - NEW VALUE). */
83
		if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
84
			printk(KERN_ERR "bl : set brightness failed\n");
85
			ret = -ETIMEDOUT;
86
		}
87
88
		/* If infact we get an TXDUMMY as output we are happy and dont
89
		   make any further comments about it */
90
out:
91
	jornada_ssp_end();
92
93
	return ret;
94
}
95
96
static struct backlight_ops jornada_bl_ops = {
97
	.get_brightness = jornada_bl_get_brightness,
98
	.update_status = jornada_bl_update_status,
99
	.options = BL_CORE_SUSPENDRESUME,
100
};
101
102
static int jornada_bl_probe(struct platform_device *pdev)
103
{
104
	int ret;
105
	struct backlight_device *bd;
106
107
	bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL, &jornada_bl_ops);
108
109
	if (IS_ERR(bd)) {
110
		ret = PTR_ERR(bd);
111
		printk(KERN_ERR "bl : failed to register device, err=%x\n", ret);
112
		return ret;
113
	}
114
115
	bd->props.power = FB_BLANK_UNBLANK;
116
	bd->props.brightness = BL_DEF_BRIGHT;
117
	/* note. make sure max brightness is set otherwise
118
	   you will get seemingly non-related errors when
119
	   trying to change brightness */
120
	bd->props.max_brightness = BL_MAX_BRIGHT;
121
	jornada_bl_update_status(bd);
122
123
	platform_set_drvdata(pdev, bd);
124
	printk(KERN_INFO "HP Jornada 700 series backlight driver\n");
125
126
	return 0;
127
}
128
129
static int jornada_bl_remove(struct platform_device *pdev)
130
{
131
	struct backlight_device *bd = platform_get_drvdata(pdev);
132
133
	backlight_device_unregister(bd);
134
135
	return 0;
136
}
137
138
static struct platform_driver jornada_bl_driver = {
139
	.probe		= jornada_bl_probe,
140
	.remove		= jornada_bl_remove,
141
	.driver	= {
142
		.name	= "jornada_bl",
143
	},
144
};
145
146
int __init jornada_bl_init(void)
147
{
148
	return platform_driver_register(&jornada_bl_driver);
149
}
150
151
void __exit jornada_bl_exit(void)
152
{
153
	platform_driver_unregister(&jornada_bl_driver);
154
}
155
156
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>");
157
MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver");
158
MODULE_LICENSE("GPL");
159
160
module_init(jornada_bl_init);
161
module_exit(jornada_bl_exit);