Lines Matching +full:sel +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/clk.h>
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 */
99 struct clk *clk; member
181 dev_dbg(&client->dev, "%s\n", __func__); in mt9m001_init()
191 /* Blanking and start values - default... */ in mt9m001_apply_selection()
198 { MT9M001_COLUMN_START, mt9m001->rect.left }, in mt9m001_apply_selection()
199 { MT9M001_ROW_START, mt9m001->rect.top }, in mt9m001_apply_selection()
200 { MT9M001_WINDOW_WIDTH, mt9m001->rect.width - 1 }, in mt9m001_apply_selection()
202 mt9m001->rect.height + mt9m001->y_skip_top - 1 }, in mt9m001_apply_selection()
214 mutex_lock(&mt9m001->mutex); in mt9m001_s_stream()
216 if (mt9m001->streaming == enable) in mt9m001_s_stream()
220 ret = pm_runtime_resume_and_get(&client->dev); in mt9m001_s_stream()
228 ret = __v4l2_ctrl_handler_setup(&mt9m001->hdl); in mt9m001_s_stream()
239 pm_runtime_put(&client->dev); in mt9m001_s_stream()
242 mt9m001->streaming = enable; in mt9m001_s_stream()
244 mutex_unlock(&mt9m001->mutex); in mt9m001_s_stream()
249 pm_runtime_put(&client->dev); in mt9m001_s_stream()
251 mutex_unlock(&mt9m001->mutex); in mt9m001_s_stream()
258 struct v4l2_subdev_selection *sel) in mt9m001_set_selection() argument
262 struct v4l2_rect rect = sel->r; in mt9m001_set_selection()
264 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || in mt9m001_set_selection()
265 sel->target != V4L2_SEL_TGT_CROP) in mt9m001_set_selection()
266 return -EINVAL; in mt9m001_set_selection()
268 if (mt9m001->fmts == mt9m001_colour_fmts) in mt9m001_set_selection()
270 * Bayer format - even number of rows for simplicity, in mt9m001_set_selection()
282 MT9M001_COLUMN_SKIP + MT9M001_MAX_WIDTH - rect.width); in mt9m001_set_selection()
287 MT9M001_ROW_SKIP + MT9M001_MAX_HEIGHT - rect.height); in mt9m001_set_selection()
289 mt9m001->total_h = rect.height + mt9m001->y_skip_top + in mt9m001_set_selection()
292 mt9m001->rect = rect; in mt9m001_set_selection()
299 struct v4l2_subdev_selection *sel) in mt9m001_get_selection() argument
304 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) in mt9m001_get_selection()
305 return -EINVAL; in mt9m001_get_selection()
307 switch (sel->target) { in mt9m001_get_selection()
309 sel->r.left = MT9M001_COLUMN_SKIP; in mt9m001_get_selection()
310 sel->r.top = MT9M001_ROW_SKIP; in mt9m001_get_selection()
311 sel->r.width = MT9M001_MAX_WIDTH; in mt9m001_get_selection()
312 sel->r.height = MT9M001_MAX_HEIGHT; in mt9m001_get_selection()
315 sel->r = mt9m001->rect; in mt9m001_get_selection()
318 return -EINVAL; in mt9m001_get_selection()
328 struct v4l2_mbus_framefmt *mf = &format->format; in mt9m001_get_fmt()
330 if (format->pad) in mt9m001_get_fmt()
331 return -EINVAL; in mt9m001_get_fmt()
333 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { in mt9m001_get_fmt()
335 format->format = *mf; in mt9m001_get_fmt()
339 mf->width = mt9m001->rect.width; in mt9m001_get_fmt()
340 mf->height = mt9m001->rect.height; in mt9m001_get_fmt()
341 mf->code = mt9m001->fmt->code; in mt9m001_get_fmt()
342 mf->colorspace = mt9m001->fmt->colorspace; in mt9m001_get_fmt()
343 mf->field = V4L2_FIELD_NONE; in mt9m001_get_fmt()
344 mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in mt9m001_get_fmt()
345 mf->quantization = V4L2_QUANTIZATION_DEFAULT; in mt9m001_get_fmt()
346 mf->xfer_func = V4L2_XFER_FUNC_DEFAULT; in mt9m001_get_fmt()
357 struct v4l2_subdev_selection sel = { in mt9m001_s_fmt() local
360 .r.left = mt9m001->rect.left, in mt9m001_s_fmt()
361 .r.top = mt9m001->rect.top, in mt9m001_s_fmt()
362 .r.width = mf->width, in mt9m001_s_fmt()
363 .r.height = mf->height, in mt9m001_s_fmt()
368 ret = mt9m001_set_selection(sd, NULL, &sel); in mt9m001_s_fmt()
370 mf->width = mt9m001->rect.width; in mt9m001_s_fmt()
371 mf->height = mt9m001->rect.height; in mt9m001_s_fmt()
372 mt9m001->fmt = fmt; in mt9m001_s_fmt()
373 mf->colorspace = fmt->colorspace; in mt9m001_s_fmt()
383 struct v4l2_mbus_framefmt *mf = &format->format; in mt9m001_set_fmt()
388 if (format->pad) in mt9m001_set_fmt()
389 return -EINVAL; in mt9m001_set_fmt()
391 v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH, in mt9m001_set_fmt()
393 &mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top, in mt9m001_set_fmt()
394 MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0); in mt9m001_set_fmt()
396 if (mt9m001->fmts == mt9m001_colour_fmts) in mt9m001_set_fmt()
397 mf->height = ALIGN(mf->height - 1, 2); in mt9m001_set_fmt()
399 fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts, in mt9m001_set_fmt()
400 mt9m001->num_fmts); in mt9m001_set_fmt()
402 fmt = mt9m001->fmt; in mt9m001_set_fmt()
403 mf->code = fmt->code; in mt9m001_set_fmt()
406 mf->colorspace = fmt->colorspace; in mt9m001_set_fmt()
407 mf->field = V4L2_FIELD_NONE; in mt9m001_set_fmt()
408 mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in mt9m001_set_fmt()
409 mf->quantization = V4L2_QUANTIZATION_DEFAULT; in mt9m001_set_fmt()
410 mf->xfer_func = V4L2_XFER_FUNC_DEFAULT; in mt9m001_set_fmt()
412 if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) in mt9m001_set_fmt()
414 sd_state->pads->try_fmt = *mf; in mt9m001_set_fmt()
424 if (reg->reg > 0xff) in mt9m001_g_register()
425 return -EINVAL; in mt9m001_g_register()
427 reg->size = 2; in mt9m001_g_register()
428 reg->val = reg_read(client, reg->reg); in mt9m001_g_register()
430 if (reg->val > 0xffff) in mt9m001_g_register()
431 return -EIO; in mt9m001_g_register()
441 if (reg->reg > 0xff) in mt9m001_s_register()
442 return -EINVAL; in mt9m001_s_register()
444 if (reg_write(client, reg->reg, reg->val) < 0) in mt9m001_s_register()
445 return -EIO; in mt9m001_s_register()
457 ret = clk_prepare_enable(mt9m001->clk); in mt9m001_power_on()
461 if (mt9m001->standby_gpio) { in mt9m001_power_on()
462 gpiod_set_value_cansleep(mt9m001->standby_gpio, 0); in mt9m001_power_on()
466 if (mt9m001->reset_gpio) { in mt9m001_power_on()
467 gpiod_set_value_cansleep(mt9m001->reset_gpio, 1); in mt9m001_power_on()
469 gpiod_set_value_cansleep(mt9m001->reset_gpio, 0); in mt9m001_power_on()
481 gpiod_set_value_cansleep(mt9m001->standby_gpio, 1); in mt9m001_power_off()
482 clk_disable_unprepare(mt9m001->clk); in mt9m001_power_off()
489 struct mt9m001 *mt9m001 = container_of(ctrl->handler, in mt9m001_g_volatile_ctrl()
493 switch (ctrl->id) { in mt9m001_g_volatile_ctrl()
495 min = mt9m001->exposure->minimum; in mt9m001_g_volatile_ctrl()
496 max = mt9m001->exposure->maximum; in mt9m001_g_volatile_ctrl()
497 mt9m001->exposure->val = in mt9m001_g_volatile_ctrl()
498 (524 + (mt9m001->total_h - 1) * (max - min)) / 1048 + min; in mt9m001_g_volatile_ctrl()
506 struct mt9m001 *mt9m001 = container_of(ctrl->handler, in mt9m001_s_ctrl()
508 struct v4l2_subdev *sd = &mt9m001->subdev; in mt9m001_s_ctrl()
510 struct v4l2_ctrl *exp = mt9m001->exposure; in mt9m001_s_ctrl()
514 if (!pm_runtime_get_if_in_use(&client->dev)) in mt9m001_s_ctrl()
517 switch (ctrl->id) { in mt9m001_s_ctrl()
519 if (ctrl->val) in mt9m001_s_ctrl()
527 if (ctrl->val <= ctrl->default_value) { in mt9m001_s_ctrl()
529 unsigned long range = ctrl->default_value - ctrl->minimum; in mt9m001_s_ctrl()
530 data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range; in mt9m001_s_ctrl()
532 dev_dbg(&client->dev, "Setting gain %d\n", data); in mt9m001_s_ctrl()
536 /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ in mt9m001_s_ctrl()
537 unsigned long range = ctrl->maximum - ctrl->default_value - 1; in mt9m001_s_ctrl()
538 unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) * in mt9m001_s_ctrl()
544 data = ((gain - 32) * 16 + 16) / 32 + 80; in mt9m001_s_ctrl()
546 data = ((gain - 64) * 7 + 28) / 56 + 96; in mt9m001_s_ctrl()
548 dev_dbg(&client->dev, "Setting gain from %d to %d\n", in mt9m001_s_ctrl()
555 if (ctrl->val == V4L2_EXPOSURE_MANUAL) { in mt9m001_s_ctrl()
556 unsigned long range = exp->maximum - exp->minimum; in mt9m001_s_ctrl()
557 unsigned long shutter = ((exp->val - (s32)exp->minimum) * 1048 + in mt9m001_s_ctrl()
560 dev_dbg(&client->dev, in mt9m001_s_ctrl()
565 mt9m001->total_h = mt9m001->rect.height + in mt9m001_s_ctrl()
566 mt9m001->y_skip_top + MT9M001_DEFAULT_VBLANK; in mt9m001_s_ctrl()
568 mt9m001->total_h); in mt9m001_s_ctrl()
572 ret = -EINVAL; in mt9m001_s_ctrl()
576 pm_runtime_put(&client->dev); in mt9m001_s_ctrl()
593 dev_dbg(&client->dev, "write: %d\n", data); in mt9m001_video_probe()
602 mt9m001->fmts = mt9m001_colour_fmts; in mt9m001_video_probe()
603 mt9m001->num_fmts = ARRAY_SIZE(mt9m001_colour_fmts); in mt9m001_video_probe()
606 mt9m001->fmts = mt9m001_monochrome_fmts; in mt9m001_video_probe()
607 mt9m001->num_fmts = ARRAY_SIZE(mt9m001_monochrome_fmts); in mt9m001_video_probe()
610 dev_err(&client->dev, in mt9m001_video_probe()
612 ret = -ENODEV; in mt9m001_video_probe()
616 mt9m001->fmt = &mt9m001->fmts[0]; in mt9m001_video_probe()
618 dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, in mt9m001_video_probe()
623 dev_err(&client->dev, "Failed to initialise the camera\n"); in mt9m001_video_probe()
628 ret = v4l2_ctrl_handler_setup(&mt9m001->hdl); in mt9m001_video_probe()
639 *lines = mt9m001->y_skip_top; in mt9m001_g_skip_top_lines()
667 try_fmt->width = MT9M001_MAX_WIDTH; in mt9m001_init_cfg()
668 try_fmt->height = MT9M001_MAX_HEIGHT; in mt9m001_init_cfg()
669 try_fmt->code = mt9m001->fmts[0].code; in mt9m001_init_cfg()
670 try_fmt->colorspace = mt9m001->fmts[0].colorspace; in mt9m001_init_cfg()
671 try_fmt->field = V4L2_FIELD_NONE; in mt9m001_init_cfg()
672 try_fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in mt9m001_init_cfg()
673 try_fmt->quantization = V4L2_QUANTIZATION_DEFAULT; in mt9m001_init_cfg()
674 try_fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; in mt9m001_init_cfg()
686 if (code->pad || code->index >= mt9m001->num_fmts) in mt9m001_enum_mbus_code()
687 return -EINVAL; in mt9m001_enum_mbus_code()
689 code->code = mt9m001->fmts[code->index].code; in mt9m001_enum_mbus_code()
698 cfg->type = V4L2_MBUS_PARALLEL; in mt9m001_get_mbus_config()
699 cfg->bus.parallel.flags = V4L2_MBUS_PCLK_SAMPLE_FALLING | in mt9m001_get_mbus_config()
736 struct i2c_adapter *adapter = client->adapter; in mt9m001_probe()
740 dev_warn(&adapter->dev, in mt9m001_probe()
741 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); in mt9m001_probe()
742 return -EIO; in mt9m001_probe()
745 mt9m001 = devm_kzalloc(&client->dev, sizeof(*mt9m001), GFP_KERNEL); in mt9m001_probe()
747 return -ENOMEM; in mt9m001_probe()
749 mt9m001->clk = devm_clk_get(&client->dev, NULL); in mt9m001_probe()
750 if (IS_ERR(mt9m001->clk)) in mt9m001_probe()
751 return PTR_ERR(mt9m001->clk); in mt9m001_probe()
753 mt9m001->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", in mt9m001_probe()
755 if (IS_ERR(mt9m001->standby_gpio)) in mt9m001_probe()
756 return PTR_ERR(mt9m001->standby_gpio); in mt9m001_probe()
758 mt9m001->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", in mt9m001_probe()
760 if (IS_ERR(mt9m001->reset_gpio)) in mt9m001_probe()
761 return PTR_ERR(mt9m001->reset_gpio); in mt9m001_probe()
763 v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops); in mt9m001_probe()
764 mt9m001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | in mt9m001_probe()
766 v4l2_ctrl_handler_init(&mt9m001->hdl, 4); in mt9m001_probe()
767 v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, in mt9m001_probe()
769 v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, in mt9m001_probe()
771 mt9m001->exposure = v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, in mt9m001_probe()
777 mt9m001->autoexposure = v4l2_ctrl_new_std_menu(&mt9m001->hdl, in mt9m001_probe()
780 mt9m001->subdev.ctrl_handler = &mt9m001->hdl; in mt9m001_probe()
781 if (mt9m001->hdl.error) in mt9m001_probe()
782 return mt9m001->hdl.error; in mt9m001_probe()
784 v4l2_ctrl_auto_cluster(2, &mt9m001->autoexposure, in mt9m001_probe()
787 mutex_init(&mt9m001->mutex); in mt9m001_probe()
788 mt9m001->hdl.lock = &mt9m001->mutex; in mt9m001_probe()
790 /* Second stage probe - when a capture adapter is there */ in mt9m001_probe()
791 mt9m001->y_skip_top = 0; in mt9m001_probe()
792 mt9m001->rect.left = MT9M001_COLUMN_SKIP; in mt9m001_probe()
793 mt9m001->rect.top = MT9M001_ROW_SKIP; in mt9m001_probe()
794 mt9m001->rect.width = MT9M001_MAX_WIDTH; in mt9m001_probe()
795 mt9m001->rect.height = MT9M001_MAX_HEIGHT; in mt9m001_probe()
797 ret = mt9m001_power_on(&client->dev); in mt9m001_probe()
801 pm_runtime_set_active(&client->dev); in mt9m001_probe()
802 pm_runtime_enable(&client->dev); in mt9m001_probe()
808 mt9m001->pad.flags = MEDIA_PAD_FL_SOURCE; in mt9m001_probe()
809 mt9m001->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; in mt9m001_probe()
810 ret = media_entity_pads_init(&mt9m001->subdev.entity, 1, &mt9m001->pad); in mt9m001_probe()
814 ret = v4l2_async_register_subdev(&mt9m001->subdev); in mt9m001_probe()
818 pm_runtime_idle(&client->dev); in mt9m001_probe()
823 media_entity_cleanup(&mt9m001->subdev.entity); in mt9m001_probe()
825 pm_runtime_disable(&client->dev); in mt9m001_probe()
826 pm_runtime_set_suspended(&client->dev); in mt9m001_probe()
827 mt9m001_power_off(&client->dev); in mt9m001_probe()
830 v4l2_ctrl_handler_free(&mt9m001->hdl); in mt9m001_probe()
831 mutex_destroy(&mt9m001->mutex); in mt9m001_probe()
844 pm_runtime_get_sync(&client->dev); in mt9m001_remove()
846 v4l2_async_unregister_subdev(&mt9m001->subdev); in mt9m001_remove()
847 media_entity_cleanup(&mt9m001->subdev.entity); in mt9m001_remove()
849 pm_runtime_disable(&client->dev); in mt9m001_remove()
850 pm_runtime_set_suspended(&client->dev); in mt9m001_remove()
851 pm_runtime_put_noidle(&client->dev); in mt9m001_remove()
852 mt9m001_power_off(&client->dev); in mt9m001_remove()
854 v4l2_ctrl_handler_free(&mt9m001->hdl); in mt9m001_remove()
855 mutex_destroy(&mt9m001->mutex); in mt9m001_remove()