This source file includes following definitions.
- ad5820_write
- ad5820_update_hw
- ad5820_power_off
- ad5820_power_on
- ad5820_set_ctrl
- ad5820_init_controls
- ad5820_registered
- ad5820_set_power
- ad5820_open
- ad5820_close
- ad5820_suspend
- ad5820_resume
- ad5820_probe
- ad5820_remove
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  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 
  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 
  40 struct 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 
  56 static 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 
  83 
  84 
  85 
  86 static 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 
 103 
 104 static int ad5820_power_off(struct ad5820_device *coil, bool standby)
 105 {
 106         int ret = 0, ret2;
 107 
 108         
 109 
 110 
 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 
 123 static 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                 
 133                 coil->standby = false;
 134                 ret = ad5820_update_hw(coil);
 135                 if (ret)
 136                         goto fail;
 137         }
 138         return 0;
 139 
 140 fail:
 141         coil->standby = true;
 142         regulator_disable(coil->vana);
 143 
 144         return ret;
 145 }
 146 
 147 
 148 
 149 
 150 static 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 
 164 static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
 165         .s_ctrl = ad5820_set_ctrl,
 166 };
 167 
 168 
 169 static int ad5820_init_controls(struct ad5820_device *coil)
 170 {
 171         v4l2_ctrl_handler_init(&coil->ctrls, 1);
 172 
 173         
 174 
 175 
 176 
 177 
 178 
 179 
 180 
 181 
 182 
 183 
 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 
 202 
 203 static 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 
 210 static int
 211 ad5820_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 
 220 
 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         
 230         coil->power_count += on ? 1 : -1;
 231         WARN_ON(coil->power_count < 0);
 232 
 233 done:
 234         mutex_unlock(&coil->power_lock);
 235         return ret;
 236 }
 237 
 238 static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 239 {
 240         return ad5820_set_power(sd, 1);
 241 }
 242 
 243 static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 244 {
 245         return ad5820_set_power(sd, 0);
 246 }
 247 
 248 static const struct v4l2_subdev_core_ops ad5820_core_ops = {
 249         .s_power = ad5820_set_power,
 250 };
 251 
 252 static const struct v4l2_subdev_ops ad5820_ops = {
 253         .core = &ad5820_core_ops,
 254 };
 255 
 256 static 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 
 264 
 265 static 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 
 277 static 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 
 289 static 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         coil->subdev.entity.function = MEDIA_ENT_F_LENS;
 313         strscpy(coil->subdev.name, "ad5820 focus", sizeof(coil->subdev.name));
 314 
 315         ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
 316         if (ret < 0)
 317                 goto cleanup2;
 318 
 319         ret = v4l2_async_register_subdev(&coil->subdev);
 320         if (ret < 0)
 321                 goto cleanup;
 322 
 323         return ret;
 324 
 325 cleanup2:
 326         mutex_destroy(&coil->power_lock);
 327 cleanup:
 328         media_entity_cleanup(&coil->subdev.entity);
 329         return ret;
 330 }
 331 
 332 static int ad5820_remove(struct i2c_client *client)
 333 {
 334         struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 335         struct ad5820_device *coil = to_ad5820_device(subdev);
 336 
 337         v4l2_async_unregister_subdev(&coil->subdev);
 338         v4l2_ctrl_handler_free(&coil->ctrls);
 339         media_entity_cleanup(&coil->subdev.entity);
 340         mutex_destroy(&coil->power_lock);
 341         return 0;
 342 }
 343 
 344 static const struct i2c_device_id ad5820_id_table[] = {
 345         { AD5820_NAME, 0 },
 346         { }
 347 };
 348 MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
 349 
 350 static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
 351 
 352 static struct i2c_driver ad5820_i2c_driver = {
 353         .driver         = {
 354                 .name   = AD5820_NAME,
 355                 .pm     = &ad5820_pm,
 356         },
 357         .probe          = ad5820_probe,
 358         .remove         = ad5820_remove,
 359         .id_table       = ad5820_id_table,
 360 };
 361 
 362 module_i2c_driver(ad5820_i2c_driver);
 363 
 364 MODULE_AUTHOR("Tuukka Toivonen");
 365 MODULE_DESCRIPTION("AD5820 camera lens driver");
 366 MODULE_LICENSE("GPL");