1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <linux/bitops.h>
5 #include <linux/kernel.h>
6 #include <linux/led-class-flash.h>
7 #include <linux/module.h>
8 #include <linux/mutex.h>
9 #include <linux/property.h>
10 #include <linux/regmap.h>
11 #include <media/v4l2-flash-led-class.h>
13 #define RT4505_REG_RESET 0x0
14 #define RT4505_REG_CONFIG 0x8
15 #define RT4505_REG_ILED 0x9
16 #define RT4505_REG_ENABLE 0xA
17 #define RT4505_REG_FLAGS 0xB
19 #define RT4505_RESET_MASK BIT(7)
20 #define RT4505_FLASHTO_MASK GENMASK(2, 0)
21 #define RT4505_ITORCH_MASK GENMASK(7, 5)
22 #define RT4505_ITORCH_SHIFT 5
23 #define RT4505_IFLASH_MASK GENMASK(4, 0)
24 #define RT4505_ENABLE_MASK GENMASK(5, 0)
25 #define RT4505_TORCH_SET (BIT(0) | BIT(4))
26 #define RT4505_FLASH_SET (BIT(0) | BIT(1) | BIT(2) | BIT(4))
27 #define RT4505_EXT_FLASH_SET (BIT(0) | BIT(1) | BIT(4) | BIT(5))
28 #define RT4505_FLASH_GET (BIT(0) | BIT(1) | BIT(4))
29 #define RT4505_OVP_MASK BIT(3)
30 #define RT4505_SHORT_MASK BIT(2)
31 #define RT4505_OTP_MASK BIT(1)
32 #define RT4505_TIMEOUT_MASK BIT(0)
34 #define RT4505_ITORCH_MINUA 46000
35 #define RT4505_ITORCH_MAXUA 375000
36 #define RT4505_ITORCH_STPUA 47000
37 #define RT4505_IFLASH_MINUA 93750
38 #define RT4505_IFLASH_MAXUA 1500000
39 #define RT4505_IFLASH_STPUA 93750
40 #define RT4505_FLASHTO_MINUS 100000
41 #define RT4505_FLASHTO_MAXUS 800000
42 #define RT4505_FLASHTO_STPUS 100000
46 struct regmap
*regmap
;
48 struct led_classdev_flash flash
;
49 struct v4l2_flash
*v4l2_flash
;
52 static int rt4505_torch_brightness_set(struct led_classdev
*lcdev
,
53 enum led_brightness level
)
55 struct rt4505_priv
*priv
=
56 container_of(lcdev
, struct rt4505_priv
, flash
.led_cdev
);
60 mutex_lock(&priv
->lock
);
62 if (level
!= LED_OFF
) {
63 ret
= regmap_update_bits(priv
->regmap
,
64 RT4505_REG_ILED
, RT4505_ITORCH_MASK
,
65 (level
- 1) << RT4505_ITORCH_SHIFT
);
69 val
= RT4505_TORCH_SET
;
72 ret
= regmap_update_bits(priv
->regmap
, RT4505_REG_ENABLE
,
73 RT4505_ENABLE_MASK
, val
);
76 mutex_unlock(&priv
->lock
);
80 static enum led_brightness
rt4505_torch_brightness_get(
81 struct led_classdev
*lcdev
)
83 struct rt4505_priv
*priv
=
84 container_of(lcdev
, struct rt4505_priv
, flash
.led_cdev
);
88 mutex_lock(&priv
->lock
);
90 ret
= regmap_read(priv
->regmap
, RT4505_REG_ENABLE
, &val
);
92 dev_err(lcdev
->dev
, "Failed to get LED enable\n");
97 if ((val
& RT4505_ENABLE_MASK
) != RT4505_TORCH_SET
) {
102 ret
= regmap_read(priv
->regmap
, RT4505_REG_ILED
, &val
);
104 dev_err(lcdev
->dev
, "Failed to get LED brightness\n");
109 ret
= ((val
& RT4505_ITORCH_MASK
) >> RT4505_ITORCH_SHIFT
) + 1;
112 mutex_unlock(&priv
->lock
);
116 static int rt4505_flash_brightness_set(struct led_classdev_flash
*fled_cdev
,
119 struct rt4505_priv
*priv
=
120 container_of(fled_cdev
, struct rt4505_priv
, flash
);
121 struct led_flash_setting
*s
= &fled_cdev
->brightness
;
122 u32 val
= (brightness
- s
->min
) / s
->step
;
125 mutex_lock(&priv
->lock
);
126 ret
= regmap_update_bits(priv
->regmap
, RT4505_REG_ILED
,
127 RT4505_IFLASH_MASK
, val
);
128 mutex_unlock(&priv
->lock
);
133 static int rt4505_flash_strobe_set(struct led_classdev_flash
*fled_cdev
,
136 struct rt4505_priv
*priv
=
137 container_of(fled_cdev
, struct rt4505_priv
, flash
);
138 u32 val
= state
? RT4505_FLASH_SET
: 0;
141 mutex_lock(&priv
->lock
);
142 ret
= regmap_update_bits(priv
->regmap
, RT4505_REG_ENABLE
,
143 RT4505_ENABLE_MASK
, val
);
144 mutex_unlock(&priv
->lock
);
149 static int rt4505_flash_strobe_get(struct led_classdev_flash
*fled_cdev
,
152 struct rt4505_priv
*priv
=
153 container_of(fled_cdev
, struct rt4505_priv
, flash
);
157 mutex_lock(&priv
->lock
);
159 ret
= regmap_read(priv
->regmap
, RT4505_REG_ENABLE
, &val
);
163 *state
= (val
& RT4505_FLASH_GET
) == RT4505_FLASH_GET
;
166 mutex_unlock(&priv
->lock
);
170 static int rt4505_flash_timeout_set(struct led_classdev_flash
*fled_cdev
,
173 struct rt4505_priv
*priv
=
174 container_of(fled_cdev
, struct rt4505_priv
, flash
);
175 struct led_flash_setting
*s
= &fled_cdev
->timeout
;
176 u32 val
= (timeout
- s
->min
) / s
->step
;
179 mutex_lock(&priv
->lock
);
180 ret
= regmap_update_bits(priv
->regmap
, RT4505_REG_CONFIG
,
181 RT4505_FLASHTO_MASK
, val
);
182 mutex_unlock(&priv
->lock
);
187 static int rt4505_fault_get(struct led_classdev_flash
*fled_cdev
, u32
*fault
)
189 struct rt4505_priv
*priv
=
190 container_of(fled_cdev
, struct rt4505_priv
, flash
);
191 u32 val
, led_faults
= 0;
194 ret
= regmap_read(priv
->regmap
, RT4505_REG_FLAGS
, &val
);
198 if (val
& RT4505_OVP_MASK
)
199 led_faults
|= LED_FAULT_OVER_VOLTAGE
;
201 if (val
& RT4505_SHORT_MASK
)
202 led_faults
|= LED_FAULT_SHORT_CIRCUIT
;
204 if (val
& RT4505_OTP_MASK
)
205 led_faults
|= LED_FAULT_OVER_TEMPERATURE
;
207 if (val
& RT4505_TIMEOUT_MASK
)
208 led_faults
|= LED_FAULT_TIMEOUT
;
214 static const struct led_flash_ops rt4505_flash_ops
= {
215 .flash_brightness_set
= rt4505_flash_brightness_set
,
216 .strobe_set
= rt4505_flash_strobe_set
,
217 .strobe_get
= rt4505_flash_strobe_get
,
218 .timeout_set
= rt4505_flash_timeout_set
,
219 .fault_get
= rt4505_fault_get
,
222 static bool rt4505_is_accessible_reg(struct device
*dev
, unsigned int reg
)
224 if (reg
== RT4505_REG_RESET
||
225 (reg
>= RT4505_REG_CONFIG
&& reg
<= RT4505_REG_FLAGS
))
230 static const struct regmap_config rt4505_regmap_config
= {
233 .max_register
= RT4505_REG_FLAGS
,
235 .readable_reg
= rt4505_is_accessible_reg
,
236 .writeable_reg
= rt4505_is_accessible_reg
,
239 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
240 static int rt4505_flash_external_strobe_set(struct v4l2_flash
*v4l2_flash
,
243 struct led_classdev_flash
*flash
= v4l2_flash
->fled_cdev
;
244 struct rt4505_priv
*priv
=
245 container_of(flash
, struct rt4505_priv
, flash
);
246 u32 val
= enable
? RT4505_EXT_FLASH_SET
: 0;
249 mutex_lock(&priv
->lock
);
250 ret
= regmap_update_bits(priv
->regmap
, RT4505_REG_ENABLE
,
251 RT4505_ENABLE_MASK
, val
);
252 mutex_unlock(&priv
->lock
);
257 static const struct v4l2_flash_ops v4l2_flash_ops
= {
258 .external_strobe_set
= rt4505_flash_external_strobe_set
,
261 static void rt4505_init_v4l2_config(struct rt4505_priv
*priv
,
262 struct v4l2_flash_config
*config
)
264 struct led_classdev_flash
*flash
= &priv
->flash
;
265 struct led_classdev
*lcdev
= &flash
->led_cdev
;
266 struct led_flash_setting
*s
;
268 strscpy(config
->dev_name
, lcdev
->dev
->kobj
.name
,
269 sizeof(config
->dev_name
));
271 s
= &config
->intensity
;
272 s
->min
= RT4505_ITORCH_MINUA
;
273 s
->step
= RT4505_ITORCH_STPUA
;
274 s
->max
= s
->val
= s
->min
+ (lcdev
->max_brightness
- 1) * s
->step
;
276 config
->flash_faults
= LED_FAULT_OVER_VOLTAGE
|
277 LED_FAULT_SHORT_CIRCUIT
|
278 LED_FAULT_LED_OVER_TEMPERATURE
|
280 config
->has_external_strobe
= 1;
283 static const struct v4l2_flash_ops v4l2_flash_ops
;
284 static void rt4505_init_v4l2_config(struct rt4505_priv
*priv
,
285 struct v4l2_flash_config
*config
)
290 static void rt4505_init_flash_properties(struct rt4505_priv
*priv
,
291 struct fwnode_handle
*child
)
293 struct led_classdev_flash
*flash
= &priv
->flash
;
294 struct led_classdev
*lcdev
= &flash
->led_cdev
;
295 struct led_flash_setting
*s
;
299 ret
= fwnode_property_read_u32(child
, "led-max-microamp", &val
);
301 dev_warn(priv
->dev
, "led-max-microamp DT property missing\n");
302 val
= RT4505_ITORCH_MINUA
;
304 val
= clamp_val(val
, RT4505_ITORCH_MINUA
, RT4505_ITORCH_MAXUA
);
306 lcdev
->max_brightness
=
307 (val
- RT4505_ITORCH_MINUA
) / RT4505_ITORCH_STPUA
+ 1;
308 lcdev
->brightness_set_blocking
= rt4505_torch_brightness_set
;
309 lcdev
->brightness_get
= rt4505_torch_brightness_get
;
310 lcdev
->flags
|= LED_DEV_CAP_FLASH
;
312 ret
= fwnode_property_read_u32(child
, "flash-max-microamp", &val
);
314 dev_warn(priv
->dev
, "flash-max-microamp DT property missing\n");
315 val
= RT4505_IFLASH_MINUA
;
317 val
= clamp_val(val
, RT4505_IFLASH_MINUA
, RT4505_IFLASH_MAXUA
);
319 s
= &flash
->brightness
;
320 s
->min
= RT4505_IFLASH_MINUA
;
321 s
->step
= RT4505_IFLASH_STPUA
;
322 s
->max
= s
->val
= val
;
324 ret
= fwnode_property_read_u32(child
, "flash-max-timeout-us", &val
);
327 "flash-max-timeout-us DT property missing\n");
328 val
= RT4505_FLASHTO_MINUS
;
330 val
= clamp_val(val
, RT4505_FLASHTO_MINUS
,
331 RT4505_FLASHTO_MAXUS
);
334 s
->min
= RT4505_FLASHTO_MINUS
;
335 s
->step
= RT4505_FLASHTO_STPUS
;
336 s
->max
= s
->val
= val
;
338 flash
->ops
= &rt4505_flash_ops
;
341 static int rt4505_probe(struct i2c_client
*client
)
343 struct rt4505_priv
*priv
;
344 struct fwnode_handle
*child
;
345 struct led_init_data init_data
= {};
346 struct v4l2_flash_config v4l2_config
= {};
349 priv
= devm_kzalloc(&client
->dev
, sizeof(*priv
), GFP_KERNEL
);
353 priv
->dev
= &client
->dev
;
354 mutex_init(&priv
->lock
);
356 priv
->regmap
= devm_regmap_init_i2c(client
, &rt4505_regmap_config
);
357 if (IS_ERR(priv
->regmap
)) {
358 dev_err(priv
->dev
, "Failed to allocate register map\n");
359 return PTR_ERR(priv
->regmap
);
362 ret
= regmap_write(priv
->regmap
, RT4505_REG_RESET
, RT4505_RESET_MASK
);
364 dev_err(priv
->dev
, "Failed to reset registers\n");
368 child
= fwnode_get_next_available_child_node(client
->dev
.fwnode
, NULL
);
370 dev_err(priv
->dev
, "Failed to get child node\n");
373 init_data
.fwnode
= child
;
375 rt4505_init_flash_properties(priv
, child
);
376 ret
= devm_led_classdev_flash_register_ext(priv
->dev
, &priv
->flash
,
379 dev_err(priv
->dev
, "Failed to register flash\n");
383 rt4505_init_v4l2_config(priv
, &v4l2_config
);
384 priv
->v4l2_flash
= v4l2_flash_init(priv
->dev
, init_data
.fwnode
,
385 &priv
->flash
, &v4l2_flash_ops
,
387 if (IS_ERR(priv
->v4l2_flash
)) {
388 dev_err(priv
->dev
, "Failed to register v4l2 flash\n");
389 return PTR_ERR(priv
->v4l2_flash
);
392 i2c_set_clientdata(client
, priv
);
396 static void rt4505_remove(struct i2c_client
*client
)
398 struct rt4505_priv
*priv
= i2c_get_clientdata(client
);
400 v4l2_flash_release(priv
->v4l2_flash
);
403 static void rt4505_shutdown(struct i2c_client
*client
)
405 struct rt4505_priv
*priv
= i2c_get_clientdata(client
);
407 /* Reset registers to make sure all off before shutdown */
408 regmap_write(priv
->regmap
, RT4505_REG_RESET
, RT4505_RESET_MASK
);
411 static const struct of_device_id __maybe_unused rt4505_leds_match
[] = {
412 { .compatible
= "richtek,rt4505", },
415 MODULE_DEVICE_TABLE(of
, rt4505_leds_match
);
417 static struct i2c_driver rt4505_driver
= {
420 .of_match_table
= of_match_ptr(rt4505_leds_match
),
422 .probe
= rt4505_probe
,
423 .remove
= rt4505_remove
,
424 .shutdown
= rt4505_shutdown
,
426 module_i2c_driver(rt4505_driver
);
428 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
429 MODULE_DESCRIPTION("Richtek RT4505 LED driver");
430 MODULE_LICENSE("GPL v2");