Skip to content

Commit 70c5702

Browse files
committed
video: backlight: Add support for Richtek RT8555 Backlight
The Richtek RT8555 is a 6 channel LED driver that supports up to 35mA/LED. This is a backlight driver that drives ILED1. Signed-off-by: Michael Abood <[email protected]>
1 parent edd4ec0 commit 70c5702

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

Diff for: drivers/video/backlight/Kconfig

+9
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,15 @@ config BACKLIGHT_RT4831
297297
It's commonly used to drive the display WLED. There're four channels
298298
inisde, and each channel can provide up to 30mA current.
299299

300+
config BACKLIGHT_RT8555
301+
tristate "Richtek RT8555 Backlight Driver"
302+
depends on I2C
303+
select REGMAP_I2C
304+
help
305+
This enables support for Richtek RT8555 Backlight driver.
306+
It's commonly used to drive the display WLED. There are six channels
307+
inisde, and each channel can provide up to 35mA current.
308+
300309
config BACKLIGHT_SAHARA
301310
tristate "Tabletkiosk Sahara Touch-iT Backlight Driver"
302311
depends on X86

Diff for: drivers/video/backlight/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
5050
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
5151
obj-$(CONFIG_BACKLIGHT_QCOM_WLED) += qcom-wled.o
5252
obj-$(CONFIG_BACKLIGHT_RT4831) += rt4831-backlight.o
53+
obj-$(CONFIG_BACKLIGHT_RT8555) += rt8555-backlight.o
5354
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
5455
obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o
5556
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o

Diff for: drivers/video/backlight/rt8555-backlight.c

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
#include <dt-bindings/leds/rt4831-backlight.h>
4+
#include <linux/backlight.h>
5+
#include <linux/bitops.h>
6+
#include <linux/kernel.h>
7+
#include <linux/module.h>
8+
#include <linux/gpio/consumer.h>
9+
#include <linux/platform_device.h>
10+
#include <linux/property.h>
11+
#include <linux/regmap.h>
12+
13+
#define RT8555_MAX_BRIGHTNESS 1023
14+
15+
#define RT8555_REG_CFG1 0x01
16+
#define RT8555_REG_ILED1_LSB 0x04
17+
#define RT8555_REG_ILED1_MSB 0x05
18+
19+
#define RT8555_EN10BIT_MASK BIT(7)
20+
#define RT8555_LSB_MASK GENMASK(7, 0)
21+
22+
struct rt8555_priv {
23+
struct device *dev;
24+
struct regmap *regmap;
25+
struct backlight_device *bl;
26+
struct gpio_desc *enable;
27+
};
28+
29+
static int rt8555_bl_update_status(struct backlight_device *bl_dev)
30+
{
31+
struct rt8555_priv *priv = bl_get_data(bl_dev);
32+
unsigned int brightness = min(backlight_get_brightness(bl_dev),
33+
priv->bl->props.max_brightness);
34+
int ret;
35+
36+
/* Enable the IC before setting the brightness */
37+
if (brightness)
38+
if (!IS_ERR_OR_NULL(priv->enable))
39+
gpiod_set_value(priv->enable, 1);
40+
41+
42+
ret = regmap_write(priv->regmap, RT8555_REG_ILED1_LSB, (brightness & RT8555_LSB_MASK));
43+
if (ret)
44+
return ret;
45+
46+
ret = regmap_write(priv->regmap, RT8555_REG_ILED1_MSB, (brightness >> 8));
47+
if (ret)
48+
return ret;
49+
50+
/* Disable the IC after setting it to 0 */
51+
if (brightness == 0)
52+
if (!IS_ERR_OR_NULL(priv->enable))
53+
gpiod_set_value(priv->enable, 0);
54+
55+
return 0;
56+
}
57+
58+
static int rt8555_bl_get_brightness(struct backlight_device *bl_dev)
59+
{
60+
struct rt8555_priv *priv = bl_get_data(bl_dev);
61+
int ret, msb, lsb;
62+
63+
/* If the RT8555 is disabled, there's no reason to turn it on just to read
64+
* it back
65+
*/
66+
if (!IS_ERR_OR_NULL(priv->enable))
67+
if (gpiod_get_value(priv->enable) == 0)
68+
return 0;
69+
70+
ret = regmap_read(priv->regmap, RT8555_REG_ILED1_MSB, &msb);
71+
if (ret)
72+
return ret;
73+
74+
ret = regmap_read(priv->regmap, RT8555_REG_ILED1_LSB, &lsb);
75+
if (ret)
76+
return ret;
77+
78+
ret = (lsb >> 8) & msb;
79+
return ret;
80+
}
81+
82+
static const struct backlight_ops rt8555_bl_ops = {
83+
.options = BL_CORE_SUSPENDRESUME,
84+
.update_status = rt8555_bl_update_status,
85+
.get_brightness = rt8555_bl_get_brightness,
86+
};
87+
88+
static const struct regmap_config rt8555_regmap_config = {
89+
.reg_bits = 8,
90+
.val_bits = 8,
91+
};
92+
93+
static int rt8555_bl_probe(struct i2c_client *client)
94+
{
95+
struct rt8555_priv *priv;
96+
struct backlight_properties bl_props = { .type = BACKLIGHT_RAW,
97+
.scale = BACKLIGHT_SCALE_LINEAR };
98+
int ret;
99+
u32 brightness;
100+
101+
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
102+
if (!priv)
103+
return -ENOMEM;
104+
105+
priv->dev = &client->dev;
106+
107+
priv->enable = devm_gpiod_get_optional(&client->dev, NULL, GPIOD_OUT_HIGH);
108+
if (!IS_ERR_OR_NULL(priv->enable))
109+
gpiod_set_value(priv->enable, 1);
110+
111+
priv->regmap = devm_regmap_init_i2c(client, &rt8555_regmap_config);
112+
if (!priv->regmap) {
113+
dev_err(&client->dev, "Failed to init regmap\n");
114+
return -ENODEV;
115+
}
116+
117+
ret = device_property_read_u32(&client->dev, "max-brightness", &brightness);
118+
if (ret)
119+
brightness = RT8555_MAX_BRIGHTNESS;
120+
121+
bl_props.max_brightness = min_t(u32, brightness, RT8555_MAX_BRIGHTNESS);
122+
123+
ret = device_property_read_u32(&client->dev, "default-brightness", &brightness);
124+
if (ret)
125+
brightness = bl_props.max_brightness;
126+
127+
bl_props.brightness = min_t(u32, brightness, bl_props.max_brightness);
128+
129+
priv->bl = devm_backlight_device_register(&client->dev, client->name, &client->dev, priv,
130+
&rt8555_bl_ops, &bl_props);
131+
if (IS_ERR(priv->bl)) {
132+
dev_err(&client->dev, "Failed to register backlight\n");
133+
return PTR_ERR(priv->bl);
134+
}
135+
136+
/* Set 10 bit mode */
137+
ret = regmap_update_bits(priv->regmap, RT8555_REG_CFG1, RT8555_EN10BIT_MASK, BIT(7));
138+
if (ret)
139+
return ret;
140+
141+
backlight_update_status(priv->bl);
142+
i2c_set_clientdata(client, priv);
143+
144+
return 0;
145+
}
146+
147+
static void rt8555_bl_remove(struct i2c_client *client)
148+
{
149+
struct rt8555_priv *priv = i2c_get_clientdata(client);
150+
struct backlight_device *bl_dev = priv->bl;
151+
152+
bl_dev->props.brightness = 0;
153+
backlight_update_status(priv->bl);
154+
155+
if (!IS_ERR_OR_NULL(priv->enable))
156+
gpiod_set_value(priv->enable, 0);
157+
}
158+
159+
static const struct of_device_id __maybe_unused rt8555_bl_of_match[] = {
160+
{ .compatible = "richtek,rt8555-backlight", },
161+
{}
162+
};
163+
MODULE_DEVICE_TABLE(of, rt8555_bl_of_match);
164+
165+
static struct i2c_driver rt8555_bl_driver = {
166+
.driver = {
167+
.name = "rt8555-backlight",
168+
.of_match_table = rt8555_bl_of_match
169+
},
170+
.probe_new = rt8555_bl_probe,
171+
.shutdown = rt8555_bl_remove
172+
};
173+
module_i2c_driver(rt8555_bl_driver);
174+
MODULE_AUTHOR("Michael Abood <[email protected]>");
175+
MODULE_LICENSE("GPL v2");

0 commit comments

Comments
 (0)