ov8858
static inline struct ov8858 *sd_to_ov8858(struct v4l2_subdev *sd)
static int ov8858_write(struct ov8858 *ov8858, u32 reg, u32 val, int *err)
struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);
return container_of(sd, struct ov8858, subdev);
static int ov8858_write_array(struct ov8858 *ov8858, const struct regval *regs)
ov8858_write(ov8858, OV8858_REG_8BIT(regs[i].addr),
static int ov8858_read(struct ov8858 *ov8858, u32 reg, u32 *val)
struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);
static int ov8858_start_stream(struct ov8858 *ov8858,
ret = ov8858_write_array(ov8858, ov8858->global_regs);
reg_list = ov8858->num_lanes == 4
ret = ov8858_write_array(ov8858, reg_list);
ret = __v4l2_ctrl_handler_setup(&ov8858->ctrl_handler);
ret = ov8858_write(ov8858, OV8858_REG_SC_CTRL0100,
static int ov8858_stop_stream(struct ov8858 *ov8858)
return ov8858_write(ov8858, OV8858_REG_SC_CTRL0100,
struct ov8858 *ov8858 = sd_to_ov8858(sd);
ret = ov8858_start_stream(ov8858, state);
ov8858_stop_stream(ov8858);
struct ov8858 *ov8858 = sd_to_ov8858(sd);
__v4l2_ctrl_modify_range(ov8858->hblank, h_blank, h_blank, 1,
__v4l2_ctrl_modify_range(ov8858->vblank, vblank_def,
static int ov8858_enable_test_pattern(struct ov8858 *ov8858, u32 pattern)
return ov8858_write(ov8858, OV8858_REG_TEST_PATTERN, val, NULL);
struct ov8858 *ov8858 = container_of(ctrl->handler,
struct ov8858, ctrl_handler);
struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);
state = v4l2_subdev_get_locked_active_state(&ov8858->subdev);
__v4l2_ctrl_modify_range(ov8858->exposure,
ov8858->exposure->minimum, max_exp,
ov8858->exposure->step,
ov8858->exposure->default_value);
ret = ov8858_write(ov8858, OV8858_REG_LONG_EXPO,
ret = ov8858_write(ov8858, OV8858_REG_LONG_GAIN,
ret = ov8858_write(ov8858, OV8858_REG_LONG_DIGIGAIN,
ret = ov8858_write(ov8858, OV8858_REG_VTS,
ret = ov8858_enable_test_pattern(ov8858, ctrl->val);
static int ov8858_power_on(struct ov8858 *ov8858)
struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);
if (clk_get_rate(ov8858->xvclk) != OV8858_XVCLK_FREQ)
ret = clk_prepare_enable(ov8858->xvclk);
ov8858->supplies);
gpiod_set_value_cansleep(ov8858->reset_gpio, 0);
gpiod_set_value_cansleep(ov8858->pwdn_gpio, 0);
clk_disable_unprepare(ov8858->xvclk);
static void ov8858_power_off(struct ov8858 *ov8858)
gpiod_set_value_cansleep(ov8858->pwdn_gpio, 1);
clk_disable_unprepare(ov8858->xvclk);
gpiod_set_value_cansleep(ov8858->reset_gpio, 1);
ov8858->supplies);
struct ov8858 *ov8858 = sd_to_ov8858(sd);
return ov8858_power_on(ov8858);
struct ov8858 *ov8858 = sd_to_ov8858(sd);
ov8858_power_off(ov8858);
static int ov8858_init_ctrls(struct ov8858 *ov8858)
struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);
struct v4l2_ctrl_handler *handler = &ov8858->ctrl_handler;
pixel_rate = OV8858_LINK_FREQ * 2 * ov8858->num_lanes / 10;
ov8858->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
if (ov8858->hblank)
ov8858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
ov8858->vblank = v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops,
ov8858->exposure = v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops,
ov8858->subdev.ctrl_handler = handler;
static int ov8858_check_sensor_id(struct ov8858 *ov8858)
struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);
ret = ov8858_read(ov8858, OV8858_REG_CHIP_ID, &id);
ret = ov8858_read(ov8858, OV8858_REG_SUB_ID, &id);
ov8858->global_regs = ov8858->num_lanes == 4
} else if (ov8858->num_lanes == 2) {
ov8858->global_regs = ov8858_global_regs_r1a;
static int ov8858_configure_regulators(struct ov8858 *ov8858)
struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);
ov8858->supplies[i].supply = ov8858_supply_names[i];
ov8858->supplies);
static int ov8858_parse_of(struct ov8858 *ov8858)
struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);
ov8858->num_lanes = vep.bus.mipi_csi2.num_data_lanes;
switch (ov8858->num_lanes) {
ov8858->num_lanes);
struct ov8858 *ov8858;
ov8858 = devm_kzalloc(dev, sizeof(*ov8858), GFP_KERNEL);
if (!ov8858)
ov8858->xvclk = devm_v4l2_sensor_clk_get(dev, "xvclk");
if (IS_ERR(ov8858->xvclk))
return dev_err_probe(dev, PTR_ERR(ov8858->xvclk),
ov8858->reset_gpio = devm_gpiod_get_optional(dev, "reset",
if (IS_ERR(ov8858->reset_gpio))
return dev_err_probe(dev, PTR_ERR(ov8858->reset_gpio),
ov8858->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown",
if (IS_ERR(ov8858->pwdn_gpio))
return dev_err_probe(dev, PTR_ERR(ov8858->pwdn_gpio),
v4l2_i2c_subdev_init(&ov8858->subdev, client, &ov8858_subdev_ops);
ov8858->subdev.internal_ops = &ov8858_internal_ops;
ret = ov8858_configure_regulators(ov8858);
ret = ov8858_parse_of(ov8858);
ret = ov8858_init_ctrls(ov8858);
sd = &ov8858->subdev;
ov8858->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&sd->entity, 1, &ov8858->pad);
sd->state_lock = ov8858->ctrl_handler.lock;
ret = ov8858_power_on(ov8858);
ret = ov8858_check_sensor_id(ov8858);
ov8858_power_off(ov8858);
v4l2_ctrl_handler_free(&ov8858->ctrl_handler);
struct ov8858 *ov8858 = sd_to_ov8858(sd);
v4l2_ctrl_handler_free(&ov8858->ctrl_handler);
ov8858_power_off(ov8858);