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