Lines Matching full:mt9p031
3 * Driver for MT9P031 CMOS Image Sensor from Aptina
118 struct mt9p031 { struct
148 static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd) in to_mt9p031() argument
150 return container_of(sd, struct mt9p031, subdev); in to_mt9p031()
163 static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear, in mt9p031_set_output_control() argument
166 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_set_output_control()
167 u16 value = (mt9p031->output_control & ~clear) | set; in mt9p031_set_output_control()
174 mt9p031->output_control = value; in mt9p031_set_output_control()
178 static int mt9p031_set_mode2(struct mt9p031 *mt9p031, u16 clear, u16 set) in mt9p031_set_mode2() argument
180 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_set_mode2()
181 u16 value = (mt9p031->mode2 & ~clear) | set; in mt9p031_set_mode2()
188 mt9p031->mode2 = value; in mt9p031_set_mode2()
192 static int mt9p031_reset(struct mt9p031 *mt9p031) in mt9p031_reset() argument
194 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_reset()
206 MT9P031_PIXEL_CLOCK_DIVIDE(mt9p031->clk_div)); in mt9p031_reset()
210 return mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN, in mt9p031_reset()
214 static int mt9p031_clk_setup(struct mt9p031 *mt9p031) in mt9p031_clk_setup() argument
232 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_clk_setup()
236 mt9p031->clk = devm_clk_get(&client->dev, NULL); in mt9p031_clk_setup()
237 if (IS_ERR(mt9p031->clk)) in mt9p031_clk_setup()
238 return PTR_ERR(mt9p031->clk); in mt9p031_clk_setup()
240 ret = clk_set_rate(mt9p031->clk, mt9p031->ext_freq); in mt9p031_clk_setup()
244 ext_freq = clk_get_rate(mt9p031->clk); in mt9p031_clk_setup()
252 div = DIV_ROUND_UP(ext_freq, mt9p031->target_freq); in mt9p031_clk_setup()
255 mt9p031->clk_div = min_t(unsigned int, div, 64); in mt9p031_clk_setup()
256 mt9p031->use_pll = false; in mt9p031_clk_setup()
261 mt9p031->pll.ext_clock = ext_freq; in mt9p031_clk_setup()
262 mt9p031->pll.pix_clock = mt9p031->target_freq; in mt9p031_clk_setup()
263 mt9p031->use_pll = true; in mt9p031_clk_setup()
265 return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); in mt9p031_clk_setup()
268 static int mt9p031_pll_enable(struct mt9p031 *mt9p031) in mt9p031_pll_enable() argument
270 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_pll_enable()
273 if (!mt9p031->use_pll) in mt9p031_pll_enable()
282 (mt9p031->pll.m << 8) | (mt9p031->pll.n - 1)); in mt9p031_pll_enable()
286 ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll.p1 - 1); in mt9p031_pll_enable()
297 static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031) in mt9p031_pll_disable() argument
299 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_pll_disable()
301 if (!mt9p031->use_pll) in mt9p031_pll_disable()
308 static int mt9p031_power_on(struct mt9p031 *mt9p031) in mt9p031_power_on() argument
314 if (mt9p031->reset) { in mt9p031_power_on()
315 gpiod_set_value(mt9p031->reset, 1); in mt9p031_power_on()
320 ret = regulator_bulk_enable(ARRAY_SIZE(mt9p031->regulators), in mt9p031_power_on()
321 mt9p031->regulators); in mt9p031_power_on()
326 if (mt9p031->clk) { in mt9p031_power_on()
327 ret = clk_prepare_enable(mt9p031->clk); in mt9p031_power_on()
329 regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators), in mt9p031_power_on()
330 mt9p031->regulators); in mt9p031_power_on()
336 if (mt9p031->reset) { in mt9p031_power_on()
337 gpiod_set_value(mt9p031->reset, 0); in mt9p031_power_on()
339 rate = clk_get_rate(mt9p031->clk); in mt9p031_power_on()
349 static void mt9p031_power_off(struct mt9p031 *mt9p031) in mt9p031_power_off() argument
351 if (mt9p031->reset) { in mt9p031_power_off()
352 gpiod_set_value(mt9p031->reset, 1); in mt9p031_power_off()
356 regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators), in mt9p031_power_off()
357 mt9p031->regulators); in mt9p031_power_off()
359 clk_disable_unprepare(mt9p031->clk); in mt9p031_power_off()
362 static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on) in __mt9p031_set_power() argument
364 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in __mt9p031_set_power()
368 mt9p031_power_off(mt9p031); in __mt9p031_set_power()
372 ret = mt9p031_power_on(mt9p031); in __mt9p031_set_power()
376 ret = mt9p031_reset(mt9p031); in __mt9p031_set_power()
383 if (mt9p031->pixclk_pol) { in __mt9p031_set_power()
390 return v4l2_ctrl_handler_setup(&mt9p031->ctrls); in __mt9p031_set_power()
397 static int mt9p031_set_params(struct mt9p031 *mt9p031) in mt9p031_set_params() argument
399 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_set_params()
400 struct v4l2_mbus_framefmt *format = &mt9p031->format; in mt9p031_set_params()
401 const struct v4l2_rect *crop = &mt9p031->crop; in mt9p031_set_params()
464 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_s_stream() local
483 ret = mt9p031_set_output_control(mt9p031, in mt9p031_s_stream()
488 return mt9p031_pll_disable(mt9p031); in mt9p031_s_stream()
491 ret = mt9p031_set_params(mt9p031); in mt9p031_s_stream()
496 ret = mt9p031_set_output_control(mt9p031, 0, in mt9p031_s_stream()
511 return mt9p031_pll_enable(mt9p031); in mt9p031_s_stream()
518 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_enum_mbus_code() local
523 code->code = mt9p031->format.code; in mt9p031_enum_mbus_code()
531 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_enum_frame_size() local
533 if (fse->index >= 8 || fse->code != mt9p031->format.code) in mt9p031_enum_frame_size()
546 __mt9p031_get_pad_format(struct mt9p031 *mt9p031, in __mt9p031_get_pad_format() argument
554 return &mt9p031->format; in __mt9p031_get_pad_format()
561 __mt9p031_get_pad_crop(struct mt9p031 *mt9p031, in __mt9p031_get_pad_crop() argument
569 return &mt9p031->crop; in __mt9p031_get_pad_crop()
579 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_get_format() local
581 fmt->format = *__mt9p031_get_pad_format(mt9p031, sd_state, fmt->pad, in mt9p031_get_format()
590 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_set_format() local
598 __crop = __mt9p031_get_pad_crop(mt9p031, sd_state, format->pad, in mt9p031_set_format()
614 __format = __mt9p031_get_pad_format(mt9p031, sd_state, format->pad, in mt9p031_set_format()
628 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_get_selection() local
639 sel->r = *__mt9p031_get_pad_crop(mt9p031, sd_state, in mt9p031_get_selection()
652 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_set_selection() local
679 __crop = __mt9p031_get_pad_crop(mt9p031, sd_state, sel->pad, in mt9p031_set_selection()
686 __format = __mt9p031_get_pad_format(mt9p031, sd_state, in mt9p031_set_selection()
702 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_init_state() local
708 crop = __mt9p031_get_pad_crop(mt9p031, sd_state, 0, which); in mt9p031_init_state()
714 format = __mt9p031_get_pad_format(mt9p031, sd_state, 0, which); in mt9p031_init_state()
715 format->code = mt9p031->code; in mt9p031_init_state()
733 static int mt9p031_restore_blc(struct mt9p031 *mt9p031) in mt9p031_restore_blc() argument
735 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_restore_blc()
738 if (mt9p031->blc_auto->cur.val != 0) { in mt9p031_restore_blc()
739 ret = mt9p031_set_mode2(mt9p031, 0, in mt9p031_restore_blc()
745 if (mt9p031->blc_offset->cur.val != 0) { in mt9p031_restore_blc()
747 mt9p031->blc_offset->cur.val); in mt9p031_restore_blc()
757 struct mt9p031 *mt9p031 = in mt9p031_s_ctrl() local
758 container_of(ctrl->handler, struct mt9p031, ctrls); in mt9p031_s_ctrl()
759 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); in mt9p031_s_ctrl()
805 return mt9p031_set_mode2(mt9p031, in mt9p031_s_ctrl()
808 return mt9p031_set_mode2(mt9p031, in mt9p031_s_ctrl()
813 return mt9p031_set_mode2(mt9p031, in mt9p031_s_ctrl()
816 return mt9p031_set_mode2(mt9p031, in mt9p031_s_ctrl()
825 v4l2_ctrl_activate(mt9p031->blc_auto, ctrl->val == 0); in mt9p031_s_ctrl()
826 v4l2_ctrl_activate(mt9p031->blc_offset, ctrl->val == 0); in mt9p031_s_ctrl()
830 ret = mt9p031_restore_blc(mt9p031); in mt9p031_s_ctrl()
848 ret = mt9p031_set_mode2(mt9p031, MT9P031_READ_MODE_2_ROW_BLC, in mt9p031_s_ctrl()
862 ret = mt9p031_set_mode2(mt9p031, in mt9p031_s_ctrl()
964 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_set_power() local
967 mutex_lock(&mt9p031->power_lock); in mt9p031_set_power()
972 if (mt9p031->power_count == !on) { in mt9p031_set_power()
973 ret = __mt9p031_set_power(mt9p031, !!on); in mt9p031_set_power()
979 mt9p031->power_count += on ? 1 : -1; in mt9p031_set_power()
980 WARN_ON(mt9p031->power_count < 0); in mt9p031_set_power()
983 mutex_unlock(&mt9p031->power_lock); in mt9p031_set_power()
994 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_registered() local
998 ret = mt9p031_power_on(mt9p031); in mt9p031_registered()
1000 dev_err(&client->dev, "MT9P031 power up failed\n"); in mt9p031_registered()
1006 mt9p031_power_off(mt9p031); in mt9p031_registered()
1009 dev_err(&client->dev, "MT9P031 not detected, wrong version " in mt9p031_registered()
1014 dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n", in mt9p031_registered()
1064 static int mt9p031_parse_properties(struct mt9p031 *mt9p031, struct device *dev) in mt9p031_parse_properties() argument
1082 &mt9p031->ext_freq); in mt9p031_parse_properties()
1084 &mt9p031->target_freq); in mt9p031_parse_properties()
1086 mt9p031->pixclk_pol = !!(endpoint.bus.parallel.flags & in mt9p031_parse_properties()
1095 struct mt9p031 *mt9p031; in mt9p031_probe() local
1105 mt9p031 = devm_kzalloc(&client->dev, sizeof(*mt9p031), GFP_KERNEL); in mt9p031_probe()
1106 if (mt9p031 == NULL) in mt9p031_probe()
1109 ret = mt9p031_parse_properties(mt9p031, &client->dev); in mt9p031_probe()
1113 mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF; in mt9p031_probe()
1114 mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC; in mt9p031_probe()
1115 mt9p031->code = (uintptr_t)device_get_match_data(&client->dev); in mt9p031_probe()
1117 mt9p031->regulators[0].supply = "vdd"; in mt9p031_probe()
1118 mt9p031->regulators[1].supply = "vdd_io"; in mt9p031_probe()
1119 mt9p031->regulators[2].supply = "vaa"; in mt9p031_probe()
1121 ret = devm_regulator_bulk_get(&client->dev, 3, mt9p031->regulators); in mt9p031_probe()
1127 mutex_init(&mt9p031->power_lock); in mt9p031_probe()
1129 v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6); in mt9p031_probe()
1131 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, in mt9p031_probe()
1135 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, in mt9p031_probe()
1138 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, in mt9p031_probe()
1140 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, in mt9p031_probe()
1142 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, in mt9p031_probe()
1143 V4L2_CID_PIXEL_RATE, mt9p031->target_freq, in mt9p031_probe()
1144 mt9p031->target_freq, 1, mt9p031->target_freq); in mt9p031_probe()
1145 v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops, in mt9p031_probe()
1151 v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL); in mt9p031_probe()
1153 mt9p031->subdev.ctrl_handler = &mt9p031->ctrls; in mt9p031_probe()
1155 if (mt9p031->ctrls.error) { in mt9p031_probe()
1157 __func__, mt9p031->ctrls.error); in mt9p031_probe()
1158 ret = mt9p031->ctrls.error; in mt9p031_probe()
1162 mt9p031->blc_auto = v4l2_ctrl_find(&mt9p031->ctrls, V4L2_CID_BLC_AUTO); in mt9p031_probe()
1163 mt9p031->blc_offset = v4l2_ctrl_find(&mt9p031->ctrls, in mt9p031_probe()
1166 v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops); in mt9p031_probe()
1167 mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops; in mt9p031_probe()
1169 mt9p031->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; in mt9p031_probe()
1170 mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE; in mt9p031_probe()
1171 ret = media_entity_pads_init(&mt9p031->subdev.entity, 1, &mt9p031->pad); in mt9p031_probe()
1175 mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in mt9p031_probe()
1177 ret = mt9p031_init_state(&mt9p031->subdev, NULL); in mt9p031_probe()
1181 mt9p031->reset = devm_gpiod_get_optional(&client->dev, "reset", in mt9p031_probe()
1184 ret = mt9p031_clk_setup(mt9p031); in mt9p031_probe()
1188 ret = v4l2_async_register_subdev(&mt9p031->subdev); in mt9p031_probe()
1192 v4l2_ctrl_handler_free(&mt9p031->ctrls); in mt9p031_probe()
1193 media_entity_cleanup(&mt9p031->subdev.entity); in mt9p031_probe()
1194 mutex_destroy(&mt9p031->power_lock); in mt9p031_probe()
1203 struct mt9p031 *mt9p031 = to_mt9p031(subdev); in mt9p031_remove() local
1205 v4l2_ctrl_handler_free(&mt9p031->ctrls); in mt9p031_remove()
1208 mutex_destroy(&mt9p031->power_lock); in mt9p031_remove()
1221 { .compatible = "aptina,mt9p031", .data = &mt9p031_models_bayer },
1230 .name = "mt9p031",
1238 MODULE_DESCRIPTION("Aptina MT9P031 Camera driver");