drivers/media/i2c/ov64a40.c
2857
static inline struct ov64a40 *sd_to_ov64a40(struct v4l2_subdev *sd)
drivers/media/i2c/ov64a40.c
2859
return container_of_const(sd, struct ov64a40, sd);
drivers/media/i2c/ov64a40.c
2863
ov64a40_get_timings(struct ov64a40 *ov64a40, unsigned int link_freq_index)
drivers/media/i2c/ov64a40.c
2865
s64 link_freq = ov64a40->link_frequencies[link_freq_index];
drivers/media/i2c/ov64a40.c
2870
return &ov64a40->mode->timings_default[timings_index];
drivers/media/i2c/ov64a40.c
2873
static int ov64a40_program_geometry(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
2875
struct ov64a40_mode *mode = ov64a40->mode;
drivers/media/i2c/ov64a40.c
2882
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL0,
drivers/media/i2c/ov64a40.c
2884
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL2,
drivers/media/i2c/ov64a40.c
2886
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL4,
drivers/media/i2c/ov64a40.c
2888
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL6,
drivers/media/i2c/ov64a40.c
2892
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL10,
drivers/media/i2c/ov64a40.c
2894
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL12,
drivers/media/i2c/ov64a40.c
2896
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL8,
drivers/media/i2c/ov64a40.c
2898
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLA,
drivers/media/i2c/ov64a40.c
2902
timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val);
drivers/media/i2c/ov64a40.c
2903
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLC, timings->ppl, &ret);
drivers/media/i2c/ov64a40.c
2904
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLE, timings->vts, &ret);
drivers/media/i2c/ov64a40.c
2909
static int ov64a40_program_subsampling(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
2911
struct ov64a40_subsampling *subsampling = &ov64a40->mode->subsampling;
drivers/media/i2c/ov64a40.c
2915
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL14,
drivers/media/i2c/ov64a40.c
2918
cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL15,
drivers/media/i2c/ov64a40.c
2923
cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20,
drivers/media/i2c/ov64a40.c
2927
cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21,
drivers/media/i2c/ov64a40.c
2935
static int ov64a40_start_streaming(struct ov64a40 *ov64a40,
drivers/media/i2c/ov64a40.c
2938
const struct ov64a40_reglist *reglist = &ov64a40->mode->reglist;
drivers/media/i2c/ov64a40.c
2943
ret = pm_runtime_resume_and_get(ov64a40->dev);
drivers/media/i2c/ov64a40.c
2947
ret = cci_multi_reg_write(ov64a40->cci, ov64a40_init,
drivers/media/i2c/ov64a40.c
2952
ret = cci_multi_reg_write(ov64a40->cci, reglist->regvals,
drivers/media/i2c/ov64a40.c
2957
ret = ov64a40_program_geometry(ov64a40);
drivers/media/i2c/ov64a40.c
2961
ret = ov64a40_program_subsampling(ov64a40);
drivers/media/i2c/ov64a40.c
2965
ret = __v4l2_ctrl_handler_setup(&ov64a40->ctrl_handler);
drivers/media/i2c/ov64a40.c
2969
ret = cci_write(ov64a40->cci, OV64A40_REG_SMIA,
drivers/media/i2c/ov64a40.c
2975
__v4l2_ctrl_grab(ov64a40->link_freq, true);
drivers/media/i2c/ov64a40.c
2976
__v4l2_ctrl_grab(ov64a40->vflip, true);
drivers/media/i2c/ov64a40.c
2977
__v4l2_ctrl_grab(ov64a40->hflip, true);
drivers/media/i2c/ov64a40.c
2980
timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val);
drivers/media/i2c/ov64a40.c
2985
delay += DIV_ROUND_UP(timings->ppl * 4 * ov64a40->exposure->cur.val,
drivers/media/i2c/ov64a40.c
2992
pm_runtime_put_autosuspend(ov64a40->dev);
drivers/media/i2c/ov64a40.c
2997
static int ov64a40_stop_streaming(struct ov64a40 *ov64a40,
drivers/media/i2c/ov64a40.c
3000
cci_update_bits(ov64a40->cci, OV64A40_REG_SMIA, BIT(0), 0, NULL);
drivers/media/i2c/ov64a40.c
3001
pm_runtime_put_autosuspend(ov64a40->dev);
drivers/media/i2c/ov64a40.c
3003
__v4l2_ctrl_grab(ov64a40->link_freq, false);
drivers/media/i2c/ov64a40.c
3004
__v4l2_ctrl_grab(ov64a40->vflip, false);
drivers/media/i2c/ov64a40.c
3005
__v4l2_ctrl_grab(ov64a40->hflip, false);
drivers/media/i2c/ov64a40.c
3012
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3018
ret = ov64a40_start_streaming(ov64a40, state);
drivers/media/i2c/ov64a40.c
3020
ret = ov64a40_stop_streaming(ov64a40, state);
drivers/media/i2c/ov64a40.c
3030
static u32 ov64a40_mbus_code(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3032
unsigned int index = ov64a40->hflip->val << 1 | ov64a40->vflip->val;
drivers/media/i2c/ov64a40.c
3037
static void ov64a40_update_pad_fmt(struct ov64a40 *ov64a40,
drivers/media/i2c/ov64a40.c
3041
fmt->code = ov64a40_mbus_code(ov64a40);
drivers/media/i2c/ov64a40.c
3054
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3059
ov64a40_update_pad_fmt(ov64a40, &ov64a40_modes[0], format);
drivers/media/i2c/ov64a40.c
3074
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3079
code->code = ov64a40_mbus_code(ov64a40);
drivers/media/i2c/ov64a40.c
3088
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3095
code = ov64a40_mbus_code(ov64a40);
drivers/media/i2c/ov64a40.c
3143
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3152
ov64a40_update_pad_fmt(ov64a40, mode, &fmt->format);
drivers/media/i2c/ov64a40.c
3155
if (ov64a40->mode == mode && format->code == fmt->format.code)
drivers/media/i2c/ov64a40.c
3164
ov64a40->mode = mode;
drivers/media/i2c/ov64a40.c
3168
timings = ov64a40_get_timings(ov64a40,
drivers/media/i2c/ov64a40.c
3169
ov64a40->link_freq->cur.val);
drivers/media/i2c/ov64a40.c
3172
__v4l2_ctrl_modify_range(ov64a40->vblank, OV64A40_VBLANK_MIN,
drivers/media/i2c/ov64a40.c
3174
__v4l2_ctrl_s_ctrl(ov64a40->vblank, vblank_def);
drivers/media/i2c/ov64a40.c
3177
__v4l2_ctrl_modify_range(ov64a40->exposure,
drivers/media/i2c/ov64a40.c
3182
__v4l2_ctrl_modify_range(ov64a40->hblank,
drivers/media/i2c/ov64a40.c
3211
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3214
ret = clk_prepare_enable(ov64a40->xclk);
drivers/media/i2c/ov64a40.c
3219
ov64a40->supplies);
drivers/media/i2c/ov64a40.c
3221
clk_disable_unprepare(ov64a40->xclk);
drivers/media/i2c/ov64a40.c
3226
gpiod_set_value_cansleep(ov64a40->reset_gpio, 0);
drivers/media/i2c/ov64a40.c
3236
struct ov64a40 *ov64a40 = sd_to_ov64a40(sd);
drivers/media/i2c/ov64a40.c
3238
gpiod_set_value_cansleep(ov64a40->reset_gpio, 1);
drivers/media/i2c/ov64a40.c
3240
ov64a40->supplies);
drivers/media/i2c/ov64a40.c
3241
clk_disable_unprepare(ov64a40->xclk);
drivers/media/i2c/ov64a40.c
3246
static int ov64a40_link_freq_config(struct ov64a40 *ov64a40, int link_freq_id)
drivers/media/i2c/ov64a40.c
3252
cci_multi_reg_write(ov64a40->cci, ov64a40_pll_config,
drivers/media/i2c/ov64a40.c
3256
link_frequency = ov64a40->link_frequencies[link_freq_id];
drivers/media/i2c/ov64a40.c
3258
cci_write(ov64a40->cci, OV64A40_PLL1_MULTIPLIER, 0x0078, &ret);
drivers/media/i2c/ov64a40.c
3265
struct ov64a40 *ov64a40 = container_of(ctrl->handler, struct ov64a40,
drivers/media/i2c/ov64a40.c
3271
int exp_max = ov64a40->mode->height + ctrl->val
drivers/media/i2c/ov64a40.c
3273
int exp_val = min(ov64a40->exposure->cur.val, exp_max);
drivers/media/i2c/ov64a40.c
3275
__v4l2_ctrl_modify_range(ov64a40->exposure,
drivers/media/i2c/ov64a40.c
3276
ov64a40->exposure->minimum,
drivers/media/i2c/ov64a40.c
3280
pm_status = pm_runtime_get_if_active(ov64a40->dev);
drivers/media/i2c/ov64a40.c
3286
ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_EXPO,
drivers/media/i2c/ov64a40.c
3290
ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_GAIN,
drivers/media/i2c/ov64a40.c
3294
int vts = ctrl->val + ov64a40->mode->height;
drivers/media/i2c/ov64a40.c
3296
cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_LOW, vts, &ret);
drivers/media/i2c/ov64a40.c
3297
cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_MID,
drivers/media/i2c/ov64a40.c
3299
cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_HIGH,
drivers/media/i2c/ov64a40.c
3304
ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20,
drivers/media/i2c/ov64a40.c
3310
ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21,
drivers/media/i2c/ov64a40.c
3317
ret = cci_write(ov64a40->cci, OV64A40_REG_TEST_PATTERN,
drivers/media/i2c/ov64a40.c
3321
ret = ov64a40_link_freq_config(ov64a40, ctrl->val);
drivers/media/i2c/ov64a40.c
3324
dev_err(ov64a40->dev, "Unhandled control: %#x\n", ctrl->id);
drivers/media/i2c/ov64a40.c
3330
pm_runtime_put_autosuspend(ov64a40->dev);
drivers/media/i2c/ov64a40.c
3339
static int ov64a40_init_controls(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3342
struct v4l2_ctrl_handler *hdlr = &ov64a40->ctrl_handler;
drivers/media/i2c/ov64a40.c
3355
ov64a40->link_freq =
drivers/media/i2c/ov64a40.c
3358
ov64a40->num_link_frequencies - 1,
drivers/media/i2c/ov64a40.c
3359
0, ov64a40->link_frequencies);
drivers/media/i2c/ov64a40.c
3366
timings = ov64a40_get_timings(ov64a40, 0);
drivers/media/i2c/ov64a40.c
3368
ov64a40->exposure = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3373
hblank_val = timings->ppl * 4 - ov64a40->mode->width;
drivers/media/i2c/ov64a40.c
3374
ov64a40->hblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3377
if (ov64a40->hblank)
drivers/media/i2c/ov64a40.c
3378
ov64a40->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
drivers/media/i2c/ov64a40.c
3380
vblank_def = timings->vts - ov64a40->mode->height;
drivers/media/i2c/ov64a40.c
3381
vblank_max = OV64A40_VTS_MAX - ov64a40->mode->height;
drivers/media/i2c/ov64a40.c
3382
ov64a40->vblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3390
ov64a40->hflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3392
if (ov64a40->hflip)
drivers/media/i2c/ov64a40.c
3393
ov64a40->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
drivers/media/i2c/ov64a40.c
3395
ov64a40->vflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops,
drivers/media/i2c/ov64a40.c
3397
if (ov64a40->vflip)
drivers/media/i2c/ov64a40.c
3398
ov64a40->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
drivers/media/i2c/ov64a40.c
3402
dev_err(ov64a40->dev, "control init failed: %d\n", ret);
drivers/media/i2c/ov64a40.c
3406
ret = v4l2_fwnode_device_parse(ov64a40->dev, &props);
drivers/media/i2c/ov64a40.c
3415
ov64a40->sd.ctrl_handler = hdlr;
drivers/media/i2c/ov64a40.c
3424
static int ov64a40_identify(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3429
ret = cci_read(ov64a40->cci, OV64A40_REG_CHIP_ID, &id, NULL);
drivers/media/i2c/ov64a40.c
3431
dev_err(ov64a40->dev, "Failed to read chip id: %d\n", ret);
drivers/media/i2c/ov64a40.c
3436
dev_err(ov64a40->dev, "chip id mismatch: %#llx\n", id);
drivers/media/i2c/ov64a40.c
3440
dev_dbg(ov64a40->dev, "OV64A40 chip identified: %#llx\n", id);
drivers/media/i2c/ov64a40.c
3445
static int ov64a40_parse_dt(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3454
endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(ov64a40->dev),
drivers/media/i2c/ov64a40.c
3457
dev_err(ov64a40->dev, "Failed to find endpoint\n");
drivers/media/i2c/ov64a40.c
3464
dev_err(ov64a40->dev, "Failed to parse endpoint\n");
drivers/media/i2c/ov64a40.c
3469
dev_err(ov64a40->dev, "Unsupported number of data lanes: %u\n",
drivers/media/i2c/ov64a40.c
3476
dev_warn(ov64a40->dev, "no link frequencies defined\n");
drivers/media/i2c/ov64a40.c
3482
dev_warn(ov64a40->dev,
drivers/media/i2c/ov64a40.c
3488
ov64a40->link_frequencies =
drivers/media/i2c/ov64a40.c
3489
devm_kcalloc(ov64a40->dev, v4l2_fwnode.nr_of_link_frequencies,
drivers/media/i2c/ov64a40.c
3492
if (!ov64a40->link_frequencies) {
drivers/media/i2c/ov64a40.c
3496
ov64a40->num_link_frequencies = v4l2_fwnode.nr_of_link_frequencies;
drivers/media/i2c/ov64a40.c
3501
dev_err(ov64a40->dev,
drivers/media/i2c/ov64a40.c
3508
ov64a40->link_frequencies[i] = v4l2_fwnode.link_frequencies[i];
drivers/media/i2c/ov64a40.c
3516
static int ov64a40_get_regulators(struct ov64a40 *ov64a40)
drivers/media/i2c/ov64a40.c
3518
struct i2c_client *client = v4l2_get_subdevdata(&ov64a40->sd);
drivers/media/i2c/ov64a40.c
3522
ov64a40->supplies[i].supply = ov64a40_supply_names[i];
drivers/media/i2c/ov64a40.c
3526
ov64a40->supplies);
drivers/media/i2c/ov64a40.c
3531
struct ov64a40 *ov64a40;
drivers/media/i2c/ov64a40.c
3535
ov64a40 = devm_kzalloc(&client->dev, sizeof(*ov64a40), GFP_KERNEL);
drivers/media/i2c/ov64a40.c
3536
if (!ov64a40)
drivers/media/i2c/ov64a40.c
3539
ov64a40->dev = &client->dev;
drivers/media/i2c/ov64a40.c
3540
v4l2_i2c_subdev_init(&ov64a40->sd, client, &ov64a40_subdev_ops);
drivers/media/i2c/ov64a40.c
3542
ov64a40->cci = devm_cci_regmap_init_i2c(client, 16);
drivers/media/i2c/ov64a40.c
3543
if (IS_ERR(ov64a40->cci)) {
drivers/media/i2c/ov64a40.c
3545
return PTR_ERR(ov64a40->cci);
drivers/media/i2c/ov64a40.c
3548
ov64a40->xclk = devm_v4l2_sensor_clk_get(&client->dev, NULL);
drivers/media/i2c/ov64a40.c
3549
if (IS_ERR(ov64a40->xclk))
drivers/media/i2c/ov64a40.c
3550
return dev_err_probe(&client->dev, PTR_ERR(ov64a40->xclk),
drivers/media/i2c/ov64a40.c
3553
xclk_freq = clk_get_rate(ov64a40->xclk);
drivers/media/i2c/ov64a40.c
3560
ret = ov64a40_get_regulators(ov64a40);
drivers/media/i2c/ov64a40.c
3564
ov64a40->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
drivers/media/i2c/ov64a40.c
3566
if (IS_ERR(ov64a40->reset_gpio))
drivers/media/i2c/ov64a40.c
3567
return dev_err_probe(&client->dev, PTR_ERR(ov64a40->reset_gpio),
drivers/media/i2c/ov64a40.c
3570
ret = ov64a40_parse_dt(ov64a40);
drivers/media/i2c/ov64a40.c
3578
ret = ov64a40_identify(ov64a40);
drivers/media/i2c/ov64a40.c
3582
ov64a40->mode = &ov64a40_modes[0];
drivers/media/i2c/ov64a40.c
3590
ret = ov64a40_init_controls(ov64a40);
drivers/media/i2c/ov64a40.c
3595
ov64a40->sd.internal_ops = &ov64a40_internal_ops;
drivers/media/i2c/ov64a40.c
3596
ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
drivers/media/i2c/ov64a40.c
3597
ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
drivers/media/i2c/ov64a40.c
3599
ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE;
drivers/media/i2c/ov64a40.c
3600
ret = media_entity_pads_init(&ov64a40->sd.entity, 1, &ov64a40->pad);
drivers/media/i2c/ov64a40.c
3606
ov64a40->sd.state_lock = ov64a40->ctrl_handler.lock;
drivers/media/i2c/ov64a40.c
3607
ret = v4l2_subdev_init_finalize(&ov64a40->sd);
drivers/media/i2c/ov64a40.c
3613
ret = v4l2_async_register_subdev_sensor(&ov64a40->sd);
drivers/media/i2c/ov64a40.c
3625
v4l2_subdev_cleanup(&ov64a40->sd);
drivers/media/i2c/ov64a40.c
3627
media_entity_cleanup(&ov64a40->sd.entity);
drivers/media/i2c/ov64a40.c
3629
v4l2_ctrl_handler_free(ov64a40->sd.ctrl_handler);