blob: 16f593b64427a606093f1c14dce6498ab791a5cb [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
Jingoo Han20c225c2012-05-29 15:07:18 -070012#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000014#include <linux/backlight.h>
15#include <linux/device.h>
16#include <linux/fb.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/platform_device.h>
20
21#include <mach/jornada720.h>
22#include <mach/hardware.h>
23
24#include <video/s1d13xxxfb.h>
25
26#define BL_MAX_BRIGHT 255
27#define BL_DEF_BRIGHT 25
28
29static int jornada_bl_get_brightness(struct backlight_device *bd)
30{
31 int ret;
32
33 /* check if backlight is on */
34 if (!(PPSR & PPC_LDD1))
35 return 0;
36
37 jornada_ssp_start();
38
39 /* cmd should return txdummy */
40 ret = jornada_ssp_byte(GETBRIGHTNESS);
41
42 if (jornada_ssp_byte(GETBRIGHTNESS) != TXDUMMY) {
Jingoo Han20c225c2012-05-29 15:07:18 -070043 pr_err("get brightness timeout\n");
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000044 jornada_ssp_end();
45 return -ETIMEDOUT;
46 } else /* exchange txdummy for value */
47 ret = jornada_ssp_byte(TXDUMMY);
48
49 jornada_ssp_end();
50
51 return (BL_MAX_BRIGHT - ret);
52}
53
54static int jornada_bl_update_status(struct backlight_device *bd)
55{
56 int ret = 0;
57
58 jornada_ssp_start();
59
60 /* If backlight is off then really turn it off */
61 if ((bd->props.power != FB_BLANK_UNBLANK) || (bd->props.fb_blank != FB_BLANK_UNBLANK)) {
62 ret = jornada_ssp_byte(BRIGHTNESSOFF);
63 if (ret != TXDUMMY) {
Jingoo Han20c225c2012-05-29 15:07:18 -070064 pr_info("brightness off timeout\n");
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000065 /* turn off backlight */
66 PPSR &= ~PPC_LDD1;
67 PPDR |= PPC_LDD1;
68 ret = -ETIMEDOUT;
69 }
70 } else /* turn on backlight */
71 PPSR |= PPC_LDD1;
72
73 /* send command to our mcu */
74 if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
Jingoo Han20c225c2012-05-29 15:07:18 -070075 pr_info("failed to set brightness\n");
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000076 ret = -ETIMEDOUT;
Kristoffer Ericsonb317c8332009-07-29 15:04:03 -070077 goto out;
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000078 }
79
80 /* at this point we expect that the mcu has accepted
81 our command and is waiting for our new value
82 please note that maximum brightness is 255,
83 but due to physical layout it is equal to 0, so we simply
84 invert the value (MAX VALUE - NEW VALUE). */
85 if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
Jingoo Han20c225c2012-05-29 15:07:18 -070086 pr_err("set brightness failed\n");
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000087 ret = -ETIMEDOUT;
88 }
89
90 /* If infact we get an TXDUMMY as output we are happy and dont
91 make any further comments about it */
92out:
93 jornada_ssp_end();
94
95 return ret;
96}
97
Emese Revfy9905a432009-12-14 00:58:57 +010098static const struct backlight_ops jornada_bl_ops = {
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +000099 .get_brightness = jornada_bl_get_brightness,
100 .update_status = jornada_bl_update_status,
101 .options = BL_CORE_SUSPENDRESUME,
102};
103
104static int jornada_bl_probe(struct platform_device *pdev)
105{
Matthew Garretta19a6ee2010-02-17 16:39:44 -0500106 struct backlight_properties props;
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000107 int ret;
108 struct backlight_device *bd;
109
Matthew Garretta19a6ee2010-02-17 16:39:44 -0500110 memset(&props, 0, sizeof(struct backlight_properties));
Matthew Garrettbb7ca742011-03-22 16:30:21 -0700111 props.type = BACKLIGHT_RAW;
Matthew Garretta19a6ee2010-02-17 16:39:44 -0500112 props.max_brightness = BL_MAX_BRIGHT;
113 bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
114 &jornada_bl_ops, &props);
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000115
116 if (IS_ERR(bd)) {
117 ret = PTR_ERR(bd);
Jingoo Han20c225c2012-05-29 15:07:18 -0700118 pr_err("failed to register device, err=%x\n", ret);
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000119 return ret;
120 }
121
122 bd->props.power = FB_BLANK_UNBLANK;
123 bd->props.brightness = BL_DEF_BRIGHT;
124 /* note. make sure max brightness is set otherwise
125 you will get seemingly non-related errors when
126 trying to change brightness */
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000127 jornada_bl_update_status(bd);
128
129 platform_set_drvdata(pdev, bd);
Jingoo Han20c225c2012-05-29 15:07:18 -0700130 pr_info("HP Jornada 700 series backlight driver\n");
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000131
132 return 0;
133}
134
135static int jornada_bl_remove(struct platform_device *pdev)
136{
137 struct backlight_device *bd = platform_get_drvdata(pdev);
138
139 backlight_device_unregister(bd);
140
141 return 0;
142}
143
144static struct platform_driver jornada_bl_driver = {
145 .probe = jornada_bl_probe,
146 .remove = jornada_bl_remove,
147 .driver = {
148 .name = "jornada_bl",
149 },
150};
151
Axel Lin81178e02012-01-10 15:09:11 -0800152module_platform_driver(jornada_bl_driver);
Kristoffer Ericson13a7b5d2009-02-18 11:50:43 +0000153
154MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>");
155MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver");
156MODULE_LICENSE("GPL");