linux/drivers/media/i2c/adp1653.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * drivers/media/i2c/adp1653.c
   4 *
   5 * Copyright (C) 2008--2011 Nokia Corporation
   6 *
   7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
   8 *
   9 * Contributors:
  10 *      Sakari Ailus <sakari.ailus@iki.fi>
  11 *      Tuukka Toivonen <tuukkat76@gmail.com>
  12 *      Pavel Machek <pavel@ucw.cz>
  13 *
  14 * TODO:
  15 * - fault interrupt handling
  16 * - hardware strobe
  17 * - power doesn't need to be ON if all lights are off
  18 */
  19
  20#include <linux/delay.h>
  21#include <linux/module.h>
  22#include <linux/i2c.h>
  23#include <linux/slab.h>
  24#include <linux/of.h>
  25#include <linux/gpio/consumer.h>
  26#include <media/i2c/adp1653.h>
  27#include <media/v4l2-device.h>
  28
  29#define TIMEOUT_MAX             820000
  30#define TIMEOUT_STEP            54600
  31#define TIMEOUT_MIN             (TIMEOUT_MAX - ADP1653_REG_CONFIG_TMR_SET_MAX \
  32                                 * TIMEOUT_STEP)
  33#define TIMEOUT_US_TO_CODE(t)   ((TIMEOUT_MAX + (TIMEOUT_STEP / 2) - (t)) \
  34                                 / TIMEOUT_STEP)
  35#define TIMEOUT_CODE_TO_US(c)   (TIMEOUT_MAX - (c) * TIMEOUT_STEP)
  36
  37/* Write values into ADP1653 registers. */
  38static int adp1653_update_hw(struct adp1653_flash *flash)
  39{
  40        struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
  41        u8 out_sel;
  42        u8 config = 0;
  43        int rval;
  44
  45        out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
  46                flash->indicator_intensity->val)
  47                << ADP1653_REG_OUT_SEL_ILED_SHIFT;
  48
  49        switch (flash->led_mode->val) {
  50        case V4L2_FLASH_LED_MODE_NONE:
  51                break;
  52        case V4L2_FLASH_LED_MODE_FLASH:
  53                /* Flash mode, light on with strobe, duration from timer */
  54                config = ADP1653_REG_CONFIG_TMR_CFG;
  55                config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
  56                          << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
  57                break;
  58        case V4L2_FLASH_LED_MODE_TORCH:
  59                /* Torch mode, light immediately on, duration indefinite */
  60                out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
  61                        flash->torch_intensity->val)
  62                        << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
  63                break;
  64        }
  65
  66        rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
  67        if (rval < 0)
  68                return rval;
  69
  70        rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
  71        if (rval < 0)
  72                return rval;
  73
  74        return 0;
  75}
  76
  77static int adp1653_get_fault(struct adp1653_flash *flash)
  78{
  79        struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
  80        int fault;
  81        int rval;
  82
  83        fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
  84        if (fault < 0)
  85                return fault;
  86
  87        flash->fault |= fault;
  88
  89        if (!flash->fault)
  90                return 0;
  91
  92        /* Clear faults. */
  93        rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
  94        if (rval < 0)
  95                return rval;
  96
  97        flash->led_mode->val = V4L2_FLASH_LED_MODE_NONE;
  98
  99        rval = adp1653_update_hw(flash);
 100        if (rval)
 101                return rval;
 102
 103        return flash->fault;
 104}
 105
 106static int adp1653_strobe(struct adp1653_flash *flash, int enable)
 107{
 108        struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
 109        u8 out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
 110                flash->indicator_intensity->val)
 111                << ADP1653_REG_OUT_SEL_ILED_SHIFT;
 112        int rval;
 113
 114        if (flash->led_mode->val != V4L2_FLASH_LED_MODE_FLASH)
 115                return -EBUSY;
 116
 117        if (!enable)
 118                return i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL,
 119                                                 out_sel);
 120
 121        out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
 122                flash->flash_intensity->val)
 123                << ADP1653_REG_OUT_SEL_HPLED_SHIFT;
 124        rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
 125        if (rval)
 126                return rval;
 127
 128        /* Software strobe using i2c */
 129        rval = i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE,
 130                ADP1653_REG_SW_STROBE_SW_STROBE);
 131        if (rval)
 132                return rval;
 133        return i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE, 0);
 134}
 135
 136/* --------------------------------------------------------------------------
 137 * V4L2 controls
 138 */
 139
 140static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
 141{
 142        struct adp1653_flash *flash =
 143                container_of(ctrl->handler, struct adp1653_flash, ctrls);
 144        int rval;
 145
 146        rval = adp1653_get_fault(flash);
 147        if (rval)
 148                return rval;
 149
 150        ctrl->cur.val = 0;
 151
 152        if (flash->fault & ADP1653_REG_FAULT_FLT_SCP)
 153                ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
 154        if (flash->fault & ADP1653_REG_FAULT_FLT_OT)
 155                ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
 156        if (flash->fault & ADP1653_REG_FAULT_FLT_TMR)
 157                ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
 158        if (flash->fault & ADP1653_REG_FAULT_FLT_OV)
 159                ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
 160
 161        flash->fault = 0;
 162
 163        return 0;
 164}
 165
 166static int adp1653_set_ctrl(struct v4l2_ctrl *ctrl)
 167{
 168        struct adp1653_flash *flash =
 169                container_of(ctrl->handler, struct adp1653_flash, ctrls);
 170        int rval;
 171
 172        rval = adp1653_get_fault(flash);
 173        if (rval)
 174                return rval;
 175        if ((rval & (ADP1653_REG_FAULT_FLT_SCP |
 176                     ADP1653_REG_FAULT_FLT_OT |
 177                     ADP1653_REG_FAULT_FLT_OV)) &&
 178            (ctrl->id == V4L2_CID_FLASH_STROBE ||
 179             ctrl->id == V4L2_CID_FLASH_TORCH_INTENSITY ||
 180             ctrl->id == V4L2_CID_FLASH_LED_MODE))
 181                return -EBUSY;
 182
 183        switch (ctrl->id) {
 184        case V4L2_CID_FLASH_STROBE:
 185                return adp1653_strobe(flash, 1);
 186        case V4L2_CID_FLASH_STROBE_STOP:
 187                return adp1653_strobe(flash, 0);
 188        }
 189
 190        return adp1653_update_hw(flash);
 191}
 192
 193static const struct v4l2_ctrl_ops adp1653_ctrl_ops = {
 194        .g_volatile_ctrl = adp1653_get_ctrl,
 195        .s_ctrl = adp1653_set_ctrl,
 196};
 197
 198static int adp1653_init_controls(struct adp1653_flash *flash)
 199{
 200        struct v4l2_ctrl *fault;
 201
 202        v4l2_ctrl_handler_init(&flash->ctrls, 9);
 203
 204        flash->led_mode =
 205                v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
 206                                       V4L2_CID_FLASH_LED_MODE,
 207                                       V4L2_FLASH_LED_MODE_TORCH, ~0x7, 0);
 208        v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
 209                               V4L2_CID_FLASH_STROBE_SOURCE,
 210                               V4L2_FLASH_STROBE_SOURCE_SOFTWARE, ~0x1, 0);
 211        v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
 212                          V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
 213        v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
 214                          V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
 215        flash->flash_timeout =
 216                v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
 217                                  V4L2_CID_FLASH_TIMEOUT, TIMEOUT_MIN,
 218                                  flash->platform_data->max_flash_timeout,
 219                                  TIMEOUT_STEP,
 220                                  flash->platform_data->max_flash_timeout);
 221        flash->flash_intensity =
 222                v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
 223                                  V4L2_CID_FLASH_INTENSITY,
 224                                  ADP1653_FLASH_INTENSITY_MIN,
 225                                  flash->platform_data->max_flash_intensity,
 226                                  1, flash->platform_data->max_flash_intensity);
 227        flash->torch_intensity =
 228                v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
 229                                  V4L2_CID_FLASH_TORCH_INTENSITY,
 230                                  ADP1653_TORCH_INTENSITY_MIN,
 231                                  flash->platform_data->max_torch_intensity,
 232                                  ADP1653_FLASH_INTENSITY_STEP,
 233                                  flash->platform_data->max_torch_intensity);
 234        flash->indicator_intensity =
 235                v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
 236                                  V4L2_CID_FLASH_INDICATOR_INTENSITY,
 237                                  ADP1653_INDICATOR_INTENSITY_MIN,
 238                                  flash->platform_data->max_indicator_intensity,
 239                                  ADP1653_INDICATOR_INTENSITY_STEP,
 240                                  ADP1653_INDICATOR_INTENSITY_MIN);
 241        fault = v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
 242                                  V4L2_CID_FLASH_FAULT, 0,
 243                                  V4L2_FLASH_FAULT_OVER_VOLTAGE
 244                                  | V4L2_FLASH_FAULT_OVER_TEMPERATURE
 245                                  | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
 246
 247        if (flash->ctrls.error)
 248                return flash->ctrls.error;
 249
 250        fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
 251
 252        flash->subdev.ctrl_handler = &flash->ctrls;
 253        return 0;
 254}
 255
 256/* --------------------------------------------------------------------------
 257 * V4L2 subdev operations
 258 */
 259
 260static int
 261adp1653_init_device(struct adp1653_flash *flash)
 262{
 263        struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
 264        int rval;
 265
 266        /* Clear FAULT register by writing zero to OUT_SEL */
 267        rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
 268        if (rval < 0) {
 269                dev_err(&client->dev, "failed writing fault register\n");
 270                return -EIO;
 271        }
 272
 273        mutex_lock(flash->ctrls.lock);
 274        /* Reset faults before reading new ones. */
 275        flash->fault = 0;
 276        rval = adp1653_get_fault(flash);
 277        mutex_unlock(flash->ctrls.lock);
 278        if (rval > 0) {
 279                dev_err(&client->dev, "faults detected: 0x%1.1x\n", rval);
 280                return -EIO;
 281        }
 282
 283        mutex_lock(flash->ctrls.lock);
 284        rval = adp1653_update_hw(flash);
 285        mutex_unlock(flash->ctrls.lock);
 286        if (rval) {
 287                dev_err(&client->dev,
 288                        "adp1653_update_hw failed at %s\n", __func__);
 289                return -EIO;
 290        }
 291
 292        return 0;
 293}
 294
 295static int
 296__adp1653_set_power(struct adp1653_flash *flash, int on)
 297{
 298        int ret;
 299
 300        if (flash->platform_data->power) {
 301                ret = flash->platform_data->power(&flash->subdev, on);
 302                if (ret < 0)
 303                        return ret;
 304        } else {
 305                gpiod_set_value(flash->platform_data->enable_gpio, on);
 306                if (on)
 307                        /* Some delay is apparently required. */
 308                        udelay(20);
 309        }
 310
 311        if (!on)
 312                return 0;
 313
 314        ret = adp1653_init_device(flash);
 315        if (ret >= 0)
 316                return ret;
 317
 318        if (flash->platform_data->power)
 319                flash->platform_data->power(&flash->subdev, 0);
 320        else
 321                gpiod_set_value(flash->platform_data->enable_gpio, 0);
 322
 323        return ret;
 324}
 325
 326static int
 327adp1653_set_power(struct v4l2_subdev *subdev, int on)
 328{
 329        struct adp1653_flash *flash = to_adp1653_flash(subdev);
 330        int ret = 0;
 331
 332        mutex_lock(&flash->power_lock);
 333
 334        /* If the power count is modified from 0 to != 0 or from != 0 to 0,
 335         * update the power state.
 336         */
 337        if (flash->power_count == !on) {
 338                ret = __adp1653_set_power(flash, !!on);
 339                if (ret < 0)
 340                        goto done;
 341        }
 342
 343        /* Update the power count. */
 344        flash->power_count += on ? 1 : -1;
 345        WARN_ON(flash->power_count < 0);
 346
 347done:
 348        mutex_unlock(&flash->power_lock);
 349        return ret;
 350}
 351
 352static int adp1653_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 353{
 354        return adp1653_set_power(sd, 1);
 355}
 356
 357static int adp1653_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 358{
 359        return adp1653_set_power(sd, 0);
 360}
 361
 362static const struct v4l2_subdev_core_ops adp1653_core_ops = {
 363        .s_power = adp1653_set_power,
 364};
 365
 366static const struct v4l2_subdev_ops adp1653_ops = {
 367        .core = &adp1653_core_ops,
 368};
 369
 370static const struct v4l2_subdev_internal_ops adp1653_internal_ops = {
 371        .open = adp1653_open,
 372        .close = adp1653_close,
 373};
 374
 375/* --------------------------------------------------------------------------
 376 * I2C driver
 377 */
 378#ifdef CONFIG_PM
 379
 380static int adp1653_suspend(struct device *dev)
 381{
 382        struct i2c_client *client = to_i2c_client(dev);
 383        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 384        struct adp1653_flash *flash = to_adp1653_flash(subdev);
 385
 386        if (!flash->power_count)
 387                return 0;
 388
 389        return __adp1653_set_power(flash, 0);
 390}
 391
 392static int adp1653_resume(struct device *dev)
 393{
 394        struct i2c_client *client = to_i2c_client(dev);
 395        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 396        struct adp1653_flash *flash = to_adp1653_flash(subdev);
 397
 398        if (!flash->power_count)
 399                return 0;
 400
 401        return __adp1653_set_power(flash, 1);
 402}
 403
 404#else
 405
 406#define adp1653_suspend NULL
 407#define adp1653_resume  NULL
 408
 409#endif /* CONFIG_PM */
 410
 411static int adp1653_of_init(struct i2c_client *client,
 412                           struct adp1653_flash *flash,
 413                           struct device_node *node)
 414{
 415        struct adp1653_platform_data *pd;
 416        struct device_node *child;
 417
 418        pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL);
 419        if (!pd)
 420                return -ENOMEM;
 421        flash->platform_data = pd;
 422
 423        child = of_get_child_by_name(node, "flash");
 424        if (!child)
 425                return -EINVAL;
 426
 427        if (of_property_read_u32(child, "flash-timeout-us",
 428                                 &pd->max_flash_timeout))
 429                goto err;
 430
 431        if (of_property_read_u32(child, "flash-max-microamp",
 432                                 &pd->max_flash_intensity))
 433                goto err;
 434
 435        pd->max_flash_intensity /= 1000;
 436
 437        if (of_property_read_u32(child, "led-max-microamp",
 438                                 &pd->max_torch_intensity))
 439                goto err;
 440
 441        pd->max_torch_intensity /= 1000;
 442        of_node_put(child);
 443
 444        child = of_get_child_by_name(node, "indicator");
 445        if (!child)
 446                return -EINVAL;
 447
 448        if (of_property_read_u32(child, "led-max-microamp",
 449                                 &pd->max_indicator_intensity))
 450                goto err;
 451
 452        of_node_put(child);
 453
 454        pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW);
 455        if (IS_ERR(pd->enable_gpio)) {
 456                dev_err(&client->dev, "Error getting GPIO\n");
 457                return PTR_ERR(pd->enable_gpio);
 458        }
 459
 460        return 0;
 461err:
 462        dev_err(&client->dev, "Required property not found\n");
 463        of_node_put(child);
 464        return -EINVAL;
 465}
 466
 467
 468static int adp1653_probe(struct i2c_client *client,
 469                         const struct i2c_device_id *devid)
 470{
 471        struct adp1653_flash *flash;
 472        int ret;
 473
 474        flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
 475        if (flash == NULL)
 476                return -ENOMEM;
 477
 478        if (client->dev.of_node) {
 479                ret = adp1653_of_init(client, flash, client->dev.of_node);
 480                if (ret)
 481                        return ret;
 482        } else {
 483                if (!client->dev.platform_data) {
 484                        dev_err(&client->dev,
 485                                "Neither DT not platform data provided\n");
 486                        return -EINVAL;
 487                }
 488                flash->platform_data = client->dev.platform_data;
 489        }
 490
 491        mutex_init(&flash->power_lock);
 492
 493        v4l2_i2c_subdev_init(&flash->subdev, client, &adp1653_ops);
 494        flash->subdev.internal_ops = &adp1653_internal_ops;
 495        flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 496
 497        ret = adp1653_init_controls(flash);
 498        if (ret)
 499                goto free_and_quit;
 500
 501        ret = media_entity_pads_init(&flash->subdev.entity, 0, NULL);
 502        if (ret < 0)
 503                goto free_and_quit;
 504
 505        flash->subdev.entity.function = MEDIA_ENT_F_FLASH;
 506
 507        return 0;
 508
 509free_and_quit:
 510        dev_err(&client->dev, "adp1653: failed to register device\n");
 511        v4l2_ctrl_handler_free(&flash->ctrls);
 512        return ret;
 513}
 514
 515static int adp1653_remove(struct i2c_client *client)
 516{
 517        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 518        struct adp1653_flash *flash = to_adp1653_flash(subdev);
 519
 520        v4l2_device_unregister_subdev(&flash->subdev);
 521        v4l2_ctrl_handler_free(&flash->ctrls);
 522        media_entity_cleanup(&flash->subdev.entity);
 523
 524        return 0;
 525}
 526
 527static const struct i2c_device_id adp1653_id_table[] = {
 528        { ADP1653_NAME, 0 },
 529        { }
 530};
 531MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
 532
 533static const struct dev_pm_ops adp1653_pm_ops = {
 534        .suspend        = adp1653_suspend,
 535        .resume         = adp1653_resume,
 536};
 537
 538static struct i2c_driver adp1653_i2c_driver = {
 539        .driver         = {
 540                .name   = ADP1653_NAME,
 541                .pm     = &adp1653_pm_ops,
 542        },
 543        .probe          = adp1653_probe,
 544        .remove         = adp1653_remove,
 545        .id_table       = adp1653_id_table,
 546};
 547
 548module_i2c_driver(adp1653_i2c_driver);
 549
 550MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
 551MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver");
 552MODULE_LICENSE("GPL");
 553