ov02a10
static inline struct ov02a10 *to_ov02a10(struct v4l2_subdev *sd)
return container_of(sd, struct ov02a10, subdev);
static int ov02a10_write_array(struct ov02a10 *ov02a10,
struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
struct ov02a10 *ov02a10 = to_ov02a10(sd);
mutex_lock(&ov02a10->mutex);
if (ov02a10->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
mbus_fmt->code = ov02a10->fmt.code;
ov02a10_fill_fmt(ov02a10->cur_mode, mbus_fmt);
frame_fmt = &ov02a10->fmt;
mutex_unlock(&ov02a10->mutex);
struct ov02a10 *ov02a10 = to_ov02a10(sd);
mutex_lock(&ov02a10->mutex);
fmt->format = ov02a10->fmt;
mbus_fmt->code = ov02a10->fmt.code;
ov02a10_fill_fmt(ov02a10->cur_mode, mbus_fmt);
mutex_unlock(&ov02a10->mutex);
struct ov02a10 *ov02a10 = to_ov02a10(sd);
code->code = ov02a10->fmt.code;
static int ov02a10_check_sensor_id(struct ov02a10 *ov02a10)
struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
dev_err(ov02a10->dev, "unexpected sensor id(0x%04x)\n", chip_id);
struct ov02a10 *ov02a10 = to_ov02a10(sd);
gpiod_set_value_cansleep(ov02a10->rst_gpio, 1);
gpiod_set_value_cansleep(ov02a10->pd_gpio, 1);
ret = clk_prepare_enable(ov02a10->eclk);
ov02a10->supplies);
gpiod_set_value_cansleep(ov02a10->pd_gpio, 0);
gpiod_set_value_cansleep(ov02a10->rst_gpio, 0);
ret = ov02a10_check_sensor_id(ov02a10);
ov02a10->supplies);
clk_disable_unprepare(ov02a10->eclk);
struct ov02a10 *ov02a10 = to_ov02a10(sd);
gpiod_set_value_cansleep(ov02a10->rst_gpio, 1);
clk_disable_unprepare(ov02a10->eclk);
gpiod_set_value_cansleep(ov02a10->pd_gpio, 1);
ov02a10->supplies);
static int __ov02a10_start_stream(struct ov02a10 *ov02a10)
struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
reg_list = &ov02a10->cur_mode->reg_list;
ret = ov02a10_write_array(ov02a10, reg_list);
ret = __v4l2_ctrl_handler_setup(ov02a10->subdev.ctrl_handler);
if (ov02a10->upside_down) {
dev_err(ov02a10->dev, "failed to set orientation\n");
if (ov02a10->mipi_clock_voltage != OV02A10_MIPI_TX_SPEED_DEFAULT) {
ov02a10->mipi_clock_voltage);
static int __ov02a10_stop_stream(struct ov02a10 *ov02a10)
struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
struct ov02a10 *ov02a10 = to_ov02a10(sd);
mutex_lock(&ov02a10->mutex);
if (ov02a10->streaming == on) {
ret = pm_runtime_resume_and_get(ov02a10->dev);
ret = __ov02a10_start_stream(ov02a10);
__ov02a10_stop_stream(ov02a10);
ov02a10->streaming = !on;
__ov02a10_stop_stream(ov02a10);
pm_runtime_put(ov02a10->dev);
ov02a10->streaming = on;
mutex_unlock(&ov02a10->mutex);
pm_runtime_put(ov02a10->dev);
mutex_unlock(&ov02a10->mutex);
static int ov02a10_set_exposure(struct ov02a10 *ov02a10, int val)
struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
static int ov02a10_set_gain(struct ov02a10 *ov02a10, int val)
struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
static int ov02a10_set_vblank(struct ov02a10 *ov02a10, int val)
struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
u32 vts = val + ov02a10->cur_mode->height - OV02A10_BASE_LINES;
static int ov02a10_set_test_pattern(struct ov02a10 *ov02a10, int pattern)
struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev);
struct ov02a10 *ov02a10 = container_of(ctrl->handler,
struct ov02a10, ctrl_handler);
max_expo = ov02a10->cur_mode->height + ctrl->val -
__v4l2_ctrl_modify_range(ov02a10->exposure,
ov02a10->exposure->minimum, max_expo,
ov02a10->exposure->step,
ov02a10->exposure->default_value);
if (!pm_runtime_get_if_in_use(ov02a10->dev))
ret = ov02a10_set_exposure(ov02a10, ctrl->val);
ret = ov02a10_set_gain(ov02a10, ctrl->val);
ret = ov02a10_set_vblank(ov02a10, ctrl->val);
ret = ov02a10_set_test_pattern(ov02a10, ctrl->val);
pm_runtime_put(ov02a10->dev);
static int ov02a10_initialize_controls(struct ov02a10 *ov02a10)
handler = &ov02a10->ctrl_handler;
mode = ov02a10->cur_mode;
handler->lock = &ov02a10->mutex;
ov02a10->exposure = v4l2_ctrl_new_std(handler, &ov02a10_ctrl_ops,
dev_err(ov02a10->dev, "failed to init controls(%d)\n", ret);
ov02a10->subdev.ctrl_handler = handler;
static int ov02a10_check_hwcfg(struct device *dev, struct ov02a10 *ov02a10)
ov02a10->mipi_clock_voltage = clk_volt;
struct ov02a10 *ov02a10;
ov02a10 = devm_kzalloc(dev, sizeof(*ov02a10), GFP_KERNEL);
if (!ov02a10)
ov02a10->dev = dev;
ret = ov02a10_check_hwcfg(dev, ov02a10);
v4l2_i2c_subdev_init(&ov02a10->subdev, client, &ov02a10_subdev_ops);
ov02a10->subdev.internal_ops = &ov02a10_internal_ops;
ov02a10->mipi_clock_voltage = OV02A10_MIPI_TX_SPEED_DEFAULT;
ov02a10->fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
ov02a10->upside_down = true;
ov02a10->fmt.code = MEDIA_BUS_FMT_SRGGB10_1X10;
ov02a10->eclk = devm_v4l2_sensor_clk_get_legacy(dev, "eclk", false, 0);
if (IS_ERR(ov02a10->eclk))
return dev_err_probe(dev, PTR_ERR(ov02a10->eclk),
if (clk_get_rate(ov02a10->eclk) != OV02A10_ECLK_FREQ)
ov02a10->pd_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_HIGH);
if (IS_ERR(ov02a10->pd_gpio))
return dev_err_probe(dev, PTR_ERR(ov02a10->pd_gpio),
ov02a10->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ov02a10->rst_gpio))
return dev_err_probe(dev, PTR_ERR(ov02a10->rst_gpio),
ov02a10->supplies[i].supply = ov02a10_supply_names[i];
ov02a10->supplies);
mutex_init(&ov02a10->mutex);
ov02a10->cur_mode = &supported_modes[0];
ret = ov02a10_initialize_controls(ov02a10);
ov02a10->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov02a10->subdev.entity.ops = &ov02a10_subdev_entity_ops;
ov02a10->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ov02a10->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&ov02a10->subdev.entity, 1, &ov02a10->pad);
ret = v4l2_async_register_subdev(&ov02a10->subdev);
media_entity_cleanup(&ov02a10->subdev.entity);
v4l2_ctrl_handler_free(ov02a10->subdev.ctrl_handler);
mutex_destroy(&ov02a10->mutex);
struct ov02a10 *ov02a10 = to_ov02a10(sd);
pm_runtime_disable(ov02a10->dev);
if (!pm_runtime_status_suspended(ov02a10->dev))
ov02a10_power_off(ov02a10->dev);
pm_runtime_set_suspended(ov02a10->dev);
mutex_destroy(&ov02a10->mutex);