aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c/ov13858.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/ov13858.c')
-rw-r--r--drivers/media/i2c/ov13858.c101
1 files changed, 59 insertions, 42 deletions
diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c
index 86550d8ddfee..af7af0d14c69 100644
--- a/drivers/media/i2c/ov13858.c
+++ b/drivers/media/i2c/ov13858.c
@@ -57,16 +57,14 @@
#define OV13858_VTS_30FPS 0x0c8e /* 30 fps */
#define OV13858_VTS_60FPS 0x0648 /* 60 fps */
#define OV13858_VTS_MAX 0x7fff
-#define OV13858_VBLANK_MIN 56
/* HBLANK control - read only */
-#define OV13858_PPL_540MHZ 2244
-#define OV13858_PPL_1080MHZ 4488
+#define OV13858_PPL_270MHZ 2244
+#define OV13858_PPL_540MHZ 4488
/* Exposure control */
#define OV13858_REG_EXPOSURE 0x3500
#define OV13858_EXPOSURE_MIN 4
-#define OV13858_EXPOSURE_MAX (OV13858_VTS_MAX - 8)
#define OV13858_EXPOSURE_STEP 1
#define OV13858_EXPOSURE_DEFAULT 0x640
@@ -78,13 +76,13 @@
#define OV13858_ANA_GAIN_DEFAULT 0x80
/* Digital gain control */
-#define OV13858_REG_DIGITAL_GAIN 0x350a
-#define OV13858_DGTL_GAIN_MASK 0xf3
-#define OV13858_DGTL_GAIN_SHIFT 2
-#define OV13858_DGTL_GAIN_MIN 1
-#define OV13858_DGTL_GAIN_MAX 4
-#define OV13858_DGTL_GAIN_STEP 1
-#define OV13858_DGTL_GAIN_DEFAULT 1
+#define OV13858_REG_B_MWB_GAIN 0x5100
+#define OV13858_REG_G_MWB_GAIN 0x5102
+#define OV13858_REG_R_MWB_GAIN 0x5104
+#define OV13858_DGTL_GAIN_MIN 0
+#define OV13858_DGTL_GAIN_MAX 16384 /* Max = 16 X */
+#define OV13858_DGTL_GAIN_DEFAULT 1024 /* Default gain = 1 X */
+#define OV13858_DGTL_GAIN_STEP 1 /* Each step = 1/1024 */
/* Test Pattern Control */
#define OV13858_REG_TEST_PATTERN 0x4503
@@ -121,7 +119,8 @@ struct ov13858_mode {
u32 height;
/* V-timing */
- u32 vts;
+ u32 vts_def;
+ u32 vts_min;
/* Index of Link frequency config to be used */
u32 link_freq_index;
@@ -944,31 +943,33 @@ static const char * const ov13858_test_pattern_menu[] = {
/* Configurations for supported link frequencies */
#define OV13858_NUM_OF_LINK_FREQS 2
-#define OV13858_LINK_FREQ_1080MBPS 1080000000
-#define OV13858_LINK_FREQ_540MBPS 540000000
+#define OV13858_LINK_FREQ_540MHZ 540000000ULL
+#define OV13858_LINK_FREQ_270MHZ 270000000ULL
#define OV13858_LINK_FREQ_INDEX_0 0
#define OV13858_LINK_FREQ_INDEX_1 1
/* Menu items for LINK_FREQ V4L2 control */
static const s64 link_freq_menu_items[OV13858_NUM_OF_LINK_FREQS] = {
- OV13858_LINK_FREQ_1080MBPS,
- OV13858_LINK_FREQ_540MBPS
+ OV13858_LINK_FREQ_540MHZ,
+ OV13858_LINK_FREQ_270MHZ
};
/* Link frequency configs */
static const struct ov13858_link_freq_config
link_freq_configs[OV13858_NUM_OF_LINK_FREQS] = {
{
- .pixel_rate = 864000000,
- .pixels_per_line = OV13858_PPL_1080MHZ,
+ /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
+ .pixel_rate = (OV13858_LINK_FREQ_540MHZ * 2 * 4) / 10,
+ .pixels_per_line = OV13858_PPL_540MHZ,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mipi_data_rate_1080mbps),
.regs = mipi_data_rate_1080mbps,
}
},
{
- .pixel_rate = 432000000,
- .pixels_per_line = OV13858_PPL_540MHZ,
+ /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
+ .pixel_rate = (OV13858_LINK_FREQ_270MHZ * 2 * 4) / 10,
+ .pixels_per_line = OV13858_PPL_270MHZ,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mipi_data_rate_540mbps),
.regs = mipi_data_rate_540mbps,
@@ -981,7 +982,8 @@ static const struct ov13858_mode supported_modes[] = {
{
.width = 4224,
.height = 3136,
- .vts = OV13858_VTS_30FPS,
+ .vts_def = OV13858_VTS_30FPS,
+ .vts_min = OV13858_VTS_30FPS,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_4224x3136_regs),
.regs = mode_4224x3136_regs,
@@ -991,7 +993,8 @@ static const struct ov13858_mode supported_modes[] = {
{
.width = 2112,
.height = 1568,
- .vts = OV13858_VTS_30FPS,
+ .vts_def = OV13858_VTS_30FPS,
+ .vts_min = 1608,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2112x1568_regs),
.regs = mode_2112x1568_regs,
@@ -1001,7 +1004,8 @@ static const struct ov13858_mode supported_modes[] = {
{
.width = 2112,
.height = 1188,
- .vts = OV13858_VTS_30FPS,
+ .vts_def = OV13858_VTS_30FPS,
+ .vts_min = 1608,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2112x1188_regs),
.regs = mode_2112x1188_regs,
@@ -1011,7 +1015,8 @@ static const struct ov13858_mode supported_modes[] = {
{
.width = 1056,
.height = 784,
- .vts = OV13858_VTS_30FPS,
+ .vts_def = OV13858_VTS_30FPS,
+ .vts_min = 804,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1056x784_regs),
.regs = mode_1056x784_regs,
@@ -1161,21 +1166,21 @@ static int ov13858_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
static int ov13858_update_digital_gain(struct ov13858 *ov13858, u32 d_gain)
{
int ret;
- u32 val;
- if (d_gain == 3)
- return -EINVAL;
+ ret = ov13858_write_reg(ov13858, OV13858_REG_B_MWB_GAIN,
+ OV13858_REG_VALUE_16BIT, d_gain);
+ if (ret)
+ return ret;
- ret = ov13858_read_reg(ov13858, OV13858_REG_DIGITAL_GAIN,
- OV13858_REG_VALUE_08BIT, &val);
+ ret = ov13858_write_reg(ov13858, OV13858_REG_G_MWB_GAIN,
+ OV13858_REG_VALUE_16BIT, d_gain);
if (ret)
return ret;
- val &= OV13858_DGTL_GAIN_MASK;
- val |= (d_gain - 1) << OV13858_DGTL_GAIN_SHIFT;
+ ret = ov13858_write_reg(ov13858, OV13858_REG_R_MWB_GAIN,
+ OV13858_REG_VALUE_16BIT, d_gain);
- return ov13858_write_reg(ov13858, OV13858_REG_DIGITAL_GAIN,
- OV13858_REG_VALUE_08BIT, val);
+ return ret;
}
static int ov13858_enable_test_pattern(struct ov13858 *ov13858, u32 pattern)
@@ -1377,6 +1382,8 @@ ov13858_set_pad_format(struct v4l2_subdev *sd,
struct ov13858 *ov13858 = to_ov13858(sd);
const struct ov13858_mode *mode;
struct v4l2_mbus_framefmt *framefmt;
+ s32 vblank_def;
+ s32 vblank_min;
s64 h_blank;
mutex_lock(&ov13858->mutex);
@@ -1397,10 +1404,15 @@ ov13858_set_pad_format(struct v4l2_subdev *sd,
ov13858->pixel_rate,
link_freq_configs[mode->link_freq_index].pixel_rate);
/* Update limits and set FPS to default */
+ vblank_def = ov13858->cur_mode->vts_def -
+ ov13858->cur_mode->height;
+ vblank_min = ov13858->cur_mode->vts_min -
+ ov13858->cur_mode->height;
__v4l2_ctrl_modify_range(
- ov13858->vblank, OV13858_VBLANK_MIN,
+ ov13858->vblank, vblank_min,
OV13858_VTS_MAX - ov13858->cur_mode->height, 1,
- ov13858->cur_mode->vts - ov13858->cur_mode->height);
+ vblank_def);
+ __v4l2_ctrl_s_ctrl(ov13858->vblank, vblank_def);
h_blank =
link_freq_configs[mode->link_freq_index].pixels_per_line
- ov13858->cur_mode->width;
@@ -1602,6 +1614,9 @@ static int ov13858_init_controls(struct ov13858 *ov13858)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
struct v4l2_ctrl_handler *ctrl_hdlr;
+ s64 exposure_max;
+ s64 vblank_def;
+ s64 vblank_min;
int ret;
ctrl_hdlr = &ov13858->ctrl_handler;
@@ -1625,25 +1640,27 @@ static int ov13858_init_controls(struct ov13858 *ov13858)
link_freq_configs[0].pixel_rate, 1,
link_freq_configs[0].pixel_rate);
+ vblank_def = ov13858->cur_mode->vts_def - ov13858->cur_mode->height;
+ vblank_min = ov13858->cur_mode->vts_min - ov13858->cur_mode->height;
ov13858->vblank = v4l2_ctrl_new_std(
ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_VBLANK,
- OV13858_VBLANK_MIN,
+ vblank_min,
OV13858_VTS_MAX - ov13858->cur_mode->height, 1,
- ov13858->cur_mode->vts
- - ov13858->cur_mode->height);
+ vblank_def);
ov13858->hblank = v4l2_ctrl_new_std(
ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_HBLANK,
- OV13858_PPL_1080MHZ - ov13858->cur_mode->width,
- OV13858_PPL_1080MHZ - ov13858->cur_mode->width,
+ OV13858_PPL_540MHZ - ov13858->cur_mode->width,
+ OV13858_PPL_540MHZ - ov13858->cur_mode->width,
1,
- OV13858_PPL_1080MHZ - ov13858->cur_mode->width);
+ OV13858_PPL_540MHZ - ov13858->cur_mode->width);
ov13858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ exposure_max = ov13858->cur_mode->vts_def - 8;
ov13858->exposure = v4l2_ctrl_new_std(
ctrl_hdlr, &ov13858_ctrl_ops,
V4L2_CID_EXPOSURE, OV13858_EXPOSURE_MIN,
- OV13858_EXPOSURE_MAX, OV13858_EXPOSURE_STEP,
+ exposure_max, OV13858_EXPOSURE_STEP,
OV13858_EXPOSURE_DEFAULT);
v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,