Lines Matching +full:sd +full:- +full:lines
1 // SPDX-License-Identifier: GPL-2.0-only
16 #include <media/v4l2-ctrls.h>
17 #include <media/v4l2-fwnode.h>
18 #include <media/v4l2-subdev.h>
25 /* Lines per frame */
60 * struct imx412_reg - imx412 sensor register
70 * struct imx412_reg_list - imx412 sensor register list
80 * struct imx412_mode - imx412 sensor mode structure
84 * @hblank: Horizontal blanking in lines
85 * @vblank: Vertical blanking in lines
86 * @vblank_min: Minimum vertical blanking in lines
87 * @vblank_max: Maximum vertical blanking in lines
112 * struct imx412 - imx412 sensor device structure
115 * @sd: V4L2 sub-device
127 * @vblank: Vertical blanking in lines
134 struct v4l2_subdev sd; member
410 * to_imx412() - imx412 V4L2 sub-device to imx412 device.
411 * @subdev: pointer to imx412 V4L2 sub-device
417 return container_of(subdev, struct imx412, sd); in to_imx412()
421 * imx412_read_reg() - Read registers.
431 struct i2c_client *client = v4l2_get_subdevdata(&imx412->sd); in imx412_read_reg()
438 return -EINVAL; in imx412_read_reg()
443 msgs[0].addr = client->addr; in imx412_read_reg()
449 msgs[1].addr = client->addr; in imx412_read_reg()
452 msgs[1].buf = &data_buf[4 - len]; in imx412_read_reg()
454 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in imx412_read_reg()
456 return -EIO; in imx412_read_reg()
464 * imx412_write_reg() - Write register
474 struct i2c_client *client = v4l2_get_subdevdata(&imx412->sd); in imx412_write_reg()
478 return -EINVAL; in imx412_write_reg()
481 put_unaligned_be32(val << (8 * (4 - len)), buf + 2); in imx412_write_reg()
483 return -EIO; in imx412_write_reg()
489 * imx412_write_regs() - Write a list of registers
512 * imx412_update_controls() - Update control ranges based on streaming mode
523 ret = __v4l2_ctrl_s_ctrl(imx412->link_freq_ctrl, mode->link_freq_idx); in imx412_update_controls()
527 ret = __v4l2_ctrl_s_ctrl(imx412->hblank_ctrl, mode->hblank); in imx412_update_controls()
531 return __v4l2_ctrl_modify_range(imx412->vblank_ctrl, mode->vblank_min, in imx412_update_controls()
532 mode->vblank_max, 1, mode->vblank); in imx412_update_controls()
536 * imx412_update_exp_gain() - Set updated exposure and gain
548 lpfr = imx412->vblank + imx412->cur_mode->height; in imx412_update_exp_gain()
549 shutter = lpfr - exposure; in imx412_update_exp_gain()
551 dev_dbg(imx412->dev, "Set exp %u, analog gain %u, shutter %u, lpfr %u", in imx412_update_exp_gain()
575 * imx412_set_ctrl() - Set subdevice control
579 * - V4L2_CID_VBLANK
580 * - cluster controls:
581 * - V4L2_CID_ANALOGUE_GAIN
582 * - V4L2_CID_EXPOSURE
589 container_of(ctrl->handler, struct imx412, ctrl_handler); in imx412_set_ctrl()
594 switch (ctrl->id) { in imx412_set_ctrl()
596 imx412->vblank = imx412->vblank_ctrl->val; in imx412_set_ctrl()
598 dev_dbg(imx412->dev, "Received vblank %u, new lpfr %u", in imx412_set_ctrl()
599 imx412->vblank, in imx412_set_ctrl()
600 imx412->vblank + imx412->cur_mode->height); in imx412_set_ctrl()
602 ret = __v4l2_ctrl_modify_range(imx412->exp_ctrl, in imx412_set_ctrl()
604 imx412->vblank + in imx412_set_ctrl()
605 imx412->cur_mode->height - in imx412_set_ctrl()
611 if (!pm_runtime_get_if_in_use(imx412->dev)) in imx412_set_ctrl()
614 exposure = ctrl->val; in imx412_set_ctrl()
615 analog_gain = imx412->again_ctrl->val; in imx412_set_ctrl()
617 dev_dbg(imx412->dev, "Received exp %u, analog gain %u", in imx412_set_ctrl()
622 pm_runtime_put(imx412->dev); in imx412_set_ctrl()
626 dev_err(imx412->dev, "Invalid control %d", ctrl->id); in imx412_set_ctrl()
627 ret = -EINVAL; in imx412_set_ctrl()
639 * imx412_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
640 * @sd: pointer to imx412 V4L2 sub-device structure
641 * @sd_state: V4L2 sub-device configuration
642 * @code: V4L2 sub-device code enumeration need to be filled
646 static int imx412_enum_mbus_code(struct v4l2_subdev *sd, in imx412_enum_mbus_code() argument
650 if (code->index > 0) in imx412_enum_mbus_code()
651 return -EINVAL; in imx412_enum_mbus_code()
653 code->code = supported_mode.code; in imx412_enum_mbus_code()
659 * imx412_enum_frame_size() - Enumerate V4L2 sub-device frame sizes
660 * @sd: pointer to imx412 V4L2 sub-device structure
661 * @sd_state: V4L2 sub-device configuration
662 * @fsize: V4L2 sub-device size enumeration need to be filled
666 static int imx412_enum_frame_size(struct v4l2_subdev *sd, in imx412_enum_frame_size() argument
670 if (fsize->index > 0) in imx412_enum_frame_size()
671 return -EINVAL; in imx412_enum_frame_size()
673 if (fsize->code != supported_mode.code) in imx412_enum_frame_size()
674 return -EINVAL; in imx412_enum_frame_size()
676 fsize->min_width = supported_mode.width; in imx412_enum_frame_size()
677 fsize->max_width = fsize->min_width; in imx412_enum_frame_size()
678 fsize->min_height = supported_mode.height; in imx412_enum_frame_size()
679 fsize->max_height = fsize->min_height; in imx412_enum_frame_size()
685 * imx412_fill_pad_format() - Fill subdevice pad format
689 * @fmt: V4L2 sub-device format need to be filled
695 fmt->format.width = mode->width; in imx412_fill_pad_format()
696 fmt->format.height = mode->height; in imx412_fill_pad_format()
697 fmt->format.code = mode->code; in imx412_fill_pad_format()
698 fmt->format.field = V4L2_FIELD_NONE; in imx412_fill_pad_format()
699 fmt->format.colorspace = V4L2_COLORSPACE_RAW; in imx412_fill_pad_format()
700 fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in imx412_fill_pad_format()
701 fmt->format.quantization = V4L2_QUANTIZATION_DEFAULT; in imx412_fill_pad_format()
702 fmt->format.xfer_func = V4L2_XFER_FUNC_NONE; in imx412_fill_pad_format()
706 * imx412_get_pad_format() - Get subdevice pad format
707 * @sd: pointer to imx412 V4L2 sub-device structure
708 * @sd_state: V4L2 sub-device configuration
709 * @fmt: V4L2 sub-device format need to be set
713 static int imx412_get_pad_format(struct v4l2_subdev *sd, in imx412_get_pad_format() argument
717 struct imx412 *imx412 = to_imx412(sd); in imx412_get_pad_format()
719 mutex_lock(&imx412->mutex); in imx412_get_pad_format()
721 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in imx412_get_pad_format()
724 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); in imx412_get_pad_format()
725 fmt->format = *framefmt; in imx412_get_pad_format()
727 imx412_fill_pad_format(imx412, imx412->cur_mode, fmt); in imx412_get_pad_format()
730 mutex_unlock(&imx412->mutex); in imx412_get_pad_format()
736 * imx412_set_pad_format() - Set subdevice pad format
737 * @sd: pointer to imx412 V4L2 sub-device structure
738 * @sd_state: V4L2 sub-device configuration
739 * @fmt: V4L2 sub-device format need to be set
743 static int imx412_set_pad_format(struct v4l2_subdev *sd, in imx412_set_pad_format() argument
747 struct imx412 *imx412 = to_imx412(sd); in imx412_set_pad_format()
751 mutex_lock(&imx412->mutex); in imx412_set_pad_format()
756 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in imx412_set_pad_format()
759 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); in imx412_set_pad_format()
760 *framefmt = fmt->format; in imx412_set_pad_format()
764 imx412->cur_mode = mode; in imx412_set_pad_format()
767 mutex_unlock(&imx412->mutex); in imx412_set_pad_format()
773 * imx412_init_state() - Initialize sub-device state
774 * @sd: pointer to imx412 V4L2 sub-device structure
775 * @sd_state: V4L2 sub-device configuration
779 static int imx412_init_state(struct v4l2_subdev *sd, in imx412_init_state() argument
782 struct imx412 *imx412 = to_imx412(sd); in imx412_init_state()
788 return imx412_set_pad_format(sd, sd_state, &fmt); in imx412_init_state()
792 * imx412_start_streaming() - Start sensor stream
803 reg_list = &imx412->cur_mode->reg_list; in imx412_start_streaming()
804 ret = imx412_write_regs(imx412, reg_list->regs, in imx412_start_streaming()
805 reg_list->num_of_regs); in imx412_start_streaming()
807 dev_err(imx412->dev, "fail to write initial registers"); in imx412_start_streaming()
812 ret = __v4l2_ctrl_handler_setup(imx412->sd.ctrl_handler); in imx412_start_streaming()
814 dev_err(imx412->dev, "fail to setup handler"); in imx412_start_streaming()
825 dev_err(imx412->dev, "fail to start streaming"); in imx412_start_streaming()
833 * imx412_stop_streaming() - Stop sensor stream
845 * imx412_set_stream() - Enable sensor streaming
846 * @sd: pointer to imx412 subdevice
851 static int imx412_set_stream(struct v4l2_subdev *sd, int enable) in imx412_set_stream() argument
853 struct imx412 *imx412 = to_imx412(sd); in imx412_set_stream()
856 mutex_lock(&imx412->mutex); in imx412_set_stream()
859 ret = pm_runtime_resume_and_get(imx412->dev); in imx412_set_stream()
868 pm_runtime_put(imx412->dev); in imx412_set_stream()
871 mutex_unlock(&imx412->mutex); in imx412_set_stream()
876 pm_runtime_put(imx412->dev); in imx412_set_stream()
878 mutex_unlock(&imx412->mutex); in imx412_set_stream()
884 * imx412_detect() - Detect imx412 sensor
887 * Return: 0 if successful, -EIO if sensor id does not match
899 dev_err(imx412->dev, "chip id mismatch: %x!=%x", in imx412_detect()
901 return -ENXIO; in imx412_detect()
908 * imx412_parse_hw_config() - Parse HW configuration and check if supported
915 struct fwnode_handle *fwnode = dev_fwnode(imx412->dev); in imx412_parse_hw_config()
925 return -ENXIO; in imx412_parse_hw_config()
928 imx412->reset_gpio = devm_gpiod_get_optional(imx412->dev, "reset", in imx412_parse_hw_config()
930 if (IS_ERR(imx412->reset_gpio)) { in imx412_parse_hw_config()
931 dev_err(imx412->dev, "failed to get reset gpio %ld", in imx412_parse_hw_config()
932 PTR_ERR(imx412->reset_gpio)); in imx412_parse_hw_config()
933 return PTR_ERR(imx412->reset_gpio); in imx412_parse_hw_config()
937 imx412->inclk = devm_clk_get(imx412->dev, NULL); in imx412_parse_hw_config()
938 if (IS_ERR(imx412->inclk)) { in imx412_parse_hw_config()
939 dev_err(imx412->dev, "could not get inclk"); in imx412_parse_hw_config()
940 return PTR_ERR(imx412->inclk); in imx412_parse_hw_config()
943 rate = clk_get_rate(imx412->inclk); in imx412_parse_hw_config()
945 dev_err(imx412->dev, "inclk frequency mismatch"); in imx412_parse_hw_config()
946 return -EINVAL; in imx412_parse_hw_config()
951 imx412->supplies[i].supply = imx412_supply_names[i]; in imx412_parse_hw_config()
953 ret = devm_regulator_bulk_get(imx412->dev, in imx412_parse_hw_config()
955 imx412->supplies); in imx412_parse_hw_config()
961 return -ENXIO; in imx412_parse_hw_config()
969 dev_err(imx412->dev, in imx412_parse_hw_config()
972 ret = -EINVAL; in imx412_parse_hw_config()
977 dev_err(imx412->dev, "no link frequencies defined"); in imx412_parse_hw_config()
978 ret = -EINVAL; in imx412_parse_hw_config()
986 ret = -EINVAL; in imx412_parse_hw_config()
1016 * imx412_power_on() - Sensor power on sequence
1023 struct v4l2_subdev *sd = dev_get_drvdata(dev); in imx412_power_on() local
1024 struct imx412 *imx412 = to_imx412(sd); in imx412_power_on()
1028 imx412->supplies); in imx412_power_on()
1034 gpiod_set_value_cansleep(imx412->reset_gpio, 0); in imx412_power_on()
1036 ret = clk_prepare_enable(imx412->inclk); in imx412_power_on()
1038 dev_err(imx412->dev, "fail to enable inclk"); in imx412_power_on()
1047 gpiod_set_value_cansleep(imx412->reset_gpio, 1); in imx412_power_on()
1049 imx412->supplies); in imx412_power_on()
1055 * imx412_power_off() - Sensor power off sequence
1062 struct v4l2_subdev *sd = dev_get_drvdata(dev); in imx412_power_off() local
1063 struct imx412 *imx412 = to_imx412(sd); in imx412_power_off()
1065 clk_disable_unprepare(imx412->inclk); in imx412_power_off()
1067 gpiod_set_value_cansleep(imx412->reset_gpio, 1); in imx412_power_off()
1070 imx412->supplies); in imx412_power_off()
1076 * imx412_init_controls() - Initialize sensor subdevice controls
1083 struct v4l2_ctrl_handler *ctrl_hdlr = &imx412->ctrl_handler; in imx412_init_controls()
1084 const struct imx412_mode *mode = imx412->cur_mode; in imx412_init_controls()
1093 ctrl_hdlr->lock = &imx412->mutex; in imx412_init_controls()
1096 lpfr = mode->vblank + mode->height; in imx412_init_controls()
1097 imx412->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in imx412_init_controls()
1101 lpfr - IMX412_EXPOSURE_OFFSET, in imx412_init_controls()
1105 imx412->again_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in imx412_init_controls()
1113 v4l2_ctrl_cluster(2, &imx412->exp_ctrl); in imx412_init_controls()
1115 imx412->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in imx412_init_controls()
1118 mode->vblank_min, in imx412_init_controls()
1119 mode->vblank_max, in imx412_init_controls()
1120 1, mode->vblank); in imx412_init_controls()
1123 imx412->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in imx412_init_controls()
1126 mode->pclk, mode->pclk, in imx412_init_controls()
1127 1, mode->pclk); in imx412_init_controls()
1129 imx412->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, in imx412_init_controls()
1132 ARRAY_SIZE(link_freq) - in imx412_init_controls()
1134 mode->link_freq_idx, in imx412_init_controls()
1136 if (imx412->link_freq_ctrl) in imx412_init_controls()
1137 imx412->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in imx412_init_controls()
1139 imx412->hblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, in imx412_init_controls()
1144 1, mode->hblank); in imx412_init_controls()
1145 if (imx412->hblank_ctrl) in imx412_init_controls()
1146 imx412->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in imx412_init_controls()
1148 if (ctrl_hdlr->error) { in imx412_init_controls()
1149 dev_err(imx412->dev, "control init failed: %d", in imx412_init_controls()
1150 ctrl_hdlr->error); in imx412_init_controls()
1152 return ctrl_hdlr->error; in imx412_init_controls()
1155 imx412->sd.ctrl_handler = ctrl_hdlr; in imx412_init_controls()
1161 * imx412_probe() - I2C client device binding
1172 imx412 = devm_kzalloc(&client->dev, sizeof(*imx412), GFP_KERNEL); in imx412_probe()
1174 return -ENOMEM; in imx412_probe()
1176 imx412->dev = &client->dev; in imx412_probe()
1177 name = device_get_match_data(&client->dev); in imx412_probe()
1179 return -ENODEV; in imx412_probe()
1182 v4l2_i2c_subdev_init(&imx412->sd, client, &imx412_subdev_ops); in imx412_probe()
1183 imx412->sd.internal_ops = &imx412_internal_ops; in imx412_probe()
1187 dev_err(imx412->dev, "HW configuration is not supported"); in imx412_probe()
1191 mutex_init(&imx412->mutex); in imx412_probe()
1193 ret = imx412_power_on(imx412->dev); in imx412_probe()
1195 dev_err(imx412->dev, "failed to power-on the sensor"); in imx412_probe()
1202 dev_err(imx412->dev, "failed to find sensor: %d", ret); in imx412_probe()
1207 imx412->cur_mode = &supported_mode; in imx412_probe()
1208 imx412->vblank = imx412->cur_mode->vblank; in imx412_probe()
1212 dev_err(imx412->dev, "failed to init controls: %d", ret); in imx412_probe()
1217 imx412->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in imx412_probe()
1218 imx412->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; in imx412_probe()
1220 v4l2_i2c_subdev_set_name(&imx412->sd, client, name, NULL); in imx412_probe()
1223 imx412->pad.flags = MEDIA_PAD_FL_SOURCE; in imx412_probe()
1224 ret = media_entity_pads_init(&imx412->sd.entity, 1, &imx412->pad); in imx412_probe()
1226 dev_err(imx412->dev, "failed to init entity pads: %d", ret); in imx412_probe()
1230 ret = v4l2_async_register_subdev_sensor(&imx412->sd); in imx412_probe()
1232 dev_err(imx412->dev, in imx412_probe()
1237 pm_runtime_set_active(imx412->dev); in imx412_probe()
1238 pm_runtime_enable(imx412->dev); in imx412_probe()
1239 pm_runtime_idle(imx412->dev); in imx412_probe()
1244 media_entity_cleanup(&imx412->sd.entity); in imx412_probe()
1246 v4l2_ctrl_handler_free(imx412->sd.ctrl_handler); in imx412_probe()
1248 imx412_power_off(imx412->dev); in imx412_probe()
1250 mutex_destroy(&imx412->mutex); in imx412_probe()
1256 * imx412_remove() - I2C client device unbinding
1263 struct v4l2_subdev *sd = i2c_get_clientdata(client); in imx412_remove() local
1264 struct imx412 *imx412 = to_imx412(sd); in imx412_remove()
1266 v4l2_async_unregister_subdev(sd); in imx412_remove()
1267 media_entity_cleanup(&sd->entity); in imx412_remove()
1268 v4l2_ctrl_handler_free(sd->ctrl_handler); in imx412_remove()
1270 pm_runtime_disable(&client->dev); in imx412_remove()
1271 if (!pm_runtime_status_suspended(&client->dev)) in imx412_remove()
1272 imx412_power_off(&client->dev); in imx412_remove()
1273 pm_runtime_set_suspended(&client->dev); in imx412_remove()
1275 mutex_destroy(&imx412->mutex); in imx412_remove()