ov02e10
static inline struct ov02e10 *to_ov02e10(struct v4l2_subdev *subdev)
return container_of(subdev, struct ov02e10, sd);
static void ov02e10_test_pattern(struct ov02e10 *ov02e10, u32 pattern, int *pret)
cci_write(ov02e10->regmap, OV02E10_REG_TEST_PATTERN, pattern, pret);
struct ov02e10 *ov02e10 = container_of(ctrl->handler,
struct ov02e10, ctrl_handler);
exposure_max = ov02e10->cur_mode->height + ctrl->val -
ret = __v4l2_ctrl_modify_range(ov02e10->exposure,
ov02e10->exposure->minimum,
ov02e10->exposure->step,
if (!pm_runtime_get_if_in_use(ov02e10->dev))
ret = cci_write(ov02e10->regmap, OV02E10_REG_COMMAND_UPDATE,
cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG,
cci_write(ov02e10->regmap, OV02E10_REG_ANALOG_GAIN,
cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG,
cci_write(ov02e10->regmap, OV02E10_REG_DIGITAL_GAIN,
cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG,
cci_write(ov02e10->regmap, OV02E10_REG_EXPOSURE,
cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG,
cci_write(ov02e10->regmap, OV02E10_REG_ORIENTATION,
ov02e10->hflip->val | ov02e10->vflip->val << 1, &ret);
cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG,
cci_write(ov02e10->regmap, OV02E10_REG_VTS,
ov02e10->cur_mode->height + ctrl->val, &ret);
cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG,
ov02e10_test_pattern(ov02e10, ctrl->val, &ret);
cci_write(ov02e10->regmap, OV02E10_REG_COMMAND_UPDATE,
pm_runtime_put(ov02e10->dev);
static int ov02e10_init_controls(struct ov02e10 *ov02e10)
struct v4l2_ctrl_handler *ctrl_hdlr = &ov02e10->ctrl_handler;
const struct ov02e10_mode *mode = ov02e10->cur_mode;
ov02e10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
ov02e10->link_freq_index,
if (ov02e10->link_freq)
ov02e10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
pixel_rate = to_pixel_rate(ov02e10->link_freq_index);
ov02e10->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov02e10_ctrl_ops,
ov02e10->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov02e10_ctrl_ops,
ov02e10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov02e10_ctrl_ops,
if (ov02e10->hblank)
ov02e10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
ov02e10->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov02e10_ctrl_ops,
ov02e10->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov02e10_ctrl_ops,
if (ov02e10->hflip)
ov02e10->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
ov02e10->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov02e10_ctrl_ops,
if (ov02e10->vflip)
ov02e10->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
ret = v4l2_fwnode_device_parse(ov02e10->dev, &props);
ov02e10->sd.ctrl_handler = ctrl_hdlr;
static int ov02e10_set_stream_mode(struct ov02e10 *ov02e10, u8 val)
cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG, OV02E10_PAGE_0, &ret);
cci_write(ov02e10->regmap, CCI_REG8(0xa0), val, &ret);
cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG, OV02E10_PAGE_1, &ret);
cci_write(ov02e10->regmap, CCI_REG8(0x01), 0x02, &ret);
struct ov02e10 *ov02e10 = to_ov02e10(sd);
ret = pm_runtime_resume_and_get(ov02e10->dev);
reg_list = &ov02e10->cur_mode->reg_list;
ret = regmap_multi_reg_write(ov02e10->regmap, reg_list->regs,
dev_err(ov02e10->dev, "failed to set mode\n");
ret = __v4l2_ctrl_handler_setup(ov02e10->sd.ctrl_handler);
ret = ov02e10_set_stream_mode(ov02e10, 1);
pm_runtime_put(ov02e10->dev);
struct ov02e10 *ov02e10 = to_ov02e10(sd);
ov02e10_set_stream_mode(ov02e10, 0);
pm_runtime_put(ov02e10->dev);
struct ov02e10 *ov02e10 = to_ov02e10(sd);
ov02e10->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ov02e10->reset))
return dev_err_probe(dev, PTR_ERR(ov02e10->reset),
ov02e10->supplies[i].supply = ov02e10_supply_names[i];
ov02e10->supplies);
struct ov02e10 *ov02e10 = to_ov02e10(sd);
if (ov02e10->reset)
gpiod_set_value_cansleep(ov02e10->reset, 1);
ov02e10->supplies);
clk_disable_unprepare(ov02e10->img_clk);
struct ov02e10 *ov02e10 = to_ov02e10(sd);
ret = clk_prepare_enable(ov02e10->img_clk);
ov02e10->supplies);
if (ov02e10->reset) {
gpiod_set_value_cansleep(ov02e10->reset, 0);
clk_disable_unprepare(ov02e10->img_clk);
struct ov02e10 *ov02e10 = to_ov02e10(sd);
ov02e10->cur_mode = mode;
ret = __v4l2_ctrl_s_ctrl(ov02e10->link_freq,
ov02e10->link_freq_index);
ret = __v4l2_ctrl_s_ctrl_int64(ov02e10->pixel_rate,
to_pixel_rate(ov02e10->link_freq_index));
ret = __v4l2_ctrl_modify_range(ov02e10->vblank,
ret = __v4l2_ctrl_s_ctrl(ov02e10->vblank, vblank_def);
h_blank = to_pixels_per_line(mode->hts, ov02e10->link_freq_index);
ret = __v4l2_ctrl_modify_range(ov02e10->hblank, h_blank,
struct ov02e10 *ov02e10 = to_ov02e10(sd);
ov02e10_update_pad_format(ov02e10->cur_mode, &fmt->format);
static int ov02e10_identify_module(struct ov02e10 *ov02e10)
ret = cci_write(ov02e10->regmap, OV02E10_REG_PAGE_FLAG,
cci_read(ov02e10->regmap, OV02E10_REG_CHIP_ID, &val, &ret);
dev_err(ov02e10->dev, "chip id mismatch: %x!=%x\n",
static int ov02e10_check_hwcfg(struct ov02e10 *ov02e10)
struct device *dev = ov02e10->dev;
ov02e10->link_freq_index = ffs(link_freq_bitmap) - 1;
ov02e10->mipi_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
struct ov02e10 *ov02e10 = to_ov02e10(sd);
pm_runtime_disable(ov02e10->dev);
if (!pm_runtime_status_suspended(ov02e10->dev)) {
ov02e10_power_off(ov02e10->dev);
pm_runtime_set_suspended(ov02e10->dev);
struct ov02e10 *ov02e10;
ov02e10 = devm_kzalloc(&client->dev, sizeof(*ov02e10), GFP_KERNEL);
if (!ov02e10)
ov02e10->dev = &client->dev;
ov02e10->img_clk = devm_v4l2_sensor_clk_get(ov02e10->dev, NULL);
if (IS_ERR(ov02e10->img_clk))
return dev_err_probe(ov02e10->dev, PTR_ERR(ov02e10->img_clk),
freq = clk_get_rate(ov02e10->img_clk);
return dev_err_probe(ov02e10->dev, -EINVAL,
v4l2_i2c_subdev_init(&ov02e10->sd, client, &ov02e10_subdev_ops);
ret = ov02e10_check_hwcfg(ov02e10);
ov02e10->regmap = devm_cci_regmap_init_i2c(client, 8);
if (IS_ERR(ov02e10->regmap))
return PTR_ERR(ov02e10->regmap);
ret = ov02e10_get_pm_resources(ov02e10->dev);
ret = ov02e10_power_on(ov02e10->dev);
dev_err_probe(ov02e10->dev, ret, "failed to power on\n");
ret = ov02e10_identify_module(ov02e10);
dev_err(ov02e10->dev, "failed to find sensor: %d\n", ret);
ov02e10->cur_mode = &supported_modes[0];
ret = ov02e10_init_controls(ov02e10);
dev_err(ov02e10->dev, "failed to init controls: %d\n", ret);
ov02e10->sd.internal_ops = &ov02e10_internal_ops;
ov02e10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov02e10->sd.entity.ops = &ov02e10_subdev_entity_ops;
ov02e10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ov02e10->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&ov02e10->sd.entity, 1, &ov02e10->pad);
dev_err(ov02e10->dev, "failed to init entity pads: %d", ret);
ov02e10->sd.state_lock = ov02e10->ctrl_handler.lock;
ret = v4l2_subdev_init_finalize(&ov02e10->sd);
dev_err(ov02e10->dev, "failed to init subdev: %d", ret);
pm_runtime_set_active(ov02e10->dev);
pm_runtime_enable(ov02e10->dev);
ret = v4l2_async_register_subdev_sensor(&ov02e10->sd);
dev_err(ov02e10->dev, "failed to register V4L2 subdev: %d",
pm_runtime_idle(ov02e10->dev);
pm_runtime_disable(ov02e10->dev);
pm_runtime_set_suspended(ov02e10->dev);
v4l2_subdev_cleanup(&ov02e10->sd);
media_entity_cleanup(&ov02e10->sd.entity);
v4l2_ctrl_handler_free(ov02e10->sd.ctrl_handler);
ov02e10_power_off(ov02e10->dev);