1 // SPDX-License-Identifier: GPL-2.0-only
3 * V4L2 flash LED sub-device registration helpers.
5 * Copyright (C) 2015 Samsung Electronics Co., Ltd
6 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
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>
17 #define has_flash_op(v4l2_flash, op) \
18 (v4l2_flash && v4l2_flash->ops && v4l2_flash->ops->op)
20 #define call_flash_op(v4l2_flash, op, arg) \
21 (has_flash_op(v4l2_flash, op) ? \
22 v4l2_flash->ops->op(v4l2_flash, arg) : \
25 enum ctrl_init_data_id
{
33 * Only above values are applicable to
34 * the 'ctrls' array in the struct v4l2_flash.
43 static enum led_brightness
__intensity_to_led_brightness(
44 struct v4l2_ctrl
*ctrl
, s32 intensity
)
46 intensity
-= ctrl
->minimum
;
47 intensity
/= (u32
) ctrl
->step
;
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.
61 static s32
__led_brightness_to_intensity(struct v4l2_ctrl
*ctrl
,
62 enum led_brightness brightness
)
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.
73 if (ctrl
->id
!= V4L2_CID_FLASH_INDICATOR_INTENSITY
)
76 return (brightness
* ctrl
->step
) + ctrl
->minimum
;
79 static void v4l2_flash_set_led_brightness(struct v4l2_flash
*v4l2_flash
,
80 struct v4l2_ctrl
*ctrl
)
82 struct v4l2_ctrl
**ctrls
= v4l2_flash
->ctrls
;
83 enum led_brightness brightness
;
85 if (has_flash_op(v4l2_flash
, intensity_to_led_brightness
))
86 brightness
= call_flash_op(v4l2_flash
,
87 intensity_to_led_brightness
,
90 brightness
= __intensity_to_led_brightness(ctrl
, ctrl
->val
);
92 * In case a LED Flash class driver provides ops for custom
93 * brightness <-> intensity conversion, it also must have defined
94 * related v4l2 control step == 1. In such a case a backward conversion
95 * from led brightness to v4l2 intensity is required to find out the
96 * the aligned intensity value.
98 if (has_flash_op(v4l2_flash
, led_brightness_to_intensity
))
99 ctrl
->val
= call_flash_op(v4l2_flash
,
100 led_brightness_to_intensity
,
103 if (ctrl
== ctrls
[TORCH_INTENSITY
]) {
104 if (ctrls
[LED_MODE
]->val
!= V4L2_FLASH_LED_MODE_TORCH
)
107 led_set_brightness_sync(&v4l2_flash
->fled_cdev
->led_cdev
,
110 led_set_brightness_sync(v4l2_flash
->iled_cdev
,
115 static int v4l2_flash_update_led_brightness(struct v4l2_flash
*v4l2_flash
,
116 struct v4l2_ctrl
*ctrl
)
118 struct v4l2_ctrl
**ctrls
= v4l2_flash
->ctrls
;
119 struct led_classdev
*led_cdev
;
122 if (ctrl
== ctrls
[TORCH_INTENSITY
]) {
124 * Update torch brightness only if in TORCH_MODE. In other modes
125 * torch led is turned off, which would spuriously inform the
126 * user space that V4L2_CID_FLASH_TORCH_INTENSITY control value
129 if (ctrls
[LED_MODE
]->val
!= V4L2_FLASH_LED_MODE_TORCH
)
131 led_cdev
= &v4l2_flash
->fled_cdev
->led_cdev
;
133 led_cdev
= v4l2_flash
->iled_cdev
;
136 ret
= led_update_brightness(led_cdev
);
140 if (has_flash_op(v4l2_flash
, led_brightness_to_intensity
))
141 ctrl
->val
= call_flash_op(v4l2_flash
,
142 led_brightness_to_intensity
,
143 led_cdev
->brightness
);
145 ctrl
->val
= __led_brightness_to_intensity(ctrl
,
146 led_cdev
->brightness
);
151 static int v4l2_flash_g_volatile_ctrl(struct v4l2_ctrl
*c
)
153 struct v4l2_flash
*v4l2_flash
= v4l2_ctrl_to_v4l2_flash(c
);
154 struct led_classdev_flash
*fled_cdev
= v4l2_flash
->fled_cdev
;
159 case V4L2_CID_FLASH_TORCH_INTENSITY
:
160 case V4L2_CID_FLASH_INDICATOR_INTENSITY
:
161 return v4l2_flash_update_led_brightness(v4l2_flash
, c
);
162 case V4L2_CID_FLASH_INTENSITY
:
163 ret
= led_update_flash_brightness(fled_cdev
);
167 * No conversion is needed as LED Flash class also uses
168 * microamperes for flash intensity units.
170 c
->val
= fled_cdev
->brightness
.val
;
172 case V4L2_CID_FLASH_STROBE_STATUS
:
173 ret
= led_get_flash_strobe(fled_cdev
, &is_strobing
);
176 c
->val
= is_strobing
;
178 case V4L2_CID_FLASH_FAULT
:
179 /* LED faults map directly to V4L2 flash faults */
180 return led_get_flash_fault(fled_cdev
, &c
->val
);
186 static bool __software_strobe_mode_inactive(struct v4l2_ctrl
**ctrls
)
188 return ((ctrls
[LED_MODE
]->val
!= V4L2_FLASH_LED_MODE_FLASH
) ||
189 (ctrls
[STROBE_SOURCE
] && (ctrls
[STROBE_SOURCE
]->val
!=
190 V4L2_FLASH_STROBE_SOURCE_SOFTWARE
)));
193 static int v4l2_flash_s_ctrl(struct v4l2_ctrl
*c
)
195 struct v4l2_flash
*v4l2_flash
= v4l2_ctrl_to_v4l2_flash(c
);
196 struct led_classdev_flash
*fled_cdev
= v4l2_flash
->fled_cdev
;
197 struct led_classdev
*led_cdev
= fled_cdev
? &fled_cdev
->led_cdev
: NULL
;
198 struct v4l2_ctrl
**ctrls
= v4l2_flash
->ctrls
;
199 bool external_strobe
;
203 case V4L2_CID_FLASH_LED_MODE
:
205 case V4L2_FLASH_LED_MODE_NONE
:
206 led_set_brightness_sync(led_cdev
, LED_OFF
);
207 return led_set_flash_strobe(fled_cdev
, false);
208 case V4L2_FLASH_LED_MODE_FLASH
:
209 /* Turn the torch LED off */
210 led_set_brightness_sync(led_cdev
, LED_OFF
);
211 if (ctrls
[STROBE_SOURCE
]) {
212 external_strobe
= (ctrls
[STROBE_SOURCE
]->val
==
213 V4L2_FLASH_STROBE_SOURCE_EXTERNAL
);
215 ret
= call_flash_op(v4l2_flash
,
220 case V4L2_FLASH_LED_MODE_TORCH
:
221 if (ctrls
[STROBE_SOURCE
]) {
222 ret
= call_flash_op(v4l2_flash
,
228 /* Stop flash strobing */
229 ret
= led_set_flash_strobe(fled_cdev
, false);
233 v4l2_flash_set_led_brightness(v4l2_flash
,
234 ctrls
[TORCH_INTENSITY
]);
238 case V4L2_CID_FLASH_STROBE_SOURCE
:
239 external_strobe
= (c
->val
== V4L2_FLASH_STROBE_SOURCE_EXTERNAL
);
241 * For some hardware arrangements setting strobe source may
242 * affect torch mode. Therefore, if not in the flash mode,
243 * cache only this setting. It will be applied upon switching
246 if (ctrls
[LED_MODE
]->val
!= V4L2_FLASH_LED_MODE_FLASH
)
249 return call_flash_op(v4l2_flash
, external_strobe_set
,
251 case V4L2_CID_FLASH_STROBE
:
252 if (__software_strobe_mode_inactive(ctrls
))
254 return led_set_flash_strobe(fled_cdev
, true);
255 case V4L2_CID_FLASH_STROBE_STOP
:
256 if (__software_strobe_mode_inactive(ctrls
))
258 return led_set_flash_strobe(fled_cdev
, false);
259 case V4L2_CID_FLASH_TIMEOUT
:
261 * No conversion is needed as LED Flash class also uses
262 * microseconds for flash timeout units.
264 return led_set_flash_timeout(fled_cdev
, c
->val
);
265 case V4L2_CID_FLASH_INTENSITY
:
267 * No conversion is needed as LED Flash class also uses
268 * microamperes for flash intensity units.
270 return led_set_flash_brightness(fled_cdev
, c
->val
);
271 case V4L2_CID_FLASH_TORCH_INTENSITY
:
272 case V4L2_CID_FLASH_INDICATOR_INTENSITY
:
273 v4l2_flash_set_led_brightness(v4l2_flash
, c
);
280 static const struct v4l2_ctrl_ops v4l2_flash_ctrl_ops
= {
281 .g_volatile_ctrl
= v4l2_flash_g_volatile_ctrl
,
282 .s_ctrl
= v4l2_flash_s_ctrl
,
285 static void __lfs_to_v4l2_ctrl_config(struct led_flash_setting
*s
,
286 struct v4l2_ctrl_config
*c
)
294 static void __fill_ctrl_init_data(struct v4l2_flash
*v4l2_flash
,
295 struct v4l2_flash_config
*flash_cfg
,
296 struct v4l2_flash_ctrl_data
*ctrl_init_data
)
298 struct led_classdev_flash
*fled_cdev
= v4l2_flash
->fled_cdev
;
299 struct led_classdev
*led_cdev
= fled_cdev
? &fled_cdev
->led_cdev
: NULL
;
300 struct v4l2_ctrl_config
*ctrl_cfg
;
303 /* Init INDICATOR_INTENSITY ctrl data */
304 if (v4l2_flash
->iled_cdev
) {
305 ctrl_init_data
[INDICATOR_INTENSITY
].cid
=
306 V4L2_CID_FLASH_INDICATOR_INTENSITY
;
307 ctrl_cfg
= &ctrl_init_data
[INDICATOR_INTENSITY
].config
;
308 __lfs_to_v4l2_ctrl_config(&flash_cfg
->intensity
,
310 ctrl_cfg
->id
= V4L2_CID_FLASH_INDICATOR_INTENSITY
;
312 ctrl_cfg
->flags
= V4L2_CTRL_FLAG_VOLATILE
|
313 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE
;
316 if (!led_cdev
|| WARN_ON(!(led_cdev
->flags
& LED_DEV_CAP_FLASH
)))
319 /* Init FLASH_FAULT ctrl data */
320 if (flash_cfg
->flash_faults
) {
321 ctrl_init_data
[FLASH_FAULT
].cid
= V4L2_CID_FLASH_FAULT
;
322 ctrl_cfg
= &ctrl_init_data
[FLASH_FAULT
].config
;
323 ctrl_cfg
->id
= V4L2_CID_FLASH_FAULT
;
324 ctrl_cfg
->max
= flash_cfg
->flash_faults
;
325 ctrl_cfg
->flags
= V4L2_CTRL_FLAG_VOLATILE
|
326 V4L2_CTRL_FLAG_READ_ONLY
;
329 /* Init FLASH_LED_MODE ctrl data */
330 mask
= 1 << V4L2_FLASH_LED_MODE_NONE
|
331 1 << V4L2_FLASH_LED_MODE_TORCH
;
332 if (led_cdev
->flags
& LED_DEV_CAP_FLASH
)
333 mask
|= 1 << V4L2_FLASH_LED_MODE_FLASH
;
335 ctrl_init_data
[LED_MODE
].cid
= V4L2_CID_FLASH_LED_MODE
;
336 ctrl_cfg
= &ctrl_init_data
[LED_MODE
].config
;
337 ctrl_cfg
->id
= V4L2_CID_FLASH_LED_MODE
;
338 ctrl_cfg
->max
= V4L2_FLASH_LED_MODE_TORCH
;
339 ctrl_cfg
->menu_skip_mask
= ~mask
;
340 ctrl_cfg
->def
= V4L2_FLASH_LED_MODE_NONE
;
343 /* Init TORCH_INTENSITY ctrl data */
344 ctrl_init_data
[TORCH_INTENSITY
].cid
= V4L2_CID_FLASH_TORCH_INTENSITY
;
345 ctrl_cfg
= &ctrl_init_data
[TORCH_INTENSITY
].config
;
346 __lfs_to_v4l2_ctrl_config(&flash_cfg
->intensity
, ctrl_cfg
);
347 ctrl_cfg
->id
= V4L2_CID_FLASH_TORCH_INTENSITY
;
348 ctrl_cfg
->flags
= V4L2_CTRL_FLAG_VOLATILE
|
349 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE
;
351 /* Init FLASH_STROBE ctrl data */
352 ctrl_init_data
[FLASH_STROBE
].cid
= V4L2_CID_FLASH_STROBE
;
353 ctrl_cfg
= &ctrl_init_data
[FLASH_STROBE
].config
;
354 ctrl_cfg
->id
= V4L2_CID_FLASH_STROBE
;
356 /* Init STROBE_STOP ctrl data */
357 ctrl_init_data
[STROBE_STOP
].cid
= V4L2_CID_FLASH_STROBE_STOP
;
358 ctrl_cfg
= &ctrl_init_data
[STROBE_STOP
].config
;
359 ctrl_cfg
->id
= V4L2_CID_FLASH_STROBE_STOP
;
361 /* Init FLASH_STROBE_SOURCE ctrl data */
362 if (flash_cfg
->has_external_strobe
) {
363 mask
= (1 << V4L2_FLASH_STROBE_SOURCE_SOFTWARE
) |
364 (1 << V4L2_FLASH_STROBE_SOURCE_EXTERNAL
);
365 ctrl_init_data
[STROBE_SOURCE
].cid
=
366 V4L2_CID_FLASH_STROBE_SOURCE
;
367 ctrl_cfg
= &ctrl_init_data
[STROBE_SOURCE
].config
;
368 ctrl_cfg
->id
= V4L2_CID_FLASH_STROBE_SOURCE
;
369 ctrl_cfg
->max
= V4L2_FLASH_STROBE_SOURCE_EXTERNAL
;
370 ctrl_cfg
->menu_skip_mask
= ~mask
;
371 ctrl_cfg
->def
= V4L2_FLASH_STROBE_SOURCE_SOFTWARE
;
374 /* Init STROBE_STATUS ctrl data */
375 if (has_flash_op(fled_cdev
, strobe_get
)) {
376 ctrl_init_data
[STROBE_STATUS
].cid
=
377 V4L2_CID_FLASH_STROBE_STATUS
;
378 ctrl_cfg
= &ctrl_init_data
[STROBE_STATUS
].config
;
379 ctrl_cfg
->id
= V4L2_CID_FLASH_STROBE_STATUS
;
380 ctrl_cfg
->flags
= V4L2_CTRL_FLAG_VOLATILE
|
381 V4L2_CTRL_FLAG_READ_ONLY
;
384 /* Init FLASH_TIMEOUT ctrl data */
385 if (has_flash_op(fled_cdev
, timeout_set
)) {
386 ctrl_init_data
[FLASH_TIMEOUT
].cid
= V4L2_CID_FLASH_TIMEOUT
;
387 ctrl_cfg
= &ctrl_init_data
[FLASH_TIMEOUT
].config
;
388 __lfs_to_v4l2_ctrl_config(&fled_cdev
->timeout
, ctrl_cfg
);
389 ctrl_cfg
->id
= V4L2_CID_FLASH_TIMEOUT
;
392 /* Init FLASH_INTENSITY ctrl data */
393 if (has_flash_op(fled_cdev
, flash_brightness_set
)) {
394 ctrl_init_data
[FLASH_INTENSITY
].cid
= V4L2_CID_FLASH_INTENSITY
;
395 ctrl_cfg
= &ctrl_init_data
[FLASH_INTENSITY
].config
;
396 __lfs_to_v4l2_ctrl_config(&fled_cdev
->brightness
, ctrl_cfg
);
397 ctrl_cfg
->id
= V4L2_CID_FLASH_INTENSITY
;
398 ctrl_cfg
->flags
= V4L2_CTRL_FLAG_VOLATILE
|
399 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE
;
403 static int v4l2_flash_init_controls(struct v4l2_flash
*v4l2_flash
,
404 struct v4l2_flash_config
*flash_cfg
)
407 struct v4l2_flash_ctrl_data
*ctrl_init_data
;
408 struct v4l2_ctrl
*ctrl
;
409 struct v4l2_ctrl_config
*ctrl_cfg
;
410 int i
, ret
, num_ctrls
= 0;
412 v4l2_flash
->ctrls
= devm_kcalloc(v4l2_flash
->sd
.dev
,
414 sizeof(*v4l2_flash
->ctrls
),
416 if (!v4l2_flash
->ctrls
)
419 /* allocate memory dynamically so as not to exceed stack frame size */
420 ctrl_init_data
= kcalloc(NUM_FLASH_CTRLS
, sizeof(*ctrl_init_data
),
425 __fill_ctrl_init_data(v4l2_flash
, flash_cfg
, ctrl_init_data
);
427 for (i
= 0; i
< NUM_FLASH_CTRLS
; ++i
)
428 if (ctrl_init_data
[i
].cid
)
431 v4l2_ctrl_handler_init(&v4l2_flash
->hdl
, num_ctrls
);
433 for (i
= 0; i
< NUM_FLASH_CTRLS
; ++i
) {
434 ctrl_cfg
= &ctrl_init_data
[i
].config
;
435 if (!ctrl_init_data
[i
].cid
)
438 if (ctrl_cfg
->id
== V4L2_CID_FLASH_LED_MODE
||
439 ctrl_cfg
->id
== V4L2_CID_FLASH_STROBE_SOURCE
)
440 ctrl
= v4l2_ctrl_new_std_menu(&v4l2_flash
->hdl
,
441 &v4l2_flash_ctrl_ops
,
444 ctrl_cfg
->menu_skip_mask
,
447 ctrl
= v4l2_ctrl_new_std(&v4l2_flash
->hdl
,
448 &v4l2_flash_ctrl_ops
,
456 ctrl
->flags
|= ctrl_cfg
->flags
;
458 if (i
<= STROBE_SOURCE
)
459 v4l2_flash
->ctrls
[i
] = ctrl
;
462 kfree(ctrl_init_data
);
464 if (v4l2_flash
->hdl
.error
) {
465 ret
= v4l2_flash
->hdl
.error
;
466 goto error_free_handler
;
469 v4l2_ctrl_handler_setup(&v4l2_flash
->hdl
);
471 v4l2_flash
->sd
.ctrl_handler
= &v4l2_flash
->hdl
;
476 v4l2_ctrl_handler_free(&v4l2_flash
->hdl
);
480 static int __sync_device_with_v4l2_controls(struct v4l2_flash
*v4l2_flash
)
482 struct led_classdev_flash
*fled_cdev
= v4l2_flash
->fled_cdev
;
483 struct v4l2_ctrl
**ctrls
= v4l2_flash
->ctrls
;
486 if (ctrls
[TORCH_INTENSITY
])
487 v4l2_flash_set_led_brightness(v4l2_flash
,
488 ctrls
[TORCH_INTENSITY
]);
490 if (ctrls
[INDICATOR_INTENSITY
])
491 v4l2_flash_set_led_brightness(v4l2_flash
,
492 ctrls
[INDICATOR_INTENSITY
]);
494 if (ctrls
[FLASH_TIMEOUT
]) {
495 ret
= led_set_flash_timeout(fled_cdev
,
496 ctrls
[FLASH_TIMEOUT
]->val
);
501 if (ctrls
[FLASH_INTENSITY
]) {
502 ret
= led_set_flash_brightness(fled_cdev
,
503 ctrls
[FLASH_INTENSITY
]->val
);
509 * For some hardware arrangements setting strobe source may affect
510 * torch mode. Synchronize strobe source setting only if not in torch
511 * mode. For torch mode case it will get synchronized upon switching
514 if (ctrls
[STROBE_SOURCE
] &&
515 ctrls
[LED_MODE
]->val
!= V4L2_FLASH_LED_MODE_TORCH
)
516 ret
= call_flash_op(v4l2_flash
, external_strobe_set
,
517 ctrls
[STROBE_SOURCE
]->val
);
523 * V4L2 subdev internal operations
526 static int v4l2_flash_open(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
)
528 struct v4l2_flash
*v4l2_flash
= v4l2_subdev_to_v4l2_flash(sd
);
529 struct led_classdev_flash
*fled_cdev
= v4l2_flash
->fled_cdev
;
530 struct led_classdev
*led_cdev
= fled_cdev
? &fled_cdev
->led_cdev
: NULL
;
531 struct led_classdev
*led_cdev_ind
= v4l2_flash
->iled_cdev
;
534 if (!v4l2_fh_is_singular(&fh
->vfh
))
538 mutex_lock(&led_cdev
->led_access
);
540 led_sysfs_disable(led_cdev
);
541 led_trigger_remove(led_cdev
);
543 mutex_unlock(&led_cdev
->led_access
);
547 mutex_lock(&led_cdev_ind
->led_access
);
549 led_sysfs_disable(led_cdev_ind
);
550 led_trigger_remove(led_cdev_ind
);
552 mutex_unlock(&led_cdev_ind
->led_access
);
555 ret
= __sync_device_with_v4l2_controls(v4l2_flash
);
557 goto out_sync_device
;
562 mutex_lock(&led_cdev
->led_access
);
563 led_sysfs_enable(led_cdev
);
564 mutex_unlock(&led_cdev
->led_access
);
568 mutex_lock(&led_cdev_ind
->led_access
);
569 led_sysfs_enable(led_cdev_ind
);
570 mutex_unlock(&led_cdev_ind
->led_access
);
576 static int v4l2_flash_close(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
)
578 struct v4l2_flash
*v4l2_flash
= v4l2_subdev_to_v4l2_flash(sd
);
579 struct led_classdev_flash
*fled_cdev
= v4l2_flash
->fled_cdev
;
580 struct led_classdev
*led_cdev
= fled_cdev
? &fled_cdev
->led_cdev
: NULL
;
581 struct led_classdev
*led_cdev_ind
= v4l2_flash
->iled_cdev
;
584 if (!v4l2_fh_is_singular(&fh
->vfh
))
588 mutex_lock(&led_cdev
->led_access
);
590 if (v4l2_flash
->ctrls
[STROBE_SOURCE
])
591 ret
= v4l2_ctrl_s_ctrl(
592 v4l2_flash
->ctrls
[STROBE_SOURCE
],
593 V4L2_FLASH_STROBE_SOURCE_SOFTWARE
);
594 led_sysfs_enable(led_cdev
);
596 mutex_unlock(&led_cdev
->led_access
);
600 mutex_lock(&led_cdev_ind
->led_access
);
601 led_sysfs_enable(led_cdev_ind
);
602 mutex_unlock(&led_cdev_ind
->led_access
);
608 static const struct v4l2_subdev_internal_ops v4l2_flash_subdev_internal_ops
= {
609 .open
= v4l2_flash_open
,
610 .close
= v4l2_flash_close
,
613 static const struct v4l2_subdev_ops v4l2_flash_subdev_ops
;
615 static struct v4l2_flash
*__v4l2_flash_init(
616 struct device
*dev
, struct fwnode_handle
*fwn
,
617 struct led_classdev_flash
*fled_cdev
, struct led_classdev
*iled_cdev
,
618 const struct v4l2_flash_ops
*ops
, struct v4l2_flash_config
*config
)
620 struct v4l2_flash
*v4l2_flash
;
621 struct v4l2_subdev
*sd
;
625 return ERR_PTR(-EINVAL
);
627 v4l2_flash
= devm_kzalloc(dev
, sizeof(*v4l2_flash
), GFP_KERNEL
);
629 return ERR_PTR(-ENOMEM
);
631 sd
= &v4l2_flash
->sd
;
632 v4l2_flash
->fled_cdev
= fled_cdev
;
633 v4l2_flash
->iled_cdev
= iled_cdev
;
634 v4l2_flash
->ops
= ops
;
636 sd
->fwnode
= fwn
? fwn
: dev_fwnode(dev
);
637 v4l2_subdev_init(sd
, &v4l2_flash_subdev_ops
);
638 sd
->internal_ops
= &v4l2_flash_subdev_internal_ops
;
639 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
640 strscpy(sd
->name
, config
->dev_name
, sizeof(sd
->name
));
642 ret
= media_entity_pads_init(&sd
->entity
, 0, NULL
);
646 sd
->entity
.function
= MEDIA_ENT_F_FLASH
;
648 ret
= v4l2_flash_init_controls(v4l2_flash
, config
);
650 goto err_init_controls
;
652 fwnode_handle_get(sd
->fwnode
);
654 ret
= v4l2_async_register_subdev(sd
);
656 goto err_async_register_sd
;
660 err_async_register_sd
:
661 fwnode_handle_put(sd
->fwnode
);
662 v4l2_ctrl_handler_free(sd
->ctrl_handler
);
664 media_entity_cleanup(&sd
->entity
);
669 struct v4l2_flash
*v4l2_flash_init(
670 struct device
*dev
, struct fwnode_handle
*fwn
,
671 struct led_classdev_flash
*fled_cdev
,
672 const struct v4l2_flash_ops
*ops
,
673 struct v4l2_flash_config
*config
)
675 return __v4l2_flash_init(dev
, fwn
, fled_cdev
, NULL
, ops
, config
);
677 EXPORT_SYMBOL_GPL(v4l2_flash_init
);
679 struct v4l2_flash
*v4l2_flash_indicator_init(
680 struct device
*dev
, struct fwnode_handle
*fwn
,
681 struct led_classdev
*iled_cdev
,
682 struct v4l2_flash_config
*config
)
684 return __v4l2_flash_init(dev
, fwn
, NULL
, iled_cdev
, NULL
, config
);
686 EXPORT_SYMBOL_GPL(v4l2_flash_indicator_init
);
688 void v4l2_flash_release(struct v4l2_flash
*v4l2_flash
)
690 struct v4l2_subdev
*sd
;
692 if (IS_ERR_OR_NULL(v4l2_flash
))
695 sd
= &v4l2_flash
->sd
;
697 v4l2_async_unregister_subdev(sd
);
699 fwnode_handle_put(sd
->fwnode
);
701 v4l2_ctrl_handler_free(sd
->ctrl_handler
);
702 media_entity_cleanup(&sd
->entity
);
704 EXPORT_SYMBOL_GPL(v4l2_flash_release
);
706 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
707 MODULE_DESCRIPTION("V4L2 Flash sub-device helpers");
708 MODULE_LICENSE("GPL v2");