...+
+struct ox05b1s_mode {
+ u32 index;
+ u32 width;
+ u32 height;
+ u32 code;
+ u32 bpp;
+ u32 vts; /* default VTS */
+ u32 hts; /* default HTS */
+ u32 exp; /* max exposure */
+ bool h_bin; /* horizontal binning */
+ u32 fps;
+ struct ox05b1s_reglist *reg_data;
+};
+
...+
+static struct ox05b1s_mode ox05b1s_supported_modes[] = {
+ {
+ .index = 0,
+ .width = 2592,
+ .height = 1944,
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .bpp = 10,
+ .vts = 0x850,
+ .hts = 0x2f0,
+ .exp = 0x850 - 8,
+ .h_bin = false,
+ .fps = 30,
+ .reg_data = ox05b1s_reglist_2592x1944,
+ }, {
+ /* sentinel */
+ }
+};
+
...+
+static int ox05b1s_set_vts(struct ox05b1s *sensor, u32 vts)
+{
+ u8 values[2] = { (u8)(vts >> 8) & 0xff, (u8)(vts & 0xff) };
+
+ return regmap_bulk_write(sensor->regmap, OX05B1S_REG_TIMING_VTS_H, values, 2);
+}
+
...+
+static int ox05b1s_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ox05b1s *sensor = client_to_ox05b1s(client);
+ u32 w = sensor->mode->width;
+ u32 h = sensor->mode->height;
+ int ret = 0;
+
+ /* apply V4L2 controls values only if power is already up */
+ if (!pm_runtime_get_if_in_use(&client->dev))
+ return 0;
+
+ /* s_ctrl holds sensor lock */
+ switch (ctrl->id) {
+ case V4L2_CID_VBLANK:
+ ret = ox05b1s_set_vts(sensor, h + ctrl->val);
+ break;
+ case V4L2_CID_HBLANK:
+ if (sensor->mode->h_bin)
+ ret = ox05b1s_set_hts(sensor, w + ctrl->val);
+ else
+ ret = ox05b1s_set_hts(sensor, (w + ctrl->val) / 2);
+ break;
+ case V4L2_CID_PIXEL_RATE:
+ /* Read-only, but we adjust it based on mode. */
+ break;
+ case V4L2_CID_ANALOGUE_GAIN:
+ ret = ox05b1s_set_analog_gain(sensor, ctrl->val);
+ break;
+ case V4L2_CID_EXPOSURE:
+ ret = ox05b1s_set_exp(sensor, ctrl->val);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ pm_runtime_put(&client->dev);
+
+ return ret;
+}
+
Yes, the frame rate will change, but the fps variable above won't. ItI'm not sure I understand.+Unless the sensor adjusts the pixel rate when you write the blanking
+/* Update control ranges based on current streaming mode, needs sensor lock */
+static int ox05b1s_update_controls(struct ox05b1s *sensor)
+{
+ int ret;
+ struct device *dev = &sensor->i2c_client->dev;
+ u32 hts = sensor->mode->hts;
+ u32 hblank;
+ u32 vts = sensor->mode->vts;
+ u32 vblank = vts - sensor->mode->height;
+ u32 fps = sensor->mode->fps;
+ u64 pixel_rate = (sensor->mode->h_bin) ? hts * vts * fps : 2 * hts * vts * fps;
registers, this doesn't seem correct.
The pixel_rate value calculated here is fixed per mode, as the
hts,vts,fps are the default values per mode.
The hblank is basically read-only (min=max value). If vblank is changed
by user, the frame rate will change, but the pixel_rate value will
remain the same.
will still be set to the default fps for the mode, while the actual
frame rate produced by the sensor will differ. The pixel rate
calculation here will therefore give an incorrect value.
Thanks, I'll add macros for the documented registers.The latter, using OX05B1S_REG_SW_STB here. I'd like a macro for eachDo you mean to add a define for all register numbers in the init list,+ {0x0100, 0x00},Please use register macros for the registers that are documented.
or just use the define in the init list, in case it was defined already
for other usages elsewhere in the code?
register in the init list, but macros such as OX05B1S_REG_0107 are
useless. Registers that are documented in the datasheet should be named
with macros, registers that are not can use numerical addresses and
values.