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>
69 static inline struct aw8601_device *to_aw8601_vcm(struct v4l2_ctrl *ctrl) in to_aw8601_vcm() argument
71 return container_of(ctrl->handler, struct aw8601_device, ctrls_vcm); in to_aw8601_vcm()
88 return -EINVAL; in aw8601_write_reg()
95 val_i = 4 - len; in aw8601_write_reg()
101 dev_err(&client->dev, "Failed to write 0x%04x,0x%x\n", reg, val); in aw8601_write_reg()
102 return -EIO; in aw8601_write_reg()
118 return -EINVAL; in aw8601_read_reg()
122 msgs[0].addr = client->addr; in aw8601_read_reg()
128 msgs[1].addr = client->addr; in aw8601_read_reg()
131 msgs[1].buf = &data_be_p[4 - len]; in aw8601_read_reg()
133 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in aw8601_read_reg()
135 return -EIO; in aw8601_read_reg()
145 struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd); in aw8601_move_time_div()
148 switch (dev_vcm->t_div) { in aw8601_move_time_div()
168 dev_err(&client->dev, in aw8601_move_time_div()
170 __func__, dev_vcm->t_div); in aw8601_move_time_div()
179 struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd); in aw8601_move_time()
182 switch (dev_vcm->step_mode) { in aw8601_move_time()
184 move_time_us = 252 + dev_vcm->t_src * 4; in aw8601_move_time()
191 move_time_us = 6300 + dev_vcm->t_src * 100; in aw8601_move_time()
198 dev_err(&client->dev, in aw8601_move_time()
200 __func__, dev_vcm->step_mode); in aw8601_move_time()
210 struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd); in aw8601_get_pos()
214 range = dev_vcm->rated_current - dev_vcm->start_current; in aw8601_get_pos()
219 if (abs_step <= dev_vcm->start_current) { in aw8601_get_pos()
220 abs_step = dev_vcm->max_logicalpos; in aw8601_get_pos()
221 } else if ((abs_step > dev_vcm->start_current) && in aw8601_get_pos()
222 (abs_step <= dev_vcm->rated_current)) { in aw8601_get_pos()
223 abs_step = (abs_step - dev_vcm->start_current) * dev_vcm->max_logicalpos / range; in aw8601_get_pos()
224 abs_step = dev_vcm->max_logicalpos - abs_step; in aw8601_get_pos()
230 dev_dbg(&client->dev, "%s: get position %d\n", __func__, *cur_pos); in aw8601_get_pos()
234 dev_err(&client->dev, in aw8601_get_pos()
244 struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd); in aw8601_set_pos()
248 range = dev_vcm->rated_current - dev_vcm->start_current; in aw8601_set_pos()
249 if (dest_pos >= dev_vcm->max_logicalpos) in aw8601_set_pos()
250 position = dev_vcm->start_current; in aw8601_set_pos()
252 position = dev_vcm->start_current + in aw8601_set_pos()
253 (range * (dev_vcm->max_logicalpos - dest_pos) / dev_vcm->max_logicalpos); in aw8601_set_pos()
258 dev_vcm->current_lens_pos = position; in aw8601_set_pos()
259 dev_vcm->current_related_pos = dest_pos; in aw8601_set_pos()
266 ret = aw8601_write_reg(client, 0x03, 2, dev_vcm->current_lens_pos); in aw8601_set_pos()
269 dev_dbg(&client->dev, in aw8601_set_pos()
270 "%s: set reg val %d\n", __func__, dev_vcm->current_lens_pos); in aw8601_set_pos()
273 dev_err(&client->dev, in aw8601_set_pos()
278 static int aw8601_get_ctrl(struct v4l2_ctrl *ctrl) in aw8601_get_ctrl() argument
280 struct aw8601_device *dev_vcm = to_aw8601_vcm(ctrl); in aw8601_get_ctrl()
282 if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) in aw8601_get_ctrl()
283 return aw8601_get_pos(dev_vcm, &ctrl->val); in aw8601_get_ctrl()
285 return -EINVAL; in aw8601_get_ctrl()
288 static int aw8601_set_ctrl(struct v4l2_ctrl *ctrl) in aw8601_set_ctrl() argument
290 struct aw8601_device *dev_vcm = to_aw8601_vcm(ctrl); in aw8601_set_ctrl()
291 struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd); in aw8601_set_ctrl()
292 unsigned int dest_pos = ctrl->val; in aw8601_set_ctrl()
297 if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) { in aw8601_set_ctrl()
298 if (dest_pos > dev_vcm->max_logicalpos) { in aw8601_set_ctrl()
299 dev_info(&client->dev, in aw8601_set_ctrl()
301 __func__, dest_pos, dev_vcm->max_logicalpos); in aw8601_set_ctrl()
302 return -EINVAL; in aw8601_set_ctrl()
305 move_pos = dev_vcm->current_related_pos - dest_pos; in aw8601_set_ctrl()
307 move_pos = -move_pos; in aw8601_set_ctrl()
311 if (dev_vcm->step_mode == LSC_MODE) in aw8601_set_ctrl()
312 dev_vcm->move_us = ((dev_vcm->vcm_movefull_t * (uint32_t)move_pos) / in aw8601_set_ctrl()
313 dev_vcm->max_logicalpos); in aw8601_set_ctrl()
315 dev_vcm->move_us = dev_vcm->vcm_movefull_t; in aw8601_set_ctrl()
317 dev_dbg(&client->dev, in aw8601_set_ctrl()
319 dest_pos, dev_vcm->move_us); in aw8601_set_ctrl()
321 dev_vcm->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); in aw8601_set_ctrl()
322 mv_us = dev_vcm->start_move_tv.tv_usec + in aw8601_set_ctrl()
323 dev_vcm->move_us; in aw8601_set_ctrl()
325 dev_vcm->end_move_tv.tv_sec = in aw8601_set_ctrl()
326 dev_vcm->start_move_tv.tv_sec + 1; in aw8601_set_ctrl()
327 dev_vcm->end_move_tv.tv_usec = mv_us - 1000000; in aw8601_set_ctrl()
329 dev_vcm->end_move_tv.tv_sec = in aw8601_set_ctrl()
330 dev_vcm->start_move_tv.tv_sec; in aw8601_set_ctrl()
331 dev_vcm->end_move_tv.tv_usec = mv_us; in aw8601_set_ctrl()
347 rval = pm_runtime_get_sync(sd->dev); in aw8601_open()
349 pm_runtime_put_noidle(sd->dev); in aw8601_open()
358 pm_runtime_put(sd->dev); in aw8601_close()
370 struct i2c_client *client = v4l2_get_subdevdata(&dev_vcm->sd); in aw8601_update_vcm_cfg()
372 if (dev_vcm->max_ma == 0) { in aw8601_update_vcm_cfg()
373 dev_err(&client->dev, "max current is zero"); in aw8601_update_vcm_cfg()
377 dev_vcm->start_current = dev_vcm->vcm_cfg.start_ma * in aw8601_update_vcm_cfg()
378 AW8601_MAX_REG / dev_vcm->max_ma; in aw8601_update_vcm_cfg()
379 dev_vcm->rated_current = dev_vcm->vcm_cfg.rated_ma * in aw8601_update_vcm_cfg()
380 AW8601_MAX_REG / dev_vcm->max_ma; in aw8601_update_vcm_cfg()
381 dev_vcm->step_mode = dev_vcm->vcm_cfg.step_mode; in aw8601_update_vcm_cfg()
383 dev_info(&client->dev, in aw8601_update_vcm_cfg()
385 dev_vcm->vcm_cfg.start_ma, in aw8601_update_vcm_cfg()
386 dev_vcm->vcm_cfg.rated_ma, in aw8601_update_vcm_cfg()
387 dev_vcm->vcm_cfg.step_mode, in aw8601_update_vcm_cfg()
388 dev_vcm->max_ma); in aw8601_update_vcm_cfg()
403 vcm_tim->vcm_start_t.tv_sec = dev_vcm->start_move_tv.tv_sec; in aw8601_ioctl()
404 vcm_tim->vcm_start_t.tv_usec = in aw8601_ioctl()
405 dev_vcm->start_move_tv.tv_usec; in aw8601_ioctl()
406 vcm_tim->vcm_end_t.tv_sec = dev_vcm->end_move_tv.tv_sec; in aw8601_ioctl()
407 vcm_tim->vcm_end_t.tv_usec = dev_vcm->end_move_tv.tv_usec; in aw8601_ioctl()
409 dev_dbg(&client->dev, "aw8601_get_move_res 0x%lx, 0x%lx, 0x%lx, 0x%lx\n", in aw8601_ioctl()
410 vcm_tim->vcm_start_t.tv_sec, in aw8601_ioctl()
411 vcm_tim->vcm_start_t.tv_usec, in aw8601_ioctl()
412 vcm_tim->vcm_end_t.tv_sec, in aw8601_ioctl()
413 vcm_tim->vcm_end_t.tv_usec); in aw8601_ioctl()
417 vcm_cfg->start_ma = dev_vcm->vcm_cfg.start_ma; in aw8601_ioctl()
418 vcm_cfg->rated_ma = dev_vcm->vcm_cfg.rated_ma; in aw8601_ioctl()
419 vcm_cfg->step_mode = dev_vcm->vcm_cfg.step_mode; in aw8601_ioctl()
423 if (vcm_cfg->start_ma == 0 && vcm_cfg->rated_ma == 0) { in aw8601_ioctl()
424 dev_err(&client->dev, in aw8601_ioctl()
426 vcm_cfg->start_ma, vcm_cfg->rated_ma); in aw8601_ioctl()
427 return -EINVAL; in aw8601_ioctl()
429 dev_vcm->vcm_cfg.start_ma = vcm_cfg->start_ma; in aw8601_ioctl()
430 dev_vcm->vcm_cfg.rated_ma = vcm_cfg->rated_ma; in aw8601_ioctl()
431 dev_vcm->vcm_cfg.step_mode = vcm_cfg->step_mode; in aw8601_ioctl()
437 dev_vcm->max_logicalpos = max_logicalpos; in aw8601_ioctl()
438 __v4l2_ctrl_modify_range(dev_vcm->focus, in aw8601_ioctl()
439 0, dev_vcm->max_logicalpos, 1, dev_vcm->max_logicalpos); in aw8601_ioctl()
441 dev_dbg(&client->dev, in aw8601_ioctl()
444 dev_err(&client->dev, in aw8601_ioctl()
446 return -EINVAL; in aw8601_ioctl()
474 &p32->vcm_start_t.tv_sec); in aw8601_compat_ioctl32()
476 &p32->vcm_start_t.tv_usec); in aw8601_compat_ioctl32()
478 &p32->vcm_end_t.tv_sec); in aw8601_compat_ioctl32()
480 &p32->vcm_end_t.tv_usec); in aw8601_compat_ioctl32()
486 ret = -EFAULT; in aw8601_compat_ioctl32()
493 ret = -EFAULT; in aw8601_compat_ioctl32()
499 ret = -EFAULT; in aw8601_compat_ioctl32()
501 dev_err(&client->dev, in aw8601_compat_ioctl32()
503 return -EINVAL; in aw8601_compat_ioctl32()
523 v4l2_device_unregister_subdev(&aw8601_dev->sd); in aw8601_subdev_cleanup()
524 v4l2_device_unregister(&aw8601_dev->vdev); in aw8601_subdev_cleanup()
525 v4l2_ctrl_handler_free(&aw8601_dev->ctrls_vcm); in aw8601_subdev_cleanup()
526 media_entity_cleanup(&aw8601_dev->sd.entity); in aw8601_subdev_cleanup()
531 struct v4l2_ctrl_handler *hdl = &dev_vcm->ctrls_vcm; in aw8601_init_controls()
536 dev_vcm->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, in aw8601_init_controls()
537 0, dev_vcm->max_logicalpos, 1, 0); in aw8601_init_controls()
539 if (hdl->error) in aw8601_init_controls()
540 dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n", in aw8601_init_controls()
541 __func__, hdl->error); in aw8601_init_controls()
542 dev_vcm->sd.ctrl_handler = hdl; in aw8601_init_controls()
543 return hdl->error; in aw8601_init_controls()
549 struct device_node *np = of_node_get(client->dev.of_node); in aw8601_probe()
557 dev_info(&client->dev, "probing...\n"); in aw8601_probe()
562 dev_info(&client->dev, in aw8601_probe()
563 "could not get module %s from dts!\n", in aw8601_probe()
573 dev_info(&client->dev, in aw8601_probe()
574 "could not get module %s from dts!\n", in aw8601_probe()
581 dev_info(&client->dev, in aw8601_probe()
582 "could not get module %s from dts!\n", in aw8601_probe()
589 dev_info(&client->dev, in aw8601_probe()
590 "could not get module %s from dts!\n", in aw8601_probe()
598 dev_info(&client->dev, in aw8601_probe()
599 "could not get module %s from dts!\n", in aw8601_probe()
607 dev_info(&client->dev, in aw8601_probe()
608 "could not get module %s from dts!\n", in aw8601_probe()
612 aw8601_dev = devm_kzalloc(&client->dev, sizeof(*aw8601_dev), in aw8601_probe()
615 return -ENOMEM; in aw8601_probe()
618 &aw8601_dev->module_index); in aw8601_probe()
620 &aw8601_dev->module_facing); in aw8601_probe()
622 dev_err(&client->dev, in aw8601_probe()
623 "could not get module information!\n"); in aw8601_probe()
624 return -EINVAL; in aw8601_probe()
627 v4l2_i2c_subdev_init(&aw8601_dev->sd, client, &aw8601_ops); in aw8601_probe()
628 aw8601_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in aw8601_probe()
629 aw8601_dev->sd.internal_ops = &aw8601_int_ops; in aw8601_probe()
631 aw8601_dev->max_logicalpos = VCMDRV_MAX_LOG; in aw8601_probe()
636 ret = media_entity_pads_init(&aw8601_dev->sd.entity, 0, NULL); in aw8601_probe()
640 sd = &aw8601_dev->sd; in aw8601_probe()
641 sd->entity.function = MEDIA_ENT_F_LENS; in aw8601_probe()
644 if (strcmp(aw8601_dev->module_facing, "back") == 0) in aw8601_probe()
649 snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", in aw8601_probe()
650 aw8601_dev->module_index, facing, in aw8601_probe()
651 AW8601_NAME, dev_name(sd->dev)); in aw8601_probe()
654 dev_err(&client->dev, "v4l2 async register subdev failed\n"); in aw8601_probe()
656 aw8601_dev->max_ma = max_ma; in aw8601_probe()
657 aw8601_dev->vcm_cfg.start_ma = start_ma; in aw8601_probe()
658 aw8601_dev->vcm_cfg.rated_ma = rated_ma; in aw8601_probe()
659 aw8601_dev->vcm_cfg.step_mode = step_mode; in aw8601_probe()
661 aw8601_dev->move_us = 0; in aw8601_probe()
662 aw8601_dev->current_related_pos = aw8601_dev->max_logicalpos; in aw8601_probe()
663 aw8601_dev->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); in aw8601_probe()
664 aw8601_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); in aw8601_probe()
666 aw8601_dev->t_src = t_src; in aw8601_probe()
667 aw8601_dev->t_div = t_div; in aw8601_probe()
669 aw8601_dev->vcm_movefull_t = in aw8601_probe()
671 pm_runtime_set_active(&client->dev); in aw8601_probe()
672 pm_runtime_enable(&client->dev); in aw8601_probe()
673 pm_runtime_idle(&client->dev); in aw8601_probe()
675 dev_info(&client->dev, "probing successful\n"); in aw8601_probe()
681 dev_err(&client->dev, "Probe failed: %d\n", ret); in aw8601_probe()
690 pm_runtime_disable(&client->dev); in aw8601_remove()
716 if (dev_vcm->step_mode != DIRECT_MODE && in aw8601_init()
717 dev_vcm->step_mode != LSC_MODE) in aw8601_init()
722 switch (dev_vcm->step_mode) { in aw8601_init()
727 mode_val |= dev_vcm->step_mode << 6; in aw8601_init()
735 mode_val |= ((dev_vcm->t_div >> 2) & 0x01); in aw8601_init()
736 algo_time = dev_vcm->t_div << 6 | dev_vcm->t_src; in aw8601_init()
747 dev_err(&client->dev, "failed with error %d\n", ret); in aw8601_init()
748 return -1; in aw8601_init()
763 aw8601_set_pos(dev_vcm, dev_vcm->current_related_pos); in aw8601_vcm_resume()