Lines Matching +full:hb +full:- +full:pll +full:- +full:clock

1 // SPDX-License-Identifier: GPL-2.0
21 #include <linux/v4l2-mediabus.h>
24 #include <media/v4l2-ctrls.h>
25 #include <media/v4l2-device.h>
26 #include <media/v4l2-fwnode.h>
27 #include <media/v4l2-image-sizes.h>
28 #include <media/v4l2-subdev.h>
31 * MT9V111 is a 1/4-Inch CMOS digital image sensor with an integrated
40 * auto-exposure algorithm might modify the programmed frame rate. While the
41 * driver initially programs the sensor with auto-exposure and
42 * auto-white-balancing enabled, it is possible to disable them and more
45 * While it seems possible to instruct the auto-exposure control algorithm to
49 * MT9V111_1.fm - Rev. G 1/05 EN).
149 /* Clock provider and system clock frequency. */
161 * mt9v111_mbus_fmt - List all media bus formats supported by the driver.
167 * obtained by configuring blanking as the sensor does not have a PLL but
168 * only a fixed clock divider that generates the output pixel clock.
190 * mt9v111_frame_sizes - List sensor's supported resolutions.
218 /* --- Device I/O access --- */
226 msg[0].addr = c->addr; in __mt9v111_read()
231 msg[1].addr = c->addr; in __mt9v111_read()
236 ret = i2c_transfer(c->adapter, msg, 2); in __mt9v111_read()
238 dev_err(&c->dev, "i2c read transfer error: %d\n", ret); in __mt9v111_read()
244 dev_dbg(&c->dev, "%s: %x=%x\n", __func__, reg, *val); in __mt9v111_read()
259 msg.addr = c->addr; in __mt9v111_write()
264 dev_dbg(&c->dev, "%s: %x = %x%x\n", __func__, reg, buf[1], buf[2]); in __mt9v111_write()
266 ret = i2c_transfer(c->adapter, &msg, 1); in __mt9v111_write()
268 dev_err(&c->dev, "i2c write transfer error: %d\n", ret); in __mt9v111_write()
282 if (mt9v111->addr_space == addr_space) in __mt9v111_addr_space_select()
295 return -EINVAL; in __mt9v111_addr_space_select()
297 mt9v111->addr_space = addr_space; in __mt9v111_addr_space_select()
359 /* --- Sensor HW operations --- */
366 ret = clk_prepare_enable(mt9v111->clk); in __mt9v111_power_on()
370 clk_set_rate(mt9v111->clk, mt9v111->sysclk); in __mt9v111_power_on()
372 gpiod_set_value(mt9v111->standby, 0); in __mt9v111_power_on()
375 gpiod_set_value(mt9v111->oe, 1); in __mt9v111_power_on()
385 gpiod_set_value(mt9v111->oe, 0); in __mt9v111_power_off()
388 gpiod_set_value(mt9v111->standby, 1); in __mt9v111_power_off()
391 clk_disable_unprepare(mt9v111->clk); in __mt9v111_power_off()
398 if (!mt9v111->reset) in __mt9v111_hw_reset()
399 return -EINVAL; in __mt9v111_hw_reset()
401 gpiod_set_value(mt9v111->reset, 1); in __mt9v111_hw_reset()
404 gpiod_set_value(mt9v111->reset, 0); in __mt9v111_hw_reset()
412 struct i2c_client *c = mt9v111->client; in __mt9v111_sw_reset()
451 unsigned int fps = tpf->numerator ? in mt9v111_calc_frame_rate()
452 tpf->denominator / tpf->numerator : in mt9v111_calc_frame_rate()
453 tpf->denominator; in mt9v111_calc_frame_rate()
461 unsigned int hb; in mt9v111_calc_frame_rate() local
469 diff = abs(fps - mt9v111_frame_intervals[i]); in mt9v111_calc_frame_rate()
478 * The sensor does not provide a PLL circuitry and pixel clock is in mt9v111_calc_frame_rate()
479 * generated dividing the master clock source by two. in mt9v111_calc_frame_rate()
492 best_fps = vb = hb = 0; in mt9v111_calc_frame_rate()
493 pclk = DIV_ROUND_CLOSEST(mt9v111->sysclk, 2); in mt9v111_calc_frame_rate()
500 for (hb = MT9V111_CORE_R05_MIN_HBLANK; in mt9v111_calc_frame_rate()
501 hb < MT9V111_CORE_R05_MAX_HBLANK; hb += 10) { in mt9v111_calc_frame_rate()
502 unsigned int t_frame = (row_pclk + hb) * in mt9v111_calc_frame_rate()
506 diff = abs(fps - t_fps); in mt9v111_calc_frame_rate()
520 ret = v4l2_ctrl_s_ctrl_int64(mt9v111->hblank, hb); in mt9v111_calc_frame_rate()
524 ret = v4l2_ctrl_s_ctrl_int64(mt9v111->vblank, vb); in mt9v111_calc_frame_rate()
528 tpf->numerator = 1; in mt9v111_calc_frame_rate()
529 tpf->denominator = best_fps; in mt9v111_calc_frame_rate()
536 struct i2c_client *c = mt9v111->client; in mt9v111_hw_config()
542 if (ret == -EINVAL) in mt9v111_hw_config()
547 /* Configure internal clock sample rate. */ in mt9v111_hw_config()
548 ret = mt9v111->sysclk < DIV_ROUND_CLOSEST(MT9V111_MAX_CLKIN, 2) ? in mt9v111_hw_config()
564 switch (mt9v111->fmt.code) { in mt9v111_hw_config()
620 mt9v111->fmt.width); in mt9v111_hw_config()
625 mt9v111->fmt.height); in mt9v111_hw_config()
630 ret = v4l2_ctrl_handler_setup(&mt9v111->ctrls); in mt9v111_hw_config()
644 /* --- V4L2 subdev operations --- */
652 mutex_lock(&mt9v111->pwr_mutex); in mt9v111_s_power()
658 pwr_count = mt9v111->pwr_count; in mt9v111_s_power()
659 pwr_count += on ? 1 : -1; in mt9v111_s_power()
665 mt9v111->pwr_count = pwr_count; in mt9v111_s_power()
667 mutex_unlock(&mt9v111->pwr_mutex); in mt9v111_s_power()
677 mt9v111->pwr_count = pwr_count; in mt9v111_s_power()
679 mutex_unlock(&mt9v111->pwr_mutex); in mt9v111_s_power()
689 mutex_lock(&mt9v111->stream_mutex); in mt9v111_s_stream()
691 if (mt9v111->streaming == enable) { in mt9v111_s_stream()
692 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_stream()
700 if (enable && mt9v111->pending) { in mt9v111_s_stream()
710 mt9v111->pending = false; in mt9v111_s_stream()
713 mt9v111->streaming = enable ? true : false; in mt9v111_s_stream()
714 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_stream()
719 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_stream()
728 struct v4l2_fract *tpf = &ival->interval; in mt9v111_s_frame_interval()
729 unsigned int fps = tpf->numerator ? in mt9v111_s_frame_interval()
730 tpf->denominator / tpf->numerator : in mt9v111_s_frame_interval()
731 tpf->denominator; in mt9v111_s_frame_interval()
734 if (!tpf->numerator) in mt9v111_s_frame_interval()
735 tpf->numerator = 1; in mt9v111_s_frame_interval()
737 mutex_lock(&mt9v111->stream_mutex); in mt9v111_s_frame_interval()
739 if (mt9v111->streaming) { in mt9v111_s_frame_interval()
740 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_frame_interval()
741 return -EBUSY; in mt9v111_s_frame_interval()
744 if (mt9v111->fps == fps) { in mt9v111_s_frame_interval()
745 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_frame_interval()
750 if (mt9v111->fmt.width < QVGA_WIDTH && in mt9v111_s_frame_interval()
751 mt9v111->fmt.height < QVGA_HEIGHT) in mt9v111_s_frame_interval()
753 else if (mt9v111->fmt.width < CIF_WIDTH && in mt9v111_s_frame_interval()
754 mt9v111->fmt.height < CIF_HEIGHT) in mt9v111_s_frame_interval()
757 max_fps = mt9v111->sysclk < in mt9v111_s_frame_interval()
762 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_frame_interval()
763 return -EINVAL; in mt9v111_s_frame_interval()
768 mt9v111->fps = fps; in mt9v111_s_frame_interval()
769 mt9v111->pending = true; in mt9v111_s_frame_interval()
771 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_frame_interval()
780 struct v4l2_fract *tpf = &ival->interval; in mt9v111_g_frame_interval()
782 mutex_lock(&mt9v111->stream_mutex); in mt9v111_g_frame_interval()
784 tpf->numerator = 1; in mt9v111_g_frame_interval()
785 tpf->denominator = mt9v111->fps; in mt9v111_g_frame_interval()
787 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_g_frame_interval()
801 return v4l2_subdev_get_try_format(&mt9v111->sd, sd_state, pad); in __mt9v111_get_pad_format()
803 return &sd_state->pads->try_fmt; in __mt9v111_get_pad_format()
806 return &mt9v111->fmt; in __mt9v111_get_pad_format()
816 if (code->pad || code->index > ARRAY_SIZE(mt9v111_formats) - 1) in mt9v111_enum_mbus_code()
817 return -EINVAL; in mt9v111_enum_mbus_code()
819 code->code = mt9v111_formats[code->index].code; in mt9v111_enum_mbus_code()
830 if (fie->pad || fie->index >= ARRAY_SIZE(mt9v111_frame_intervals)) in mt9v111_enum_frame_interval()
831 return -EINVAL; in mt9v111_enum_frame_interval()
834 if (fie->width == mt9v111_frame_sizes[i].width && in mt9v111_enum_frame_interval()
835 fie->height == mt9v111_frame_sizes[i].height) in mt9v111_enum_frame_interval()
839 return -EINVAL; in mt9v111_enum_frame_interval()
841 fie->interval.numerator = 1; in mt9v111_enum_frame_interval()
842 fie->interval.denominator = mt9v111_frame_intervals[fie->index]; in mt9v111_enum_frame_interval()
851 if (fse->pad || fse->index >= ARRAY_SIZE(mt9v111_frame_sizes)) in mt9v111_enum_frame_size()
852 return -EINVAL; in mt9v111_enum_frame_size()
854 fse->min_width = mt9v111_frame_sizes[fse->index].width; in mt9v111_enum_frame_size()
855 fse->max_width = mt9v111_frame_sizes[fse->index].width; in mt9v111_enum_frame_size()
856 fse->min_height = mt9v111_frame_sizes[fse->index].height; in mt9v111_enum_frame_size()
857 fse->max_height = mt9v111_frame_sizes[fse->index].height; in mt9v111_enum_frame_size()
868 if (format->pad) in mt9v111_get_format()
869 return -EINVAL; in mt9v111_get_format()
871 mutex_lock(&mt9v111->stream_mutex); in mt9v111_get_format()
872 format->format = *__mt9v111_get_pad_format(mt9v111, sd_state, in mt9v111_get_format()
873 format->pad, in mt9v111_get_format()
874 format->which); in mt9v111_get_format()
875 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_get_format()
891 mutex_lock(&mt9v111->stream_mutex); in mt9v111_set_format()
892 if (mt9v111->streaming) { in mt9v111_set_format()
893 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_format()
894 return -EBUSY; in mt9v111_set_format()
897 if (format->pad) { in mt9v111_set_format()
898 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_format()
899 return -EINVAL; in mt9v111_set_format()
904 if (format->format.code == mt9v111_formats[i].code) { in mt9v111_set_format()
913 unsigned int fit = abs(mt9v111_frame_sizes[i].width - in mt9v111_set_format()
914 format->format.width) + in mt9v111_set_format()
915 abs(mt9v111_frame_sizes[i].height - in mt9v111_set_format()
916 format->format.height); in mt9v111_set_format()
929 __fmt = __mt9v111_get_pad_format(mt9v111, sd_state, format->pad, in mt9v111_set_format()
930 format->which); in mt9v111_set_format()
933 if (__fmt->code == new_fmt.code && in mt9v111_set_format()
934 __fmt->width == new_fmt.width && in mt9v111_set_format()
935 __fmt->height == new_fmt.height) in mt9v111_set_format()
939 __fmt->code = new_fmt.code; in mt9v111_set_format()
940 __fmt->width = new_fmt.width; in mt9v111_set_format()
941 __fmt->height = new_fmt.height; in mt9v111_set_format()
943 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) in mt9v111_set_format()
944 mt9v111->pending = true; in mt9v111_set_format()
946 dev_dbg(mt9v111->dev, "%s: mbus_code: %x - (%ux%u)\n", in mt9v111_set_format()
947 __func__, __fmt->code, __fmt->width, __fmt->height); in mt9v111_set_format()
950 format->format = *__fmt; in mt9v111_set_format()
952 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_format()
960 sd_state->pads->try_fmt = mt9v111_def_fmt; in mt9v111_init_cfg()
996 /* --- V4L2 ctrl --- */
999 struct mt9v111_dev *mt9v111 = container_of(ctrl->handler, in mt9v111_s_ctrl()
1004 mutex_lock(&mt9v111->pwr_mutex); in mt9v111_s_ctrl()
1009 if (!mt9v111->pwr_count) { in mt9v111_s_ctrl()
1010 mt9v111->pending = true; in mt9v111_s_ctrl()
1011 mutex_unlock(&mt9v111->pwr_mutex); in mt9v111_s_ctrl()
1014 mutex_unlock(&mt9v111->pwr_mutex); in mt9v111_s_ctrl()
1023 if (mt9v111->auto_exp->is_new || mt9v111->auto_awb->is_new) { in mt9v111_s_ctrl()
1024 if (mt9v111->auto_exp->val == V4L2_EXPOSURE_MANUAL && in mt9v111_s_ctrl()
1025 mt9v111->auto_awb->val == V4L2_WHITE_BALANCE_MANUAL) in mt9v111_s_ctrl()
1026 ret = mt9v111_update(mt9v111->client, MT9V111_R01_IFP, in mt9v111_s_ctrl()
1031 ret = mt9v111_update(mt9v111->client, MT9V111_R01_IFP, in mt9v111_s_ctrl()
1039 ret = -EINVAL; in mt9v111_s_ctrl()
1040 switch (ctrl->id) { in mt9v111_s_ctrl()
1042 ret = mt9v111_update(mt9v111->client, MT9V111_R01_IFP, in mt9v111_s_ctrl()
1045 ctrl->val == V4L2_WHITE_BALANCE_AUTO ? in mt9v111_s_ctrl()
1049 ret = mt9v111_update(mt9v111->client, MT9V111_R01_IFP, in mt9v111_s_ctrl()
1052 ctrl->val == V4L2_EXPOSURE_AUTO ? in mt9v111_s_ctrl()
1056 ret = mt9v111_update(mt9v111->client, MT9V111_R01_CORE, in mt9v111_s_ctrl()
1059 mt9v111->hblank->val); in mt9v111_s_ctrl()
1062 ret = mt9v111_update(mt9v111->client, MT9V111_R01_CORE, in mt9v111_s_ctrl()
1065 mt9v111->vblank->val); in mt9v111_s_ctrl()
1081 ret = __mt9v111_power_on(&mt9v111->sd); in mt9v111_chip_probe()
1085 ret = mt9v111_read(mt9v111->client, MT9V111_R01_CORE, in mt9v111_chip_probe()
1092 dev_err(mt9v111->dev, in mt9v111_chip_probe()
1095 ret = -EIO; in mt9v111_chip_probe()
1099 dev_dbg(mt9v111->dev, "Chip identified: 0x%2x%2x\n", in mt9v111_chip_probe()
1103 __mt9v111_power_off(&mt9v111->sd); in mt9v111_chip_probe()
1114 mt9v111 = devm_kzalloc(&client->dev, sizeof(*mt9v111), GFP_KERNEL); in mt9v111_probe()
1116 return -ENOMEM; in mt9v111_probe()
1118 mt9v111->dev = &client->dev; in mt9v111_probe()
1119 mt9v111->client = client; in mt9v111_probe()
1121 mt9v111->clk = devm_clk_get(&client->dev, NULL); in mt9v111_probe()
1122 if (IS_ERR(mt9v111->clk)) in mt9v111_probe()
1123 return PTR_ERR(mt9v111->clk); in mt9v111_probe()
1125 mt9v111->sysclk = clk_get_rate(mt9v111->clk); in mt9v111_probe()
1126 if (mt9v111->sysclk > MT9V111_MAX_CLKIN) in mt9v111_probe()
1127 return -EINVAL; in mt9v111_probe()
1129 mt9v111->oe = devm_gpiod_get_optional(&client->dev, "enable", in mt9v111_probe()
1131 if (IS_ERR(mt9v111->oe)) { in mt9v111_probe()
1132 dev_err(&client->dev, "Unable to get GPIO \"enable\": %ld\n", in mt9v111_probe()
1133 PTR_ERR(mt9v111->oe)); in mt9v111_probe()
1134 return PTR_ERR(mt9v111->oe); in mt9v111_probe()
1137 mt9v111->standby = devm_gpiod_get_optional(&client->dev, "standby", in mt9v111_probe()
1139 if (IS_ERR(mt9v111->standby)) { in mt9v111_probe()
1140 dev_err(&client->dev, "Unable to get GPIO \"standby\": %ld\n", in mt9v111_probe()
1141 PTR_ERR(mt9v111->standby)); in mt9v111_probe()
1142 return PTR_ERR(mt9v111->standby); in mt9v111_probe()
1145 mt9v111->reset = devm_gpiod_get_optional(&client->dev, "reset", in mt9v111_probe()
1147 if (IS_ERR(mt9v111->reset)) { in mt9v111_probe()
1148 dev_err(&client->dev, "Unable to get GPIO \"reset\": %ld\n", in mt9v111_probe()
1149 PTR_ERR(mt9v111->reset)); in mt9v111_probe()
1150 return PTR_ERR(mt9v111->reset); in mt9v111_probe()
1153 mutex_init(&mt9v111->pwr_mutex); in mt9v111_probe()
1154 mutex_init(&mt9v111->stream_mutex); in mt9v111_probe()
1156 v4l2_ctrl_handler_init(&mt9v111->ctrls, 5); in mt9v111_probe()
1158 mt9v111->auto_awb = v4l2_ctrl_new_std(&mt9v111->ctrls, in mt9v111_probe()
1163 mt9v111->auto_exp = v4l2_ctrl_new_std_menu(&mt9v111->ctrls, in mt9v111_probe()
1168 mt9v111->hblank = v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops, in mt9v111_probe()
1173 mt9v111->vblank = v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops, in mt9v111_probe()
1180 v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops, in mt9v111_probe()
1182 DIV_ROUND_CLOSEST(mt9v111->sysclk, 2), 1, in mt9v111_probe()
1183 DIV_ROUND_CLOSEST(mt9v111->sysclk, 2)); in mt9v111_probe()
1185 if (mt9v111->ctrls.error) { in mt9v111_probe()
1186 ret = mt9v111->ctrls.error; in mt9v111_probe()
1189 mt9v111->sd.ctrl_handler = &mt9v111->ctrls; in mt9v111_probe()
1192 mt9v111->fmt = mt9v111_def_fmt; in mt9v111_probe()
1194 /* Re-calculate blankings for 640x480@15fps. */ in mt9v111_probe()
1195 mt9v111->fps = 15; in mt9v111_probe()
1197 tpf.denominator = mt9v111->fps; in mt9v111_probe()
1200 mt9v111->pwr_count = 0; in mt9v111_probe()
1201 mt9v111->addr_space = MT9V111_R01_IFP; in mt9v111_probe()
1202 mt9v111->pending = true; in mt9v111_probe()
1204 v4l2_i2c_subdev_init(&mt9v111->sd, client, &mt9v111_ops); in mt9v111_probe()
1207 mt9v111->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in mt9v111_probe()
1208 mt9v111->sd.entity.ops = &mt9v111_subdev_entity_ops; in mt9v111_probe()
1209 mt9v111->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; in mt9v111_probe()
1211 mt9v111->pad.flags = MEDIA_PAD_FL_SOURCE; in mt9v111_probe()
1212 ret = media_entity_pads_init(&mt9v111->sd.entity, 1, &mt9v111->pad); in mt9v111_probe()
1221 ret = v4l2_async_register_subdev(&mt9v111->sd); in mt9v111_probe()
1229 media_entity_cleanup(&mt9v111->sd.entity); in mt9v111_probe()
1233 v4l2_ctrl_handler_free(&mt9v111->ctrls); in mt9v111_probe()
1235 mutex_destroy(&mt9v111->pwr_mutex); in mt9v111_probe()
1236 mutex_destroy(&mt9v111->stream_mutex); in mt9v111_probe()
1249 media_entity_cleanup(&sd->entity); in mt9v111_remove()
1252 v4l2_ctrl_handler_free(&mt9v111->ctrls); in mt9v111_remove()
1254 mutex_destroy(&mt9v111->pwr_mutex); in mt9v111_remove()
1255 mutex_destroy(&mt9v111->stream_mutex); in mt9v111_remove()