imx219
struct imx219 *imx219 = to_imx219(sd);
imx219->supplies);
ret = clk_prepare_enable(imx219->xclk);
gpiod_set_value_cansleep(imx219->reset_gpio, 1);
regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies);
struct imx219 *imx219 = to_imx219(sd);
gpiod_set_value_cansleep(imx219->reset_gpio, 0);
regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies);
clk_disable_unprepare(imx219->xclk);
static int imx219_get_regulators(struct imx219 *imx219)
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
imx219->supplies[i].supply = imx219_supply_name[i];
imx219->supplies);
static int imx219_identify_module(struct imx219 *imx219)
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
ret = cci_read(imx219->regmap, IMX219_REG_CHIP_ID, &val, NULL);
static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
imx219->lanes = ep_cfg.bus.mipi_csi2.num_data_lanes;
switch (imx219->lanes) {
struct imx219 *imx219;
imx219 = devm_kzalloc(&client->dev, sizeof(*imx219), GFP_KERNEL);
if (!imx219)
v4l2_i2c_subdev_init(&imx219->sd, client, &imx219_subdev_ops);
imx219->sd.internal_ops = &imx219_internal_ops;
if (imx219_check_hwcfg(dev, imx219))
imx219->regmap = devm_cci_regmap_init_i2c(client, 16);
if (IS_ERR(imx219->regmap))
return dev_err_probe(dev, PTR_ERR(imx219->regmap),
imx219->xclk = devm_v4l2_sensor_clk_get(dev, NULL);
if (IS_ERR(imx219->xclk))
return dev_err_probe(dev, PTR_ERR(imx219->xclk),
imx219->xclk_freq = clk_get_rate(imx219->xclk);
if (imx219->xclk_freq != IMX219_XCLK_FREQ)
imx219->xclk_freq);
ret = imx219_get_regulators(imx219);
imx219->reset_gpio = devm_gpiod_get_optional(dev, "reset",
ret = imx219_identify_module(imx219);
ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
ret = imx219_init_controls(imx219);
imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
imx219->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&imx219->sd.entity, 1, &imx219->pad);
imx219->sd.state_lock = imx219->ctrl_handler.lock;
ret = v4l2_subdev_init_finalize(&imx219->sd);
ret = v4l2_async_register_subdev_sensor(&imx219->sd);
v4l2_subdev_cleanup(&imx219->sd);
media_entity_cleanup(&imx219->sd.entity);
imx219_free_controls(imx219);
struct imx219 *imx219 = to_imx219(sd);
imx219_free_controls(imx219);
static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd)
return container_of(_sd, struct imx219, sd);
static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
i = (i & ~3) | (imx219->vflip->val ? 2 : 0) |
(imx219->hflip->val ? 1 : 0);
struct imx219 *imx219 =
container_of(ctrl->handler, struct imx219, ctrl_handler);
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
state = v4l2_subdev_get_locked_active_state(&imx219->sd);
ret = __v4l2_ctrl_modify_range(imx219->exposure,
imx219->exposure->minimum,
imx219->exposure->step,
cci_write(imx219->regmap, IMX219_REG_ANALOG_GAIN,
cci_write(imx219->regmap, IMX219_REG_EXPOSURE,
cci_write(imx219->regmap, IMX219_REG_DIGITAL_GAIN,
cci_write(imx219->regmap, IMX219_REG_TEST_PATTERN,
cci_write(imx219->regmap, IMX219_REG_ORIENTATION,
imx219->hflip->val | imx219->vflip->val << 1, &ret);
cci_write(imx219->regmap, IMX219_REG_FRM_LENGTH_A,
cci_write(imx219->regmap, IMX219_REG_LINE_LENGTH_A,
cci_write(imx219->regmap, IMX219_REG_TESTP_RED,
cci_write(imx219->regmap, IMX219_REG_TESTP_GREENR,
cci_write(imx219->regmap, IMX219_REG_TESTP_BLUE,
cci_write(imx219->regmap, IMX219_REG_TESTP_GREENB,
static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE;
static int imx219_init_controls(struct imx219 *imx219)
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
ctrl_hdlr = &imx219->ctrl_handler;
imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
imx219_get_pixel_rate(imx219),
imx219_get_pixel_rate(imx219), 1,
imx219_get_pixel_rate(imx219));
imx219->link_freq =
(imx219->lanes == 2) ? imx219_link_freq_menu :
if (imx219->link_freq)
imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
if (imx219->hflip)
imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
if (imx219->vflip)
imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
imx219->sd.ctrl_handler = ctrl_hdlr;
static void imx219_free_controls(struct imx219 *imx219)
v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
static int imx219_set_framefmt(struct imx219 *imx219,
cci_write(imx219->regmap, IMX219_REG_X_ADD_STA_A,
cci_write(imx219->regmap, IMX219_REG_X_ADD_END_A,
cci_write(imx219->regmap, IMX219_REG_Y_ADD_STA_A,
cci_write(imx219->regmap, IMX219_REG_Y_ADD_END_A,
cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_H, bin_h, &ret);
cci_write(imx219->regmap, IMX219_REG_BINNING_MODE_V, bin_v, &ret);
cci_write(imx219->regmap, IMX219_REG_X_OUTPUT_SIZE,
cci_write(imx219->regmap, IMX219_REG_Y_OUTPUT_SIZE,
cci_write(imx219->regmap, IMX219_REG_TP_WINDOW_WIDTH,
cci_write(imx219->regmap, IMX219_REG_TP_WINDOW_HEIGHT,
cci_write(imx219->regmap, IMX219_REG_CSI_DATA_FORMAT_A,
cci_write(imx219->regmap, IMX219_REG_OPPXCK_DIV, bpp, &ret);
static int imx219_configure_lanes(struct imx219 *imx219)
return cci_multi_reg_write(imx219->regmap,
imx219->lanes == 2 ? imx219_2lane_regs : imx219_4lane_regs,
imx219->lanes == 2 ? ARRAY_SIZE(imx219_2lane_regs) :
struct imx219 *imx219 = to_imx219(sd);
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
ret = cci_multi_reg_write(imx219->regmap, imx219_common_regs,
ret = imx219_configure_lanes(imx219);
ret = imx219_set_framefmt(imx219, state);
ret = __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler);
ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
__v4l2_ctrl_grab(imx219->vflip, true);
__v4l2_ctrl_grab(imx219->hflip, true);
struct imx219 *imx219 = to_imx219(sd);
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
ret = cci_write(imx219->regmap, IMX219_REG_MODE_SELECT,
__v4l2_ctrl_grab(imx219->vflip, false);
__v4l2_ctrl_grab(imx219->hflip, false);
struct imx219 *imx219 = to_imx219(sd);
code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]);
struct imx219 *imx219 = to_imx219(sd);
code = imx219_get_format_code(imx219, fse->code);
struct imx219 *imx219 = to_imx219(sd);
prev_line_len = format->width + imx219->hblank->val;
fmt->format.code = imx219_get_format_code(imx219, fmt->format.code);
ret = __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
ret = __v4l2_ctrl_s_ctrl(imx219->vblank,
ret = __v4l2_ctrl_modify_range(imx219->exposure,
imx219->exposure->minimum,
imx219->exposure->step,
ret = __v4l2_ctrl_modify_range(imx219->hblank,
ret = __v4l2_ctrl_s_ctrl(imx219->hblank, hblank);
pixel_rate = imx219_get_pixel_rate(imx219) *
ret = __v4l2_ctrl_modify_range(imx219->pixel_rate, pixel_rate,