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
);
43 return lm3533_ctrlbank_set_brightness(&bl
->cb
, backlight_get_brightness(bd
));
46 static int lm3533_bl_get_brightness(struct backlight_device
*bd
)
48 struct lm3533_bl
*bl
= bl_get_data(bd
);
52 ret
= lm3533_ctrlbank_get_brightness(&bl
->cb
, &val
);
59 static const struct backlight_ops lm3533_bl_ops
= {
60 .get_brightness
= lm3533_bl_get_brightness
,
61 .update_status
= lm3533_bl_update_status
,
64 static ssize_t
show_id(struct device
*dev
,
65 struct device_attribute
*attr
, char *buf
)
67 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
69 return scnprintf(buf
, PAGE_SIZE
, "%d\n", bl
->id
);
72 static ssize_t
show_als_channel(struct device
*dev
,
73 struct device_attribute
*attr
, char *buf
)
75 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
76 unsigned channel
= lm3533_bl_get_ctrlbank_id(bl
);
78 return scnprintf(buf
, PAGE_SIZE
, "%u\n", channel
);
81 static ssize_t
show_als_en(struct device
*dev
,
82 struct device_attribute
*attr
, char *buf
)
84 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
85 int ctrlbank
= lm3533_bl_get_ctrlbank_id(bl
);
91 ret
= lm3533_read(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, &val
);
95 mask
= 1 << (2 * ctrlbank
);
98 return scnprintf(buf
, PAGE_SIZE
, "%d\n", enable
);
101 static ssize_t
store_als_en(struct device
*dev
,
102 struct device_attribute
*attr
,
103 const char *buf
, size_t len
)
105 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
106 int ctrlbank
= lm3533_bl_get_ctrlbank_id(bl
);
112 if (kstrtoint(buf
, 0, &enable
))
115 mask
= 1 << (2 * ctrlbank
);
122 ret
= lm3533_update(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, val
,
130 static ssize_t
show_linear(struct device
*dev
,
131 struct device_attribute
*attr
, char *buf
)
133 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
139 ret
= lm3533_read(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, &val
);
143 mask
= 1 << (2 * lm3533_bl_get_ctrlbank_id(bl
) + 1);
150 return scnprintf(buf
, PAGE_SIZE
, "%x\n", linear
);
153 static ssize_t
store_linear(struct device
*dev
,
154 struct device_attribute
*attr
,
155 const char *buf
, size_t len
)
157 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
158 unsigned long linear
;
163 if (kstrtoul(buf
, 0, &linear
))
166 mask
= 1 << (2 * lm3533_bl_get_ctrlbank_id(bl
) + 1);
173 ret
= lm3533_update(bl
->lm3533
, LM3533_REG_CTRLBANK_AB_BCONF
, val
,
181 static ssize_t
show_pwm(struct device
*dev
,
182 struct device_attribute
*attr
,
185 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
189 ret
= lm3533_ctrlbank_get_pwm(&bl
->cb
, &val
);
193 return scnprintf(buf
, PAGE_SIZE
, "%u\n", val
);
196 static ssize_t
store_pwm(struct device
*dev
,
197 struct device_attribute
*attr
,
198 const char *buf
, size_t len
)
200 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
204 if (kstrtou8(buf
, 0, &val
))
207 ret
= lm3533_ctrlbank_set_pwm(&bl
->cb
, val
);
214 static LM3533_ATTR_RO(als_channel
);
215 static LM3533_ATTR_RW(als_en
);
216 static LM3533_ATTR_RO(id
);
217 static LM3533_ATTR_RW(linear
);
218 static LM3533_ATTR_RW(pwm
);
220 static struct attribute
*lm3533_bl_attributes
[] = {
221 &dev_attr_als_channel
.attr
,
222 &dev_attr_als_en
.attr
,
224 &dev_attr_linear
.attr
,
229 static umode_t
lm3533_bl_attr_is_visible(struct kobject
*kobj
,
230 struct attribute
*attr
, int n
)
232 struct device
*dev
= kobj_to_dev(kobj
);
233 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
234 umode_t mode
= attr
->mode
;
236 if (attr
== &dev_attr_als_channel
.attr
||
237 attr
== &dev_attr_als_en
.attr
) {
238 if (!bl
->lm3533
->have_als
)
245 static struct attribute_group lm3533_bl_attribute_group
= {
246 .is_visible
= lm3533_bl_attr_is_visible
,
247 .attrs
= lm3533_bl_attributes
250 static int lm3533_bl_setup(struct lm3533_bl
*bl
,
251 struct lm3533_bl_platform_data
*pdata
)
255 ret
= lm3533_ctrlbank_set_max_current(&bl
->cb
, pdata
->max_current
);
259 return lm3533_ctrlbank_set_pwm(&bl
->cb
, pdata
->pwm
);
262 static int lm3533_bl_probe(struct platform_device
*pdev
)
264 struct lm3533
*lm3533
;
265 struct lm3533_bl_platform_data
*pdata
;
266 struct lm3533_bl
*bl
;
267 struct backlight_device
*bd
;
268 struct backlight_properties props
;
271 dev_dbg(&pdev
->dev
, "%s\n", __func__
);
273 lm3533
= dev_get_drvdata(pdev
->dev
.parent
);
277 pdata
= dev_get_platdata(&pdev
->dev
);
279 dev_err(&pdev
->dev
, "no platform data\n");
283 if (pdev
->id
< 0 || pdev
->id
>= LM3533_HVCTRLBANK_COUNT
) {
284 dev_err(&pdev
->dev
, "illegal backlight id %d\n", pdev
->id
);
288 bl
= devm_kzalloc(&pdev
->dev
, sizeof(*bl
), GFP_KERNEL
);
295 bl
->cb
.lm3533
= lm3533
;
296 bl
->cb
.id
= lm3533_bl_get_ctrlbank_id(bl
);
297 bl
->cb
.dev
= NULL
; /* until registered */
299 memset(&props
, 0, sizeof(props
));
300 props
.type
= BACKLIGHT_RAW
;
301 props
.max_brightness
= LM3533_BL_MAX_BRIGHTNESS
;
302 props
.brightness
= pdata
->default_brightness
;
303 bd
= devm_backlight_device_register(&pdev
->dev
, pdata
->name
,
304 pdev
->dev
.parent
, bl
, &lm3533_bl_ops
,
307 dev_err(&pdev
->dev
, "failed to register backlight device\n");
312 bl
->cb
.dev
= &bl
->bd
->dev
;
314 platform_set_drvdata(pdev
, bl
);
316 ret
= sysfs_create_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
318 dev_err(&pdev
->dev
, "failed to create sysfs attributes\n");
322 backlight_update_status(bd
);
324 ret
= lm3533_bl_setup(bl
, pdata
);
326 goto err_sysfs_remove
;
328 ret
= lm3533_ctrlbank_enable(&bl
->cb
);
330 goto err_sysfs_remove
;
335 sysfs_remove_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
340 static int lm3533_bl_remove(struct platform_device
*pdev
)
342 struct lm3533_bl
*bl
= platform_get_drvdata(pdev
);
343 struct backlight_device
*bd
= bl
->bd
;
345 dev_dbg(&bd
->dev
, "%s\n", __func__
);
347 bd
->props
.power
= FB_BLANK_POWERDOWN
;
348 bd
->props
.brightness
= 0;
350 lm3533_ctrlbank_disable(&bl
->cb
);
351 sysfs_remove_group(&bd
->dev
.kobj
, &lm3533_bl_attribute_group
);
356 #ifdef CONFIG_PM_SLEEP
357 static int lm3533_bl_suspend(struct device
*dev
)
359 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
361 dev_dbg(dev
, "%s\n", __func__
);
363 return lm3533_ctrlbank_disable(&bl
->cb
);
366 static int lm3533_bl_resume(struct device
*dev
)
368 struct lm3533_bl
*bl
= dev_get_drvdata(dev
);
370 dev_dbg(dev
, "%s\n", __func__
);
372 return lm3533_ctrlbank_enable(&bl
->cb
);
376 static SIMPLE_DEV_PM_OPS(lm3533_bl_pm_ops
, lm3533_bl_suspend
, lm3533_bl_resume
);
378 static void lm3533_bl_shutdown(struct platform_device
*pdev
)
380 struct lm3533_bl
*bl
= platform_get_drvdata(pdev
);
382 dev_dbg(&pdev
->dev
, "%s\n", __func__
);
384 lm3533_ctrlbank_disable(&bl
->cb
);
387 static struct platform_driver lm3533_bl_driver
= {
389 .name
= "lm3533-backlight",
390 .pm
= &lm3533_bl_pm_ops
,
392 .probe
= lm3533_bl_probe
,
393 .remove
= lm3533_bl_remove
,
394 .shutdown
= lm3533_bl_shutdown
,
396 module_platform_driver(lm3533_bl_driver
);
398 MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
399 MODULE_DESCRIPTION("LM3533 Backlight driver");
400 MODULE_LICENSE("GPL");
401 MODULE_ALIAS("platform:lm3533-backlight");