Lines Matching +full:clk +full:- +full:output +full:- +full:sel
1 // SPDX-License-Identifier: GPL-2.0-only
12 #include <linux/clk.h>
23 #include <linux/v4l2-mediabus.h>
27 #include <media/v4l2-ctrls.h>
28 #include <media/v4l2-device.h>
29 #include <media/v4l2-fwnode.h>
30 #include <media/v4l2-subdev.h>
203 struct clk *clk; member
228 struct regmap *map = mt9v032->regmap; in mt9v032_update_aec_agc()
229 u16 value = mt9v032->aec_agc; in mt9v032_update_aec_agc()
241 mt9v032->aec_agc = value; in mt9v032_update_aec_agc()
248 struct v4l2_rect *crop = &mt9v032->crop; in mt9v032_update_hblank()
249 unsigned int min_hblank = mt9v032->model->data->min_hblank; in mt9v032_update_hblank()
252 if (mt9v032->version->version == MT9V034_CHIP_ID_REV1) in mt9v032_update_hblank()
253 min_hblank += (mt9v032->hratio - 1) * 10; in mt9v032_update_hblank()
254 min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width, in mt9v032_update_hblank()
256 hblank = max_t(unsigned int, mt9v032->hblank, min_hblank); in mt9v032_update_hblank()
258 return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING, in mt9v032_update_hblank()
264 struct regmap *map = mt9v032->regmap; in mt9v032_power_on()
267 gpiod_set_value_cansleep(mt9v032->reset_gpio, 1); in mt9v032_power_on()
269 ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk); in mt9v032_power_on()
274 ret = clk_prepare_enable(mt9v032->clk); in mt9v032_power_on()
280 if (mt9v032->reset_gpio) { in mt9v032_power_on()
281 gpiod_set_value_cansleep(mt9v032->reset_gpio, 0); in mt9v032_power_on()
308 clk_disable_unprepare(mt9v032->clk); in mt9v032_power_on()
314 clk_disable_unprepare(mt9v032->clk); in mt9v032_power_off()
319 struct regmap *map = mt9v032->regmap; in __mt9v032_set_power()
332 if (mt9v032->pdata && mt9v032->pdata->clk_pol) { in __mt9v032_set_power()
333 ret = regmap_write(map, mt9v032->model->data->pclk_reg, in __mt9v032_set_power()
344 return v4l2_ctrl_handler_setup(&mt9v032->ctrls); in __mt9v032_set_power()
347 /* -----------------------------------------------------------------------------
357 return v4l2_subdev_get_try_format(&mt9v032->subdev, cfg, pad); in __mt9v032_get_pad_format()
359 return &mt9v032->format; in __mt9v032_get_pad_format()
371 return v4l2_subdev_get_try_crop(&mt9v032->subdev, cfg, pad); in __mt9v032_get_pad_crop()
373 return &mt9v032->crop; in __mt9v032_get_pad_crop()
384 struct v4l2_rect *crop = &mt9v032->crop; in mt9v032_s_stream()
385 struct regmap *map = mt9v032->regmap; in mt9v032_s_stream()
394 hbin = fls(mt9v032->hratio) - 1; in mt9v032_s_stream()
395 vbin = fls(mt9v032->vratio) - 1; in mt9v032_s_stream()
403 ret = regmap_write(map, MT9V032_COLUMN_START, crop->left); in mt9v032_s_stream()
407 ret = regmap_write(map, MT9V032_ROW_START, crop->top); in mt9v032_s_stream()
411 ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width); in mt9v032_s_stream()
415 ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height); in mt9v032_s_stream()
433 if (code->index > 0) in mt9v032_enum_mbus_code()
434 return -EINVAL; in mt9v032_enum_mbus_code()
436 code->code = mt9v032->format.code; in mt9v032_enum_mbus_code()
446 if (fse->index >= 3) in mt9v032_enum_frame_size()
447 return -EINVAL; in mt9v032_enum_frame_size()
448 if (mt9v032->format.code != fse->code) in mt9v032_enum_frame_size()
449 return -EINVAL; in mt9v032_enum_frame_size()
451 fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index); in mt9v032_enum_frame_size()
452 fse->max_width = fse->min_width; in mt9v032_enum_frame_size()
453 fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / (1 << fse->index); in mt9v032_enum_frame_size()
454 fse->max_height = fse->min_height; in mt9v032_enum_frame_size()
465 format->format = *__mt9v032_get_pad_format(mt9v032, cfg, format->pad, in mt9v032_get_format()
466 format->which); in mt9v032_get_format()
472 struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev); in mt9v032_configure_pixel_rate()
475 ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate, in mt9v032_configure_pixel_rate()
476 mt9v032->sysclk / mt9v032->hratio); in mt9v032_configure_pixel_rate()
478 dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret); in mt9v032_configure_pixel_rate()
481 static unsigned int mt9v032_calc_ratio(unsigned int input, unsigned int output) in mt9v032_calc_ratio() argument
483 /* Compute the power-of-two binning factor closest to the input size to in mt9v032_calc_ratio()
484 * output size ratio. Given that the output size is bounded by input/4 in mt9v032_calc_ratio()
487 if (output * 3 > input * 2) in mt9v032_calc_ratio()
489 if (output * 3 > input) in mt9v032_calc_ratio()
506 __crop = __mt9v032_get_pad_crop(mt9v032, cfg, format->pad, in mt9v032_set_format()
507 format->which); in mt9v032_set_format()
510 width = clamp(ALIGN(format->format.width, 2), in mt9v032_set_format()
511 max_t(unsigned int, __crop->width / 4, in mt9v032_set_format()
513 __crop->width); in mt9v032_set_format()
514 height = clamp(ALIGN(format->format.height, 2), in mt9v032_set_format()
515 max_t(unsigned int, __crop->height / 4, in mt9v032_set_format()
517 __crop->height); in mt9v032_set_format()
519 hratio = mt9v032_calc_ratio(__crop->width, width); in mt9v032_set_format()
520 vratio = mt9v032_calc_ratio(__crop->height, height); in mt9v032_set_format()
522 __format = __mt9v032_get_pad_format(mt9v032, cfg, format->pad, in mt9v032_set_format()
523 format->which); in mt9v032_set_format()
524 __format->width = __crop->width / hratio; in mt9v032_set_format()
525 __format->height = __crop->height / vratio; in mt9v032_set_format()
527 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { in mt9v032_set_format()
528 mt9v032->hratio = hratio; in mt9v032_set_format()
529 mt9v032->vratio = vratio; in mt9v032_set_format()
533 format->format = *__format; in mt9v032_set_format()
540 struct v4l2_subdev_selection *sel) in mt9v032_get_selection() argument
544 if (sel->target != V4L2_SEL_TGT_CROP) in mt9v032_get_selection()
545 return -EINVAL; in mt9v032_get_selection()
547 sel->r = *__mt9v032_get_pad_crop(mt9v032, cfg, sel->pad, sel->which); in mt9v032_get_selection()
553 struct v4l2_subdev_selection *sel) in mt9v032_set_selection() argument
560 if (sel->target != V4L2_SEL_TGT_CROP) in mt9v032_set_selection()
561 return -EINVAL; in mt9v032_set_selection()
566 rect.left = clamp(ALIGN(sel->r.left + 1, 2) - 1, in mt9v032_set_selection()
569 rect.top = clamp(ALIGN(sel->r.top + 1, 2) - 1, in mt9v032_set_selection()
572 rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), in mt9v032_set_selection()
575 rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), in mt9v032_set_selection()
580 rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left); in mt9v032_set_selection()
582 rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top); in mt9v032_set_selection()
584 __crop = __mt9v032_get_pad_crop(mt9v032, cfg, sel->pad, sel->which); in mt9v032_set_selection()
586 if (rect.width != __crop->width || rect.height != __crop->height) { in mt9v032_set_selection()
587 /* Reset the output image size if the crop rectangle size has in mt9v032_set_selection()
590 __format = __mt9v032_get_pad_format(mt9v032, cfg, sel->pad, in mt9v032_set_selection()
591 sel->which); in mt9v032_set_selection()
592 __format->width = rect.width; in mt9v032_set_selection()
593 __format->height = rect.height; in mt9v032_set_selection()
594 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { in mt9v032_set_selection()
595 mt9v032->hratio = 1; in mt9v032_set_selection()
596 mt9v032->vratio = 1; in mt9v032_set_selection()
602 sel->r = rect; in mt9v032_set_selection()
607 /* -----------------------------------------------------------------------------
621 * Possible values are 0-2. 0 means no LPF. For 1 and 2 this equation is used:
623 * if |(calculated new exp - current exp)| > (current exp / 4)
626 * next exp = current exp + ((calculated new exp - current exp) / 2^LPF)
644 container_of(ctrl->handler, struct mt9v032, ctrls); in mt9v032_s_ctrl()
645 struct regmap *map = mt9v032->regmap; in mt9v032_s_ctrl()
649 switch (ctrl->id) { in mt9v032_s_ctrl()
652 ctrl->val); in mt9v032_s_ctrl()
655 return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val); in mt9v032_s_ctrl()
659 !ctrl->val); in mt9v032_s_ctrl()
663 ctrl->val); in mt9v032_s_ctrl()
666 mt9v032->hblank = ctrl->val; in mt9v032_s_ctrl()
671 ctrl->val); in mt9v032_s_ctrl()
675 if (mt9v032->link_freq == NULL) in mt9v032_s_ctrl()
678 freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val]; in mt9v032_s_ctrl()
679 *mt9v032->pixel_rate->p_new.p_s64 = freq; in mt9v032_s_ctrl()
680 mt9v032->sysclk = freq; in mt9v032_s_ctrl()
684 switch (mt9v032->test_pattern->val) { in mt9v032_s_ctrl()
701 data = (mt9v032->test_pattern_color->val << in mt9v032_s_ctrl()
711 return regmap_write(map, MT9V032_AEGC_DESIRED_BIN, ctrl->val); in mt9v032_s_ctrl()
714 return regmap_write(map, MT9V032_AEC_LPF, ctrl->val); in mt9v032_s_ctrl()
717 return regmap_write(map, MT9V032_AGC_LPF, ctrl->val); in mt9v032_s_ctrl()
721 ctrl->val); in mt9v032_s_ctrl()
725 ctrl->val); in mt9v032_s_ctrl()
729 mt9v032->model->data->aec_max_shutter_reg, in mt9v032_s_ctrl()
730 ctrl->val); in mt9v032_s_ctrl()
838 /* -----------------------------------------------------------------------------
847 mutex_lock(&mt9v032->power_lock); in mt9v032_set_power()
852 if (mt9v032->power_count == !on) { in mt9v032_set_power()
859 mt9v032->power_count += on ? 1 : -1; in mt9v032_set_power()
860 WARN_ON(mt9v032->power_count < 0); in mt9v032_set_power()
863 mutex_unlock(&mt9v032->power_lock); in mt9v032_set_power()
867 /* -----------------------------------------------------------------------------
879 dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n", in mt9v032_registered()
880 client->addr); in mt9v032_registered()
884 dev_err(&client->dev, "MT9V032 power up failed\n"); in mt9v032_registered()
889 ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version); in mt9v032_registered()
894 dev_err(&client->dev, "Failed reading chip version\n"); in mt9v032_registered()
900 mt9v032->version = &mt9v032_versions[i]; in mt9v032_registered()
905 if (mt9v032->version == NULL) { in mt9v032_registered()
906 dev_err(&client->dev, "Unsupported chip version 0x%04x\n", in mt9v032_registered()
908 return -ENODEV; in mt9v032_registered()
911 dev_info(&client->dev, "%s detected at address 0x%02x\n", in mt9v032_registered()
912 mt9v032->version->name, client->addr); in mt9v032_registered()
925 crop = v4l2_subdev_get_try_crop(subdev, fh->pad, 0); in mt9v032_open()
926 crop->left = MT9V032_COLUMN_START_DEF; in mt9v032_open()
927 crop->top = MT9V032_ROW_START_DEF; in mt9v032_open()
928 crop->width = MT9V032_WINDOW_WIDTH_DEF; in mt9v032_open()
929 crop->height = MT9V032_WINDOW_HEIGHT_DEF; in mt9v032_open()
931 format = v4l2_subdev_get_try_format(subdev, fh->pad, 0); in mt9v032_open()
933 if (mt9v032->model->color) in mt9v032_open()
934 format->code = MEDIA_BUS_FMT_SGRBG10_1X10; in mt9v032_open()
936 format->code = MEDIA_BUS_FMT_Y10_1X10; in mt9v032_open()
938 format->width = MT9V032_WINDOW_WIDTH_DEF; in mt9v032_open()
939 format->height = MT9V032_WINDOW_HEIGHT_DEF; in mt9v032_open()
940 format->field = V4L2_FIELD_NONE; in mt9v032_open()
941 format->colorspace = V4L2_COLORSPACE_SRGB; in mt9v032_open()
987 /* -----------------------------------------------------------------------------
999 if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) in mt9v032_get_pdata()
1000 return client->dev.platform_data; in mt9v032_get_pdata()
1002 np = of_graph_get_next_endpoint(client->dev.of_node, NULL); in mt9v032_get_pdata()
1009 pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); in mt9v032_get_pdata()
1013 prop = of_find_property(np, "link-frequencies", NULL); in mt9v032_get_pdata()
1016 size_t size = prop->length / sizeof(*link_freqs); in mt9v032_get_pdata()
1018 link_freqs = devm_kcalloc(&client->dev, size, in mt9v032_get_pdata()
1023 if (of_property_read_u64_array(np, "link-frequencies", in mt9v032_get_pdata()
1027 pdata->link_freqs = link_freqs; in mt9v032_get_pdata()
1028 pdata->link_def_freq = link_freqs[0]; in mt9v032_get_pdata()
1031 pdata->clk_pol = !!(endpoint.bus.parallel.flags & in mt9v032_get_pdata()
1047 mt9v032 = devm_kzalloc(&client->dev, sizeof(*mt9v032), GFP_KERNEL); in mt9v032_probe()
1049 return -ENOMEM; in mt9v032_probe()
1051 mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config); in mt9v032_probe()
1052 if (IS_ERR(mt9v032->regmap)) in mt9v032_probe()
1053 return PTR_ERR(mt9v032->regmap); in mt9v032_probe()
1055 mt9v032->clk = devm_clk_get(&client->dev, NULL); in mt9v032_probe()
1056 if (IS_ERR(mt9v032->clk)) in mt9v032_probe()
1057 return PTR_ERR(mt9v032->clk); in mt9v032_probe()
1059 mt9v032->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", in mt9v032_probe()
1061 if (IS_ERR(mt9v032->reset_gpio)) in mt9v032_probe()
1062 return PTR_ERR(mt9v032->reset_gpio); in mt9v032_probe()
1064 mt9v032->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", in mt9v032_probe()
1066 if (IS_ERR(mt9v032->standby_gpio)) in mt9v032_probe()
1067 return PTR_ERR(mt9v032->standby_gpio); in mt9v032_probe()
1069 mutex_init(&mt9v032->power_lock); in mt9v032_probe()
1070 mt9v032->pdata = pdata; in mt9v032_probe()
1071 mt9v032->model = (const void *)did->driver_data; in mt9v032_probe()
1073 v4l2_ctrl_handler_init(&mt9v032->ctrls, 11 + in mt9v032_probe()
1076 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, in mt9v032_probe()
1078 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, in mt9v032_probe()
1081 v4l2_ctrl_new_std_menu(&mt9v032->ctrls, &mt9v032_ctrl_ops, in mt9v032_probe()
1084 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, in mt9v032_probe()
1085 V4L2_CID_EXPOSURE, mt9v032->model->data->min_shutter, in mt9v032_probe()
1086 mt9v032->model->data->max_shutter, 1, in mt9v032_probe()
1088 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, in mt9v032_probe()
1089 V4L2_CID_HBLANK, mt9v032->model->data->min_hblank, in mt9v032_probe()
1092 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, in mt9v032_probe()
1093 V4L2_CID_VBLANK, mt9v032->model->data->min_vblank, in mt9v032_probe()
1094 mt9v032->model->data->max_vblank, 1, in mt9v032_probe()
1096 mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls, in mt9v032_probe()
1098 ARRAY_SIZE(mt9v032_test_pattern_menu) - 1, 0, 0, in mt9v032_probe()
1100 mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls, in mt9v032_probe()
1103 v4l2_ctrl_new_custom(&mt9v032->ctrls, in mt9v032_probe()
1104 mt9v032->model->data->aec_max_shutter_v4l2_ctrl, in mt9v032_probe()
1107 v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_aegc_controls[i], in mt9v032_probe()
1110 v4l2_ctrl_cluster(2, &mt9v032->test_pattern); in mt9v032_probe()
1112 mt9v032->pixel_rate = in mt9v032_probe()
1113 v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops, in mt9v032_probe()
1116 if (pdata && pdata->link_freqs) { in mt9v032_probe()
1119 for (i = 0; pdata->link_freqs[i]; ++i) { in mt9v032_probe()
1120 if (pdata->link_freqs[i] == pdata->link_def_freq) in mt9v032_probe()
1124 mt9v032->link_freq = in mt9v032_probe()
1125 v4l2_ctrl_new_int_menu(&mt9v032->ctrls, in mt9v032_probe()
1127 V4L2_CID_LINK_FREQ, i - 1, def, in mt9v032_probe()
1128 pdata->link_freqs); in mt9v032_probe()
1129 v4l2_ctrl_cluster(2, &mt9v032->link_freq); in mt9v032_probe()
1133 mt9v032->subdev.ctrl_handler = &mt9v032->ctrls; in mt9v032_probe()
1135 if (mt9v032->ctrls.error) { in mt9v032_probe()
1136 dev_err(&client->dev, "control initialization error %d\n", in mt9v032_probe()
1137 mt9v032->ctrls.error); in mt9v032_probe()
1138 ret = mt9v032->ctrls.error; in mt9v032_probe()
1142 mt9v032->crop.left = MT9V032_COLUMN_START_DEF; in mt9v032_probe()
1143 mt9v032->crop.top = MT9V032_ROW_START_DEF; in mt9v032_probe()
1144 mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF; in mt9v032_probe()
1145 mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF; in mt9v032_probe()
1147 if (mt9v032->model->color) in mt9v032_probe()
1148 mt9v032->format.code = MEDIA_BUS_FMT_SGRBG10_1X10; in mt9v032_probe()
1150 mt9v032->format.code = MEDIA_BUS_FMT_Y10_1X10; in mt9v032_probe()
1152 mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF; in mt9v032_probe()
1153 mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF; in mt9v032_probe()
1154 mt9v032->format.field = V4L2_FIELD_NONE; in mt9v032_probe()
1155 mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB; in mt9v032_probe()
1157 mt9v032->hratio = 1; in mt9v032_probe()
1158 mt9v032->vratio = 1; in mt9v032_probe()
1160 mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE; in mt9v032_probe()
1161 mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF; in mt9v032_probe()
1162 mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF; in mt9v032_probe()
1164 v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops); in mt9v032_probe()
1165 mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops; in mt9v032_probe()
1166 mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in mt9v032_probe()
1168 mt9v032->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; in mt9v032_probe()
1169 mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; in mt9v032_probe()
1170 ret = media_entity_pads_init(&mt9v032->subdev.entity, 1, &mt9v032->pad); in mt9v032_probe()
1174 mt9v032->subdev.dev = &client->dev; in mt9v032_probe()
1175 ret = v4l2_async_register_subdev(&mt9v032->subdev); in mt9v032_probe()
1182 media_entity_cleanup(&mt9v032->subdev.entity); in mt9v032_probe()
1183 v4l2_ctrl_handler_free(&mt9v032->ctrls); in mt9v032_probe()
1193 v4l2_ctrl_handler_free(&mt9v032->ctrls); in mt9v032_remove()
1194 media_entity_cleanup(&subdev->entity); in mt9v032_remove()