1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * lm3533-bl.c -- LM3533 Backlight driver
5 * Copyright (C) 2011-2012 Texas Instruments
7 * Author: Johan Hovold <jhovold@gmail.com>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/platform_device.h>
13 #include <linux/backlight.h>
14 #include <linux/slab.h>
16 #include <linux/mfd/lm3533.h>
19 #define LM3533_HVCTRLBANK_COUNT 2
20 #define LM3533_BL_MAX_BRIGHTNESS 255
22 #define LM3533_REG_CTRLBANK_AB_BCONF 0x1a
26 struct lm3533
*lm3533
;
27 struct lm3533_ctrlbank cb
;
28 struct backlight_device
*bd
;
33 static inline int lm3533_bl_get_ctrlbank_id(struct lm3533_bl
*bl
)
38 static int lm3533_bl_update_status(struct backlight_device
*bd
)
40 struct lm3533_bl
*bl
= bl_get_data(bd
);
42 return lm3533_ctrlbank_set_brightness(&bl
->cb
, backlight_get_brightness(bd
));
45 static int lm3533_bl_get_brightness(struct backlight_device
*bd
)
47 struct lm3533_bl
*bl
= bl_get_data(bd
);
51 ret
= lm3533_ctrlbank_get_brightness(&bl
->cb
, &val
);
58 static const struct backlight_ops lm3533_bl_ops
= {
59 .get_brightness
= lm3533_bl_get_brightness
,
60 .update_status
= lm3533_bl_update_status
,
63 static ssize_t
show_id(struct device
*dev
,
64 struct device_attribute
*attr
, char *buf
)
66 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
68 return scnprintf(buf
, PAGE_SIZE
, "%d\n", bl
->id
);
71 static ssize_t
show_als_channel(struct device
*dev
,
72 struct device_attribute
*attr
, char *buf
)
74 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
75 unsigned channel
= lm3533_bl_get_ctrlbank_id(bl
);
77 return scnprintf(buf
, PAGE_SIZE
, "%u\n", channel
);
80 static ssize_t
show_als_en(struct device
*dev
,
81 struct device_attribute
*attr
, char *buf
)
83 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
84 int ctrlbank
= lm3533_bl_get_ctrlbank_id(bl
);
90 ret
= lm3533_read(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, &val
);
94 mask
= 1 << (2 * ctrlbank
);
97 return scnprintf(buf
, PAGE_SIZE
, "%d\n", enable
);
100 static ssize_t
store_als_en(struct device
*dev
,
101 struct device_attribute
*attr
,
102 const char *buf
, size_t len
)
104 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
105 int ctrlbank
= lm3533_bl_get_ctrlbank_id(bl
);
111 if (kstrtoint(buf
, 0, &enable
))
114 mask
= 1 << (2 * ctrlbank
);
121 ret
= lm3533_update(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, val
,
129 static ssize_t
show_linear(struct device
*dev
,
130 struct device_attribute
*attr
, char *buf
)
132 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
138 ret
= lm3533_read(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, &val
);
142 mask
= 1 << (2 * lm3533_bl_get_ctrlbank_id(bl
) + 1);
149 return scnprintf(buf
, PAGE_SIZE
, "%x\n", linear
);
152 static ssize_t
store_linear(struct device
*dev
,
153 struct device_attribute
*attr
,
154 const char *buf
, size_t len
)
156 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
157 unsigned long linear
;
162 if (kstrtoul(buf
, 0, &linear
))
165 mask
= 1 << (2 * lm3533_bl_get_ctrlbank_id(bl
) + 1);
172 ret
= lm3533_update(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, val
,
180 static ssize_t
show_pwm(struct device
*dev
,
181 struct device_attribute
*attr
,
184 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
188 ret
= lm3533_ctrlbank_get_pwm(&bl
->cb
, &val
);
192 return scnprintf(buf
, PAGE_SIZE
, "%u\n", val
);
195 static ssize_t
store_pwm(struct device
*dev
,
196 struct device_attribute
*attr
,
197 const char *buf
, size_t len
)
199 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
203 if (kstrtou8(buf
, 0, &val
))
206 ret
= lm3533_ctrlbank_set_pwm(&bl
->cb
, val
);
213 static LM3533_ATTR_RO(als_channel
);
214 static LM3533_ATTR_RW(als_en
);
215 static LM3533_ATTR_RO(id
);
216 static LM3533_ATTR_RW(linear
);
217 static LM3533_ATTR_RW(pwm
);
219 static struct attribute
*lm3533_bl_attributes
[] = {
220 &dev_attr_als_channel
.attr
,
221 &dev_attr_als_en
.attr
,
223 &dev_attr_linear
.attr
,
228 static umode_t
lm3533_bl_attr_is_visible(struct kobject
*kobj
,
229 struct attribute
*attr
, int n
)
231 struct device
*dev
= kobj_to_dev(kobj
);
232 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
233 umode_t mode
= attr
->mode
;
235 if (attr
== &dev_attr_als_channel
.attr
||
236 attr
== &dev_attr_als_en
.attr
) {
237 if (!bl
->lm3533
->have_als
)
244 static struct attribute_group lm3533_bl_attribute_group
= {
245 .is_visible
= lm3533_bl_attr_is_visible
,
246 .attrs
= lm3533_bl_attributes
249 static int lm3533_bl_setup(struct lm3533_bl
*bl
,
250 struct lm3533_bl_platform_data
*pdata
)
254 ret
= lm3533_ctrlbank_set_max_current(&bl
->cb
, pdata
->max_current
);
258 return lm3533_ctrlbank_set_pwm(&bl
->cb
, pdata
->pwm
);
261 static int lm3533_bl_probe(struct platform_device
*pdev
)
263 struct lm3533
*lm3533
;
264 struct lm3533_bl_platform_data
*pdata
;
265 struct lm3533_bl
*bl
;
266 struct backlight_device
*bd
;
267 struct backlight_properties props
;
270 dev_dbg(&pdev
->dev
, "%s\n", __func__
);
272 lm3533
= dev_get_drvdata(pdev
->dev
.parent
);
276 pdata
= dev_get_platdata(&pdev
->dev
);
278 dev_err(&pdev
->dev
, "no platform data\n");
282 if (pdev
->id
< 0 || pdev
->id
>= LM3533_HVCTRLBANK_COUNT
) {
283 dev_err(&pdev
->dev
, "illegal backlight id %d\n", pdev
->id
);
287 bl
= devm_kzalloc(&pdev
->dev
, sizeof(*bl
), GFP_KERNEL
);
294 bl
->cb
.lm3533
= lm3533
;
295 bl
->cb
.id
= lm3533_bl_get_ctrlbank_id(bl
);
296 bl
->cb
.dev
= NULL
; /* until registered */
298 memset(&props
, 0, sizeof(props
));
299 props
.type
= BACKLIGHT_RAW
;
300 props
.max_brightness
= LM3533_BL_MAX_BRIGHTNESS
;
301 props
.brightness
= pdata
->default_brightness
;
302 bd
= devm_backlight_device_register(&pdev
->dev
, pdata
->name
,
303 pdev
->dev
.parent
, bl
, &lm3533_bl_ops
,
306 dev_err(&pdev
->dev
, "failed to register backlight device\n");
311 bl
->cb
.dev
= &bl
->bd
->dev
;
313 platform_set_drvdata(pdev
, bl
);
315 ret
= sysfs_create_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
317 dev_err(&pdev
->dev
, "failed to create sysfs attributes\n");
321 backlight_update_status(bd
);
323 ret
= lm3533_bl_setup(bl
, pdata
);
325 goto err_sysfs_remove
;
327 ret
= lm3533_ctrlbank_enable(&bl
->cb
);
329 goto err_sysfs_remove
;
334 sysfs_remove_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
339 static void lm3533_bl_remove(struct platform_device
*pdev
)
341 struct lm3533_bl
*bl
= platform_get_drvdata(pdev
);
342 struct backlight_device
*bd
= bl
->bd
;
344 dev_dbg(&bd
->dev
, "%s\n", __func__
);
346 bd
->props
.power
= BACKLIGHT_POWER_OFF
;
347 bd
->props
.brightness
= 0;
349 lm3533_ctrlbank_disable(&bl
->cb
);
350 sysfs_remove_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
353 #ifdef CONFIG_PM_SLEEP
354 static int lm3533_bl_suspend(struct device
*dev
)
356 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
358 dev_dbg(dev
, "%s\n", __func__
);
360 return lm3533_ctrlbank_disable(&bl
->cb
);
363 static int lm3533_bl_resume(struct device
*dev
)
365 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
367 dev_dbg(dev
, "%s\n", __func__
);
369 return lm3533_ctrlbank_enable(&bl
->cb
);
373 static SIMPLE_DEV_PM_OPS(lm3533_bl_pm_ops
, lm3533_bl_suspend
, lm3533_bl_resume
);
375 static void lm3533_bl_shutdown(struct platform_device
*pdev
)
377 struct lm3533_bl
*bl
= platform_get_drvdata(pdev
);
379 dev_dbg(&pdev
->dev
, "%s\n", __func__
);
381 lm3533_ctrlbank_disable(&bl
->cb
);
384 static struct platform_driver lm3533_bl_driver
= {
386 .name
= "lm3533-backlight",
387 .pm
= &lm3533_bl_pm_ops
,
389 .probe
= lm3533_bl_probe
,
390 .remove
= lm3533_bl_remove
,
391 .shutdown
= lm3533_bl_shutdown
,
393 module_platform_driver(lm3533_bl_driver
);
395 MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
396 MODULE_DESCRIPTION("LM3533 Backlight driver");
397 MODULE_LICENSE("GPL");
398 MODULE_ALIAS("platform:lm3533-backlight");