Lines Matching +full:st +full:- +full:vgxy61

1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for VGXY61 global shutter sensor family driver
21 #include <media/mipi-csi2.h>
22 #include <media/v4l2-async.h>
23 #include <media/v4l2-cci.h>
24 #include <media/v4l2-ctrls.h>
25 #include <media/v4l2-device.h>
26 #include <media/v4l2-event.h>
27 #include <media/v4l2-fwnode.h>
28 #include <media/v4l2-subdev.h>
463 * Freq range is [6Mhz-27Mhz] already checked. in compute_pll_parameters_by_freq()
464 * Output of divider should be in [6Mhz-12Mhz[. in compute_pll_parameters_by_freq()
482 return div64_u64((u64)sensor->data_rate_in_mbps * sensor->nb_of_lane, in get_pixel_rate()
483 get_bpp_by_code(sensor->fmt.code)); in get_pixel_rate()
493 return &container_of(ctrl->handler, struct vgxy61_dev, in ctrl_to_sd()
494 ctrl_handler)->sd; in ctrl_to_sd()
499 struct i2c_adapter *adapter = sensor->i2c_client->adapter; in get_chunk_size()
502 if (adapter->quirks && adapter->quirks->max_write_len) in get_chunk_size()
503 max_write_len = adapter->quirks->max_write_len - 2; in get_chunk_size()
519 ret = regmap_bulk_write(sensor->regmap, CCI_REG_ADDR(reg), in vgxy61_write_array()
523 nb -= sz; in vgxy61_write_array()
541 false, sensor->regmap, reg, &val, NULL); in vgxy61_poll_reg()
560 unsigned int binning_scale = sensor->current_mode->crop.height / in vgxy61_check_bw()
561 sensor->current_mode->height; in vgxy61_check_bw()
562 u8 bpp = get_bpp_by_code(sensor->fmt.code); in vgxy61_check_bw()
567 line_rate = sensor->nb_of_lane * (u64)sensor->data_rate_in_mbps * in vgxy61_check_bw()
568 sensor->line_length; in vgxy61_check_bw()
569 max_bit_per_line = div64_u64(line_rate, sensor->pclk) - mipi_margin; in vgxy61_check_bw()
570 bit_per_line = (bpp * sensor->current_mode->width) / binning_scale; in vgxy61_check_bw()
572 return bit_per_line > max_bit_per_line ? -EINVAL : 0; in vgxy61_check_bw()
580 cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_SHORT, 0, &ret); in vgxy61_apply_exposure()
581 cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_LONG, in vgxy61_apply_exposure()
582 sensor->expo_long, &ret); in vgxy61_apply_exposure()
583 cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_SHORT, in vgxy61_apply_exposure()
584 sensor->expo_short, &ret); in vgxy61_apply_exposure()
594 sensor->supplies[i].supply = vgxy61_supply_name[i]; in vgxy61_get_regulators()
596 return devm_regulator_bulk_get(&sensor->i2c_client->dev, in vgxy61_get_regulators()
598 sensor->supplies); in vgxy61_get_regulators()
603 gpiod_set_value_cansleep(sensor->reset_gpio, 0); in vgxy61_apply_reset()
605 gpiod_set_value_cansleep(sensor->reset_gpio, 1); in vgxy61_apply_reset()
607 gpiod_set_value_cansleep(sensor->reset_gpio, 0); in vgxy61_apply_reset()
617 fmt->code = code; in vgxy61_fill_framefmt()
618 fmt->width = mode->width; in vgxy61_fill_framefmt()
619 fmt->height = mode->height; in vgxy61_fill_framefmt()
620 fmt->colorspace = V4L2_COLORSPACE_RAW; in vgxy61_fill_framefmt()
621 fmt->field = V4L2_FIELD_NONE; in vgxy61_fill_framefmt()
622 fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in vgxy61_fill_framefmt()
623 fmt->quantization = V4L2_QUANTIZATION_DEFAULT; in vgxy61_fill_framefmt()
624 fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; in vgxy61_fill_framefmt()
636 if (vgxy61_supported_codes[index].code == fmt->code) in vgxy61_try_fmt_internal()
642 mode = v4l2_find_nearest_size(sensor->sensor_modes, in vgxy61_try_fmt_internal()
643 sensor->sensor_modes_nb, width, height, in vgxy61_try_fmt_internal()
644 fmt->width, fmt->height); in vgxy61_try_fmt_internal()
660 switch (sel->target) { in vgxy61_get_selection()
662 sel->r = sensor->current_mode->crop; in vgxy61_get_selection()
667 sel->r.top = 0; in vgxy61_get_selection()
668 sel->r.left = 0; in vgxy61_get_selection()
669 sel->r.width = sensor->sensor_width; in vgxy61_get_selection()
670 sel->r.height = sensor->sensor_height; in vgxy61_get_selection()
674 return -EINVAL; in vgxy61_get_selection()
681 if (code->index >= ARRAY_SIZE(vgxy61_supported_codes)) in vgxy61_enum_mbus_code()
682 return -EINVAL; in vgxy61_enum_mbus_code()
684 code->code = vgxy61_supported_codes[code->index].code; in vgxy61_enum_mbus_code()
696 mutex_lock(&sensor->lock); in vgxy61_get_fmt()
698 if (format->which == V4L2_SUBDEV_FORMAT_TRY) in vgxy61_get_fmt()
699 fmt = v4l2_subdev_state_get_format(sd_state, format->pad); in vgxy61_get_fmt()
701 fmt = &sensor->fmt; in vgxy61_get_fmt()
703 format->format = *fmt; in vgxy61_get_fmt()
705 mutex_unlock(&sensor->lock); in vgxy61_get_fmt()
713 u16 min_vblank = VGXY61_MIN_FRAME_LENGTH - in vgxy61_get_vblank_min()
714 sensor->current_mode->crop.height; in vgxy61_get_vblank_min()
716 u16 min_vblank_hdr = VGXY61_MIN_EXPOSURE + sensor->rot_term + 1; in vgxy61_get_vblank_min()
729 if (fse->index >= sensor->sensor_modes_nb) in vgxy61_enum_frame_size()
730 return -EINVAL; in vgxy61_enum_frame_size()
732 fse->min_width = sensor->sensor_modes[fse->index].width; in vgxy61_enum_frame_size()
733 fse->max_width = fse->min_width; in vgxy61_enum_frame_size()
734 fse->min_height = sensor->sensor_modes[fse->index].height; in vgxy61_enum_frame_size()
735 fse->max_height = fse->min_height; in vgxy61_enum_frame_size()
742 sensor->analog_gain = target; in vgxy61_update_analog_gain()
744 if (sensor->streaming) in vgxy61_update_analog_gain()
745 return cci_write(sensor->regmap, VGXY61_REG_ANALOG_GAIN, target, in vgxy61_update_analog_gain()
760 cci_write(sensor->regmap, VGXY61_REG_DIGITAL_GAIN_LONG, digital_gain, in vgxy61_apply_digital_gain()
762 cci_write(sensor->regmap, VGXY61_REG_DIGITAL_GAIN_SHORT, digital_gain, in vgxy61_apply_digital_gain()
770 sensor->digital_gain = target; in vgxy61_update_digital_gain()
772 if (sensor->streaming) in vgxy61_update_digital_gain()
773 return vgxy61_apply_digital_gain(sensor, sensor->digital_gain); in vgxy61_update_digital_gain()
788 return cci_write(sensor->regmap, VGXY61_REG_PATGEN_CTRL, reg, NULL); in vgxy61_apply_patgen()
793 sensor->pattern = pattern; in vgxy61_update_patgen()
795 if (sensor->streaming) in vgxy61_update_patgen()
796 return vgxy61_apply_patgen(sensor, sensor->pattern); in vgxy61_update_patgen()
810 return cci_update_bits(sensor->regmap, VGXY61_REG_SIGNALS_CTRL, in vgxy61_apply_gpiox_strobe_mode()
822 sensor->strobe_mode = VGXY61_STROBE_ENABLED; in vgxy61_update_gpios_strobe_mode()
826 sensor->strobe_mode = VGXY61_STROBE_LONG; in vgxy61_update_gpios_strobe_mode()
834 if (!sensor->streaming) in vgxy61_update_gpios_strobe_mode()
839 sensor->strobe_mode, in vgxy61_update_gpios_strobe_mode()
853 if (sensor->streaming) in vgxy61_update_gpios_strobe_polarity()
854 return -EBUSY; in vgxy61_update_gpios_strobe_polarity()
856 cci_write(sensor->regmap, VGXY61_REG_GPIO_0_CTRL, polarity << 1, &ret); in vgxy61_update_gpios_strobe_polarity()
857 cci_write(sensor->regmap, VGXY61_REG_GPIO_1_CTRL, polarity << 1, &ret); in vgxy61_update_gpios_strobe_polarity()
858 cci_write(sensor->regmap, VGXY61_REG_GPIO_2_CTRL, polarity << 1, &ret); in vgxy61_update_gpios_strobe_polarity()
859 cci_write(sensor->regmap, VGXY61_REG_GPIO_3_CTRL, polarity << 1, &ret); in vgxy61_update_gpios_strobe_polarity()
860 cci_write(sensor->regmap, VGXY61_REG_SIGNALS_POLARITY_CTRL, polarity, in vgxy61_update_gpios_strobe_polarity()
877 ((sensor->frame_length - sensor->current_mode->crop.height - in vgxy61_get_expo_long_max()
878 sensor->rot_term) * short_expo_ratio) - 1; in vgxy61_get_expo_long_max()
885 (((sensor->frame_length - VGXY61_EXPOS_ROT_TERM) * in vgxy61_get_expo_long_max()
886 short_expo_ratio) / (short_expo_ratio + 1)) - 1; in vgxy61_get_expo_long_max()
892 third_rot_max_expo = (sensor->frame_length / 71) * short_expo_ratio; in vgxy61_get_expo_long_max()
902 struct i2c_client *client = sensor->i2c_client; in vgxy61_update_exposure()
943 expo_long_max = sensor->frame_length - VGXY61_EXPOS_ROT_TERM; in vgxy61_update_exposure()
955 dev_warn(&client->dev, "Exposure %d too high, clamping to %d\n", in vgxy61_update_exposure()
961 sensor->expo_long = new_expo_long; in vgxy61_update_exposure()
962 sensor->expo_short = new_expo_short; in vgxy61_update_exposure()
963 sensor->expo_max = expo_long_max; in vgxy61_update_exposure()
964 sensor->expo_min = expo_long_min; in vgxy61_update_exposure()
966 if (sensor->streaming) in vgxy61_update_exposure()
973 return cci_write(sensor->regmap, VGXY61_REG_FRAME_LENGTH, in vgxy61_apply_framelength()
974 sensor->frame_length, NULL); in vgxy61_apply_framelength()
982 sensor->vblank_min = vgxy61_get_vblank_min(sensor, hdr); in vgxy61_update_vblank()
983 sensor->vblank = max(sensor->vblank_min, vblank); in vgxy61_update_vblank()
984 sensor->frame_length = sensor->current_mode->crop.height + in vgxy61_update_vblank()
985 sensor->vblank; in vgxy61_update_vblank()
988 ret = vgxy61_update_exposure(sensor, sensor->expo_long, hdr); in vgxy61_update_vblank()
992 if (sensor->streaming) in vgxy61_update_vblank()
1002 return cci_write(sensor->regmap, VGXY61_REG_HDR_CTRL, index2val[index], in vgxy61_apply_hdr()
1016 ret = vgxy61_update_vblank(sensor, sensor->vblank, index); in vgxy61_update_hdr()
1025 sensor->hdr = index; in vgxy61_update_hdr()
1027 if (sensor->streaming) in vgxy61_update_hdr()
1028 return vgxy61_apply_hdr(sensor, sensor->hdr); in vgxy61_update_hdr()
1037 ret = vgxy61_apply_hdr(sensor, sensor->hdr); in vgxy61_apply_settings()
1049 ret = cci_write(sensor->regmap, VGXY61_REG_ANALOG_GAIN, in vgxy61_apply_settings()
1050 sensor->analog_gain, NULL); in vgxy61_apply_settings()
1053 ret = vgxy61_apply_digital_gain(sensor, sensor->digital_gain); in vgxy61_apply_settings()
1057 ret = cci_write(sensor->regmap, VGXY61_REG_ORIENTATION, in vgxy61_apply_settings()
1058 sensor->hflip | (sensor->vflip << 1), NULL); in vgxy61_apply_settings()
1062 ret = vgxy61_apply_patgen(sensor, sensor->pattern); in vgxy61_apply_settings()
1068 sensor->strobe_mode, i); in vgxy61_apply_settings()
1078 struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd); in vgxy61_stream_enable()
1079 const struct v4l2_rect *crop = &sensor->current_mode->crop; in vgxy61_stream_enable()
1086 ret = pm_runtime_resume_and_get(&client->dev); in vgxy61_stream_enable()
1090 cci_write(sensor->regmap, VGXY61_REG_FORMAT_CTRL, in vgxy61_stream_enable()
1091 get_bpp_by_code(sensor->fmt.code), &ret); in vgxy61_stream_enable()
1092 cci_write(sensor->regmap, VGXY61_REG_OIF_ROI0_CTRL, in vgxy61_stream_enable()
1093 get_data_type_by_code(sensor->fmt.code), &ret); in vgxy61_stream_enable()
1095 cci_write(sensor->regmap, VGXY61_REG_READOUT_CTRL, in vgxy61_stream_enable()
1096 sensor->current_mode->bin_mode, &ret); in vgxy61_stream_enable()
1097 cci_write(sensor->regmap, VGXY61_REG_ROI0_START_H, crop->left, &ret); in vgxy61_stream_enable()
1098 cci_write(sensor->regmap, VGXY61_REG_ROI0_END_H, in vgxy61_stream_enable()
1099 crop->left + crop->width - 1, &ret); in vgxy61_stream_enable()
1100 cci_write(sensor->regmap, VGXY61_REG_ROI0_START_V, crop->top, &ret); in vgxy61_stream_enable()
1101 cci_write(sensor->regmap, VGXY61_REG_ROI0_END_V, in vgxy61_stream_enable()
1102 crop->top + crop->height - 1, &ret); in vgxy61_stream_enable()
1110 ret = cci_write(sensor->regmap, VGXY61_REG_STREAMING, in vgxy61_stream_enable()
1126 __v4l2_ctrl_grab(sensor->vflip_ctrl, true); in vgxy61_stream_enable()
1127 __v4l2_ctrl_grab(sensor->hflip_ctrl, true); in vgxy61_stream_enable()
1132 pm_runtime_put(&client->dev); in vgxy61_stream_enable()
1138 struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd); in vgxy61_stream_disable()
1141 ret = cci_write(sensor->regmap, VGXY61_REG_STREAMING, in vgxy61_stream_disable()
1156 __v4l2_ctrl_grab(sensor->vflip_ctrl, false); in vgxy61_stream_disable()
1157 __v4l2_ctrl_grab(sensor->hflip_ctrl, false); in vgxy61_stream_disable()
1162 pm_runtime_put(&client->dev); in vgxy61_stream_disable()
1172 mutex_lock(&sensor->lock); in vgxy61_s_stream()
1177 sensor->streaming = enable; in vgxy61_s_stream()
1179 mutex_unlock(&sensor->lock); in vgxy61_s_stream()
1193 mutex_lock(&sensor->lock); in vgxy61_set_fmt()
1195 if (sensor->streaming) { in vgxy61_set_fmt()
1196 ret = -EBUSY; in vgxy61_set_fmt()
1200 ret = vgxy61_try_fmt_internal(sd, &format->format, &new_mode); in vgxy61_set_fmt()
1204 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { in vgxy61_set_fmt()
1206 *fmt = format->format; in vgxy61_set_fmt()
1207 } else if (sensor->current_mode != new_mode || in vgxy61_set_fmt()
1208 sensor->fmt.code != format->format.code) { in vgxy61_set_fmt()
1209 fmt = &sensor->fmt; in vgxy61_set_fmt()
1210 *fmt = format->format; in vgxy61_set_fmt()
1212 sensor->current_mode = new_mode; in vgxy61_set_fmt()
1216 VGXY61_FRAME_LENGTH_DEF - in vgxy61_set_fmt()
1217 new_mode->crop.height, in vgxy61_set_fmt()
1218 sensor->hdr); in vgxy61_set_fmt()
1221 __v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_ctrl, in vgxy61_set_fmt()
1223 __v4l2_ctrl_modify_range(sensor->vblank_ctrl, in vgxy61_set_fmt()
1224 sensor->vblank_min, in vgxy61_set_fmt()
1225 0xffff - new_mode->crop.height, in vgxy61_set_fmt()
1226 1, sensor->vblank); in vgxy61_set_fmt()
1227 __v4l2_ctrl_s_ctrl(sensor->vblank_ctrl, sensor->vblank); in vgxy61_set_fmt()
1228 __v4l2_ctrl_modify_range(sensor->expo_ctrl, sensor->expo_min, in vgxy61_set_fmt()
1229 sensor->expo_max, 1, in vgxy61_set_fmt()
1230 sensor->expo_long); in vgxy61_set_fmt()
1234 mutex_unlock(&sensor->lock); in vgxy61_set_fmt()
1245 vgxy61_fill_framefmt(sensor, sensor->current_mode, &fmt.format, in vgxy61_init_state()
1255 const struct vgxy61_mode_info *cur_mode = sensor->current_mode; in vgxy61_s_ctrl()
1258 switch (ctrl->id) { in vgxy61_s_ctrl()
1260 ret = vgxy61_update_exposure(sensor, ctrl->val, sensor->hdr); in vgxy61_s_ctrl()
1261 ctrl->val = sensor->expo_long; in vgxy61_s_ctrl()
1264 ret = vgxy61_update_analog_gain(sensor, ctrl->val); in vgxy61_s_ctrl()
1267 ret = vgxy61_update_digital_gain(sensor, ctrl->val); in vgxy61_s_ctrl()
1271 if (sensor->streaming) { in vgxy61_s_ctrl()
1272 ret = -EBUSY; in vgxy61_s_ctrl()
1275 if (ctrl->id == V4L2_CID_VFLIP) in vgxy61_s_ctrl()
1276 sensor->vflip = ctrl->val; in vgxy61_s_ctrl()
1277 if (ctrl->id == V4L2_CID_HFLIP) in vgxy61_s_ctrl()
1278 sensor->hflip = ctrl->val; in vgxy61_s_ctrl()
1282 ret = vgxy61_update_patgen(sensor, ctrl->val); in vgxy61_s_ctrl()
1285 ret = vgxy61_update_hdr(sensor, ctrl->val); in vgxy61_s_ctrl()
1287 __v4l2_ctrl_modify_range(sensor->vblank_ctrl, in vgxy61_s_ctrl()
1288 sensor->vblank_min, in vgxy61_s_ctrl()
1289 0xffff - cur_mode->crop.height, in vgxy61_s_ctrl()
1290 1, sensor->vblank); in vgxy61_s_ctrl()
1291 __v4l2_ctrl_modify_range(sensor->expo_ctrl, sensor->expo_min, in vgxy61_s_ctrl()
1292 sensor->expo_max, 1, in vgxy61_s_ctrl()
1293 sensor->expo_long); in vgxy61_s_ctrl()
1296 ret = vgxy61_update_vblank(sensor, ctrl->val, sensor->hdr); in vgxy61_s_ctrl()
1298 __v4l2_ctrl_modify_range(sensor->expo_ctrl, sensor->expo_min, in vgxy61_s_ctrl()
1299 sensor->expo_max, 1, in vgxy61_s_ctrl()
1300 sensor->expo_long); in vgxy61_s_ctrl()
1303 ret = -EINVAL; in vgxy61_s_ctrl()
1317 struct v4l2_ctrl_handler *hdl = &sensor->ctrl_handler; in vgxy61_init_controls()
1318 const struct vgxy61_mode_info *cur_mode = sensor->current_mode; in vgxy61_init_controls()
1325 hdl->lock = &sensor->lock; in vgxy61_init_controls()
1327 sensor->analog_gain); in vgxy61_init_controls()
1329 sensor->digital_gain); in vgxy61_init_controls()
1331 ARRAY_SIZE(vgxy61_test_pattern_menu) - 1, in vgxy61_init_controls()
1334 sensor->line_length, 1, in vgxy61_init_controls()
1335 sensor->line_length - cur_mode->width); in vgxy61_init_controls()
1337 ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in vgxy61_init_controls()
1339 ARRAY_SIZE(link_freq) - 1, 0, link_freq); in vgxy61_init_controls()
1341 ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in vgxy61_init_controls()
1343 ARRAY_SIZE(vgxy61_hdr_mode_menu) - 1, 0, in vgxy61_init_controls()
1350 sensor->pixel_rate_ctrl = v4l2_ctrl_new_std(hdl, ops, in vgxy61_init_controls()
1354 if (sensor->pixel_rate_ctrl) in vgxy61_init_controls()
1355 sensor->pixel_rate_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; in vgxy61_init_controls()
1356 sensor->expo_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, in vgxy61_init_controls()
1357 sensor->expo_min, in vgxy61_init_controls()
1358 sensor->expo_max, 1, in vgxy61_init_controls()
1359 sensor->expo_long); in vgxy61_init_controls()
1360 sensor->vblank_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VBLANK, in vgxy61_init_controls()
1361 sensor->vblank_min, in vgxy61_init_controls()
1362 0xffff - cur_mode->crop.height, in vgxy61_init_controls()
1363 1, sensor->vblank); in vgxy61_init_controls()
1364 sensor->vflip_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, in vgxy61_init_controls()
1365 0, 1, 1, sensor->vflip); in vgxy61_init_controls()
1366 sensor->hflip_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, in vgxy61_init_controls()
1367 0, 1, 1, sensor->hflip); in vgxy61_init_controls()
1369 if (hdl->error) { in vgxy61_init_controls()
1370 ret = hdl->error; in vgxy61_init_controls()
1374 ret = v4l2_fwnode_device_parse(&sensor->i2c_client->dev, &props); in vgxy61_init_controls()
1382 sensor->sd.ctrl_handler = hdl; in vgxy61_init_controls()
1425 struct i2c_client *client = sensor->i2c_client; in vgxy61_tx_from_ep()
1435 return -EINVAL; in vgxy61_tx_from_ep()
1439 dev_err(&client->dev, "invalid data lane number %d\n", l_nb); in vgxy61_tx_from_ep()
1447 log2phy[l] = ep.bus.mipi_csi2.data_lanes[l - 1]; in vgxy61_tx_from_ep()
1465 dev_err(&client->dev, "clk lane must be map to physical lane 0\n"); in vgxy61_tx_from_ep()
1468 sensor->oif_ctrl = (polarities[4] << 15) + ((phy2log[4] - 1) << 13) + in vgxy61_tx_from_ep()
1469 (polarities[3] << 12) + ((phy2log[3] - 1) << 10) + in vgxy61_tx_from_ep()
1470 (polarities[2] << 9) + ((phy2log[2] - 1) << 7) + in vgxy61_tx_from_ep()
1471 (polarities[1] << 6) + ((phy2log[1] - 1) << 4) + in vgxy61_tx_from_ep()
1474 sensor->nb_of_lane = l_nb; in vgxy61_tx_from_ep()
1476 dev_dbg(&client->dev, "tx uses %d lanes", l_nb); in vgxy61_tx_from_ep()
1478 dev_dbg(&client->dev, "log2phy[%d] = %d\n", i, log2phy[i]); in vgxy61_tx_from_ep()
1479 dev_dbg(&client->dev, "phy2log[%d] = %d\n", i, phy2log[i]); in vgxy61_tx_from_ep()
1480 dev_dbg(&client->dev, "polarity[%d] = %d\n", i, polarities[i]); in vgxy61_tx_from_ep()
1482 dev_dbg(&client->dev, "oif_ctrl = 0x%04x\n", sensor->oif_ctrl); in vgxy61_tx_from_ep()
1491 return -EINVAL; in vgxy61_tx_from_ep()
1501 compute_pll_parameters_by_freq(sensor->clk_freq, &prediv, &mult); in vgxy61_configure()
1502 sensor_freq = (mult * sensor->clk_freq) / prediv; in vgxy61_configure()
1504 sensor->data_rate_in_mbps = sensor_freq; in vgxy61_configure()
1506 sensor->pclk = sensor_freq / 5; in vgxy61_configure()
1508 cci_read(sensor->regmap, VGXY61_REG_LINE_LENGTH, &line_length, &ret); in vgxy61_configure()
1511 sensor->line_length = (u16)line_length; in vgxy61_configure()
1512 cci_write(sensor->regmap, VGXY61_REG_EXT_CLOCK, sensor->clk_freq, &ret); in vgxy61_configure()
1513 cci_write(sensor->regmap, VGXY61_REG_CLK_PLL_PREDIV, prediv, &ret); in vgxy61_configure()
1514 cci_write(sensor->regmap, VGXY61_REG_CLK_SYS_PLL_MULT, mult, &ret); in vgxy61_configure()
1515 cci_write(sensor->regmap, VGXY61_REG_OIF_CTRL, sensor->oif_ctrl, &ret); in vgxy61_configure()
1516 cci_write(sensor->regmap, VGXY61_REG_FRAME_CONTENT_CTRL, 0, &ret); in vgxy61_configure()
1517 cci_write(sensor->regmap, VGXY61_REG_BYPASS_CTRL, 4, &ret); in vgxy61_configure()
1520 vgxy61_update_gpios_strobe_polarity(sensor, sensor->gpios_polarity); in vgxy61_configure()
1522 cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_GR, 0x800, &ret); in vgxy61_configure()
1523 cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_R, 0x800, &ret); in vgxy61_configure()
1524 cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_B, 0x800, &ret); in vgxy61_configure()
1525 cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_GB, 0x800, &ret); in vgxy61_configure()
1526 cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_GR, 0x800, &ret); in vgxy61_configure()
1527 cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_R, 0x800, &ret); in vgxy61_configure()
1528 cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_B, 0x800, &ret); in vgxy61_configure()
1529 cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_GB, 0x800, &ret); in vgxy61_configure()
1538 struct i2c_client *client = sensor->i2c_client; in vgxy61_patch()
1544 cci_write(sensor->regmap, VGXY61_REG_STBY, 0x10, &ret); in vgxy61_patch()
1549 cci_read(sensor->regmap, VGXY61_REG_FWPATCH_REVISION, &patch, &ret); in vgxy61_patch()
1556 dev_err(&client->dev, in vgxy61_patch()
1562 return -ENODEV; in vgxy61_patch()
1564 dev_dbg(&client->dev, "patch %u.%u.%u applied\n", in vgxy61_patch()
1572 struct i2c_client *client = sensor->i2c_client; in vgxy61_detect_cut_version()
1576 ret = cci_read(sensor->regmap, VGXY61_REG_REVISION, &device_rev, NULL); in vgxy61_detect_cut_version()
1582 dev_dbg(&client->dev, "Cut1 detected\n"); in vgxy61_detect_cut_version()
1583 dev_err(&client->dev, "Cut1 not supported by this driver\n"); in vgxy61_detect_cut_version()
1584 return -ENODEV; in vgxy61_detect_cut_version()
1586 dev_dbg(&client->dev, "Cut2 detected\n"); in vgxy61_detect_cut_version()
1589 dev_dbg(&client->dev, "Cut3 detected\n"); in vgxy61_detect_cut_version()
1592 dev_err(&client->dev, "Unable to detect cut version\n"); in vgxy61_detect_cut_version()
1593 return -ENODEV; in vgxy61_detect_cut_version()
1599 struct i2c_client *client = sensor->i2c_client; in vgxy61_detect()
1600 u64 st, id = 0; in vgxy61_detect() local
1603 ret = cci_read(sensor->regmap, VGXY61_REG_MODEL_ID, &id, NULL); in vgxy61_detect()
1607 dev_warn(&client->dev, "Unsupported sensor id %x\n", (u16)id); in vgxy61_detect()
1608 return -ENODEV; in vgxy61_detect()
1610 dev_dbg(&client->dev, "detected sensor id = 0x%04x\n", (u16)id); in vgxy61_detect()
1611 sensor->id = id; in vgxy61_detect()
1618 ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL); in vgxy61_detect()
1620 return st; in vgxy61_detect()
1621 if (st != VGXY61_NVM_OK) in vgxy61_detect()
1622 dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st); in vgxy61_detect()
1640 sensor->supplies); in vgxy61_power_on()
1642 dev_err(&client->dev, "failed to enable regulators %d\n", ret); in vgxy61_power_on()
1646 ret = clk_prepare_enable(sensor->xclk); in vgxy61_power_on()
1648 dev_err(&client->dev, "failed to enable clock %d\n", ret); in vgxy61_power_on()
1652 if (sensor->reset_gpio) { in vgxy61_power_on()
1655 dev_err(&client->dev, "sensor reset failed %d\n", ret); in vgxy61_power_on()
1662 dev_err(&client->dev, "sensor detect failed %d\n", ret); in vgxy61_power_on()
1668 dev_err(&client->dev, "sensor patch failed %d\n", ret); in vgxy61_power_on()
1674 dev_err(&client->dev, "sensor configuration failed %d\n", ret); in vgxy61_power_on()
1681 clk_disable_unprepare(sensor->xclk); in vgxy61_power_on()
1684 sensor->supplies); in vgxy61_power_on()
1695 clk_disable_unprepare(sensor->xclk); in vgxy61_power_off()
1697 sensor->supplies); in vgxy61_power_off()
1703 if (sensor->id == VG5761_MODEL_ID) { in vgxy61_fill_sensor_param()
1704 sensor->sensor_width = VGX761_WIDTH; in vgxy61_fill_sensor_param()
1705 sensor->sensor_height = VGX761_HEIGHT; in vgxy61_fill_sensor_param()
1706 sensor->sensor_modes = vgx761_mode_data; in vgxy61_fill_sensor_param()
1707 sensor->sensor_modes_nb = ARRAY_SIZE(vgx761_mode_data); in vgxy61_fill_sensor_param()
1708 sensor->default_mode = &vgx761_mode_data[VGX761_DEFAULT_MODE]; in vgxy61_fill_sensor_param()
1709 sensor->rot_term = VGX761_SHORT_ROT_TERM; in vgxy61_fill_sensor_param()
1710 } else if (sensor->id == VG5661_MODEL_ID) { in vgxy61_fill_sensor_param()
1711 sensor->sensor_width = VGX661_WIDTH; in vgxy61_fill_sensor_param()
1712 sensor->sensor_height = VGX661_HEIGHT; in vgxy61_fill_sensor_param()
1713 sensor->sensor_modes = vgx661_mode_data; in vgxy61_fill_sensor_param()
1714 sensor->sensor_modes_nb = ARRAY_SIZE(vgx661_mode_data); in vgxy61_fill_sensor_param()
1715 sensor->default_mode = &vgx661_mode_data[VGX661_DEFAULT_MODE]; in vgxy61_fill_sensor_param()
1716 sensor->rot_term = VGX661_SHORT_ROT_TERM; in vgxy61_fill_sensor_param()
1721 sensor->current_mode = sensor->default_mode; in vgxy61_fill_sensor_param()
1726 struct device *dev = &client->dev; in vgxy61_probe()
1733 return -ENOMEM; in vgxy61_probe()
1735 sensor->i2c_client = client; in vgxy61_probe()
1736 sensor->streaming = false; in vgxy61_probe()
1737 sensor->hdr = VGXY61_NO_HDR; in vgxy61_probe()
1738 sensor->expo_long = 200; in vgxy61_probe()
1739 sensor->expo_short = 0; in vgxy61_probe()
1740 sensor->hflip = false; in vgxy61_probe()
1741 sensor->vflip = false; in vgxy61_probe()
1742 sensor->analog_gain = 0; in vgxy61_probe()
1743 sensor->digital_gain = 256; in vgxy61_probe()
1745 sensor->regmap = devm_cci_regmap_init_i2c(client, 16); in vgxy61_probe()
1746 if (IS_ERR(sensor->regmap)) { in vgxy61_probe()
1747 ret = PTR_ERR(sensor->regmap); in vgxy61_probe()
1754 return -EINVAL; in vgxy61_probe()
1764 sensor->xclk = devm_clk_get(dev, NULL); in vgxy61_probe()
1765 if (IS_ERR(sensor->xclk)) { in vgxy61_probe()
1767 return PTR_ERR(sensor->xclk); in vgxy61_probe()
1769 sensor->clk_freq = clk_get_rate(sensor->xclk); in vgxy61_probe()
1770 if (sensor->clk_freq < 6 * HZ_PER_MHZ || in vgxy61_probe()
1771 sensor->clk_freq > 27 * HZ_PER_MHZ) { in vgxy61_probe()
1772 dev_err(dev, "Only 6Mhz-27Mhz clock range supported. provide %lu MHz\n", in vgxy61_probe()
1773 sensor->clk_freq / HZ_PER_MHZ); in vgxy61_probe()
1774 return -EINVAL; in vgxy61_probe()
1776 sensor->gpios_polarity = in vgxy61_probe()
1777 device_property_read_bool(dev, "st,strobe-gpios-polarity"); in vgxy61_probe()
1779 v4l2_i2c_subdev_init(&sensor->sd, client, &vgxy61_subdev_ops); in vgxy61_probe()
1780 sensor->sd.internal_ops = &vgxy61_internal_ops; in vgxy61_probe()
1781 sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | in vgxy61_probe()
1783 sensor->pad.flags = MEDIA_PAD_FL_SOURCE; in vgxy61_probe()
1784 sensor->sd.entity.ops = &vgxy61_subdev_entity_ops; in vgxy61_probe()
1785 sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; in vgxy61_probe()
1787 sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset", in vgxy61_probe()
1792 dev_err(&client->dev, "failed to get regulators %d\n", ret); in vgxy61_probe()
1801 vgxy61_fill_framefmt(sensor, sensor->current_mode, &sensor->fmt, in vgxy61_probe()
1804 mutex_init(&sensor->lock); in vgxy61_probe()
1806 ret = vgxy61_update_hdr(sensor, sensor->hdr); in vgxy61_probe()
1812 dev_err(&client->dev, "controls initialization failed %d\n", in vgxy61_probe()
1817 ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad); in vgxy61_probe()
1819 dev_err(&client->dev, "pads init failed %d\n", ret); in vgxy61_probe()
1828 ret = v4l2_async_register_subdev(&sensor->sd); in vgxy61_probe()
1830 dev_err(&client->dev, "async subdev register failed %d\n", ret); in vgxy61_probe()
1834 pm_runtime_set_autosuspend_delay(&client->dev, 1000); in vgxy61_probe()
1835 pm_runtime_use_autosuspend(&client->dev); in vgxy61_probe()
1837 dev_dbg(&client->dev, "vgxy61 probe successfully\n"); in vgxy61_probe()
1842 pm_runtime_disable(&client->dev); in vgxy61_probe()
1843 pm_runtime_set_suspended(&client->dev); in vgxy61_probe()
1844 media_entity_cleanup(&sensor->sd.entity); in vgxy61_probe()
1846 v4l2_ctrl_handler_free(sensor->sd.ctrl_handler); in vgxy61_probe()
1848 mutex_destroy(&sensor->lock); in vgxy61_probe()
1859 v4l2_async_unregister_subdev(&sensor->sd); in vgxy61_remove()
1860 mutex_destroy(&sensor->lock); in vgxy61_remove()
1861 media_entity_cleanup(&sensor->sd.entity); in vgxy61_remove()
1863 pm_runtime_disable(&client->dev); in vgxy61_remove()
1864 if (!pm_runtime_status_suspended(&client->dev)) in vgxy61_remove()
1865 vgxy61_power_off(&client->dev); in vgxy61_remove()
1866 pm_runtime_set_suspended(&client->dev); in vgxy61_remove()
1870 { .compatible = "st,st-vgxy61" },
1881 .name = "vgxy61",
1891 MODULE_AUTHOR("Benjamin Mugnier <benjamin.mugnier@foss.st.com>");
1892 MODULE_AUTHOR("Mickael Guene <mickael.guene@st.com>");
1893 MODULE_AUTHOR("Sylvain Petinot <sylvain.petinot@foss.st.com>");
1894 MODULE_DESCRIPTION("VGXY61 camera subdev driver");