1 From a327bf2a6c7a4d9d1025f4fc6b350e0d7385f753 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Fri, 25 Feb 2022 18:16:13 +0000
4 Subject: [PATCH] media/i2c: Add driver for Omnivision OV2311
6 Omnivision OV2311 is a CSI2 1600x1300 global shutter image sensor.
9 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
11 drivers/media/i2c/Kconfig | 11 +
12 drivers/media/i2c/Makefile | 1 +
13 drivers/media/i2c/ov2311.c | 1181 ++++++++++++++++++++++++++++++++++++
14 3 files changed, 1193 insertions(+)
15 create mode 100644 drivers/media/i2c/ov2311.c
17 --- a/drivers/media/i2c/Kconfig
18 +++ b/drivers/media/i2c/Kconfig
19 @@ -918,6 +918,17 @@ config VIDEO_OV02A10
20 To compile this driver as a module, choose M here: the
21 module will be called ov02a10.
24 + tristate "OmniVision OV2311 sensor support"
25 + depends on I2C && VIDEO_V4L2
26 + depends on MEDIA_CAMERA_SUPPORT
28 + This is a Video4Linux2 sensor-level driver for the OmniVision
31 + To compile this driver as a module, choose M here: the
32 + module will be called ov2311.
35 tristate "OmniVision OV2640 sensor support"
36 depends on VIDEO_V4L2 && I2C
37 --- a/drivers/media/i2c/Makefile
38 +++ b/drivers/media/i2c/Makefile
39 @@ -65,6 +65,7 @@ obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony
40 obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
41 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
42 obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o
43 +obj-$(CONFIG_VIDEO_OV2311) += ov2311.o
44 obj-$(CONFIG_VIDEO_OV2640) += ov2640.o
45 obj-$(CONFIG_VIDEO_OV2680) += ov2680.o
46 obj-$(CONFIG_VIDEO_OV2685) += ov2685.o
48 +++ b/drivers/media/i2c/ov2311.c
50 +// SPDX-License-Identifier: GPL-2.0
52 + * Omnivision OV2311 1600x1300 global shutter image sensor driver
53 + * Copyright (C) 2022, Raspberry Pi (Trading) Ltd
55 + * This driver is based on the OV9281 driver.
56 + * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
57 + * Register configuration from
58 + * https://github.com/ArduCAM/ArduCAM_USB_Camera_Shield/tree/master/Config/USB3.0_UC-425_Rev.C%2BUC-628_Rev.B/OV2311
59 + * with additional exposure and gain register information from
60 + * https://github.com/renesas-rcar/linux-bsp/tree/0cf6e36f5bf49e1c2aab87139ec5b588623c56f8/drivers/media/i2c/imagers
63 +#include <linux/clk.h>
64 +#include <linux/device.h>
65 +#include <linux/delay.h>
66 +#include <linux/gpio/consumer.h>
67 +#include <linux/i2c.h>
68 +#include <linux/module.h>
69 +#include <linux/pm_runtime.h>
70 +#include <linux/regulator/consumer.h>
71 +#include <media/media-entity.h>
72 +#include <media/v4l2-async.h>
73 +#include <media/v4l2-ctrls.h>
74 +#include <media/v4l2-event.h>
75 +#include <media/v4l2-fwnode.h>
76 +#include <media/v4l2-subdev.h>
78 +#define OV2311_LINK_FREQ 400000000
79 +#define OV2311_LANES 2
81 +/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
82 +#define OV2311_PIXEL_RATE_10BIT (OV2311_LINK_FREQ * 2 * \
84 +#define OV2311_PIXEL_RATE_8BIT (OV2311_LINK_FREQ * 2 * \
86 +#define OV2311_XVCLK_FREQ 24000000
88 +#define CHIP_ID 0x2311
89 +#define OV2311_REG_CHIP_ID 0x300a
91 +#define OV2311_REG_CTRL_MODE 0x0100
92 +#define OV2311_MODE_SW_STANDBY 0x0
93 +#define OV2311_MODE_STREAMING BIT(0)
95 +#define OV2311_REG_V_FLIP 0x3820
96 +#define OV2311_REG_H_FLIP 0x3821
97 +#define OV2311_FLIP_BIT BIT(2)
99 +#define OV2311_REG_EXPOSURE 0x3501
100 +#define OV2311_EXPOSURE_MIN 4
101 +#define OV2311_EXPOSURE_STEP 1
102 +#define OV2311_VTS_MAX 0xffff
104 +#define OV2311_REG_GAIN_H 0x3508
105 +#define OV2311_REG_GAIN_L 0x3509
106 +#define OV2311_GAIN_H_MASK 0x07
107 +#define OV2311_GAIN_H_SHIFT 8
108 +#define OV2311_GAIN_L_MASK 0xff
109 +#define OV2311_GAIN_MIN 0x100
110 +#define OV2311_GAIN_MAX 0x780
111 +#define OV2311_GAIN_STEP 1
112 +#define OV2311_GAIN_DEFAULT OV2311_GAIN_MIN
114 +#define OV2311_REG_TEST_PATTERN 0x5e00
115 +#define OV2311_TEST_PATTERN_ENABLE 0x80
116 +#define OV2311_TEST_PATTERN_DISABLE 0x0
118 +#define OV2311_REG_VTS 0x380e
121 + * OV2311 native and active pixel array size.
122 + * Datasheet not available to confirm these values. renesas-rcar linux-bsp tree
123 + * has these values.
125 +#define OV2311_NATIVE_WIDTH 1616U
126 +#define OV2311_NATIVE_HEIGHT 1316U
127 +#define OV2311_PIXEL_ARRAY_LEFT 8U
128 +#define OV2311_PIXEL_ARRAY_TOP 8U
129 +#define OV2311_PIXEL_ARRAY_WIDTH 1600U
130 +#define OV2311_PIXEL_ARRAY_HEIGHT 1300U
132 +#define REG_NULL 0xFFFF
134 +#define OV2311_REG_VALUE_08BIT 1
135 +#define OV2311_REG_VALUE_16BIT 2
136 +#define OV2311_REG_VALUE_24BIT 3
138 +#define OV2311_NAME "ov2311"
140 +static const char * const ov2311_supply_names[] = {
141 + "avdd", /* Analog power */
142 + "dovdd", /* Digital I/O power */
143 + "dvdd", /* Digital core power */
146 +#define OV2311_NUM_SUPPLIES ARRAY_SIZE(ov2311_supply_names)
153 +struct ov2311_mode {
159 + struct v4l2_rect crop;
160 + const struct regval *reg_list;
164 + struct i2c_client *client;
166 + struct gpio_desc *reset_gpio;
167 + struct gpio_desc *pwdn_gpio;
168 + struct regulator_bulk_data supplies[OV2311_NUM_SUPPLIES];
170 + struct v4l2_subdev subdev;
171 + struct media_pad pad;
172 + struct v4l2_ctrl_handler ctrl_handler;
173 + struct v4l2_ctrl *exposure;
174 + struct v4l2_ctrl *hblank;
175 + struct v4l2_ctrl *vblank;
176 + struct v4l2_ctrl *pixel_rate;
178 + * Mutex for serialized access:
179 + * Protect sensor module set pad format and start/stop streaming safely.
181 + struct mutex mutex;
183 + /* Streaming on/off */
186 + const struct ov2311_mode *cur_mode;
190 +#define to_ov2311(sd) container_of(sd, struct ov2311, subdev)
194 + * max_framerate 60fps for 10 bit, 74.6fps for 8 bit.
196 +static const struct regval ov2311_common_regs[] = {
336 +static const struct regval ov2311_1600x1300_regs[] = {
350 +static const struct regval ov2311_1600x1080_regs[] = {
370 +static const struct regval op_10bit[] = {
376 +static const struct regval op_8bit[] = {
382 +static const struct ov2311_mode supported_modes[] = {
387 + .hts_def = (0x0388 * 2),/* Registers 0x380c / 0x380d * 2 */
388 + .vts_def = 0x5c2, /* Registers 0x380e / 0x380f
392 + .left = OV2311_PIXEL_ARRAY_LEFT,
393 + .top = OV2311_PIXEL_ARRAY_TOP,
397 + .reg_list = ov2311_1600x1300_regs,
403 + .hts_def = (0x0388 * 2),/* Registers 0x380c / 0x380d * 2 */
404 + .vts_def = 0x5c2, /* Registers 0x380e / 0x380f
408 + .left = OV2311_PIXEL_ARRAY_LEFT,
409 + .top = 110 + OV2311_PIXEL_ARRAY_TOP,
413 + .reg_list = ov2311_1600x1080_regs,
417 +static const s64 link_freq_menu_items[] = {
421 +static const char * const ov2311_test_pattern_menu[] = {
423 + "Vertical Color Bar Type 1",
424 + "Vertical Color Bar Type 2",
425 + "Vertical Color Bar Type 3",
426 + "Vertical Color Bar Type 4"
429 +/* Write registers up to 4 at a time */
430 +static int ov2311_write_reg(struct i2c_client *client, u16 reg,
442 + buf[1] = reg & 0xff;
444 + val_be = cpu_to_be32(val);
445 + val_p = (u8 *)&val_be;
450 + buf[buf_i++] = val_p[val_i++];
452 + if (i2c_master_send(client, buf, len + 2) != len + 2)
458 +static int ov2311_write_array(struct i2c_client *client,
459 + const struct regval *regs)
464 + for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
465 + ret = ov2311_write_reg(client, regs[i].addr,
466 + OV2311_REG_VALUE_08BIT, regs[i].val);
471 +/* Read registers up to 4 at a time */
472 +static int ov2311_read_reg(struct i2c_client *client, u16 reg, unsigned int len,
475 + struct i2c_msg msgs[2];
477 + __be32 data_be = 0;
478 + __be16 reg_addr_be = cpu_to_be16(reg);
481 + if (len > 4 || !len)
484 + data_be_p = (u8 *)&data_be;
485 + /* Write register address */
486 + msgs[0].addr = client->addr;
489 + msgs[0].buf = (u8 *)®_addr_be;
491 + /* Read data from register */
492 + msgs[1].addr = client->addr;
493 + msgs[1].flags = I2C_M_RD;
495 + msgs[1].buf = &data_be_p[4 - len];
497 + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
498 + if (ret != ARRAY_SIZE(msgs))
501 + *val = be32_to_cpu(data_be);
506 +static int ov2311_set_fmt(struct v4l2_subdev *sd,
507 + struct v4l2_subdev_state *sd_state,
508 + struct v4l2_subdev_format *fmt)
510 + struct ov2311 *ov2311 = to_ov2311(sd);
511 + const struct ov2311_mode *mode;
512 + s64 h_blank, vblank_def, pixel_rate;
514 + mutex_lock(&ov2311->mutex);
516 + mode = v4l2_find_nearest_size(supported_modes,
517 + ARRAY_SIZE(supported_modes),
520 + fmt->format.height);
521 + if (fmt->format.code != MEDIA_BUS_FMT_Y8_1X8)
522 + fmt->format.code = MEDIA_BUS_FMT_Y10_1X10;
523 + fmt->format.width = mode->width;
524 + fmt->format.height = mode->height;
525 + fmt->format.field = V4L2_FIELD_NONE;
526 + fmt->format.colorspace = V4L2_COLORSPACE_RAW;
527 + fmt->format.ycbcr_enc =
528 + V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace);
529 + fmt->format.quantization =
530 + V4L2_MAP_QUANTIZATION_DEFAULT(true, fmt->format.colorspace,
531 + fmt->format.ycbcr_enc);
532 + fmt->format.xfer_func =
533 + V4L2_MAP_XFER_FUNC_DEFAULT(fmt->format.colorspace);
535 + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
536 + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) =
539 + ov2311->cur_mode = mode;
540 + ov2311->code = fmt->format.code;
541 + h_blank = mode->hts_def - mode->width;
542 + __v4l2_ctrl_modify_range(ov2311->hblank, h_blank,
543 + h_blank, 1, h_blank);
544 + __v4l2_ctrl_s_ctrl(ov2311->hblank, h_blank);
545 + vblank_def = mode->vts_def - mode->height;
546 + __v4l2_ctrl_modify_range(ov2311->vblank, vblank_def,
547 + OV2311_VTS_MAX - mode->height,
549 + __v4l2_ctrl_s_ctrl(ov2311->vblank, vblank_def);
551 + pixel_rate = (fmt->format.code == MEDIA_BUS_FMT_Y10_1X10) ?
552 + OV2311_PIXEL_RATE_10BIT : OV2311_PIXEL_RATE_8BIT;
553 + __v4l2_ctrl_modify_range(ov2311->pixel_rate, pixel_rate,
554 + pixel_rate, 1, pixel_rate);
557 + mutex_unlock(&ov2311->mutex);
562 +static int ov2311_get_fmt(struct v4l2_subdev *sd,
563 + struct v4l2_subdev_state *sd_state,
564 + struct v4l2_subdev_format *fmt)
566 + struct ov2311 *ov2311 = to_ov2311(sd);
567 + const struct ov2311_mode *mode = ov2311->cur_mode;
569 + mutex_lock(&ov2311->mutex);
570 + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
571 + fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
573 + fmt->format.width = mode->width;
574 + fmt->format.height = mode->height;
575 + fmt->format.code = ov2311->code;
576 + fmt->format.field = V4L2_FIELD_NONE;
577 + fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
578 + fmt->format.ycbcr_enc =
579 + V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->format.colorspace);
580 + fmt->format.quantization =
581 + V4L2_MAP_QUANTIZATION_DEFAULT(true,
582 + fmt->format.colorspace,
583 + fmt->format.ycbcr_enc);
584 + fmt->format.xfer_func =
585 + V4L2_MAP_XFER_FUNC_DEFAULT(fmt->format.colorspace);
587 + mutex_unlock(&ov2311->mutex);
592 +static int ov2311_enum_mbus_code(struct v4l2_subdev *sd,
593 + struct v4l2_subdev_state *sd_state,
594 + struct v4l2_subdev_mbus_code_enum *code)
596 + switch (code->index) {
600 + code->code = MEDIA_BUS_FMT_Y10_1X10;
603 + code->code = MEDIA_BUS_FMT_Y8_1X8;
610 +static int ov2311_enum_frame_sizes(struct v4l2_subdev *sd,
611 + struct v4l2_subdev_state *sd_state,
612 + struct v4l2_subdev_frame_size_enum *fse)
614 + if (fse->index >= ARRAY_SIZE(supported_modes))
617 + if (fse->code != MEDIA_BUS_FMT_Y10_1X10 &&
618 + fse->code != MEDIA_BUS_FMT_Y8_1X8)
621 + fse->min_width = supported_modes[fse->index].width;
622 + fse->max_width = supported_modes[fse->index].width;
623 + fse->max_height = supported_modes[fse->index].height;
624 + fse->min_height = supported_modes[fse->index].height;
629 +static int ov2311_enable_test_pattern(struct ov2311 *ov2311, u32 pattern)
634 + val = (pattern - 1) | OV2311_TEST_PATTERN_ENABLE;
636 + val = OV2311_TEST_PATTERN_DISABLE;
638 + return ov2311_write_reg(ov2311->client, OV2311_REG_TEST_PATTERN,
639 + OV2311_REG_VALUE_08BIT, val);
642 +static const struct v4l2_rect *
643 +__ov2311_get_pad_crop(struct ov2311 *ov2311, struct v4l2_subdev_state *sd_state,
644 + unsigned int pad, enum v4l2_subdev_format_whence which)
647 + case V4L2_SUBDEV_FORMAT_TRY:
648 + return v4l2_subdev_get_try_crop(&ov2311->subdev, sd_state, pad);
649 + case V4L2_SUBDEV_FORMAT_ACTIVE:
650 + return &ov2311->cur_mode->crop;
656 +static int ov2311_get_selection(struct v4l2_subdev *sd,
657 + struct v4l2_subdev_state *sd_state,
658 + struct v4l2_subdev_selection *sel)
660 + switch (sel->target) {
661 + case V4L2_SEL_TGT_CROP: {
662 + struct ov2311 *ov2311 = to_ov2311(sd);
664 + mutex_lock(&ov2311->mutex);
665 + sel->r = *__ov2311_get_pad_crop(ov2311, sd_state, sel->pad,
667 + mutex_unlock(&ov2311->mutex);
672 + case V4L2_SEL_TGT_NATIVE_SIZE:
675 + sel->r.width = OV2311_NATIVE_WIDTH;
676 + sel->r.height = OV2311_NATIVE_HEIGHT;
680 + case V4L2_SEL_TGT_CROP_DEFAULT:
681 + case V4L2_SEL_TGT_CROP_BOUNDS:
682 + sel->r.top = OV2311_PIXEL_ARRAY_TOP;
683 + sel->r.left = OV2311_PIXEL_ARRAY_LEFT;
684 + sel->r.width = OV2311_PIXEL_ARRAY_WIDTH;
685 + sel->r.height = OV2311_PIXEL_ARRAY_HEIGHT;
693 +static int ov2311_start_stream(struct ov2311 *ov2311)
697 + ret = ov2311_write_array(ov2311->client, ov2311_common_regs);
701 + ret = ov2311_write_array(ov2311->client, ov2311->cur_mode->reg_list);
705 + if (ov2311->code == MEDIA_BUS_FMT_Y10_1X10)
706 + ret = ov2311_write_array(ov2311->client, op_10bit);
708 + ret = ov2311_write_array(ov2311->client, op_8bit);
712 + /* In case these controls are set before streaming */
713 + mutex_unlock(&ov2311->mutex);
714 + ret = v4l2_ctrl_handler_setup(&ov2311->ctrl_handler);
715 + mutex_lock(&ov2311->mutex);
719 + return ov2311_write_reg(ov2311->client, OV2311_REG_CTRL_MODE,
720 + OV2311_REG_VALUE_08BIT, OV2311_MODE_STREAMING);
723 +static int ov2311_stop_stream(struct ov2311 *ov2311)
725 + return ov2311_write_reg(ov2311->client, OV2311_REG_CTRL_MODE,
726 + OV2311_REG_VALUE_08BIT, OV2311_MODE_SW_STANDBY);
729 +static int ov2311_s_stream(struct v4l2_subdev *sd, int enable)
731 + struct ov2311 *ov2311 = to_ov2311(sd);
732 + struct i2c_client *client = ov2311->client;
735 + mutex_lock(&ov2311->mutex);
736 + if (ov2311->streaming == enable) {
737 + mutex_unlock(&ov2311->mutex);
742 + ret = pm_runtime_resume_and_get(&client->dev);
744 + goto unlock_and_return;
746 + ret = ov2311_start_stream(ov2311);
748 + v4l2_err(sd, "start stream failed while write regs\n");
749 + pm_runtime_put(&client->dev);
750 + goto unlock_and_return;
753 + ov2311_stop_stream(ov2311);
754 + pm_runtime_put(&client->dev);
757 + ov2311->streaming = enable;
760 + mutex_unlock(&ov2311->mutex);
765 +static int ov2311_power_on(struct device *dev)
767 + struct v4l2_subdev *sd = dev_get_drvdata(dev);
768 + struct ov2311 *ov2311 = to_ov2311(sd);
771 + ret = clk_set_rate(ov2311->xvclk, OV2311_XVCLK_FREQ);
773 + dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
774 + if (clk_get_rate(ov2311->xvclk) != OV2311_XVCLK_FREQ)
775 + dev_warn(dev, "xvclk mismatched, modes are based on 24MHz - rate is %lu\n",
776 + clk_get_rate(ov2311->xvclk));
778 + ret = clk_prepare_enable(ov2311->xvclk);
780 + dev_err(dev, "Failed to enable xvclk\n");
784 + gpiod_set_value_cansleep(ov2311->reset_gpio, 0);
786 + ret = regulator_bulk_enable(OV2311_NUM_SUPPLIES, ov2311->supplies);
788 + dev_err(dev, "Failed to enable regulators\n");
792 + gpiod_set_value_cansleep(ov2311->reset_gpio, 1);
794 + usleep_range(500, 1000);
795 + gpiod_set_value_cansleep(ov2311->pwdn_gpio, 1);
797 + usleep_range(1000, 2000);
802 + clk_disable_unprepare(ov2311->xvclk);
807 +static int ov2311_power_off(struct device *dev)
809 + struct v4l2_subdev *sd = dev_get_drvdata(dev);
810 + struct ov2311 *ov2311 = to_ov2311(sd);
812 + gpiod_set_value_cansleep(ov2311->pwdn_gpio, 0);
813 + clk_disable_unprepare(ov2311->xvclk);
814 + gpiod_set_value_cansleep(ov2311->reset_gpio, 0);
815 + regulator_bulk_disable(OV2311_NUM_SUPPLIES, ov2311->supplies);
820 +static int ov2311_runtime_resume(struct device *dev)
822 + struct v4l2_subdev *sd = dev_get_drvdata(dev);
823 + struct ov2311 *ov2311 = to_ov2311(sd);
826 + if (ov2311->streaming) {
827 + ret = ov2311_start_stream(ov2311);
834 + ov2311_stop_stream(ov2311);
835 + ov2311->streaming = 0;
839 +static int ov2311_runtime_suspend(struct device *dev)
841 + struct v4l2_subdev *sd = dev_get_drvdata(dev);
842 + struct ov2311 *ov2311 = to_ov2311(sd);
844 + if (ov2311->streaming)
845 + ov2311_stop_stream(ov2311);
850 +static int ov2311_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
852 + struct ov2311 *ov2311 = to_ov2311(sd);
853 + struct v4l2_mbus_framefmt *try_fmt =
854 + v4l2_subdev_get_try_format(sd, fh->state, 0);
855 + const struct ov2311_mode *def_mode = &supported_modes[0];
857 + mutex_lock(&ov2311->mutex);
858 + /* Initialize try_fmt */
859 + try_fmt->width = def_mode->width;
860 + try_fmt->height = def_mode->height;
861 + try_fmt->code = MEDIA_BUS_FMT_Y10_1X10;
862 + try_fmt->field = V4L2_FIELD_NONE;
863 + try_fmt->colorspace = V4L2_COLORSPACE_RAW;
864 + try_fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(try_fmt->colorspace);
865 + try_fmt->quantization =
866 + V4L2_MAP_QUANTIZATION_DEFAULT(true, try_fmt->colorspace,
867 + try_fmt->ycbcr_enc);
868 + try_fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(try_fmt->colorspace);
870 + mutex_unlock(&ov2311->mutex);
871 + /* No crop or compose */
876 +static const struct dev_pm_ops ov2311_pm_ops = {
877 + SET_RUNTIME_PM_OPS(ov2311_runtime_suspend, ov2311_runtime_resume, NULL)
878 + SET_RUNTIME_PM_OPS(ov2311_power_off, ov2311_power_on, NULL)
881 +static const struct v4l2_subdev_internal_ops ov2311_internal_ops = {
882 + .open = ov2311_open,
885 +static const struct v4l2_subdev_core_ops ov2311_core_ops = {
886 + .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
887 + .unsubscribe_event = v4l2_event_subdev_unsubscribe,
890 +static const struct v4l2_subdev_video_ops ov2311_video_ops = {
891 + .s_stream = ov2311_s_stream,
894 +static const struct v4l2_subdev_pad_ops ov2311_pad_ops = {
895 + .enum_mbus_code = ov2311_enum_mbus_code,
896 + .enum_frame_size = ov2311_enum_frame_sizes,
897 + .get_fmt = ov2311_get_fmt,
898 + .set_fmt = ov2311_set_fmt,
899 + .get_selection = ov2311_get_selection,
902 +static const struct v4l2_subdev_ops ov2311_subdev_ops = {
903 + .core = &ov2311_core_ops,
904 + .video = &ov2311_video_ops,
905 + .pad = &ov2311_pad_ops,
908 +static int ov2311_set_ctrl(struct v4l2_ctrl *ctrl)
910 + struct ov2311 *ov2311 = container_of(ctrl->handler,
911 + struct ov2311, ctrl_handler);
912 + struct i2c_client *client = ov2311->client;
916 + /* Propagate change of current control to all related controls */
917 + switch (ctrl->id) {
918 + case V4L2_CID_VBLANK:
919 + /* Update max exposure while meeting expected vblanking */
920 + max = ov2311->cur_mode->height + ctrl->val - 4;
921 + __v4l2_ctrl_modify_range(ov2311->exposure,
922 + ov2311->exposure->minimum, max,
923 + ov2311->exposure->step,
924 + ov2311->exposure->default_value);
928 + if (pm_runtime_get(&client->dev) <= 0)
931 + switch (ctrl->id) {
932 + case V4L2_CID_EXPOSURE:
933 + ret = ov2311_write_reg(ov2311->client, OV2311_REG_EXPOSURE,
934 + OV2311_REG_VALUE_16BIT, ctrl->val);
936 + case V4L2_CID_ANALOGUE_GAIN:
937 + ret = ov2311_write_reg(ov2311->client, OV2311_REG_GAIN_H,
938 + OV2311_REG_VALUE_08BIT,
939 + (ctrl->val >> OV2311_GAIN_H_SHIFT) &
940 + OV2311_GAIN_H_MASK);
941 + ret |= ov2311_write_reg(ov2311->client, OV2311_REG_GAIN_L,
942 + OV2311_REG_VALUE_08BIT,
943 + ctrl->val & OV2311_GAIN_L_MASK);
945 + case V4L2_CID_VBLANK:
946 + ret = ov2311_write_reg(ov2311->client, OV2311_REG_VTS,
947 + OV2311_REG_VALUE_16BIT,
948 + ctrl->val + ov2311->cur_mode->height);
950 + case V4L2_CID_TEST_PATTERN:
951 + ret = ov2311_enable_test_pattern(ov2311, ctrl->val);
953 + case V4L2_CID_HFLIP:
954 + ret = ov2311_write_reg(ov2311->client, OV2311_REG_H_FLIP,
955 + OV2311_REG_VALUE_08BIT,
956 + ctrl->val ? OV2311_FLIP_BIT : 0);
958 + case V4L2_CID_VFLIP:
959 + ret = ov2311_write_reg(ov2311->client, OV2311_REG_V_FLIP,
960 + OV2311_REG_VALUE_08BIT,
961 + ctrl->val ? OV2311_FLIP_BIT : 0);
964 + dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
965 + __func__, ctrl->id, ctrl->val);
969 + pm_runtime_put(&client->dev);
974 +static const struct v4l2_ctrl_ops ov2311_ctrl_ops = {
975 + .s_ctrl = ov2311_set_ctrl,
978 +static int ov2311_initialize_controls(struct ov2311 *ov2311)
980 + struct v4l2_fwnode_device_properties props;
981 + const struct ov2311_mode *mode;
982 + struct v4l2_ctrl_handler *handler;
983 + struct v4l2_ctrl *ctrl;
984 + s64 exposure_max, vblank_def;
988 + handler = &ov2311->ctrl_handler;
989 + mode = ov2311->cur_mode;
990 + ret = v4l2_ctrl_handler_init(handler, 11);
993 + handler->lock = &ov2311->mutex;
995 + ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
996 + 0, 0, link_freq_menu_items);
998 + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1000 + ov2311->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
1001 + V4L2_CID_PIXEL_RATE,
1002 + OV2311_PIXEL_RATE_10BIT,
1003 + OV2311_PIXEL_RATE_10BIT, 1,
1004 + OV2311_PIXEL_RATE_10BIT);
1006 + h_blank = mode->hts_def - mode->width;
1007 + ov2311->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
1008 + h_blank, h_blank, 1, h_blank);
1009 + if (ov2311->hblank)
1010 + ov2311->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1012 + vblank_def = mode->vts_def - mode->height;
1013 + ov2311->vblank = v4l2_ctrl_new_std(handler, &ov2311_ctrl_ops,
1014 + V4L2_CID_VBLANK, vblank_def,
1015 + OV2311_VTS_MAX - mode->height, 1,
1018 + exposure_max = mode->vts_def - 4;
1019 + ov2311->exposure = v4l2_ctrl_new_std(handler, &ov2311_ctrl_ops,
1020 + V4L2_CID_EXPOSURE,
1021 + OV2311_EXPOSURE_MIN, exposure_max,
1022 + OV2311_EXPOSURE_STEP,
1025 + v4l2_ctrl_new_std(handler, &ov2311_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
1026 + OV2311_GAIN_MIN, OV2311_GAIN_MAX, OV2311_GAIN_STEP,
1027 + OV2311_GAIN_DEFAULT);
1029 + v4l2_ctrl_new_std_menu_items(handler, &ov2311_ctrl_ops,
1030 + V4L2_CID_TEST_PATTERN,
1031 + ARRAY_SIZE(ov2311_test_pattern_menu) - 1,
1032 + 0, 0, ov2311_test_pattern_menu);
1034 + v4l2_ctrl_new_std(handler, &ov2311_ctrl_ops,
1035 + V4L2_CID_HFLIP, 0, 1, 1, 0);
1037 + v4l2_ctrl_new_std(handler, &ov2311_ctrl_ops,
1038 + V4L2_CID_VFLIP, 0, 1, 1, 0);
1040 + ret = v4l2_fwnode_device_parse(&ov2311->client->dev, &props);
1042 + goto err_free_handler;
1044 + ret = v4l2_ctrl_new_fwnode_properties(handler, &ov2311_ctrl_ops,
1047 + goto err_free_handler;
1049 + if (handler->error) {
1050 + ret = handler->error;
1051 + dev_err(&ov2311->client->dev,
1052 + "Failed to init controls(%d)\n", ret);
1053 + goto err_free_handler;
1056 + ov2311->subdev.ctrl_handler = handler;
1061 + v4l2_ctrl_handler_free(handler);
1066 +static int ov2311_check_sensor_id(struct ov2311 *ov2311,
1067 + struct i2c_client *client)
1069 + struct device *dev = &ov2311->client->dev;
1070 + u32 id = 0, id_msb;
1073 + ret = ov2311_read_reg(client, OV2311_REG_CHIP_ID + 1,
1074 + OV2311_REG_VALUE_08BIT, &id);
1076 + ret = ov2311_read_reg(client, OV2311_REG_CHIP_ID,
1077 + OV2311_REG_VALUE_08BIT, &id_msb);
1078 + id |= (id_msb << 8);
1079 + if (ret || id != CHIP_ID) {
1080 + dev_err(dev, "Unexpected sensor id(%04x), ret(%d)\n", id, ret);
1084 + dev_info(dev, "Detected OV%06x sensor\n", CHIP_ID);
1089 +static int ov2311_configure_regulators(struct ov2311 *ov2311)
1093 + for (i = 0; i < OV2311_NUM_SUPPLIES; i++)
1094 + ov2311->supplies[i].supply = ov2311_supply_names[i];
1096 + return devm_regulator_bulk_get(&ov2311->client->dev,
1097 + OV2311_NUM_SUPPLIES,
1098 + ov2311->supplies);
1101 +static int ov2311_probe(struct i2c_client *client,
1102 + const struct i2c_device_id *id)
1104 + struct device *dev = &client->dev;
1105 + struct ov2311 *ov2311;
1106 + struct v4l2_subdev *sd;
1109 + ov2311 = devm_kzalloc(dev, sizeof(*ov2311), GFP_KERNEL);
1113 + ov2311->client = client;
1114 + ov2311->cur_mode = &supported_modes[0];
1116 + ov2311->xvclk = devm_clk_get(dev, "xvclk");
1117 + if (IS_ERR(ov2311->xvclk)) {
1118 + dev_err(dev, "Failed to get xvclk\n");
1122 + ov2311->reset_gpio = devm_gpiod_get_optional(dev, "reset",
1124 + if (IS_ERR(ov2311->reset_gpio))
1125 + dev_warn(dev, "Failed to get reset-gpios\n");
1127 + ov2311->pwdn_gpio = devm_gpiod_get_optional(dev, "pwdn", GPIOD_OUT_LOW);
1128 + if (IS_ERR(ov2311->pwdn_gpio))
1129 + dev_warn(dev, "Failed to get pwdn-gpios\n");
1131 + ret = ov2311_configure_regulators(ov2311);
1133 + dev_err(dev, "Failed to get power regulators\n");
1137 + mutex_init(&ov2311->mutex);
1139 + sd = &ov2311->subdev;
1140 + v4l2_i2c_subdev_init(sd, client, &ov2311_subdev_ops);
1141 + ret = ov2311_initialize_controls(ov2311);
1143 + goto err_destroy_mutex;
1145 + ret = ov2311_power_on(&client->dev);
1147 + goto err_free_handler;
1149 + ret = ov2311_check_sensor_id(ov2311, client);
1151 + goto err_power_off;
1153 + sd->internal_ops = &ov2311_internal_ops;
1154 + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1156 + ov2311->pad.flags = MEDIA_PAD_FL_SOURCE;
1157 + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
1158 + ret = media_entity_pads_init(&sd->entity, 1, &ov2311->pad);
1160 + goto err_power_off;
1162 + ret = v4l2_async_register_subdev(sd);
1164 + dev_err(dev, "v4l2 async register subdev failed\n");
1165 + goto err_clean_entity;
1168 + pm_runtime_set_active(dev);
1169 + pm_runtime_enable(dev);
1170 + pm_runtime_idle(dev);
1175 + media_entity_cleanup(&sd->entity);
1177 + ov2311_power_off(&client->dev);
1179 + v4l2_ctrl_handler_free(&ov2311->ctrl_handler);
1181 + mutex_destroy(&ov2311->mutex);
1186 +static int ov2311_remove(struct i2c_client *client)
1188 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
1189 + struct ov2311 *ov2311 = to_ov2311(sd);
1191 + v4l2_async_unregister_subdev(sd);
1192 + media_entity_cleanup(&sd->entity);
1193 + v4l2_ctrl_handler_free(&ov2311->ctrl_handler);
1194 + mutex_destroy(&ov2311->mutex);
1196 + pm_runtime_disable(&client->dev);
1197 + if (!pm_runtime_status_suspended(&client->dev))
1198 + ov2311_power_off(&client->dev);
1199 + pm_runtime_set_suspended(&client->dev);
1204 +static const struct of_device_id ov2311_of_match[] = {
1205 + { .compatible = "ovti,ov2311" },
1208 +MODULE_DEVICE_TABLE(of, ov2311_of_match);
1210 +static const struct i2c_device_id ov2311_match_id[] = {
1211 + { "ovti,ov2311", 0 },
1215 +static struct i2c_driver ov2311_i2c_driver = {
1217 + .name = OV2311_NAME,
1218 + .pm = &ov2311_pm_ops,
1219 + .of_match_table = of_match_ptr(ov2311_of_match),
1221 + .probe = &ov2311_probe,
1222 + .remove = &ov2311_remove,
1223 + .id_table = ov2311_match_id,
1226 +module_i2c_driver(ov2311_i2c_driver);
1228 +MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.com");
1229 +MODULE_DESCRIPTION("OmniVision OV2311 sensor driver");
1230 +MODULE_LICENSE("GPL v2");