From 4ce81eae6fb73e399e69b2db94d85ab51e71e6ca Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 15 Oct 2024 16:05:57 +0100 Subject: [PATCH 1/4] media: i2c: ov5647: Tidy up mode registers to make the order common To make comparisons of the mode registers easier, put the registers for the binned and VGA modes in the same order as the others. Signed-off-by: Dave Stevenson --- drivers/media/i2c/ov5647.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 92e89def59dbe4..baf7a07687a2eb 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -344,6 +344,8 @@ static struct regval_list ov5647_2x2binned_10bpp[] = { {0x3036, 0x62}, {0x303c, 0x11}, {0x3106, 0xf5}, + {0x3821, 0x01}, + {0x3820, 0x41}, {0x3827, 0xec}, {0x370c, 0x03}, {0x3612, 0x59}, @@ -416,8 +418,6 @@ static struct regval_list ov5647_2x2binned_10bpp[] = { {0x4837, 0x16}, {0x4800, 0x24}, {0x3503, 0x03}, - {0x3820, 0x41}, - {0x3821, 0x01}, {0x350a, 0x00}, {0x350b, 0x10}, {0x3500, 0x00}, @@ -430,20 +430,27 @@ static struct regval_list ov5647_2x2binned_10bpp[] = { static struct regval_list ov5647_640x480_10bpp[] = { {0x0100, 0x00}, {0x0103, 0x01}, - {0x3035, 0x11}, + {0x3034, 0x1a}, + {0x3035, 0x21}, {0x3036, 0x46}, {0x303c, 0x11}, + {0x3106, 0xf5}, {0x3821, 0x01}, {0x3820, 0x41}, + {0x3827, 0xec}, {0x370c, 0x03}, {0x3612, 0x59}, {0x3618, 0x00}, {0x5000, 0x06}, {0x5003, 0x08}, {0x5a00, 0x08}, - {0x3000, 0xff}, - {0x3001, 0xff}, - {0x3002, 0xff}, + {0x3000, 0x00}, + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3016, 0x08}, + {0x3017, 0xe0}, + {0x3018, 0x44}, + {0x301c, 0xf8}, {0x301d, 0xf0}, {0x3a18, 0x00}, {0x3a19, 0xf8}, @@ -469,6 +476,7 @@ static struct regval_list ov5647_640x480_10bpp[] = { {0x3632, 0xe2}, {0x3633, 0x23}, {0x3634, 0x44}, + {0x3636, 0x06}, {0x3620, 0x64}, {0x3621, 0xe0}, {0x3600, 0x37}, @@ -497,19 +505,6 @@ static struct regval_list ov5647_640x480_10bpp[] = { {0x4001, 0x02}, {0x4004, 0x02}, {0x4000, 0x09}, - {0x3000, 0x00}, - {0x3001, 0x00}, - {0x3002, 0x00}, - {0x3017, 0xe0}, - {0x301c, 0xfc}, - {0x3636, 0x06}, - {0x3016, 0x08}, - {0x3827, 0xec}, - {0x3018, 0x44}, - {0x3035, 0x21}, - {0x3106, 0xf5}, - {0x3034, 0x1a}, - {0x301c, 0xf8}, {0x4800, 0x34}, {0x3503, 0x03}, {0x0100, 0x01}, From d6ec8ee9347536014a20197ca51301d406a2eb5f Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 15 Oct 2024 17:02:39 +0100 Subject: [PATCH 2/4] media: i2c: ov5647: Separate out the common registers. There are many registers in common between all the modes. Pull those out into one common table. Signed-off-by: Dave Stevenson --- drivers/media/i2c/ov5647.c | 243 ++++++++----------------------------- 1 file changed, 50 insertions(+), 193 deletions(-) diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index baf7a07687a2eb..b797d48fc5fc96 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -162,22 +162,16 @@ static const struct regval_list sensor_oe_enable_regs[] = { {0x3002, 0xe4}, }; -static struct regval_list ov5647_2592x1944_10bpp[] = { +static struct regval_list ov5647_common_regs[] = { {0x0100, 0x00}, {0x0103, 0x01}, {0x3034, 0x1a}, {0x3035, 0x21}, - {0x3036, 0x69}, {0x303c, 0x11}, {0x3106, 0xf5}, - {0x3821, 0x00}, - {0x3820, 0x00}, {0x3827, 0xec}, {0x370c, 0x03}, - {0x3612, 0x5b}, - {0x3618, 0x04}, {0x5000, 0x06}, - {0x5002, 0x41}, {0x5003, 0x08}, {0x5a00, 0x08}, {0x3000, 0x00}, @@ -192,24 +186,6 @@ static struct regval_list ov5647_2592x1944_10bpp[] = { {0x3a19, 0xf8}, {0x3c01, 0x80}, {0x3b07, 0x0c}, - {0x3814, 0x11}, - {0x3815, 0x11}, - {0x3708, 0x64}, - {0x3709, 0x12}, - {0x3808, 0x0a}, - {0x3809, 0x20}, - {0x380a, 0x07}, - {0x380b, 0x98}, - {0x3800, 0x00}, - {0x3801, 0x00}, - {0x3802, 0x00}, - {0x3803, 0x00}, - {0x3804, 0x0a}, - {0x3805, 0x3f}, - {0x3806, 0x07}, - {0x3807, 0xa3}, - {0x3811, 0x10}, - {0x3813, 0x06}, {0x3630, 0x2e}, {0x3632, 0xe2}, {0x3633, 0x23}, @@ -229,11 +205,6 @@ static struct regval_list ov5647_2592x1944_10bpp[] = { {0x3f06, 0x10}, {0x3f01, 0x0a}, {0x3a08, 0x01}, - {0x3a09, 0x28}, - {0x3a0a, 0x00}, - {0x3a0b, 0xf6}, - {0x3a0d, 0x08}, - {0x3a0e, 0x06}, {0x3a0f, 0x58}, {0x3a10, 0x50}, {0x3a1b, 0x58}, @@ -241,52 +212,57 @@ static struct regval_list ov5647_2592x1944_10bpp[] = { {0x3a11, 0x60}, {0x3a1f, 0x28}, {0x4001, 0x02}, - {0x4004, 0x04}, {0x4000, 0x09}, + {0x3503, 0x03}, +}; + +static struct regval_list ov5647_2592x1944_10bpp[] = { + {0x3036, 0x69}, + {0x3821, 0x00}, + {0x3820, 0x00}, + {0x3612, 0x5b}, + {0x3618, 0x04}, + {0x5002, 0x41}, + {0x3814, 0x11}, + {0x3815, 0x11}, + {0x3708, 0x64}, + {0x3709, 0x12}, + {0x3800, 0x00}, + {0x3801, 0x00}, + {0x3802, 0x00}, + {0x3803, 0x00}, + {0x3804, 0x0a}, + {0x3805, 0x3f}, + {0x3806, 0x07}, + {0x3807, 0xa3}, + {0x3808, 0x0a}, + {0x3809, 0x20}, + {0x380a, 0x07}, + {0x380b, 0x98}, + {0x3811, 0x10}, + {0x3813, 0x06}, + {0x3a09, 0x28}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0d, 0x08}, + {0x3a0e, 0x06}, + {0x4004, 0x04}, {0x4837, 0x19}, {0x4800, 0x24}, - {0x3503, 0x03}, {0x0100, 0x01}, }; static struct regval_list ov5647_1080p30_10bpp[] = { - {0x0100, 0x00}, - {0x0103, 0x01}, - {0x3034, 0x1a}, - {0x3035, 0x21}, {0x3036, 0x62}, - {0x303c, 0x11}, - {0x3106, 0xf5}, {0x3821, 0x00}, {0x3820, 0x00}, - {0x3827, 0xec}, - {0x370c, 0x03}, {0x3612, 0x5b}, {0x3618, 0x04}, - {0x5000, 0x06}, {0x5002, 0x41}, - {0x5003, 0x08}, - {0x5a00, 0x08}, - {0x3000, 0x00}, - {0x3001, 0x00}, - {0x3002, 0x00}, - {0x3016, 0x08}, - {0x3017, 0xe0}, - {0x3018, 0x44}, - {0x301c, 0xf8}, - {0x301d, 0xf0}, - {0x3a18, 0x00}, - {0x3a19, 0xf8}, - {0x3c01, 0x80}, - {0x3b07, 0x0c}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3708, 0x64}, {0x3709, 0x12}, - {0x3808, 0x07}, - {0x3809, 0x80}, - {0x380a, 0x04}, - {0x380b, 0x38}, {0x3800, 0x01}, {0x3801, 0x5c}, {0x3802, 0x01}, @@ -295,77 +271,30 @@ static struct regval_list ov5647_1080p30_10bpp[] = { {0x3805, 0xe3}, {0x3806, 0x05}, {0x3807, 0xf1}, + {0x3808, 0x07}, + {0x3809, 0x80}, + {0x380a, 0x04}, + {0x380b, 0x38}, {0x3811, 0x04}, {0x3813, 0x02}, - {0x3630, 0x2e}, - {0x3632, 0xe2}, - {0x3633, 0x23}, - {0x3634, 0x44}, - {0x3636, 0x06}, - {0x3620, 0x64}, - {0x3621, 0xe0}, - {0x3600, 0x37}, - {0x3704, 0xa0}, - {0x3703, 0x5a}, - {0x3715, 0x78}, - {0x3717, 0x01}, - {0x3731, 0x02}, - {0x370b, 0x60}, - {0x3705, 0x1a}, - {0x3f05, 0x02}, - {0x3f06, 0x10}, - {0x3f01, 0x0a}, - {0x3a08, 0x01}, {0x3a09, 0x4b}, {0x3a0a, 0x01}, {0x3a0b, 0x13}, {0x3a0d, 0x04}, {0x3a0e, 0x03}, - {0x3a0f, 0x58}, - {0x3a10, 0x50}, - {0x3a1b, 0x58}, - {0x3a1e, 0x50}, - {0x3a11, 0x60}, - {0x3a1f, 0x28}, - {0x4001, 0x02}, {0x4004, 0x04}, - {0x4000, 0x09}, {0x4837, 0x19}, {0x4800, 0x34}, - {0x3503, 0x03}, {0x0100, 0x01}, }; static struct regval_list ov5647_2x2binned_10bpp[] = { - {0x0100, 0x00}, - {0x0103, 0x01}, - {0x3034, 0x1a}, - {0x3035, 0x21}, {0x3036, 0x62}, - {0x303c, 0x11}, - {0x3106, 0xf5}, {0x3821, 0x01}, {0x3820, 0x41}, - {0x3827, 0xec}, - {0x370c, 0x03}, {0x3612, 0x59}, {0x3618, 0x00}, - {0x5000, 0x06}, {0x5002, 0x41}, - {0x5003, 0x08}, - {0x5a00, 0x08}, - {0x3000, 0x00}, - {0x3001, 0x00}, - {0x3002, 0x00}, - {0x3016, 0x08}, - {0x3017, 0xe0}, - {0x3018, 0x44}, - {0x301c, 0xf8}, - {0x301d, 0xf0}, - {0x3a18, 0x00}, - {0x3a19, 0xf8}, - {0x3c01, 0x80}, - {0x3b07, 0x0c}, {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, @@ -382,42 +311,14 @@ static struct regval_list ov5647_2x2binned_10bpp[] = { {0x3813, 0x06}, {0x3814, 0x31}, {0x3815, 0x31}, - {0x3630, 0x2e}, - {0x3632, 0xe2}, - {0x3633, 0x23}, - {0x3634, 0x44}, - {0x3636, 0x06}, - {0x3620, 0x64}, - {0x3621, 0xe0}, - {0x3600, 0x37}, - {0x3704, 0xa0}, - {0x3703, 0x5a}, - {0x3715, 0x78}, - {0x3717, 0x01}, - {0x3731, 0x02}, - {0x370b, 0x60}, - {0x3705, 0x1a}, - {0x3f05, 0x02}, - {0x3f06, 0x10}, - {0x3f01, 0x0a}, - {0x3a08, 0x01}, {0x3a09, 0x28}, {0x3a0a, 0x00}, {0x3a0b, 0xf6}, {0x3a0d, 0x08}, {0x3a0e, 0x06}, - {0x3a0f, 0x58}, - {0x3a10, 0x50}, - {0x3a1b, 0x58}, - {0x3a1e, 0x50}, - {0x3a11, 0x60}, - {0x3a1f, 0x28}, - {0x4001, 0x02}, {0x4004, 0x04}, - {0x4000, 0x09}, {0x4837, 0x16}, {0x4800, 0x24}, - {0x3503, 0x03}, {0x350a, 0x00}, {0x350b, 0x10}, {0x3500, 0x00}, @@ -428,42 +329,15 @@ static struct regval_list ov5647_2x2binned_10bpp[] = { }; static struct regval_list ov5647_640x480_10bpp[] = { - {0x0100, 0x00}, - {0x0103, 0x01}, - {0x3034, 0x1a}, - {0x3035, 0x21}, {0x3036, 0x46}, - {0x303c, 0x11}, - {0x3106, 0xf5}, {0x3821, 0x01}, {0x3820, 0x41}, - {0x3827, 0xec}, - {0x370c, 0x03}, {0x3612, 0x59}, {0x3618, 0x00}, - {0x5000, 0x06}, - {0x5003, 0x08}, - {0x5a00, 0x08}, - {0x3000, 0x00}, - {0x3001, 0x00}, - {0x3002, 0x00}, - {0x3016, 0x08}, - {0x3017, 0xe0}, - {0x3018, 0x44}, - {0x301c, 0xf8}, - {0x301d, 0xf0}, - {0x3a18, 0x00}, - {0x3a19, 0xf8}, - {0x3c01, 0x80}, - {0x3b07, 0x0c}, {0x3814, 0x35}, {0x3815, 0x35}, {0x3708, 0x64}, {0x3709, 0x52}, - {0x3808, 0x02}, - {0x3809, 0x80}, - {0x380a, 0x01}, - {0x380b, 0xe0}, {0x3800, 0x00}, {0x3801, 0x10}, {0x3802, 0x00}, @@ -472,41 +346,17 @@ static struct regval_list ov5647_640x480_10bpp[] = { {0x3805, 0x2f}, {0x3806, 0x07}, {0x3807, 0x9f}, - {0x3630, 0x2e}, - {0x3632, 0xe2}, - {0x3633, 0x23}, - {0x3634, 0x44}, - {0x3636, 0x06}, - {0x3620, 0x64}, - {0x3621, 0xe0}, - {0x3600, 0x37}, - {0x3704, 0xa0}, - {0x3703, 0x5a}, - {0x3715, 0x78}, - {0x3717, 0x01}, - {0x3731, 0x02}, - {0x370b, 0x60}, - {0x3705, 0x1a}, - {0x3f05, 0x02}, - {0x3f06, 0x10}, - {0x3f01, 0x0a}, - {0x3a08, 0x01}, + {0x3808, 0x02}, + {0x3809, 0x80}, + {0x380a, 0x01}, + {0x380b, 0xe0}, {0x3a09, 0x2e}, {0x3a0a, 0x00}, {0x3a0b, 0xfb}, {0x3a0d, 0x02}, {0x3a0e, 0x01}, - {0x3a0f, 0x58}, - {0x3a10, 0x50}, - {0x3a1b, 0x58}, - {0x3a1e, 0x50}, - {0x3a11, 0x60}, - {0x3a1f, 0x28}, - {0x4001, 0x02}, {0x4004, 0x02}, - {0x4000, 0x09}, {0x4800, 0x34}, - {0x3503, 0x03}, {0x0100, 0x01}, }; @@ -715,6 +565,13 @@ static int ov5647_set_mode(struct v4l2_subdev *sd) if (ret < 0) return ret; + ret = ov5647_write_array(sd, ov5647_common_regs, + ARRAY_SIZE(ov5647_common_regs)); + if (ret < 0) { + dev_err(&client->dev, "write sensor common regs error\n"); + return ret; + } + ret = ov5647_write_array(sd, sensor->mode->reg_list, sensor->mode->num_regs); if (ret < 0) { From 5f57cb1b96e22d5522befa4a01a9e41d15c8ac4e Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 15 Oct 2024 19:36:13 +0100 Subject: [PATCH 3/4] media: i2c: ov5647: Use the same PLL config for full, 1080p, and binned modes In order to simplify the driver slightly, use the same PLL configuration, and hence pixel rate and link frequency (to be added) for the full, 1080p, and binned modes. Signed-off-by: Dave Stevenson --- drivers/media/i2c/ov5647.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index b797d48fc5fc96..6ac369c0cf712d 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -253,7 +253,7 @@ static struct regval_list ov5647_2592x1944_10bpp[] = { }; static struct regval_list ov5647_1080p30_10bpp[] = { - {0x3036, 0x62}, + {0x3036, 0x69}, {0x3821, 0x00}, {0x3820, 0x00}, {0x3612, 0x5b}, @@ -289,7 +289,7 @@ static struct regval_list ov5647_1080p30_10bpp[] = { }; static struct regval_list ov5647_2x2binned_10bpp[] = { - {0x3036, 0x62}, + {0x3036, 0x69}, {0x3821, 0x01}, {0x3820, 0x41}, {0x3612, 0x59}, @@ -397,7 +397,7 @@ static const struct ov5647_mode ov5647_modes[] = { .width = 1928, .height = 1080, }, - .pixel_rate = 81666700, + .pixel_rate = 87500000, .hts = 2416, .vts = 0x450, .reg_list = ov5647_1080p30_10bpp, @@ -418,7 +418,7 @@ static const struct ov5647_mode ov5647_modes[] = { .width = 2592, .height = 1944, }, - .pixel_rate = 81666700, + .pixel_rate = 87500000, .hts = 1896, .vts = 0x59b, .reg_list = ov5647_2x2binned_10bpp, From 37c87cc99ecf98ecf45842534db50d19e8e36df6 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 15 Oct 2024 19:46:01 +0100 Subject: [PATCH 4/4] media: i2c: ov5647: Add V4L2_CID_LINK_FREQUENCY control The link frequency can vary between modes, so add it as a control. Signed-off-by: Dave Stevenson --- drivers/media/i2c/ov5647.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 6ac369c0cf712d..f474d22dbded94 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -97,6 +97,13 @@ static const char * const ov5647_supply_names[] = { #define OV5647_NUM_SUPPLIES ARRAY_SIZE(ov5647_supply_names) +#define FREQ_INDEX_FULL 0 +#define FREQ_INDEX_VGA 1 +static const s64 ov5647_link_freqs[] = { + [FREQ_INDEX_FULL] = 218500000, + [FREQ_INDEX_VGA] = 208333000, +}; + struct regval_list { u16 addr; u8 data; @@ -106,6 +113,7 @@ struct ov5647_mode { struct v4l2_mbus_framefmt format; struct v4l2_rect crop; u64 pixel_rate; + unsigned int link_freq_index; int hts; int vts; const struct regval_list *reg_list; @@ -128,6 +136,7 @@ struct ov5647 { struct v4l2_ctrl *exposure; struct v4l2_ctrl *hflip; struct v4l2_ctrl *vflip; + struct v4l2_ctrl *link_freq; bool streaming; }; @@ -377,6 +386,7 @@ static const struct ov5647_mode ov5647_modes[] = { .height = 1944 }, .pixel_rate = 87500000, + .link_freq_index = FREQ_INDEX_FULL, .hts = 2844, .vts = 0x7b0, .reg_list = ov5647_2592x1944_10bpp, @@ -398,6 +408,7 @@ static const struct ov5647_mode ov5647_modes[] = { .height = 1080, }, .pixel_rate = 87500000, + .link_freq_index = FREQ_INDEX_FULL, .hts = 2416, .vts = 0x450, .reg_list = ov5647_1080p30_10bpp, @@ -419,6 +430,7 @@ static const struct ov5647_mode ov5647_modes[] = { .height = 1944, }, .pixel_rate = 87500000, + .link_freq_index = FREQ_INDEX_FULL, .hts = 1896, .vts = 0x59b, .reg_list = ov5647_2x2binned_10bpp, @@ -440,6 +452,7 @@ static const struct ov5647_mode ov5647_modes[] = { .height = 1920, }, .pixel_rate = 55000000, + .link_freq_index = FREQ_INDEX_VGA, .hts = 1852, .vts = 0x1f8, .reg_list = ov5647_640x480_10bpp, @@ -943,6 +956,8 @@ static int ov5647_set_pad_fmt(struct v4l2_subdev *sd, sensor->exposure->minimum, exposure_max, sensor->exposure->step, exposure_def); + + __v4l2_ctrl_s_ctrl(sensor->link_freq, mode->link_freq_index); } *fmt = mode->format; /* The code we pass back must reflect the current h/vflips. */ @@ -1248,7 +1263,7 @@ static int ov5647_init_controls(struct ov5647 *sensor, struct device *dev) int hblank, exposure_max, exposure_def; struct v4l2_fwnode_device_properties props; - v4l2_ctrl_handler_init(&sensor->ctrls, 9); + v4l2_ctrl_handler_init(&sensor->ctrls, 10); v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 0); @@ -1308,6 +1323,14 @@ static int ov5647_init_controls(struct ov5647 *sensor, struct device *dev) if (sensor->vflip) sensor->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; + sensor->link_freq = + v4l2_ctrl_new_int_menu(&sensor->ctrls, &ov5647_ctrl_ops, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(ov5647_link_freqs) - 1, 0, + ov5647_link_freqs); + if (sensor->link_freq) + sensor->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + v4l2_fwnode_device_parse(dev, &props); v4l2_ctrl_new_fwnode_properties(&sensor->ctrls, &ov5647_ctrl_ops,