| .. | .. |
|---|
| 15 | 15 | #include <media/v4l2-device.h> |
|---|
| 16 | 16 | #include <linux/rk_vcm_head.h> |
|---|
| 17 | 17 | #include <linux/compat.h> |
|---|
| 18 | +#include <linux/regulator/consumer.h> |
|---|
| 18 | 19 | |
|---|
| 19 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) |
|---|
| 20 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) |
|---|
| 20 | 21 | #define DW9763_NAME "dw9763" |
|---|
| 21 | 22 | |
|---|
| 22 | 23 | #define DW9763_MAX_CURRENT 120U |
|---|
| 23 | 24 | #define DW9763_MAX_REG 1023U |
|---|
| 25 | +#define DW9763_GRADUAL_MOVELENS_STEPS 32 |
|---|
| 24 | 26 | |
|---|
| 25 | 27 | #define DW9763_DEFAULT_START_CURRENT 20 |
|---|
| 26 | 28 | #define DW9763_DEFAULT_RATED_CURRENT 90 |
|---|
| .. | .. |
|---|
| 40 | 42 | SAC4_MODE = 5, |
|---|
| 41 | 43 | DIRECT_MODE, |
|---|
| 42 | 44 | }; |
|---|
| 45 | + |
|---|
| 46 | +static int debug; |
|---|
| 47 | +module_param(debug, int, 0644); |
|---|
| 48 | +MODULE_PARM_DESC(debug, "debug level (0-2)"); |
|---|
| 43 | 49 | |
|---|
| 44 | 50 | /* dw9763 device structure */ |
|---|
| 45 | 51 | struct dw9763_device { |
|---|
| .. | .. |
|---|
| 69 | 75 | struct rk_cam_vcm_cfg vcm_cfg; |
|---|
| 70 | 76 | int max_ma; |
|---|
| 71 | 77 | struct mutex lock; |
|---|
| 78 | + struct regulator *supply; |
|---|
| 79 | + bool power_on; |
|---|
| 72 | 80 | }; |
|---|
| 73 | 81 | |
|---|
| 74 | 82 | static inline struct dw9763_device *to_dw9763_vcm(struct v4l2_ctrl *ctrl) |
|---|
| .. | .. |
|---|
| 88 | 96 | u8 buf[5]; |
|---|
| 89 | 97 | u8 *val_p; |
|---|
| 90 | 98 | __be32 val_be; |
|---|
| 99 | + struct dw9763_device *dev_vcm = i2c_get_clientdata(client); |
|---|
| 91 | 100 | |
|---|
| 92 | 101 | if (len > 4) |
|---|
| 93 | 102 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 106 | 115 | dev_err(&client->dev, "Failed to write 0x%04x,0x%x\n", reg, val); |
|---|
| 107 | 116 | return -EIO; |
|---|
| 108 | 117 | } |
|---|
| 109 | | - dev_dbg(&client->dev, "succeed to write 0x%04x,0x%x\n", reg, val); |
|---|
| 118 | + v4l2_dbg(1, debug, &dev_vcm->sd, "succeed to write 0x%04x,0x%x\n", reg, val); |
|---|
| 110 | 119 | |
|---|
| 111 | 120 | return 0; |
|---|
| 112 | 121 | } |
|---|
| .. | .. |
|---|
| 120 | 129 | u8 *data_be_p; |
|---|
| 121 | 130 | __be32 data_be = 0; |
|---|
| 122 | 131 | int ret; |
|---|
| 132 | + struct dw9763_device *dev_vcm = i2c_get_clientdata(client); |
|---|
| 123 | 133 | |
|---|
| 124 | 134 | if (len > 4 || !len) |
|---|
| 125 | 135 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 142 | 152 | return -EIO; |
|---|
| 143 | 153 | |
|---|
| 144 | 154 | *val = be32_to_cpu(data_be); |
|---|
| 155 | + |
|---|
| 156 | + v4l2_dbg(1, debug, &dev_vcm->sd, "succeed to read 0x%04x,0x%x\n", reg, *val); |
|---|
| 145 | 157 | |
|---|
| 146 | 158 | return 0; |
|---|
| 147 | 159 | } |
|---|
| .. | .. |
|---|
| 204 | 216 | break; |
|---|
| 205 | 217 | } |
|---|
| 206 | 218 | |
|---|
| 207 | | - dev_dbg(&client->dev, |
|---|
| 219 | + v4l2_dbg(1, debug, &dev_vcm->sd, |
|---|
| 208 | 220 | "%s: vcm_movefull_t is: %d us\n", |
|---|
| 209 | 221 | __func__, move_time_us); |
|---|
| 210 | 222 | |
|---|
| 211 | | - return move_time_us; |
|---|
| 223 | + return ((move_time_us + 500) / 1000); |
|---|
| 212 | 224 | } |
|---|
| 213 | 225 | |
|---|
| 214 | 226 | static int dw9763_set_dac(struct dw9763_device *dev_vcm, |
|---|
| .. | .. |
|---|
| 228 | 240 | ret = dw9763_write_reg(client, 0x03, 2, dest_dac); |
|---|
| 229 | 241 | if (ret != 0) |
|---|
| 230 | 242 | goto err; |
|---|
| 231 | | - dev_dbg(&client->dev, |
|---|
| 243 | + v4l2_dbg(1, debug, &dev_vcm->sd, |
|---|
| 232 | 244 | "%s: set reg val %d\n", __func__, dest_dac); |
|---|
| 233 | 245 | |
|---|
| 234 | 246 | return ret; |
|---|
| .. | .. |
|---|
| 249 | 261 | goto err; |
|---|
| 250 | 262 | |
|---|
| 251 | 263 | *cur_dac = abs_step; |
|---|
| 252 | | - dev_dbg(&client->dev, "%s: get dac %d\n", __func__, *cur_dac); |
|---|
| 264 | + v4l2_dbg(1, debug, &dev_vcm->sd, "%s: get dac %d\n", __func__, *cur_dac); |
|---|
| 253 | 265 | |
|---|
| 254 | 266 | return 0; |
|---|
| 255 | 267 | |
|---|
| .. | .. |
|---|
| 279 | 291 | abs_step = 0; |
|---|
| 280 | 292 | |
|---|
| 281 | 293 | *cur_pos = abs_step; |
|---|
| 282 | | - dev_dbg(&client->dev, "%s: get position %d\n", __func__, *cur_pos); |
|---|
| 294 | + v4l2_dbg(1, debug, &dev_vcm->sd, "%s: get position %d\n", __func__, *cur_pos); |
|---|
| 283 | 295 | return 0; |
|---|
| 284 | 296 | |
|---|
| 285 | 297 | err: |
|---|
| .. | .. |
|---|
| 293 | 305 | { |
|---|
| 294 | 306 | int ret; |
|---|
| 295 | 307 | unsigned int position = 0; |
|---|
| 296 | | - struct i2c_client *client = dev_vcm->client; |
|---|
| 297 | 308 | |
|---|
| 298 | 309 | if (dest_pos >= VCMDRV_MAX_LOG) |
|---|
| 299 | 310 | position = dev_vcm->start_current; |
|---|
| .. | .. |
|---|
| 308 | 319 | dev_vcm->current_related_pos = dest_pos; |
|---|
| 309 | 320 | |
|---|
| 310 | 321 | ret = dw9763_set_dac(dev_vcm, position); |
|---|
| 311 | | - dev_dbg(&client->dev, "%s: set position %d, dac %d\n", __func__, dest_pos, position); |
|---|
| 322 | + v4l2_dbg(1, debug, &dev_vcm->sd, "%s: set position %d, dac %d\n", |
|---|
| 323 | + __func__, dest_pos, position); |
|---|
| 312 | 324 | |
|---|
| 313 | 325 | return ret; |
|---|
| 314 | 326 | } |
|---|
| .. | .. |
|---|
| 331 | 343 | long mv_us; |
|---|
| 332 | 344 | int ret = 0; |
|---|
| 333 | 345 | |
|---|
| 334 | | - dev_dbg(&client->dev, "ctrl->id: 0x%x, ctrl->val: 0x%x\n", |
|---|
| 346 | + v4l2_dbg(1, debug, &dev_vcm->sd, "ctrl->id: 0x%x, ctrl->val: 0x%x\n", |
|---|
| 335 | 347 | ctrl->id, ctrl->val); |
|---|
| 336 | 348 | |
|---|
| 337 | 349 | if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) { |
|---|
| .. | .. |
|---|
| 345 | 357 | |
|---|
| 346 | 358 | ret = dw9763_set_pos(dev_vcm, dest_pos); |
|---|
| 347 | 359 | |
|---|
| 348 | | - dev_vcm->move_us = dev_vcm->vcm_movefull_t; |
|---|
| 360 | + dev_vcm->move_us = dev_vcm->vcm_movefull_t * 1000; |
|---|
| 349 | 361 | |
|---|
| 350 | | - dev_dbg(&client->dev, |
|---|
| 362 | + v4l2_dbg(1, debug, &dev_vcm->sd, |
|---|
| 351 | 363 | "dest_pos %d, move_us %ld\n", |
|---|
| 352 | 364 | dest_pos, dev_vcm->move_us); |
|---|
| 353 | 365 | |
|---|
| .. | .. |
|---|
| 373 | 385 | .s_ctrl = dw9763_set_ctrl, |
|---|
| 374 | 386 | }; |
|---|
| 375 | 387 | |
|---|
| 388 | +static int dw9763_init(struct i2c_client *client); |
|---|
| 376 | 389 | static int dw9763_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
|---|
| 377 | 390 | { |
|---|
| 378 | 391 | int rval; |
|---|
| 392 | + struct dw9763_device *dev_vcm = sd_to_dw9763_vcm(sd); |
|---|
| 393 | + unsigned int move_time; |
|---|
| 394 | + int dac = dev_vcm->start_current; |
|---|
| 395 | + struct i2c_client *client = dev_vcm->client; |
|---|
| 396 | + |
|---|
| 397 | +#ifdef CONFIG_PM |
|---|
| 398 | + v4l2_info(sd, "%s: enter, power.usage_count(%d)!\n", __func__, |
|---|
| 399 | + atomic_read(&sd->dev->power.usage_count)); |
|---|
| 400 | +#endif |
|---|
| 379 | 401 | |
|---|
| 380 | 402 | rval = pm_runtime_get_sync(sd->dev); |
|---|
| 381 | 403 | if (rval < 0) { |
|---|
| .. | .. |
|---|
| 383 | 405 | return rval; |
|---|
| 384 | 406 | } |
|---|
| 385 | 407 | |
|---|
| 408 | + dw9763_init(client); |
|---|
| 409 | + |
|---|
| 410 | + v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", |
|---|
| 411 | + __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); |
|---|
| 412 | + |
|---|
| 413 | + move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS); |
|---|
| 414 | + while (dac <= dev_vcm->current_lens_pos) { |
|---|
| 415 | + dw9763_set_dac(dev_vcm, dac); |
|---|
| 416 | + usleep_range(move_time, move_time + 100); |
|---|
| 417 | + dac += DW9763_GRADUAL_MOVELENS_STEPS; |
|---|
| 418 | + if (dac > dev_vcm->current_lens_pos) |
|---|
| 419 | + break; |
|---|
| 420 | + } |
|---|
| 421 | + |
|---|
| 422 | + if (dac > dev_vcm->current_lens_pos) { |
|---|
| 423 | + dac = dev_vcm->current_lens_pos; |
|---|
| 424 | + dw9763_set_dac(dev_vcm, dac); |
|---|
| 425 | + } |
|---|
| 426 | + |
|---|
| 427 | +#ifdef CONFIG_PM |
|---|
| 428 | + v4l2_info(sd, "%s: exit, power.usage_count(%d)!\n", __func__, |
|---|
| 429 | + atomic_read(&sd->dev->power.usage_count)); |
|---|
| 430 | +#endif |
|---|
| 386 | 431 | return 0; |
|---|
| 387 | 432 | } |
|---|
| 388 | 433 | |
|---|
| 389 | 434 | static int dw9763_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
|---|
| 390 | 435 | { |
|---|
| 436 | + struct dw9763_device *dev_vcm = sd_to_dw9763_vcm(sd); |
|---|
| 437 | + int dac = dev_vcm->current_lens_pos; |
|---|
| 438 | + unsigned int move_time; |
|---|
| 439 | + int ret; |
|---|
| 440 | + struct i2c_client *client = dev_vcm->client; |
|---|
| 441 | + |
|---|
| 442 | +#ifdef CONFIG_PM |
|---|
| 443 | + v4l2_info(sd, "%s: enter, power.usage_count(%d)!\n", __func__, |
|---|
| 444 | + atomic_read(&sd->dev->power.usage_count)); |
|---|
| 445 | +#endif |
|---|
| 446 | + |
|---|
| 447 | + v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", |
|---|
| 448 | + __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); |
|---|
| 449 | + |
|---|
| 450 | + dac -= DW9763_GRADUAL_MOVELENS_STEPS; |
|---|
| 451 | + move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS); |
|---|
| 452 | + while (dac >= DW9763_GRADUAL_MOVELENS_STEPS) { |
|---|
| 453 | + dw9763_set_dac(dev_vcm, dac); |
|---|
| 454 | + usleep_range(move_time, move_time + 1000); |
|---|
| 455 | + dac -= DW9763_GRADUAL_MOVELENS_STEPS; |
|---|
| 456 | + if (dac <= 0) |
|---|
| 457 | + break; |
|---|
| 458 | + } |
|---|
| 459 | + |
|---|
| 460 | + if (dac < DW9763_GRADUAL_MOVELENS_STEPS) { |
|---|
| 461 | + dac = DW9763_GRADUAL_MOVELENS_STEPS / 2; |
|---|
| 462 | + dw9763_set_dac(dev_vcm, dac); |
|---|
| 463 | + } |
|---|
| 464 | + /* set to power down mode */ |
|---|
| 465 | + ret = dw9763_write_reg(client, 0x02, 1, 0x01); |
|---|
| 466 | + if (ret) |
|---|
| 467 | + dev_err(&client->dev, "failed to set power down mode!\n"); |
|---|
| 468 | + |
|---|
| 391 | 469 | pm_runtime_put(sd->dev); |
|---|
| 470 | +#ifdef CONFIG_PM |
|---|
| 471 | + v4l2_info(sd, "%s: exit, power.usage_count(%d)!\n", __func__, |
|---|
| 472 | + atomic_read(&sd->dev->power.usage_count)); |
|---|
| 473 | +#endif |
|---|
| 392 | 474 | |
|---|
| 393 | 475 | return 0; |
|---|
| 394 | 476 | } |
|---|
| .. | .. |
|---|
| 442 | 524 | vcm_tim->vcm_end_t.tv_sec = dev_vcm->end_move_tv.tv_sec; |
|---|
| 443 | 525 | vcm_tim->vcm_end_t.tv_usec = dev_vcm->end_move_tv.tv_usec; |
|---|
| 444 | 526 | |
|---|
| 445 | | - dev_dbg(&client->dev, "dw9763_get_move_res 0x%lx, 0x%lx, 0x%lx, 0x%lx\n", |
|---|
| 527 | + v4l2_dbg(1, debug, &dev_vcm->sd, "dw9763_get_move_res 0x%lx, 0x%lx, 0x%lx, 0x%lx\n", |
|---|
| 446 | 528 | vcm_tim->vcm_start_t.tv_sec, |
|---|
| 447 | 529 | vcm_tim->vcm_start_t.tv_usec, |
|---|
| 448 | 530 | vcm_tim->vcm_end_t.tv_sec, |
|---|
| .. | .. |
|---|
| 634 | 716 | } |
|---|
| 635 | 717 | #endif |
|---|
| 636 | 718 | |
|---|
| 637 | | -static int __dw9763_set_power(struct dw9763_device *dw9763_dev, bool on) |
|---|
| 719 | +static int __dw9763_set_power(struct dw9763_device *dw9763, bool on) |
|---|
| 638 | 720 | { |
|---|
| 639 | | - if (dw9763_dev->power_gpio) |
|---|
| 640 | | - gpiod_direction_output(dw9763_dev->power_gpio, on); |
|---|
| 641 | | - usleep_range(10000, 11000); |
|---|
| 721 | + struct i2c_client *client = dw9763->client; |
|---|
| 722 | + int ret = 0; |
|---|
| 642 | 723 | |
|---|
| 643 | | - return 0; |
|---|
| 724 | + dev_info(&client->dev, "%s(%d) on(%d)\n", __func__, __LINE__, on); |
|---|
| 725 | + |
|---|
| 726 | + if (dw9763->power_on == !!on) |
|---|
| 727 | + goto unlock_and_return; |
|---|
| 728 | + |
|---|
| 729 | + if (on) { |
|---|
| 730 | + ret = regulator_enable(dw9763->supply); |
|---|
| 731 | + if (ret < 0) { |
|---|
| 732 | + dev_err(&client->dev, "Failed to enable regulator\n"); |
|---|
| 733 | + goto unlock_and_return; |
|---|
| 734 | + } |
|---|
| 735 | + dw9763->power_on = true; |
|---|
| 736 | + } else { |
|---|
| 737 | + ret = regulator_disable(dw9763->supply); |
|---|
| 738 | + if (ret < 0) { |
|---|
| 739 | + dev_err(&client->dev, "Failed to disable regulator\n"); |
|---|
| 740 | + goto unlock_and_return; |
|---|
| 741 | + } |
|---|
| 742 | + dw9763->power_on = false; |
|---|
| 743 | + } |
|---|
| 744 | + |
|---|
| 745 | +unlock_and_return: |
|---|
| 746 | + return ret; |
|---|
| 747 | +} |
|---|
| 748 | + |
|---|
| 749 | +static int dw9763_configure_regulator(struct dw9763_device *dw9763) |
|---|
| 750 | +{ |
|---|
| 751 | + struct i2c_client *client = dw9763->client; |
|---|
| 752 | + int ret = 0; |
|---|
| 753 | + |
|---|
| 754 | + dw9763->supply = devm_regulator_get(&client->dev, "avdd"); |
|---|
| 755 | + if (IS_ERR(dw9763->supply)) { |
|---|
| 756 | + ret = PTR_ERR(dw9763->supply); |
|---|
| 757 | + if (ret != -EPROBE_DEFER) |
|---|
| 758 | + dev_err(&client->dev, "could not get regulator avdd\n"); |
|---|
| 759 | + return ret; |
|---|
| 760 | + } |
|---|
| 761 | + dw9763->power_on = false; |
|---|
| 762 | + return ret; |
|---|
| 644 | 763 | } |
|---|
| 645 | 764 | |
|---|
| 646 | 765 | static int __maybe_unused dw9763_check_id(struct dw9763_device *dw9763_dev) |
|---|
| .. | .. |
|---|
| 661 | 780 | dev_info(&dw9763_dev->client->dev, |
|---|
| 662 | 781 | "Detected dw9763 vcm id:0x%x\n", DW9763_CHIP_ID); |
|---|
| 663 | 782 | return 0; |
|---|
| 664 | | -} |
|---|
| 665 | | -static int dw9763_probe_init(struct i2c_client *client) |
|---|
| 666 | | -{ |
|---|
| 667 | | - int ret = 0; |
|---|
| 668 | | - |
|---|
| 669 | | - /* Default goto power down mode when finished probe */ |
|---|
| 670 | | - ret = dw9763_write_reg(client, 0x02, 1, 0x01); |
|---|
| 671 | | - if (ret) |
|---|
| 672 | | - goto err; |
|---|
| 673 | | - |
|---|
| 674 | | - return 0; |
|---|
| 675 | | -err: |
|---|
| 676 | | - dev_err(&client->dev, "probe init failed with error %d\n", ret); |
|---|
| 677 | | - return -1; |
|---|
| 678 | 783 | } |
|---|
| 679 | 784 | |
|---|
| 680 | 785 | static int dw9763_probe(struct i2c_client *client, |
|---|
| .. | .. |
|---|
| 765 | 870 | dev_warn(&client->dev, |
|---|
| 766 | 871 | "Failed to get power-gpios, maybe no use\n"); |
|---|
| 767 | 872 | } |
|---|
| 768 | | - |
|---|
| 769 | | - /* enter power down mode */ |
|---|
| 770 | | - dw9763_probe_init(client); |
|---|
| 873 | + ret = dw9763_configure_regulator(dw9763_dev); |
|---|
| 874 | + if (ret) { |
|---|
| 875 | + dev_err(&client->dev, "Failed to get power regulator!\n"); |
|---|
| 876 | + return ret; |
|---|
| 877 | + } |
|---|
| 771 | 878 | |
|---|
| 772 | 879 | v4l2_i2c_subdev_init(&dw9763_dev->sd, client, &dw9763_ops); |
|---|
| 773 | 880 | dw9763_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
|---|
| .. | .. |
|---|
| 780 | 887 | ret = media_entity_pads_init(&dw9763_dev->sd.entity, 0, NULL); |
|---|
| 781 | 888 | if (ret < 0) |
|---|
| 782 | 889 | goto err_cleanup; |
|---|
| 890 | + |
|---|
| 891 | + ret = dw9763_check_id(dw9763_dev); |
|---|
| 892 | + if (ret) |
|---|
| 893 | + goto err_power_off; |
|---|
| 783 | 894 | |
|---|
| 784 | 895 | sd = &dw9763_dev->sd; |
|---|
| 785 | 896 | sd->entity.function = MEDIA_ENT_F_LENS; |
|---|
| .. | .. |
|---|
| 823 | 934 | dev_info(&client->dev, "probing successful\n"); |
|---|
| 824 | 935 | |
|---|
| 825 | 936 | return 0; |
|---|
| 937 | +err_power_off: |
|---|
| 938 | + __dw9763_set_power(dw9763_dev, false); |
|---|
| 939 | + |
|---|
| 826 | 940 | err_cleanup: |
|---|
| 827 | 941 | dw9763_subdev_cleanup(dw9763_dev); |
|---|
| 828 | 942 | |
|---|
| .. | .. |
|---|
| 847 | 961 | { |
|---|
| 848 | 962 | struct dw9763_device *dev_vcm = i2c_get_clientdata(client); |
|---|
| 849 | 963 | int ret = 0; |
|---|
| 850 | | - u32 ring = 0; |
|---|
| 851 | 964 | u32 mode_val = 0; |
|---|
| 852 | 965 | u32 algo_time = 0; |
|---|
| 853 | 966 | |
|---|
| 967 | + if (dev_vcm->step_mode == DIRECT_MODE) |
|---|
| 968 | + return 0; |
|---|
| 854 | 969 | |
|---|
| 855 | | - /* Delay 200us~300us */ |
|---|
| 856 | | - usleep_range(200, 300); |
|---|
| 857 | 970 | ret = dw9763_write_reg(client, 0x02, 1, 0x00); |
|---|
| 858 | 971 | if (ret) |
|---|
| 859 | 972 | goto err; |
|---|
| 860 | | - usleep_range(100, 200); |
|---|
| 861 | 973 | |
|---|
| 862 | | - if (dev_vcm->step_mode != DIRECT_MODE) |
|---|
| 863 | | - ring = 0x02; |
|---|
| 864 | | - ret = dw9763_write_reg(client, 0x02, 1, ring); |
|---|
| 974 | + usleep_range(200, 300); |
|---|
| 975 | + ret = dw9763_write_reg(client, 0x02, 1, 0x02); |
|---|
| 865 | 976 | if (ret) |
|---|
| 866 | 977 | goto err; |
|---|
| 867 | 978 | switch (dev_vcm->step_mode) { |
|---|
| .. | .. |
|---|
| 895 | 1006 | static int __maybe_unused dw9763_vcm_suspend(struct device *dev) |
|---|
| 896 | 1007 | { |
|---|
| 897 | 1008 | struct i2c_client *client = to_i2c_client(dev); |
|---|
| 898 | | - int ret = 0; |
|---|
| 1009 | + struct dw9763_device *dev_vcm = i2c_get_clientdata(client); |
|---|
| 1010 | + struct v4l2_subdev *sd = &(dev_vcm->sd); |
|---|
| 899 | 1011 | |
|---|
| 900 | | - /* set to power down mode */ |
|---|
| 901 | | - ret = dw9763_write_reg(client, 0x02, 1, 0x01); |
|---|
| 902 | | - if (ret) |
|---|
| 903 | | - dev_err(&client->dev, "failed to set power down mode!\n"); |
|---|
| 1012 | +#ifdef CONFIG_PM |
|---|
| 1013 | + v4l2_dbg(1, debug, sd, "%s: enter, power.usage_count(%d)!\n", __func__, |
|---|
| 1014 | + atomic_read(&sd->dev->power.usage_count)); |
|---|
| 1015 | +#endif |
|---|
| 904 | 1016 | |
|---|
| 1017 | + __dw9763_set_power(dev_vcm, false); |
|---|
| 905 | 1018 | return 0; |
|---|
| 906 | 1019 | } |
|---|
| 907 | 1020 | |
|---|
| .. | .. |
|---|
| 909 | 1022 | { |
|---|
| 910 | 1023 | struct i2c_client *client = to_i2c_client(dev); |
|---|
| 911 | 1024 | struct dw9763_device *dev_vcm = i2c_get_clientdata(client); |
|---|
| 1025 | + struct v4l2_subdev *sd = &(dev_vcm->sd); |
|---|
| 912 | 1026 | |
|---|
| 913 | | - dw9763_init(client); |
|---|
| 914 | | - dw9763_set_pos(dev_vcm, dev_vcm->current_related_pos); |
|---|
| 1027 | +#ifdef CONFIG_PM |
|---|
| 1028 | + v4l2_dbg(1, debug, sd, "%s: enter, power.usage_count(%d)!\n", __func__, |
|---|
| 1029 | + atomic_read(&sd->dev->power.usage_count)); |
|---|
| 1030 | +#endif |
|---|
| 1031 | + __dw9763_set_power(dev_vcm, true); |
|---|
| 1032 | + |
|---|
| 915 | 1033 | return 0; |
|---|
| 916 | 1034 | } |
|---|
| 917 | 1035 | |
|---|