blob: 2f177b3a4885c1658685712703d266184b5b35ed [file] [log] [blame]
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +00001/*
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
27static 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
52static 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;
Kristoffer Ericsonb317c8332009-07-29 15:04:03 -070075 goto out;
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000076 }
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 */
90out:
91 jornada_ssp_end();
92
93 return ret;
94}
95
Emese Revfy9905a432009-12-14 00:58:57 +010096static const struct backlight_ops jornada_bl_ops = {
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000097 .get_brightness = jornada_bl_get_brightness,
98 .update_status = jornada_bl_update_status,
99 .options = BL_CORE_SUSPENDRESUME,
100};
101
102static int jornada_bl_probe(struct platform_device *pdev)
103{
Matthew Garretta19a6ee2010-02-17 16:39:44 -0500104 struct backlight_properties props;
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000105 int ret;
106 struct backlight_device *bd;
107
Matthew Garretta19a6ee2010-02-17 16:39:44 -0500108 memset(&props, 0, sizeof(struct backlight_properties));
109 props.max_brightness = BL_MAX_BRIGHT;
110 bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
111 &jornada_bl_ops, &props);
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000112
113 if (IS_ERR(bd)) {
114 ret = PTR_ERR(bd);
115 printk(KERN_ERR "bl : failed to register device, err=%x\n", ret);
116 return ret;
117 }
118
119 bd->props.power = FB_BLANK_UNBLANK;
120 bd->props.brightness = BL_DEF_BRIGHT;
121 /* note. make sure max brightness is set otherwise
122 you will get seemingly non-related errors when
123 trying to change brightness */
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000124 jornada_bl_update_status(bd);
125
126 platform_set_drvdata(pdev, bd);
127 printk(KERN_INFO "HP Jornada 700 series backlight driver\n");
128
129 return 0;
130}
131
132static int jornada_bl_remove(struct platform_device *pdev)
133{
134 struct backlight_device *bd = platform_get_drvdata(pdev);
135
136 backlight_device_unregister(bd);
137
138 return 0;
139}
140
141static struct platform_driver jornada_bl_driver = {
142 .probe = jornada_bl_probe,
143 .remove = jornada_bl_remove,
144 .driver = {
145 .name = "jornada_bl",
146 },
147};
148
149int __init jornada_bl_init(void)
150{
151 return platform_driver_register(&jornada_bl_driver);
152}
153
154void __exit jornada_bl_exit(void)
155{
156 platform_driver_unregister(&jornada_bl_driver);
157}
158
159MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>");
160MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver");
161MODULE_LICENSE("GPL");
162
163module_init(jornada_bl_init);
164module_exit(jornada_bl_exit);