drivers/media/i2c/ov64a40.c
2858
static inline struct ov64a40 *sd_to_ov64a40(struct v4l2_subdev *sd)
drivers/media/i2c/ov64a40.c
2860
return container_of_const(sd, struct ov64a40, sd);
drivers/media/i2c/ov64a40.c
2864
ov64a40_get_timings(struct ov64a40 *ov64a40, unsigned int link_freq_index)
drivers/media/i2c/ov64a40.c
2866
s64 link_freq = ov64a40->link_frequencies[link_freq_index];
drivers/media/i2c/ov64a40.c
2871
return &ov64a40->mode->timings_default[timings_index];
drivers/media/i2c/ov64a40.c
2874
static int ov64a40_program_geometry(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
2876
struct ov64a40_mode *mode = ov64a40->mode;
drivers/media/i2c/ov64a40.c
2883
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL0,
drivers/media/i2c/ov64a40.c
2885
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL2,
drivers/media/i2c/ov64a40.c
2887
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL4,
drivers/media/i2c/ov64a40.c
2889
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL6,
drivers/media/i2c/ov64a40.c
2893
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL10,
drivers/media/i2c/ov64a40.c
2895
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL12,
drivers/media/i2c/ov64a40.c
2897
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL8,
drivers/media/i2c/ov64a40.c
2899
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLA,
drivers/media/i2c/ov64a40.c
2903
timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val);
drivers/media/i2c/ov64a40.c
2904
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLC, timings->ppl, &ret);
drivers/media/i2c/ov64a40.c
2905
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLE, timings->vts, &ret);
drivers/media/i2c/ov64a40.c
2910
static int ov64a40_program_subsampling(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
2912
struct ov64a40_subsampling *subsampling = &ov64a40->mode->subsampling;
drivers/media/i2c/ov64a40.c
2916
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL14,
drivers/media/i2c/ov64a40.c
2919
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL15,
drivers/media/i2c/ov64a40.c
2924
cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20,
drivers/media/i2c/ov64a40.c
2928
cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21,
drivers/media/i2c/ov64a40.c
2936
static int ov64a40_start_streaming(struct ov64a40 *ov64a40,
drivers/media/i2c/ov64a40.c
2939
const struct ov64a40_reglist *reglist = &ov64a40->mode->reglist;
drivers/media/i2c/ov64a40.c
2944
ret = pm_runtime_resume_and_get(ov64a40->dev);
drivers/media/i2c/ov64a40.c
2948
ret = cci_multi_reg_write(ov64a40->cci, ov64a40_init,
drivers/media/i2c/ov64a40.c
2953
ret = cci_multi_reg_write(ov64a40->cci, reglist->regvals,
drivers/media/i2c/ov64a40.c
2958
ret = ov64a40_program_geometry(ov64a40);
drivers/media/i2c/ov64a40.c
2962
ret = ov64a40_program_subsampling(ov64a40);
drivers/media/i2c/ov64a40.c
2966
ret = __v4l2_ctrl_handler_setup(&ov64a40->ctrl_handler);
drivers/media/i2c/ov64a40.c
2970
ret = cci_write(ov64a40->cci, OV64A40_REG_SMIA,
drivers/media/i2c/ov64a40.c
2976
__v4l2_ctrl_grab(ov64a40->link_freq, true);
drivers/media/i2c/ov64a40.c
2977
__v4l2_ctrl_grab(ov64a40->vflip, true);
drivers/media/i2c/ov64a40.c
2978
__v4l2_ctrl_grab(ov64a40->hflip, true);
drivers/media/i2c/ov64a40.c
2981
timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val);
drivers/media/i2c/ov64a40.c
2986
delay += DIV_ROUND_UP(timings->ppl * 4 * ov64a40->exposure->cur.val,
drivers/media/i2c/ov64a40.c
2993
pm_runtime_put_autosuspend(ov64a40->dev);
drivers/media/i2c/ov64a40.c
2998
static int ov64a40_stop_streaming(struct ov64a40 *ov64a40,
drivers/media/i2c/ov64a40.c
3001
cci_update_bits(ov64a40->cci, OV64A40_REG_SMIA, BIT(0), 0, NULL);
drivers/media/i2c/ov64a40.c
3002
pm_runtime_put_autosuspend(ov64a40->dev);
drivers/media/i2c/ov64a40.c
3004
__v4l2_ctrl_grab(ov64a40->link_freq, false);
drivers/media/i2c/ov64a40.c
3005
__v4l2_ctrl_grab(ov64a40->vflip, false);
drivers/media/i2c/ov64a40.c
3006
__v4l2_ctrl_grab(ov64a40->hflip, false);
drivers/media/i2c/ov64a40.c
3013
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3019
ret = ov64a40_start_streaming(ov64a40, state);
drivers/media/i2c/ov64a40.c
3021
ret = ov64a40_stop_streaming(ov64a40, state);
drivers/media/i2c/ov64a40.c
3031
static u32 ov64a40_mbus_code(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3033
unsigned int index = ov64a40->hflip->val << 1 | ov64a40->vflip->val;
drivers/media/i2c/ov64a40.c
3038
static void ov64a40_update_pad_fmt(struct ov64a40 *ov64a40,
drivers/media/i2c/ov64a40.c
3042
fmt->code = ov64a40_mbus_code(ov64a40);
drivers/media/i2c/ov64a40.c
3055
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3060
ov64a40_update_pad_fmt(ov64a40, &ov64a40_modes[0], format);
drivers/media/i2c/ov64a40.c
3075
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3080
code->code = ov64a40_mbus_code(ov64a40);
drivers/media/i2c/ov64a40.c
3089
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3096
code = ov64a40_mbus_code(ov64a40);
drivers/media/i2c/ov64a40.c
3144
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3153
ov64a40_update_pad_fmt(ov64a40, mode, &fmt->format);
drivers/media/i2c/ov64a40.c
3156
if (ov64a40->mode == mode && format->code == fmt->format.code)
drivers/media/i2c/ov64a40.c
3165
ov64a40->mode = mode;
drivers/media/i2c/ov64a40.c
3169
timings = ov64a40_get_timings(ov64a40,
drivers/media/i2c/ov64a40.c
3170
ov64a40->link_freq->cur.val);
drivers/media/i2c/ov64a40.c
3173
__v4l2_ctrl_modify_range(ov64a40->vblank, OV64A40_VBLANK_MIN,
drivers/media/i2c/ov64a40.c
3175
__v4l2_ctrl_s_ctrl(ov64a40->vblank, vblank_def);
drivers/media/i2c/ov64a40.c
3178
__v4l2_ctrl_modify_range(ov64a40->exposure,
drivers/media/i2c/ov64a40.c
3183
__v4l2_ctrl_modify_range(ov64a40->hblank,
drivers/media/i2c/ov64a40.c
3212
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3215
ret = clk_prepare_enable(ov64a40->xclk);
drivers/media/i2c/ov64a40.c
3220
ov64a40->supplies);
drivers/media/i2c/ov64a40.c
3222
clk_disable_unprepare(ov64a40->xclk);
drivers/media/i2c/ov64a40.c
3227
gpiod_set_value_cansleep(ov64a40->reset_gpio, 0);
drivers/media/i2c/ov64a40.c
3237
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3239
gpiod_set_value_cansleep(ov64a40->reset_gpio, 1);
drivers/media/i2c/ov64a40.c
3241
ov64a40->supplies);
drivers/media/i2c/ov64a40.c
3242
clk_disable_unprepare(ov64a40->xclk);
drivers/media/i2c/ov64a40.c
3247
static int ov64a40_link_freq_config(struct ov64a40 *ov64a40, int link_freq_id)
drivers/media/i2c/ov64a40.c
3253
cci_multi_reg_write(ov64a40->cci, ov64a40_pll_config,
drivers/media/i2c/ov64a40.c
3257
link_frequency = ov64a40->link_frequencies[link_freq_id];
drivers/media/i2c/ov64a40.c
3259
cci_write(ov64a40->cci, OV64A40_PLL1_MULTIPLIER, 0x0078, &ret);
drivers/media/i2c/ov64a40.c
3266
struct ov64a40 *ov64a40 = container_of(ctrl->handler, struct ov64a40,
drivers/media/i2c/ov64a40.c
3272
int exp_max = ov64a40->mode->height + ctrl->val
drivers/media/i2c/ov64a40.c
3274
int exp_val = min(ov64a40->exposure->cur.val, exp_max);
drivers/media/i2c/ov64a40.c
3276
__v4l2_ctrl_modify_range(ov64a40->exposure,
drivers/media/i2c/ov64a40.c
3277
ov64a40->exposure->minimum,
drivers/media/i2c/ov64a40.c
3281
pm_status = pm_runtime_get_if_active(ov64a40->dev);
drivers/media/i2c/ov64a40.c
3287
ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_EXPO,
drivers/media/i2c/ov64a40.c
3291
ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_GAIN,
drivers/media/i2c/ov64a40.c
3295
int vts = ctrl->val + ov64a40->mode->height;
drivers/media/i2c/ov64a40.c
3297
cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_LOW, vts, &ret);
drivers/media/i2c/ov64a40.c
3298
cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_MID,
drivers/media/i2c/ov64a40.c
3300
cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_HIGH,
drivers/media/i2c/ov64a40.c
3305
ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20,
drivers/media/i2c/ov64a40.c
3311
ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21,
drivers/media/i2c/ov64a40.c
3318
ret = cci_write(ov64a40->cci, OV64A40_REG_TEST_PATTERN,
drivers/media/i2c/ov64a40.c
3322
ret = ov64a40_link_freq_config(ov64a40, ctrl->val);
drivers/media/i2c/ov64a40.c
3325
dev_err(ov64a40->dev, "Unhandled control: %#x\n", ctrl->id);
drivers/media/i2c/ov64a40.c
3331
pm_runtime_put_autosuspend(ov64a40->dev);
drivers/media/i2c/ov64a40.c
3340
static int ov64a40_init_controls(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3343
struct v4l2_ctrl_handler *hdlr = &ov64a40->ctrl_handler;
drivers/media/i2c/ov64a40.c
3356
ov64a40->link_freq =
drivers/media/i2c/ov64a40.c
3359
ov64a40->num_link_frequencies - 1,
drivers/media/i2c/ov64a40.c
3360
0, ov64a40->link_frequencies);
drivers/media/i2c/ov64a40.c
3367
timings = ov64a40_get_timings(ov64a40, 0);
drivers/media/i2c/ov64a40.c
3369
ov64a40->exposure = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3374
hblank_val = timings->ppl * 4 - ov64a40->mode->width;
drivers/media/i2c/ov64a40.c
3375
ov64a40->hblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3378
if (ov64a40->hblank)
drivers/media/i2c/ov64a40.c
3379
ov64a40->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
drivers/media/i2c/ov64a40.c
3381
vblank_def = timings->vts - ov64a40->mode->height;
drivers/media/i2c/ov64a40.c
3382
vblank_max = OV64A40_VTS_MAX - ov64a40->mode->height;
drivers/media/i2c/ov64a40.c
3383
ov64a40->vblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3391
ov64a40->hflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3393
if (ov64a40->hflip)
drivers/media/i2c/ov64a40.c
3394
ov64a40->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
drivers/media/i2c/ov64a40.c
3396
ov64a40->vflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3398
if (ov64a40->vflip)
drivers/media/i2c/ov64a40.c
3399
ov64a40->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
drivers/media/i2c/ov64a40.c
3403
dev_err(ov64a40->dev, "control init failed: %d\n", ret);
drivers/media/i2c/ov64a40.c
3407
ret = v4l2_fwnode_device_parse(ov64a40->dev, &props);
drivers/media/i2c/ov64a40.c
3416
ov64a40->sd.ctrl_handler = hdlr;
drivers/media/i2c/ov64a40.c
3425
static int ov64a40_identify(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3430
ret = cci_read(ov64a40->cci, OV64A40_REG_CHIP_ID, &id, NULL);
drivers/media/i2c/ov64a40.c
3432
dev_err(ov64a40->dev, "Failed to read chip id: %d\n", ret);
drivers/media/i2c/ov64a40.c
3437
dev_err(ov64a40->dev, "chip id mismatch: %#llx\n", id);
drivers/media/i2c/ov64a40.c
3441
dev_dbg(ov64a40->dev, "OV64A40 chip identified: %#llx\n", id);
drivers/media/i2c/ov64a40.c
3446
static int ov64a40_parse_dt(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3455
endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(ov64a40->dev),
drivers/media/i2c/ov64a40.c
3458
dev_err(ov64a40->dev, "Failed to find endpoint\n");
drivers/media/i2c/ov64a40.c
3465
dev_err(ov64a40->dev, "Failed to parse endpoint\n");
drivers/media/i2c/ov64a40.c
3470
dev_err(ov64a40->dev, "Unsupported number of data lanes: %u\n",
drivers/media/i2c/ov64a40.c
3477
dev_warn(ov64a40->dev, "no link frequencies defined\n");
drivers/media/i2c/ov64a40.c
3483
dev_warn(ov64a40->dev,
drivers/media/i2c/ov64a40.c
3489
ov64a40->link_frequencies =
drivers/media/i2c/ov64a40.c
3490
devm_kcalloc(ov64a40->dev, v4l2_fwnode.nr_of_link_frequencies,
drivers/media/i2c/ov64a40.c
3493
if (!ov64a40->link_frequencies) {
drivers/media/i2c/ov64a40.c
3497
ov64a40->num_link_frequencies = v4l2_fwnode.nr_of_link_frequencies;
drivers/media/i2c/ov64a40.c
3502
dev_err(ov64a40->dev,
drivers/media/i2c/ov64a40.c
3509
ov64a40->link_frequencies[i] = v4l2_fwnode.link_frequencies[i];
drivers/media/i2c/ov64a40.c
3517
static int ov64a40_get_regulators(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3519
struct i2c_client *client = v4l2_get_subdevdata(&ov64a40->sd);
drivers/media/i2c/ov64a40.c
3523
ov64a40->supplies[i].supply = ov64a40_supply_names[i];
drivers/media/i2c/ov64a40.c
3527
ov64a40->supplies);
drivers/media/i2c/ov64a40.c
3532
struct ov64a40 *ov64a40;
drivers/media/i2c/ov64a40.c
3536
ov64a40 = devm_kzalloc(&client->dev, sizeof(*ov64a40), GFP_KERNEL);
drivers/media/i2c/ov64a40.c
3537
if (!ov64a40)
drivers/media/i2c/ov64a40.c
3540
ov64a40->dev = &client->dev;
drivers/media/i2c/ov64a40.c
3541
v4l2_i2c_subdev_init(&ov64a40->sd, client, &ov64a40_subdev_ops);
drivers/media/i2c/ov64a40.c
3543
ov64a40->cci = devm_cci_regmap_init_i2c(client, 16);
drivers/media/i2c/ov64a40.c
3544
if (IS_ERR(ov64a40->cci)) {
drivers/media/i2c/ov64a40.c
3546
return PTR_ERR(ov64a40->cci);
drivers/media/i2c/ov64a40.c
3549
ov64a40->xclk = devm_v4l2_sensor_clk_get(&client->dev, NULL);
drivers/media/i2c/ov64a40.c
3550
if (IS_ERR(ov64a40->xclk))
drivers/media/i2c/ov64a40.c
3551
return dev_err_probe(&client->dev, PTR_ERR(ov64a40->xclk),
drivers/media/i2c/ov64a40.c
3554
xclk_freq = clk_get_rate(ov64a40->xclk);
drivers/media/i2c/ov64a40.c
3561
ret = ov64a40_get_regulators(ov64a40);
drivers/media/i2c/ov64a40.c
3565
ov64a40->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
drivers/media/i2c/ov64a40.c
3567
if (IS_ERR(ov64a40->reset_gpio))
drivers/media/i2c/ov64a40.c
3568
return dev_err_probe(&client->dev, PTR_ERR(ov64a40->reset_gpio),
drivers/media/i2c/ov64a40.c
3571
ret = ov64a40_parse_dt(ov64a40);
drivers/media/i2c/ov64a40.c
3579
ret = ov64a40_identify(ov64a40);
drivers/media/i2c/ov64a40.c
3583
ov64a40->mode = &ov64a40_modes[0];
drivers/media/i2c/ov64a40.c
3591
ret = ov64a40_init_controls(ov64a40);
drivers/media/i2c/ov64a40.c
3596
ov64a40->sd.internal_ops = &ov64a40_internal_ops;
drivers/media/i2c/ov64a40.c
3597
ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
drivers/media/i2c/ov64a40.c
3598
ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
drivers/media/i2c/ov64a40.c
3600
ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE;
drivers/media/i2c/ov64a40.c
3601
ret = media_entity_pads_init(&ov64a40->sd.entity, 1, &ov64a40->pad);
drivers/media/i2c/ov64a40.c
3607
ov64a40->sd.state_lock = ov64a40->ctrl_handler.lock;
drivers/media/i2c/ov64a40.c
3608
ret = v4l2_subdev_init_finalize(&ov64a40->sd);
drivers/media/i2c/ov64a40.c
3614
ret = v4l2_async_register_subdev_sensor(&ov64a40->sd);
drivers/media/i2c/ov64a40.c
3626
v4l2_subdev_cleanup(&ov64a40->sd);
drivers/media/i2c/ov64a40.c
3628
media_entity_cleanup(&ov64a40->sd.entity);
drivers/media/i2c/ov64a40.c
3630
v4l2_ctrl_handler_free(ov64a40->sd.ctrl_handler);