1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
4 * PCF50633 backlight device driver
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/slab.h>
10 #include <linux/platform_device.h>
12 #include <linux/backlight.h>
14 #include <linux/mfd/pcf50633/core.h>
15 #include <linux/mfd/pcf50633/backlight.h>
19 struct backlight_device
*bl
;
21 unsigned int brightness
;
22 unsigned int brightness_limit
;
26 * pcf50633_bl_set_brightness_limit
28 * Update the brightness limit for the pc50633 backlight. The actual brightness
29 * will not go above the limit. This is useful to limit power drain for example
32 * @dev: Pointer to a pcf50633 device
33 * @limit: The brightness limit. Valid values are 0-63
35 int pcf50633_bl_set_brightness_limit(struct pcf50633
*pcf
, unsigned int limit
)
37 struct pcf50633_bl
*pcf_bl
= platform_get_drvdata(pcf
->bl_pdev
);
42 pcf_bl
->brightness_limit
= limit
& 0x3f;
43 backlight_update_status(pcf_bl
->bl
);
48 static int pcf50633_bl_update_status(struct backlight_device
*bl
)
50 struct pcf50633_bl
*pcf_bl
= bl_get_data(bl
);
51 unsigned int new_brightness
;
54 if (bl
->props
.state
& (BL_CORE_SUSPENDED
| BL_CORE_FBBLANK
) ||
55 bl
->props
.power
!= BACKLIGHT_POWER_ON
)
57 else if (bl
->props
.brightness
< pcf_bl
->brightness_limit
)
58 new_brightness
= bl
->props
.brightness
;
60 new_brightness
= pcf_bl
->brightness_limit
;
63 if (pcf_bl
->brightness
== new_brightness
)
67 pcf50633_reg_write(pcf_bl
->pcf
, PCF50633_REG_LEDOUT
,
69 if (!pcf_bl
->brightness
)
70 pcf50633_reg_write(pcf_bl
->pcf
, PCF50633_REG_LEDENA
, 1);
72 pcf50633_reg_write(pcf_bl
->pcf
, PCF50633_REG_LEDENA
, 0);
75 pcf_bl
->brightness
= new_brightness
;
80 static int pcf50633_bl_get_brightness(struct backlight_device
*bl
)
82 struct pcf50633_bl
*pcf_bl
= bl_get_data(bl
);
84 return pcf_bl
->brightness
;
87 static const struct backlight_ops pcf50633_bl_ops
= {
88 .get_brightness
= pcf50633_bl_get_brightness
,
89 .update_status
= pcf50633_bl_update_status
,
90 .options
= BL_CORE_SUSPENDRESUME
,
93 static int pcf50633_bl_probe(struct platform_device
*pdev
)
95 struct pcf50633_bl
*pcf_bl
;
96 struct device
*parent
= pdev
->dev
.parent
;
97 struct pcf50633_platform_data
*pcf50633_data
= dev_get_platdata(parent
);
98 struct pcf50633_bl_platform_data
*pdata
= pcf50633_data
->backlight_data
;
99 struct backlight_properties bl_props
;
101 pcf_bl
= devm_kzalloc(&pdev
->dev
, sizeof(*pcf_bl
), GFP_KERNEL
);
105 memset(&bl_props
, 0, sizeof(bl_props
));
106 bl_props
.type
= BACKLIGHT_RAW
;
107 bl_props
.max_brightness
= 0x3f;
108 bl_props
.power
= BACKLIGHT_POWER_ON
;
111 bl_props
.brightness
= pdata
->default_brightness
;
112 pcf_bl
->brightness_limit
= pdata
->default_brightness_limit
;
114 bl_props
.brightness
= 0x3f;
115 pcf_bl
->brightness_limit
= 0x3f;
118 pcf_bl
->pcf
= dev_to_pcf50633(pdev
->dev
.parent
);
120 pcf_bl
->bl
= devm_backlight_device_register(&pdev
->dev
, pdev
->name
,
122 &pcf50633_bl_ops
, &bl_props
);
124 if (IS_ERR(pcf_bl
->bl
))
125 return PTR_ERR(pcf_bl
->bl
);
127 platform_set_drvdata(pdev
, pcf_bl
);
129 pcf50633_reg_write(pcf_bl
->pcf
, PCF50633_REG_LEDDIM
, pdata
->ramp_time
);
132 * Should be different from bl_props.brightness, so we do not exit
133 * update_status early the first time it's called
135 pcf_bl
->brightness
= pcf_bl
->bl
->props
.brightness
+ 1;
137 backlight_update_status(pcf_bl
->bl
);
142 static struct platform_driver pcf50633_bl_driver
= {
143 .probe
= pcf50633_bl_probe
,
145 .name
= "pcf50633-backlight",
149 module_platform_driver(pcf50633_bl_driver
);
151 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
152 MODULE_DESCRIPTION("PCF50633 backlight driver");
153 MODULE_LICENSE("GPL");
154 MODULE_ALIAS("platform:pcf50633-backlight");