Merge tag 'i3c/for-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux
[linux-2.6-microblaze.git] / drivers / media / v4l2-core / v4l2-flash-led-class.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * V4L2 flash LED sub-device registration helpers.
4  *
5  *      Copyright (C) 2015 Samsung Electronics Co., Ltd
6  *      Author: Jacek Anaszewski <j.anaszewski@samsung.com>
7  */
8
9 #include <linux/led-class-flash.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
12 #include <linux/property.h>
13 #include <linux/slab.h>
14 #include <linux/types.h>
15 #include <media/v4l2-flash-led-class.h>
16
17 #define has_flash_op(v4l2_flash, op)                            \
18         (v4l2_flash && v4l2_flash->ops && v4l2_flash->ops->op)
19
20 #define call_flash_op(v4l2_flash, op, arg)                      \
21                 (has_flash_op(v4l2_flash, op) ?                 \
22                         v4l2_flash->ops->op(v4l2_flash, arg) :  \
23                         -EINVAL)
24
25 enum ctrl_init_data_id {
26         LED_MODE,
27         TORCH_INTENSITY,
28         FLASH_INTENSITY,
29         INDICATOR_INTENSITY,
30         FLASH_TIMEOUT,
31         STROBE_SOURCE,
32         /*
33          * Only above values are applicable to
34          * the 'ctrls' array in the struct v4l2_flash.
35          */
36         FLASH_STROBE,
37         STROBE_STOP,
38         STROBE_STATUS,
39         FLASH_FAULT,
40         NUM_FLASH_CTRLS,
41 };
42
43 static enum led_brightness __intensity_to_led_brightness(
44                                         struct v4l2_ctrl *ctrl, s32 intensity)
45 {
46         intensity -= ctrl->minimum;
47         intensity /= (u32) ctrl->step;
48
49         /*
50          * Indicator LEDs, unlike torch LEDs, are turned on/off basing on
51          * the state of V4L2_CID_FLASH_INDICATOR_INTENSITY control only.
52          * Therefore it must be possible to set it to 0 level which in
53          * the LED subsystem reflects LED_OFF state.
54          */
55         if (ctrl->minimum)
56                 ++intensity;
57
58         return intensity;
59 }
60
61 static s32 __led_brightness_to_intensity(struct v4l2_ctrl *ctrl,
62                                          enum led_brightness brightness)
63 {
64         /*
65          * Indicator LEDs, unlike torch LEDs, are turned on/off basing on
66          * the state of V4L2_CID_FLASH_INDICATOR_INTENSITY control only.
67          * Do not decrement brightness read from the LED subsystem for
68          * indicator LED as it may equal 0. For torch LEDs this function
69          * is called only when V4L2_FLASH_LED_MODE_TORCH is set and the
70          * brightness read is guaranteed to be greater than 0. In the mode
71          * V4L2_FLASH_LED_MODE_NONE the cached torch intensity value is used.
72          */
73         if (ctrl->id != V4L2_CID_FLASH_INDICATOR_INTENSITY)
74                 --brightness;
75
76         return (brightness * ctrl->step) + ctrl->minimum;
77 }
78
79 static int v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
80                                          struct v4l2_ctrl *ctrl)
81 {
82         struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
83         struct led_classdev *led_cdev;
84         enum led_brightness brightness;
85
86         if (has_flash_op(v4l2_flash, intensity_to_led_brightness))
87                 brightness = call_flash_op(v4l2_flash,
88                                         intensity_to_led_brightness,
89                                         ctrl->val);
90         else
91                 brightness = __intensity_to_led_brightness(ctrl, ctrl->val);
92         /*
93          * In case a LED Flash class driver provides ops for custom
94          * brightness <-> intensity conversion, it also must have defined
95          * related v4l2 control step == 1. In such a case a backward conversion
96          * from led brightness to v4l2 intensity is required to find out the
97          * aligned intensity value.
98          */
99         if (has_flash_op(v4l2_flash, led_brightness_to_intensity))
100                 ctrl->val = call_flash_op(v4l2_flash,
101                                         led_brightness_to_intensity,
102                                         brightness);
103
104         if (ctrl == ctrls[TORCH_INTENSITY]) {
105                 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
106                         return 0;
107
108                 if (WARN_ON_ONCE(!v4l2_flash->fled_cdev))
109                         return -EINVAL;
110
111                 led_cdev = &v4l2_flash->fled_cdev->led_cdev;
112         } else {
113                 if (WARN_ON_ONCE(!v4l2_flash->iled_cdev))
114                         return -EINVAL;
115
116                 led_cdev = v4l2_flash->iled_cdev;
117         }
118
119         return led_set_brightness_sync(led_cdev, brightness);
120 }
121
122 static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
123                                         struct v4l2_ctrl *ctrl)
124 {
125         struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
126         struct led_classdev *led_cdev;
127         int ret;
128
129         if (ctrl == ctrls[TORCH_INTENSITY]) {
130                 /*
131                  * Update torch brightness only if in TORCH_MODE. In other modes
132                  * torch led is turned off, which would spuriously inform the
133                  * user space that V4L2_CID_FLASH_TORCH_INTENSITY control value
134                  * has changed to 0.
135                  */
136                 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
137                         return 0;
138
139                 if (WARN_ON_ONCE(!v4l2_flash->fled_cdev))
140                         return -EINVAL;
141
142                 led_cdev = &v4l2_flash->fled_cdev->led_cdev;
143         } else {
144                 if (WARN_ON_ONCE(!v4l2_flash->iled_cdev))
145                         return -EINVAL;
146
147                 led_cdev = v4l2_flash->iled_cdev;
148         }
149
150         ret = led_update_brightness(led_cdev);
151         if (ret < 0)
152                 return ret;
153
154         if (has_flash_op(v4l2_flash, led_brightness_to_intensity))
155                 ctrl->val = call_flash_op(v4l2_flash,
156                                                 led_brightness_to_intensity,
157                                                 led_cdev->brightness);
158         else
159                 ctrl->val = __led_brightness_to_intensity(ctrl,
160                                                 led_cdev->brightness);
161
162         return 0;
163 }
164
165 static int v4l2_flash_g_volatile_ctrl(struct v4l2_ctrl *c)
166 {
167         struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
168         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
169         bool is_strobing;
170         int ret;
171
172         switch (c->id) {
173         case V4L2_CID_FLASH_TORCH_INTENSITY:
174         case V4L2_CID_FLASH_INDICATOR_INTENSITY:
175                 return v4l2_flash_update_led_brightness(v4l2_flash, c);
176         }
177
178         if (!fled_cdev)
179                 return -EINVAL;
180
181         switch (c->id) {
182         case V4L2_CID_FLASH_INTENSITY:
183                 ret = led_update_flash_brightness(fled_cdev);
184                 if (ret < 0)
185                         return ret;
186                 /*
187                  * No conversion is needed as LED Flash class also uses
188                  * microamperes for flash intensity units.
189                  */
190                 c->val = fled_cdev->brightness.val;
191                 return 0;
192         case V4L2_CID_FLASH_STROBE_STATUS:
193                 ret = led_get_flash_strobe(fled_cdev, &is_strobing);
194                 if (ret < 0)
195                         return ret;
196                 c->val = is_strobing;
197                 return 0;
198         case V4L2_CID_FLASH_FAULT:
199                 /* LED faults map directly to V4L2 flash faults */
200                 return led_get_flash_fault(fled_cdev, &c->val);
201         default:
202                 return -EINVAL;
203         }
204 }
205
206 static bool __software_strobe_mode_inactive(struct v4l2_ctrl **ctrls)
207 {
208         return ((ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_FLASH) ||
209                 (ctrls[STROBE_SOURCE] && (ctrls[STROBE_SOURCE]->val !=
210                                 V4L2_FLASH_STROBE_SOURCE_SOFTWARE)));
211 }
212
213 static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
214 {
215         struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
216         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
217         struct led_classdev *led_cdev;
218         struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
219         bool external_strobe;
220         int ret = 0;
221
222         switch (c->id) {
223         case V4L2_CID_FLASH_TORCH_INTENSITY:
224         case V4L2_CID_FLASH_INDICATOR_INTENSITY:
225                 return v4l2_flash_set_led_brightness(v4l2_flash, c);
226         }
227
228         if (!fled_cdev)
229                 return -EINVAL;
230
231         led_cdev = &fled_cdev->led_cdev;
232
233         switch (c->id) {
234         case V4L2_CID_FLASH_LED_MODE:
235                 switch (c->val) {
236                 case V4L2_FLASH_LED_MODE_NONE:
237                         led_set_brightness_sync(led_cdev, LED_OFF);
238                         return led_set_flash_strobe(fled_cdev, false);
239                 case V4L2_FLASH_LED_MODE_FLASH:
240                         /* Turn the torch LED off */
241                         led_set_brightness_sync(led_cdev, LED_OFF);
242                         if (ctrls[STROBE_SOURCE]) {
243                                 external_strobe = (ctrls[STROBE_SOURCE]->val ==
244                                         V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
245
246                                 ret = call_flash_op(v4l2_flash,
247                                                 external_strobe_set,
248                                                 external_strobe);
249                         }
250                         return ret;
251                 case V4L2_FLASH_LED_MODE_TORCH:
252                         if (ctrls[STROBE_SOURCE]) {
253                                 ret = call_flash_op(v4l2_flash,
254                                                 external_strobe_set,
255                                                 false);
256                                 if (ret < 0)
257                                         return ret;
258                         }
259                         /* Stop flash strobing */
260                         ret = led_set_flash_strobe(fled_cdev, false);
261                         if (ret < 0)
262                                 return ret;
263
264                         return v4l2_flash_set_led_brightness(v4l2_flash,
265                                                              ctrls[TORCH_INTENSITY]);
266                 }
267                 break;
268         case V4L2_CID_FLASH_STROBE_SOURCE:
269                 external_strobe = (c->val == V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
270                 /*
271                  * For some hardware arrangements setting strobe source may
272                  * affect torch mode. Therefore, if not in the flash mode,
273                  * cache only this setting. It will be applied upon switching
274                  * to flash mode.
275                  */
276                 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_FLASH)
277                         return 0;
278
279                 return call_flash_op(v4l2_flash, external_strobe_set,
280                                         external_strobe);
281         case V4L2_CID_FLASH_STROBE:
282                 if (__software_strobe_mode_inactive(ctrls))
283                         return -EBUSY;
284                 return led_set_flash_strobe(fled_cdev, true);
285         case V4L2_CID_FLASH_STROBE_STOP:
286                 if (__software_strobe_mode_inactive(ctrls))
287                         return -EBUSY;
288                 return led_set_flash_strobe(fled_cdev, false);
289         case V4L2_CID_FLASH_TIMEOUT:
290                 /*
291                  * No conversion is needed as LED Flash class also uses
292                  * microseconds for flash timeout units.
293                  */
294                 return led_set_flash_timeout(fled_cdev, c->val);
295         case V4L2_CID_FLASH_INTENSITY:
296                 /*
297                  * No conversion is needed as LED Flash class also uses
298                  * microamperes for flash intensity units.
299                  */
300                 return led_set_flash_brightness(fled_cdev, c->val);
301         }
302
303         return -EINVAL;
304 }
305
306 static const struct v4l2_ctrl_ops v4l2_flash_ctrl_ops = {
307         .g_volatile_ctrl = v4l2_flash_g_volatile_ctrl,
308         .s_ctrl = v4l2_flash_s_ctrl,
309 };
310
311 static void __lfs_to_v4l2_ctrl_config(struct led_flash_setting *s,
312                                 struct v4l2_ctrl_config *c)
313 {
314         c->min = s->min;
315         c->max = s->max;
316         c->step = s->step;
317         c->def = s->val;
318 }
319
320 static void __fill_ctrl_init_data(struct v4l2_flash *v4l2_flash,
321                           struct v4l2_flash_config *flash_cfg,
322                           struct v4l2_flash_ctrl_data *ctrl_init_data)
323 {
324         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
325         struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
326         struct v4l2_ctrl_config *ctrl_cfg;
327         u32 mask;
328
329         /* Init INDICATOR_INTENSITY ctrl data */
330         if (v4l2_flash->iled_cdev) {
331                 ctrl_init_data[INDICATOR_INTENSITY].cid =
332                                         V4L2_CID_FLASH_INDICATOR_INTENSITY;
333                 ctrl_cfg = &ctrl_init_data[INDICATOR_INTENSITY].config;
334                 __lfs_to_v4l2_ctrl_config(&flash_cfg->intensity,
335                                           ctrl_cfg);
336                 ctrl_cfg->id = V4L2_CID_FLASH_INDICATOR_INTENSITY;
337                 ctrl_cfg->min = 0;
338                 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
339                                   V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
340         }
341
342         if (!led_cdev || WARN_ON(!(led_cdev->flags & LED_DEV_CAP_FLASH)))
343                 return;
344
345         /* Init FLASH_FAULT ctrl data */
346         if (flash_cfg->flash_faults) {
347                 ctrl_init_data[FLASH_FAULT].cid = V4L2_CID_FLASH_FAULT;
348                 ctrl_cfg = &ctrl_init_data[FLASH_FAULT].config;
349                 ctrl_cfg->id = V4L2_CID_FLASH_FAULT;
350                 ctrl_cfg->max = flash_cfg->flash_faults;
351                 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
352                                   V4L2_CTRL_FLAG_READ_ONLY;
353         }
354
355         /* Init FLASH_LED_MODE ctrl data */
356         mask = 1 << V4L2_FLASH_LED_MODE_NONE |
357                1 << V4L2_FLASH_LED_MODE_TORCH;
358         if (led_cdev->flags & LED_DEV_CAP_FLASH)
359                 mask |= 1 << V4L2_FLASH_LED_MODE_FLASH;
360
361         ctrl_init_data[LED_MODE].cid = V4L2_CID_FLASH_LED_MODE;
362         ctrl_cfg = &ctrl_init_data[LED_MODE].config;
363         ctrl_cfg->id = V4L2_CID_FLASH_LED_MODE;
364         ctrl_cfg->max = V4L2_FLASH_LED_MODE_TORCH;
365         ctrl_cfg->menu_skip_mask = ~mask;
366         ctrl_cfg->def = V4L2_FLASH_LED_MODE_NONE;
367         ctrl_cfg->flags = 0;
368
369         /* Init TORCH_INTENSITY ctrl data */
370         ctrl_init_data[TORCH_INTENSITY].cid = V4L2_CID_FLASH_TORCH_INTENSITY;
371         ctrl_cfg = &ctrl_init_data[TORCH_INTENSITY].config;
372         __lfs_to_v4l2_ctrl_config(&flash_cfg->intensity, ctrl_cfg);
373         ctrl_cfg->id = V4L2_CID_FLASH_TORCH_INTENSITY;
374         ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
375                           V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
376
377         /* Init FLASH_STROBE ctrl data */
378         ctrl_init_data[FLASH_STROBE].cid = V4L2_CID_FLASH_STROBE;
379         ctrl_cfg = &ctrl_init_data[FLASH_STROBE].config;
380         ctrl_cfg->id = V4L2_CID_FLASH_STROBE;
381
382         /* Init STROBE_STOP ctrl data */
383         ctrl_init_data[STROBE_STOP].cid = V4L2_CID_FLASH_STROBE_STOP;
384         ctrl_cfg = &ctrl_init_data[STROBE_STOP].config;
385         ctrl_cfg->id = V4L2_CID_FLASH_STROBE_STOP;
386
387         /* Init FLASH_STROBE_SOURCE ctrl data */
388         if (flash_cfg->has_external_strobe) {
389                 mask = (1 << V4L2_FLASH_STROBE_SOURCE_SOFTWARE) |
390                        (1 << V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
391                 ctrl_init_data[STROBE_SOURCE].cid =
392                                         V4L2_CID_FLASH_STROBE_SOURCE;
393                 ctrl_cfg = &ctrl_init_data[STROBE_SOURCE].config;
394                 ctrl_cfg->id = V4L2_CID_FLASH_STROBE_SOURCE;
395                 ctrl_cfg->max = V4L2_FLASH_STROBE_SOURCE_EXTERNAL;
396                 ctrl_cfg->menu_skip_mask = ~mask;
397                 ctrl_cfg->def = V4L2_FLASH_STROBE_SOURCE_SOFTWARE;
398         }
399
400         /* Init STROBE_STATUS ctrl data */
401         if (has_flash_op(fled_cdev, strobe_get)) {
402                 ctrl_init_data[STROBE_STATUS].cid =
403                                         V4L2_CID_FLASH_STROBE_STATUS;
404                 ctrl_cfg = &ctrl_init_data[STROBE_STATUS].config;
405                 ctrl_cfg->id = V4L2_CID_FLASH_STROBE_STATUS;
406                 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
407                                   V4L2_CTRL_FLAG_READ_ONLY;
408         }
409
410         /* Init FLASH_TIMEOUT ctrl data */
411         if (has_flash_op(fled_cdev, timeout_set)) {
412                 ctrl_init_data[FLASH_TIMEOUT].cid = V4L2_CID_FLASH_TIMEOUT;
413                 ctrl_cfg = &ctrl_init_data[FLASH_TIMEOUT].config;
414                 __lfs_to_v4l2_ctrl_config(&fled_cdev->timeout, ctrl_cfg);
415                 ctrl_cfg->id = V4L2_CID_FLASH_TIMEOUT;
416         }
417
418         /* Init FLASH_INTENSITY ctrl data */
419         if (has_flash_op(fled_cdev, flash_brightness_set)) {
420                 ctrl_init_data[FLASH_INTENSITY].cid = V4L2_CID_FLASH_INTENSITY;
421                 ctrl_cfg = &ctrl_init_data[FLASH_INTENSITY].config;
422                 __lfs_to_v4l2_ctrl_config(&fled_cdev->brightness, ctrl_cfg);
423                 ctrl_cfg->id = V4L2_CID_FLASH_INTENSITY;
424                 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
425                                   V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
426         }
427 }
428
429 static int v4l2_flash_init_controls(struct v4l2_flash *v4l2_flash,
430                                 struct v4l2_flash_config *flash_cfg)
431
432 {
433         struct v4l2_flash_ctrl_data *ctrl_init_data;
434         struct v4l2_ctrl *ctrl;
435         struct v4l2_ctrl_config *ctrl_cfg;
436         int i, ret, num_ctrls = 0;
437
438         v4l2_flash->ctrls = devm_kcalloc(v4l2_flash->sd.dev,
439                                         STROBE_SOURCE + 1,
440                                         sizeof(*v4l2_flash->ctrls),
441                                         GFP_KERNEL);
442         if (!v4l2_flash->ctrls)
443                 return -ENOMEM;
444
445         /* allocate memory dynamically so as not to exceed stack frame size */
446         ctrl_init_data = kcalloc(NUM_FLASH_CTRLS, sizeof(*ctrl_init_data),
447                                         GFP_KERNEL);
448         if (!ctrl_init_data)
449                 return -ENOMEM;
450
451         __fill_ctrl_init_data(v4l2_flash, flash_cfg, ctrl_init_data);
452
453         for (i = 0; i < NUM_FLASH_CTRLS; ++i)
454                 if (ctrl_init_data[i].cid)
455                         ++num_ctrls;
456
457         v4l2_ctrl_handler_init(&v4l2_flash->hdl, num_ctrls);
458
459         for (i = 0; i < NUM_FLASH_CTRLS; ++i) {
460                 ctrl_cfg = &ctrl_init_data[i].config;
461                 if (!ctrl_init_data[i].cid)
462                         continue;
463
464                 if (ctrl_cfg->id == V4L2_CID_FLASH_LED_MODE ||
465                     ctrl_cfg->id == V4L2_CID_FLASH_STROBE_SOURCE)
466                         ctrl = v4l2_ctrl_new_std_menu(&v4l2_flash->hdl,
467                                                 &v4l2_flash_ctrl_ops,
468                                                 ctrl_cfg->id,
469                                                 ctrl_cfg->max,
470                                                 ctrl_cfg->menu_skip_mask,
471                                                 ctrl_cfg->def);
472                 else
473                         ctrl = v4l2_ctrl_new_std(&v4l2_flash->hdl,
474                                                 &v4l2_flash_ctrl_ops,
475                                                 ctrl_cfg->id,
476                                                 ctrl_cfg->min,
477                                                 ctrl_cfg->max,
478                                                 ctrl_cfg->step,
479                                                 ctrl_cfg->def);
480
481                 if (ctrl)
482                         ctrl->flags |= ctrl_cfg->flags;
483
484                 if (i <= STROBE_SOURCE)
485                         v4l2_flash->ctrls[i] = ctrl;
486         }
487
488         kfree(ctrl_init_data);
489
490         if (v4l2_flash->hdl.error) {
491                 ret = v4l2_flash->hdl.error;
492                 goto error_free_handler;
493         }
494
495         v4l2_ctrl_handler_setup(&v4l2_flash->hdl);
496
497         v4l2_flash->sd.ctrl_handler = &v4l2_flash->hdl;
498
499         return 0;
500
501 error_free_handler:
502         v4l2_ctrl_handler_free(&v4l2_flash->hdl);
503         return ret;
504 }
505
506 static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
507 {
508         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
509         struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
510         int ret = 0;
511
512         if (ctrls[TORCH_INTENSITY]) {
513                 ret = v4l2_flash_set_led_brightness(v4l2_flash,
514                                                     ctrls[TORCH_INTENSITY]);
515                 if (ret < 0)
516                         return ret;
517         }
518
519         if (ctrls[INDICATOR_INTENSITY]) {
520                 ret = v4l2_flash_set_led_brightness(v4l2_flash,
521                                                     ctrls[INDICATOR_INTENSITY]);
522                 if (ret < 0)
523                         return ret;
524         }
525
526         if (ctrls[FLASH_TIMEOUT]) {
527                 if (WARN_ON_ONCE(!fled_cdev))
528                         return -EINVAL;
529
530                 ret = led_set_flash_timeout(fled_cdev,
531                                         ctrls[FLASH_TIMEOUT]->val);
532                 if (ret < 0)
533                         return ret;
534         }
535
536         if (ctrls[FLASH_INTENSITY]) {
537                 if (WARN_ON_ONCE(!fled_cdev))
538                         return -EINVAL;
539
540                 ret = led_set_flash_brightness(fled_cdev,
541                                         ctrls[FLASH_INTENSITY]->val);
542                 if (ret < 0)
543                         return ret;
544         }
545
546         /*
547          * For some hardware arrangements setting strobe source may affect
548          * torch mode. Synchronize strobe source setting only if not in torch
549          * mode. For torch mode case it will get synchronized upon switching
550          * to flash mode.
551          */
552         if (ctrls[STROBE_SOURCE] &&
553             ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
554                 ret = call_flash_op(v4l2_flash, external_strobe_set,
555                                         ctrls[STROBE_SOURCE]->val);
556
557         return ret;
558 }
559
560 /*
561  * V4L2 subdev internal operations
562  */
563
564 static int v4l2_flash_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
565 {
566         struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd);
567         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
568         struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
569         struct led_classdev *led_cdev_ind = v4l2_flash->iled_cdev;
570         int ret = 0;
571
572         if (!v4l2_fh_is_singular(&fh->vfh))
573                 return 0;
574
575         if (led_cdev) {
576                 mutex_lock(&led_cdev->led_access);
577
578                 led_sysfs_disable(led_cdev);
579                 led_trigger_remove(led_cdev);
580
581                 mutex_unlock(&led_cdev->led_access);
582         }
583
584         if (led_cdev_ind) {
585                 mutex_lock(&led_cdev_ind->led_access);
586
587                 led_sysfs_disable(led_cdev_ind);
588                 led_trigger_remove(led_cdev_ind);
589
590                 mutex_unlock(&led_cdev_ind->led_access);
591         }
592
593         ret = __sync_device_with_v4l2_controls(v4l2_flash);
594         if (ret < 0)
595                 goto out_sync_device;
596
597         return 0;
598 out_sync_device:
599         if (led_cdev) {
600                 mutex_lock(&led_cdev->led_access);
601                 led_sysfs_enable(led_cdev);
602                 mutex_unlock(&led_cdev->led_access);
603         }
604
605         if (led_cdev_ind) {
606                 mutex_lock(&led_cdev_ind->led_access);
607                 led_sysfs_enable(led_cdev_ind);
608                 mutex_unlock(&led_cdev_ind->led_access);
609         }
610
611         return ret;
612 }
613
614 static int v4l2_flash_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
615 {
616         struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd);
617         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
618         struct led_classdev *led_cdev = fled_cdev ? &fled_cdev->led_cdev : NULL;
619         struct led_classdev *led_cdev_ind = v4l2_flash->iled_cdev;
620         int ret = 0;
621
622         if (!v4l2_fh_is_singular(&fh->vfh))
623                 return 0;
624
625         if (led_cdev) {
626                 mutex_lock(&led_cdev->led_access);
627
628                 if (v4l2_flash->ctrls[STROBE_SOURCE])
629                         ret = v4l2_ctrl_s_ctrl(
630                                 v4l2_flash->ctrls[STROBE_SOURCE],
631                                 V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
632                 led_sysfs_enable(led_cdev);
633
634                 mutex_unlock(&led_cdev->led_access);
635         }
636
637         if (led_cdev_ind) {
638                 mutex_lock(&led_cdev_ind->led_access);
639                 led_sysfs_enable(led_cdev_ind);
640                 mutex_unlock(&led_cdev_ind->led_access);
641         }
642
643         return ret;
644 }
645
646 static const struct v4l2_subdev_internal_ops v4l2_flash_subdev_internal_ops = {
647         .open = v4l2_flash_open,
648         .close = v4l2_flash_close,
649 };
650
651 static const struct v4l2_subdev_ops v4l2_flash_subdev_ops;
652
653 static struct v4l2_flash *__v4l2_flash_init(
654         struct device *dev, struct fwnode_handle *fwn,
655         struct led_classdev_flash *fled_cdev, struct led_classdev *iled_cdev,
656         const struct v4l2_flash_ops *ops, struct v4l2_flash_config *config)
657 {
658         struct v4l2_flash *v4l2_flash;
659         struct v4l2_subdev *sd;
660         int ret;
661
662         if (!config)
663                 return ERR_PTR(-EINVAL);
664
665         v4l2_flash = devm_kzalloc(dev, sizeof(*v4l2_flash), GFP_KERNEL);
666         if (!v4l2_flash)
667                 return ERR_PTR(-ENOMEM);
668
669         sd = &v4l2_flash->sd;
670         v4l2_flash->fled_cdev = fled_cdev;
671         v4l2_flash->iled_cdev = iled_cdev;
672         v4l2_flash->ops = ops;
673         sd->dev = dev;
674         sd->fwnode = fwn ? fwn : dev_fwnode(dev);
675         v4l2_subdev_init(sd, &v4l2_flash_subdev_ops);
676         sd->internal_ops = &v4l2_flash_subdev_internal_ops;
677         sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
678         strscpy(sd->name, config->dev_name, sizeof(sd->name));
679
680         ret = media_entity_pads_init(&sd->entity, 0, NULL);
681         if (ret < 0)
682                 return ERR_PTR(ret);
683
684         sd->entity.function = MEDIA_ENT_F_FLASH;
685
686         ret = v4l2_flash_init_controls(v4l2_flash, config);
687         if (ret < 0)
688                 goto err_init_controls;
689
690         fwnode_handle_get(sd->fwnode);
691
692         ret = v4l2_async_register_subdev(sd);
693         if (ret < 0)
694                 goto err_async_register_sd;
695
696         return v4l2_flash;
697
698 err_async_register_sd:
699         fwnode_handle_put(sd->fwnode);
700         v4l2_ctrl_handler_free(sd->ctrl_handler);
701 err_init_controls:
702         media_entity_cleanup(&sd->entity);
703
704         return ERR_PTR(ret);
705 }
706
707 struct v4l2_flash *v4l2_flash_init(
708         struct device *dev, struct fwnode_handle *fwn,
709         struct led_classdev_flash *fled_cdev,
710         const struct v4l2_flash_ops *ops,
711         struct v4l2_flash_config *config)
712 {
713         return __v4l2_flash_init(dev, fwn, fled_cdev, NULL, ops, config);
714 }
715 EXPORT_SYMBOL_GPL(v4l2_flash_init);
716
717 struct v4l2_flash *v4l2_flash_indicator_init(
718         struct device *dev, struct fwnode_handle *fwn,
719         struct led_classdev *iled_cdev,
720         struct v4l2_flash_config *config)
721 {
722         return __v4l2_flash_init(dev, fwn, NULL, iled_cdev, NULL, config);
723 }
724 EXPORT_SYMBOL_GPL(v4l2_flash_indicator_init);
725
726 void v4l2_flash_release(struct v4l2_flash *v4l2_flash)
727 {
728         struct v4l2_subdev *sd;
729
730         if (IS_ERR_OR_NULL(v4l2_flash))
731                 return;
732
733         sd = &v4l2_flash->sd;
734
735         v4l2_async_unregister_subdev(sd);
736
737         fwnode_handle_put(sd->fwnode);
738
739         v4l2_ctrl_handler_free(sd->ctrl_handler);
740         media_entity_cleanup(&sd->entity);
741 }
742 EXPORT_SYMBOL_GPL(v4l2_flash_release);
743
744 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
745 MODULE_DESCRIPTION("V4L2 Flash sub-device helpers");
746 MODULE_LICENSE("GPL v2");