linux/drivers/media/i2c/ad5820.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * drivers/media/i2c/ad5820.c
   4 *
   5 * AD5820 DAC driver for camera voice coil focus.
   6 *
   7 * Copyright (C) 2008 Nokia Corporation
   8 * Copyright (C) 2007 Texas Instruments
   9 * Copyright (C) 2016 Pavel Machek <pavel@ucw.cz>
  10 *
  11 * Contact: Tuukka Toivonen <tuukkat76@gmail.com>
  12 *          Sakari Ailus <sakari.ailus@iki.fi>
  13 *
  14 * Based on af_d88.c by Texas Instruments.
  15 */
  16
  17#include <linux/errno.h>
  18#include <linux/i2c.h>
  19#include <linux/kernel.h>
  20#include <linux/module.h>
  21#include <linux/regulator/consumer.h>
  22
  23#include <media/v4l2-ctrls.h>
  24#include <media/v4l2-device.h>
  25#include <media/v4l2-subdev.h>
  26
  27#define AD5820_NAME             "ad5820"
  28
  29/* Register definitions */
  30#define AD5820_POWER_DOWN               (1 << 15)
  31#define AD5820_DAC_SHIFT                4
  32#define AD5820_RAMP_MODE_LINEAR         (0 << 3)
  33#define AD5820_RAMP_MODE_64_16          (1 << 3)
  34
  35#define CODE_TO_RAMP_US(s)      ((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
  36#define RAMP_US_TO_CODE(c)      fls(((c) + ((c)>>1)) / 50)
  37
  38#define to_ad5820_device(sd)    container_of(sd, struct ad5820_device, subdev)
  39
  40struct ad5820_device {
  41        struct v4l2_subdev subdev;
  42        struct ad5820_platform_data *platform_data;
  43        struct regulator *vana;
  44
  45        struct v4l2_ctrl_handler ctrls;
  46        u32 focus_absolute;
  47        u32 focus_ramp_time;
  48        u32 focus_ramp_mode;
  49
  50        struct mutex power_lock;
  51        int power_count;
  52
  53        bool standby;
  54};
  55
  56static int ad5820_write(struct ad5820_device *coil, u16 data)
  57{
  58        struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
  59        struct i2c_msg msg;
  60        __be16 be_data;
  61        int r;
  62
  63        if (!client->adapter)
  64                return -ENODEV;
  65
  66        be_data = cpu_to_be16(data);
  67        msg.addr  = client->addr;
  68        msg.flags = 0;
  69        msg.len   = 2;
  70        msg.buf   = (u8 *)&be_data;
  71
  72        r = i2c_transfer(client->adapter, &msg, 1);
  73        if (r < 0) {
  74                dev_err(&client->dev, "write failed, error %d\n", r);
  75                return r;
  76        }
  77
  78        return 0;
  79}
  80
  81/*
  82 * Calculate status word and write it to the device based on current
  83 * values of V4L2 controls. It is assumed that the stored V4L2 control
  84 * values are properly limited and rounded.
  85 */
  86static int ad5820_update_hw(struct ad5820_device *coil)
  87{
  88        u16 status;
  89
  90        status = RAMP_US_TO_CODE(coil->focus_ramp_time);
  91        status |= coil->focus_ramp_mode
  92                ? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
  93        status |= coil->focus_absolute << AD5820_DAC_SHIFT;
  94
  95        if (coil->standby)
  96                status |= AD5820_POWER_DOWN;
  97
  98        return ad5820_write(coil, status);
  99}
 100
 101/*
 102 * Power handling
 103 */
 104static int ad5820_power_off(struct ad5820_device *coil, bool standby)
 105{
 106        int ret = 0, ret2;
 107
 108        /*
 109         * Go to standby first as real power off my be denied by the hardware
 110         * (single power line control for both coil and sensor).
 111         */
 112        if (standby) {
 113                coil->standby = true;
 114                ret = ad5820_update_hw(coil);
 115        }
 116
 117        ret2 = regulator_disable(coil->vana);
 118        if (ret)
 119                return ret;
 120        return ret2;
 121}
 122
 123static int ad5820_power_on(struct ad5820_device *coil, bool restore)
 124{
 125        int ret;
 126
 127        ret = regulator_enable(coil->vana);
 128        if (ret < 0)
 129                return ret;
 130
 131        if (restore) {
 132                /* Restore the hardware settings. */
 133                coil->standby = false;
 134                ret = ad5820_update_hw(coil);
 135                if (ret)
 136                        goto fail;
 137        }
 138        return 0;
 139
 140fail:
 141        coil->standby = true;
 142        regulator_disable(coil->vana);
 143
 144        return ret;
 145}
 146
 147/*
 148 * V4L2 controls
 149 */
 150static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
 151{
 152        struct ad5820_device *coil =
 153                container_of(ctrl->handler, struct ad5820_device, ctrls);
 154
 155        switch (ctrl->id) {
 156        case V4L2_CID_FOCUS_ABSOLUTE:
 157                coil->focus_absolute = ctrl->val;
 158                return ad5820_update_hw(coil);
 159        }
 160
 161        return 0;
 162}
 163
 164static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
 165        .s_ctrl = ad5820_set_ctrl,
 166};
 167
 168
 169static int ad5820_init_controls(struct ad5820_device *coil)
 170{
 171        v4l2_ctrl_handler_init(&coil->ctrls, 1);
 172
 173        /*
 174         * V4L2_CID_FOCUS_ABSOLUTE
 175         *
 176         * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
 177         * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
 178         * for focus position, because it is meaningless for user. Meaningful
 179         * would be to use focus distance or even its inverse, but since the
 180         * driver doesn't have sufficiently knowledge to do the conversion, we
 181         * will just use abstract codes here. In any case, smaller value = focus
 182         * position farther from camera. The default zero value means focus at
 183         * infinity, and also least current consumption.
 184         */
 185        v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
 186                          V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
 187
 188        if (coil->ctrls.error)
 189                return coil->ctrls.error;
 190
 191        coil->focus_absolute = 0;
 192        coil->focus_ramp_time = 0;
 193        coil->focus_ramp_mode = 0;
 194
 195        coil->subdev.ctrl_handler = &coil->ctrls;
 196
 197        return 0;
 198}
 199
 200/*
 201 * V4L2 subdev operations
 202 */
 203static int ad5820_registered(struct v4l2_subdev *subdev)
 204{
 205        struct ad5820_device *coil = to_ad5820_device(subdev);
 206
 207        return ad5820_init_controls(coil);
 208}
 209
 210static int
 211ad5820_set_power(struct v4l2_subdev *subdev, int on)
 212{
 213        struct ad5820_device *coil = to_ad5820_device(subdev);
 214        int ret = 0;
 215
 216        mutex_lock(&coil->power_lock);
 217
 218        /*
 219         * If the power count is modified from 0 to != 0 or from != 0 to 0,
 220         * update the power state.
 221         */
 222        if (coil->power_count == !on) {
 223                ret = on ? ad5820_power_on(coil, true) :
 224                        ad5820_power_off(coil, true);
 225                if (ret < 0)
 226                        goto done;
 227        }
 228
 229        /* Update the power count. */
 230        coil->power_count += on ? 1 : -1;
 231        WARN_ON(coil->power_count < 0);
 232
 233done:
 234        mutex_unlock(&coil->power_lock);
 235        return ret;
 236}
 237
 238static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 239{
 240        return ad5820_set_power(sd, 1);
 241}
 242
 243static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 244{
 245        return ad5820_set_power(sd, 0);
 246}
 247
 248static const struct v4l2_subdev_core_ops ad5820_core_ops = {
 249        .s_power = ad5820_set_power,
 250};
 251
 252static const struct v4l2_subdev_ops ad5820_ops = {
 253        .core = &ad5820_core_ops,
 254};
 255
 256static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
 257        .registered = ad5820_registered,
 258        .open = ad5820_open,
 259        .close = ad5820_close,
 260};
 261
 262/*
 263 * I2C driver
 264 */
 265static int __maybe_unused ad5820_suspend(struct device *dev)
 266{
 267        struct i2c_client *client = container_of(dev, struct i2c_client, dev);
 268        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 269        struct ad5820_device *coil = to_ad5820_device(subdev);
 270
 271        if (!coil->power_count)
 272                return 0;
 273
 274        return ad5820_power_off(coil, false);
 275}
 276
 277static int __maybe_unused ad5820_resume(struct device *dev)
 278{
 279        struct i2c_client *client = container_of(dev, struct i2c_client, dev);
 280        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 281        struct ad5820_device *coil = to_ad5820_device(subdev);
 282
 283        if (!coil->power_count)
 284                return 0;
 285
 286        return ad5820_power_on(coil, true);
 287}
 288
 289static int ad5820_probe(struct i2c_client *client,
 290                        const struct i2c_device_id *devid)
 291{
 292        struct ad5820_device *coil;
 293        int ret;
 294
 295        coil = devm_kzalloc(&client->dev, sizeof(*coil), GFP_KERNEL);
 296        if (!coil)
 297                return -ENOMEM;
 298
 299        coil->vana = devm_regulator_get(&client->dev, "VANA");
 300        if (IS_ERR(coil->vana)) {
 301                ret = PTR_ERR(coil->vana);
 302                if (ret != -EPROBE_DEFER)
 303                        dev_err(&client->dev, "could not get regulator for vana\n");
 304                return ret;
 305        }
 306
 307        mutex_init(&coil->power_lock);
 308
 309        v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
 310        coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 311        coil->subdev.internal_ops = &ad5820_internal_ops;
 312        strscpy(coil->subdev.name, "ad5820 focus", sizeof(coil->subdev.name));
 313
 314        ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
 315        if (ret < 0)
 316                goto cleanup2;
 317
 318        ret = v4l2_async_register_subdev(&coil->subdev);
 319        if (ret < 0)
 320                goto cleanup;
 321
 322        return ret;
 323
 324cleanup2:
 325        mutex_destroy(&coil->power_lock);
 326cleanup:
 327        media_entity_cleanup(&coil->subdev.entity);
 328        return ret;
 329}
 330
 331static int ad5820_remove(struct i2c_client *client)
 332{
 333        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 334        struct ad5820_device *coil = to_ad5820_device(subdev);
 335
 336        v4l2_async_unregister_subdev(&coil->subdev);
 337        v4l2_ctrl_handler_free(&coil->ctrls);
 338        media_entity_cleanup(&coil->subdev.entity);
 339        mutex_destroy(&coil->power_lock);
 340        return 0;
 341}
 342
 343static const struct i2c_device_id ad5820_id_table[] = {
 344        { AD5820_NAME, 0 },
 345        { }
 346};
 347MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
 348
 349static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
 350
 351static struct i2c_driver ad5820_i2c_driver = {
 352        .driver         = {
 353                .name   = AD5820_NAME,
 354                .pm     = &ad5820_pm,
 355        },
 356        .probe          = ad5820_probe,
 357        .remove         = ad5820_remove,
 358        .id_table       = ad5820_id_table,
 359};
 360
 361module_i2c_driver(ad5820_i2c_driver);
 362
 363MODULE_AUTHOR("Tuukka Toivonen");
 364MODULE_DESCRIPTION("AD5820 camera lens driver");
 365MODULE_LICENSE("GPL");
 366