Lines Matching +full:target +full:- +full:12 +full:v +full:- +full:supply

1 // SPDX-License-Identifier: GPL-2.0
11 #include <media/v4l2-cci.h>
12 #include <media/v4l2-ctrls.h>
13 #include <media/v4l2-device.h>
14 #include <media/v4l2-fwnode.h>
33 /* HBLANK control - read only */
42 #define IMX258_EXPOSURE_MAX (IMX258_VTS_MAX - IMX258_EXPOSURE_OFFSET)
163 /* V-timing */
461 * - no flip
462 * - h flip
463 * - v flip
464 * - h&v flips
467 /* 10-bit modes. */
485 "vana", /* Analog (2.8V) supply */
486 "vdig", /* Digital Core (1.2V) supply */
487 "vif", /* IF (1.8V) supply */
508 * bits per pixel being 10, and D-PHY being DDR is assumed by this function, so
513 f *= 2 * link_cfg->lf_to_pix_rate_factor; in link_freq_to_pixel_rate()
693 lockdep_assert_held(&imx258->mutex); in imx258_get_format_code()
695 i = (imx258->vflip->val ? 2 : 0) | in imx258_get_format_code()
696 (imx258->hflip->val ? 1 : 0); in imx258_get_format_code()
701 /* Open sub-device */
706 v4l2_subdev_state_get_format(fh->state, 0); in imx258_open()
710 try_fmt->width = supported_modes[0].width; in imx258_open()
711 try_fmt->height = supported_modes[0].height; in imx258_open()
712 try_fmt->code = imx258_get_format_code(imx258); in imx258_open()
713 try_fmt->field = V4L2_FIELD_NONE; in imx258_open()
716 try_crop = v4l2_subdev_state_get_crop(fh->state, 0); in imx258_open()
717 try_crop->left = IMX258_PIXEL_ARRAY_LEFT; in imx258_open()
718 try_crop->top = IMX258_PIXEL_ARRAY_TOP; in imx258_open()
719 try_crop->width = IMX258_PIXEL_ARRAY_WIDTH; in imx258_open()
720 try_crop->height = IMX258_PIXEL_ARRAY_HEIGHT; in imx258_open()
729 cci_write(imx258->regmap, IMX258_REG_GR_DIGITAL_GAIN, val, &ret); in imx258_update_digital_gain()
730 cci_write(imx258->regmap, IMX258_REG_GB_DIGITAL_GAIN, val, &ret); in imx258_update_digital_gain()
731 cci_write(imx258->regmap, IMX258_REG_R_DIGITAL_GAIN, val, &ret); in imx258_update_digital_gain()
732 cci_write(imx258->regmap, IMX258_REG_B_DIGITAL_GAIN, val, &ret); in imx258_update_digital_gain()
742 exposure_max = imx258->cur_mode->height + imx258->vblank->val - in imx258_adjust_exposure_range()
744 exposure_def = min(exposure_max, imx258->exposure->val); in imx258_adjust_exposure_range()
745 __v4l2_ctrl_modify_range(imx258->exposure, imx258->exposure->minimum, in imx258_adjust_exposure_range()
746 exposure_max, imx258->exposure->step, in imx258_adjust_exposure_range()
753 container_of(ctrl->handler, struct imx258, ctrl_handler); in imx258_set_ctrl()
754 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); in imx258_set_ctrl()
761 if (ctrl->id == V4L2_CID_VBLANK) in imx258_set_ctrl()
768 if (pm_runtime_get_if_in_use(&client->dev) == 0) in imx258_set_ctrl()
771 switch (ctrl->id) { in imx258_set_ctrl()
773 ret = cci_write(imx258->regmap, IMX258_REG_ANALOG_GAIN, in imx258_set_ctrl()
774 ctrl->val, NULL); in imx258_set_ctrl()
777 ret = cci_write(imx258->regmap, IMX258_REG_EXPOSURE, in imx258_set_ctrl()
778 ctrl->val, NULL); in imx258_set_ctrl()
781 ret = imx258_update_digital_gain(imx258, ctrl->val); in imx258_set_ctrl()
784 ret = cci_write(imx258->regmap, IMX258_REG_TEST_PATTERN, in imx258_set_ctrl()
785 ctrl->val, NULL); in imx258_set_ctrl()
788 if (!ctrl->val) { in imx258_set_ctrl()
789 ret = cci_write(imx258->regmap, IMX258_REG_HDR, in imx258_set_ctrl()
792 ret = cci_write(imx258->regmap, IMX258_REG_HDR, in imx258_set_ctrl()
796 ret = cci_write(imx258->regmap, IMX258_REG_HDR_RATIO, in imx258_set_ctrl()
801 ret = cci_write(imx258->regmap, IMX258_REG_FRM_LENGTH_LINES, in imx258_set_ctrl()
802 imx258->cur_mode->height + ctrl->val, NULL); in imx258_set_ctrl()
806 ret = cci_write(imx258->regmap, REG_MIRROR_FLIP_CONTROL, in imx258_set_ctrl()
807 (imx258->hflip->val ? in imx258_set_ctrl()
809 (imx258->vflip->val ? in imx258_set_ctrl()
814 dev_info(&client->dev, in imx258_set_ctrl()
816 ctrl->id, ctrl->val); in imx258_set_ctrl()
817 ret = -EINVAL; in imx258_set_ctrl()
821 pm_runtime_put(&client->dev); in imx258_set_ctrl()
837 if (code->index > 0) in imx258_enum_mbus_code()
838 return -EINVAL; in imx258_enum_mbus_code()
840 code->code = imx258_get_format_code(imx258); in imx258_enum_mbus_code()
850 if (fse->index >= ARRAY_SIZE(supported_modes)) in imx258_enum_frame_size()
851 return -EINVAL; in imx258_enum_frame_size()
853 if (fse->code != imx258_get_format_code(imx258)) in imx258_enum_frame_size()
854 return -EINVAL; in imx258_enum_frame_size()
856 fse->min_width = supported_modes[fse->index].width; in imx258_enum_frame_size()
857 fse->max_width = fse->min_width; in imx258_enum_frame_size()
858 fse->min_height = supported_modes[fse->index].height; in imx258_enum_frame_size()
859 fse->max_height = fse->min_height; in imx258_enum_frame_size()
868 fmt->format.width = mode->width; in imx258_update_pad_format()
869 fmt->format.height = mode->height; in imx258_update_pad_format()
870 fmt->format.code = imx258_get_format_code(imx258); in imx258_update_pad_format()
871 fmt->format.field = V4L2_FIELD_NONE; in imx258_update_pad_format()
878 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) in __imx258_get_pad_format()
879 fmt->format = *v4l2_subdev_state_get_format(sd_state, in __imx258_get_pad_format()
880 fmt->pad); in __imx258_get_pad_format()
882 imx258_update_pad_format(imx258, imx258->cur_mode, fmt); in __imx258_get_pad_format()
894 mutex_lock(&imx258->mutex); in imx258_get_pad_format()
896 mutex_unlock(&imx258->mutex); in imx258_get_pad_format()
916 mutex_lock(&imx258->mutex); in imx258_set_pad_format()
918 fmt->format.code = imx258_get_format_code(imx258); in imx258_set_pad_format()
922 fmt->format.width, fmt->format.height); in imx258_set_pad_format()
924 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in imx258_set_pad_format()
925 framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); in imx258_set_pad_format()
926 *framefmt = fmt->format; in imx258_set_pad_format()
928 imx258->cur_mode = mode; in imx258_set_pad_format()
929 __v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index); in imx258_set_pad_format()
931 link_freq = imx258->link_freq_menu_items[mode->link_freq_index]; in imx258_set_pad_format()
933 &imx258->link_freq_configs[mode->link_freq_index]; in imx258_set_pad_format()
935 link_cfg = &link_freq_cfgs->link_cfg[imx258->lane_mode_idx]; in imx258_set_pad_format()
937 __v4l2_ctrl_modify_range(imx258->pixel_rate, pixel_rate, in imx258_set_pad_format()
940 vblank_def = imx258->cur_mode->vts_def - in imx258_set_pad_format()
941 imx258->cur_mode->height; in imx258_set_pad_format()
942 vblank_min = imx258->cur_mode->vts_min - in imx258_set_pad_format()
943 imx258->cur_mode->height; in imx258_set_pad_format()
945 imx258->vblank, vblank_min, in imx258_set_pad_format()
946 IMX258_VTS_MAX - imx258->cur_mode->height, 1, in imx258_set_pad_format()
948 __v4l2_ctrl_s_ctrl(imx258->vblank, vblank_def); in imx258_set_pad_format()
950 imx258->link_freq_configs[mode->link_freq_index].pixels_per_line in imx258_set_pad_format()
951 - imx258->cur_mode->width; in imx258_set_pad_format()
952 __v4l2_ctrl_modify_range(imx258->hblank, h_blank, in imx258_set_pad_format()
956 mutex_unlock(&imx258->mutex); in imx258_set_pad_format()
970 return &imx258->cur_mode->crop; in __imx258_get_pad_crop()
980 switch (sel->target) { in imx258_get_selection()
984 mutex_lock(&imx258->mutex); in imx258_get_selection()
985 sel->r = *__imx258_get_pad_crop(imx258, sd_state, sel->pad, in imx258_get_selection()
986 sel->which); in imx258_get_selection()
987 mutex_unlock(&imx258->mutex); in imx258_get_selection()
993 sel->r.left = 0; in imx258_get_selection()
994 sel->r.top = 0; in imx258_get_selection()
995 sel->r.width = IMX258_NATIVE_WIDTH; in imx258_get_selection()
996 sel->r.height = IMX258_NATIVE_HEIGHT; in imx258_get_selection()
1002 sel->r.left = IMX258_PIXEL_ARRAY_LEFT; in imx258_get_selection()
1003 sel->r.top = IMX258_PIXEL_ARRAY_TOP; in imx258_get_selection()
1004 sel->r.width = IMX258_PIXEL_ARRAY_WIDTH; in imx258_get_selection()
1005 sel->r.height = IMX258_PIXEL_ARRAY_HEIGHT; in imx258_get_selection()
1010 return -EINVAL; in imx258_get_selection()
1016 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); in imx258_start_streaming()
1021 ret = cci_write(imx258->regmap, IMX258_REG_RESET, 0x01, NULL); in imx258_start_streaming()
1023 dev_err(&client->dev, "%s failed to reset sensor\n", __func__); in imx258_start_streaming()
1027 /* 12ms is required from poweron to standby */ in imx258_start_streaming()
1031 link_freq_index = imx258->cur_mode->link_freq_index; in imx258_start_streaming()
1032 link_freq_cfg = &imx258->link_freq_configs[link_freq_index]; in imx258_start_streaming()
1034 reg_list = &link_freq_cfg->link_cfg[imx258->lane_mode_idx].reg_list; in imx258_start_streaming()
1035 ret = cci_multi_reg_write(imx258->regmap, reg_list->regs, reg_list->num_of_regs, NULL); in imx258_start_streaming()
1037 dev_err(&client->dev, "%s failed to set plls\n", __func__); in imx258_start_streaming()
1041 ret = cci_multi_reg_write(imx258->regmap, mode_common_regs, in imx258_start_streaming()
1044 dev_err(&client->dev, "%s failed to set common regs\n", __func__); in imx258_start_streaming()
1048 ret = cci_multi_reg_write(imx258->regmap, imx258->variant_cfg->regs, in imx258_start_streaming()
1049 imx258->variant_cfg->num_regs, NULL); in imx258_start_streaming()
1051 dev_err(&client->dev, "%s failed to set variant config\n", in imx258_start_streaming()
1056 ret = cci_write(imx258->regmap, IMX258_CLK_BLANK_STOP, in imx258_start_streaming()
1057 !!(imx258->csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK), in imx258_start_streaming()
1060 dev_err(&client->dev, "%s failed to set clock lane mode\n", __func__); in imx258_start_streaming()
1065 reg_list = &imx258->cur_mode->reg_list; in imx258_start_streaming()
1066 ret = cci_multi_reg_write(imx258->regmap, reg_list->regs, reg_list->num_of_regs, NULL); in imx258_start_streaming()
1068 dev_err(&client->dev, "%s failed to set mode\n", __func__); in imx258_start_streaming()
1073 ret = __v4l2_ctrl_handler_setup(imx258->sd.ctrl_handler); in imx258_start_streaming()
1078 return cci_write(imx258->regmap, IMX258_REG_MODE_SELECT, in imx258_start_streaming()
1085 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); in imx258_stop_streaming()
1089 ret = cci_write(imx258->regmap, IMX258_REG_MODE_SELECT, in imx258_stop_streaming()
1092 dev_err(&client->dev, "%s failed to set stream\n", __func__); in imx258_stop_streaming()
1108 imx258->supplies); in imx258_power_on()
1115 ret = clk_prepare_enable(imx258->clk); in imx258_power_on()
1118 regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies); in imx258_power_on()
1129 clk_disable_unprepare(imx258->clk); in imx258_power_off()
1130 regulator_bulk_disable(IMX258_NUM_SUPPLIES, imx258->supplies); in imx258_power_off()
1141 mutex_lock(&imx258->mutex); in imx258_set_stream()
1144 ret = pm_runtime_resume_and_get(&client->dev); in imx258_set_stream()
1157 pm_runtime_put(&client->dev); in imx258_set_stream()
1160 mutex_unlock(&imx258->mutex); in imx258_set_stream()
1165 pm_runtime_put(&client->dev); in imx258_set_stream()
1167 mutex_unlock(&imx258->mutex); in imx258_set_stream()
1175 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); in imx258_identify_module()
1179 ret = cci_read(imx258->regmap, IMX258_REG_CHIP_ID, in imx258_identify_module()
1182 dev_err(&client->dev, "failed to read chip id %x\n", in imx258_identify_module()
1188 dev_err(&client->dev, "chip id mismatch: %x!=%llx\n", in imx258_identify_module()
1190 return -EIO; in imx258_identify_module()
1220 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd); in imx258_init_controls()
1230 ctrl_hdlr = &imx258->ctrl_handler; in imx258_init_controls()
1235 mutex_init(&imx258->mutex); in imx258_init_controls()
1236 ctrl_hdlr->lock = &imx258->mutex; in imx258_init_controls()
1237 imx258->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, in imx258_init_controls()
1240 ARRAY_SIZE(link_freq_menu_items_19_2) - 1, in imx258_init_controls()
1242 imx258->link_freq_menu_items); in imx258_init_controls()
1244 if (imx258->link_freq) in imx258_init_controls()
1245 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; in imx258_init_controls()
1247 imx258->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops, in imx258_init_controls()
1249 if (imx258->hflip) in imx258_init_controls()
1250 imx258->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; in imx258_init_controls()
1252 imx258->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops, in imx258_init_controls()
1254 if (imx258->vflip) in imx258_init_controls()
1255 imx258->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; in imx258_init_controls()
1257 link_freq_cfgs = &imx258->link_freq_configs[0]; in imx258_init_controls()
1258 link_cfg = link_freq_cfgs[imx258->lane_mode_idx].link_cfg; in imx258_init_controls()
1259 pixel_rate = link_freq_to_pixel_rate(imx258->link_freq_menu_items[0], in imx258_init_controls()
1263 imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops, in imx258_init_controls()
1268 vblank_def = imx258->cur_mode->vts_def - imx258->cur_mode->height; in imx258_init_controls()
1269 vblank_min = imx258->cur_mode->vts_min - imx258->cur_mode->height; in imx258_init_controls()
1270 imx258->vblank = v4l2_ctrl_new_std( in imx258_init_controls()
1273 IMX258_VTS_MAX - imx258->cur_mode->height, 1, in imx258_init_controls()
1276 imx258->hblank = v4l2_ctrl_new_std( in imx258_init_controls()
1278 IMX258_PPL_DEFAULT - imx258->cur_mode->width, in imx258_init_controls()
1279 IMX258_PPL_DEFAULT - imx258->cur_mode->width, in imx258_init_controls()
1281 IMX258_PPL_DEFAULT - imx258->cur_mode->width); in imx258_init_controls()
1283 if (imx258->hblank) in imx258_init_controls()
1284 imx258->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; in imx258_init_controls()
1286 imx258->exposure = v4l2_ctrl_new_std( in imx258_init_controls()
1306 ARRAY_SIZE(imx258_test_pattern_menu) - 1, in imx258_init_controls()
1309 if (ctrl_hdlr->error) { in imx258_init_controls()
1310 ret = ctrl_hdlr->error; in imx258_init_controls()
1311 dev_err(&client->dev, "%s control init failed (%d)\n", in imx258_init_controls()
1316 ret = v4l2_fwnode_device_parse(&client->dev, &props); in imx258_init_controls()
1325 imx258->sd.ctrl_handler = ctrl_hdlr; in imx258_init_controls()
1331 mutex_destroy(&imx258->mutex); in imx258_init_controls()
1338 v4l2_ctrl_handler_free(imx258->sd.ctrl_handler); in imx258_free_controls()
1339 mutex_destroy(&imx258->mutex); in imx258_free_controls()
1348 imx258->supplies[i].supply = imx258_supply_name[i]; in imx258_get_regulators()
1350 return devm_regulator_bulk_get(&client->dev, in imx258_get_regulators()
1351 IMX258_NUM_SUPPLIES, imx258->supplies); in imx258_get_regulators()
1364 imx258 = devm_kzalloc(&client->dev, sizeof(*imx258), GFP_KERNEL); in imx258_probe()
1366 return -ENOMEM; in imx258_probe()
1368 imx258->regmap = devm_cci_regmap_init_i2c(client, 16); in imx258_probe()
1369 if (IS_ERR(imx258->regmap)) { in imx258_probe()
1370 ret = PTR_ERR(imx258->regmap); in imx258_probe()
1371 dev_err(&client->dev, "failed to initialize CCI: %d\n", ret); in imx258_probe()
1377 return dev_err_probe(&client->dev, ret, in imx258_probe()
1380 imx258->clk = devm_clk_get_optional(&client->dev, NULL); in imx258_probe()
1381 if (IS_ERR(imx258->clk)) in imx258_probe()
1382 return dev_err_probe(&client->dev, PTR_ERR(imx258->clk), in imx258_probe()
1384 if (!imx258->clk) { in imx258_probe()
1385 dev_dbg(&client->dev, in imx258_probe()
1386 "no clock provided, using clock-frequency property\n"); in imx258_probe()
1388 device_property_read_u32(&client->dev, "clock-frequency", &val); in imx258_probe()
1390 val = clk_get_rate(imx258->clk); in imx258_probe()
1395 imx258->link_freq_configs = link_freq_configs_19_2; in imx258_probe()
1396 imx258->link_freq_menu_items = link_freq_menu_items_19_2; in imx258_probe()
1399 imx258->link_freq_configs = link_freq_configs_24; in imx258_probe()
1400 imx258->link_freq_menu_items = link_freq_menu_items_24; in imx258_probe()
1403 dev_err(&client->dev, "input clock frequency of %u not supported\n", in imx258_probe()
1405 return -EINVAL; in imx258_probe()
1408 endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL); in imx258_probe()
1410 dev_err(&client->dev, "Endpoint node not found\n"); in imx258_probe()
1411 return -EINVAL; in imx258_probe()
1417 dev_err(&client->dev, "Parsing endpoint node failed\n"); in imx258_probe()
1421 ret = v4l2_link_freq_to_bitmap(&client->dev, in imx258_probe()
1424 imx258->link_freq_menu_items, in imx258_probe()
1426 &imx258->link_freq_bitmap); in imx258_probe()
1428 dev_err(&client->dev, "Link frequency not supported\n"); in imx258_probe()
1435 imx258->lane_mode_idx = IMX258_2_LANE_MODE; in imx258_probe()
1438 imx258->lane_mode_idx = IMX258_4_LANE_MODE; in imx258_probe()
1441 dev_err(&client->dev, "Invalid data lanes: %u\n", in imx258_probe()
1443 ret = -EINVAL; in imx258_probe()
1447 imx258->csi2_flags = ep.bus.mipi_csi2.flags; in imx258_probe()
1449 imx258->variant_cfg = device_get_match_data(&client->dev); in imx258_probe()
1450 if (!imx258->variant_cfg) in imx258_probe()
1451 imx258->variant_cfg = &imx258_cfg; in imx258_probe()
1454 v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops); in imx258_probe()
1457 ret = imx258_power_on(&client->dev); in imx258_probe()
1467 imx258->cur_mode = &supported_modes[0]; in imx258_probe()
1474 imx258->sd.internal_ops = &imx258_internal_ops; in imx258_probe()
1475 imx258->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in imx258_probe()
1476 imx258->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; in imx258_probe()
1479 imx258->pad.flags = MEDIA_PAD_FL_SOURCE; in imx258_probe()
1481 ret = media_entity_pads_init(&imx258->sd.entity, 1, &imx258->pad); in imx258_probe()
1485 ret = v4l2_async_register_subdev_sensor(&imx258->sd); in imx258_probe()
1489 pm_runtime_set_active(&client->dev); in imx258_probe()
1490 pm_runtime_enable(&client->dev); in imx258_probe()
1491 pm_runtime_idle(&client->dev); in imx258_probe()
1497 media_entity_cleanup(&imx258->sd.entity); in imx258_probe()
1503 imx258_power_off(&client->dev); in imx258_probe()
1517 media_entity_cleanup(&sd->entity); in imx258_remove()
1520 pm_runtime_disable(&client->dev); in imx258_remove()
1521 if (!pm_runtime_status_suspended(&client->dev)) in imx258_remove()
1522 imx258_power_off(&client->dev); in imx258_remove()
1523 pm_runtime_set_suspended(&client->dev); in imx258_remove()
1541 { .compatible = "sony,imx258-pdaf", .data = &imx258_pdaf_cfg },