2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * PCF50633 backlight device driver
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <linux/platform_device.h>
21 #include <linux/backlight.h>
24 #include <linux/mfd/pcf50633/core.h>
25 #include <linux/mfd/pcf50633/backlight.h>
29 struct backlight_device
*bl
;
31 unsigned int brightness
;
32 unsigned int brightness_limit
;
36 * pcf50633_bl_set_brightness_limit
38 * Update the brightness limit for the pc50633 backlight. The actual brightness
39 * will not go above the limit. This is useful to limit power drain for example
42 * @dev: Pointer to a pcf50633 device
43 * @limit: The brightness limit. Valid values are 0-63
45 int pcf50633_bl_set_brightness_limit(struct pcf50633
*pcf
, unsigned int limit
)
47 struct pcf50633_bl
*pcf_bl
= platform_get_drvdata(pcf
->bl_pdev
);
52 pcf_bl
->brightness_limit
= limit
& 0x3f;
53 backlight_update_status(pcf_bl
->bl
);
58 static int pcf50633_bl_update_status(struct backlight_device
*bl
)
60 struct pcf50633_bl
*pcf_bl
= bl_get_data(bl
);
61 unsigned int new_brightness
;
64 if (bl
->props
.state
& (BL_CORE_SUSPENDED
| BL_CORE_FBBLANK
) ||
65 bl
->props
.power
!= FB_BLANK_UNBLANK
)
67 else if (bl
->props
.brightness
< pcf_bl
->brightness_limit
)
68 new_brightness
= bl
->props
.brightness
;
70 new_brightness
= pcf_bl
->brightness_limit
;
73 if (pcf_bl
->brightness
== new_brightness
)
77 pcf50633_reg_write(pcf_bl
->pcf
, PCF50633_REG_LEDOUT
,
79 if (!pcf_bl
->brightness
)
80 pcf50633_reg_write(pcf_bl
->pcf
, PCF50633_REG_LEDENA
, 1);
82 pcf50633_reg_write(pcf_bl
->pcf
, PCF50633_REG_LEDENA
, 0);
85 pcf_bl
->brightness
= new_brightness
;
90 static int pcf50633_bl_get_brightness(struct backlight_device
*bl
)
92 struct pcf50633_bl
*pcf_bl
= bl_get_data(bl
);
93 return pcf_bl
->brightness
;
96 static const struct backlight_ops pcf50633_bl_ops
= {
97 .get_brightness
= pcf50633_bl_get_brightness
,
98 .update_status
= pcf50633_bl_update_status
,
99 .options
= BL_CORE_SUSPENDRESUME
,
102 static int __devinit
pcf50633_bl_probe(struct platform_device
*pdev
)
105 struct pcf50633_bl
*pcf_bl
;
106 struct device
*parent
= pdev
->dev
.parent
;
107 struct pcf50633_platform_data
*pcf50633_data
= parent
->platform_data
;
108 struct pcf50633_bl_platform_data
*pdata
= pcf50633_data
->backlight_data
;
109 struct backlight_properties bl_props
;
111 pcf_bl
= kzalloc(sizeof(*pcf_bl
), GFP_KERNEL
);
115 bl_props
.type
= BACKLIGHT_RAW
;
116 bl_props
.max_brightness
= 0x3f;
117 bl_props
.power
= FB_BLANK_UNBLANK
;
120 bl_props
.brightness
= pdata
->default_brightness
;
121 pcf_bl
->brightness_limit
= pdata
->default_brightness_limit
;
123 bl_props
.brightness
= 0x3f;
124 pcf_bl
->brightness_limit
= 0x3f;
127 pcf_bl
->pcf
= dev_to_pcf50633(pdev
->dev
.parent
);
129 pcf_bl
->bl
= backlight_device_register(pdev
->name
, &pdev
->dev
, pcf_bl
,
130 &pcf50633_bl_ops
, &bl_props
);
132 if (IS_ERR(pcf_bl
->bl
)) {
133 ret
= PTR_ERR(pcf_bl
->bl
);
137 platform_set_drvdata(pdev
, pcf_bl
);
139 pcf50633_reg_write(pcf_bl
->pcf
, PCF50633_REG_LEDDIM
, pdata
->ramp_time
);
141 /* Should be different from bl_props.brightness, so we do not exit
142 * update_status early the first time it's called */
143 pcf_bl
->brightness
= pcf_bl
->bl
->props
.brightness
+ 1;
145 backlight_update_status(pcf_bl
->bl
);
155 static int __devexit
pcf50633_bl_remove(struct platform_device
*pdev
)
157 struct pcf50633_bl
*pcf_bl
= platform_get_drvdata(pdev
);
159 backlight_device_unregister(pcf_bl
->bl
);
161 platform_set_drvdata(pdev
, NULL
);
168 static struct platform_driver pcf50633_bl_driver
= {
169 .probe
= pcf50633_bl_probe
,
170 .remove
= __devexit_p(pcf50633_bl_remove
),
172 .name
= "pcf50633-backlight",
176 static int __init
pcf50633_bl_init(void)
178 return platform_driver_register(&pcf50633_bl_driver
);
180 module_init(pcf50633_bl_init
);
182 static void __exit
pcf50633_bl_exit(void)
184 platform_driver_unregister(&pcf50633_bl_driver
);
186 module_exit(pcf50633_bl_exit
);
188 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
189 MODULE_DESCRIPTION("PCF50633 backlight driver");
190 MODULE_LICENSE("GPL");
191 MODULE_ALIAS("platform:pcf50633-backlight");