Lines Matching +full:9 +full:- +full:inch
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).
77 #define MT9V111_IFP_DECIMATION_MASK GENMASK(9, 0)
86 #define MT9V111_CORE_R05_MAX_HBLANK GENMASK(9, 0)
159 * mt9v111_mbus_fmt - List all media bus formats supported by the driver.
188 * mt9v111_frame_sizes - List sensor's supported resolutions.
216 /* --- Device I/O access --- */
224 msg[0].addr = c->addr; in __mt9v111_read()
229 msg[1].addr = c->addr; in __mt9v111_read()
234 ret = i2c_transfer(c->adapter, msg, 2); in __mt9v111_read()
236 dev_err(&c->dev, "i2c read transfer error: %d\n", ret); in __mt9v111_read()
242 dev_dbg(&c->dev, "%s: %x=%x\n", __func__, reg, *val); in __mt9v111_read()
257 msg.addr = c->addr; in __mt9v111_write()
262 dev_dbg(&c->dev, "%s: %x = %x%x\n", __func__, reg, buf[1], buf[2]); in __mt9v111_write()
264 ret = i2c_transfer(c->adapter, &msg, 1); in __mt9v111_write()
266 dev_err(&c->dev, "i2c write transfer error: %d\n", ret); in __mt9v111_write()
280 if (mt9v111->addr_space == addr_space) in __mt9v111_addr_space_select()
293 return -EINVAL; in __mt9v111_addr_space_select()
295 mt9v111->addr_space = addr_space; in __mt9v111_addr_space_select()
357 /* --- Sensor HW operations --- */
364 ret = clk_prepare_enable(mt9v111->clk); in __mt9v111_power_on()
368 clk_set_rate(mt9v111->clk, mt9v111->sysclk); in __mt9v111_power_on()
370 gpiod_set_value(mt9v111->standby, 0); in __mt9v111_power_on()
373 gpiod_set_value(mt9v111->oe, 1); in __mt9v111_power_on()
383 gpiod_set_value(mt9v111->oe, 0); in __mt9v111_power_off()
386 gpiod_set_value(mt9v111->standby, 1); in __mt9v111_power_off()
389 clk_disable_unprepare(mt9v111->clk); in __mt9v111_power_off()
396 if (!mt9v111->reset) in __mt9v111_hw_reset()
397 return -EINVAL; in __mt9v111_hw_reset()
399 gpiod_set_value(mt9v111->reset, 1); in __mt9v111_hw_reset()
402 gpiod_set_value(mt9v111->reset, 0); in __mt9v111_hw_reset()
410 struct i2c_client *c = mt9v111->client; in __mt9v111_sw_reset()
449 unsigned int fps = tpf->numerator ? in mt9v111_calc_frame_rate()
450 tpf->denominator / tpf->numerator : in mt9v111_calc_frame_rate()
451 tpf->denominator; in mt9v111_calc_frame_rate()
467 diff = abs(fps - mt9v111_frame_intervals[i]); in mt9v111_calc_frame_rate()
491 pclk = DIV_ROUND_CLOSEST(mt9v111->sysclk, 2); in mt9v111_calc_frame_rate()
504 diff = abs(fps - t_fps); in mt9v111_calc_frame_rate()
518 ret = v4l2_ctrl_s_ctrl_int64(mt9v111->hblank, hb); in mt9v111_calc_frame_rate()
522 ret = v4l2_ctrl_s_ctrl_int64(mt9v111->vblank, vb); in mt9v111_calc_frame_rate()
526 tpf->numerator = 1; in mt9v111_calc_frame_rate()
527 tpf->denominator = best_fps; in mt9v111_calc_frame_rate()
534 struct i2c_client *c = mt9v111->client; in mt9v111_hw_config()
540 if (ret == -EINVAL) in mt9v111_hw_config()
546 ret = mt9v111->sysclk < DIV_ROUND_CLOSEST(MT9V111_MAX_CLKIN, 2) ? in mt9v111_hw_config()
562 switch (mt9v111->fmt.code) { in mt9v111_hw_config()
618 mt9v111->fmt.width); in mt9v111_hw_config()
623 mt9v111->fmt.height); in mt9v111_hw_config()
628 ret = v4l2_ctrl_handler_setup(&mt9v111->ctrls); in mt9v111_hw_config()
642 /* --- V4L2 subdev operations --- */
650 mutex_lock(&mt9v111->pwr_mutex); in mt9v111_s_power()
656 pwr_count = mt9v111->pwr_count; in mt9v111_s_power()
657 pwr_count += on ? 1 : -1; in mt9v111_s_power()
663 mt9v111->pwr_count = pwr_count; in mt9v111_s_power()
665 mutex_unlock(&mt9v111->pwr_mutex); in mt9v111_s_power()
675 mt9v111->pwr_count = pwr_count; in mt9v111_s_power()
677 mutex_unlock(&mt9v111->pwr_mutex); in mt9v111_s_power()
687 mutex_lock(&mt9v111->stream_mutex); in mt9v111_s_stream()
689 if (mt9v111->streaming == enable) { in mt9v111_s_stream()
690 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_stream()
698 if (enable && mt9v111->pending) { in mt9v111_s_stream()
708 mt9v111->pending = false; in mt9v111_s_stream()
711 mt9v111->streaming = enable ? true : false; in mt9v111_s_stream()
712 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_stream()
717 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_s_stream()
727 struct v4l2_fract *tpf = &ival->interval; in mt9v111_set_frame_interval()
728 unsigned int fps = tpf->numerator ? in mt9v111_set_frame_interval()
729 tpf->denominator / tpf->numerator : in mt9v111_set_frame_interval()
730 tpf->denominator; in mt9v111_set_frame_interval()
737 if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) in mt9v111_set_frame_interval()
738 return -EINVAL; in mt9v111_set_frame_interval()
740 if (!tpf->numerator) in mt9v111_set_frame_interval()
741 tpf->numerator = 1; in mt9v111_set_frame_interval()
743 mutex_lock(&mt9v111->stream_mutex); in mt9v111_set_frame_interval()
745 if (mt9v111->streaming) { in mt9v111_set_frame_interval()
746 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_frame_interval()
747 return -EBUSY; in mt9v111_set_frame_interval()
750 if (mt9v111->fps == fps) { in mt9v111_set_frame_interval()
751 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_frame_interval()
756 if (mt9v111->fmt.width < QVGA_WIDTH && in mt9v111_set_frame_interval()
757 mt9v111->fmt.height < QVGA_HEIGHT) in mt9v111_set_frame_interval()
759 else if (mt9v111->fmt.width < CIF_WIDTH && in mt9v111_set_frame_interval()
760 mt9v111->fmt.height < CIF_HEIGHT) in mt9v111_set_frame_interval()
763 max_fps = mt9v111->sysclk < in mt9v111_set_frame_interval()
768 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_frame_interval()
769 return -EINVAL; in mt9v111_set_frame_interval()
774 mt9v111->fps = fps; in mt9v111_set_frame_interval()
775 mt9v111->pending = true; in mt9v111_set_frame_interval()
777 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_frame_interval()
787 struct v4l2_fract *tpf = &ival->interval; in mt9v111_get_frame_interval()
793 if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) in mt9v111_get_frame_interval()
794 return -EINVAL; in mt9v111_get_frame_interval()
796 mutex_lock(&mt9v111->stream_mutex); in mt9v111_get_frame_interval()
798 tpf->numerator = 1; in mt9v111_get_frame_interval()
799 tpf->denominator = mt9v111->fps; in mt9v111_get_frame_interval()
801 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_get_frame_interval()
816 return &mt9v111->fmt; in __mt9v111_get_pad_format()
826 if (code->pad || code->index > ARRAY_SIZE(mt9v111_formats) - 1) in mt9v111_enum_mbus_code()
827 return -EINVAL; in mt9v111_enum_mbus_code()
829 code->code = mt9v111_formats[code->index].code; in mt9v111_enum_mbus_code()
840 if (fie->pad || fie->index >= ARRAY_SIZE(mt9v111_frame_intervals)) in mt9v111_enum_frame_interval()
841 return -EINVAL; in mt9v111_enum_frame_interval()
844 if (fie->width == mt9v111_frame_sizes[i].width && in mt9v111_enum_frame_interval()
845 fie->height == mt9v111_frame_sizes[i].height) in mt9v111_enum_frame_interval()
849 return -EINVAL; in mt9v111_enum_frame_interval()
851 fie->interval.numerator = 1; in mt9v111_enum_frame_interval()
852 fie->interval.denominator = mt9v111_frame_intervals[fie->index]; in mt9v111_enum_frame_interval()
861 if (fse->pad || fse->index >= ARRAY_SIZE(mt9v111_frame_sizes)) in mt9v111_enum_frame_size()
862 return -EINVAL; in mt9v111_enum_frame_size()
864 fse->min_width = mt9v111_frame_sizes[fse->index].width; in mt9v111_enum_frame_size()
865 fse->max_width = mt9v111_frame_sizes[fse->index].width; in mt9v111_enum_frame_size()
866 fse->min_height = mt9v111_frame_sizes[fse->index].height; in mt9v111_enum_frame_size()
867 fse->max_height = mt9v111_frame_sizes[fse->index].height; in mt9v111_enum_frame_size()
878 if (format->pad) in mt9v111_get_format()
879 return -EINVAL; in mt9v111_get_format()
881 mutex_lock(&mt9v111->stream_mutex); in mt9v111_get_format()
882 format->format = *__mt9v111_get_pad_format(mt9v111, sd_state, in mt9v111_get_format()
883 format->pad, in mt9v111_get_format()
884 format->which); in mt9v111_get_format()
885 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_get_format()
901 mutex_lock(&mt9v111->stream_mutex); in mt9v111_set_format()
902 if (mt9v111->streaming) { in mt9v111_set_format()
903 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_format()
904 return -EBUSY; in mt9v111_set_format()
907 if (format->pad) { in mt9v111_set_format()
908 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_format()
909 return -EINVAL; in mt9v111_set_format()
914 if (format->format.code == mt9v111_formats[i].code) { in mt9v111_set_format()
923 unsigned int fit = abs(mt9v111_frame_sizes[i].width - in mt9v111_set_format()
924 format->format.width) + in mt9v111_set_format()
925 abs(mt9v111_frame_sizes[i].height - in mt9v111_set_format()
926 format->format.height); in mt9v111_set_format()
939 __fmt = __mt9v111_get_pad_format(mt9v111, sd_state, format->pad, in mt9v111_set_format()
940 format->which); in mt9v111_set_format()
943 if (__fmt->code == new_fmt.code && in mt9v111_set_format()
944 __fmt->width == new_fmt.width && in mt9v111_set_format()
945 __fmt->height == new_fmt.height) in mt9v111_set_format()
949 __fmt->code = new_fmt.code; in mt9v111_set_format()
950 __fmt->width = new_fmt.width; in mt9v111_set_format()
951 __fmt->height = new_fmt.height; in mt9v111_set_format()
953 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) in mt9v111_set_format()
954 mt9v111->pending = true; in mt9v111_set_format()
956 dev_dbg(mt9v111->dev, "%s: mbus_code: %x - (%ux%u)\n", in mt9v111_set_format()
957 __func__, __fmt->code, __fmt->width, __fmt->height); in mt9v111_set_format()
960 format->format = *__fmt; in mt9v111_set_format()
962 mutex_unlock(&mt9v111->stream_mutex); in mt9v111_set_format()
1007 /* --- V4L2 ctrl --- */
1010 struct mt9v111_dev *mt9v111 = container_of(ctrl->handler, in mt9v111_s_ctrl()
1015 mutex_lock(&mt9v111->pwr_mutex); in mt9v111_s_ctrl()
1020 if (!mt9v111->pwr_count) { in mt9v111_s_ctrl()
1021 mt9v111->pending = true; in mt9v111_s_ctrl()
1022 mutex_unlock(&mt9v111->pwr_mutex); in mt9v111_s_ctrl()
1025 mutex_unlock(&mt9v111->pwr_mutex); in mt9v111_s_ctrl()
1034 if (mt9v111->auto_exp->is_new || mt9v111->auto_awb->is_new) { in mt9v111_s_ctrl()
1035 if (mt9v111->auto_exp->val == V4L2_EXPOSURE_MANUAL && in mt9v111_s_ctrl()
1036 mt9v111->auto_awb->val == V4L2_WHITE_BALANCE_MANUAL) in mt9v111_s_ctrl()
1037 ret = mt9v111_update(mt9v111->client, MT9V111_R01_IFP, in mt9v111_s_ctrl()
1042 ret = mt9v111_update(mt9v111->client, MT9V111_R01_IFP, in mt9v111_s_ctrl()
1050 ret = -EINVAL; in mt9v111_s_ctrl()
1051 switch (ctrl->id) { in mt9v111_s_ctrl()
1053 ret = mt9v111_update(mt9v111->client, MT9V111_R01_IFP, in mt9v111_s_ctrl()
1056 ctrl->val == V4L2_WHITE_BALANCE_AUTO ? in mt9v111_s_ctrl()
1060 ret = mt9v111_update(mt9v111->client, MT9V111_R01_IFP, in mt9v111_s_ctrl()
1063 ctrl->val == V4L2_EXPOSURE_AUTO ? in mt9v111_s_ctrl()
1067 ret = mt9v111_update(mt9v111->client, MT9V111_R01_CORE, in mt9v111_s_ctrl()
1070 mt9v111->hblank->val); in mt9v111_s_ctrl()
1073 ret = mt9v111_update(mt9v111->client, MT9V111_R01_CORE, in mt9v111_s_ctrl()
1076 mt9v111->vblank->val); in mt9v111_s_ctrl()
1092 ret = __mt9v111_power_on(&mt9v111->sd); in mt9v111_chip_probe()
1096 ret = mt9v111_read(mt9v111->client, MT9V111_R01_CORE, in mt9v111_chip_probe()
1103 dev_err(mt9v111->dev, in mt9v111_chip_probe()
1106 ret = -EIO; in mt9v111_chip_probe()
1110 dev_dbg(mt9v111->dev, "Chip identified: 0x%2x%2x\n", in mt9v111_chip_probe()
1114 __mt9v111_power_off(&mt9v111->sd); in mt9v111_chip_probe()
1125 mt9v111 = devm_kzalloc(&client->dev, sizeof(*mt9v111), GFP_KERNEL); in mt9v111_probe()
1127 return -ENOMEM; in mt9v111_probe()
1129 mt9v111->dev = &client->dev; in mt9v111_probe()
1130 mt9v111->client = client; in mt9v111_probe()
1132 mt9v111->clk = devm_clk_get(&client->dev, NULL); in mt9v111_probe()
1133 if (IS_ERR(mt9v111->clk)) in mt9v111_probe()
1134 return PTR_ERR(mt9v111->clk); in mt9v111_probe()
1136 mt9v111->sysclk = clk_get_rate(mt9v111->clk); in mt9v111_probe()
1137 if (mt9v111->sysclk > MT9V111_MAX_CLKIN) in mt9v111_probe()
1138 return -EINVAL; in mt9v111_probe()
1140 mt9v111->oe = devm_gpiod_get_optional(&client->dev, "enable", in mt9v111_probe()
1142 if (IS_ERR(mt9v111->oe)) { in mt9v111_probe()
1143 dev_err(&client->dev, "Unable to get GPIO \"enable\": %ld\n", in mt9v111_probe()
1144 PTR_ERR(mt9v111->oe)); in mt9v111_probe()
1145 return PTR_ERR(mt9v111->oe); in mt9v111_probe()
1148 mt9v111->standby = devm_gpiod_get_optional(&client->dev, "standby", in mt9v111_probe()
1150 if (IS_ERR(mt9v111->standby)) { in mt9v111_probe()
1151 dev_err(&client->dev, "Unable to get GPIO \"standby\": %ld\n", in mt9v111_probe()
1152 PTR_ERR(mt9v111->standby)); in mt9v111_probe()
1153 return PTR_ERR(mt9v111->standby); in mt9v111_probe()
1156 mt9v111->reset = devm_gpiod_get_optional(&client->dev, "reset", in mt9v111_probe()
1158 if (IS_ERR(mt9v111->reset)) { in mt9v111_probe()
1159 dev_err(&client->dev, "Unable to get GPIO \"reset\": %ld\n", in mt9v111_probe()
1160 PTR_ERR(mt9v111->reset)); in mt9v111_probe()
1161 return PTR_ERR(mt9v111->reset); in mt9v111_probe()
1164 mutex_init(&mt9v111->pwr_mutex); in mt9v111_probe()
1165 mutex_init(&mt9v111->stream_mutex); in mt9v111_probe()
1167 v4l2_ctrl_handler_init(&mt9v111->ctrls, 5); in mt9v111_probe()
1169 mt9v111->auto_awb = v4l2_ctrl_new_std(&mt9v111->ctrls, in mt9v111_probe()
1174 mt9v111->auto_exp = v4l2_ctrl_new_std_menu(&mt9v111->ctrls, in mt9v111_probe()
1179 mt9v111->hblank = v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops, in mt9v111_probe()
1184 mt9v111->vblank = v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops, in mt9v111_probe()
1191 v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops, in mt9v111_probe()
1193 DIV_ROUND_CLOSEST(mt9v111->sysclk, 2), 1, in mt9v111_probe()
1194 DIV_ROUND_CLOSEST(mt9v111->sysclk, 2)); in mt9v111_probe()
1196 if (mt9v111->ctrls.error) { in mt9v111_probe()
1197 ret = mt9v111->ctrls.error; in mt9v111_probe()
1200 mt9v111->sd.ctrl_handler = &mt9v111->ctrls; in mt9v111_probe()
1203 mt9v111->fmt = mt9v111_def_fmt; in mt9v111_probe()
1205 /* Re-calculate blankings for 640x480@15fps. */ in mt9v111_probe()
1206 mt9v111->fps = 15; in mt9v111_probe()
1208 tpf.denominator = mt9v111->fps; in mt9v111_probe()
1211 mt9v111->pwr_count = 0; in mt9v111_probe()
1212 mt9v111->addr_space = MT9V111_R01_IFP; in mt9v111_probe()
1213 mt9v111->pending = true; in mt9v111_probe()
1215 v4l2_i2c_subdev_init(&mt9v111->sd, client, &mt9v111_ops); in mt9v111_probe()
1216 mt9v111->sd.internal_ops = &mt9v111_internal_ops; in mt9v111_probe()
1218 mt9v111->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in mt9v111_probe()
1219 mt9v111->sd.entity.ops = &mt9v111_subdev_entity_ops; in mt9v111_probe()
1220 mt9v111->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; in mt9v111_probe()
1222 mt9v111->pad.flags = MEDIA_PAD_FL_SOURCE; in mt9v111_probe()
1223 ret = media_entity_pads_init(&mt9v111->sd.entity, 1, &mt9v111->pad); in mt9v111_probe()
1231 ret = v4l2_async_register_subdev(&mt9v111->sd); in mt9v111_probe()
1238 media_entity_cleanup(&mt9v111->sd.entity); in mt9v111_probe()
1241 v4l2_ctrl_handler_free(&mt9v111->ctrls); in mt9v111_probe()
1243 mutex_destroy(&mt9v111->pwr_mutex); in mt9v111_probe()
1244 mutex_destroy(&mt9v111->stream_mutex); in mt9v111_probe()
1256 media_entity_cleanup(&sd->entity); in mt9v111_remove()
1258 v4l2_ctrl_handler_free(&mt9v111->ctrls); in mt9v111_remove()
1260 mutex_destroy(&mt9v111->pwr_mutex); in mt9v111_remove()
1261 mutex_destroy(&mt9v111->stream_mutex); in mt9v111_remove()