hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/media/i2c/dw9800w.c
....@@ -44,6 +44,7 @@
4444 /* dw9800w device structure */
4545 struct dw9800w_device {
4646 struct v4l2_ctrl_handler ctrls_vcm;
47
+ struct v4l2_ctrl *focus;
4748 struct i2c_client *client;
4849 struct v4l2_subdev sd;
4950 struct v4l2_device vdev;
....@@ -52,13 +53,14 @@
5253 struct gpio_desc *power_gpio;
5354 unsigned short current_related_pos;
5455 unsigned short current_lens_pos;
56
+ unsigned int max_current;
5557 unsigned int start_current;
5658 unsigned int rated_current;
57
- unsigned int step;
5859 unsigned int step_mode;
5960 unsigned int vcm_movefull_t;
6061 unsigned int t_src;
6162 unsigned int t_div;
63
+ unsigned int max_logicalpos;
6264
6365 struct __kernel_old_timeval start_move_tv;
6466 struct __kernel_old_timeval end_move_tv;
....@@ -67,7 +69,6 @@
6769 u32 module_index;
6870 const char *module_facing;
6971 struct rk_cam_vcm_cfg vcm_cfg;
70
- int max_ma;
7172 struct mutex lock;
7273 };
7374
....@@ -217,22 +218,25 @@
217218 unsigned int *cur_pos)
218219 {
219220 struct i2c_client *client = dev_vcm->client;
221
+ unsigned int dac, position, range;
220222 int ret;
221
- unsigned int abs_step;
222223
223
- ret = dw9800w_read_reg(client, 0x03, 2, &abs_step);
224
+ range = dev_vcm->rated_current - dev_vcm->start_current;
225
+ ret = dw9800w_read_reg(client, 0x03, 2, &dac);
224226 if (ret != 0)
225227 goto err;
226228
227
- if (abs_step <= dev_vcm->start_current)
228
- abs_step = VCMDRV_MAX_LOG;
229
- else if ((abs_step > dev_vcm->start_current) &&
230
- (abs_step <= dev_vcm->rated_current))
231
- abs_step = (dev_vcm->rated_current - abs_step) / dev_vcm->step;
232
- else
233
- abs_step = 0;
229
+ if (dac <= dev_vcm->start_current) {
230
+ position = dev_vcm->max_logicalpos;
231
+ } else if ((dac > dev_vcm->start_current) &&
232
+ (dac <= dev_vcm->rated_current)) {
233
+ position = (dac - dev_vcm->start_current) * dev_vcm->max_logicalpos / range;
234
+ position = dev_vcm->max_logicalpos - position;
235
+ } else {
236
+ position = 0;
237
+ }
234238
235
- *cur_pos = abs_step;
239
+ *cur_pos = position;
236240 dev_dbg(&client->dev, "%s: get position %d\n", __func__, *cur_pos);
237241 return 0;
238242
....@@ -245,16 +249,18 @@
245249 static int dw9800w_set_pos(struct dw9800w_device *dev_vcm,
246250 unsigned int dest_pos)
247251 {
248
- int ret;
249
- unsigned int position = 0;
250
- struct i2c_client *client = dev_vcm->client;
252
+ struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd);
253
+ unsigned int position;
254
+ unsigned int range;
251255 u32 is_busy, i;
256
+ int ret;
252257
253
- if (dest_pos >= VCMDRV_MAX_LOG)
258
+ range = dev_vcm->rated_current - dev_vcm->start_current;
259
+ if (dest_pos >= dev_vcm->max_logicalpos)
254260 position = dev_vcm->start_current;
255261 else
256262 position = dev_vcm->start_current +
257
- (dev_vcm->step * (VCMDRV_MAX_LOG - dest_pos));
263
+ (range * (dev_vcm->max_logicalpos - dest_pos) / dev_vcm->max_logicalpos);
258264
259265 if (position > DW9800W_MAX_REG)
260266 position = DW9800W_MAX_REG;
....@@ -304,10 +310,10 @@
304310
305311 if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) {
306312
307
- if (dest_pos > VCMDRV_MAX_LOG) {
313
+ if (dest_pos > dev_vcm->max_logicalpos) {
308314 dev_info(&client->dev,
309315 "%s dest_pos is error. %d > %d\n",
310
- __func__, dest_pos, VCMDRV_MAX_LOG);
316
+ __func__, dest_pos, dev_vcm->max_logicalpos);
311317 return -EINVAL;
312318 }
313319 /* calculate move time */
....@@ -318,7 +324,7 @@
318324 ret = dw9800w_set_pos(dev_vcm, dest_pos);
319325 if (dev_vcm->step_mode == LSC_MODE)
320326 dev_vcm->move_us = ((dev_vcm->vcm_movefull_t * (uint32_t)move_pos) /
321
- VCMDRV_MAX_LOG);
327
+ dev_vcm->max_logicalpos);
322328 else
323329 dev_vcm->move_us = dev_vcm->vcm_movefull_t;
324330
....@@ -376,28 +382,27 @@
376382 static void dw9800w_update_vcm_cfg(struct dw9800w_device *dev_vcm)
377383 {
378384 struct i2c_client *client = dev_vcm->client;
379
- int cur_dist;
380385
381
- if (dev_vcm->max_ma == 0) {
386
+ if (dev_vcm->max_current == 0) {
382387 dev_err(&client->dev, "max current is zero");
383388 return;
384389 }
385390
386
- cur_dist = dev_vcm->vcm_cfg.rated_ma - dev_vcm->vcm_cfg.start_ma;
387
- cur_dist = cur_dist * DW9800W_MAX_REG / dev_vcm->max_ma;
388
- dev_vcm->step = (cur_dist + (VCMDRV_MAX_LOG - 1)) / VCMDRV_MAX_LOG;
391
+ if (dev_vcm->vcm_cfg.rated_ma > dev_vcm->max_current)
392
+ dev_vcm->max_current = DW9800W_MAX_REG;
393
+
389394 dev_vcm->start_current = dev_vcm->vcm_cfg.start_ma *
390
- DW9800W_MAX_REG / dev_vcm->max_ma;
395
+ DW9800W_MAX_REG / dev_vcm->max_current;
391396 dev_vcm->rated_current = dev_vcm->vcm_cfg.rated_ma *
392
- DW9800W_MAX_REG / dev_vcm->max_ma;
397
+ DW9800W_MAX_REG / dev_vcm->max_current;
393398 dev_vcm->step_mode = dev_vcm->vcm_cfg.step_mode;
394399
395400 dev_info(&client->dev,
396
- "vcm_cfg: %d, %d, %d, max_ma %d\n",
401
+ "vcm_cfg: %d, %d, %d, max_current %d\n",
397402 dev_vcm->vcm_cfg.start_ma,
398403 dev_vcm->vcm_cfg.rated_ma,
399404 dev_vcm->vcm_cfg.step_mode,
400
- dev_vcm->max_ma);
405
+ dev_vcm->max_current);
401406 }
402407
403408 static long dw9800w_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
....@@ -406,6 +411,7 @@
406411 struct i2c_client *client = dev_vcm->client;
407412 struct rk_cam_vcm_tim *vcm_tim;
408413 struct rk_cam_vcm_cfg *vcm_cfg;
414
+ unsigned int max_logicalpos;
409415 int ret = 0;
410416
411417 if (cmd == RK_VIDIOC_VCM_TIMEINFO) {
....@@ -441,6 +447,16 @@
441447 dev_vcm->vcm_cfg.rated_ma = vcm_cfg->rated_ma;
442448 dev_vcm->vcm_cfg.step_mode = vcm_cfg->step_mode;
443449 dw9800w_update_vcm_cfg(dev_vcm);
450
+ } else if (cmd == RK_VIDIOC_SET_VCM_MAX_LOGICALPOS) {
451
+ max_logicalpos = *(unsigned int *)arg;
452
+
453
+ if (max_logicalpos > 0) {
454
+ dev_vcm->max_logicalpos = max_logicalpos;
455
+ __v4l2_ctrl_modify_range(dev_vcm->focus,
456
+ 0, dev_vcm->max_logicalpos, 1, dev_vcm->max_logicalpos);
457
+ }
458
+ dev_dbg(&client->dev,
459
+ "max_logicalpos %d\n", max_logicalpos);
444460 } else {
445461 dev_err(&client->dev,
446462 "cmd 0x%x not supported\n", cmd);
....@@ -460,6 +476,7 @@
460476 struct rk_cam_compat_vcm_tim compat_vcm_tim;
461477 struct rk_cam_vcm_tim vcm_tim;
462478 struct rk_cam_vcm_cfg vcm_cfg;
479
+ unsigned int max_logicalpos;
463480 long ret;
464481
465482 if (cmd == RK_VIDIOC_COMPAT_VCM_TIMEINFO) {
....@@ -490,6 +507,12 @@
490507 ret = copy_from_user(&vcm_cfg, up, sizeof(vcm_cfg));
491508 if (!ret)
492509 ret = dw9800w_ioctl(sd, cmd, &vcm_cfg);
510
+ else
511
+ ret = -EFAULT;
512
+ } else if (cmd == RK_VIDIOC_SET_VCM_MAX_LOGICALPOS) {
513
+ ret = copy_from_user(&max_logicalpos, up, sizeof(max_logicalpos));
514
+ if (!ret)
515
+ ret = dw9800w_ioctl(sd, cmd, &max_logicalpos);
493516 else
494517 ret = -EFAULT;
495518 } else {
....@@ -528,8 +551,9 @@
528551
529552 v4l2_ctrl_handler_init(hdl, 1);
530553
531
- v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
532
- 0, VCMDRV_MAX_LOG, 1, 32);
554
+ dev_vcm->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
555
+ 0, dev_vcm->max_logicalpos, 1,
556
+ dev_vcm->max_logicalpos / 2);
533557
534558 if (hdl->error)
535559 dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n",
....@@ -585,7 +609,7 @@
585609 {
586610 struct device_node *np = of_node_get(client->dev.of_node);
587611 struct dw9800w_device *dw9800w_dev;
588
- unsigned int max_ma, start_ma, rated_ma, step_mode;
612
+ unsigned int max_current, start_ma, rated_ma, step_mode;
589613 unsigned int t_src, t_div;
590614 struct v4l2_subdev *sd;
591615 char facing[2];
....@@ -594,14 +618,14 @@
594618 dev_info(&client->dev, "probing...\n");
595619 if (of_property_read_u32(np,
596620 OF_CAMERA_VCMDRV_MAX_CURRENT,
597
- (unsigned int *)&max_ma)) {
598
- max_ma = DW9800W_MAX_CURRENT;
621
+ (unsigned int *)&max_current)) {
622
+ max_current = DW9800W_MAX_CURRENT;
599623 dev_info(&client->dev,
600624 "could not get module %s from dts!\n",
601625 OF_CAMERA_VCMDRV_MAX_CURRENT);
602626 }
603
- if (max_ma == 0)
604
- max_ma = DW9800W_MAX_CURRENT;
627
+ if (max_current == 0)
628
+ max_current = DW9800W_MAX_CURRENT;
605629
606630 if (of_property_read_u32(np,
607631 OF_CAMERA_VCMDRV_START_CURRENT,
....@@ -680,6 +704,7 @@
680704 dw9800w_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
681705 dw9800w_dev->sd.internal_ops = &dw9800w_int_ops;
682706
707
+ dw9800w_dev->max_logicalpos = VCMDRV_MAX_LOG;
683708 ret = dw9800w_init_controls(dw9800w_dev);
684709 if (ret)
685710 goto err_cleanup;
....@@ -704,13 +729,13 @@
704729 if (ret)
705730 dev_err(&client->dev, "v4l2 async register subdev failed\n");
706731
707
- dw9800w_dev->max_ma = max_ma;
732
+ dw9800w_dev->max_current = max_current;
708733 dw9800w_dev->vcm_cfg.start_ma = start_ma;
709734 dw9800w_dev->vcm_cfg.rated_ma = rated_ma;
710735 dw9800w_dev->vcm_cfg.step_mode = step_mode;
711736 dw9800w_update_vcm_cfg(dw9800w_dev);
712737 dw9800w_dev->move_us = 0;
713
- dw9800w_dev->current_related_pos = VCMDRV_MAX_LOG;
738
+ dw9800w_dev->current_related_pos = dw9800w_dev->max_logicalpos;
714739 dw9800w_dev->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
715740 dw9800w_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
716741