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>
15 #include <linux/slab.h>
17 #include <linux/mfd/lm3533.h>
20 #define LM3533_HVCTRLBANK_COUNT 2
21 #define LM3533_BL_MAX_BRIGHTNESS 255
23 #define LM3533_REG_CTRLBANK_AB_BCONF 0x1a
27 struct lm3533
*lm3533
;
28 struct lm3533_ctrlbank cb
;
29 struct backlight_device
*bd
;
34 static inline int lm3533_bl_get_ctrlbank_id(struct lm3533_bl
*bl
)
39 static int lm3533_bl_update_status(struct backlight_device
*bd
)
41 struct lm3533_bl
*bl
= bl_get_data(bd
);
42 int brightness
= bd
->props
.brightness
;
44 if (bd
->props
.power
!= FB_BLANK_UNBLANK
)
46 if (bd
->props
.fb_blank
!= FB_BLANK_UNBLANK
)
49 return lm3533_ctrlbank_set_brightness(&bl
->cb
, (u8
)brightness
);
52 static int lm3533_bl_get_brightness(struct backlight_device
*bd
)
54 struct lm3533_bl
*bl
= bl_get_data(bd
);
58 ret
= lm3533_ctrlbank_get_brightness(&bl
->cb
, &val
);
65 static const struct backlight_ops lm3533_bl_ops
= {
66 .get_brightness
= lm3533_bl_get_brightness
,
67 .update_status
= lm3533_bl_update_status
,
70 static ssize_t
show_id(struct device
*dev
,
71 struct device_attribute
*attr
, char *buf
)
73 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
75 return scnprintf(buf
, PAGE_SIZE
, "%d\n", bl
->id
);
78 static ssize_t
show_als_channel(struct device
*dev
,
79 struct device_attribute
*attr
, char *buf
)
81 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
82 unsigned channel
= lm3533_bl_get_ctrlbank_id(bl
);
84 return scnprintf(buf
, PAGE_SIZE
, "%u\n", channel
);
87 static ssize_t
show_als_en(struct device
*dev
,
88 struct device_attribute
*attr
, char *buf
)
90 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
91 int ctrlbank
= lm3533_bl_get_ctrlbank_id(bl
);
97 ret
= lm3533_read(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, &val
);
101 mask
= 1 << (2 * ctrlbank
);
104 return scnprintf(buf
, PAGE_SIZE
, "%d\n", enable
);
107 static ssize_t
store_als_en(struct device
*dev
,
108 struct device_attribute
*attr
,
109 const char *buf
, size_t len
)
111 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
112 int ctrlbank
= lm3533_bl_get_ctrlbank_id(bl
);
118 if (kstrtoint(buf
, 0, &enable
))
121 mask
= 1 << (2 * ctrlbank
);
128 ret
= lm3533_update(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, val
,
136 static ssize_t
show_linear(struct device
*dev
,
137 struct device_attribute
*attr
, char *buf
)
139 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
145 ret
= lm3533_read(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, &val
);
149 mask
= 1 << (2 * lm3533_bl_get_ctrlbank_id(bl
) + 1);
156 return scnprintf(buf
, PAGE_SIZE
, "%x\n", linear
);
159 static ssize_t
store_linear(struct device
*dev
,
160 struct device_attribute
*attr
,
161 const char *buf
, size_t len
)
163 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
164 unsigned long linear
;
169 if (kstrtoul(buf
, 0, &linear
))
172 mask
= 1 << (2 * lm3533_bl_get_ctrlbank_id(bl
) + 1);
179 ret
= lm3533_update(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, val
,
187 static ssize_t
show_pwm(struct device
*dev
,
188 struct device_attribute
*attr
,
191 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
195 ret
= lm3533_ctrlbank_get_pwm(&bl
->cb
, &val
);
199 return scnprintf(buf
, PAGE_SIZE
, "%u\n", val
);
202 static ssize_t
store_pwm(struct device
*dev
,
203 struct device_attribute
*attr
,
204 const char *buf
, size_t len
)
206 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
210 if (kstrtou8(buf
, 0, &val
))
213 ret
= lm3533_ctrlbank_set_pwm(&bl
->cb
, val
);
220 static LM3533_ATTR_RO(als_channel
);
221 static LM3533_ATTR_RW(als_en
);
222 static LM3533_ATTR_RO(id
);
223 static LM3533_ATTR_RW(linear
);
224 static LM3533_ATTR_RW(pwm
);
226 static struct attribute
*lm3533_bl_attributes
[] = {
227 &dev_attr_als_channel
.attr
,
228 &dev_attr_als_en
.attr
,
230 &dev_attr_linear
.attr
,
235 static umode_t
lm3533_bl_attr_is_visible(struct kobject
*kobj
,
236 struct attribute
*attr
, int n
)
238 struct device
*dev
= container_of(kobj
, struct device
, kobj
);
239 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
240 umode_t mode
= attr
->mode
;
242 if (attr
== &dev_attr_als_channel
.attr
||
243 attr
== &dev_attr_als_en
.attr
) {
244 if (!bl
->lm3533
->have_als
)
251 static struct attribute_group lm3533_bl_attribute_group
= {
252 .is_visible
= lm3533_bl_attr_is_visible
,
253 .attrs
= lm3533_bl_attributes
256 static int lm3533_bl_setup(struct lm3533_bl
*bl
,
257 struct lm3533_bl_platform_data
*pdata
)
261 ret
= lm3533_ctrlbank_set_max_current(&bl
->cb
, pdata
->max_current
);
265 return lm3533_ctrlbank_set_pwm(&bl
->cb
, pdata
->pwm
);
268 static int lm3533_bl_probe(struct platform_device
*pdev
)
270 struct lm3533
*lm3533
;
271 struct lm3533_bl_platform_data
*pdata
;
272 struct lm3533_bl
*bl
;
273 struct backlight_device
*bd
;
274 struct backlight_properties props
;
277 dev_dbg(&pdev
->dev
, "%s\n", __func__
);
279 lm3533
= dev_get_drvdata(pdev
->dev
.parent
);
283 pdata
= dev_get_platdata(&pdev
->dev
);
285 dev_err(&pdev
->dev
, "no platform data\n");
289 if (pdev
->id
< 0 || pdev
->id
>= LM3533_HVCTRLBANK_COUNT
) {
290 dev_err(&pdev
->dev
, "illegal backlight id %d\n", pdev
->id
);
294 bl
= devm_kzalloc(&pdev
->dev
, sizeof(*bl
), GFP_KERNEL
);
301 bl
->cb
.lm3533
= lm3533
;
302 bl
->cb
.id
= lm3533_bl_get_ctrlbank_id(bl
);
303 bl
->cb
.dev
= NULL
; /* until registered */
305 memset(&props
, 0, sizeof(props
));
306 props
.type
= BACKLIGHT_RAW
;
307 props
.max_brightness
= LM3533_BL_MAX_BRIGHTNESS
;
308 props
.brightness
= pdata
->default_brightness
;
309 bd
= devm_backlight_device_register(&pdev
->dev
, pdata
->name
,
310 pdev
->dev
.parent
, bl
, &lm3533_bl_ops
,
313 dev_err(&pdev
->dev
, "failed to register backlight device\n");
318 bl
->cb
.dev
= &bl
->bd
->dev
;
320 platform_set_drvdata(pdev
, bl
);
322 ret
= sysfs_create_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
324 dev_err(&pdev
->dev
, "failed to create sysfs attributes\n");
328 backlight_update_status(bd
);
330 ret
= lm3533_bl_setup(bl
, pdata
);
332 goto err_sysfs_remove
;
334 ret
= lm3533_ctrlbank_enable(&bl
->cb
);
336 goto err_sysfs_remove
;
341 sysfs_remove_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
346 static int lm3533_bl_remove(struct platform_device
*pdev
)
348 struct lm3533_bl
*bl
= platform_get_drvdata(pdev
);
349 struct backlight_device
*bd
= bl
->bd
;
351 dev_dbg(&bd
->dev
, "%s\n", __func__
);
353 bd
->props
.power
= FB_BLANK_POWERDOWN
;
354 bd
->props
.brightness
= 0;
356 lm3533_ctrlbank_disable(&bl
->cb
);
357 sysfs_remove_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
362 #ifdef CONFIG_PM_SLEEP
363 static int lm3533_bl_suspend(struct device
*dev
)
365 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
367 dev_dbg(dev
, "%s\n", __func__
);
369 return lm3533_ctrlbank_disable(&bl
->cb
);
372 static int lm3533_bl_resume(struct device
*dev
)
374 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
376 dev_dbg(dev
, "%s\n", __func__
);
378 return lm3533_ctrlbank_enable(&bl
->cb
);
382 static SIMPLE_DEV_PM_OPS(lm3533_bl_pm_ops
, lm3533_bl_suspend
, lm3533_bl_resume
);
384 static void lm3533_bl_shutdown(struct platform_device
*pdev
)
386 struct lm3533_bl
*bl
= platform_get_drvdata(pdev
);
388 dev_dbg(&pdev
->dev
, "%s\n", __func__
);
390 lm3533_ctrlbank_disable(&bl
->cb
);
393 static struct platform_driver lm3533_bl_driver
= {
395 .name
= "lm3533-backlight",
396 .pm
= &lm3533_bl_pm_ops
,
398 .probe
= lm3533_bl_probe
,
399 .remove
= lm3533_bl_remove
,
400 .shutdown
= lm3533_bl_shutdown
,
402 module_platform_driver(lm3533_bl_driver
);
404 MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
405 MODULE_DESCRIPTION("LM3533 Backlight driver");
406 MODULE_LICENSE("GPL");
407 MODULE_ALIAS("platform:lm3533-backlight");