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 v4l2_subdev *subdev = dev_get_drvdata(dev);
 383        struct adp1653_flash *flash = to_adp1653_flash(subdev);
 384
 385        if (!flash->power_count)
 386                return 0;
 387
 388        return __adp1653_set_power(flash, 0);
 389}
 390
 391static int adp1653_resume(struct device *dev)
 392{
 393        struct v4l2_subdev *subdev = dev_get_drvdata(dev);
 394        struct adp1653_flash *flash = to_adp1653_flash(subdev);
 395
 396        if (!flash->power_count)
 397                return 0;
 398
 399        return __adp1653_set_power(flash, 1);
 400}
 401
 402#else
 403
 404#define adp1653_suspend NULL
 405#define adp1653_resume  NULL
 406
 407#endif /* CONFIG_PM */
 408
 409static int adp1653_of_init(struct i2c_client *client,
 410                           struct adp1653_flash *flash,
 411                           struct device_node *node)
 412{
 413        struct adp1653_platform_data *pd;
 414        struct device_node *child;
 415
 416        pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL);
 417        if (!pd)
 418                return -ENOMEM;
 419        flash->platform_data = pd;
 420
 421        child = of_get_child_by_name(node, "flash");
 422        if (!child)
 423                return -EINVAL;
 424
 425        if (of_property_read_u32(child, "flash-timeout-us",
 426                                 &pd->max_flash_timeout))
 427                goto err;
 428
 429        if (of_property_read_u32(child, "flash-max-microamp",
 430                                 &pd->max_flash_intensity))
 431                goto err;
 432
 433        pd->max_flash_intensity /= 1000;
 434
 435        if (of_property_read_u32(child, "led-max-microamp",
 436                                 &pd->max_torch_intensity))
 437                goto err;
 438
 439        pd->max_torch_intensity /= 1000;
 440        of_node_put(child);
 441
 442        child = of_get_child_by_name(node, "indicator");
 443        if (!child)
 444                return -EINVAL;
 445
 446        if (of_property_read_u32(child, "led-max-microamp",
 447                                 &pd->max_indicator_intensity))
 448                goto err;
 449
 450        of_node_put(child);
 451
 452        pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW);
 453        if (IS_ERR(pd->enable_gpio)) {
 454                dev_err(&client->dev, "Error getting GPIO\n");
 455                return PTR_ERR(pd->enable_gpio);
 456        }
 457
 458        return 0;
 459err:
 460        dev_err(&client->dev, "Required property not found\n");
 461        of_node_put(child);
 462        return -EINVAL;
 463}
 464
 465
 466static int adp1653_probe(struct i2c_client *client,
 467                         const struct i2c_device_id *devid)
 468{
 469        struct adp1653_flash *flash;
 470        int ret;
 471
 472        flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
 473        if (flash == NULL)
 474                return -ENOMEM;
 475
 476        if (client->dev.of_node) {
 477                ret = adp1653_of_init(client, flash, client->dev.of_node);
 478                if (ret)
 479                        return ret;
 480        } else {
 481                if (!client->dev.platform_data) {
 482                        dev_err(&client->dev,
 483                                "Neither DT not platform data provided\n");
 484                        return -EINVAL;
 485                }
 486                flash->platform_data = client->dev.platform_data;
 487        }
 488
 489        mutex_init(&flash->power_lock);
 490
 491        v4l2_i2c_subdev_init(&flash->subdev, client, &adp1653_ops);
 492        flash->subdev.internal_ops = &adp1653_internal_ops;
 493        flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 494
 495        ret = adp1653_init_controls(flash);
 496        if (ret)
 497                goto free_and_quit;
 498
 499        ret = media_entity_pads_init(&flash->subdev.entity, 0, NULL);
 500        if (ret < 0)
 501                goto free_and_quit;
 502
 503        flash->subdev.entity.function = MEDIA_ENT_F_FLASH;
 504
 505        return 0;
 506
 507free_and_quit:
 508        dev_err(&client->dev, "adp1653: failed to register device\n");
 509        v4l2_ctrl_handler_free(&flash->ctrls);
 510        return ret;
 511}
 512
 513static int adp1653_remove(struct i2c_client *client)
 514{
 515        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 516        struct adp1653_flash *flash = to_adp1653_flash(subdev);
 517
 518        v4l2_device_unregister_subdev(&flash->subdev);
 519        v4l2_ctrl_handler_free(&flash->ctrls);
 520        media_entity_cleanup(&flash->subdev.entity);
 521
 522        return 0;
 523}
 524
 525static const struct i2c_device_id adp1653_id_table[] = {
 526        { ADP1653_NAME, 0 },
 527        { }
 528};
 529MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
 530
 531static const struct dev_pm_ops adp1653_pm_ops = {
 532        .suspend        = adp1653_suspend,
 533        .resume         = adp1653_resume,
 534};
 535
 536static struct i2c_driver adp1653_i2c_driver = {
 537        .driver         = {
 538                .name   = ADP1653_NAME,
 539                .pm     = &adp1653_pm_ops,
 540        },
 541        .probe          = adp1653_probe,
 542        .remove         = adp1653_remove,
 543        .id_table       = adp1653_id_table,
 544};
 545
 546module_i2c_driver(adp1653_i2c_driver);
 547
 548MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
 549MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver");
 550MODULE_LICENSE("GPL");
 551