Lines Matching +full:capture +full:- +full:sd +full:- +full:lines
1 // SPDX-License-Identifier: GPL-2.0
18 #include <media/v4l2-ctrls.h>
19 #include <media/v4l2-device.h>
20 #include <media/v4l2-event.h>
21 #include <media/v4l2-subdev.h>
83 /* Order important - see above */
92 /* exposure/auto-exposure cluster */
105 unsigned short y_skip_top; /* Lines to skip at the top */
180 dev_dbg(&client->dev, "%s\n", __func__); in mt9m001_init()
185 static int mt9m001_apply_selection(struct v4l2_subdev *sd) in mt9m001_apply_selection() argument
187 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_apply_selection()
190 /* Blanking and start values - default... */ in mt9m001_apply_selection()
197 { MT9M001_COLUMN_START, mt9m001->rect.left }, in mt9m001_apply_selection()
198 { MT9M001_ROW_START, mt9m001->rect.top }, in mt9m001_apply_selection()
199 { MT9M001_WINDOW_WIDTH, mt9m001->rect.width - 1 }, in mt9m001_apply_selection()
201 mt9m001->rect.height + mt9m001->y_skip_top - 1 }, in mt9m001_apply_selection()
207 static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) in mt9m001_s_stream() argument
209 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_s_stream()
213 mutex_lock(&mt9m001->mutex); in mt9m001_s_stream()
216 ret = pm_runtime_resume_and_get(&client->dev); in mt9m001_s_stream()
220 ret = mt9m001_apply_selection(sd); in mt9m001_s_stream()
224 ret = __v4l2_ctrl_handler_setup(&mt9m001->hdl); in mt9m001_s_stream()
235 pm_runtime_put(&client->dev); in mt9m001_s_stream()
238 mutex_unlock(&mt9m001->mutex); in mt9m001_s_stream()
243 pm_runtime_put(&client->dev); in mt9m001_s_stream()
245 mutex_unlock(&mt9m001->mutex); in mt9m001_s_stream()
250 static int mt9m001_set_selection(struct v4l2_subdev *sd, in mt9m001_set_selection() argument
254 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_set_selection()
256 struct v4l2_rect rect = sel->r; in mt9m001_set_selection()
258 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || in mt9m001_set_selection()
259 sel->target != V4L2_SEL_TGT_CROP) in mt9m001_set_selection()
260 return -EINVAL; in mt9m001_set_selection()
262 if (mt9m001->fmts == mt9m001_colour_fmts) in mt9m001_set_selection()
264 * Bayer format - even number of rows for simplicity, in mt9m001_set_selection()
276 MT9M001_COLUMN_SKIP + MT9M001_MAX_WIDTH - rect.width); in mt9m001_set_selection()
281 MT9M001_ROW_SKIP + MT9M001_MAX_HEIGHT - rect.height); in mt9m001_set_selection()
283 mt9m001->total_h = rect.height + mt9m001->y_skip_top + in mt9m001_set_selection()
286 mt9m001->rect = rect; in mt9m001_set_selection()
291 static int mt9m001_get_selection(struct v4l2_subdev *sd, in mt9m001_get_selection() argument
295 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_get_selection()
298 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) in mt9m001_get_selection()
299 return -EINVAL; in mt9m001_get_selection()
301 switch (sel->target) { in mt9m001_get_selection()
303 sel->r.left = MT9M001_COLUMN_SKIP; in mt9m001_get_selection()
304 sel->r.top = MT9M001_ROW_SKIP; in mt9m001_get_selection()
305 sel->r.width = MT9M001_MAX_WIDTH; in mt9m001_get_selection()
306 sel->r.height = MT9M001_MAX_HEIGHT; in mt9m001_get_selection()
309 sel->r = mt9m001->rect; in mt9m001_get_selection()
312 return -EINVAL; in mt9m001_get_selection()
316 static int mt9m001_get_fmt(struct v4l2_subdev *sd, in mt9m001_get_fmt() argument
320 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_get_fmt()
322 struct v4l2_mbus_framefmt *mf = &format->format; in mt9m001_get_fmt()
324 if (format->pad) in mt9m001_get_fmt()
325 return -EINVAL; in mt9m001_get_fmt()
327 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { in mt9m001_get_fmt()
329 format->format = *mf; in mt9m001_get_fmt()
333 mf->width = mt9m001->rect.width; in mt9m001_get_fmt()
334 mf->height = mt9m001->rect.height; in mt9m001_get_fmt()
335 mf->code = mt9m001->fmt->code; in mt9m001_get_fmt()
336 mf->colorspace = mt9m001->fmt->colorspace; in mt9m001_get_fmt()
337 mf->field = V4L2_FIELD_NONE; in mt9m001_get_fmt()
338 mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in mt9m001_get_fmt()
339 mf->quantization = V4L2_QUANTIZATION_DEFAULT; in mt9m001_get_fmt()
340 mf->xfer_func = V4L2_XFER_FUNC_DEFAULT; in mt9m001_get_fmt()
345 static int mt9m001_s_fmt(struct v4l2_subdev *sd, in mt9m001_s_fmt() argument
349 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_s_fmt()
354 .r.left = mt9m001->rect.left, in mt9m001_s_fmt()
355 .r.top = mt9m001->rect.top, in mt9m001_s_fmt()
356 .r.width = mf->width, in mt9m001_s_fmt()
357 .r.height = mf->height, in mt9m001_s_fmt()
362 ret = mt9m001_set_selection(sd, NULL, &sel); in mt9m001_s_fmt()
364 mf->width = mt9m001->rect.width; in mt9m001_s_fmt()
365 mf->height = mt9m001->rect.height; in mt9m001_s_fmt()
366 mt9m001->fmt = fmt; in mt9m001_s_fmt()
367 mf->colorspace = fmt->colorspace; in mt9m001_s_fmt()
373 static int mt9m001_set_fmt(struct v4l2_subdev *sd, in mt9m001_set_fmt() argument
377 struct v4l2_mbus_framefmt *mf = &format->format; in mt9m001_set_fmt()
378 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_set_fmt()
382 if (format->pad) in mt9m001_set_fmt()
383 return -EINVAL; in mt9m001_set_fmt()
385 v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH, in mt9m001_set_fmt()
387 &mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top, in mt9m001_set_fmt()
388 MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0); in mt9m001_set_fmt()
390 if (mt9m001->fmts == mt9m001_colour_fmts) in mt9m001_set_fmt()
391 mf->height = ALIGN(mf->height - 1, 2); in mt9m001_set_fmt()
393 fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts, in mt9m001_set_fmt()
394 mt9m001->num_fmts); in mt9m001_set_fmt()
396 fmt = mt9m001->fmt; in mt9m001_set_fmt()
397 mf->code = fmt->code; in mt9m001_set_fmt()
400 mf->colorspace = fmt->colorspace; in mt9m001_set_fmt()
401 mf->field = V4L2_FIELD_NONE; in mt9m001_set_fmt()
402 mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in mt9m001_set_fmt()
403 mf->quantization = V4L2_QUANTIZATION_DEFAULT; in mt9m001_set_fmt()
404 mf->xfer_func = V4L2_XFER_FUNC_DEFAULT; in mt9m001_set_fmt()
406 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) in mt9m001_set_fmt()
407 return mt9m001_s_fmt(sd, fmt, mf); in mt9m001_set_fmt()
413 static int mt9m001_g_register(struct v4l2_subdev *sd, in mt9m001_g_register() argument
416 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_g_register()
418 if (reg->reg > 0xff) in mt9m001_g_register()
419 return -EINVAL; in mt9m001_g_register()
421 reg->size = 2; in mt9m001_g_register()
422 reg->val = reg_read(client, reg->reg); in mt9m001_g_register()
424 if (reg->val > 0xffff) in mt9m001_g_register()
425 return -EIO; in mt9m001_g_register()
430 static int mt9m001_s_register(struct v4l2_subdev *sd, in mt9m001_s_register() argument
433 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_s_register()
435 if (reg->reg > 0xff) in mt9m001_s_register()
436 return -EINVAL; in mt9m001_s_register()
438 if (reg_write(client, reg->reg, reg->val) < 0) in mt9m001_s_register()
439 return -EIO; in mt9m001_s_register()
451 ret = clk_prepare_enable(mt9m001->clk); in mt9m001_power_on()
455 if (mt9m001->standby_gpio) { in mt9m001_power_on()
456 gpiod_set_value_cansleep(mt9m001->standby_gpio, 0); in mt9m001_power_on()
460 if (mt9m001->reset_gpio) { in mt9m001_power_on()
461 gpiod_set_value_cansleep(mt9m001->reset_gpio, 1); in mt9m001_power_on()
463 gpiod_set_value_cansleep(mt9m001->reset_gpio, 0); in mt9m001_power_on()
475 gpiod_set_value_cansleep(mt9m001->standby_gpio, 1); in mt9m001_power_off()
476 clk_disable_unprepare(mt9m001->clk); in mt9m001_power_off()
483 struct mt9m001 *mt9m001 = container_of(ctrl->handler, in mt9m001_g_volatile_ctrl()
487 switch (ctrl->id) { in mt9m001_g_volatile_ctrl()
489 min = mt9m001->exposure->minimum; in mt9m001_g_volatile_ctrl()
490 max = mt9m001->exposure->maximum; in mt9m001_g_volatile_ctrl()
491 mt9m001->exposure->val = in mt9m001_g_volatile_ctrl()
492 (524 + (mt9m001->total_h - 1) * (max - min)) / 1048 + min; in mt9m001_g_volatile_ctrl()
500 struct mt9m001 *mt9m001 = container_of(ctrl->handler, in mt9m001_s_ctrl()
502 struct v4l2_subdev *sd = &mt9m001->subdev; in mt9m001_s_ctrl() local
503 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_s_ctrl()
504 struct v4l2_ctrl *exp = mt9m001->exposure; in mt9m001_s_ctrl()
508 if (!pm_runtime_get_if_in_use(&client->dev)) in mt9m001_s_ctrl()
511 switch (ctrl->id) { in mt9m001_s_ctrl()
513 if (ctrl->val) in mt9m001_s_ctrl()
521 if (ctrl->val <= ctrl->default_value) { in mt9m001_s_ctrl()
523 unsigned long range = ctrl->default_value - ctrl->minimum; in mt9m001_s_ctrl()
524 data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range; in mt9m001_s_ctrl()
526 dev_dbg(&client->dev, "Setting gain %d\n", data); in mt9m001_s_ctrl()
530 /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ in mt9m001_s_ctrl()
531 unsigned long range = ctrl->maximum - ctrl->default_value - 1; in mt9m001_s_ctrl()
532 unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) * in mt9m001_s_ctrl()
538 data = ((gain - 32) * 16 + 16) / 32 + 80; in mt9m001_s_ctrl()
540 data = ((gain - 64) * 7 + 28) / 56 + 96; in mt9m001_s_ctrl()
542 dev_dbg(&client->dev, "Setting gain from %d to %d\n", in mt9m001_s_ctrl()
549 if (ctrl->val == V4L2_EXPOSURE_MANUAL) { in mt9m001_s_ctrl()
550 unsigned long range = exp->maximum - exp->minimum; in mt9m001_s_ctrl()
551 unsigned long shutter = ((exp->val - (s32)exp->minimum) * 1048 + in mt9m001_s_ctrl()
554 dev_dbg(&client->dev, in mt9m001_s_ctrl()
559 mt9m001->total_h = mt9m001->rect.height + in mt9m001_s_ctrl()
560 mt9m001->y_skip_top + MT9M001_DEFAULT_VBLANK; in mt9m001_s_ctrl()
562 mt9m001->total_h); in mt9m001_s_ctrl()
566 ret = -EINVAL; in mt9m001_s_ctrl()
570 pm_runtime_put(&client->dev); in mt9m001_s_ctrl()
577 * this wasn't our capture interface, so, we wait for the right one
587 dev_dbg(&client->dev, "write: %d\n", data); in mt9m001_video_probe()
596 mt9m001->fmts = mt9m001_colour_fmts; in mt9m001_video_probe()
597 mt9m001->num_fmts = ARRAY_SIZE(mt9m001_colour_fmts); in mt9m001_video_probe()
600 mt9m001->fmts = mt9m001_monochrome_fmts; in mt9m001_video_probe()
601 mt9m001->num_fmts = ARRAY_SIZE(mt9m001_monochrome_fmts); in mt9m001_video_probe()
604 dev_err(&client->dev, in mt9m001_video_probe()
606 ret = -ENODEV; in mt9m001_video_probe()
610 mt9m001->fmt = &mt9m001->fmts[0]; in mt9m001_video_probe()
612 dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, in mt9m001_video_probe()
617 dev_err(&client->dev, "Failed to initialise the camera\n"); in mt9m001_video_probe()
622 ret = v4l2_ctrl_handler_setup(&mt9m001->hdl); in mt9m001_video_probe()
628 static int mt9m001_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) in mt9m001_g_skip_top_lines() argument
630 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_g_skip_top_lines()
633 *lines = mt9m001->y_skip_top; in mt9m001_g_skip_top_lines()
653 static int mt9m001_init_state(struct v4l2_subdev *sd, in mt9m001_init_state() argument
656 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_init_state()
661 try_fmt->width = MT9M001_MAX_WIDTH; in mt9m001_init_state()
662 try_fmt->height = MT9M001_MAX_HEIGHT; in mt9m001_init_state()
663 try_fmt->code = mt9m001->fmts[0].code; in mt9m001_init_state()
664 try_fmt->colorspace = mt9m001->fmts[0].colorspace; in mt9m001_init_state()
665 try_fmt->field = V4L2_FIELD_NONE; in mt9m001_init_state()
666 try_fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in mt9m001_init_state()
667 try_fmt->quantization = V4L2_QUANTIZATION_DEFAULT; in mt9m001_init_state()
668 try_fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; in mt9m001_init_state()
673 static int mt9m001_enum_mbus_code(struct v4l2_subdev *sd, in mt9m001_enum_mbus_code() argument
677 struct i2c_client *client = v4l2_get_subdevdata(sd); in mt9m001_enum_mbus_code()
680 if (code->pad || code->index >= mt9m001->num_fmts) in mt9m001_enum_mbus_code()
681 return -EINVAL; in mt9m001_enum_mbus_code()
683 code->code = mt9m001->fmts[code->index].code; in mt9m001_enum_mbus_code()
687 static int mt9m001_get_mbus_config(struct v4l2_subdev *sd, in mt9m001_get_mbus_config() argument
692 cfg->type = V4L2_MBUS_PARALLEL; in mt9m001_get_mbus_config()
693 cfg->bus.parallel.flags = V4L2_MBUS_PCLK_SAMPLE_FALLING | in mt9m001_get_mbus_config()
733 struct i2c_adapter *adapter = client->adapter; in mt9m001_probe()
737 dev_warn(&adapter->dev, in mt9m001_probe()
738 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); in mt9m001_probe()
739 return -EIO; in mt9m001_probe()
742 mt9m001 = devm_kzalloc(&client->dev, sizeof(*mt9m001), GFP_KERNEL); in mt9m001_probe()
744 return -ENOMEM; in mt9m001_probe()
746 mt9m001->clk = devm_clk_get(&client->dev, NULL); in mt9m001_probe()
747 if (IS_ERR(mt9m001->clk)) in mt9m001_probe()
748 return PTR_ERR(mt9m001->clk); in mt9m001_probe()
750 mt9m001->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", in mt9m001_probe()
752 if (IS_ERR(mt9m001->standby_gpio)) in mt9m001_probe()
753 return PTR_ERR(mt9m001->standby_gpio); in mt9m001_probe()
755 mt9m001->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", in mt9m001_probe()
757 if (IS_ERR(mt9m001->reset_gpio)) in mt9m001_probe()
758 return PTR_ERR(mt9m001->reset_gpio); in mt9m001_probe()
760 v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops); in mt9m001_probe()
761 mt9m001->subdev.internal_ops = &mt9m001_internal_ops; in mt9m001_probe()
762 mt9m001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | in mt9m001_probe()
764 v4l2_ctrl_handler_init(&mt9m001->hdl, 4); in mt9m001_probe()
765 v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, in mt9m001_probe()
767 v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, in mt9m001_probe()
769 mt9m001->exposure = v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, in mt9m001_probe()
775 mt9m001->autoexposure = v4l2_ctrl_new_std_menu(&mt9m001->hdl, in mt9m001_probe()
778 mt9m001->subdev.ctrl_handler = &mt9m001->hdl; in mt9m001_probe()
779 if (mt9m001->hdl.error) in mt9m001_probe()
780 return mt9m001->hdl.error; in mt9m001_probe()
782 v4l2_ctrl_auto_cluster(2, &mt9m001->autoexposure, in mt9m001_probe()
785 mutex_init(&mt9m001->mutex); in mt9m001_probe()
786 mt9m001->hdl.lock = &mt9m001->mutex; in mt9m001_probe()
788 /* Second stage probe - when a capture adapter is there */ in mt9m001_probe()
789 mt9m001->y_skip_top = 0; in mt9m001_probe()
790 mt9m001->rect.left = MT9M001_COLUMN_SKIP; in mt9m001_probe()
791 mt9m001->rect.top = MT9M001_ROW_SKIP; in mt9m001_probe()
792 mt9m001->rect.width = MT9M001_MAX_WIDTH; in mt9m001_probe()
793 mt9m001->rect.height = MT9M001_MAX_HEIGHT; in mt9m001_probe()
795 ret = mt9m001_power_on(&client->dev); in mt9m001_probe()
799 pm_runtime_set_active(&client->dev); in mt9m001_probe()
800 pm_runtime_enable(&client->dev); in mt9m001_probe()
806 mt9m001->pad.flags = MEDIA_PAD_FL_SOURCE; in mt9m001_probe()
807 mt9m001->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; in mt9m001_probe()
808 ret = media_entity_pads_init(&mt9m001->subdev.entity, 1, &mt9m001->pad); in mt9m001_probe()
812 ret = v4l2_async_register_subdev(&mt9m001->subdev); in mt9m001_probe()
816 pm_runtime_idle(&client->dev); in mt9m001_probe()
821 media_entity_cleanup(&mt9m001->subdev.entity); in mt9m001_probe()
823 pm_runtime_disable(&client->dev); in mt9m001_probe()
824 pm_runtime_set_suspended(&client->dev); in mt9m001_probe()
825 mt9m001_power_off(&client->dev); in mt9m001_probe()
828 v4l2_ctrl_handler_free(&mt9m001->hdl); in mt9m001_probe()
829 mutex_destroy(&mt9m001->mutex); in mt9m001_probe()
842 pm_runtime_get_sync(&client->dev); in mt9m001_remove()
844 v4l2_async_unregister_subdev(&mt9m001->subdev); in mt9m001_remove()
845 media_entity_cleanup(&mt9m001->subdev.entity); in mt9m001_remove()
847 pm_runtime_disable(&client->dev); in mt9m001_remove()
848 pm_runtime_set_suspended(&client->dev); in mt9m001_remove()
849 pm_runtime_put_noidle(&client->dev); in mt9m001_remove()
850 mt9m001_power_off(&client->dev); in mt9m001_remove()
852 v4l2_ctrl_handler_free(&mt9m001->hdl); in mt9m001_remove()
853 mutex_destroy(&mt9m001->mutex); in mt9m001_remove()