Lines Matching full:ov5693

5  * Adapted from the atomisp-ov5693 driver, with contributions from:
39 /* Yes, this is right. The datasheet for the OV5693 gives its ID as 0x5690 */
358 static int ov5693_flip_vert_configure(struct ov5693_device *ov5693, in ov5693_flip_vert_configure() argument
365 ret = cci_update_bits(ov5693->regmap, OV5693_FORMAT1_REG, bits, in ov5693_flip_vert_configure()
373 static int ov5693_flip_horz_configure(struct ov5693_device *ov5693, in ov5693_flip_horz_configure() argument
380 ret = cci_update_bits(ov5693->regmap, OV5693_FORMAT2_REG, bits, in ov5693_flip_horz_configure()
388 static int ov5693_get_exposure(struct ov5693_device *ov5693, s32 *value) in ov5693_get_exposure() argument
393 ret = cci_read(ov5693->regmap, OV5693_EXPOSURE_CTRL_REG, &exposure, in ov5693_get_exposure()
404 static int ov5693_exposure_configure(struct ov5693_device *ov5693, in ov5693_exposure_configure() argument
411 cci_write(ov5693->regmap, OV5693_EXPOSURE_CTRL_REG, exposure, &ret); in ov5693_exposure_configure()
416 static int ov5693_get_gain(struct ov5693_device *ov5693, u32 *gain) in ov5693_get_gain() argument
421 ret = cci_read(ov5693->regmap, OV5693_GAIN_CTRL_REG, &value, NULL); in ov5693_get_gain()
431 static int ov5693_digital_gain_configure(struct ov5693_device *ov5693, in ov5693_digital_gain_configure() argument
438 cci_write(ov5693->regmap, OV5693_MWB_RED_GAIN_REG, gain, &ret); in ov5693_digital_gain_configure()
439 cci_write(ov5693->regmap, OV5693_MWB_GREEN_GAIN_REG, gain, &ret); in ov5693_digital_gain_configure()
440 cci_write(ov5693->regmap, OV5693_MWB_BLUE_GAIN_REG, gain, &ret); in ov5693_digital_gain_configure()
445 static int ov5693_analog_gain_configure(struct ov5693_device *ov5693, u32 gain) in ov5693_analog_gain_configure() argument
451 cci_write(ov5693->regmap, OV5693_GAIN_CTRL_REG, gain, &ret); in ov5693_analog_gain_configure()
456 static int ov5693_vts_configure(struct ov5693_device *ov5693, u32 vblank) in ov5693_vts_configure() argument
458 u16 vts = ov5693->mode.format.height + vblank; in ov5693_vts_configure()
461 cci_write(ov5693->regmap, OV5693_TIMING_VTS_REG, vts, &ret); in ov5693_vts_configure()
466 static int ov5693_test_pattern_configure(struct ov5693_device *ov5693, u32 idx) in ov5693_test_pattern_configure() argument
470 cci_write(ov5693->regmap, OV5693_TEST_PATTERN_REG, in ov5693_test_pattern_configure()
478 struct ov5693_device *ov5693 = in ov5693_s_ctrl() local
486 exposure_max = ov5693->mode.format.height + ctrl->val - in ov5693_s_ctrl()
488 __v4l2_ctrl_modify_range(ov5693->ctrls.exposure, in ov5693_s_ctrl()
489 ov5693->ctrls.exposure->minimum, in ov5693_s_ctrl()
491 ov5693->ctrls.exposure->step, in ov5693_s_ctrl()
492 min(ov5693->ctrls.exposure->val, in ov5693_s_ctrl()
497 if (!pm_runtime_get_if_in_use(ov5693->dev)) in ov5693_s_ctrl()
502 ret = ov5693_exposure_configure(ov5693, ctrl->val); in ov5693_s_ctrl()
505 ret = ov5693_analog_gain_configure(ov5693, ctrl->val); in ov5693_s_ctrl()
508 ret = ov5693_digital_gain_configure(ov5693, ctrl->val); in ov5693_s_ctrl()
511 ret = ov5693_flip_horz_configure(ov5693, !!ctrl->val); in ov5693_s_ctrl()
514 ret = ov5693_flip_vert_configure(ov5693, !!ctrl->val); in ov5693_s_ctrl()
517 ret = ov5693_vts_configure(ov5693, ctrl->val); in ov5693_s_ctrl()
520 ret = ov5693_test_pattern_configure(ov5693, ctrl->val); in ov5693_s_ctrl()
526 pm_runtime_put(ov5693->dev); in ov5693_s_ctrl()
533 struct ov5693_device *ov5693 = container_of(ctrl->handler, in ov5693_g_volatile_ctrl() local
539 return ov5693_get_exposure(ov5693, &ctrl->val); in ov5693_g_volatile_ctrl()
541 return ov5693_get_gain(ov5693, &ctrl->val); in ov5693_g_volatile_ctrl()
554 static int ov5693_mode_configure(struct ov5693_device *ov5693) in ov5693_mode_configure() argument
556 const struct ov5693_mode *mode = &ov5693->mode; in ov5693_mode_configure()
560 cci_write(ov5693->regmap, OV5693_CROP_START_X_REG, mode->crop.left, in ov5693_mode_configure()
564 cci_write(ov5693->regmap, OV5693_OFFSET_START_X_REG, 0, &ret); in ov5693_mode_configure()
567 cci_write(ov5693->regmap, OV5693_OUTPUT_SIZE_X_REG, mode->format.width, in ov5693_mode_configure()
571 cci_write(ov5693->regmap, OV5693_CROP_END_X_REG, in ov5693_mode_configure()
575 cci_write(ov5693->regmap, OV5693_TIMING_HTS_REG, OV5693_FIXED_PPL, in ov5693_mode_configure()
579 cci_write(ov5693->regmap, OV5693_CROP_START_Y_REG, mode->crop.top, in ov5693_mode_configure()
583 cci_write(ov5693->regmap, OV5693_OFFSET_START_Y_REG, 0, &ret); in ov5693_mode_configure()
586 cci_write(ov5693->regmap, OV5693_OUTPUT_SIZE_Y_REG, mode->format.height, in ov5693_mode_configure()
590 cci_write(ov5693->regmap, OV5693_CROP_END_Y_REG, in ov5693_mode_configure()
594 cci_write(ov5693->regmap, OV5693_SUB_INC_X_REG, in ov5693_mode_configure()
597 cci_write(ov5693->regmap, OV5693_SUB_INC_Y_REG, in ov5693_mode_configure()
601 cci_update_bits(ov5693->regmap, OV5693_FORMAT1_REG, in ov5693_mode_configure()
605 cci_update_bits(ov5693->regmap, OV5693_FORMAT2_REG, in ov5693_mode_configure()
612 static int ov5693_enable_streaming(struct ov5693_device *ov5693, bool enable) in ov5693_enable_streaming() argument
616 cci_write(ov5693->regmap, OV5693_SW_STREAM_REG, in ov5693_enable_streaming()
623 static int ov5693_sw_reset(struct ov5693_device *ov5693) in ov5693_sw_reset() argument
627 cci_write(ov5693->regmap, OV5693_SW_RESET_REG, OV5693_SW_RESET, &ret); in ov5693_sw_reset()
632 static int ov5693_sensor_init(struct ov5693_device *ov5693) in ov5693_sensor_init() argument
636 ret = ov5693_sw_reset(ov5693); in ov5693_sensor_init()
638 return dev_err_probe(ov5693->dev, ret, in ov5693_sensor_init()
641 ret = cci_multi_reg_write(ov5693->regmap, ov5693_global_regs, in ov5693_sensor_init()
644 return dev_err_probe(ov5693->dev, ret, in ov5693_sensor_init()
647 ret = ov5693_mode_configure(ov5693); in ov5693_sensor_init()
649 return dev_err_probe(ov5693->dev, ret, in ov5693_sensor_init()
652 ret = ov5693_enable_streaming(ov5693, false); in ov5693_sensor_init()
654 dev_err(ov5693->dev, "stop streaming error\n"); in ov5693_sensor_init()
659 static void ov5693_sensor_powerdown(struct ov5693_device *ov5693) in ov5693_sensor_powerdown() argument
661 gpiod_set_value_cansleep(ov5693->privacy_led, 0); in ov5693_sensor_powerdown()
662 gpiod_set_value_cansleep(ov5693->reset, 1); in ov5693_sensor_powerdown()
663 gpiod_set_value_cansleep(ov5693->powerdown, 1); in ov5693_sensor_powerdown()
665 regulator_bulk_disable(OV5693_NUM_SUPPLIES, ov5693->supplies); in ov5693_sensor_powerdown()
667 clk_disable_unprepare(ov5693->xvclk); in ov5693_sensor_powerdown()
670 static int ov5693_sensor_powerup(struct ov5693_device *ov5693) in ov5693_sensor_powerup() argument
674 gpiod_set_value_cansleep(ov5693->reset, 1); in ov5693_sensor_powerup()
675 gpiod_set_value_cansleep(ov5693->powerdown, 1); in ov5693_sensor_powerup()
677 ret = clk_prepare_enable(ov5693->xvclk); in ov5693_sensor_powerup()
679 dev_err(ov5693->dev, "Failed to enable clk\n"); in ov5693_sensor_powerup()
683 ret = regulator_bulk_enable(OV5693_NUM_SUPPLIES, ov5693->supplies); in ov5693_sensor_powerup()
685 dev_err(ov5693->dev, "Failed to enable regulators\n"); in ov5693_sensor_powerup()
689 gpiod_set_value_cansleep(ov5693->powerdown, 0); in ov5693_sensor_powerup()
690 gpiod_set_value_cansleep(ov5693->reset, 0); in ov5693_sensor_powerup()
691 gpiod_set_value_cansleep(ov5693->privacy_led, 1); in ov5693_sensor_powerup()
698 ov5693_sensor_powerdown(ov5693); in ov5693_sensor_powerup()
705 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_sensor_suspend() local
707 ov5693_sensor_powerdown(ov5693); in ov5693_sensor_suspend()
715 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_sensor_resume() local
718 mutex_lock(&ov5693->lock); in ov5693_sensor_resume()
720 ret = ov5693_sensor_powerup(ov5693); in ov5693_sensor_resume()
724 ret = ov5693_sensor_init(ov5693); in ov5693_sensor_resume()
726 dev_err(dev, "ov5693 sensor init failure\n"); in ov5693_sensor_resume()
733 ov5693_sensor_powerdown(ov5693); in ov5693_sensor_resume()
735 mutex_unlock(&ov5693->lock); in ov5693_sensor_resume()
739 static int ov5693_detect(struct ov5693_device *ov5693) in ov5693_detect() argument
744 ret = cci_read(ov5693->regmap, OV5693_REG_CHIP_ID, &id, NULL); in ov5693_detect()
749 return dev_err_probe(ov5693->dev, -ENODEV, in ov5693_detect()
773 __ov5693_get_pad_format(struct ov5693_device *ov5693, in __ov5693_get_pad_format() argument
779 return v4l2_subdev_get_try_format(&ov5693->sd, state, pad); in __ov5693_get_pad_format()
781 return &ov5693->mode.format; in __ov5693_get_pad_format()
788 __ov5693_get_pad_crop(struct ov5693_device *ov5693, in __ov5693_get_pad_crop() argument
794 return v4l2_subdev_get_try_crop(&ov5693->sd, state, pad); in __ov5693_get_pad_crop()
796 return &ov5693->mode.crop; in __ov5693_get_pad_crop()
806 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_get_fmt() local
808 format->format = ov5693->mode.format; in ov5693_get_fmt()
817 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_set_fmt() local
825 crop = __ov5693_get_pad_crop(ov5693, state, format->pad, format->which); in ov5693_set_fmt()
845 fmt = __ov5693_get_pad_format(ov5693, state, format->pad, in ov5693_set_fmt()
857 mutex_lock(&ov5693->lock); in ov5693_set_fmt()
859 ov5693->mode.binning_x = hratio > 1; in ov5693_set_fmt()
860 ov5693->mode.inc_x_odd = hratio > 1 ? 3 : 1; in ov5693_set_fmt()
861 ov5693->mode.binning_y = vratio > 1; in ov5693_set_fmt()
862 ov5693->mode.inc_y_odd = vratio > 1 ? 3 : 1; in ov5693_set_fmt()
864 ov5693->mode.vts = __ov5693_calc_vts(fmt->height); in ov5693_set_fmt()
866 __v4l2_ctrl_modify_range(ov5693->ctrls.vblank, in ov5693_set_fmt()
869 1, ov5693->mode.vts - fmt->height); in ov5693_set_fmt()
870 __v4l2_ctrl_s_ctrl(ov5693->ctrls.vblank, in ov5693_set_fmt()
871 ov5693->mode.vts - fmt->height); in ov5693_set_fmt()
874 __v4l2_ctrl_modify_range(ov5693->ctrls.hblank, hblank, hblank, 1, in ov5693_set_fmt()
877 exposure_max = ov5693->mode.vts - OV5693_INTEGRATION_TIME_MARGIN; in ov5693_set_fmt()
878 __v4l2_ctrl_modify_range(ov5693->ctrls.exposure, in ov5693_set_fmt()
879 ov5693->ctrls.exposure->minimum, exposure_max, in ov5693_set_fmt()
880 ov5693->ctrls.exposure->step, in ov5693_set_fmt()
881 min(ov5693->ctrls.exposure->val, in ov5693_set_fmt()
884 mutex_unlock(&ov5693->lock); in ov5693_set_fmt()
892 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_get_selection() local
896 mutex_lock(&ov5693->lock); in ov5693_get_selection()
897 sel->r = *__ov5693_get_pad_crop(ov5693, state, sel->pad, in ov5693_get_selection()
899 mutex_unlock(&ov5693->lock); in ov5693_get_selection()
925 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_set_selection() local
953 __crop = __ov5693_get_pad_crop(ov5693, state, sel->pad, sel->which); in ov5693_set_selection()
960 format = __ov5693_get_pad_format(ov5693, state, sel->pad, in ov5693_set_selection()
974 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_s_stream() local
978 ret = pm_runtime_get_sync(ov5693->dev); in ov5693_s_stream()
982 mutex_lock(&ov5693->lock); in ov5693_s_stream()
983 ret = __v4l2_ctrl_handler_setup(&ov5693->ctrls.handler); in ov5693_s_stream()
985 mutex_unlock(&ov5693->lock); in ov5693_s_stream()
989 ret = ov5693_enable_streaming(ov5693, true); in ov5693_s_stream()
990 mutex_unlock(&ov5693->lock); in ov5693_s_stream()
992 mutex_lock(&ov5693->lock); in ov5693_s_stream()
993 ret = ov5693_enable_streaming(ov5693, false); in ov5693_s_stream()
994 mutex_unlock(&ov5693->lock); in ov5693_s_stream()
999 ov5693->streaming = !!enable; in ov5693_s_stream()
1002 pm_runtime_put(ov5693->dev); in ov5693_s_stream()
1006 pm_runtime_put_noidle(ov5693->dev); in ov5693_s_stream()
1013 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_g_frame_interval() local
1014 unsigned int framesize = OV5693_FIXED_PPL * (ov5693->mode.format.height + in ov5693_g_frame_interval()
1015 ov5693->ctrls.vblank->val); in ov5693_g_frame_interval()
1040 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_enum_frame_size() local
1046 __crop = __ov5693_get_pad_crop(ov5693, state, fse->pad, fse->which); in ov5693_enum_frame_size()
1079 static int ov5693_init_controls(struct ov5693_device *ov5693) in ov5693_init_controls() argument
1082 struct ov5693_v4l2_ctrls *ctrls = &ov5693->ctrls; in ov5693_init_controls()
1107 exposure_max = ov5693->mode.vts - OV5693_INTEGRATION_TIME_MARGIN; in ov5693_init_controls()
1135 hblank = OV5693_FIXED_PPL - ov5693->mode.format.width; in ov5693_init_controls()
1143 vblank_max = OV5693_TIMING_MAX_VTS - ov5693->mode.format.height; in ov5693_init_controls()
1144 vblank_def = ov5693->mode.vts - ov5693->mode.format.height; in ov5693_init_controls()
1157 dev_err(ov5693->dev, "Error initialising v4l2 ctrls\n"); in ov5693_init_controls()
1163 ret = v4l2_fwnode_device_parse(ov5693->dev, &props); in ov5693_init_controls()
1173 ctrls->handler.lock = &ov5693->lock; in ov5693_init_controls()
1174 ov5693->sd.ctrl_handler = &ctrls->handler; in ov5693_init_controls()
1183 static int ov5693_configure_gpios(struct ov5693_device *ov5693) in ov5693_configure_gpios() argument
1185 ov5693->reset = devm_gpiod_get_optional(ov5693->dev, "reset", in ov5693_configure_gpios()
1187 if (IS_ERR(ov5693->reset)) { in ov5693_configure_gpios()
1188 dev_err(ov5693->dev, "Error fetching reset GPIO\n"); in ov5693_configure_gpios()
1189 return PTR_ERR(ov5693->reset); in ov5693_configure_gpios()
1192 ov5693->powerdown = devm_gpiod_get_optional(ov5693->dev, "powerdown", in ov5693_configure_gpios()
1194 if (IS_ERR(ov5693->powerdown)) { in ov5693_configure_gpios()
1195 dev_err(ov5693->dev, "Error fetching powerdown GPIO\n"); in ov5693_configure_gpios()
1196 return PTR_ERR(ov5693->powerdown); in ov5693_configure_gpios()
1199 ov5693->privacy_led = devm_gpiod_get_optional(ov5693->dev, "privacy-led", in ov5693_configure_gpios()
1201 if (IS_ERR(ov5693->privacy_led)) { in ov5693_configure_gpios()
1202 dev_err(ov5693->dev, "Error fetching privacy-led GPIO\n"); in ov5693_configure_gpios()
1203 return PTR_ERR(ov5693->privacy_led); in ov5693_configure_gpios()
1209 static int ov5693_get_regulators(struct ov5693_device *ov5693) in ov5693_get_regulators() argument
1214 ov5693->supplies[i].supply = ov5693_supply_names[i]; in ov5693_get_regulators()
1216 return devm_regulator_bulk_get(ov5693->dev, OV5693_NUM_SUPPLIES, in ov5693_get_regulators()
1217 ov5693->supplies); in ov5693_get_regulators()
1220 static int ov5693_check_hwcfg(struct ov5693_device *ov5693) in ov5693_check_hwcfg() argument
1222 struct fwnode_handle *fwnode = dev_fwnode(ov5693->dev); in ov5693_check_hwcfg()
1240 dev_err(ov5693->dev, "only a 2-lane CSI2 config is supported"); in ov5693_check_hwcfg()
1246 dev_err(ov5693->dev, "no link frequencies defined\n"); in ov5693_check_hwcfg()
1256 dev_err(ov5693->dev, "supported link freq %ull not found\n", in ov5693_check_hwcfg()
1270 struct ov5693_device *ov5693; in ov5693_probe() local
1274 ov5693 = devm_kzalloc(&client->dev, sizeof(*ov5693), GFP_KERNEL); in ov5693_probe()
1275 if (!ov5693) in ov5693_probe()
1278 ov5693->dev = &client->dev; in ov5693_probe()
1280 ov5693->regmap = devm_cci_regmap_init_i2c(client, 16); in ov5693_probe()
1281 if (IS_ERR(ov5693->regmap)) in ov5693_probe()
1282 return PTR_ERR(ov5693->regmap); in ov5693_probe()
1284 ret = ov5693_check_hwcfg(ov5693); in ov5693_probe()
1288 mutex_init(&ov5693->lock); in ov5693_probe()
1290 v4l2_i2c_subdev_init(&ov5693->sd, client, &ov5693_ops); in ov5693_probe()
1292 ov5693->xvclk = devm_clk_get_optional(&client->dev, "xvclk"); in ov5693_probe()
1293 if (IS_ERR(ov5693->xvclk)) in ov5693_probe()
1294 return dev_err_probe(&client->dev, PTR_ERR(ov5693->xvclk), in ov5693_probe()
1296 PTR_ERR(ov5693->xvclk)); in ov5693_probe()
1298 if (ov5693->xvclk) { in ov5693_probe()
1299 xvclk_rate = clk_get_rate(ov5693->xvclk); in ov5693_probe()
1315 ret = ov5693_configure_gpios(ov5693); in ov5693_probe()
1319 ret = ov5693_get_regulators(ov5693); in ov5693_probe()
1324 ov5693->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in ov5693_probe()
1325 ov5693->pad.flags = MEDIA_PAD_FL_SOURCE; in ov5693_probe()
1326 ov5693->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; in ov5693_probe()
1328 ov5693->mode.crop = ov5693_default_crop; in ov5693_probe()
1329 ov5693->mode.format = ov5693_default_fmt; in ov5693_probe()
1330 ov5693->mode.vts = __ov5693_calc_vts(ov5693->mode.format.height); in ov5693_probe()
1332 ret = ov5693_init_controls(ov5693); in ov5693_probe()
1336 ret = media_entity_pads_init(&ov5693->sd.entity, 1, &ov5693->pad); in ov5693_probe()
1347 ret = ov5693_sensor_powerup(ov5693); in ov5693_probe()
1351 ret = ov5693_detect(ov5693); in ov5693_probe()
1359 ret = v4l2_async_register_subdev_sensor(&ov5693->sd); in ov5693_probe()
1376 ov5693_sensor_powerdown(ov5693); in ov5693_probe()
1378 media_entity_cleanup(&ov5693->sd.entity); in ov5693_probe()
1380 v4l2_ctrl_handler_free(&ov5693->ctrls.handler); in ov5693_probe()
1388 struct ov5693_device *ov5693 = to_ov5693_sensor(sd); in ov5693_remove() local
1391 media_entity_cleanup(&ov5693->sd.entity); in ov5693_remove()
1392 v4l2_ctrl_handler_free(&ov5693->ctrls.handler); in ov5693_remove()
1393 mutex_destroy(&ov5693->lock); in ov5693_remove()
1401 ov5693_sensor_powerdown(ov5693); in ov5693_remove()
1416 { .compatible = "ovti,ov5693", },
1423 .name = "ov5693",