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->led_cdev; 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->led_cdev; 303 struct v4l2_ctrl_config *ctrl_cfg; 304 u32 mask; 305 306 /* Init FLASH_FAULT ctrl data */ 307 if (flash_cfg->flash_faults) { 308 ctrl_init_data[FLASH_FAULT].cid = V4L2_CID_FLASH_FAULT; 309 ctrl_cfg = &ctrl_init_data[FLASH_FAULT].config; 310 ctrl_cfg->id = V4L2_CID_FLASH_FAULT; 311 ctrl_cfg->max = flash_cfg->flash_faults; 312 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE | 313 V4L2_CTRL_FLAG_READ_ONLY; 314 } 315 316 /* Init FLASH_LED_MODE ctrl data */ 317 mask = 1 << V4L2_FLASH_LED_MODE_NONE | 318 1 << V4L2_FLASH_LED_MODE_TORCH; 319 if (led_cdev->flags & LED_DEV_CAP_FLASH) 320 mask |= 1 << V4L2_FLASH_LED_MODE_FLASH; 321 322 ctrl_init_data[LED_MODE].cid = V4L2_CID_FLASH_LED_MODE; 323 ctrl_cfg = &ctrl_init_data[LED_MODE].config; 324 ctrl_cfg->id = V4L2_CID_FLASH_LED_MODE; 325 ctrl_cfg->max = V4L2_FLASH_LED_MODE_TORCH; 326 ctrl_cfg->menu_skip_mask = ~mask; 327 ctrl_cfg->def = V4L2_FLASH_LED_MODE_NONE; 328 ctrl_cfg->flags = 0; 329 330 /* Init TORCH_INTENSITY ctrl data */ 331 ctrl_init_data[TORCH_INTENSITY].cid = V4L2_CID_FLASH_TORCH_INTENSITY; 332 ctrl_cfg = &ctrl_init_data[TORCH_INTENSITY].config; 333 __lfs_to_v4l2_ctrl_config(&flash_cfg->torch_intensity, ctrl_cfg); 334 ctrl_cfg->id = V4L2_CID_FLASH_TORCH_INTENSITY; 335 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE | 336 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; 337 338 /* Init INDICATOR_INTENSITY ctrl data */ 339 if (v4l2_flash->iled_cdev) { 340 ctrl_init_data[INDICATOR_INTENSITY].cid = 341 V4L2_CID_FLASH_INDICATOR_INTENSITY; 342 ctrl_cfg = &ctrl_init_data[INDICATOR_INTENSITY].config; 343 __lfs_to_v4l2_ctrl_config(&flash_cfg->indicator_intensity, 344 ctrl_cfg); 345 ctrl_cfg->id = V4L2_CID_FLASH_INDICATOR_INTENSITY; 346 ctrl_cfg->min = 0; 347 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE | 348 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; 349 } 350 351 if (!(led_cdev->flags & LED_DEV_CAP_FLASH)) 352 return; 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 v4l2_flash_set_led_brightness(v4l2_flash, ctrls[TORCH_INTENSITY]); 489 490 if (ctrls[INDICATOR_INTENSITY]) 491 v4l2_flash_set_led_brightness(v4l2_flash, 492 ctrls[INDICATOR_INTENSITY]); 493 494 if (ctrls[FLASH_TIMEOUT]) { 495 ret = led_set_flash_timeout(fled_cdev, 496 ctrls[FLASH_TIMEOUT]->val); 497 if (ret < 0) 498 return ret; 499 } 500 501 if (ctrls[FLASH_INTENSITY]) { 502 ret = led_set_flash_brightness(fled_cdev, 503 ctrls[FLASH_INTENSITY]->val); 504 if (ret < 0) 505 return ret; 506 } 507 508 /* 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 512 * to flash mode. 513 */ 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); 518 519 return ret; 520 } 521 522 /* 523 * V4L2 subdev internal operations 524 */ 525 526 static int v4l2_flash_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 527 { 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->led_cdev; 531 struct led_classdev *led_cdev_ind = v4l2_flash->iled_cdev; 532 int ret = 0; 533 534 if (!v4l2_fh_is_singular(&fh->vfh)) 535 return 0; 536 537 mutex_lock(&led_cdev->led_access); 538 539 led_sysfs_disable(led_cdev); 540 led_trigger_remove(led_cdev); 541 542 mutex_unlock(&led_cdev->led_access); 543 544 if (led_cdev_ind) { 545 mutex_lock(&led_cdev_ind->led_access); 546 547 led_sysfs_disable(led_cdev_ind); 548 led_trigger_remove(led_cdev_ind); 549 550 mutex_unlock(&led_cdev_ind->led_access); 551 } 552 553 ret = __sync_device_with_v4l2_controls(v4l2_flash); 554 if (ret < 0) 555 goto out_sync_device; 556 557 return 0; 558 out_sync_device: 559 mutex_lock(&led_cdev->led_access); 560 led_sysfs_enable(led_cdev); 561 mutex_unlock(&led_cdev->led_access); 562 563 if (led_cdev_ind) { 564 mutex_lock(&led_cdev_ind->led_access); 565 led_sysfs_enable(led_cdev_ind); 566 mutex_unlock(&led_cdev_ind->led_access); 567 } 568 569 return ret; 570 } 571 572 static int v4l2_flash_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 573 { 574 struct v4l2_flash *v4l2_flash = v4l2_subdev_to_v4l2_flash(sd); 575 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev; 576 struct led_classdev *led_cdev = &fled_cdev->led_cdev; 577 struct led_classdev *led_cdev_ind = v4l2_flash->iled_cdev; 578 int ret = 0; 579 580 if (!v4l2_fh_is_singular(&fh->vfh)) 581 return 0; 582 583 mutex_lock(&led_cdev->led_access); 584 585 if (v4l2_flash->ctrls[STROBE_SOURCE]) 586 ret = v4l2_ctrl_s_ctrl(v4l2_flash->ctrls[STROBE_SOURCE], 587 V4L2_FLASH_STROBE_SOURCE_SOFTWARE); 588 led_sysfs_enable(led_cdev); 589 590 mutex_unlock(&led_cdev->led_access); 591 592 if (led_cdev_ind) { 593 mutex_lock(&led_cdev_ind->led_access); 594 led_sysfs_enable(led_cdev_ind); 595 mutex_unlock(&led_cdev_ind->led_access); 596 } 597 598 return ret; 599 } 600 601 static const struct v4l2_subdev_internal_ops v4l2_flash_subdev_internal_ops = { 602 .open = v4l2_flash_open, 603 .close = v4l2_flash_close, 604 }; 605 606 static const struct v4l2_subdev_ops v4l2_flash_subdev_ops; 607 608 struct v4l2_flash *v4l2_flash_init( 609 struct device *dev, struct fwnode_handle *fwn, 610 struct led_classdev_flash *fled_cdev, 611 struct led_classdev *iled_cdev, 612 const struct v4l2_flash_ops *ops, 613 struct v4l2_flash_config *config) 614 { 615 struct v4l2_flash *v4l2_flash; 616 struct led_classdev *led_cdev; 617 struct v4l2_subdev *sd; 618 int ret; 619 620 if (!fled_cdev || !config) 621 return ERR_PTR(-EINVAL); 622 623 led_cdev = &fled_cdev->led_cdev; 624 625 v4l2_flash = devm_kzalloc(led_cdev->dev, sizeof(*v4l2_flash), 626 GFP_KERNEL); 627 if (!v4l2_flash) 628 return ERR_PTR(-ENOMEM); 629 630 sd = &v4l2_flash->sd; 631 v4l2_flash->fled_cdev = fled_cdev; 632 v4l2_flash->iled_cdev = iled_cdev; 633 v4l2_flash->ops = ops; 634 sd->dev = dev; 635 sd->fwnode = fwn ? fwn : dev_fwnode(led_cdev->dev); 636 v4l2_subdev_init(sd, &v4l2_flash_subdev_ops); 637 sd->internal_ops = &v4l2_flash_subdev_internal_ops; 638 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 639 strlcpy(sd->name, config->dev_name, sizeof(sd->name)); 640 641 ret = media_entity_pads_init(&sd->entity, 0, NULL); 642 if (ret < 0) 643 return ERR_PTR(ret); 644 645 sd->entity.function = MEDIA_ENT_F_FLASH; 646 647 ret = v4l2_flash_init_controls(v4l2_flash, config); 648 if (ret < 0) 649 goto err_init_controls; 650 651 fwnode_handle_get(sd->fwnode); 652 653 ret = v4l2_async_register_subdev(sd); 654 if (ret < 0) 655 goto err_async_register_sd; 656 657 return v4l2_flash; 658 659 err_async_register_sd: 660 fwnode_handle_put(sd->fwnode); 661 v4l2_ctrl_handler_free(sd->ctrl_handler); 662 err_init_controls: 663 media_entity_cleanup(&sd->entity); 664 665 return ERR_PTR(ret); 666 } 667 EXPORT_SYMBOL_GPL(v4l2_flash_init); 668 669 void v4l2_flash_release(struct v4l2_flash *v4l2_flash) 670 { 671 struct v4l2_subdev *sd; 672 673 if (IS_ERR_OR_NULL(v4l2_flash)) 674 return; 675 676 sd = &v4l2_flash->sd; 677 678 v4l2_async_unregister_subdev(sd); 679 680 fwnode_handle_put(sd->fwnode); 681 682 v4l2_ctrl_handler_free(sd->ctrl_handler); 683 media_entity_cleanup(&sd->entity); 684 } 685 EXPORT_SYMBOL_GPL(v4l2_flash_release); 686 687 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>"); 688 MODULE_DESCRIPTION("V4L2 Flash sub-device helpers"); 689 MODULE_LICENSE("GPL v2"); 690