root/drivers/media/v4l2-core/v4l2-flash-led-class.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __intensity_to_led_brightness
  2. __led_brightness_to_intensity
  3. v4l2_flash_set_led_brightness
  4. v4l2_flash_update_led_brightness
  5. v4l2_flash_g_volatile_ctrl
  6. __software_strobe_mode_inactive
  7. v4l2_flash_s_ctrl
  8. __lfs_to_v4l2_ctrl_config
  9. __fill_ctrl_init_data
  10. v4l2_flash_init_controls
  11. __sync_device_with_v4l2_controls
  12. v4l2_flash_open
  13. v4l2_flash_close
  14. __v4l2_flash_init
  15. v4l2_flash_init
  16. v4l2_flash_indicator_init
  17. v4l2_flash_release

   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 void 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         enum led_brightness brightness;
  84 
  85         if (has_flash_op(v4l2_flash, intensity_to_led_brightness))
  86                 brightness = call_flash_op(v4l2_flash,
  87                                         intensity_to_led_brightness,
  88                                         ctrl->val);
  89         else
  90                 brightness = __intensity_to_led_brightness(ctrl, ctrl->val);
  91         /*
  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.
  97          */
  98         if (has_flash_op(v4l2_flash, led_brightness_to_intensity))
  99                 ctrl->val = call_flash_op(v4l2_flash,
 100                                         led_brightness_to_intensity,
 101                                         brightness);
 102 
 103         if (ctrl == ctrls[TORCH_INTENSITY]) {
 104                 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
 105                         return;
 106 
 107                 led_set_brightness_sync(&v4l2_flash->fled_cdev->led_cdev,
 108                                         brightness);
 109         } else {
 110                 led_set_brightness_sync(v4l2_flash->iled_cdev,
 111                                         brightness);
 112         }
 113 }
 114 
 115 static int v4l2_flash_update_led_brightness(struct v4l2_flash *v4l2_flash,
 116                                         struct v4l2_ctrl *ctrl)
 117 {
 118         struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
 119         struct led_classdev *led_cdev;
 120         int ret;
 121 
 122         if (ctrl == ctrls[TORCH_INTENSITY]) {
 123                 /*
 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
 127                  * has changed to 0.
 128                  */
 129                 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
 130                         return 0;
 131                 led_cdev = &v4l2_flash->fled_cdev->led_cdev;
 132         } else {
 133                 led_cdev = v4l2_flash->iled_cdev;
 134         }
 135 
 136         ret = led_update_brightness(led_cdev);
 137         if (ret < 0)
 138                 return ret;
 139 
 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);
 144         else
 145                 ctrl->val = __led_brightness_to_intensity(ctrl,
 146                                                 led_cdev->brightness);
 147 
 148         return 0;
 149 }
 150 
 151 static int v4l2_flash_g_volatile_ctrl(struct v4l2_ctrl *c)
 152 {
 153         struct v4l2_flash *v4l2_flash = v4l2_ctrl_to_v4l2_flash(c);
 154         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
 155         bool is_strobing;
 156         int ret;
 157 
 158         switch (c->id) {
 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);
 164                 if (ret < 0)
 165                         return ret;
 166                 /*
 167                  * No conversion is needed as LED Flash class also uses
 168                  * microamperes for flash intensity units.
 169                  */
 170                 c->val = fled_cdev->brightness.val;
 171                 return 0;
 172         case V4L2_CID_FLASH_STROBE_STATUS:
 173                 ret = led_get_flash_strobe(fled_cdev, &is_strobing);
 174                 if (ret < 0)
 175                         return ret;
 176                 c->val = is_strobing;
 177                 return 0;
 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);
 181         default:
 182                 return -EINVAL;
 183         }
 184 }
 185 
 186 static bool __software_strobe_mode_inactive(struct v4l2_ctrl **ctrls)
 187 {
 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)));
 191 }
 192 
 193 static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
 194 {
 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;
 200         int ret = 0;
 201 
 202         switch (c->id) {
 203         case V4L2_CID_FLASH_LED_MODE:
 204                 switch (c->val) {
 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);
 214 
 215                                 ret = call_flash_op(v4l2_flash,
 216                                                 external_strobe_set,
 217                                                 external_strobe);
 218                         }
 219                         return ret;
 220                 case V4L2_FLASH_LED_MODE_TORCH:
 221                         if (ctrls[STROBE_SOURCE]) {
 222                                 ret = call_flash_op(v4l2_flash,
 223                                                 external_strobe_set,
 224                                                 false);
 225                                 if (ret < 0)
 226                                         return ret;
 227                         }
 228                         /* Stop flash strobing */
 229                         ret = led_set_flash_strobe(fled_cdev, false);
 230                         if (ret < 0)
 231                                 return ret;
 232 
 233                         v4l2_flash_set_led_brightness(v4l2_flash,
 234                                                         ctrls[TORCH_INTENSITY]);
 235                         return 0;
 236                 }
 237                 break;
 238         case V4L2_CID_FLASH_STROBE_SOURCE:
 239                 external_strobe = (c->val == V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
 240                 /*
 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
 244                  * to flash mode.
 245                  */
 246                 if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_FLASH)
 247                         return 0;
 248 
 249                 return call_flash_op(v4l2_flash, external_strobe_set,
 250                                         external_strobe);
 251         case V4L2_CID_FLASH_STROBE:
 252                 if (__software_strobe_mode_inactive(ctrls))
 253                         return -EBUSY;
 254                 return led_set_flash_strobe(fled_cdev, true);
 255         case V4L2_CID_FLASH_STROBE_STOP:
 256                 if (__software_strobe_mode_inactive(ctrls))
 257                         return -EBUSY;
 258                 return led_set_flash_strobe(fled_cdev, false);
 259         case V4L2_CID_FLASH_TIMEOUT:
 260                 /*
 261                  * No conversion is needed as LED Flash class also uses
 262                  * microseconds for flash timeout units.
 263                  */
 264                 return led_set_flash_timeout(fled_cdev, c->val);
 265         case V4L2_CID_FLASH_INTENSITY:
 266                 /*
 267                  * No conversion is needed as LED Flash class also uses
 268                  * microamperes for flash intensity units.
 269                  */
 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);
 274                 return 0;
 275         }
 276 
 277         return -EINVAL;
 278 }
 279 
 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,
 283 };
 284 
 285 static void __lfs_to_v4l2_ctrl_config(struct led_flash_setting *s,
 286                                 struct v4l2_ctrl_config *c)
 287 {
 288         c->min = s->min;
 289         c->max = s->max;
 290         c->step = s->step;
 291         c->def = s->val;
 292 }
 293 
 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)
 297 {
 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;
 301         u32 mask;
 302 
 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,
 309                                           ctrl_cfg);
 310                 ctrl_cfg->id = V4L2_CID_FLASH_INDICATOR_INTENSITY;
 311                 ctrl_cfg->min = 0;
 312                 ctrl_cfg->flags = V4L2_CTRL_FLAG_VOLATILE |
 313                                   V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
 314         }
 315 
 316         if (!led_cdev || WARN_ON(!(led_cdev->flags & LED_DEV_CAP_FLASH)))
 317                 return;
 318 
 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;
 327         }
 328 
 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;
 334 
 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;
 341         ctrl_cfg->flags = 0;
 342 
 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;
 350 
 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;
 355 
 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;
 360 
 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;
 372         }
 373 
 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;
 382         }
 383 
 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;
 390         }
 391 
 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;
 400         }
 401 }
 402 
 403 static int v4l2_flash_init_controls(struct v4l2_flash *v4l2_flash,
 404                                 struct v4l2_flash_config *flash_cfg)
 405 
 406 {
 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;
 411 
 412         v4l2_flash->ctrls = devm_kcalloc(v4l2_flash->sd.dev,
 413                                         STROBE_SOURCE + 1,
 414                                         sizeof(*v4l2_flash->ctrls),
 415                                         GFP_KERNEL);
 416         if (!v4l2_flash->ctrls)
 417                 return -ENOMEM;
 418 
 419         /* allocate memory dynamically so as not to exceed stack frame size */
 420         ctrl_init_data = kcalloc(NUM_FLASH_CTRLS, sizeof(*ctrl_init_data),
 421                                         GFP_KERNEL);
 422         if (!ctrl_init_data)
 423                 return -ENOMEM;
 424 
 425         __fill_ctrl_init_data(v4l2_flash, flash_cfg, ctrl_init_data);
 426 
 427         for (i = 0; i < NUM_FLASH_CTRLS; ++i)
 428                 if (ctrl_init_data[i].cid)
 429                         ++num_ctrls;
 430 
 431         v4l2_ctrl_handler_init(&v4l2_flash->hdl, num_ctrls);
 432 
 433         for (i = 0; i < NUM_FLASH_CTRLS; ++i) {
 434                 ctrl_cfg = &ctrl_init_data[i].config;
 435                 if (!ctrl_init_data[i].cid)
 436                         continue;
 437 
 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,
 442                                                 ctrl_cfg->id,
 443                                                 ctrl_cfg->max,
 444                                                 ctrl_cfg->menu_skip_mask,
 445                                                 ctrl_cfg->def);
 446                 else
 447                         ctrl = v4l2_ctrl_new_std(&v4l2_flash->hdl,
 448                                                 &v4l2_flash_ctrl_ops,
 449                                                 ctrl_cfg->id,
 450                                                 ctrl_cfg->min,
 451                                                 ctrl_cfg->max,
 452                                                 ctrl_cfg->step,
 453                                                 ctrl_cfg->def);
 454 
 455                 if (ctrl)
 456                         ctrl->flags |= ctrl_cfg->flags;
 457 
 458                 if (i <= STROBE_SOURCE)
 459                         v4l2_flash->ctrls[i] = ctrl;
 460         }
 461 
 462         kfree(ctrl_init_data);
 463 
 464         if (v4l2_flash->hdl.error) {
 465                 ret = v4l2_flash->hdl.error;
 466                 goto error_free_handler;
 467         }
 468 
 469         v4l2_ctrl_handler_setup(&v4l2_flash->hdl);
 470 
 471         v4l2_flash->sd.ctrl_handler = &v4l2_flash->hdl;
 472 
 473         return 0;
 474 
 475 error_free_handler:
 476         v4l2_ctrl_handler_free(&v4l2_flash->hdl);
 477         return ret;
 478 }
 479 
 480 static int __sync_device_with_v4l2_controls(struct v4l2_flash *v4l2_flash)
 481 {
 482         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
 483         struct v4l2_ctrl **ctrls = v4l2_flash->ctrls;
 484         int ret = 0;
 485 
 486         if (ctrls[TORCH_INTENSITY])
 487                 v4l2_flash_set_led_brightness(v4l2_flash,
 488                                               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 ? &fled_cdev->led_cdev : NULL;
 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         if (led_cdev) {
 538                 mutex_lock(&led_cdev->led_access);
 539 
 540                 led_sysfs_disable(led_cdev);
 541                 led_trigger_remove(led_cdev);
 542 
 543                 mutex_unlock(&led_cdev->led_access);
 544         }
 545 
 546         if (led_cdev_ind) {
 547                 mutex_lock(&led_cdev_ind->led_access);
 548 
 549                 led_sysfs_disable(led_cdev_ind);
 550                 led_trigger_remove(led_cdev_ind);
 551 
 552                 mutex_unlock(&led_cdev_ind->led_access);
 553         }
 554 
 555         ret = __sync_device_with_v4l2_controls(v4l2_flash);
 556         if (ret < 0)
 557                 goto out_sync_device;
 558 
 559         return 0;
 560 out_sync_device:
 561         if (led_cdev) {
 562                 mutex_lock(&led_cdev->led_access);
 563                 led_sysfs_enable(led_cdev);
 564                 mutex_unlock(&led_cdev->led_access);
 565         }
 566 
 567         if (led_cdev_ind) {
 568                 mutex_lock(&led_cdev_ind->led_access);
 569                 led_sysfs_enable(led_cdev_ind);
 570                 mutex_unlock(&led_cdev_ind->led_access);
 571         }
 572 
 573         return ret;
 574 }
 575 
 576 static int v4l2_flash_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 577 {
 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;
 582         int ret = 0;
 583 
 584         if (!v4l2_fh_is_singular(&fh->vfh))
 585                 return 0;
 586 
 587         if (led_cdev) {
 588                 mutex_lock(&led_cdev->led_access);
 589 
 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);
 595 
 596                 mutex_unlock(&led_cdev->led_access);
 597         }
 598 
 599         if (led_cdev_ind) {
 600                 mutex_lock(&led_cdev_ind->led_access);
 601                 led_sysfs_enable(led_cdev_ind);
 602                 mutex_unlock(&led_cdev_ind->led_access);
 603         }
 604 
 605         return ret;
 606 }
 607 
 608 static const struct v4l2_subdev_internal_ops v4l2_flash_subdev_internal_ops = {
 609         .open = v4l2_flash_open,
 610         .close = v4l2_flash_close,
 611 };
 612 
 613 static const struct v4l2_subdev_ops v4l2_flash_subdev_ops;
 614 
 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)
 619 {
 620         struct v4l2_flash *v4l2_flash;
 621         struct v4l2_subdev *sd;
 622         int ret;
 623 
 624         if (!config)
 625                 return ERR_PTR(-EINVAL);
 626 
 627         v4l2_flash = devm_kzalloc(dev, sizeof(*v4l2_flash), GFP_KERNEL);
 628         if (!v4l2_flash)
 629                 return ERR_PTR(-ENOMEM);
 630 
 631         sd = &v4l2_flash->sd;
 632         v4l2_flash->fled_cdev = fled_cdev;
 633         v4l2_flash->iled_cdev = iled_cdev;
 634         v4l2_flash->ops = ops;
 635         sd->dev = dev;
 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));
 641 
 642         ret = media_entity_pads_init(&sd->entity, 0, NULL);
 643         if (ret < 0)
 644                 return ERR_PTR(ret);
 645 
 646         sd->entity.function = MEDIA_ENT_F_FLASH;
 647 
 648         ret = v4l2_flash_init_controls(v4l2_flash, config);
 649         if (ret < 0)
 650                 goto err_init_controls;
 651 
 652         fwnode_handle_get(sd->fwnode);
 653 
 654         ret = v4l2_async_register_subdev(sd);
 655         if (ret < 0)
 656                 goto err_async_register_sd;
 657 
 658         return v4l2_flash;
 659 
 660 err_async_register_sd:
 661         fwnode_handle_put(sd->fwnode);
 662         v4l2_ctrl_handler_free(sd->ctrl_handler);
 663 err_init_controls:
 664         media_entity_cleanup(&sd->entity);
 665 
 666         return ERR_PTR(ret);
 667 }
 668 
 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)
 674 {
 675         return __v4l2_flash_init(dev, fwn, fled_cdev, NULL, ops, config);
 676 }
 677 EXPORT_SYMBOL_GPL(v4l2_flash_init);
 678 
 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)
 683 {
 684         return __v4l2_flash_init(dev, fwn, NULL, iled_cdev, NULL, config);
 685 }
 686 EXPORT_SYMBOL_GPL(v4l2_flash_indicator_init);
 687 
 688 void v4l2_flash_release(struct v4l2_flash *v4l2_flash)
 689 {
 690         struct v4l2_subdev *sd;
 691 
 692         if (IS_ERR_OR_NULL(v4l2_flash))
 693                 return;
 694 
 695         sd = &v4l2_flash->sd;
 696 
 697         v4l2_async_unregister_subdev(sd);
 698 
 699         fwnode_handle_put(sd->fwnode);
 700 
 701         v4l2_ctrl_handler_free(sd->ctrl_handler);
 702         media_entity_cleanup(&sd->entity);
 703 }
 704 EXPORT_SYMBOL_GPL(v4l2_flash_release);
 705 
 706 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
 707 MODULE_DESCRIPTION("V4L2 Flash sub-device helpers");
 708 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */