GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / leds / flash / leds-rt4505.c
1 // SPDX-License-Identifier: GPL-2.0-only
2
3 #include <linux/bitops.h>
4 #include <linux/i2c.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>
12
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
18
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)
33
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
43
44 struct rt4505_priv {
45         struct device *dev;
46         struct regmap *regmap;
47         struct mutex lock;
48         struct led_classdev_flash flash;
49         struct v4l2_flash *v4l2_flash;
50 };
51
52 static int rt4505_torch_brightness_set(struct led_classdev *lcdev,
53                                        enum led_brightness level)
54 {
55         struct rt4505_priv *priv =
56                 container_of(lcdev, struct rt4505_priv, flash.led_cdev);
57         u32 val = 0;
58         int ret;
59
60         mutex_lock(&priv->lock);
61
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);
66                 if (ret)
67                         goto unlock;
68
69                 val = RT4505_TORCH_SET;
70         }
71
72         ret = regmap_update_bits(priv->regmap, RT4505_REG_ENABLE,
73                                  RT4505_ENABLE_MASK, val);
74
75 unlock:
76         mutex_unlock(&priv->lock);
77         return ret;
78 }
79
80 static enum led_brightness rt4505_torch_brightness_get(
81                                                 struct led_classdev *lcdev)
82 {
83         struct rt4505_priv *priv =
84                 container_of(lcdev, struct rt4505_priv, flash.led_cdev);
85         u32 val;
86         int ret;
87
88         mutex_lock(&priv->lock);
89
90         ret = regmap_read(priv->regmap, RT4505_REG_ENABLE, &val);
91         if (ret) {
92                 dev_err(lcdev->dev, "Failed to get LED enable\n");
93                 ret = LED_OFF;
94                 goto unlock;
95         }
96
97         if ((val & RT4505_ENABLE_MASK) != RT4505_TORCH_SET) {
98                 ret = LED_OFF;
99                 goto unlock;
100         }
101
102         ret = regmap_read(priv->regmap, RT4505_REG_ILED, &val);
103         if (ret) {
104                 dev_err(lcdev->dev, "Failed to get LED brightness\n");
105                 ret = LED_OFF;
106                 goto unlock;
107         }
108
109         ret = ((val & RT4505_ITORCH_MASK) >> RT4505_ITORCH_SHIFT) + 1;
110
111 unlock:
112         mutex_unlock(&priv->lock);
113         return ret;
114 }
115
116 static int rt4505_flash_brightness_set(struct led_classdev_flash *fled_cdev,
117                                        u32 brightness)
118 {
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;
123         int ret;
124
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);
129
130         return ret;
131 }
132
133 static int rt4505_flash_strobe_set(struct led_classdev_flash *fled_cdev,
134                                    bool state)
135 {
136         struct rt4505_priv *priv =
137                 container_of(fled_cdev, struct rt4505_priv, flash);
138         u32 val = state ? RT4505_FLASH_SET : 0;
139         int ret;
140
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);
145
146         return ret;
147 }
148
149 static int rt4505_flash_strobe_get(struct led_classdev_flash *fled_cdev,
150                                    bool *state)
151 {
152         struct rt4505_priv *priv =
153                 container_of(fled_cdev, struct rt4505_priv, flash);
154         u32 val;
155         int ret;
156
157         mutex_lock(&priv->lock);
158
159         ret = regmap_read(priv->regmap, RT4505_REG_ENABLE, &val);
160         if (ret)
161                 goto unlock;
162
163         *state = (val & RT4505_FLASH_GET) == RT4505_FLASH_GET;
164
165 unlock:
166         mutex_unlock(&priv->lock);
167         return ret;
168 }
169
170 static int rt4505_flash_timeout_set(struct led_classdev_flash *fled_cdev,
171                                     u32 timeout)
172 {
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;
177         int ret;
178
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);
183
184         return ret;
185 }
186
187 static int rt4505_fault_get(struct led_classdev_flash *fled_cdev, u32 *fault)
188 {
189         struct rt4505_priv *priv =
190                 container_of(fled_cdev, struct rt4505_priv, flash);
191         u32 val, led_faults = 0;
192         int ret;
193
194         ret = regmap_read(priv->regmap, RT4505_REG_FLAGS, &val);
195         if (ret)
196                 return ret;
197
198         if (val & RT4505_OVP_MASK)
199                 led_faults |= LED_FAULT_OVER_VOLTAGE;
200
201         if (val & RT4505_SHORT_MASK)
202                 led_faults |= LED_FAULT_SHORT_CIRCUIT;
203
204         if (val & RT4505_OTP_MASK)
205                 led_faults |= LED_FAULT_OVER_TEMPERATURE;
206
207         if (val & RT4505_TIMEOUT_MASK)
208                 led_faults |= LED_FAULT_TIMEOUT;
209
210         *fault = led_faults;
211         return 0;
212 }
213
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,
220 };
221
222 static bool rt4505_is_accessible_reg(struct device *dev, unsigned int reg)
223 {
224         if (reg == RT4505_REG_RESET ||
225                 (reg >= RT4505_REG_CONFIG && reg <= RT4505_REG_FLAGS))
226                 return true;
227         return false;
228 }
229
230 static const struct regmap_config rt4505_regmap_config = {
231         .reg_bits = 8,
232         .val_bits = 8,
233         .max_register = RT4505_REG_FLAGS,
234
235         .readable_reg = rt4505_is_accessible_reg,
236         .writeable_reg = rt4505_is_accessible_reg,
237 };
238
239 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
240 static int rt4505_flash_external_strobe_set(struct v4l2_flash *v4l2_flash,
241                                             bool enable)
242 {
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;
247         int ret;
248
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);
253
254         return ret;
255 }
256
257 static const struct v4l2_flash_ops v4l2_flash_ops = {
258         .external_strobe_set = rt4505_flash_external_strobe_set,
259 };
260
261 static void rt4505_init_v4l2_config(struct rt4505_priv *priv,
262                                     struct v4l2_flash_config *config)
263 {
264         struct led_classdev_flash *flash = &priv->flash;
265         struct led_classdev *lcdev = &flash->led_cdev;
266         struct led_flash_setting *s;
267
268         strscpy(config->dev_name, lcdev->dev->kobj.name,
269                 sizeof(config->dev_name));
270
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;
275
276         config->flash_faults = LED_FAULT_OVER_VOLTAGE |
277                                LED_FAULT_SHORT_CIRCUIT |
278                                LED_FAULT_LED_OVER_TEMPERATURE |
279                                LED_FAULT_TIMEOUT;
280         config->has_external_strobe = 1;
281 }
282 #else
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)
286 {
287 }
288 #endif
289
290 static void rt4505_init_flash_properties(struct rt4505_priv *priv,
291                                          struct fwnode_handle *child)
292 {
293         struct led_classdev_flash *flash = &priv->flash;
294         struct led_classdev *lcdev = &flash->led_cdev;
295         struct led_flash_setting *s;
296         u32 val;
297         int ret;
298
299         ret = fwnode_property_read_u32(child, "led-max-microamp", &val);
300         if (ret) {
301                 dev_warn(priv->dev, "led-max-microamp DT property missing\n");
302                 val = RT4505_ITORCH_MINUA;
303         } else
304                 val = clamp_val(val, RT4505_ITORCH_MINUA, RT4505_ITORCH_MAXUA);
305
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;
311
312         ret = fwnode_property_read_u32(child, "flash-max-microamp", &val);
313         if (ret) {
314                 dev_warn(priv->dev, "flash-max-microamp DT property missing\n");
315                 val = RT4505_IFLASH_MINUA;
316         } else
317                 val = clamp_val(val, RT4505_IFLASH_MINUA, RT4505_IFLASH_MAXUA);
318
319         s = &flash->brightness;
320         s->min = RT4505_IFLASH_MINUA;
321         s->step = RT4505_IFLASH_STPUA;
322         s->max = s->val = val;
323
324         ret = fwnode_property_read_u32(child, "flash-max-timeout-us", &val);
325         if (ret) {
326                 dev_warn(priv->dev,
327                          "flash-max-timeout-us DT property missing\n");
328                 val = RT4505_FLASHTO_MINUS;
329         } else
330                 val = clamp_val(val, RT4505_FLASHTO_MINUS,
331                                 RT4505_FLASHTO_MAXUS);
332
333         s = &flash->timeout;
334         s->min = RT4505_FLASHTO_MINUS;
335         s->step = RT4505_FLASHTO_STPUS;
336         s->max = s->val = val;
337
338         flash->ops = &rt4505_flash_ops;
339 }
340
341 static int rt4505_probe(struct i2c_client *client)
342 {
343         struct rt4505_priv *priv;
344         struct fwnode_handle *child;
345         struct led_init_data init_data = {};
346         struct v4l2_flash_config v4l2_config = {};
347         int ret;
348
349         priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
350         if (!priv)
351                 return -ENOMEM;
352
353         priv->dev = &client->dev;
354         mutex_init(&priv->lock);
355
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);
360         }
361
362         ret = regmap_write(priv->regmap, RT4505_REG_RESET, RT4505_RESET_MASK);
363         if (ret) {
364                 dev_err(priv->dev, "Failed to reset registers\n");
365                 return ret;
366         }
367
368         child = fwnode_get_next_available_child_node(client->dev.fwnode, NULL);
369         if (!child) {
370                 dev_err(priv->dev, "Failed to get child node\n");
371                 return -EINVAL;
372         }
373         init_data.fwnode = child;
374
375         rt4505_init_flash_properties(priv, child);
376         ret = devm_led_classdev_flash_register_ext(priv->dev, &priv->flash,
377                                                    &init_data);
378         if (ret) {
379                 dev_err(priv->dev, "Failed to register flash\n");
380                 return ret;
381         }
382
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,
386                                            &v4l2_config);
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);
390         }
391
392         i2c_set_clientdata(client, priv);
393         return 0;
394 }
395
396 static int rt4505_remove(struct i2c_client *client)
397 {
398         struct rt4505_priv *priv = i2c_get_clientdata(client);
399
400         v4l2_flash_release(priv->v4l2_flash);
401         return 0;
402 }
403
404 static void rt4505_shutdown(struct i2c_client *client)
405 {
406         struct rt4505_priv *priv = i2c_get_clientdata(client);
407
408         /* Reset registers to make sure all off before shutdown */
409         regmap_write(priv->regmap, RT4505_REG_RESET, RT4505_RESET_MASK);
410 }
411
412 static const struct of_device_id __maybe_unused rt4505_leds_match[] = {
413         { .compatible = "richtek,rt4505", },
414         {}
415 };
416 MODULE_DEVICE_TABLE(of, rt4505_leds_match);
417
418 static struct i2c_driver rt4505_driver = {
419         .driver = {
420                 .name = "rt4505",
421                 .of_match_table = of_match_ptr(rt4505_leds_match),
422         },
423         .probe_new = rt4505_probe,
424         .remove = rt4505_remove,
425         .shutdown = rt4505_shutdown,
426 };
427 module_i2c_driver(rt4505_driver);
428
429 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
430 MODULE_LICENSE("GPL v2");