Lines Matching +full:ctrl +full:- +full:module
1 // SPDX-License-Identifier: GPL-2.0
10 #include <linux/module.h>
12 #include <linux/rk-camera-module.h>
14 #include <media/v4l2-ctrls.h>
15 #include <media/v4l2-device.h>
74 static inline struct dw9800w_device *to_dw9800w_vcm(struct v4l2_ctrl *ctrl) in to_dw9800w_vcm() argument
76 return container_of(ctrl->handler, struct dw9800w_device, ctrls_vcm); in to_dw9800w_vcm()
93 return -EINVAL; in dw9800w_write_reg()
100 val_i = 4 - len; in dw9800w_write_reg()
106 dev_err(&client->dev, "Failed to write 0x%04x,0x%x\n", reg, val); in dw9800w_write_reg()
107 return -EIO; in dw9800w_write_reg()
123 return -EINVAL; in dw9800w_read_reg()
127 msgs[0].addr = client->addr; in dw9800w_read_reg()
133 msgs[1].addr = client->addr; in dw9800w_read_reg()
136 msgs[1].buf = &data_be_p[4 - len]; in dw9800w_read_reg()
138 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in dw9800w_read_reg()
140 return -EIO; in dw9800w_read_reg()
150 struct i2c_client *client = dev_vcm->client; in dw9800w_move_time_div()
153 switch (dev_vcm->t_div) { in dw9800w_move_time_div()
173 dev_err(&client->dev, in dw9800w_move_time_div()
175 __func__, dev_vcm->t_div); in dw9800w_move_time_div()
184 struct i2c_client *client = dev_vcm->client; in dw9800w_move_time()
187 switch (dev_vcm->step_mode) { in dw9800w_move_time()
189 move_time_us = 252 + dev_vcm->t_src * 4; in dw9800w_move_time()
196 move_time_us = 6300 + dev_vcm->t_src * 100; in dw9800w_move_time()
203 dev_err(&client->dev, in dw9800w_move_time()
205 __func__, dev_vcm->step_mode); in dw9800w_move_time()
209 dev_err(&client->dev, in dw9800w_move_time()
219 struct i2c_client *client = dev_vcm->client; in dw9800w_get_pos()
227 if (abs_step <= dev_vcm->start_current) in dw9800w_get_pos()
229 else if ((abs_step > dev_vcm->start_current) && in dw9800w_get_pos()
230 (abs_step <= dev_vcm->rated_current)) in dw9800w_get_pos()
231 abs_step = (dev_vcm->rated_current - abs_step) / dev_vcm->step; in dw9800w_get_pos()
236 dev_dbg(&client->dev, "%s: get position %d\n", __func__, *cur_pos); in dw9800w_get_pos()
240 dev_err(&client->dev, in dw9800w_get_pos()
250 struct i2c_client *client = dev_vcm->client; in dw9800w_set_pos()
254 position = dev_vcm->start_current; in dw9800w_set_pos()
256 position = dev_vcm->start_current + in dw9800w_set_pos()
257 (dev_vcm->step * (VCMDRV_MAX_LOG - dest_pos)); in dw9800w_set_pos()
262 dev_vcm->current_lens_pos = position; in dw9800w_set_pos()
263 dev_vcm->current_related_pos = dest_pos; in dw9800w_set_pos()
271 ret = dw9800w_write_reg(client, 0x03, 2, dev_vcm->current_lens_pos); in dw9800w_set_pos()
274 dev_info(&client->dev, in dw9800w_set_pos()
275 "%s: set reg val %d\n", __func__, dev_vcm->current_lens_pos); in dw9800w_set_pos()
278 dev_err(&client->dev, in dw9800w_set_pos()
283 static int dw9800w_get_ctrl(struct v4l2_ctrl *ctrl) in dw9800w_get_ctrl() argument
285 struct dw9800w_device *dev_vcm = to_dw9800w_vcm(ctrl); in dw9800w_get_ctrl()
287 if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) in dw9800w_get_ctrl()
288 return dw9800w_get_pos(dev_vcm, &ctrl->val); in dw9800w_get_ctrl()
290 return -EINVAL; in dw9800w_get_ctrl()
293 static int dw9800w_set_ctrl(struct v4l2_ctrl *ctrl) in dw9800w_set_ctrl() argument
295 struct dw9800w_device *dev_vcm = to_dw9800w_vcm(ctrl); in dw9800w_set_ctrl()
296 struct i2c_client *client = dev_vcm->client; in dw9800w_set_ctrl()
297 unsigned int dest_pos = ctrl->val; in dw9800w_set_ctrl()
302 dev_dbg(&client->dev, "ctrl->id: 0x%x, ctrl->val: 0x%x\n", in dw9800w_set_ctrl()
303 ctrl->id, ctrl->val); in dw9800w_set_ctrl()
305 if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) { in dw9800w_set_ctrl()
308 dev_info(&client->dev, in dw9800w_set_ctrl()
311 return -EINVAL; in dw9800w_set_ctrl()
314 move_pos = dev_vcm->current_related_pos - dest_pos; in dw9800w_set_ctrl()
316 move_pos = -move_pos; in dw9800w_set_ctrl()
319 if (dev_vcm->step_mode == LSC_MODE) in dw9800w_set_ctrl()
320 dev_vcm->move_us = ((dev_vcm->vcm_movefull_t * (uint32_t)move_pos) / in dw9800w_set_ctrl()
323 dev_vcm->move_us = dev_vcm->vcm_movefull_t; in dw9800w_set_ctrl()
325 dev_dbg(&client->dev, in dw9800w_set_ctrl()
327 dest_pos, dev_vcm->move_us); in dw9800w_set_ctrl()
329 dev_vcm->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); in dw9800w_set_ctrl()
330 mv_us = dev_vcm->start_move_tv.tv_usec + in dw9800w_set_ctrl()
331 dev_vcm->move_us; in dw9800w_set_ctrl()
333 dev_vcm->end_move_tv.tv_sec = in dw9800w_set_ctrl()
334 dev_vcm->start_move_tv.tv_sec + 1; in dw9800w_set_ctrl()
335 dev_vcm->end_move_tv.tv_usec = mv_us - 1000000; in dw9800w_set_ctrl()
337 dev_vcm->end_move_tv.tv_sec = in dw9800w_set_ctrl()
338 dev_vcm->start_move_tv.tv_sec; in dw9800w_set_ctrl()
339 dev_vcm->end_move_tv.tv_usec = mv_us; in dw9800w_set_ctrl()
355 rval = pm_runtime_get_sync(sd->dev); in dw9800w_open()
357 pm_runtime_put_noidle(sd->dev); in dw9800w_open()
366 pm_runtime_put(sd->dev); in dw9800w_close()
378 struct i2c_client *client = dev_vcm->client; in dw9800w_update_vcm_cfg()
381 if (dev_vcm->max_ma == 0) { in dw9800w_update_vcm_cfg()
382 dev_err(&client->dev, "max current is zero"); in dw9800w_update_vcm_cfg()
386 cur_dist = dev_vcm->vcm_cfg.rated_ma - dev_vcm->vcm_cfg.start_ma; in dw9800w_update_vcm_cfg()
387 cur_dist = cur_dist * DW9800W_MAX_REG / dev_vcm->max_ma; in dw9800w_update_vcm_cfg()
388 dev_vcm->step = (cur_dist + (VCMDRV_MAX_LOG - 1)) / VCMDRV_MAX_LOG; in dw9800w_update_vcm_cfg()
389 dev_vcm->start_current = dev_vcm->vcm_cfg.start_ma * in dw9800w_update_vcm_cfg()
390 DW9800W_MAX_REG / dev_vcm->max_ma; in dw9800w_update_vcm_cfg()
391 dev_vcm->rated_current = dev_vcm->vcm_cfg.rated_ma * in dw9800w_update_vcm_cfg()
392 DW9800W_MAX_REG / dev_vcm->max_ma; in dw9800w_update_vcm_cfg()
393 dev_vcm->step_mode = dev_vcm->vcm_cfg.step_mode; in dw9800w_update_vcm_cfg()
395 dev_info(&client->dev, in dw9800w_update_vcm_cfg()
397 dev_vcm->vcm_cfg.start_ma, in dw9800w_update_vcm_cfg()
398 dev_vcm->vcm_cfg.rated_ma, in dw9800w_update_vcm_cfg()
399 dev_vcm->vcm_cfg.step_mode, in dw9800w_update_vcm_cfg()
400 dev_vcm->max_ma); in dw9800w_update_vcm_cfg()
406 struct i2c_client *client = dev_vcm->client; in dw9800w_ioctl()
414 vcm_tim->vcm_start_t.tv_sec = dev_vcm->start_move_tv.tv_sec; in dw9800w_ioctl()
415 vcm_tim->vcm_start_t.tv_usec = in dw9800w_ioctl()
416 dev_vcm->start_move_tv.tv_usec; in dw9800w_ioctl()
417 vcm_tim->vcm_end_t.tv_sec = dev_vcm->end_move_tv.tv_sec; in dw9800w_ioctl()
418 vcm_tim->vcm_end_t.tv_usec = dev_vcm->end_move_tv.tv_usec; in dw9800w_ioctl()
420 dev_dbg(&client->dev, "dw9800w_get_move_res 0x%lx, 0x%lx, 0x%lx, 0x%lx\n", in dw9800w_ioctl()
421 vcm_tim->vcm_start_t.tv_sec, in dw9800w_ioctl()
422 vcm_tim->vcm_start_t.tv_usec, in dw9800w_ioctl()
423 vcm_tim->vcm_end_t.tv_sec, in dw9800w_ioctl()
424 vcm_tim->vcm_end_t.tv_usec); in dw9800w_ioctl()
428 vcm_cfg->start_ma = dev_vcm->vcm_cfg.start_ma; in dw9800w_ioctl()
429 vcm_cfg->rated_ma = dev_vcm->vcm_cfg.rated_ma; in dw9800w_ioctl()
430 vcm_cfg->step_mode = dev_vcm->vcm_cfg.step_mode; in dw9800w_ioctl()
434 if (vcm_cfg->start_ma == 0 && vcm_cfg->rated_ma == 0) { in dw9800w_ioctl()
435 dev_err(&client->dev, in dw9800w_ioctl()
437 vcm_cfg->start_ma, vcm_cfg->rated_ma); in dw9800w_ioctl()
438 return -EINVAL; in dw9800w_ioctl()
440 dev_vcm->vcm_cfg.start_ma = vcm_cfg->start_ma; in dw9800w_ioctl()
441 dev_vcm->vcm_cfg.rated_ma = vcm_cfg->rated_ma; in dw9800w_ioctl()
442 dev_vcm->vcm_cfg.step_mode = vcm_cfg->step_mode; in dw9800w_ioctl()
445 dev_err(&client->dev, in dw9800w_ioctl()
447 return -EINVAL; in dw9800w_ioctl()
458 struct i2c_client *client = dev_vcm->client; in dw9800w_compat_ioctl32()
475 &p32->vcm_start_t.tv_sec); in dw9800w_compat_ioctl32()
477 &p32->vcm_start_t.tv_usec); in dw9800w_compat_ioctl32()
479 &p32->vcm_end_t.tv_sec); in dw9800w_compat_ioctl32()
481 &p32->vcm_end_t.tv_usec); in dw9800w_compat_ioctl32()
487 ret = -EFAULT; in dw9800w_compat_ioctl32()
494 ret = -EFAULT; in dw9800w_compat_ioctl32()
496 dev_err(&client->dev, in dw9800w_compat_ioctl32()
498 return -EINVAL; in dw9800w_compat_ioctl32()
518 v4l2_device_unregister_subdev(&dw9800w_dev->sd); in dw9800w_subdev_cleanup()
519 v4l2_device_unregister(&dw9800w_dev->vdev); in dw9800w_subdev_cleanup()
520 v4l2_ctrl_handler_free(&dw9800w_dev->ctrls_vcm); in dw9800w_subdev_cleanup()
521 media_entity_cleanup(&dw9800w_dev->sd.entity); in dw9800w_subdev_cleanup()
526 struct v4l2_ctrl_handler *hdl = &dev_vcm->ctrls_vcm; in dw9800w_init_controls()
534 if (hdl->error) in dw9800w_init_controls()
535 dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n", in dw9800w_init_controls()
536 __func__, hdl->error); in dw9800w_init_controls()
537 dev_vcm->sd.ctrl_handler = hdl; in dw9800w_init_controls()
538 return hdl->error; in dw9800w_init_controls()
543 if (dw9800w_dev->power_gpio) in __dw9800w_set_power()
544 gpiod_direction_output(dw9800w_dev->power_gpio, on); in __dw9800w_set_power()
553 struct i2c_client *client = dw9800w_dev->client; in dw9800w_check_id()
554 struct device *dev = &client->dev; in dw9800w_check_id()
561 return -ENODEV; in dw9800w_check_id()
564 dev_info(&dw9800w_dev->client->dev, in dw9800w_check_id()
579 dev_err(&client->dev, "probe init failed with error %d\n", ret); in dw9800w_probe_init()
580 return -1; in dw9800w_probe_init()
586 struct device_node *np = of_node_get(client->dev.of_node); in dw9800w_probe()
594 dev_info(&client->dev, "probing...\n"); in dw9800w_probe()
599 dev_info(&client->dev, in dw9800w_probe()
600 "could not get module %s from dts!\n", in dw9800w_probe()
610 dev_info(&client->dev, in dw9800w_probe()
611 "could not get module %s from dts!\n", in dw9800w_probe()
618 dev_info(&client->dev, in dw9800w_probe()
619 "could not get module %s from dts!\n", in dw9800w_probe()
626 dev_info(&client->dev, in dw9800w_probe()
627 "could not get module %s from dts!\n", in dw9800w_probe()
635 dev_info(&client->dev, in dw9800w_probe()
636 "could not get module %s from dts!\n", in dw9800w_probe()
644 dev_info(&client->dev, in dw9800w_probe()
645 "could not get module %s from dts!\n", in dw9800w_probe()
649 dw9800w_dev = devm_kzalloc(&client->dev, sizeof(*dw9800w_dev), in dw9800w_probe()
652 return -ENOMEM; in dw9800w_probe()
655 &dw9800w_dev->module_index); in dw9800w_probe()
657 &dw9800w_dev->module_facing); in dw9800w_probe()
659 dev_err(&client->dev, in dw9800w_probe()
660 "could not get module information!\n"); in dw9800w_probe()
661 return -EINVAL; in dw9800w_probe()
663 dw9800w_dev->client = client; in dw9800w_probe()
664 dw9800w_dev->power_gpio = devm_gpiod_get(&client->dev, in dw9800w_probe()
666 if (IS_ERR(dw9800w_dev->power_gpio)) { in dw9800w_probe()
667 dw9800w_dev->power_gpio = NULL; in dw9800w_probe()
668 dev_warn(&client->dev, in dw9800w_probe()
669 "Failed to get power-gpios, maybe no use\n"); in dw9800w_probe()
679 v4l2_i2c_subdev_init(&dw9800w_dev->sd, client, &dw9800w_ops); in dw9800w_probe()
680 dw9800w_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in dw9800w_probe()
681 dw9800w_dev->sd.internal_ops = &dw9800w_int_ops; in dw9800w_probe()
687 ret = media_entity_pads_init(&dw9800w_dev->sd.entity, 0, NULL); in dw9800w_probe()
691 sd = &dw9800w_dev->sd; in dw9800w_probe()
692 sd->entity.function = MEDIA_ENT_F_LENS; in dw9800w_probe()
695 if (strcmp(dw9800w_dev->module_facing, "back") == 0) in dw9800w_probe()
700 snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", in dw9800w_probe()
701 dw9800w_dev->module_index, facing, in dw9800w_probe()
702 DW9800W_NAME, dev_name(sd->dev)); in dw9800w_probe()
705 dev_err(&client->dev, "v4l2 async register subdev failed\n"); in dw9800w_probe()
707 dw9800w_dev->max_ma = max_ma; in dw9800w_probe()
708 dw9800w_dev->vcm_cfg.start_ma = start_ma; in dw9800w_probe()
709 dw9800w_dev->vcm_cfg.rated_ma = rated_ma; in dw9800w_probe()
710 dw9800w_dev->vcm_cfg.step_mode = step_mode; in dw9800w_probe()
712 dw9800w_dev->move_us = 0; in dw9800w_probe()
713 dw9800w_dev->current_related_pos = VCMDRV_MAX_LOG; in dw9800w_probe()
714 dw9800w_dev->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); in dw9800w_probe()
715 dw9800w_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); in dw9800w_probe()
717 dw9800w_dev->t_src = t_src; in dw9800w_probe()
718 dw9800w_dev->t_div = t_div; in dw9800w_probe()
721 mutex_init(&dw9800w_dev->lock); in dw9800w_probe()
723 dw9800w_dev->vcm_movefull_t = in dw9800w_probe()
725 pm_runtime_set_active(&client->dev); in dw9800w_probe()
726 pm_runtime_enable(&client->dev); in dw9800w_probe()
727 pm_runtime_idle(&client->dev); in dw9800w_probe()
729 dev_info(&client->dev, "probing successful\n"); in dw9800w_probe()
737 dev_err(&client->dev, "Probe failed: %d\n", ret); in dw9800w_probe()
746 mutex_destroy(&dw9800w_dev->lock); in dw9800w_remove()
747 pm_runtime_disable(&client->dev); in dw9800w_remove()
769 if (dev_vcm->step_mode != DIRECT_MODE && in dw9800w_init()
770 dev_vcm->step_mode != LSC_MODE) in dw9800w_init()
775 switch (dev_vcm->step_mode) { in dw9800w_init()
780 mode_val |= dev_vcm->step_mode << 6; in dw9800w_init()
788 mode_val |= ((dev_vcm->t_div >> 2) & 0x01); in dw9800w_init()
789 algo_time = dev_vcm->t_div << 6 | dev_vcm->t_src; in dw9800w_init()
800 dev_err(&client->dev, "init failed with error %d\n", ret); in dw9800w_init()
801 return -1; in dw9800w_init()
812 dev_err(&client->dev, "failed to set power down mode!\n"); in dw9800w_vcm_suspend()
823 dw9800w_set_pos(dev_vcm, dev_vcm->current_related_pos); in dw9800w_vcm_resume()