gc05a2
ret = __v4l2_ctrl_handler_setup(&gc05a2->ctrls);
dev_err(gc05a2->dev, "could not sync v4l2 controls\n");
ret = cci_write(gc05a2->regmap, GC05A2_STREAMING_REG, 1, NULL);
dev_err(gc05a2->dev, "write STREAMING_REG failed: %d\n", ret);
pm_runtime_put(gc05a2->dev);
static int gc05a2_stop_streaming(struct gc05a2 *gc05a2)
ret = cci_write(gc05a2->regmap, GC05A2_STREAMING_REG, 0, NULL);
dev_err(gc05a2->dev, "could not sent stop streaming %d\n", ret);
pm_runtime_put(gc05a2->dev);
struct gc05a2 *gc05a2 = to_gc05a2(subdev);
ret = gc05a2_start_streaming(gc05a2);
ret = gc05a2_stop_streaming(gc05a2);
static int gc05a2_get_regulators(struct device *dev, struct gc05a2 *gc05a2)
gc05a2->supplies[i].supply = gc05a2_supply_name[i];
gc05a2->supplies);
static int gc05a2_parse_fwnode(struct gc05a2 *gc05a2)
struct device *dev = gc05a2->dev;
&gc05a2->link_freq_bitmap);
static int gc05a2_init_controls(struct gc05a2 *gc05a2)
struct i2c_client *client = v4l2_get_subdevdata(&gc05a2->sd);
ctrl_hdlr = &gc05a2->ctrls;
gc05a2->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
gc05a2->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
v4l2_ctrl_cluster(2, &gc05a2->hflip);
gc05a2->link_freq =
if (gc05a2->link_freq)
gc05a2->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
gc05a2->pixel_rate =
gc05a2->vblank =
gc05a2->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
if (gc05a2->hblank)
gc05a2->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
gc05a2->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &gc05a2_ctrl_ops,
gc05a2->sd.ctrl_handler = ctrl_hdlr;
struct gc05a2 *gc05a2;
gc05a2 = devm_kzalloc(dev, sizeof(*gc05a2), GFP_KERNEL);
if (!gc05a2)
gc05a2->dev = dev;
ret = gc05a2_parse_fwnode(gc05a2);
gc05a2->regmap = devm_cci_regmap_init_i2c(client, 16);
if (IS_ERR(gc05a2->regmap))
return dev_err_probe(dev, PTR_ERR(gc05a2->regmap),
gc05a2->xclk = devm_v4l2_sensor_clk_get_legacy(dev, NULL, true,
if (IS_ERR(gc05a2->xclk))
return dev_err_probe(dev, PTR_ERR(gc05a2->xclk),
ret = gc05a2_get_regulators(dev, gc05a2);
gc05a2->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(gc05a2->reset_gpio))
return dev_err_probe(dev, PTR_ERR(gc05a2->reset_gpio),
v4l2_i2c_subdev_init(&gc05a2->sd, client, &gc05a2_subdev_ops);
gc05a2->sd.internal_ops = &gc05a2_internal_ops;
gc05a2->cur_mode = &gc05a2_modes[0];
ret = gc05a2_init_controls(gc05a2);
gc05a2->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
gc05a2->pad.flags = MEDIA_PAD_FL_SOURCE;
gc05a2->sd.dev = &client->dev;
gc05a2->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&gc05a2->sd.entity, 1, &gc05a2->pad);
gc05a2->sd.state_lock = gc05a2->ctrls.lock;
ret = v4l2_subdev_init_finalize(&gc05a2->sd);
pm_runtime_enable(gc05a2->dev);
pm_runtime_set_autosuspend_delay(gc05a2->dev, 1000);
pm_runtime_use_autosuspend(gc05a2->dev);
pm_runtime_idle(gc05a2->dev);
ret = v4l2_async_register_subdev_sensor(&gc05a2->sd);
pm_runtime_disable(gc05a2->dev);
v4l2_subdev_cleanup(&gc05a2->sd);
media_entity_cleanup(&gc05a2->sd.entity);
v4l2_ctrl_handler_free(&gc05a2->ctrls);
struct gc05a2 *gc05a2 = to_gc05a2(sd);
v4l2_async_unregister_subdev(&gc05a2->sd);
media_entity_cleanup(&gc05a2->sd.entity);
v4l2_ctrl_handler_free(&gc05a2->ctrls);
gc05a2_power_off(gc05a2->dev);
static inline struct gc05a2 *to_gc05a2(struct v4l2_subdev *sd)
return container_of(sd, struct gc05a2, sd);
struct gc05a2 *gc05a2 = to_gc05a2(sd);
gc05a2->supplies);
dev_err(gc05a2->dev, "failed to enable regulators: %d\n", ret);
ret = clk_prepare_enable(gc05a2->xclk);
gc05a2->supplies);
dev_err(gc05a2->dev, "clk prepare enable failed\n");
gpiod_set_value_cansleep(gc05a2->reset_gpio, 0);
struct gc05a2 *gc05a2 = to_gc05a2(sd);
clk_disable_unprepare(gc05a2->xclk);
gpiod_set_value_cansleep(gc05a2->reset_gpio, 1);
gc05a2->supplies);
static int gc05a2_update_cur_mode_controls(struct gc05a2 *gc05a2,
ret = __v4l2_ctrl_modify_range(gc05a2->vblank,
dev_err(gc05a2->dev, "VB ctrl range update failed\n");
ret = __v4l2_ctrl_modify_range(gc05a2->hblank, h_blank, h_blank, 1,
dev_err(gc05a2->dev, "HB ctrl range update failed\n");
ret = __v4l2_ctrl_modify_range(gc05a2->exposure, GC05A2_EXP_MIN,
dev_err(gc05a2->dev, "exposure ctrl range update failed\n");
static void gc05a2_update_pad_format(struct gc05a2 *gc08a3,
struct gc05a2 *gc05a2 = to_gc05a2(sd);
gc05a2_update_pad_format(gc05a2, mode, &fmt->format);
gc05a2->cur_mode = mode;
gc05a2_update_cur_mode_controls(gc05a2, mode);
static int gc05a2_set_ctrl_hflip(struct gc05a2 *gc05a2, u32 ctrl_val)
ret = cci_read(gc05a2->regmap, GC05A2_FLIP_REG, &val, NULL);
dev_err(gc05a2->dev, "read hflip register failed: %d\n", ret);
return cci_update_bits(gc05a2->regmap, GC05A2_FLIP_REG,
static int gc05a2_set_ctrl_vflip(struct gc05a2 *gc05a2, u32 ctrl_val)
ret = cci_read(gc05a2->regmap, GC05A2_FLIP_REG, &val, NULL);
dev_err(gc05a2->dev, "read vflip register failed: %d\n", ret);
return cci_update_bits(gc05a2->regmap, GC05A2_FLIP_REG,
static int gc05a2_test_pattern(struct gc05a2 *gc05a2, u32 pattern_menu)
ret = cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_IDX,
return cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_EN,
return cci_write(gc05a2->regmap, GC05A2_REG_TEST_PATTERN_EN,
struct gc05a2 *gc05a2 =
container_of(ctrl->handler, struct gc05a2, ctrls);
state = v4l2_subdev_get_locked_active_state(&gc05a2->sd);
__v4l2_ctrl_modify_range(gc05a2->exposure,
gc05a2->exposure->minimum,
exposure_max, gc05a2->exposure->step,
if (!pm_runtime_get_if_active(gc05a2->dev))
ret = cci_write(gc05a2->regmap, GC05A2_EXP_REG,
ret = cci_write(gc05a2->regmap, GC05A2_AGAIN_REG,
ret = cci_write(gc05a2->regmap, GC05A2_FRAME_LENGTH_REG,
gc05a2->cur_mode->height + ctrl->val, NULL);
ret = gc05a2_set_ctrl_hflip(gc05a2, ctrl->val);
ret = gc05a2_set_ctrl_vflip(gc05a2, ctrl->val);
ret = gc05a2_test_pattern(gc05a2, ctrl->val);
pm_runtime_put(gc05a2->dev);
static int gc05a2_identify_module(struct gc05a2 *gc05a2)
if (gc05a2->identified)
ret = cci_read(gc05a2->regmap, GC05A2_REG_CHIP_ID, &val, NULL);
dev_err(gc05a2->dev, "chip id mismatch: 0x%x!=0x%llx",
gc05a2->identified = true;
static int gc05a2_start_streaming(struct gc05a2 *gc05a2)
ret = pm_runtime_resume_and_get(gc05a2->dev);
ret = gc05a2_identify_module(gc05a2);
ret = cci_multi_reg_write(gc05a2->regmap,
mode = gc05a2->cur_mode;
ret = cci_multi_reg_write(gc05a2->regmap,