media: ov08x40: Modify the tline calculation in different modes
ov08x40 quad bayer sensor ISP has the following work modes: - normal mode: full size - 2x2 binned mode: binning size In normal and binned modes, different tline calculations are applied. - normal mode: Tline value needs to be doubled as per the vendor's update. Tline time = 2 * HTS / SCLK Exposure unit : 1 * HTS = 0.5 Tline - 2x2 binned mode: Tline time = 1 * HTS / SCLK Exposure unit : 1 * HTS = 1 Tline Signed-off-by: Jason Chen <jason.z.chen@intel.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
parent
b1a42fde6e
commit
eea8f730df
@ -34,7 +34,7 @@
|
||||
|
||||
/* V_TIMING internal */
|
||||
#define OV08X40_REG_VTS 0x380e
|
||||
#define OV08X40_VTS_30FPS 0x1388
|
||||
#define OV08X40_VTS_30FPS 0x09c4 /* the VTS need to be half in normal mode */
|
||||
#define OV08X40_VTS_BIN_30FPS 0x115c
|
||||
#define OV08X40_VTS_MAX 0x7fff
|
||||
|
||||
@ -44,8 +44,9 @@
|
||||
|
||||
/* Exposure control */
|
||||
#define OV08X40_REG_EXPOSURE 0x3500
|
||||
#define OV08X40_EXPOSURE_MAX_MARGIN 31
|
||||
#define OV08X40_EXPOSURE_MIN 1
|
||||
#define OV08X40_EXPOSURE_MAX_MARGIN 8
|
||||
#define OV08X40_EXPOSURE_BIN_MAX_MARGIN 2
|
||||
#define OV08X40_EXPOSURE_MIN 4
|
||||
#define OV08X40_EXPOSURE_STEP 1
|
||||
#define OV08X40_EXPOSURE_DEFAULT 0x40
|
||||
|
||||
@ -126,13 +127,17 @@ struct ov08x40_mode {
|
||||
u32 vts_def;
|
||||
u32 vts_min;
|
||||
|
||||
/* HTS */
|
||||
u32 hts;
|
||||
/* Line Length Pixels */
|
||||
u32 llp;
|
||||
|
||||
/* Index of Link frequency config to be used */
|
||||
u32 link_freq_index;
|
||||
/* Default register values */
|
||||
struct ov08x40_reg_list reg_list;
|
||||
|
||||
/* Exposure calculation */
|
||||
u16 exposure_margin;
|
||||
u16 exposure_shift;
|
||||
};
|
||||
|
||||
static const struct ov08x40_reg mipi_data_rate_800mbps[] = {
|
||||
@ -2354,7 +2359,7 @@ static const char * const ov08x40_test_pattern_menu[] = {
|
||||
|
||||
/* Configurations for supported link frequencies */
|
||||
#define OV08X40_LINK_FREQ_400MHZ 400000000ULL
|
||||
|
||||
#define OV08X40_SCLK_96MHZ 96000000ULL
|
||||
#define OV08X40_EXT_CLK 19200000
|
||||
#define OV08X40_DATA_LANES 4
|
||||
|
||||
@ -2392,26 +2397,30 @@ static const struct ov08x40_mode supported_modes[] = {
|
||||
.height = 2416,
|
||||
.vts_def = OV08X40_VTS_30FPS,
|
||||
.vts_min = OV08X40_VTS_30FPS,
|
||||
.hts = 640,
|
||||
.llp = 0x10aa, /* in normal mode, tline time = 2 * HTS / SCLK */
|
||||
.lanes = 4,
|
||||
.reg_list = {
|
||||
.num_of_regs = ARRAY_SIZE(mode_3856x2416_regs),
|
||||
.regs = mode_3856x2416_regs,
|
||||
},
|
||||
.link_freq_index = OV08X40_LINK_FREQ_400MHZ_INDEX,
|
||||
.exposure_shift = 1,
|
||||
.exposure_margin = OV08X40_EXPOSURE_MAX_MARGIN,
|
||||
},
|
||||
{
|
||||
.width = 1928,
|
||||
.height = 1208,
|
||||
.vts_def = OV08X40_VTS_BIN_30FPS,
|
||||
.vts_min = OV08X40_VTS_BIN_30FPS,
|
||||
.hts = 720,
|
||||
.llp = 0x960,
|
||||
.lanes = 4,
|
||||
.reg_list = {
|
||||
.num_of_regs = ARRAY_SIZE(mode_1928x1208_regs),
|
||||
.regs = mode_1928x1208_regs,
|
||||
},
|
||||
.link_freq_index = OV08X40_LINK_FREQ_400MHZ_INDEX,
|
||||
.exposure_shift = 0,
|
||||
.exposure_margin = OV08X40_EXPOSURE_BIN_MAX_MARGIN,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2667,13 +2676,23 @@ static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
struct ov08x40, ctrl_handler);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
|
||||
s64 max;
|
||||
int exp;
|
||||
int fll;
|
||||
int ret = 0;
|
||||
|
||||
/* Propagate change of current control to all related controls */
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_VBLANK:
|
||||
/* Update max exposure while meeting expected vblanking */
|
||||
max = ov08x->cur_mode->height + ctrl->val - OV08X40_EXPOSURE_MAX_MARGIN;
|
||||
/*
|
||||
* because in normal mode, 1 HTS = 0.5 tline
|
||||
* fps = sclk / hts / vts
|
||||
* so the vts value needs to be double
|
||||
*/
|
||||
max = ((ov08x->cur_mode->height + ctrl->val) <<
|
||||
ov08x->cur_mode->exposure_shift) -
|
||||
ov08x->cur_mode->exposure_margin;
|
||||
|
||||
__v4l2_ctrl_modify_range(ov08x->exposure,
|
||||
ov08x->exposure->minimum,
|
||||
max, ov08x->exposure->step, max);
|
||||
@ -2697,15 +2716,20 @@ static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
ret = ov08x40_update_digital_gain(ov08x, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_EXPOSURE:
|
||||
exp = (ctrl->val << ov08x->cur_mode->exposure_shift) -
|
||||
ov08x->cur_mode->exposure_margin;
|
||||
|
||||
ret = ov08x40_write_reg(ov08x, OV08X40_REG_EXPOSURE,
|
||||
OV08X40_REG_VALUE_24BIT,
|
||||
ctrl->val);
|
||||
exp);
|
||||
break;
|
||||
case V4L2_CID_VBLANK:
|
||||
fll = ((ov08x->cur_mode->height + ctrl->val) <<
|
||||
ov08x->cur_mode->exposure_shift);
|
||||
|
||||
ret = ov08x40_write_reg(ov08x, OV08X40_REG_VTS,
|
||||
OV08X40_REG_VALUE_16BIT,
|
||||
ov08x->cur_mode->height
|
||||
+ ctrl->val);
|
||||
fll);
|
||||
break;
|
||||
case V4L2_CID_TEST_PATTERN:
|
||||
ret = ov08x40_enable_test_pattern(ov08x, ctrl->val);
|
||||
@ -2815,6 +2839,7 @@ ov08x40_set_pad_format(struct v4l2_subdev *sd,
|
||||
s64 h_blank;
|
||||
s64 pixel_rate;
|
||||
s64 link_freq;
|
||||
u64 steps;
|
||||
|
||||
mutex_lock(&ov08x->mutex);
|
||||
|
||||
@ -2842,13 +2867,22 @@ ov08x40_set_pad_format(struct v4l2_subdev *sd,
|
||||
ov08x->cur_mode->height;
|
||||
vblank_min = ov08x->cur_mode->vts_min -
|
||||
ov08x->cur_mode->height;
|
||||
|
||||
/*
|
||||
* The frame length line should be aligned to a multiple of 4,
|
||||
* as provided by the sensor vendor, in normal mode.
|
||||
*/
|
||||
steps = mode->exposure_shift == 1 ? 4 : 1;
|
||||
|
||||
__v4l2_ctrl_modify_range(ov08x->vblank, vblank_min,
|
||||
OV08X40_VTS_MAX
|
||||
- ov08x->cur_mode->height,
|
||||
1,
|
||||
steps,
|
||||
vblank_def);
|
||||
__v4l2_ctrl_s_ctrl(ov08x->vblank, vblank_def);
|
||||
h_blank = ov08x->cur_mode->hts;
|
||||
|
||||
h_blank = ov08x->cur_mode->llp - ov08x->cur_mode->width;
|
||||
|
||||
__v4l2_ctrl_modify_range(ov08x->hblank, h_blank,
|
||||
h_blank, 1, h_blank);
|
||||
}
|
||||
@ -3043,7 +3077,8 @@ static int ov08x40_init_controls(struct ov08x40 *ov08x)
|
||||
OV08X40_VTS_MAX - mode->height, 1,
|
||||
vblank_def);
|
||||
|
||||
hblank = ov08x->cur_mode->hts;
|
||||
hblank = ov08x->cur_mode->llp - ov08x->cur_mode->width;
|
||||
|
||||
ov08x->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,
|
||||
V4L2_CID_HBLANK,
|
||||
hblank, hblank, 1, hblank);
|
||||
@ -3285,6 +3320,7 @@ static struct i2c_driver ov08x40_i2c_driver = {
|
||||
module_i2c_driver(ov08x40_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Jason Chen <jason.z.chen@intel.com>");
|
||||
MODULE_AUTHOR("Qingwu Zhang <qingwu.zhang@intel.com>");
|
||||
MODULE_AUTHOR("Shawn Tu");
|
||||
MODULE_DESCRIPTION("OmniVision OV08X40 sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Loading…
x
Reference in New Issue
Block a user