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