ov13858
#define to_ov13858(_sd) container_of(_sd, struct ov13858, sd)
static int ov13858_read_reg(struct ov13858 *ov13858, u16 reg, u32 len,
struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
static int ov13858_write_reg(struct ov13858 *ov13858, u16 reg, u32 len,
struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
static int ov13858_write_regs(struct ov13858 *ov13858,
ret = ov13858_write_reg(ov13858, regs[i].address, 1,
ov13858->dev,
static int ov13858_write_reg_list(struct ov13858 *ov13858,
return ov13858_write_regs(ov13858, r_list->regs, r_list->num_of_regs);
struct ov13858 *ov13858 = to_ov13858(sd);
mutex_lock(&ov13858->mutex);
try_fmt->width = ov13858->cur_mode->width;
try_fmt->height = ov13858->cur_mode->height;
mutex_unlock(&ov13858->mutex);
static int ov13858_update_digital_gain(struct ov13858 *ov13858, u32 d_gain)
ret = ov13858_write_reg(ov13858, OV13858_REG_B_MWB_GAIN,
ret = ov13858_write_reg(ov13858, OV13858_REG_G_MWB_GAIN,
ret = ov13858_write_reg(ov13858, OV13858_REG_R_MWB_GAIN,
static int ov13858_enable_test_pattern(struct ov13858 *ov13858, u32 pattern)
ret = ov13858_read_reg(ov13858, OV13858_REG_TEST_PATTERN,
return ov13858_write_reg(ov13858, OV13858_REG_TEST_PATTERN,
struct ov13858 *ov13858 = container_of(ctrl->handler,
struct ov13858, ctrl_handler);
max = ov13858->cur_mode->height + ctrl->val - 8;
__v4l2_ctrl_modify_range(ov13858->exposure,
ov13858->exposure->minimum,
max, ov13858->exposure->step, max);
if (!pm_runtime_get_if_in_use(ov13858->dev))
ret = ov13858_write_reg(ov13858, OV13858_REG_ANALOG_GAIN,
ret = ov13858_update_digital_gain(ov13858, ctrl->val);
ret = ov13858_write_reg(ov13858, OV13858_REG_EXPOSURE,
ret = ov13858_write_reg(ov13858, OV13858_REG_VTS,
ov13858->cur_mode->height
ret = ov13858_enable_test_pattern(ov13858, ctrl->val);
dev_info(ov13858->dev,
pm_runtime_put(ov13858->dev);
static int ov13858_do_get_pad_format(struct ov13858 *ov13858,
ov13858_update_pad_format(ov13858->cur_mode, fmt);
struct ov13858 *ov13858 = to_ov13858(sd);
mutex_lock(&ov13858->mutex);
ret = ov13858_do_get_pad_format(ov13858, sd_state, fmt);
mutex_unlock(&ov13858->mutex);
struct ov13858 *ov13858 = to_ov13858(sd);
mutex_lock(&ov13858->mutex);
ov13858->cur_mode = mode;
__v4l2_ctrl_s_ctrl(ov13858->link_freq, mode->link_freq_index);
__v4l2_ctrl_s_ctrl_int64(ov13858->pixel_rate, pixel_rate);
vblank_def = ov13858->cur_mode->vts_def -
ov13858->cur_mode->height;
vblank_min = ov13858->cur_mode->vts_min -
ov13858->cur_mode->height;
ov13858->vblank, vblank_min,
OV13858_VTS_MAX - ov13858->cur_mode->height, 1,
__v4l2_ctrl_s_ctrl(ov13858->vblank, vblank_def);
- ov13858->cur_mode->width;
__v4l2_ctrl_modify_range(ov13858->hblank, h_blank,
mutex_unlock(&ov13858->mutex);
static int ov13858_start_streaming(struct ov13858 *ov13858)
ret = ov13858_write_reg(ov13858, OV13858_REG_SOFTWARE_RST,
dev_err(ov13858->dev, "%s failed to set powerup registers\n",
link_freq_index = ov13858->cur_mode->link_freq_index;
ret = ov13858_write_reg_list(ov13858, reg_list);
dev_err(ov13858->dev, "%s failed to set plls\n", __func__);
reg_list = &ov13858->cur_mode->reg_list;
ret = ov13858_write_reg_list(ov13858, reg_list);
dev_err(ov13858->dev, "%s failed to set mode\n", __func__);
ret = __v4l2_ctrl_handler_setup(ov13858->sd.ctrl_handler);
return ov13858_write_reg(ov13858, OV13858_REG_MODE_SELECT,
static int ov13858_stop_streaming(struct ov13858 *ov13858)
return ov13858_write_reg(ov13858, OV13858_REG_MODE_SELECT,
struct ov13858 *ov13858 = to_ov13858(sd);
mutex_lock(&ov13858->mutex);
ret = pm_runtime_resume_and_get(ov13858->dev);
ret = ov13858_start_streaming(ov13858);
ov13858_stop_streaming(ov13858);
pm_runtime_put(ov13858->dev);
mutex_unlock(&ov13858->mutex);
pm_runtime_put(ov13858->dev);
mutex_unlock(&ov13858->mutex);
static int ov13858_identify_module(struct ov13858 *ov13858)
ret = ov13858_read_reg(ov13858, OV13858_REG_CHIP_ID,
dev_err(ov13858->dev, "chip id mismatch: %x!=%x\n",
static int ov13858_init_controls(struct ov13858 *ov13858)
ctrl_hdlr = &ov13858->ctrl_handler;
mutex_init(&ov13858->mutex);
ctrl_hdlr->lock = &ov13858->mutex;
ov13858->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
if (ov13858->link_freq)
ov13858->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
ov13858->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops,
mode = ov13858->cur_mode;
ov13858->vblank = v4l2_ctrl_new_std(
ov13858->hblank = v4l2_ctrl_new_std(
if (ov13858->hblank)
ov13858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
ov13858->exposure = v4l2_ctrl_new_std(
dev_err(ov13858->dev, "%s control init failed (%d)\n",
ret = v4l2_fwnode_device_parse(ov13858->dev, &props);
ov13858->sd.ctrl_handler = ctrl_hdlr;
mutex_destroy(&ov13858->mutex);
static void ov13858_free_controls(struct ov13858 *ov13858)
v4l2_ctrl_handler_free(ov13858->sd.ctrl_handler);
mutex_destroy(&ov13858->mutex);
struct ov13858 *ov13858;
ov13858 = devm_kzalloc(&client->dev, sizeof(*ov13858), GFP_KERNEL);
if (!ov13858)
ov13858->dev = &client->dev;
ov13858->clk = devm_v4l2_sensor_clk_get(ov13858->dev, NULL);
if (IS_ERR(ov13858->clk))
return dev_err_probe(ov13858->dev, PTR_ERR(ov13858->clk),
freq = clk_get_rate(ov13858->clk);
return dev_err_probe(ov13858->dev, -EINVAL,
v4l2_i2c_subdev_init(&ov13858->sd, client, &ov13858_subdev_ops);
ret = ov13858_identify_module(ov13858);
dev_err(ov13858->dev, "failed to find sensor: %d\n", ret);
ov13858->cur_mode = &supported_modes[0];
ret = ov13858_init_controls(ov13858);
ov13858->sd.internal_ops = &ov13858_internal_ops;
ov13858->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
ov13858->sd.entity.ops = &ov13858_subdev_entity_ops;
ov13858->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ov13858->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&ov13858->sd.entity, 1, &ov13858->pad);
dev_err(ov13858->dev, "%s failed:%d\n", __func__, ret);
ret = v4l2_async_register_subdev_sensor(&ov13858->sd);
pm_runtime_set_active(ov13858->dev);
pm_runtime_enable(ov13858->dev);
pm_runtime_idle(ov13858->dev);
media_entity_cleanup(&ov13858->sd.entity);
ov13858_free_controls(ov13858);
dev_err(ov13858->dev, "%s failed:%d\n", __func__, ret);
struct ov13858 *ov13858 = to_ov13858(sd);
ov13858_free_controls(ov13858);
pm_runtime_disable(ov13858->dev);