Lines Matching +full:sensor +full:- +full:gain

1 // SPDX-License-Identifier: GPL-2.0-only
3 * OmniVision ov9282 Camera Sensor Driver
15 #include <media/v4l2-ctrls.h>
16 #include <media/v4l2-fwnode.h>
17 #include <media/v4l2-subdev.h>
38 /* Analog gain control */
59 * struct ov9282_reg - ov9282 sensor register
69 * struct ov9282_reg_list - ov9282 sensor register list
79 * struct ov9282_mode - ov9282 sensor mode structure
87 * @pclk: Sensor pixel clock
89 * @reg_list: Register list for sensor mode
105 * struct ov9282 - ov9282 sensor device structure
108 * @sd: V4L2 sub-device
110 * @reset_gpio: Sensor reset gpio
111 * @inclk: Sensor input clock
118 * @again_ctrl: Pointer to analog gain control
120 * @cur_mode: Pointer to current selected sensor mode
121 * @mutex: Mutex for serializing sensor controls
150 /* Sensor mode registers */
253 /* Supported sensor mode configurations */
271 * to_ov9282() - ov9282 V4L2 sub-device to ov9282 device.
272 * @subdev: pointer to ov9282 V4L2 sub-device
282 * ov9282_read_reg() - Read registers.
292 struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd); in ov9282_read_reg()
299 return -EINVAL; in ov9282_read_reg()
304 msgs[0].addr = client->addr; in ov9282_read_reg()
310 msgs[1].addr = client->addr; in ov9282_read_reg()
313 msgs[1].buf = &data_buf[4 - len]; in ov9282_read_reg()
315 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in ov9282_read_reg()
317 return -EIO; in ov9282_read_reg()
325 * ov9282_write_reg() - Write register
335 struct i2c_client *client = v4l2_get_subdevdata(&ov9282->sd); in ov9282_write_reg()
339 return -EINVAL; in ov9282_write_reg()
342 put_unaligned_be32(val << (8 * (4 - len)), buf + 2); in ov9282_write_reg()
344 return -EIO; in ov9282_write_reg()
350 * ov9282_write_regs() - Write a list of registers
373 * ov9282_update_controls() - Update control ranges based on streaming mode
375 * @mode: pointer to ov9282_mode sensor mode
384 ret = __v4l2_ctrl_s_ctrl(ov9282->link_freq_ctrl, mode->link_freq_idx); in ov9282_update_controls()
388 ret = __v4l2_ctrl_s_ctrl(ov9282->hblank_ctrl, mode->hblank); in ov9282_update_controls()
392 return __v4l2_ctrl_modify_range(ov9282->vblank_ctrl, mode->vblank_min, in ov9282_update_controls()
393 mode->vblank_max, 1, mode->vblank); in ov9282_update_controls()
397 * ov9282_update_exp_gain() - Set updated exposure and gain
400 * @gain: updated analog gain value
404 static int ov9282_update_exp_gain(struct ov9282 *ov9282, u32 exposure, u32 gain) in ov9282_update_exp_gain() argument
409 lpfr = ov9282->vblank + ov9282->cur_mode->height; in ov9282_update_exp_gain()
411 dev_dbg(ov9282->dev, "Set exp %u, analog gain %u, lpfr %u", in ov9282_update_exp_gain()
412 exposure, gain, lpfr); in ov9282_update_exp_gain()
426 ret = ov9282_write_reg(ov9282, OV9282_REG_AGAIN, 1, gain); in ov9282_update_exp_gain()
435 * ov9282_set_ctrl() - Set subdevice control
439 * - V4L2_CID_VBLANK
440 * - cluster controls:
441 * - V4L2_CID_ANALOGUE_GAIN
442 * - V4L2_CID_EXPOSURE
449 container_of(ctrl->handler, struct ov9282, ctrl_handler); in ov9282_set_ctrl()
454 switch (ctrl->id) { in ov9282_set_ctrl()
456 ov9282->vblank = ov9282->vblank_ctrl->val; in ov9282_set_ctrl()
458 dev_dbg(ov9282->dev, "Received vblank %u, new lpfr %u", in ov9282_set_ctrl()
459 ov9282->vblank, in ov9282_set_ctrl()
460 ov9282->vblank + ov9282->cur_mode->height); in ov9282_set_ctrl()
462 ret = __v4l2_ctrl_modify_range(ov9282->exp_ctrl, in ov9282_set_ctrl()
464 ov9282->vblank + in ov9282_set_ctrl()
465 ov9282->cur_mode->height - in ov9282_set_ctrl()
470 /* Set controls only if sensor is in power on state */ in ov9282_set_ctrl()
471 if (!pm_runtime_get_if_in_use(ov9282->dev)) in ov9282_set_ctrl()
474 exposure = ctrl->val; in ov9282_set_ctrl()
475 analog_gain = ov9282->again_ctrl->val; in ov9282_set_ctrl()
477 dev_dbg(ov9282->dev, "Received exp %u, analog gain %u", in ov9282_set_ctrl()
482 pm_runtime_put(ov9282->dev); in ov9282_set_ctrl()
486 dev_err(ov9282->dev, "Invalid control %d", ctrl->id); in ov9282_set_ctrl()
487 ret = -EINVAL; in ov9282_set_ctrl()
499 * ov9282_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
500 * @sd: pointer to ov9282 V4L2 sub-device structure
501 * @sd_state: V4L2 sub-device configuration
502 * @code: V4L2 sub-device code enumeration need to be filled
510 if (code->index > 0) in ov9282_enum_mbus_code()
511 return -EINVAL; in ov9282_enum_mbus_code()
513 code->code = supported_mode.code; in ov9282_enum_mbus_code()
519 * ov9282_enum_frame_size() - Enumerate V4L2 sub-device frame sizes
520 * @sd: pointer to ov9282 V4L2 sub-device structure
521 * @sd_state: V4L2 sub-device configuration
522 * @fsize: V4L2 sub-device size enumeration need to be filled
530 if (fsize->index > 0) in ov9282_enum_frame_size()
531 return -EINVAL; in ov9282_enum_frame_size()
533 if (fsize->code != supported_mode.code) in ov9282_enum_frame_size()
534 return -EINVAL; in ov9282_enum_frame_size()
536 fsize->min_width = supported_mode.width; in ov9282_enum_frame_size()
537 fsize->max_width = fsize->min_width; in ov9282_enum_frame_size()
538 fsize->min_height = supported_mode.height; in ov9282_enum_frame_size()
539 fsize->max_height = fsize->min_height; in ov9282_enum_frame_size()
545 * ov9282_fill_pad_format() - Fill subdevice pad format
546 * from selected sensor mode
548 * @mode: pointer to ov9282_mode sensor mode
549 * @fmt: V4L2 sub-device format need to be filled
555 fmt->format.width = mode->width; in ov9282_fill_pad_format()
556 fmt->format.height = mode->height; in ov9282_fill_pad_format()
557 fmt->format.code = mode->code; in ov9282_fill_pad_format()
558 fmt->format.field = V4L2_FIELD_NONE; in ov9282_fill_pad_format()
559 fmt->format.colorspace = V4L2_COLORSPACE_RAW; in ov9282_fill_pad_format()
560 fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in ov9282_fill_pad_format()
561 fmt->format.quantization = V4L2_QUANTIZATION_DEFAULT; in ov9282_fill_pad_format()
562 fmt->format.xfer_func = V4L2_XFER_FUNC_NONE; in ov9282_fill_pad_format()
566 * ov9282_get_pad_format() - Get subdevice pad format
567 * @sd: pointer to ov9282 V4L2 sub-device structure
568 * @sd_state: V4L2 sub-device configuration
569 * @fmt: V4L2 sub-device format need to be set
579 mutex_lock(&ov9282->mutex); in ov9282_get_pad_format()
581 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in ov9282_get_pad_format()
584 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); in ov9282_get_pad_format()
585 fmt->format = *framefmt; in ov9282_get_pad_format()
587 ov9282_fill_pad_format(ov9282, ov9282->cur_mode, fmt); in ov9282_get_pad_format()
590 mutex_unlock(&ov9282->mutex); in ov9282_get_pad_format()
596 * ov9282_set_pad_format() - Set subdevice pad format
597 * @sd: pointer to ov9282 V4L2 sub-device structure
598 * @sd_state: V4L2 sub-device configuration
599 * @fmt: V4L2 sub-device format need to be set
611 mutex_lock(&ov9282->mutex); in ov9282_set_pad_format()
616 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in ov9282_set_pad_format()
619 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); in ov9282_set_pad_format()
620 *framefmt = fmt->format; in ov9282_set_pad_format()
624 ov9282->cur_mode = mode; in ov9282_set_pad_format()
627 mutex_unlock(&ov9282->mutex); in ov9282_set_pad_format()
633 * ov9282_init_pad_cfg() - Initialize sub-device pad configuration
634 * @sd: pointer to ov9282 V4L2 sub-device structure
635 * @sd_state: V4L2 sub-device configuration
652 * ov9282_start_streaming() - Start sensor stream
662 /* Write sensor mode registers */ in ov9282_start_streaming()
663 reg_list = &ov9282->cur_mode->reg_list; in ov9282_start_streaming()
664 ret = ov9282_write_regs(ov9282, reg_list->regs, reg_list->num_of_regs); in ov9282_start_streaming()
666 dev_err(ov9282->dev, "fail to write initial registers"); in ov9282_start_streaming()
670 /* Setup handler will write actual exposure and gain */ in ov9282_start_streaming()
671 ret = __v4l2_ctrl_handler_setup(ov9282->sd.ctrl_handler); in ov9282_start_streaming()
673 dev_err(ov9282->dev, "fail to setup handler"); in ov9282_start_streaming()
681 dev_err(ov9282->dev, "fail to start streaming"); in ov9282_start_streaming()
689 * ov9282_stop_streaming() - Stop sensor stream
701 * ov9282_set_stream() - Enable sensor streaming
703 * @enable: set to enable sensor streaming
712 mutex_lock(&ov9282->mutex); in ov9282_set_stream()
714 if (ov9282->streaming == enable) { in ov9282_set_stream()
715 mutex_unlock(&ov9282->mutex); in ov9282_set_stream()
720 ret = pm_runtime_resume_and_get(ov9282->dev); in ov9282_set_stream()
729 pm_runtime_put(ov9282->dev); in ov9282_set_stream()
732 ov9282->streaming = enable; in ov9282_set_stream()
734 mutex_unlock(&ov9282->mutex); in ov9282_set_stream()
739 pm_runtime_put(ov9282->dev); in ov9282_set_stream()
741 mutex_unlock(&ov9282->mutex); in ov9282_set_stream()
747 * ov9282_detect() - Detect ov9282 sensor
750 * Return: 0 if successful, -EIO if sensor id does not match
762 dev_err(ov9282->dev, "chip id mismatch: %x!=%x", in ov9282_detect()
764 return -ENXIO; in ov9282_detect()
771 * ov9282_parse_hw_config() - Parse HW configuration and check if supported
778 struct fwnode_handle *fwnode = dev_fwnode(ov9282->dev); in ov9282_parse_hw_config()
788 return -ENXIO; in ov9282_parse_hw_config()
791 ov9282->reset_gpio = devm_gpiod_get_optional(ov9282->dev, "reset", in ov9282_parse_hw_config()
793 if (IS_ERR(ov9282->reset_gpio)) { in ov9282_parse_hw_config()
794 dev_err(ov9282->dev, "failed to get reset gpio %ld", in ov9282_parse_hw_config()
795 PTR_ERR(ov9282->reset_gpio)); in ov9282_parse_hw_config()
796 return PTR_ERR(ov9282->reset_gpio); in ov9282_parse_hw_config()
799 /* Get sensor input clock */ in ov9282_parse_hw_config()
800 ov9282->inclk = devm_clk_get(ov9282->dev, NULL); in ov9282_parse_hw_config()
801 if (IS_ERR(ov9282->inclk)) { in ov9282_parse_hw_config()
802 dev_err(ov9282->dev, "could not get inclk"); in ov9282_parse_hw_config()
803 return PTR_ERR(ov9282->inclk); in ov9282_parse_hw_config()
806 rate = clk_get_rate(ov9282->inclk); in ov9282_parse_hw_config()
808 dev_err(ov9282->dev, "inclk frequency mismatch"); in ov9282_parse_hw_config()
809 return -EINVAL; in ov9282_parse_hw_config()
814 return -ENXIO; in ov9282_parse_hw_config()
822 dev_err(ov9282->dev, in ov9282_parse_hw_config()
825 ret = -EINVAL; in ov9282_parse_hw_config()
830 dev_err(ov9282->dev, "no link frequencies defined"); in ov9282_parse_hw_config()
831 ret = -EINVAL; in ov9282_parse_hw_config()
839 ret = -EINVAL; in ov9282_parse_hw_config()
866 * ov9282_power_on() - Sensor power on sequence
879 gpiod_set_value_cansleep(ov9282->reset_gpio, 1); in ov9282_power_on()
881 ret = clk_prepare_enable(ov9282->inclk); in ov9282_power_on()
883 dev_err(ov9282->dev, "fail to enable inclk"); in ov9282_power_on()
892 gpiod_set_value_cansleep(ov9282->reset_gpio, 0); in ov9282_power_on()
898 * ov9282_power_off() - Sensor power off sequence
908 gpiod_set_value_cansleep(ov9282->reset_gpio, 0); in ov9282_power_off()
910 clk_disable_unprepare(ov9282->inclk); in ov9282_power_off()
916 * ov9282_init_controls() - Initialize sensor subdevice controls
923 struct v4l2_ctrl_handler *ctrl_hdlr = &ov9282->ctrl_handler; in ov9282_init_controls()
924 const struct ov9282_mode *mode = ov9282->cur_mode; in ov9282_init_controls()
932 /* Serialize controls with sensor device */ in ov9282_init_controls()
933 ctrl_hdlr->lock = &ov9282->mutex; in ov9282_init_controls()
935 /* Initialize exposure and gain */ in ov9282_init_controls()
936 lpfr = mode->vblank + mode->height; in ov9282_init_controls()
937 ov9282->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in ov9282_init_controls()
941 lpfr - OV9282_EXPOSURE_OFFSET, in ov9282_init_controls()
945 ov9282->again_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in ov9282_init_controls()
953 v4l2_ctrl_cluster(2, &ov9282->exp_ctrl); in ov9282_init_controls()
955 ov9282->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in ov9282_init_controls()
958 mode->vblank_min, in ov9282_init_controls()
959 mode->vblank_max, in ov9282_init_controls()
960 1, mode->vblank); in ov9282_init_controls()
963 ov9282->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in ov9282_init_controls()
966 mode->pclk, mode->pclk, in ov9282_init_controls()
967 1, mode->pclk); in ov9282_init_controls()
969 ov9282->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, in ov9282_init_controls()
972 ARRAY_SIZE(link_freq) - in ov9282_init_controls()
974 mode->link_freq_idx, in ov9282_init_controls()
976 if (ov9282->link_freq_ctrl) in ov9282_init_controls()
977 ov9282->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in ov9282_init_controls()
979 ov9282->hblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in ov9282_init_controls()
984 1, mode->hblank); in ov9282_init_controls()
985 if (ov9282->hblank_ctrl) in ov9282_init_controls()
986 ov9282->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in ov9282_init_controls()
988 if (ctrl_hdlr->error) { in ov9282_init_controls()
989 dev_err(ov9282->dev, "control init failed: %d", in ov9282_init_controls()
990 ctrl_hdlr->error); in ov9282_init_controls()
992 return ctrl_hdlr->error; in ov9282_init_controls()
995 ov9282->sd.ctrl_handler = ctrl_hdlr; in ov9282_init_controls()
1001 * ov9282_probe() - I2C client device binding
1011 ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL); in ov9282_probe()
1013 return -ENOMEM; in ov9282_probe()
1015 ov9282->dev = &client->dev; in ov9282_probe()
1018 v4l2_i2c_subdev_init(&ov9282->sd, client, &ov9282_subdev_ops); in ov9282_probe()
1022 dev_err(ov9282->dev, "HW configuration is not supported"); in ov9282_probe()
1026 mutex_init(&ov9282->mutex); in ov9282_probe()
1028 ret = ov9282_power_on(ov9282->dev); in ov9282_probe()
1030 dev_err(ov9282->dev, "failed to power-on the sensor"); in ov9282_probe()
1037 dev_err(ov9282->dev, "failed to find sensor: %d", ret); in ov9282_probe()
1042 ov9282->cur_mode = &supported_mode; in ov9282_probe()
1043 ov9282->vblank = ov9282->cur_mode->vblank; in ov9282_probe()
1047 dev_err(ov9282->dev, "failed to init controls: %d", ret); in ov9282_probe()
1052 ov9282->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in ov9282_probe()
1053 ov9282->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; in ov9282_probe()
1056 ov9282->pad.flags = MEDIA_PAD_FL_SOURCE; in ov9282_probe()
1057 ret = media_entity_pads_init(&ov9282->sd.entity, 1, &ov9282->pad); in ov9282_probe()
1059 dev_err(ov9282->dev, "failed to init entity pads: %d", ret); in ov9282_probe()
1063 ret = v4l2_async_register_subdev_sensor(&ov9282->sd); in ov9282_probe()
1065 dev_err(ov9282->dev, in ov9282_probe()
1070 pm_runtime_set_active(ov9282->dev); in ov9282_probe()
1071 pm_runtime_enable(ov9282->dev); in ov9282_probe()
1072 pm_runtime_idle(ov9282->dev); in ov9282_probe()
1077 media_entity_cleanup(&ov9282->sd.entity); in ov9282_probe()
1079 v4l2_ctrl_handler_free(ov9282->sd.ctrl_handler); in ov9282_probe()
1081 ov9282_power_off(ov9282->dev); in ov9282_probe()
1083 mutex_destroy(&ov9282->mutex); in ov9282_probe()
1089 * ov9282_remove() - I2C client device unbinding
1100 media_entity_cleanup(&sd->entity); in ov9282_remove()
1101 v4l2_ctrl_handler_free(sd->ctrl_handler); in ov9282_remove()
1103 pm_runtime_disable(&client->dev); in ov9282_remove()
1104 if (!pm_runtime_status_suspended(&client->dev)) in ov9282_remove()
1105 ov9282_power_off(&client->dev); in ov9282_remove()
1106 pm_runtime_set_suspended(&client->dev); in ov9282_remove()
1108 mutex_destroy(&ov9282->mutex); in ov9282_remove()
1134 MODULE_DESCRIPTION("OmniVision ov9282 sensor driver");