All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
@ 2022-02-10 11:04 Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 01/23] media: ov5640: Add pixel rate to modes Jacopo Mondi
                   ` (25 more replies)
  0 siblings, 26 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

v1:
https://patchwork.linuxtv.org/project/linux-media/list/?series=7249

A branch for testing based on the most recent media-master is available at
https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2

If anyone with a DVP setup could verify I have not broken their use case
I would very much appreciate that :)

v1 -> v2:
- rework the modes definition to process the full pixel array
- rework get_selection to report the correct BOUND and DEFAULT targets
- implement init_cfg
- minor style changes as suggested by Laurent
- test with 1 data lane

Thanks
   j

Jacopo Mondi (23):
  media: ov5640: Add pixel rate to modes
  media: ov5604: Re-arrange modes definition
  media: ov5640: Add ov5640_is_csi2() function
  media: ov5640: Associate bpp with formats
  media: ov5640: Add LINK_FREQ control
  media: ov5640: Update pixel_rate and link_freq
  media: ov5640: Rework CSI-2 clock tree
  media: ov5640: Rework timings programming
  media: ov5640: Fix 720x480 in RGB888 mode
  media: ov5640: Rework analog crop rectangles
  media: ov5640: Re-sort per-mode register tables
  media: ov5640: Remove ov5640_mode_init_data
  media: ov5640: Add HBLANK control
  media: ov5640: Add VBLANK control
  media: ov5640: Fix durations to comply with FPS
  media: ov5640: Implement init_cfg
  media: ov5640: Implement get_selection
  media: ov5640: Limit frame_interval to DVP mode only
  media: ov5640: Register device properties
  media: ov5640: Add RGB565_1X16 format
  media: ov5640: Add RGB888/BGR888 formats
  media: ov5640: Restrict sizes to mbus code
  media: ov5640: Adjust format to bpp in s_fmt

 drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
 1 file changed, 830 insertions(+), 313 deletions(-)

--
2.35.0


^ permalink raw reply	[flat|nested] 64+ messages in thread

* [PATCH v2 01/23] media: ov5640: Add pixel rate to modes
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-20 11:53   ` Laurent Pinchart
  2022-02-10 11:04 ` [PATCH v2 02/23] media: ov5604: Re-arrange modes definition Jacopo Mondi
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Add to each mode supported by the sensor the ideal pixel rate, as
defined by Table 2.1 in the chip manual.

The ideal pixel rate will be used to compute the MIPI CSI-2 clock tree.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 44 +++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index db5a19babe67..01f4a075f86e 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -118,6 +118,29 @@ enum ov5640_frame_rate {
 	OV5640_NUM_FRAMERATES,
 };
 
+enum ov5640_pixel_rate_id {
+	OV5640_PIXEL_RATE_168M,
+	OV5640_PIXEL_RATE_148M,
+	OV5640_PIXEL_RATE_124M,
+	OV5640_PIXEL_RATE_96M,
+	OV5640_PIXEL_RATE_48M,
+	OV5640_NUM_PIXEL_RATES,
+};
+
+/*
+ * The chip manual suggests 24/48/96/192 MHz pixel clocks.
+ *
+ * 192MHz exceeds the sysclk limits; use 168MHz as maximum pixel rate for
+ * full resolution mode @15 FPS.
+ */
+static const u32 ov5640_pixel_rates[] = {
+	[OV5640_PIXEL_RATE_168M] = 168000000,
+	[OV5640_PIXEL_RATE_148M] = 148000000,
+	[OV5640_PIXEL_RATE_124M] = 124000000,
+	[OV5640_PIXEL_RATE_96M] = 96000000,
+	[OV5640_PIXEL_RATE_48M] = 48000000,
+};
+
 enum ov5640_format_mux {
 	OV5640_FMT_MUX_YUV422 = 0,
 	OV5640_FMT_MUX_RGB,
@@ -189,6 +212,7 @@ struct reg_value {
 struct ov5640_mode_info {
 	enum ov5640_mode_id id;
 	enum ov5640_downsize_mode dn_mode;
+	enum ov5640_pixel_rate_id pixel_rate;
 	u32 hact;
 	u32 htot;
 	u32 vact;
@@ -565,7 +589,9 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
 
 /* power-on sensor init reg table */
 static const struct ov5640_mode_info ov5640_mode_init_data = {
-	0, SUBSAMPLING, 640, 1896, 480, 984,
+	0, SUBSAMPLING,
+	OV5640_PIXEL_RATE_96M,
+	640, 1896, 480, 984,
 	ov5640_init_setting_30fps_VGA,
 	ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
 	OV5640_30_FPS,
@@ -574,51 +600,61 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
 static const struct ov5640_mode_info
 ov5640_mode_data[OV5640_NUM_MODES] = {
 	{OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
+	 OV5640_PIXEL_RATE_48M,
 	 160, 1896, 120, 984,
 	 ov5640_setting_QQVGA_160_120,
 	 ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
 	 OV5640_30_FPS},
 	{OV5640_MODE_QCIF_176_144, SUBSAMPLING,
+	 OV5640_PIXEL_RATE_48M,
 	 176, 1896, 144, 984,
 	 ov5640_setting_QCIF_176_144,
 	 ARRAY_SIZE(ov5640_setting_QCIF_176_144),
 	 OV5640_30_FPS},
 	{OV5640_MODE_QVGA_320_240, SUBSAMPLING,
+	 OV5640_PIXEL_RATE_48M,
 	 320, 1896, 240, 984,
 	 ov5640_setting_QVGA_320_240,
 	 ARRAY_SIZE(ov5640_setting_QVGA_320_240),
 	 OV5640_30_FPS},
 	{OV5640_MODE_VGA_640_480, SUBSAMPLING,
+	 OV5640_PIXEL_RATE_48M,
 	 640, 1896, 480, 1080,
 	 ov5640_setting_VGA_640_480,
 	 ARRAY_SIZE(ov5640_setting_VGA_640_480),
 	 OV5640_60_FPS},
 	{OV5640_MODE_NTSC_720_480, SUBSAMPLING,
+	 OV5640_PIXEL_RATE_96M,
 	 720, 1896, 480, 984,
 	 ov5640_setting_NTSC_720_480,
 	 ARRAY_SIZE(ov5640_setting_NTSC_720_480),
 	OV5640_30_FPS},
 	{OV5640_MODE_PAL_720_576, SUBSAMPLING,
+	 OV5640_PIXEL_RATE_96M,
 	 720, 1896, 576, 984,
 	 ov5640_setting_PAL_720_576,
 	 ARRAY_SIZE(ov5640_setting_PAL_720_576),
 	 OV5640_30_FPS},
 	{OV5640_MODE_XGA_1024_768, SUBSAMPLING,
+	 OV5640_PIXEL_RATE_96M,
 	 1024, 1896, 768, 1080,
 	 ov5640_setting_XGA_1024_768,
 	 ARRAY_SIZE(ov5640_setting_XGA_1024_768),
 	 OV5640_30_FPS},
 	{OV5640_MODE_720P_1280_720, SUBSAMPLING,
+	 OV5640_PIXEL_RATE_124M,
 	 1280, 1892, 720, 740,
 	 ov5640_setting_720P_1280_720,
 	 ARRAY_SIZE(ov5640_setting_720P_1280_720),
 	 OV5640_30_FPS},
 	{OV5640_MODE_1080P_1920_1080, SCALING,
+	 OV5640_PIXEL_RATE_148M,
 	 1920, 2500, 1080, 1120,
 	 ov5640_setting_1080P_1920_1080,
 	 ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
 	 OV5640_30_FPS},
 	{OV5640_MODE_QSXGA_2592_1944, SCALING,
+	 OV5640_PIXEL_RATE_168M,
 	 2592, 2844, 1944, 1968,
 	 ov5640_setting_QSXGA_2592_1944,
 	 ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
@@ -2743,6 +2779,7 @@ static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
 
 static int ov5640_init_controls(struct ov5640_dev *sensor)
 {
+	const struct ov5640_mode_info *mode = sensor->current_mode;
 	const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
 	struct ov5640_ctrls *ctrls = &sensor->ctrls;
 	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
@@ -2755,8 +2792,9 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 
 	/* Clock related controls */
 	ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
-					      0, INT_MAX, 1,
-					      ov5640_calc_pixel_rate(sensor));
+				      ov5640_pixel_rates[OV5640_NUM_PIXEL_RATES - 1],
+				      ov5640_pixel_rates[0], 1,
+				      ov5640_pixel_rates[mode->pixel_rate]);
 
 	/* Auto/manual white balance */
 	ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 02/23] media: ov5604: Re-arrange modes definition
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 01/23] media: ov5640: Add pixel rate to modes Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 03/23] media: ov5640: Add ov5640_is_csi2() function Jacopo Mondi
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

The array of supported modes is close to unreadable.
Re-arrange it giving it some room to breath.

Cosmetic change only.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 141 +++++++++++++++++++++----------------
 1 file changed, 81 insertions(+), 60 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 01f4a075f86e..d8285be2bfa1 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -599,66 +599,87 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
 
 static const struct ov5640_mode_info
 ov5640_mode_data[OV5640_NUM_MODES] = {
-	{OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
-	 OV5640_PIXEL_RATE_48M,
-	 160, 1896, 120, 984,
-	 ov5640_setting_QQVGA_160_120,
-	 ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
-	 OV5640_30_FPS},
-	{OV5640_MODE_QCIF_176_144, SUBSAMPLING,
-	 OV5640_PIXEL_RATE_48M,
-	 176, 1896, 144, 984,
-	 ov5640_setting_QCIF_176_144,
-	 ARRAY_SIZE(ov5640_setting_QCIF_176_144),
-	 OV5640_30_FPS},
-	{OV5640_MODE_QVGA_320_240, SUBSAMPLING,
-	 OV5640_PIXEL_RATE_48M,
-	 320, 1896, 240, 984,
-	 ov5640_setting_QVGA_320_240,
-	 ARRAY_SIZE(ov5640_setting_QVGA_320_240),
-	 OV5640_30_FPS},
-	{OV5640_MODE_VGA_640_480, SUBSAMPLING,
-	 OV5640_PIXEL_RATE_48M,
-	 640, 1896, 480, 1080,
-	 ov5640_setting_VGA_640_480,
-	 ARRAY_SIZE(ov5640_setting_VGA_640_480),
-	 OV5640_60_FPS},
-	{OV5640_MODE_NTSC_720_480, SUBSAMPLING,
-	 OV5640_PIXEL_RATE_96M,
-	 720, 1896, 480, 984,
-	 ov5640_setting_NTSC_720_480,
-	 ARRAY_SIZE(ov5640_setting_NTSC_720_480),
-	OV5640_30_FPS},
-	{OV5640_MODE_PAL_720_576, SUBSAMPLING,
-	 OV5640_PIXEL_RATE_96M,
-	 720, 1896, 576, 984,
-	 ov5640_setting_PAL_720_576,
-	 ARRAY_SIZE(ov5640_setting_PAL_720_576),
-	 OV5640_30_FPS},
-	{OV5640_MODE_XGA_1024_768, SUBSAMPLING,
-	 OV5640_PIXEL_RATE_96M,
-	 1024, 1896, 768, 1080,
-	 ov5640_setting_XGA_1024_768,
-	 ARRAY_SIZE(ov5640_setting_XGA_1024_768),
-	 OV5640_30_FPS},
-	{OV5640_MODE_720P_1280_720, SUBSAMPLING,
-	 OV5640_PIXEL_RATE_124M,
-	 1280, 1892, 720, 740,
-	 ov5640_setting_720P_1280_720,
-	 ARRAY_SIZE(ov5640_setting_720P_1280_720),
-	 OV5640_30_FPS},
-	{OV5640_MODE_1080P_1920_1080, SCALING,
-	 OV5640_PIXEL_RATE_148M,
-	 1920, 2500, 1080, 1120,
-	 ov5640_setting_1080P_1920_1080,
-	 ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
-	 OV5640_30_FPS},
-	{OV5640_MODE_QSXGA_2592_1944, SCALING,
-	 OV5640_PIXEL_RATE_168M,
-	 2592, 2844, 1944, 1968,
-	 ov5640_setting_QSXGA_2592_1944,
-	 ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
-	 OV5640_15_FPS},
+	{
+		/* 160x120 */
+		OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
+		OV5640_PIXEL_RATE_48M,
+		160, 1896, 120, 984,
+		ov5640_setting_QQVGA_160_120,
+		ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
+		OV5640_30_FPS
+	}, {
+		/* 176x144 */
+		OV5640_MODE_QCIF_176_144, SUBSAMPLING,
+		OV5640_PIXEL_RATE_48M,
+		176, 1896, 144, 984,
+		ov5640_setting_QCIF_176_144,
+		ARRAY_SIZE(ov5640_setting_QCIF_176_144),
+		OV5640_30_FPS
+	}, {
+		/* 320x240 */
+		OV5640_MODE_QVGA_320_240, SUBSAMPLING,
+		OV5640_PIXEL_RATE_48M,
+		320, 1896, 240, 984,
+		ov5640_setting_QVGA_320_240,
+		ARRAY_SIZE(ov5640_setting_QVGA_320_240),
+		OV5640_30_FPS
+	}, {
+		/* 640x480 */
+		OV5640_MODE_VGA_640_480, SUBSAMPLING,
+		OV5640_PIXEL_RATE_48M,
+		640, 1896, 480, 1080,
+		ov5640_setting_VGA_640_480,
+		ARRAY_SIZE(ov5640_setting_VGA_640_480),
+		OV5640_60_FPS
+	}, {
+		/* 720x480 */
+		OV5640_MODE_NTSC_720_480, SUBSAMPLING,
+		OV5640_PIXEL_RATE_96M,
+		720, 1896, 480, 984,
+		ov5640_setting_NTSC_720_480,
+		ARRAY_SIZE(ov5640_setting_NTSC_720_480),
+		OV5640_30_FPS
+	}, {
+		/* 720x576 */
+		OV5640_MODE_PAL_720_576, SUBSAMPLING,
+		OV5640_PIXEL_RATE_96M,
+		720, 1896, 576, 984,
+		ov5640_setting_PAL_720_576,
+		ARRAY_SIZE(ov5640_setting_PAL_720_576),
+		OV5640_30_FPS
+	}, {
+		/* 1024x768 */
+		OV5640_MODE_XGA_1024_768, SUBSAMPLING,
+		OV5640_PIXEL_RATE_96M,
+		1024, 1896, 768, 1080,
+		ov5640_setting_XGA_1024_768,
+		ARRAY_SIZE(ov5640_setting_XGA_1024_768),
+		OV5640_30_FPS
+	}, {
+		/* 1280x720 */
+		OV5640_MODE_720P_1280_720, SUBSAMPLING,
+		OV5640_PIXEL_RATE_124M,
+		1280, 1892, 720, 740,
+		ov5640_setting_720P_1280_720,
+		ARRAY_SIZE(ov5640_setting_720P_1280_720),
+		OV5640_30_FPS
+	}, {
+		/* 1920x1080 */
+		OV5640_MODE_1080P_1920_1080, SCALING,
+		OV5640_PIXEL_RATE_148M,
+		1920, 2500, 1080, 1120,
+		ov5640_setting_1080P_1920_1080,
+		ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
+		OV5640_30_FPS
+	}, {
+		/* 2592x1944 */
+		OV5640_MODE_QSXGA_2592_1944, SCALING,
+		OV5640_PIXEL_RATE_168M,
+		2592, 2844, 1944, 1968,
+		ov5640_setting_QSXGA_2592_1944,
+		ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
+		OV5640_15_FPS
+	},
 };
 
 static int ov5640_init_slave_id(struct ov5640_dev *sensor)
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 03/23] media: ov5640: Add ov5640_is_csi2() function
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 01/23] media: ov5640: Add pixel rate to modes Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 02/23] media: ov5604: Re-arrange modes definition Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 04/23] media: ov5640: Associate bpp with formats Jacopo Mondi
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Checking if the sensor is used in DVP or MIPI CSI-2 mode is a repeated
pattern which is about to be repeated more often.

Provide an inline function to shortcut that.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index d8285be2bfa1..ce3d38eadb86 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -294,6 +294,11 @@ static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
 			     ctrls.handler)->sd;
 }
 
+static inline bool ov5640_is_csi2(struct ov5640_dev *sensor)
+{
+	return sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY;
+}
+
 /*
  * FIXME: all of these register tables are likely filled with
  * entries that set the register to their power-on default values,
@@ -1208,7 +1213,7 @@ static int ov5640_load_regs(struct ov5640_dev *sensor,
 		/* remain in power down mode for DVP */
 		if (regs->reg_addr == OV5640_REG_SYS_CTRL0 &&
 		    val == OV5640_REG_SYS_CTRL0_SW_PWUP &&
-		    sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
+		    !ov5640_is_csi2(sensor))
 			continue;
 
 		if (mask)
@@ -1843,7 +1848,7 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
 	 * the same rate than YUV, so we can just use 16 bpp all the time.
 	 */
 	rate = ov5640_calc_pixel_rate(sensor) * 16;
-	if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY) {
+	if (ov5640_is_csi2(sensor)) {
 		rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes;
 		ret = ov5640_set_mipi_pclk(sensor, rate);
 	} else {
@@ -3020,7 +3025,7 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
 			sensor->pending_fmt_change = false;
 		}
 
-		if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY)
+		if (ov5640_is_csi2(sensor))
 			ret = ov5640_set_stream_mipi(sensor, enable);
 		else
 			ret = ov5640_set_stream_dvp(sensor, enable);
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 04/23] media: ov5640: Associate bpp with formats
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (2 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 03/23] media: ov5640: Add ov5640_is_csi2() function Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 05/23] media: ov5640: Add LINK_FREQ control Jacopo Mondi
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Associate the bit depth to each format supported by the sensor.

The bpp will be used to calculate the line length.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 73 ++++++++++++++++++++++++++++++--------
 1 file changed, 59 insertions(+), 14 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index ce3d38eadb86..71404d064045 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -150,24 +150,69 @@ enum ov5640_format_mux {
 	OV5640_FMT_MUX_RAW_CIP,
 };
 
-struct ov5640_pixfmt {
+static const struct ov5640_pixfmt {
 	u32 code;
 	u32 colorspace;
+	u8 bpp;
+} ov5640_formats[] = {
+	{
+		.code = MEDIA_BUS_FMT_JPEG_1X8,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_UYVY8_2X8,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_YUYV8_2X8,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_YUYV8_1X16,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 8,
+	}, {
+		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 8
+	}, {
+		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 8,
+	}, {
+		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 8,
+	},
 };
 
-static const struct ov5640_pixfmt ov5640_formats[] = {
-	{ MEDIA_BUS_FMT_JPEG_1X8, V4L2_COLORSPACE_JPEG, },
-	{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_UYVY8_1X16, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_YUYV8_1X16, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_COLORSPACE_SRGB, },
-	{ MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_COLORSPACE_SRGB, },
-};
+static u32 ov5640_code_to_bpp(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ov5640_formats); ++i) {
+		if (ov5640_formats[i].code == code)
+			return ov5640_formats[i].bpp;
+	}
+
+	return 0;
+}
 
 /*
  * FIXME: remove this when a subdev API becomes available
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 05/23] media: ov5640: Add LINK_FREQ control
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (3 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 04/23] media: ov5640: Associate bpp with formats Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-20 11:55   ` Laurent Pinchart
  2022-02-10 11:04 ` [PATCH v2 06/23] media: ov5640: Update pixel_rate and link_freq Jacopo Mondi
                   ` (20 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Add the V4L2_CID_LINK_FREQ control to the ov5640 driver.
Make the control read-only for the moment.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 71404d064045..4c3a1fd41095 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -141,6 +141,21 @@ static const u32 ov5640_pixel_rates[] = {
 	[OV5640_PIXEL_RATE_48M] = 48000000,
 };
 
+/*
+ * MIPI CSI-2 link frequencies.
+ *
+ * Derived from the above defined pixel rate for bpp = (8, 16, 24) and
+ * data_lanes = (1, 2)
+ *
+ * link_freq = (pixel_rate * bpp) / (2 * data_lanes)
+ */
+static const s64 ov5640_csi2_link_freqs[] = {
+	992000000, 888000000, 768000000, 744000000, 672000000, 672000000,
+	592000000, 592000000, 576000000, 576000000, 496000000, 496000000,
+	384000000, 384000000, 384000000, 336000000, 296000000, 288000000,
+	248000000, 192000000, 192000000, 192000000, 96000000,
+};
+
 enum ov5640_format_mux {
 	OV5640_FMT_MUX_YUV422 = 0,
 	OV5640_FMT_MUX_RGB,
@@ -270,6 +285,7 @@ struct ov5640_mode_info {
 struct ov5640_ctrls {
 	struct v4l2_ctrl_handler handler;
 	struct v4l2_ctrl *pixel_rate;
+	struct v4l2_ctrl *link_freq;
 	struct {
 		struct v4l2_ctrl *auto_exp;
 		struct v4l2_ctrl *exposure;
@@ -2867,6 +2883,11 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 				      ov5640_pixel_rates[0], 1,
 				      ov5640_pixel_rates[mode->pixel_rate]);
 
+	ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops,
+					V4L2_CID_LINK_FREQ,
+					ARRAY_SIZE(ov5640_csi2_link_freqs) - 1,
+					4, ov5640_csi2_link_freqs);
+
 	/* Auto/manual white balance */
 	ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
 					   V4L2_CID_AUTO_WHITE_BALANCE,
@@ -2915,6 +2936,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 	}
 
 	ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
 	ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 06/23] media: ov5640: Update pixel_rate and link_freq
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (4 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 05/23] media: ov5640: Add LINK_FREQ control Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 07/23] media: ov5640: Rework CSI-2 clock tree Jacopo Mondi
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

After having set a new format re-calculate the pixel_rate and link_freq
control values and update them when in MIPI mode.

Take into account the limitation of the link frequency having to be
strictly smaller than 1GHz when computing the desired link_freq, and
adjust the resulting pixel_rate acounting for the clock tree
configuration.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 66 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 4c3a1fd41095..50b611697470 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -31,6 +31,8 @@
 
 #define OV5640_DEFAULT_SLAVE_ID 0x3c
 
+#define OV5640_LINK_RATE_MAX		490000000U
+
 #define OV5640_REG_SYS_RESET02		0x3002
 #define OV5640_REG_SYS_CLOCK_ENABLE02	0x3006
 #define OV5640_REG_SYS_CTRL0		0x3008
@@ -2409,6 +2411,66 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
+{
+	const struct ov5640_mode_info *mode = sensor->current_mode;
+	struct v4l2_mbus_framefmt *fmt = &sensor->fmt;
+	enum ov5640_pixel_rate_id pixel_rate_id = mode->pixel_rate;
+	unsigned int i = 0;
+	u32 pixel_rate;
+	s64 link_freq;
+	u32 num_lanes;
+	u32 bpp;
+
+	/*
+	 * Update the pixel rate control value.
+	 *
+	 * For DVP mode, maintain the pixel rate calculation using fixed FPS.
+	 */
+	if (!ov5640_is_csi2(sensor)) {
+		__v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
+					 ov5640_calc_pixel_rate(sensor));
+
+		return 0;
+	}
+
+	/*
+	 * The MIPI CSI-2 link frequency should comply with the CSI-2
+	 * specification and be lower than 1GHz.
+	 *
+	 * Start from the suggested pixel_rate for the current mode and
+	 * progressively slow it down if it exceeds 1GHz.
+	 */
+	num_lanes = sensor->ep.bus.mipi_csi2.num_data_lanes;
+	bpp = ov5640_code_to_bpp(fmt->code);
+	do {
+		pixel_rate = ov5640_pixel_rates[pixel_rate_id];
+		link_freq = pixel_rate * bpp / (2 * num_lanes);
+	} while (link_freq >= 1000000000U &&
+		 ++pixel_rate_id < OV5640_NUM_PIXEL_RATES);
+
+	/*
+	 * Higher link rates require the clock tree to be programmed with
+	 * 'mipi_div' = 1; this has the effect of halving the actual output
+	 * pixel rate in the MIPI domain.
+	 *
+	 * Adjust the pixel rate control value to report it correctly to
+	 * userspace.
+	 */
+	if (link_freq > OV5640_LINK_RATE_MAX)
+		pixel_rate /= 2;
+
+	for (i = 0; i < ARRAY_SIZE(ov5640_csi2_link_freqs); ++i) {
+		if (ov5640_csi2_link_freqs[i] == link_freq)
+			break;
+	}
+
+	__v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, pixel_rate);
+	__v4l2_ctrl_s_ctrl(sensor->ctrls.link_freq, i);
+
+	return 0;
+}
+
 static int ov5640_set_fmt(struct v4l2_subdev *sd,
 			  struct v4l2_subdev_state *sd_state,
 			  struct v4l2_subdev_format *format)
@@ -2448,8 +2510,8 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
 	/* update format even if code is unchanged, resolution might change */
 	sensor->fmt = *mbus_fmt;
 
-	__v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-				 ov5640_calc_pixel_rate(sensor));
+	ov5640_update_pixel_rate(sensor);
+
 out:
 	mutex_unlock(&sensor->lock);
 	return ret;
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 07/23] media: ov5640: Rework CSI-2 clock tree
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (5 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 06/23] media: ov5640: Update pixel_rate and link_freq Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-20 12:17   ` Laurent Pinchart
  2022-02-10 11:04 ` [PATCH v2 08/23] media: ov5640: Rework timings programming Jacopo Mondi
                   ` (18 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Re-work the ov5640_set_mipi_pclk() function to calculate the
PLL configuration using the pixel_rate and link_freq values set at
s_fmt time.

Rework the DVP clock mode settings to calculate the pixel clock
internally and remove the assumption on the 16bpp format.

Tested in MIPI CSI-2 mode with 1 and 2 data lanes with:
- all the sensor supported resolutions in UYVY and RGB565 formats.
- resolutions >= 1280x720 in RAW Bayer format.
- resolutions < 1280x720 in RGB888 format.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 189 ++++++++++++++++++-------------------
 1 file changed, 90 insertions(+), 99 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 50b611697470..eb4789ae6abf 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -90,6 +90,7 @@
 #define OV5640_REG_POLARITY_CTRL00	0x4740
 #define OV5640_REG_MIPI_CTRL00		0x4800
 #define OV5640_REG_DEBUG_MODE		0x4814
+#define OV5640_REG_PCLK_PERIOD		0x4837
 #define OV5640_REG_ISP_FORMAT_MUX_CTRL	0x501f
 #define OV5640_REG_PRE_ISP_TEST_SET1	0x503d
 #define OV5640_REG_SDE_CTRL0		0x5580
@@ -922,20 +923,10 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
  *                                +-----+-----+
  *                                       +------------> PCLK
  *
- * This is deviating from the datasheet at least for the register
- * 0x3108, since it's said here that the PCLK would be clocked from
- * the PLL.
- *
- * There seems to be also (unverified) constraints:
+ * There seems to be also constraints:
  *  - the PLL pre-divider output rate should be in the 4-27MHz range
  *  - the PLL multiplier output rate should be in the 500-1000MHz range
  *  - PCLK >= SCLK * 2 in YUV, >= SCLK in Raw or JPEG
- *
- * In the two latter cases, these constraints are met since our
- * factors are hardcoded. If we were to change that, we would need to
- * take this into account. The only varying parts are the PLL
- * multiplier and the system clock divider, which are shared between
- * all these clocks so won't cause any issue.
  */
 
 /*
@@ -954,13 +945,6 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
 #define OV5640_SYSDIV_MIN	1
 #define OV5640_SYSDIV_MAX	16
 
-/*
- * Hardcode these values for scaler and non-scaler modes.
- * FIXME: to be re-calcualted for 1 data lanes setups
- */
-#define OV5640_MIPI_DIV_PCLK	2
-#define OV5640_MIPI_DIV_SCLK	1
-
 /*
  * This is supposed to be ranging from 1 to 2, but the value is always
  * set to 2 in the vendor kernels.
@@ -1071,69 +1055,77 @@ static unsigned long ov5640_calc_sys_clk(struct ov5640_dev *sensor,
  * ov5640_set_mipi_pclk() - Calculate the clock tree configuration values
  *			    for the MIPI CSI-2 output.
  *
- * @rate: The requested bandwidth per lane in bytes per second.
- *	  'Bandwidth Per Lane' is calculated as:
- *	  bpl = HTOT * VTOT * FPS * bpp / num_lanes;
- *
- * This function use the requested bandwidth to calculate:
- * - sample_rate = bpl / (bpp / num_lanes);
- *	         = bpl / (PLL_RDIV * BIT_DIV * PCLK_DIV * MIPI_DIV / num_lanes);
- *
- * - mipi_sclk   = bpl / MIPI_DIV / 2; ( / 2 is for CSI-2 DDR)
- *
- * with these fixed parameters:
- *	PLL_RDIV	= 2;
- *	BIT_DIVIDER	= 2; (MIPI_BIT_MODE == 8 ? 2 : 2,5);
- *	PCLK_DIV	= 1;
- *
- * The MIPI clock generation differs for modes that use the scaler and modes
- * that do not. In case the scaler is in use, the MIPI_SCLK generates the MIPI
- * BIT CLk, and thus:
- *
- * - mipi_sclk = bpl / MIPI_DIV / 2;
- *   MIPI_DIV = 1;
- *
- * For modes that do not go through the scaler, the MIPI BIT CLOCK is generated
- * from the pixel clock, and thus:
- *
- * - sample_rate = bpl / (bpp / num_lanes);
- *	         = bpl / (2 * 2 * 1 * MIPI_DIV / num_lanes);
- *		 = bpl / (4 * MIPI_DIV / num_lanes);
- * - MIPI_DIV	 = bpp / (4 * num_lanes);
- *
- * FIXME: this have been tested with 16bpp and 2 lanes setup only.
- * MIPI_DIV is fixed to value 2, but it -might- be changed according to the
- * above formula for setups with 1 lane or image formats with different bpp.
- *
- * FIXME: this deviates from the sensor manual documentation which is quite
- * thin on the MIPI clock tree generation part.
+ * FIXME: tested with 2 lanes only.
  */
-static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
-				unsigned long rate)
+static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor)
 {
-	const struct ov5640_mode_info *mode = sensor->current_mode;
+	u8 bit_div, mipi_div, p_div, sclk_div, sclk2x_div, root_div;
+	struct v4l2_mbus_framefmt *fmt = &sensor->fmt;
 	u8 prediv, mult, sysdiv;
-	u8 mipi_div;
+	unsigned long sysclk;
+	unsigned long sample_rate;
+	u8 pclk_period;
+	s64 link_freq;
 	int ret;
 
+	/* Use the link frequency computed at ov5640_update_pixel_rate() time. */
+	link_freq = ov5640_csi2_link_freqs[sensor->ctrls.link_freq->cur.val];
+
 	/*
-	 * 1280x720 is reported to use 'SUBSAMPLING' only,
-	 * but according to the sensor manual it goes through the
-	 * scaler before subsampling.
+	 * - mipi_div - Additional divider for the MIPI lane clock.
+	 *
+	 * Higher link frequencies would make sysclk > 1GHz.
+	 * Keep the sysclk low and do not divide in the MIPI domain.
 	 */
-	if (mode->dn_mode == SCALING ||
-	   (mode->id == OV5640_MODE_720P_1280_720))
-		mipi_div = OV5640_MIPI_DIV_SCLK;
+	if (link_freq > OV5640_LINK_RATE_MAX)
+		mipi_div = 1;
 	else
-		mipi_div = OV5640_MIPI_DIV_PCLK;
+		mipi_div = 2;
 
-	ov5640_calc_sys_clk(sensor, rate, &prediv, &mult, &sysdiv);
+	sysclk = link_freq * mipi_div;
+	ov5640_calc_sys_clk(sensor, sysclk, &prediv, &mult, &sysdiv);
 
-	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0,
-			     0x0f, OV5640_PLL_CTRL0_MIPI_MODE_8BIT);
+	/*
+	 * Adjust PLL parameters to maintain the MIPI_SCLK-to-PCLK ratio;
+	 *
+	 * - root_div = 2 (fixed)
+	 * - bit_div : MIPI 8-bit = 2
+	 *	       MIPI 10-bit = 2.5
+	 * - p_div = 1 (fixed)
+	 * - pll_div  = (2 lanes ? mipi_div : 2 * mipi_div)
+	 *   2 lanes: MIPI_SCLK = (4 or 5) * PCLK
+	 *   1 lanes: MIPI_SCLK = (8 or 10) * PCLK
+	 */
+	root_div = OV5640_PLL_CTRL3_PLL_ROOT_DIV_2;
+	bit_div =  OV5640_PLL_CTRL0_MIPI_MODE_8BIT;
+	p_div = OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS;
 
-	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
-			     0xff, sysdiv << 4 | mipi_div);
+	/*
+	 * Scaler clock:
+	 * - YUV: PCLK >= 2 * SCLK
+	 * - RAW or JPEG: PCLK >= SCLK
+	 * - sclk2x_div = sclk_div / 2
+	 *
+	 * TODO: test with JPEG.
+	 */
+	sclk_div = ilog2(OV5640_SCLK_ROOT_DIV);
+	sclk2x_div = ilog2(OV5640_SCLK2X_ROOT_DIV);
+
+	/*
+	 * Set the sample period expressed in ns with 1-bit decimal
+	 * (0x01=0.5ns).
+	 */
+	sample_rate = ov5640_pixel_rates[sensor->current_mode->pixel_rate]
+		    * (ov5640_code_to_bpp(fmt->code) / 8);
+	pclk_period = 2000000000U / sample_rate;
+
+	/* Program the clock tree registers. */
+	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0, 0x0f, bit_div);
+	if (ret)
+		return ret;
+
+	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1, 0xff,
+			     (sysdiv << 4) | mipi_div);
 	if (ret)
 		return ret;
 
@@ -1141,13 +1133,27 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
 	if (ret)
 		return ret;
 
-	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
-			     0x1f, OV5640_PLL_CTRL3_PLL_ROOT_DIV_2 | prediv);
+	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3, 0x1f,
+			     root_div | prediv);
+	if (ret)
+		return ret;
+
+	ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
+			     (p_div << 4) | (sclk2x_div << 2) | sclk_div);
 	if (ret)
 		return ret;
 
-	return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER,
-			      0x30, OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS);
+	return ov5640_write_reg(sensor, OV5640_REG_PCLK_PERIOD, pclk_period);
+}
+
+static u32 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
+{
+	u32 rate;
+
+	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
+	rate *= ov5640_framerates[sensor->current_fr];
+
+	return rate;
 }
 
 static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
@@ -1167,11 +1173,16 @@ static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
 	return _rate / *pll_rdiv / *bit_div / *pclk_div;
 }
 
-static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor, unsigned long rate)
+static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor)
 {
 	u8 prediv, mult, sysdiv, pll_rdiv, bit_div, pclk_div;
+	u32 rate;
 	int ret;
 
+	rate = ov5640_calc_pixel_rate(sensor);
+	rate *= ov5640_code_to_bpp(sensor->fmt.code);
+	rate /= sensor->ep.bus.parallel.bus_width;
+
 	ov5640_calc_pclk(sensor, rate, &prediv, &mult, &sysdiv, &pll_rdiv,
 			 &bit_div, &pclk_div);
 
@@ -1696,16 +1707,6 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
 	return mode;
 }
 
-static u64 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
-{
-	u64 rate;
-
-	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
-	rate *= ov5640_framerates[sensor->current_fr];
-
-	return rate;
-}
-
 /*
  * sensor changes between scaling and subsampling, go through
  * exposure calculation
@@ -1887,7 +1888,6 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
 	enum ov5640_downsize_mode dn_mode, orig_dn_mode;
 	bool auto_gain = sensor->ctrls.auto_gain->val == 1;
 	bool auto_exp =  sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
-	unsigned long rate;
 	int ret;
 
 	dn_mode = mode->dn_mode;
@@ -1906,19 +1906,10 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
 			goto restore_auto_gain;
 	}
 
-	/*
-	 * All the formats we support have 16 bits per pixel, seems to require
-	 * the same rate than YUV, so we can just use 16 bpp all the time.
-	 */
-	rate = ov5640_calc_pixel_rate(sensor) * 16;
-	if (ov5640_is_csi2(sensor)) {
-		rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes;
-		ret = ov5640_set_mipi_pclk(sensor, rate);
-	} else {
-		rate = rate / sensor->ep.bus.parallel.bus_width;
-		ret = ov5640_set_dvp_pclk(sensor, rate);
-	}
-
+	if (ov5640_is_csi2(sensor))
+		ret = ov5640_set_mipi_pclk(sensor);
+	else
+		ret = ov5640_set_dvp_pclk(sensor);
 	if (ret < 0)
 		return 0;
 
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 08/23] media: ov5640: Rework timings programming
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (6 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 07/23] media: ov5640: Rework CSI-2 clock tree Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-20 12:44   ` Laurent Pinchart
  2022-02-10 11:04 ` [PATCH v2 09/23] media: ov5640: Fix 720x480 in RGB888 mode Jacopo Mondi
                   ` (17 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

The current definition of a sensor mode defines timings as follows:

- hact, vact: Visible width and height
- htot, vtot: Total sizes including blankings

This makes difficult to clearly separate the visible sizes from the
blankings and to make the vertical blanking programmable.

Rework the sensor modes sizes definition to:
- Report the analog crop sizes
- Report the visible crop size
- Report the total pixels per line as HBLANK is fixed
- Report the VBLANK value to make it programmable

Also modify the ov5640_set_timings() function to program all the
windowing registers are remove them from the per-mode register-value
tables.

Do not change the timing values from the ones reported in the register
tables to maintain bisectability.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 441 +++++++++++++++++++++++++------------
 1 file changed, 296 insertions(+), 145 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index eb4789ae6abf..9ba1b44d21f7 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -61,10 +61,16 @@
 #define OV5640_REG_AEC_PK_MANUAL	0x3503
 #define OV5640_REG_AEC_PK_REAL_GAIN	0x350a
 #define OV5640_REG_AEC_PK_VTS		0x350c
+#define OV5640_REG_TIMING_HS		0x3800
+#define OV5640_REG_TIMING_VS		0x3802
+#define OV5640_REG_TIMING_HW		0x3804
+#define OV5640_REG_TIMING_VH		0x3806
 #define OV5640_REG_TIMING_DVPHO		0x3808
 #define OV5640_REG_TIMING_DVPVO		0x380a
 #define OV5640_REG_TIMING_HTS		0x380c
 #define OV5640_REG_TIMING_VTS		0x380e
+#define OV5640_REG_TIMING_HOFFS		0x3810
+#define OV5640_REG_TIMING_VOFFS		0x3812
 #define OV5640_REG_TIMING_TC_REG20	0x3820
 #define OV5640_REG_TIMING_TC_REG21	0x3821
 #define OV5640_REG_AEC_CTRL00		0x3a00
@@ -276,12 +282,17 @@ struct ov5640_mode_info {
 	enum ov5640_mode_id id;
 	enum ov5640_downsize_mode dn_mode;
 	enum ov5640_pixel_rate_id pixel_rate;
-	u32 hact;
+	/* Analog crop rectangle. */
+	struct v4l2_rect analog_crop;
+	/* Visibile crop: from analog crop top-left corner. */
+	struct v4l2_rect crop;
+	/* Total pixels per line: crop.width + fixed hblank. */
 	u32 htot;
-	u32 vact;
-	u32 vtot;
+	/* Default vertical blanking: frame height = crop.height + vblank. */
+	u32 vblank_def;
 	const struct reg_value *reg_data;
 	u32 reg_data_size;
+	/* DVP only; ignored in MIPI mode. */
 	u32 max_fps;
 };
 
@@ -387,11 +398,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
 	{0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -459,11 +466,7 @@ static const struct reg_value ov5640_setting_VGA_640_480[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -478,11 +481,7 @@ static const struct reg_value ov5640_setting_XGA_1024_768[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -497,11 +496,7 @@ static const struct reg_value ov5640_setting_QVGA_320_240[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -516,11 +511,7 @@ static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -534,11 +525,7 @@ static const struct reg_value ov5640_setting_QCIF_176_144[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -553,11 +540,7 @@ static const struct reg_value ov5640_setting_NTSC_720_480[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -572,11 +555,7 @@ static const struct reg_value ov5640_setting_PAL_720_576[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -591,11 +570,7 @@ static const struct reg_value ov5640_setting_720P_1280_720[] = {
 	{0x3c07, 0x07, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+	{0x3815, 0x31, 0, 0},
 	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
 	{0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
@@ -610,11 +585,7 @@ static const struct reg_value ov5640_setting_1080P_1920_1080[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x11, 0, 0},
-	{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+	{0x3815, 0x11, 0, 0},
 	{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
 	{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -625,9 +596,6 @@ static const struct reg_value ov5640_setting_1080P_1920_1080[] = {
 	{0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0},
 	{0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-	{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
-	{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
-	{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
 	{0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
 	{0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
 	{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
@@ -641,11 +609,7 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x11, 0, 0},
-	{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-	{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
-	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
-	{0x3810, 0x00, 0, 0},
-	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+	{0x3815, 0x11, 0, 0},
 	{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
 	{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
 	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
@@ -658,96 +622,250 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
 
 /* power-on sensor init reg table */
 static const struct ov5640_mode_info ov5640_mode_init_data = {
-	0, SUBSAMPLING,
-	OV5640_PIXEL_RATE_96M,
-	640, 1896, 480, 984,
-	ov5640_init_setting_30fps_VGA,
-	ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
-	OV5640_30_FPS,
+		.id		= 0,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_96M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 4,
+			.width	= 2623,
+			.height	= 1947,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 6,
+			.width	= 640,
+			.height	= 480,
+		},
+		.htot		= 1896,
+		.vblank_def	= 504,
+		.reg_data	= ov5640_init_setting_30fps_VGA,
+		.reg_data_size	= ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
+		.max_fps	= OV5640_30_FPS
 };
 
 static const struct ov5640_mode_info
 ov5640_mode_data[OV5640_NUM_MODES] = {
 	{
 		/* 160x120 */
-		OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
-		OV5640_PIXEL_RATE_48M,
-		160, 1896, 120, 984,
-		ov5640_setting_QQVGA_160_120,
-		ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
-		OV5640_30_FPS
+		.id		= OV5640_MODE_QQVGA_160_120,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_48M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 4,
+			.width	= 2623,
+			.height	= 1947,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 6,
+			.width	= 160,
+			.height	= 120,
+		},
+		.htot		= 1896,
+		.vblank_def	= 864,
+		.reg_data	= ov5640_setting_QQVGA_160_120,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
+		.max_fps	= OV5640_30_FPS
 	}, {
 		/* 176x144 */
-		OV5640_MODE_QCIF_176_144, SUBSAMPLING,
-		OV5640_PIXEL_RATE_48M,
-		176, 1896, 144, 984,
-		ov5640_setting_QCIF_176_144,
-		ARRAY_SIZE(ov5640_setting_QCIF_176_144),
-		OV5640_30_FPS
+		.id		= OV5640_MODE_QCIF_176_144,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_48M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 4,
+			.width	= 2623,
+			.height	= 1947,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 6,
+			.width	= 176,
+			.height	= 144,
+		},
+		.htot		= 1896,
+		.vblank_def	= 840,
+		.reg_data	= ov5640_setting_QCIF_176_144,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QCIF_176_144),
+		.max_fps	= OV5640_30_FPS
 	}, {
 		/* 320x240 */
-		OV5640_MODE_QVGA_320_240, SUBSAMPLING,
-		OV5640_PIXEL_RATE_48M,
-		320, 1896, 240, 984,
-		ov5640_setting_QVGA_320_240,
-		ARRAY_SIZE(ov5640_setting_QVGA_320_240),
-		OV5640_30_FPS
+		.id		= OV5640_MODE_QVGA_320_240,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_48M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 4,
+			.width	= 2623,
+			.height	= 1947,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 6,
+			.width	= 320,
+			.height	= 240,
+		},
+		.htot		= 1896,
+		.vblank_def	= 744,
+		.reg_data	= ov5640_setting_QVGA_320_240,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QVGA_320_240),
+		.max_fps	= OV5640_30_FPS
 	}, {
 		/* 640x480 */
-		OV5640_MODE_VGA_640_480, SUBSAMPLING,
-		OV5640_PIXEL_RATE_48M,
-		640, 1896, 480, 1080,
-		ov5640_setting_VGA_640_480,
-		ARRAY_SIZE(ov5640_setting_VGA_640_480),
-		OV5640_60_FPS
+		.id		= OV5640_MODE_VGA_640_480,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_48M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 4,
+			.width	= 2623,
+			.height	= 1947,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 6,
+			.width	= 640,
+			.height	= 480,
+		},
+		.htot		= 1896,
+		.vblank_def	= 600,
+		.reg_data	= ov5640_setting_VGA_640_480,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_VGA_640_480),
+		.max_fps	= OV5640_60_FPS
 	}, {
 		/* 720x480 */
-		OV5640_MODE_NTSC_720_480, SUBSAMPLING,
-		OV5640_PIXEL_RATE_96M,
-		720, 1896, 480, 984,
-		ov5640_setting_NTSC_720_480,
-		ARRAY_SIZE(ov5640_setting_NTSC_720_480),
-		OV5640_30_FPS
+		.id		= OV5640_MODE_NTSC_720_480,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_96M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 4,
+			.width	= 2623,
+			.height	= 1947,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 60,
+			.width	= 720,
+			.height	= 480,
+		},
+		.htot		= 1896,
+		.vblank_def	= 504,
+		.reg_data	= ov5640_setting_NTSC_720_480,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_NTSC_720_480),
+		.max_fps	= OV5640_30_FPS
 	}, {
 		/* 720x576 */
-		OV5640_MODE_PAL_720_576, SUBSAMPLING,
-		OV5640_PIXEL_RATE_96M,
-		720, 1896, 576, 984,
-		ov5640_setting_PAL_720_576,
-		ARRAY_SIZE(ov5640_setting_PAL_720_576),
-		OV5640_30_FPS
+		.id		= OV5640_MODE_PAL_720_576,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_96M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 4,
+			.width	= 2623,
+			.height	= 1947,
+		},
+		.crop = {
+			.left	= 56,
+			.top	= 6,
+			.width	= 720,
+			.height	= 576,
+		},
+		.htot		= 1896,
+		.vblank_def	= 408,
+		.reg_data	= ov5640_setting_PAL_720_576,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_PAL_720_576),
+		.max_fps	= OV5640_30_FPS
 	}, {
 		/* 1024x768 */
-		OV5640_MODE_XGA_1024_768, SUBSAMPLING,
-		OV5640_PIXEL_RATE_96M,
-		1024, 1896, 768, 1080,
-		ov5640_setting_XGA_1024_768,
-		ARRAY_SIZE(ov5640_setting_XGA_1024_768),
-		OV5640_30_FPS
+		.id		= OV5640_MODE_XGA_1024_768,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_96M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 4,
+			.width	= 2623,
+			.height	= 1947,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 6,
+			.width	= 1024,
+			.height	= 768,
+		},
+		.htot		= 1896,
+		.vblank_def	= 312,
+		.reg_data	= ov5640_setting_XGA_1024_768,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_XGA_1024_768),
+		.max_fps	= OV5640_30_FPS
 	}, {
 		/* 1280x720 */
-		OV5640_MODE_720P_1280_720, SUBSAMPLING,
-		OV5640_PIXEL_RATE_124M,
-		1280, 1892, 720, 740,
-		ov5640_setting_720P_1280_720,
-		ARRAY_SIZE(ov5640_setting_720P_1280_720),
-		OV5640_30_FPS
+		.id		= OV5640_MODE_720P_1280_720,
+		.dn_mode	= SUBSAMPLING,
+		.pixel_rate	= OV5640_PIXEL_RATE_124M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 250,
+			.width	= 2623,
+			.height	= 1705,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 4,
+			.width	= 1280,
+			.height	= 720,
+		},
+		.htot		= 1892,
+		.vblank_def	= 20,
+		.reg_data	= ov5640_setting_720P_1280_720,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_720P_1280_720),
+		.max_fps	= OV5640_30_FPS
 	}, {
 		/* 1920x1080 */
-		OV5640_MODE_1080P_1920_1080, SCALING,
-		OV5640_PIXEL_RATE_148M,
-		1920, 2500, 1080, 1120,
-		ov5640_setting_1080P_1920_1080,
-		ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
-		OV5640_30_FPS
+		.id		= OV5640_MODE_1080P_1920_1080,
+		.dn_mode	= SCALING,
+		.pixel_rate	= OV5640_PIXEL_RATE_148M,
+		.analog_crop = {
+			.left	= 336,
+			.top	= 434,
+			.width	= 2287,
+			.height	= 1521,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 4,
+			.width	= 1920,
+			.height	= 1080,
+		},
+		.htot		= 2500,
+		.vblank_def	= 40,
+		.reg_data	= ov5640_setting_1080P_1920_1080,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
+		.max_fps	= OV5640_30_FPS
 	}, {
 		/* 2592x1944 */
-		OV5640_MODE_QSXGA_2592_1944, SCALING,
-		OV5640_PIXEL_RATE_168M,
-		2592, 2844, 1944, 1968,
-		ov5640_setting_QSXGA_2592_1944,
-		ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
-		OV5640_15_FPS
+		.id		= OV5640_MODE_QSXGA_2592_1944,
+		.dn_mode	= SCALING,
+		.pixel_rate	= OV5640_PIXEL_RATE_168M,
+		.analog_crop = {
+			.left	= 0,
+			.top	= 0,
+			.width	= 2623,
+			.height	= 1951,
+		},
+		.crop = {
+			.left	= 16,
+			.top	= 4,
+			.width	= 2592,
+			.height	= 1944,
+		},
+		.htot		= 2844,
+		.vblank_def	= 24,
+		.reg_data	= ov5640_setting_QSXGA_2592_1944,
+		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
+		.max_fps	= OV5640_15_FPS
 	},
 };
 
@@ -1150,7 +1268,8 @@ static u32 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
 {
 	u32 rate;
 
-	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
+	rate = sensor->current_mode->htot
+	     * (sensor->current_mode->crop.height + sensor->current_mode->vblank_def);
 	rate *= ov5640_framerates[sensor->current_fr];
 
 	return rate;
@@ -1234,17 +1353,21 @@ static int ov5640_set_jpeg_timings(struct ov5640_dev *sensor,
 	if (ret < 0)
 		return ret;
 
-	ret = ov5640_write_reg16(sensor, OV5640_REG_VFIFO_HSIZE, mode->hact);
+	ret = ov5640_write_reg16(sensor, OV5640_REG_VFIFO_HSIZE,
+				 mode->crop.width);
 	if (ret < 0)
 		return ret;
 
-	return ov5640_write_reg16(sensor, OV5640_REG_VFIFO_VSIZE, mode->vact);
+	return ov5640_write_reg16(sensor, OV5640_REG_VFIFO_VSIZE,
+				  mode->crop.height);
 }
 
 /* download ov5640 settings to sensor through i2c */
 static int ov5640_set_timings(struct ov5640_dev *sensor,
 			      const struct ov5640_mode_info *mode)
 {
+	const struct v4l2_rect *analog_crop = &mode->analog_crop;
+	const struct v4l2_rect *crop = &mode->crop;
 	int ret;
 
 	if (sensor->fmt.code == MEDIA_BUS_FMT_JPEG_1X8) {
@@ -1253,11 +1376,35 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
 			return ret;
 	}
 
-	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HS, analog_crop->left);
+	if (ret < 0)
+		return ret;
+
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VS, analog_crop->top);
+	if (ret < 0)
+		return ret;
+
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW, analog_crop->width);
+	if (ret < 0)
+		return ret;
+
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH, analog_crop->height);
+	if (ret < 0)
+		return ret;
+
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HOFFS, crop->left);
+	if (ret < 0)
+		return ret;
+
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VOFFS, crop->top);
+	if (ret < 0)
+		return ret;
+
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, crop->width);
 	if (ret < 0)
 		return ret;
 
-	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, crop->height);
 	if (ret < 0)
 		return ret;
 
@@ -1265,7 +1412,12 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
 	if (ret < 0)
 		return ret;
 
-	return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS,
+				 crop->height + mode->vblank_def);
+	if (ret < 0)
+		return ret;
+
+	return 0;
 }
 
 static int ov5640_load_regs(struct ov5640_dev *sensor,
@@ -1693,11 +1845,11 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
 
 	mode = v4l2_find_nearest_size(ov5640_mode_data,
 				      ARRAY_SIZE(ov5640_mode_data),
-				      hact, vact,
-				      width, height);
+				      crop.width, crop.height, width, height);
 
 	if (!mode ||
-	    (!nearest && (mode->hact != width || mode->vact != height)))
+	    (!nearest &&
+	     (mode->crop.width != width || mode->crop.height != height)))
 		return NULL;
 
 	/* Check to see if the current mode exceeds the max frame rate */
@@ -2381,8 +2533,8 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
 	mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true);
 	if (!mode)
 		return -EINVAL;
-	fmt->width = mode->hact;
-	fmt->height = mode->vact;
+	fmt->width = mode->crop.width;
+	fmt->height = mode->crop.height;
 
 	if (new_mode)
 		*new_mode = mode;
@@ -3014,11 +3166,9 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
 	if (fse->index >= OV5640_NUM_MODES)
 		return -EINVAL;
 
-	fse->min_width =
-		ov5640_mode_data[fse->index].hact;
+	fse->min_width = ov5640_mode_data[fse->index].crop.width;
 	fse->max_width = fse->min_width;
-	fse->min_height =
-		ov5640_mode_data[fse->index].vact;
+	fse->min_height = ov5640_mode_data[fse->index].crop.height;
 	fse->max_height = fse->min_height;
 
 	return 0;
@@ -3082,15 +3232,16 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
 	mode = sensor->current_mode;
 
 	frame_rate = ov5640_try_frame_interval(sensor, &fi->interval,
-					       mode->hact, mode->vact);
+					       mode->crop.width,
+					       mode->crop.height);
 	if (frame_rate < 0) {
 		/* Always return a valid frame interval value */
 		fi->interval = sensor->frame_interval;
 		goto out;
 	}
 
-	mode = ov5640_find_mode(sensor, frame_rate, mode->hact,
-				mode->vact, true);
+	mode = ov5640_find_mode(sensor, frame_rate, mode->crop.width,
+				mode->crop.height, true);
 	if (!mode) {
 		ret = -EINVAL;
 		goto out;
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 09/23] media: ov5640: Fix 720x480 in RGB888 mode
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (7 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 08/23] media: ov5640: Rework timings programming Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-20 12:50   ` Laurent Pinchart
  2022-02-10 11:04 ` [PATCH v2 10/23] media: ov5640: Rework analog crop rectangles Jacopo Mondi
                   ` (16 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Adjust the left crop of 720x480 to enable capture in RGB888 format,
which is otherwise broken.

The 56 pixels alignment has been copied from the 720x576 mode.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 9ba1b44d21f7..f817f865ad16 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -746,7 +746,7 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 			.height	= 1947,
 		},
 		.crop = {
-			.left	= 16,
+			.left	= 56,
 			.top	= 60,
 			.width	= 720,
 			.height	= 480,
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 10/23] media: ov5640: Rework analog crop rectangles
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (8 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 09/23] media: ov5640: Fix 720x480 in RGB888 mode Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-11  9:34   ` [v2.1] " Jacopo Mondi
  2022-02-10 11:04 ` [PATCH v2 11/23] media: ov5640: Re-sort per-mode register tables Jacopo Mondi
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

The OV5640 pixel array is composed as:
- vertically: 16 dummy columns, 1944 valid ones and 16 dummy columns
- horizontally: 8 optical black lines, 6 dummy ones, 2592 valid and 6
  dummies

Adjust the analog crop rectangle in all modes to:
- Skip the first 16 dummy columns
- Skip the first 14 black/dummy lines
- Pass the whole valid pixel array size to the ISP for all modes except
  1920x1080 which is obtained by cropping the valid pixel array.

Adjust how timings is programmed to comply with the new definitions.

Tested in RGB565, UYVY, RGB565 and RGB888 modes.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 138 +++++++++++++++++++++----------------
 1 file changed, 79 insertions(+), 59 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index f817f865ad16..72b78201f089 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -626,14 +626,14 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_96M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			.left	= 2,
+			.top	= 4,
 			.width	= 640,
 			.height	= 480,
 		},
@@ -644,22 +644,23 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
 		.max_fps	= OV5640_30_FPS
 };
 
-static const struct ov5640_mode_info
-ov5640_mode_data[OV5640_NUM_MODES] = {
+static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 	{
 		/* 160x120 */
 		.id		= OV5640_MODE_QQVGA_160_120,
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_48M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 160,
 			.height	= 120,
 		},
@@ -674,14 +675,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_48M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 176,
 			.height	= 144,
 		},
@@ -696,14 +699,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_48M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 320,
 			.height	= 240,
 		},
@@ -718,14 +723,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_48M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 640,
 			.height	= 480,
 		},
@@ -740,12 +747,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_96M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
+			/* Maintain a minimum digital crop processing margins. */
 			.left	= 56,
 			.top	= 60,
 			.width	= 720,
@@ -762,12 +771,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_96M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
+			/* Maintain a minimum digital crop processing margins. */
 			.left	= 56,
 			.top	= 6,
 			.width	= 720,
@@ -784,14 +795,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_96M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 1024,
 			.height	= 768,
 		},
@@ -806,13 +819,15 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_124M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 250,
-			.width	= 2623,
-			.height	= 1705,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
 			.top	= 4,
 			.width	= 1280,
 			.height	= 720,
@@ -828,12 +843,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SCALING,
 		.pixel_rate	= OV5640_PIXEL_RATE_148M,
 		.analog_crop = {
+			/* Crop the full valid pixel array in the center. */
 			.left	= 336,
 			.top	= 434,
-			.width	= 2287,
-			.height	= 1521,
+			.width	= 1952,
+			.height	= 1088,
 		},
 		.crop = {
+			/* Maintain a larger digital crop processing margins. */
 			.left	= 16,
 			.top	= 4,
 			.width	= 1920,
@@ -850,16 +867,17 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SCALING,
 		.pixel_rate	= OV5640_PIXEL_RATE_168M,
 		.analog_crop = {
+			/* Give more processing margin to full resolution. */
 			.left	= 0,
 			.top	= 0,
-			.width	= 2623,
-			.height	= 1951,
+			.width	= OV5640_NATIVE_WIDTH,
+			.height	= 1952,
 		},
 		.crop = {
 			.left	= 16,
 			.top	= 4,
-			.width	= 2592,
-			.height	= 1944,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.htot		= 2844,
 		.vblank_def	= 24,
@@ -1384,11 +1402,13 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
 	if (ret < 0)
 		return ret;
 
-	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW, analog_crop->width);
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW,
+				 analog_crop->width + analog_crop->left - 1);
 	if (ret < 0)
 		return ret;
 
-	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH, analog_crop->height);
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH,
+				 analog_crop->height + analog_crop->top - 1);
 	if (ret < 0)
 		return ret;
 
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 11/23] media: ov5640: Re-sort per-mode register tables
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (9 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 10/23] media: ov5640: Rework analog crop rectangles Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-20 12:52   ` Laurent Pinchart
  2022-02-10 11:04 ` [PATCH v2 12/23] media: ov5640: Remove ov5640_mode_init_data Jacopo Mondi
                   ` (14 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

The per-mode register tables are not sorted by size. Fix it.

Cosmetic change only.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 72b78201f089..17835e71665a 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -462,7 +462,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
 	{0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
 };
 
-static const struct reg_value ov5640_setting_VGA_640_480[] = {
+static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
@@ -473,11 +473,10 @@ static const struct reg_value ov5640_setting_VGA_640_480[] = {
 	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
 	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
 	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
+	{0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
 };
 
-static const struct reg_value ov5640_setting_XGA_1024_768[] = {
+static const struct reg_value ov5640_setting_QCIF_176_144[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
@@ -507,7 +506,7 @@ static const struct reg_value ov5640_setting_QVGA_320_240[] = {
 	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
 };
 
-static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
+static const struct reg_value ov5640_setting_VGA_640_480[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
@@ -518,10 +517,11 @@ static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
 	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
 	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
 	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-	{0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
+	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
 };
 
-static const struct reg_value ov5640_setting_QCIF_176_144[] = {
+static const struct reg_value ov5640_setting_NTSC_720_480[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
@@ -536,7 +536,7 @@ static const struct reg_value ov5640_setting_QCIF_176_144[] = {
 	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
 };
 
-static const struct reg_value ov5640_setting_NTSC_720_480[] = {
+static const struct reg_value ov5640_setting_PAL_720_576[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
@@ -551,7 +551,7 @@ static const struct reg_value ov5640_setting_NTSC_720_480[] = {
 	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
 };
 
-static const struct reg_value ov5640_setting_PAL_720_576[] = {
+static const struct reg_value ov5640_setting_XGA_1024_768[] = {
 	{0x3c07, 0x08, 0, 0},
 	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
 	{0x3814, 0x31, 0, 0},
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 12/23] media: ov5640: Remove ov5640_mode_init_data
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (10 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 11/23] media: ov5640: Re-sort per-mode register tables Jacopo Mondi
@ 2022-02-10 11:04 ` Jacopo Mondi
  2022-02-20 12:58   ` Laurent Pinchart
  2022-02-10 11:09 ` [PATCH v2 13/23] media: ov5640: Add HBLANK control Jacopo Mondi
                   ` (13 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:04 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

The ov5640_mode_init_data is a fictional sensor more which is used to
program the initial sensor settings.

It is only used to initialize the sensor and can be replaced
it with a throw-away mode which just wraps the register table.

Also rename the register table to drop the format from the name to make
it clear an actual sensor mode has to be applied after the initial
programming.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 47 ++++++++------------------------------
 1 file changed, 10 insertions(+), 37 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 17835e71665a..2a922224ca9d 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -382,7 +382,7 @@ static inline bool ov5640_is_csi2(struct ov5640_dev *sensor)
  * over i2c.
  */
 /* YUV422 UYVY VGA@30fps */
-static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
+static const struct reg_value ov5640_init_setting[] = {
 	{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
 	{0x3103, 0x03, 0, 0}, {0x3630, 0x36, 0, 0},
 	{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
@@ -620,30 +620,6 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
 	{0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70},
 };
 
-/* power-on sensor init reg table */
-static const struct ov5640_mode_info ov5640_mode_init_data = {
-		.id		= 0,
-		.dn_mode	= SUBSAMPLING,
-		.pixel_rate	= OV5640_PIXEL_RATE_96M,
-		.analog_crop = {
-			.left	= OV5640_PIXEL_ARRAY_LEFT,
-			.top	= OV5640_PIXEL_ARRAY_TOP,
-			.width	= OV5640_PIXEL_ARRAY_WIDTH,
-			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
-		},
-		.crop = {
-			.left	= 2,
-			.top	= 4,
-			.width	= 640,
-			.height	= 480,
-		},
-		.htot		= 1896,
-		.vblank_def	= 504,
-		.reg_data	= ov5640_init_setting_30fps_VGA,
-		.reg_data_size	= ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
-		.max_fps	= OV5640_30_FPS
-};
-
 static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 	{
 		/* 160x120 */
@@ -1440,17 +1416,16 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
 	return 0;
 }
 
-static int ov5640_load_regs(struct ov5640_dev *sensor,
-			    const struct ov5640_mode_info *mode)
+static void ov5640_load_regs(struct ov5640_dev *sensor,
+			     const struct reg_value *regs, unsigned int regnum)
 {
-	const struct reg_value *regs = mode->reg_data;
 	unsigned int i;
 	u32 delay_ms;
 	u16 reg_addr;
 	u8 mask, val;
 	int ret = 0;
 
-	for (i = 0; i < mode->reg_data_size; ++i, ++regs) {
+	for (i = 0; i < regnum; ++i, ++regs) {
 		delay_ms = regs->delay_ms;
 		reg_addr = regs->reg_addr;
 		val = regs->val;
@@ -1472,8 +1447,6 @@ static int ov5640_load_regs(struct ov5640_dev *sensor,
 		if (delay_ms)
 			usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
 	}
-
-	return ov5640_set_timings(sensor, mode);
 }
 
 static int ov5640_set_autoexposure(struct ov5640_dev *sensor, bool on)
@@ -1926,7 +1899,8 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
 		return ret;
 
 	/* Write capture setting */
-	ret = ov5640_load_regs(sensor, mode);
+	ov5640_load_regs(sensor, mode->reg_data, mode->reg_data_size);
+	ret = ov5640_set_timings(sensor, mode);
 	if (ret < 0)
 		return ret;
 
@@ -2050,7 +2024,8 @@ static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
 		return -EINVAL;
 
 	/* Write capture setting */
-	return ov5640_load_regs(sensor, mode);
+	ov5640_load_regs(sensor, mode->reg_data, mode->reg_data_size);
+	return ov5640_set_timings(sensor, mode);
 }
 
 static int ov5640_set_mode(struct ov5640_dev *sensor)
@@ -2148,10 +2123,8 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
 	int ret;
 
 	/* first load the initial register values */
-	ret = ov5640_load_regs(sensor, &ov5640_mode_init_data);
-	if (ret < 0)
-		return ret;
-	sensor->last_mode = &ov5640_mode_init_data;
+	ov5640_load_regs(sensor, ov5640_init_setting,
+			 ARRAY_SIZE(ov5640_init_setting));
 
 	ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
 			     (ilog2(OV5640_SCLK2X_ROOT_DIV) << 2) |
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 13/23] media: ov5640: Add HBLANK control
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (11 preceding siblings ...)
  2022-02-10 11:04 ` [PATCH v2 12/23] media: ov5640: Remove ov5640_mode_init_data Jacopo Mondi
@ 2022-02-10 11:09 ` Jacopo Mondi
  2022-02-10 11:09 ` [PATCH v2 14/23] media: ov5640: Add VBLANK control Jacopo Mondi
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:09 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

Add the HBLANK control as read-only.

The hblank value is fixed in the mode definition and is updated
everytime a new format is applied.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 2a922224ca9d..ade9adb43fda 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -300,6 +300,7 @@ struct ov5640_ctrls {
 	struct v4l2_ctrl_handler handler;
 	struct v4l2_ctrl *pixel_rate;
 	struct v4l2_ctrl *link_freq;
+	struct v4l2_ctrl *hblank;
 	struct {
 		struct v4l2_ctrl *auto_exp;
 		struct v4l2_ctrl *exposure;
@@ -2552,6 +2553,7 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
 	const struct ov5640_mode_info *mode = sensor->current_mode;
 	struct v4l2_mbus_framefmt *fmt = &sensor->fmt;
 	enum ov5640_pixel_rate_id pixel_rate_id = mode->pixel_rate;
+	unsigned int hblank;
 	unsigned int i = 0;
 	u32 pixel_rate;
 	s64 link_freq;
@@ -2604,6 +2606,10 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
 	__v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate, pixel_rate);
 	__v4l2_ctrl_s_ctrl(sensor->ctrls.link_freq, i);
 
+	hblank = mode->htot - mode->crop.width;
+	__v4l2_ctrl_modify_range(sensor->ctrls.hblank,
+				 hblank, hblank, 1, hblank);
+
 	return 0;
 }
 
@@ -3068,6 +3074,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 	const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
 	struct ov5640_ctrls *ctrls = &sensor->ctrls;
 	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+	unsigned int hblank;
 	int ret;
 
 	v4l2_ctrl_handler_init(hdl, 32);
@@ -3086,6 +3093,10 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 					ARRAY_SIZE(ov5640_csi2_link_freqs) - 1,
 					4, ov5640_csi2_link_freqs);
 
+	hblank = mode->htot - mode->crop.width;
+	ctrls->hblank = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HBLANK, hblank,
+					  hblank, 1, hblank);
+
 	/* Auto/manual white balance */
 	ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
 					   V4L2_CID_AUTO_WHITE_BALANCE,
@@ -3135,6 +3146,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 
 	ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	ctrls->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
 	ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 14/23] media: ov5640: Add VBLANK control
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (12 preceding siblings ...)
  2022-02-10 11:09 ` [PATCH v2 13/23] media: ov5640: Add HBLANK control Jacopo Mondi
@ 2022-02-10 11:09 ` Jacopo Mondi
  2022-02-20 13:01   ` Laurent Pinchart
  2022-02-10 11:10 ` [PATCH v2 15/23] media: ov5640: Fix durations to comply with FPS Jacopo Mondi
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:09 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

Add the VBLANK control which allows to select the duration of the
frame vertical blankings and allows to control the framerate.

The VBLANK control also modifies the exposure time range, which cannot
exceed the maximum frame length.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 53 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index ade9adb43fda..30b706a98eb9 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -29,6 +29,12 @@
 #define OV5640_XCLK_MIN  6000000
 #define OV5640_XCLK_MAX 54000000
 
+#define OV5640_LINK_RATE_MAX	490000000U
+
+/* FIXME: not documented. */
+#define OV5640_MIN_VBLANK	24
+#define OV5640_MAX_VTS		1968
+
 #define OV5640_DEFAULT_SLAVE_ID 0x3c
 
 #define OV5640_LINK_RATE_MAX		490000000U
@@ -301,6 +307,7 @@ struct ov5640_ctrls {
 	struct v4l2_ctrl *pixel_rate;
 	struct v4l2_ctrl *link_freq;
 	struct v4l2_ctrl *hblank;
+	struct v4l2_ctrl *vblank;
 	struct {
 		struct v4l2_ctrl *auto_exp;
 		struct v4l2_ctrl *exposure;
@@ -2553,6 +2560,7 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
 	const struct ov5640_mode_info *mode = sensor->current_mode;
 	struct v4l2_mbus_framefmt *fmt = &sensor->fmt;
 	enum ov5640_pixel_rate_id pixel_rate_id = mode->pixel_rate;
+	s64 exposure_val, exposure_max;
 	unsigned int hblank;
 	unsigned int i = 0;
 	u32 pixel_rate;
@@ -2610,6 +2618,20 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
 	__v4l2_ctrl_modify_range(sensor->ctrls.hblank,
 				 hblank, hblank, 1, hblank);
 
+	__v4l2_ctrl_modify_range(sensor->ctrls.vblank,
+				 OV5640_MIN_VBLANK,
+				 OV5640_MAX_VTS - mode->crop.height, 1,
+				 mode->vblank_def);
+	__v4l2_ctrl_s_ctrl(sensor->ctrls.vblank, mode->vblank_def);
+
+	exposure_max = mode->crop.height + mode->vblank_def - 4;
+	exposure_val = clamp((s64)sensor->ctrls.exposure->val,
+			     (s64)sensor->ctrls.exposure->minimum,
+			     (s64)exposure_max);
+	__v4l2_ctrl_modify_range(sensor->ctrls.exposure,
+				 sensor->ctrls.exposure->minimum,
+				 exposure_max, 1, exposure_val);
+
 	return 0;
 }
 
@@ -2982,6 +3004,15 @@ static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
 			      (BIT(2) | BIT(1)) : 0);
 }
 
+static int ov5640_set_ctrl_vblank(struct ov5640_dev *sensor, int value)
+{
+	const struct ov5640_mode_info *mode = sensor->current_mode;
+
+	/* Update the VTOT timing register value. */
+	return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS,
+				  mode->crop.height + value);
+}
+
 static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
@@ -3012,10 +3043,23 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
 	struct ov5640_dev *sensor = to_ov5640_dev(sd);
+	const struct ov5640_mode_info *mode = sensor->current_mode;
+	unsigned int exp_max;
 	int ret;
 
 	/* v4l2_ctrl_lock() locks our own mutex */
 
+	switch (ctrl->id) {
+	case V4L2_CID_VBLANK:
+		/* Update the exposure range to the newly programmed vblank. */
+		exp_max = mode->crop.height + ctrl->val - 4;
+		__v4l2_ctrl_modify_range(sensor->ctrls.exposure,
+					 sensor->ctrls.exposure->minimum,
+					 exp_max, sensor->ctrls.exposure->step,
+					 mode->vblank_def);
+		break;
+	}
+
 	/*
 	 * If the device is not powered up by the host driver do
 	 * not apply any controls to H/W at this time. Instead
@@ -3055,6 +3099,9 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
 	case V4L2_CID_VFLIP:
 		ret = ov5640_set_ctrl_vflip(sensor, ctrl->val);
 		break;
+	case V4L2_CID_VBLANK:
+		ret = ov5640_set_ctrl_vblank(sensor, ctrl->val);
+		break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -3074,6 +3121,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 	const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
 	struct ov5640_ctrls *ctrls = &sensor->ctrls;
 	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+	unsigned int max_vblank;
 	unsigned int hblank;
 	int ret;
 
@@ -3097,6 +3145,11 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 	ctrls->hblank = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HBLANK, hblank,
 					  hblank, 1, hblank);
 
+	max_vblank = OV5640_MAX_VTS - mode->crop.height;
+	ctrls->vblank = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VBLANK,
+					  OV5640_MIN_VBLANK, max_vblank,
+					  1, mode->vblank_def);
+
 	/* Auto/manual white balance */
 	ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
 					   V4L2_CID_AUTO_WHITE_BALANCE,
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 15/23] media: ov5640: Fix durations to comply with FPS
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (13 preceding siblings ...)
  2022-02-10 11:09 ` [PATCH v2 14/23] media: ov5640: Add VBLANK control Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-20 13:03   ` Laurent Pinchart
  2022-02-10 11:10 ` [PATCH v2 16/23] media: ov5640: Implement init_cfg Jacopo Mondi
                   ` (10 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

Now that the frame duration can be controlled by tuning the VBLANK
duration, fix all modes to comply with the reported FPS.

All modes run at 30 FPS except for full-resolution mode 2592x1944
which runs at 15FPS.

Tested on a 2 data lanes setup in UYVY and RGB565 modes.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 30b706a98eb9..dd7ff1bb580f 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -648,8 +648,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.width	= 160,
 			.height	= 120,
 		},
-		.htot		= 1896,
-		.vblank_def	= 864,
+		.htot		= 1600,
+		.vblank_def	= 878,
 		.reg_data	= ov5640_setting_QQVGA_160_120,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
 		.max_fps	= OV5640_30_FPS
@@ -672,8 +672,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.width	= 176,
 			.height	= 144,
 		},
-		.htot		= 1896,
-		.vblank_def	= 840,
+		.htot		= 1600,
+		.vblank_def	= 854,
 		.reg_data	= ov5640_setting_QCIF_176_144,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QCIF_176_144),
 		.max_fps	= OV5640_30_FPS
@@ -696,8 +696,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.width	= 320,
 			.height	= 240,
 		},
-		.htot		= 1896,
-		.vblank_def	= 744,
+		.htot		= 1600,
+		.vblank_def	= 760,
 		.reg_data	= ov5640_setting_QVGA_320_240,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QVGA_320_240),
 		.max_fps	= OV5640_30_FPS
@@ -720,8 +720,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.width	= 640,
 			.height	= 480,
 		},
-		.htot		= 1896,
-		.vblank_def	= 600,
+		.htot		= 1600,
+		.vblank_def	= 520,
 		.reg_data	= ov5640_setting_VGA_640_480,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_VGA_640_480),
 		.max_fps	= OV5640_60_FPS
@@ -745,7 +745,7 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.height	= 480,
 		},
 		.htot		= 1896,
-		.vblank_def	= 504,
+		.vblank_def	= 1206,
 		.reg_data	= ov5640_setting_NTSC_720_480,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_NTSC_720_480),
 		.max_fps	= OV5640_30_FPS
@@ -769,7 +769,7 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.height	= 576,
 		},
 		.htot		= 1896,
-		.vblank_def	= 408,
+		.vblank_def	= 1110,
 		.reg_data	= ov5640_setting_PAL_720_576,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_PAL_720_576),
 		.max_fps	= OV5640_30_FPS
@@ -793,7 +793,7 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.height	= 768,
 		},
 		.htot		= 1896,
-		.vblank_def	= 312,
+		.vblank_def	= 918,
 		.reg_data	= ov5640_setting_XGA_1024_768,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_XGA_1024_768),
 		.max_fps	= OV5640_30_FPS
@@ -816,8 +816,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.width	= 1280,
 			.height	= 720,
 		},
-		.htot		= 1892,
-		.vblank_def	= 20,
+		.htot		= 1600,
+		.vblank_def	= 560,
 		.reg_data	= ov5640_setting_720P_1280_720,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_720P_1280_720),
 		.max_fps	= OV5640_30_FPS
@@ -840,8 +840,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 			.width	= 1920,
 			.height	= 1080,
 		},
-		.htot		= 2500,
-		.vblank_def	= 40,
+		.htot		= 2234,
+		.vblank_def	= 24,
 		.reg_data	= ov5640_setting_1080P_1920_1080,
 		.reg_data_size	= ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
 		.max_fps	= OV5640_30_FPS
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 16/23] media: ov5640: Implement init_cfg
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (14 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 15/23] media: ov5640: Fix durations to comply with FPS Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-10 11:10 ` [PATCH v2 17/23] media: ov5640: Implement get_selection Jacopo Mondi
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

Implement the init_cfg pad operation to initialize the subdev state
format to the default one.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index dd7ff1bb580f..8b90fab26d16 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -390,6 +390,18 @@ static inline bool ov5640_is_csi2(struct ov5640_dev *sensor)
  * over i2c.
  */
 /* YUV422 UYVY VGA@30fps */
+
+static const struct v4l2_mbus_framefmt ov5640_default_fmt = {
+	.code = MEDIA_BUS_FMT_UYVY8_2X8,
+	.width = 640,
+	.height = 480,
+	.colorspace = V4L2_COLORSPACE_SRGB,
+	.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB),
+	.quantization = V4L2_QUANTIZATION_FULL_RANGE,
+	.xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB),
+	.field = V4L2_FIELD_NONE,
+};
+
 static const struct reg_value ov5640_init_setting[] = {
 	{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
 	{0x3103, 0x03, 0, 0}, {0x3630, 0x36, 0, 0},
@@ -3367,6 +3379,16 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
 	return ret;
 }
 
+static int ov5640_init_cfg(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_state *state)
+{
+	struct v4l2_mbus_framefmt *fmt = v4l2_subdev_get_try_format(sd, state, 0);
+
+	*fmt = ov5640_default_fmt;
+
+	return 0;
+}
+
 static const struct v4l2_subdev_core_ops ov5640_core_ops = {
 	.s_power = ov5640_s_power,
 	.log_status = v4l2_ctrl_subdev_log_status,
@@ -3381,6 +3403,7 @@ static const struct v4l2_subdev_video_ops ov5640_video_ops = {
 };
 
 static const struct v4l2_subdev_pad_ops ov5640_pad_ops = {
+	.init_cfg = ov5640_init_cfg,
 	.enum_mbus_code = ov5640_enum_mbus_code,
 	.get_fmt = ov5640_get_fmt,
 	.set_fmt = ov5640_set_fmt,
@@ -3439,7 +3462,6 @@ static int ov5640_probe(struct i2c_client *client)
 	struct device *dev = &client->dev;
 	struct fwnode_handle *endpoint;
 	struct ov5640_dev *sensor;
-	struct v4l2_mbus_framefmt *fmt;
 	u32 rotation;
 	int ret;
 
@@ -3453,15 +3475,7 @@ static int ov5640_probe(struct i2c_client *client)
 	 * default init sequence initialize sensor to
 	 * YUV422 UYVY VGA@30fps
 	 */
-	fmt = &sensor->fmt;
-	fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
-	fmt->colorspace = V4L2_COLORSPACE_SRGB;
-	fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-	fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-	fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-	fmt->width = 640;
-	fmt->height = 480;
-	fmt->field = V4L2_FIELD_NONE;
+	sensor->fmt = ov5640_default_fmt;
 	sensor->frame_interval.numerator = 1;
 	sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS];
 	sensor->current_fr = OV5640_30_FPS;
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 17/23] media: ov5640: Implement get_selection
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (15 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 16/23] media: ov5640: Implement init_cfg Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-20 13:06   ` Laurent Pinchart
  2022-02-10 11:10 ` [PATCH v2 18/23] media: ov5640: Limit frame_interval to DVP mode only Jacopo Mondi
                   ` (8 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

Implement the get_selection pad operation for the OV5640 sensor driver.

The supported targets report the sensor's native size, the active pixel
array size and the analog crop rectangle from which the image is
produced.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 51 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 8b90fab26d16..4ebb76d95849 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -35,6 +35,13 @@
 #define OV5640_MIN_VBLANK	24
 #define OV5640_MAX_VTS		1968
 
+#define OV5640_NATIVE_WIDTH		2624
+#define OV5640_NATIVE_HEIGHT		1964
+#define OV5640_PIXEL_ARRAY_TOP		14
+#define OV5640_PIXEL_ARRAY_LEFT		16
+#define OV5640_PIXEL_ARRAY_WIDTH	2592
+#define OV5640_PIXEL_ARRAY_HEIGHT	1944
+
 #define OV5640_DEFAULT_SLAVE_ID 0x3c
 
 #define OV5640_LINK_RATE_MAX		490000000U
@@ -2693,6 +2700,43 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
 	return ret;
 }
 
+static int ov5640_get_selection(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *sd_state,
+				struct v4l2_subdev_selection *sel)
+{
+	struct ov5640_dev *sensor = to_ov5640_dev(sd);
+	const struct ov5640_mode_info *mode = sensor->current_mode;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP: {
+		mutex_lock(&sensor->lock);
+		sel->r = mode->analog_crop;
+		mutex_unlock(&sensor->lock);
+
+		return 0;
+	}
+
+	case V4L2_SEL_TGT_NATIVE_SIZE:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		sel->r.top = 0;
+		sel->r.left = 0;
+		sel->r.width = OV5640_NATIVE_WIDTH;
+		sel->r.height = OV5640_NATIVE_HEIGHT;
+
+		return 0;
+
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.top = OV5640_PIXEL_ARRAY_TOP;
+		sel->r.left = OV5640_PIXEL_ARRAY_LEFT;
+		sel->r.width = OV5640_PIXEL_ARRAY_WIDTH;
+		sel->r.height = OV5640_PIXEL_ARRAY_HEIGHT;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static int ov5640_set_framefmt(struct ov5640_dev *sensor,
 			       struct v4l2_mbus_framefmt *format)
 {
@@ -3383,9 +3427,15 @@ static int ov5640_init_cfg(struct v4l2_subdev *sd,
 			   struct v4l2_subdev_state *state)
 {
 	struct v4l2_mbus_framefmt *fmt = v4l2_subdev_get_try_format(sd, state, 0);
+	struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, state, 0);
 
 	*fmt = ov5640_default_fmt;
 
+	crop->left = OV5640_PIXEL_ARRAY_LEFT;
+	crop->top = OV5640_PIXEL_ARRAY_TOP;
+	crop->width = OV5640_PIXEL_ARRAY_WIDTH;
+	crop->height = OV5640_PIXEL_ARRAY_HEIGHT;
+
 	return 0;
 }
 
@@ -3407,6 +3457,7 @@ static const struct v4l2_subdev_pad_ops ov5640_pad_ops = {
 	.enum_mbus_code = ov5640_enum_mbus_code,
 	.get_fmt = ov5640_get_fmt,
 	.set_fmt = ov5640_set_fmt,
+	.get_selection = ov5640_get_selection,
 	.enum_frame_size = ov5640_enum_frame_size,
 	.enum_frame_interval = ov5640_enum_frame_interval,
 };
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 18/23] media: ov5640: Limit frame_interval to DVP mode only
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (16 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 17/23] media: ov5640: Implement get_selection Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-10 11:10 ` [PATCH v2 19/23] media: ov5640: Register device properties Jacopo Mondi
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

In MIPI mode the frame rate control is performed by adjusting the
frame blankings and the s_frame_interval function is not used anymore.

Only check for the per-mode supported frame rate in DVP mode and do not
restrict MIPI mode.

Disallow enum/s/g_frame_interval if the chip is used in MIPI mode.

While at it re-indent one function which whose parameters were wrongly
aligned.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 4ebb76d95849..6695bb2b99b7 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -1872,8 +1872,13 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
 	     (mode->crop.width != width || mode->crop.height != height)))
 		return NULL;
 
-	/* Check to see if the current mode exceeds the max frame rate */
-	if (ov5640_framerates[fr] > ov5640_framerates[mode->max_fps])
+	/*
+	 * Check to see if the current mode exceeds the max frame rate.
+	 * Only DVP mode uses the frame rate set by s_frame_interval, MIPI
+	 * mode controls framerate by setting blankings.
+	 */
+	if (!ov5640_is_csi2(sensor) &&
+	    ov5640_framerates[fr] > ov5640_framerates[mode->max_fps])
 		return NULL;
 
 	return mode;
@@ -3288,15 +3293,17 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int ov5640_enum_frame_interval(
-	struct v4l2_subdev *sd,
-	struct v4l2_subdev_state *sd_state,
-	struct v4l2_subdev_frame_interval_enum *fie)
+static int ov5640_enum_frame_interval(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_state *sd_state,
+				      struct v4l2_subdev_frame_interval_enum *fie)
 {
 	struct ov5640_dev *sensor = to_ov5640_dev(sd);
 	struct v4l2_fract tpf;
 	int ret;
 
+	if (ov5640_is_csi2(sensor))
+		return -EINVAL;
+
 	if (fie->pad != 0)
 		return -EINVAL;
 	if (fie->index >= OV5640_NUM_FRAMERATES)
@@ -3319,6 +3326,9 @@ static int ov5640_g_frame_interval(struct v4l2_subdev *sd,
 {
 	struct ov5640_dev *sensor = to_ov5640_dev(sd);
 
+	if (ov5640_is_csi2(sensor))
+		return -EINVAL;
+
 	mutex_lock(&sensor->lock);
 	fi->interval = sensor->frame_interval;
 	mutex_unlock(&sensor->lock);
@@ -3333,6 +3343,9 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
 	const struct ov5640_mode_info *mode;
 	int frame_rate, ret = 0;
 
+	if (ov5640_is_csi2(sensor))
+		return -EINVAL;
+
 	if (fi->pad != 0)
 		return -EINVAL;
 
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 19/23] media: ov5640: Register device properties
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (17 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 18/23] media: ov5640: Limit frame_interval to DVP mode only Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-10 11:10 ` [PATCH v2 20/23] media: ov5640: Add RGB565_1X16 format Jacopo Mondi
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

Parse the device properties and register the rotation and orientation
V4L2 controls using v4l2_ctrl_new_fwnode_properties().

Remove the open-coded parsing of the rotation property and assume the
DTS is correct is providing either <0> or <180> as possible rotations.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 29 ++++++++++++-----------------
 1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 6695bb2b99b7..aecc8912099a 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -3182,6 +3182,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 	const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
 	struct ov5640_ctrls *ctrls = &sensor->ctrls;
 	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+	struct v4l2_fwnode_device_properties props;
 	unsigned int max_vblank;
 	unsigned int hblank;
 	int ret;
@@ -3258,6 +3259,17 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
 		goto free_ctrls;
 	}
 
+	ret = v4l2_fwnode_device_parse(&sensor->i2c_client->dev, &props);
+	if (ret)
+		goto free_ctrls;
+
+	if (props.rotation == 180)
+		sensor->upside_down = true;
+
+	ret = v4l2_ctrl_new_fwnode_properties(hdl, ops, &props);
+	if (ret)
+		goto free_ctrls;
+
 	ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	ctrls->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
@@ -3526,7 +3538,6 @@ static int ov5640_probe(struct i2c_client *client)
 	struct device *dev = &client->dev;
 	struct fwnode_handle *endpoint;
 	struct ov5640_dev *sensor;
-	u32 rotation;
 	int ret;
 
 	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
@@ -3549,22 +3560,6 @@ static int ov5640_probe(struct i2c_client *client)
 
 	sensor->ae_target = 52;
 
-	/* optional indication of physical rotation of sensor */
-	ret = fwnode_property_read_u32(dev_fwnode(&client->dev), "rotation",
-				       &rotation);
-	if (!ret) {
-		switch (rotation) {
-		case 180:
-			sensor->upside_down = true;
-			fallthrough;
-		case 0:
-			break;
-		default:
-			dev_warn(dev, "%u degrees rotation is not supported, ignoring...\n",
-				 rotation);
-		}
-	}
-
 	endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
 						  NULL);
 	if (!endpoint) {
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 20/23] media: ov5640: Add RGB565_1X16 format
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (18 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 19/23] media: ov5640: Register device properties Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-20 13:07   ` Laurent Pinchart
  2022-02-10 11:10 ` [PATCH v2 21/23] media: ov5640: Add RGB888/BGR888 formats Jacopo Mondi
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

The driver already supports the 2X8_[LE|BE] variants of RGB565
formats.

As for CSI-2 the 2X8 variants do not apply, add RGB565_1X16 variant
with little-endian ordering of components as required by the CSI-2
specifications.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index aecc8912099a..3a21f4648acf 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -220,6 +220,10 @@ static const struct ov5640_pixfmt {
 		.code = MEDIA_BUS_FMT_RGB565_2X8_BE,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_RGB565_1X16,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 16,
 	}, {
 		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
 		.colorspace = V4L2_COLORSPACE_SRGB,
@@ -2763,6 +2767,7 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
 		mux = OV5640_FMT_MUX_YUV422;
 		break;
 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+	case MEDIA_BUS_FMT_RGB565_1X16:
 		/* RGB565 {g[2:0],b[4:0]},{r[4:0],g[5:3]} */
 		fmt = 0x6F;
 		mux = OV5640_FMT_MUX_RGB;
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 21/23] media: ov5640: Add RGB888/BGR888 formats
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (19 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 20/23] media: ov5640: Add RGB565_1X16 format Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-20 13:13   ` Laurent Pinchart
  2022-02-10 11:10 ` [PATCH v2 22/23] media: ov5640: Restrict sizes to mbus code Jacopo Mondi
                   ` (4 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

Add support for RGB888/BGR888 image formats.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 3a21f4648acf..f894570ac53c 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -224,6 +224,14 @@ static const struct ov5640_pixfmt {
 		.code = MEDIA_BUS_FMT_RGB565_1X16,
 		.colorspace = V4L2_COLORSPACE_SRGB,
 		.bpp = 16,
+	}, {
+		.code = MEDIA_BUS_FMT_RGB888_1X24,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 24,
+	}, {
+		.code = MEDIA_BUS_FMT_BGR888_1X24,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.bpp = 16,
 	}, {
 		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
 		.colorspace = V4L2_COLORSPACE_SRGB,
@@ -2777,6 +2785,16 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
 		fmt = 0x61;
 		mux = OV5640_FMT_MUX_RGB;
 		break;
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		/* RGB888: BGR */
+		fmt = 0x22;
+		mux = OV5640_FMT_MUX_RGB;
+		break;
+	case MEDIA_BUS_FMT_BGR888_1X24:
+		/* BGR888: RGB */
+		fmt = 0x23;
+		mux = OV5640_FMT_MUX_RGB;
+		break;
 	case MEDIA_BUS_FMT_JPEG_1X8:
 		/* YUV422, YUYV */
 		fmt = 0x30;
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 22/23] media: ov5640: Restrict sizes to mbus code
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (20 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 21/23] media: ov5640: Add RGB888/BGR888 formats Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-20 13:16   ` Laurent Pinchart
  2022-02-10 11:10 ` [PATCH v2 23/23] media: ov5640: Adjust format to bpp in s_fmt Jacopo Mondi
                   ` (3 subsequent siblings)
  25 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

The ov5640 driver supports different sizes for different mbus_codes.
In particular:

- 8bpp modes: high resolution sizes (>= 1280x720)
- 16bpp modes: all sizes
- 24bpp modes: low resolutions sizes (< 1280x720)

Restrict the frame sizes enumerations to the above constraints.

While at it, make sure the fse->mbus_code parameter is valid, and return
-EINVAL if it's not.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index f894570ac53c..81bf547a923e 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -3315,14 +3315,28 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
 				  struct v4l2_subdev_state *sd_state,
 				  struct v4l2_subdev_frame_size_enum *fse)
 {
+	u32 bpp = ov5640_code_to_bpp(fse->code);
+	unsigned int index = fse->index;
+
 	if (fse->pad != 0)
 		return -EINVAL;
-	if (fse->index >= OV5640_NUM_MODES)
+	if (!bpp)
+		return -EINVAL;
+
+	/* Only low-resolution modes are supported for 24bpp modes. */
+	if (bpp == 24 && index >= OV5640_MODE_720P_1280_720)
+		return -EINVAL;
+
+	/* Only high-resolutions modes are supported for 8bpp formats. */
+	if (bpp == 8)
+		index += OV5640_MODE_720P_1280_720;
+
+	if (index >= OV5640_NUM_MODES)
 		return -EINVAL;
 
-	fse->min_width = ov5640_mode_data[fse->index].crop.width;
+	fse->min_width = ov5640_mode_data[index].crop.width;
 	fse->max_width = fse->min_width;
-	fse->min_height = ov5640_mode_data[fse->index].crop.height;
+	fse->min_height = ov5640_mode_data[index].crop.height;
 	fse->max_height = fse->min_height;
 
 	return 0;
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* [PATCH v2 23/23] media: ov5640: Adjust format to bpp in s_fmt
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (21 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 22/23] media: ov5640: Restrict sizes to mbus code Jacopo Mondi
@ 2022-02-10 11:10 ` Jacopo Mondi
  2022-02-10 12:03 ` [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Tomi Valkeinen
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 11:10 UTC (permalink / raw)
  To: slongerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media, Jacopo Mondi

The ov5640 driver supports different sizes for different mbus_codes.
In particular:

- 8bpp modes: high resolution sizes (>= 1280x720)
- 16bpp modes: all sizes
- 24bpp modes: low resolutions sizes (< 1280x720)

Adjust the image sizes according to the above constraints.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ov5640.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 81bf547a923e..465b09176169 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -2563,6 +2563,7 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
 				   enum ov5640_frame_rate fr,
 				   const struct ov5640_mode_info **new_mode)
 {
+	unsigned int bpp = ov5640_code_to_bpp(fmt->code);
 	struct ov5640_dev *sensor = to_ov5640_dev(sd);
 	const struct ov5640_mode_info *mode;
 	int i;
@@ -2570,6 +2571,17 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
 	mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true);
 	if (!mode)
 		return -EINVAL;
+
+	/*
+	 * Adjust mode according to bpp:
+	 * - 8bpp modes work for resolution >= 1280x720
+	 * - 24bpp modes work resolution < 1280x720
+	 */
+	if (bpp == 8 && mode->crop.width < 1280)
+		mode = &ov5640_mode_data[OV5640_MODE_720P_1280_720];
+	else if (bpp == 24 && mode->crop.width > 1024)
+		mode = &ov5640_mode_data[OV5640_MODE_XGA_1024_768];
+
 	fmt->width = mode->crop.width;
 	fmt->height = mode->crop.height;
 
-- 
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (22 preceding siblings ...)
  2022-02-10 11:10 ` [PATCH v2 23/23] media: ov5640: Adjust format to bpp in s_fmt Jacopo Mondi
@ 2022-02-10 12:03 ` Tomi Valkeinen
  2022-02-10 12:10   ` Tomi Valkeinen
  2022-02-10 13:00 ` Tomi Valkeinen
  2022-02-11 10:09 ` Eugen.Hristev
  25 siblings, 1 reply; 64+ messages in thread
From: Tomi Valkeinen @ 2022-02-10 12:03 UTC (permalink / raw)
  To: Jacopo Mondi, Steve Longerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, hugues.fruchet, prabhakar.mahadev-lad.rj,
	aford173, festevam, Eugen.Hristev, jbrunet,
	Mauro Carvalho Chehab, linux-media

Hi,

On 10/02/2022 13:04, Jacopo Mondi wrote:
> v1:
> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
> 
> A branch for testing based on the most recent media-master is available at
> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> 
> If anyone with a DVP setup could verify I have not broken their use case
> I would very much appreciate that :)

What is this based on? I'm not able to apply. "error: sha1 information 
is lacking or useless"

  Tomi

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-10 12:03 ` [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Tomi Valkeinen
@ 2022-02-10 12:10   ` Tomi Valkeinen
  0 siblings, 0 replies; 64+ messages in thread
From: Tomi Valkeinen @ 2022-02-10 12:10 UTC (permalink / raw)
  To: Jacopo Mondi, Steve Longerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, hugues.fruchet, prabhakar.mahadev-lad.rj,
	aford173, festevam, Eugen.Hristev, jbrunet,
	Mauro Carvalho Chehab, linux-media

On 10/02/2022 14:03, Tomi Valkeinen wrote:
> Hi,
> 
> On 10/02/2022 13:04, Jacopo Mondi wrote:
>> v1:
>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>>
>> A branch for testing based on the most recent media-master is 
>> available at
>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
>>
>> If anyone with a DVP setup could verify I have not broken their use case
>> I would very much appreciate that :)
> 
> What is this based on? I'm not able to apply. "error: sha1 information 
> is lacking or useless"

Answering to myself: The branch url above had an extra #, so my git 
fetch didn't get the right branch. And in that branch there's an extra 
commit that this series was based on.

  Tomi

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (23 preceding siblings ...)
  2022-02-10 12:03 ` [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Tomi Valkeinen
@ 2022-02-10 13:00 ` Tomi Valkeinen
  2022-02-10 17:11   ` Jacopo Mondi
  2022-02-11  9:36   ` Jacopo Mondi
  2022-02-11 10:09 ` Eugen.Hristev
  25 siblings, 2 replies; 64+ messages in thread
From: Tomi Valkeinen @ 2022-02-10 13:00 UTC (permalink / raw)
  To: Jacopo Mondi, Steve Longerbeam
  Cc: laurent.pinchart, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, hugues.fruchet, prabhakar.mahadev-lad.rj,
	aford173, festevam, Eugen.Hristev, jbrunet,
	Mauro Carvalho Chehab, linux-media

On 10/02/2022 13:04, Jacopo Mondi wrote:
> v1:
> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249

You could rather point to lore.kernel.org, so that the intro letter and 
the discussions are also visible.

> A branch for testing based on the most recent media-master is available at
> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> 
> If anyone with a DVP setup could verify I have not broken their use case
> I would very much appreciate that :)
> 
> v1 -> v2:
> - rework the modes definition to process the full pixel array
> - rework get_selection to report the correct BOUND and DEFAULT targets
> - implement init_cfg
> - minor style changes as suggested by Laurent
> - test with 1 data lane

Very nice! I tested this on TI's DRA76 EVM (CSI-2). UYVY and RGB565, 
with the following resolutions: 160 120, 176 144, 320 240, 640 480, 720 
480, 720 576, 1024 768, 1280 720, 1920 1080.

All work. The only issue I saw was that with 1024x768 and 1280x720 
there's a thin vertical purple column on the right edge.

  Tomi

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-10 13:00 ` Tomi Valkeinen
@ 2022-02-10 17:11   ` Jacopo Mondi
  2022-02-11  7:55     ` Tomi Valkeinen
  2022-02-11  9:36   ` Jacopo Mondi
  1 sibling, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-10 17:11 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Steve Longerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Tomi

On Thu, Feb 10, 2022 at 03:00:21PM +0200, Tomi Valkeinen wrote:
> On 10/02/2022 13:04, Jacopo Mondi wrote:
> > v1:
> > https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>
> You could rather point to lore.kernel.org, so that the intro letter and the
> discussions are also visible.

Sure, here you go!
https://lore.kernel.org/linux-media/20220131143245.128089-1-jacopo@jmondi.org/

>
> > A branch for testing based on the most recent media-master is available at
> > https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> >
> > If anyone with a DVP setup could verify I have not broken their use case
> > I would very much appreciate that :)
> >
> > v1 -> v2:
> > - rework the modes definition to process the full pixel array
> > - rework get_selection to report the correct BOUND and DEFAULT targets
> > - implement init_cfg
> > - minor style changes as suggested by Laurent
> > - test with 1 data lane
>
> Very nice! I tested this on TI's DRA76 EVM (CSI-2). UYVY and RGB565, with
> the following resolutions: 160 120, 176 144, 320 240, 640 480, 720 480, 720
> 576, 1024 768, 1280 720, 1920 1080.

Great! A 2 data lanes setup I assume ? Have you been able to test the
framerate as well ?
>
> All work. The only issue I saw was that with 1024x768 and 1280x720 there's a
> thin vertical pueple column on the right edge.

Argh, you're right.
I'll see if I can fix them!

Thanks
   j
>
>  Tomi

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-10 17:11   ` Jacopo Mondi
@ 2022-02-11  7:55     ` Tomi Valkeinen
  2022-02-11  8:01       ` Tomi Valkeinen
  0 siblings, 1 reply; 64+ messages in thread
From: Tomi Valkeinen @ 2022-02-11  7:55 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

On 10/02/2022 19:11, Jacopo Mondi wrote:
> Hi Tomi
> 
> On Thu, Feb 10, 2022 at 03:00:21PM +0200, Tomi Valkeinen wrote:
>> On 10/02/2022 13:04, Jacopo Mondi wrote:
>>> v1:
>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>>
>> You could rather point to lore.kernel.org, so that the intro letter and the
>> discussions are also visible.
> 
> Sure, here you go!
> https://lore.kernel.org/linux-media/20220131143245.128089-1-jacopo@jmondi.org/
> 
>>
>>> A branch for testing based on the most recent media-master is available at
>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
>>>
>>> If anyone with a DVP setup could verify I have not broken their use case
>>> I would very much appreciate that :)
>>>
>>> v1 -> v2:
>>> - rework the modes definition to process the full pixel array
>>> - rework get_selection to report the correct BOUND and DEFAULT targets
>>> - implement init_cfg
>>> - minor style changes as suggested by Laurent
>>> - test with 1 data lane
>>
>> Very nice! I tested this on TI's DRA76 EVM (CSI-2). UYVY and RGB565, with
>> the following resolutions: 160 120, 176 144, 320 240, 640 480, 720 480, 720
>> 576, 1024 768, 1280 720, 1920 1080.
> 
> Great! A 2 data lanes setup I assume ? Have you been able to test the
> framerate as well ?

Yes, 2 data lanes. I can see that with 640x480 and 1024x768 I get ~30fps.

Why does ov5640_enum_frame_interval() return an error if ov5640 is a csi 
sensor?

  Tomi

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-11  7:55     ` Tomi Valkeinen
@ 2022-02-11  8:01       ` Tomi Valkeinen
  0 siblings, 0 replies; 64+ messages in thread
From: Tomi Valkeinen @ 2022-02-11  8:01 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

On 11/02/2022 09:55, Tomi Valkeinen wrote:
> On 10/02/2022 19:11, Jacopo Mondi wrote:
>> Hi Tomi
>>
>> On Thu, Feb 10, 2022 at 03:00:21PM +0200, Tomi Valkeinen wrote:
>>> On 10/02/2022 13:04, Jacopo Mondi wrote:
>>>> v1:
>>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>>>
>>> You could rather point to lore.kernel.org, so that the intro letter 
>>> and the
>>> discussions are also visible.
>>
>> Sure, here you go!
>> https://lore.kernel.org/linux-media/20220131143245.128089-1-jacopo@jmondi.org/ 
>>
>>
>>>
>>>> A branch for testing based on the most recent media-master is 
>>>> available at
>>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
>>>>
>>>> If anyone with a DVP setup could verify I have not broken their use 
>>>> case
>>>> I would very much appreciate that :)
>>>>
>>>> v1 -> v2:
>>>> - rework the modes definition to process the full pixel array
>>>> - rework get_selection to report the correct BOUND and DEFAULT targets
>>>> - implement init_cfg
>>>> - minor style changes as suggested by Laurent
>>>> - test with 1 data lane
>>>
>>> Very nice! I tested this on TI's DRA76 EVM (CSI-2). UYVY and RGB565, 
>>> with
>>> the following resolutions: 160 120, 176 144, 320 240, 640 480, 720 
>>> 480, 720
>>> 576, 1024 768, 1280 720, 1920 1080.
>>
>> Great! A 2 data lanes setup I assume ? Have you been able to test the
>> framerate as well ?
> 
> Yes, 2 data lanes. I can see that with 640x480 and 1024x768 I get ~30fps.
> 
> Why does ov5640_enum_frame_interval() return an error if ov5640 is a csi 
> sensor?

Ah, never mind. I see the patch 18.

  Tomi

^ permalink raw reply	[flat|nested] 64+ messages in thread

* [v2.1] media: ov5640: Rework analog crop rectangles
  2022-02-10 11:04 ` [PATCH v2 10/23] media: ov5640: Rework analog crop rectangles Jacopo Mondi
@ 2022-02-11  9:34   ` Jacopo Mondi
  2022-02-20 12:56     ` Laurent Pinchart
  0 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-11  9:34 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Jacopo Mondi, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

The OV5640 pixel array is composed as:
- vertically: 16 dummy columns, 2592 valid ones and 16 dummy columns for
  a total of 2624 columns
- horizontally: 8 optical black lines, 6 dummy ones, 1944 valid and 6
  dummies for a total of 1964 lines

Adjust the analog crop rectangle in all modes to:
- Skip the first 16 dummy columns
- Skip the first 14 black/dummy lines
- Pass the whole valid pixel array size to the ISP for all modes except
  1024x768, 720p and 1080p which are obtained by cropping the valid pixel array.

Adjust how timings is programmed to comply with the new definitions.

Tested in RGB565, UYVY, RGB565 and RGB888 modes.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 drivers/media/i2c/ov5640.c | 120 +++++++++++++++++++++----------------
 1 file changed, 68 insertions(+), 52 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index f817f865ad16..232afd4d906a 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -626,14 +626,14 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_96M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			.left	= 2,
+			.top	= 4,
 			.width	= 640,
 			.height	= 480,
 		},
@@ -644,22 +644,23 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
 		.max_fps	= OV5640_30_FPS
 };

-static const struct ov5640_mode_info
-ov5640_mode_data[OV5640_NUM_MODES] = {
+static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
 	{
 		/* 160x120 */
 		.id		= OV5640_MODE_QQVGA_160_120,
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_48M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 160,
 			.height	= 120,
 		},
@@ -674,14 +675,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_48M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 176,
 			.height	= 144,
 		},
@@ -696,14 +699,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_48M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 320,
 			.height	= 240,
 		},
@@ -718,14 +723,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_48M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
-			.left	= 16,
-			.top	= 6,
+			/* Maintain a minimum digital crop processing margins. */
+			.left	= 2,
+			.top	= 4,
 			.width	= 640,
 			.height	= 480,
 		},
@@ -740,12 +747,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_96M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
+			/* Maintain a minimum digital crop processing margins. */
 			.left	= 56,
 			.top	= 60,
 			.width	= 720,
@@ -762,12 +771,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SUBSAMPLING,
 		.pixel_rate	= OV5640_PIXEL_RATE_96M,
 		.analog_crop = {
-			.left	= 0,
-			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			/* Feed the full valid pixel array to the ISP. */
+			.left	= OV5640_PIXEL_ARRAY_LEFT,
+			.top	= OV5640_PIXEL_ARRAY_TOP,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
+			/* Maintain a minimum digital crop processing margins. */
 			.left	= 56,
 			.top	= 6,
 			.width	= 720,
@@ -786,8 +797,8 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.analog_crop = {
 			.left	= 0,
 			.top	= 4,
-			.width	= 2623,
-			.height	= 1947,
+			.width	= OV5640_NATIVE_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.crop = {
 			.left	= 16,
@@ -808,8 +819,8 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.analog_crop = {
 			.left	= 0,
 			.top	= 250,
-			.width	= 2623,
-			.height	= 1705,
+			.width	= 2624,
+			.height	= 1456,
 		},
 		.crop = {
 			.left	= 16,
@@ -828,12 +839,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SCALING,
 		.pixel_rate	= OV5640_PIXEL_RATE_148M,
 		.analog_crop = {
+			/* Crop the full valid pixel array in the center. */
 			.left	= 336,
 			.top	= 434,
-			.width	= 2287,
-			.height	= 1521,
+			.width	= 1952,
+			.height	= 1088,
 		},
 		.crop = {
+			/* Maintain a larger digital crop processing margins. */
 			.left	= 16,
 			.top	= 4,
 			.width	= 1920,
@@ -850,16 +863,17 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
 		.dn_mode	= SCALING,
 		.pixel_rate	= OV5640_PIXEL_RATE_168M,
 		.analog_crop = {
+			/* Give more processing margin to full resolution. */
 			.left	= 0,
 			.top	= 0,
-			.width	= 2623,
-			.height	= 1951,
+			.width	= OV5640_NATIVE_WIDTH,
+			.height	= 1952,
 		},
 		.crop = {
 			.left	= 16,
 			.top	= 4,
-			.width	= 2592,
-			.height	= 1944,
+			.width	= OV5640_PIXEL_ARRAY_WIDTH,
+			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
 		},
 		.htot		= 2844,
 		.vblank_def	= 24,
@@ -1384,11 +1398,13 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
 	if (ret < 0)
 		return ret;

-	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW, analog_crop->width);
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW,
+				 analog_crop->width + analog_crop->left - 1);
 	if (ret < 0)
 		return ret;

-	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH, analog_crop->height);
+	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH,
+				 analog_crop->height + analog_crop->top - 1);
 	if (ret < 0)
 		return ret;

--
2.35.0


^ permalink raw reply related	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-10 13:00 ` Tomi Valkeinen
  2022-02-10 17:11   ` Jacopo Mondi
@ 2022-02-11  9:36   ` Jacopo Mondi
  1 sibling, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-11  9:36 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Steve Longerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Tomi,

On Thu, Feb 10, 2022 at 03:00:21PM +0200, Tomi Valkeinen wrote:
> On 10/02/2022 13:04, Jacopo Mondi wrote:
> > v1:
> > https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>
> You could rather point to lore.kernel.org, so that the intro letter and the
> discussions are also visible.
>
> > A branch for testing based on the most recent media-master is available at
> > https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> >
> > If anyone with a DVP setup could verify I have not broken their use case
> > I would very much appreciate that :)
> >
> > v1 -> v2:
> > - rework the modes definition to process the full pixel array
> > - rework get_selection to report the correct BOUND and DEFAULT targets
> > - implement init_cfg
> > - minor style changes as suggested by Laurent
> > - test with 1 data lane
>
> Very nice! I tested this on TI's DRA76 EVM (CSI-2). UYVY and RGB565, with
> the following resolutions: 160 120, 176 144, 320 240, 640 480, 720 480, 720
> 576, 1024 768, 1280 720, 1920 1080.
>
> All work. The only issue I saw was that with 1024x768 and 1280x720 there's a
> thin vertical purple column on the right edge.

Thanks for spotting.

I've sent a v2.1 version of "media: ov5640: Rework analog crop rectangles"
where I have re-introduced the crop rectangles as they were defined in
the register tables for 1024x768 and 1280x720, which are closer to
what the datasheet suggests. The vertical purple column seems to be
gone now.

Thanks
   j
>
>  Tomi

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
                   ` (24 preceding siblings ...)
  2022-02-10 13:00 ` Tomi Valkeinen
@ 2022-02-11 10:09 ` Eugen.Hristev
  2022-02-11 11:25   ` Jacopo Mondi
  25 siblings, 1 reply; 64+ messages in thread
From: Eugen.Hristev @ 2022-02-11 10:09 UTC (permalink / raw)
  To: jacopo
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

On 2/10/22 1:04 PM, Jacopo Mondi wrote:

Hello Jacopo,

> v1:
> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
> 
> A branch for testing based on the most recent media-master is available at
> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> 
> If anyone with a DVP setup could verify I have not broken their use case
> I would very much appreciate that :)

I started testing this on my bench.
So far things look good.

To be able to test this, I have to revert this patch :
"media: i2c: ov5640: Remain in power down for DVP mode unless streaming"

Otherwise the sensor will not power up when starting streaming.


I have tested several formats, as you worked more on this sensor, could 
you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or 
1024x768 ?
I managed to get it working fine at 640x480 .

The sensor looks to report valid framesizes for this mbus code :

# v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
\ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
         0x4001: MEDIA_BUS_FMT_JPEG_1X8
         0x2006: MEDIA_BUS_FMT_UYVY8_2X8
         0x200f: MEDIA_BUS_FMT_UYVY8_1X16
         0x2008: MEDIA_BUS_FMT_YUYV8_2X8
         0x2011: MEDIA_BUS_FMT_YUYV8_1X16
         0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
         0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
         0x1017: MEDIA_BUS_FMT_RGB565_1X16
         0x100a: MEDIA_BUS_FMT_RGB888_1X24
         0x1013: MEDIA_BUS_FMT_BGR888_1X24
         0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
         0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
         0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
         0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
# v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
         Size Range: 160x120 - 160x120
         Size Range: 176x144 - 176x144
         Size Range: 320x240 - 320x240
         Size Range: 640x480 - 640x480
         Size Range: 720x480 - 720x480
         Size Range: 720x576 - 720x576
         Size Range: 1024x768 - 1024x768
         Size Range: 1280x720 - 1280x720
         Size Range: 1920x1080 - 1920x1080
         Size Range: 2592x1944 - 2592x1944
#

but the ISC does not receive any frames at 1024x768 and 1920x1080.


What I can say is that the raw bayer format works at 1920x1080 , frames 
are received correctly.

Thanks,
Eugen

> 
> v1 -> v2:
> - rework the modes definition to process the full pixel array
> - rework get_selection to report the correct BOUND and DEFAULT targets
> - implement init_cfg
> - minor style changes as suggested by Laurent
> - test with 1 data lane
> 
> Thanks
>     j
> 
> Jacopo Mondi (23):
>    media: ov5640: Add pixel rate to modes
>    media: ov5604: Re-arrange modes definition
>    media: ov5640: Add ov5640_is_csi2() function
>    media: ov5640: Associate bpp with formats
>    media: ov5640: Add LINK_FREQ control
>    media: ov5640: Update pixel_rate and link_freq
>    media: ov5640: Rework CSI-2 clock tree
>    media: ov5640: Rework timings programming
>    media: ov5640: Fix 720x480 in RGB888 mode
>    media: ov5640: Rework analog crop rectangles
>    media: ov5640: Re-sort per-mode register tables
>    media: ov5640: Remove ov5640_mode_init_data
>    media: ov5640: Add HBLANK control
>    media: ov5640: Add VBLANK control
>    media: ov5640: Fix durations to comply with FPS
>    media: ov5640: Implement init_cfg
>    media: ov5640: Implement get_selection
>    media: ov5640: Limit frame_interval to DVP mode only
>    media: ov5640: Register device properties
>    media: ov5640: Add RGB565_1X16 format
>    media: ov5640: Add RGB888/BGR888 formats
>    media: ov5640: Restrict sizes to mbus code
>    media: ov5640: Adjust format to bpp in s_fmt
> 
>   drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
>   1 file changed, 830 insertions(+), 313 deletions(-)
> 
> --
> 2.35.0
> 


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-11 10:09 ` Eugen.Hristev
@ 2022-02-11 11:25   ` Jacopo Mondi
  2022-02-14 14:06     ` Eugen.Hristev
  0 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-11 11:25 UTC (permalink / raw)
  To: Eugen.Hristev
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

Hi Eugen

        thanks very much for testing

On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
>
> Hello Jacopo,
>
> > v1:
> > https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
> >
> > A branch for testing based on the most recent media-master is available at
> > https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> >
> > If anyone with a DVP setup could verify I have not broken their use case
> > I would very much appreciate that :)
>
> I started testing this on my bench.
> So far things look good.
>

\o/

> To be able to test this, I have to revert this patch :
> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
>
> Otherwise the sensor will not power up when starting streaming.
>
>
> I have tested several formats, as you worked more on this sensor, could
> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
> 1024x768 ?

I never tested the sensor driver with a parallel setup I'm afraid.
The idea behind this series is that DVP shouldn't be affected and
continue working like it did.

> I managed to get it working fine at 640x480 .
>
> The sensor looks to report valid framesizes for this mbus code :
>
> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
>          0x4001: MEDIA_BUS_FMT_JPEG_1X8
>          0x2006: MEDIA_BUS_FMT_UYVY8_2X8
>          0x200f: MEDIA_BUS_FMT_UYVY8_1X16
>          0x2008: MEDIA_BUS_FMT_YUYV8_2X8
>          0x2011: MEDIA_BUS_FMT_YUYV8_1X16
>          0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
>          0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
>          0x1017: MEDIA_BUS_FMT_RGB565_1X16
>          0x100a: MEDIA_BUS_FMT_RGB888_1X24
>          0x1013: MEDIA_BUS_FMT_BGR888_1X24
>          0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
>          0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
>          0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
>          0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>          Size Range: 160x120 - 160x120
>          Size Range: 176x144 - 176x144
>          Size Range: 320x240 - 320x240
>          Size Range: 640x480 - 640x480
>          Size Range: 720x480 - 720x480
>          Size Range: 720x576 - 720x576
>          Size Range: 1024x768 - 1024x768
>          Size Range: 1280x720 - 1280x720
>          Size Range: 1920x1080 - 1920x1080
>          Size Range: 2592x1944 - 2592x1944
> #
>
> but the ISC does not receive any frames at 1024x768 and 1920x1080.

Are 1080p and 1024x768 working without this series applied on your
setup ?

Thanks again for testin!

>
>
> What I can say is that the raw bayer format works at 1920x1080 , frames
> are received correctly.
>
> Thanks,
> Eugen
>
> >
> > v1 -> v2:
> > - rework the modes definition to process the full pixel array
> > - rework get_selection to report the correct BOUND and DEFAULT targets
> > - implement init_cfg
> > - minor style changes as suggested by Laurent
> > - test with 1 data lane
> >
> > Thanks
> >     j
> >
> > Jacopo Mondi (23):
> >    media: ov5640: Add pixel rate to modes
> >    media: ov5604: Re-arrange modes definition
> >    media: ov5640: Add ov5640_is_csi2() function
> >    media: ov5640: Associate bpp with formats
> >    media: ov5640: Add LINK_FREQ control
> >    media: ov5640: Update pixel_rate and link_freq
> >    media: ov5640: Rework CSI-2 clock tree
> >    media: ov5640: Rework timings programming
> >    media: ov5640: Fix 720x480 in RGB888 mode
> >    media: ov5640: Rework analog crop rectangles
> >    media: ov5640: Re-sort per-mode register tables
> >    media: ov5640: Remove ov5640_mode_init_data
> >    media: ov5640: Add HBLANK control
> >    media: ov5640: Add VBLANK control
> >    media: ov5640: Fix durations to comply with FPS
> >    media: ov5640: Implement init_cfg
> >    media: ov5640: Implement get_selection
> >    media: ov5640: Limit frame_interval to DVP mode only
> >    media: ov5640: Register device properties
> >    media: ov5640: Add RGB565_1X16 format
> >    media: ov5640: Add RGB888/BGR888 formats
> >    media: ov5640: Restrict sizes to mbus code
> >    media: ov5640: Adjust format to bpp in s_fmt
> >
> >   drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
> >   1 file changed, 830 insertions(+), 313 deletions(-)
> >
> > --
> > 2.35.0
> >
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-11 11:25   ` Jacopo Mondi
@ 2022-02-14 14:06     ` Eugen.Hristev
  2022-02-14 14:38       ` Jacopo Mondi
  0 siblings, 1 reply; 64+ messages in thread
From: Eugen.Hristev @ 2022-02-14 14:06 UTC (permalink / raw)
  To: jacopo
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

On 2/11/22 1:25 PM, Jacopo Mondi wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Hi Eugen
> 
>          thanks very much for testing
> 
> On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
>> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
>>
>> Hello Jacopo,
>>
>>> v1:
>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>>>
>>> A branch for testing based on the most recent media-master is available at
>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
>>>
>>> If anyone with a DVP setup could verify I have not broken their use case
>>> I would very much appreciate that :)
>>
>> I started testing this on my bench.
>> So far things look good.
>>
> 
> \o/
> 
>> To be able to test this, I have to revert this patch :
>> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
>>
>> Otherwise the sensor will not power up when starting streaming.
>>
>>
>> I have tested several formats, as you worked more on this sensor, could
>> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
>> 1024x768 ?
> 
> I never tested the sensor driver with a parallel setup I'm afraid.
> The idea behind this series is that DVP shouldn't be affected and
> continue working like it did.

Hi Jacopo,

I was hoping that you had more information about the driver than myself.
I can tell that the parallel mode is not affected by your series from 
what I've seen so far.

> 
>> I managed to get it working fine at 640x480 .
>>
>> The sensor looks to report valid framesizes for this mbus code :
>>
>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
>> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
>>           0x4001: MEDIA_BUS_FMT_JPEG_1X8
>>           0x2006: MEDIA_BUS_FMT_UYVY8_2X8
>>           0x200f: MEDIA_BUS_FMT_UYVY8_1X16
>>           0x2008: MEDIA_BUS_FMT_YUYV8_2X8
>>           0x2011: MEDIA_BUS_FMT_YUYV8_1X16
>>           0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
>>           0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
>>           0x1017: MEDIA_BUS_FMT_RGB565_1X16
>>           0x100a: MEDIA_BUS_FMT_RGB888_1X24
>>           0x1013: MEDIA_BUS_FMT_BGR888_1X24
>>           0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
>>           0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
>>           0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
>>           0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>>           Size Range: 160x120 - 160x120
>>           Size Range: 176x144 - 176x144
>>           Size Range: 320x240 - 320x240
>>           Size Range: 640x480 - 640x480
>>           Size Range: 720x480 - 720x480
>>           Size Range: 720x576 - 720x576
>>           Size Range: 1024x768 - 1024x768
>>           Size Range: 1280x720 - 1280x720
>>           Size Range: 1920x1080 - 1920x1080
>>           Size Range: 2592x1944 - 2592x1944
>> #
>>
>> but the ISC does not receive any frames at 1024x768 and 1920x1080.
> 
> Are 1080p and 1024x768 working without this series applied on your
> setup ?

I remember they weren't working before either.

I don't know exactly to which patches to add my Tested-by , as I have 
not tested the explicit patch behavior for each patch (e.g. where you 
add HBLANK control, I have not tested that ).

Is there something particular you would like me to try , except my usual 
image captures ?


Eugen

> 
> Thanks again for testin!
> 
>>
>>
>> What I can say is that the raw bayer format works at 1920x1080 , frames
>> are received correctly.
>>
>> Thanks,
>> Eugen
>>
>>>
>>> v1 -> v2:
>>> - rework the modes definition to process the full pixel array
>>> - rework get_selection to report the correct BOUND and DEFAULT targets
>>> - implement init_cfg
>>> - minor style changes as suggested by Laurent
>>> - test with 1 data lane
>>>
>>> Thanks
>>>      j
>>>
>>> Jacopo Mondi (23):
>>>     media: ov5640: Add pixel rate to modes
>>>     media: ov5604: Re-arrange modes definition
>>>     media: ov5640: Add ov5640_is_csi2() function
>>>     media: ov5640: Associate bpp with formats
>>>     media: ov5640: Add LINK_FREQ control
>>>     media: ov5640: Update pixel_rate and link_freq
>>>     media: ov5640: Rework CSI-2 clock tree
>>>     media: ov5640: Rework timings programming
>>>     media: ov5640: Fix 720x480 in RGB888 mode
>>>     media: ov5640: Rework analog crop rectangles
>>>     media: ov5640: Re-sort per-mode register tables
>>>     media: ov5640: Remove ov5640_mode_init_data
>>>     media: ov5640: Add HBLANK control
>>>     media: ov5640: Add VBLANK control
>>>     media: ov5640: Fix durations to comply with FPS
>>>     media: ov5640: Implement init_cfg
>>>     media: ov5640: Implement get_selection
>>>     media: ov5640: Limit frame_interval to DVP mode only
>>>     media: ov5640: Register device properties
>>>     media: ov5640: Add RGB565_1X16 format
>>>     media: ov5640: Add RGB888/BGR888 formats
>>>     media: ov5640: Restrict sizes to mbus code
>>>     media: ov5640: Adjust format to bpp in s_fmt
>>>
>>>    drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
>>>    1 file changed, 830 insertions(+), 313 deletions(-)
>>>
>>> --
>>> 2.35.0
>>>
>>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-14 14:06     ` Eugen.Hristev
@ 2022-02-14 14:38       ` Jacopo Mondi
  2022-02-14 15:08         ` Eugen.Hristev
  0 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-14 14:38 UTC (permalink / raw)
  To: Eugen.Hristev
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

Hi Eugen,

On Mon, Feb 14, 2022 at 02:06:02PM +0000, Eugen.Hristev@microchip.com wrote:
> On 2/11/22 1:25 PM, Jacopo Mondi wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >
> > Hi Eugen
> >
> >          thanks very much for testing
> >
> > On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
> >> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
> >>
> >> Hello Jacopo,
> >>
> >>> v1:
> >>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
> >>>
> >>> A branch for testing based on the most recent media-master is available at
> >>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> >>>
> >>> If anyone with a DVP setup could verify I have not broken their use case
> >>> I would very much appreciate that :)
> >>
> >> I started testing this on my bench.
> >> So far things look good.
> >>
> >
> > \o/
> >
> >> To be able to test this, I have to revert this patch :
> >> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
> >>
> >> Otherwise the sensor will not power up when starting streaming.
> >>
> >>
> >> I have tested several formats, as you worked more on this sensor, could
> >> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
> >> 1024x768 ?
> >
> > I never tested the sensor driver with a parallel setup I'm afraid.
> > The idea behind this series is that DVP shouldn't be affected and
> > continue working like it did.
>
> Hi Jacopo,
>
> I was hoping that you had more information about the driver than myself.

Not on DVP mode I'm sorry :(

> I can tell that the parallel mode is not affected by your series from
> what I've seen so far.

That's great, thanks for testing.

>
> >
> >> I managed to get it working fine at 640x480 .
> >>
> >> The sensor looks to report valid framesizes for this mbus code :
> >>
> >> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
> >> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
> >>           0x4001: MEDIA_BUS_FMT_JPEG_1X8
> >>           0x2006: MEDIA_BUS_FMT_UYVY8_2X8
> >>           0x200f: MEDIA_BUS_FMT_UYVY8_1X16
> >>           0x2008: MEDIA_BUS_FMT_YUYV8_2X8
> >>           0x2011: MEDIA_BUS_FMT_YUYV8_1X16
> >>           0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
> >>           0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
> >>           0x1017: MEDIA_BUS_FMT_RGB565_1X16
> >>           0x100a: MEDIA_BUS_FMT_RGB888_1X24
> >>           0x1013: MEDIA_BUS_FMT_BGR888_1X24
> >>           0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
> >>           0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
> >>           0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
> >>           0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
> >> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
> >> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>           Size Range: 160x120 - 160x120
> >>           Size Range: 176x144 - 176x144
> >>           Size Range: 320x240 - 320x240
> >>           Size Range: 640x480 - 640x480
> >>           Size Range: 720x480 - 720x480
> >>           Size Range: 720x576 - 720x576
> >>           Size Range: 1024x768 - 1024x768
> >>           Size Range: 1280x720 - 1280x720
> >>           Size Range: 1920x1080 - 1920x1080
> >>           Size Range: 2592x1944 - 2592x1944
> >> #
> >>
> >> but the ISC does not receive any frames at 1024x768 and 1920x1080.
> >
> > Are 1080p and 1024x768 working without this series applied on your
> > setup ?
>
> I remember they weren't working before either.
>
> I don't know exactly to which patches to add my Tested-by , as I have
> not tested the explicit patch behavior for each patch (e.g. where you
> add HBLANK control, I have not tested that ).
>

I think it's good enough making sure I have not broke DVP.

As you can see the driver now behaves in two different ways in DVP and
MIPI mode. The DVP works as it used to, and the framerate is
controlled by s_frame_interval, the frame size is fixed and the PCLK
is computed dyanically to accomodate the required FPS. In MIPI mode the
framerate is controlled by changing the vertical blankings. To each
mode a pixel rate is assigned and userspace changes the frame duration
by changing blankings. The most obvious gain is that the frame rate is
controllable in a continuous interval instead of being limited to a
few fixed values. It is my understanding that all drivers should be
moved to this model and s_frame_intervall should be dropped, but
unfortunately some bridge drivers in mainline still deman that.

If you are interested, I think the DVP mode should be moved to use the
same mecahnism as MIPI mode. I can't test so I haven't done so in this
series.

For now I think it's enough to make sure there are no regressions in
DVP mode.

For the tag, I think it would be appropriate to add it to the
following one:

91ae667b0d47 media: ov5640: Limit frame_interval to DVP mode only

> Is there something particular you would like me to try , except my usual
> image captures ?

RGB888 is weird on both the platforms I've tested on and I cannot get
colors right. Does your platform support RGB888 ?

Thanks
  j


>
>
> Eugen
>
> >
> > Thanks again for testin!
> >
> >>
> >>
> >> What I can say is that the raw bayer format works at 1920x1080 , frames
> >> are received correctly.
> >>
> >> Thanks,
> >> Eugen
> >>
> >>>
> >>> v1 -> v2:
> >>> - rework the modes definition to process the full pixel array
> >>> - rework get_selection to report the correct BOUND and DEFAULT targets
> >>> - implement init_cfg
> >>> - minor style changes as suggested by Laurent
> >>> - test with 1 data lane
> >>>
> >>> Thanks
> >>>      j
> >>>
> >>> Jacopo Mondi (23):
> >>>     media: ov5640: Add pixel rate to modes
> >>>     media: ov5604: Re-arrange modes definition
> >>>     media: ov5640: Add ov5640_is_csi2() function
> >>>     media: ov5640: Associate bpp with formats
> >>>     media: ov5640: Add LINK_FREQ control
> >>>     media: ov5640: Update pixel_rate and link_freq
> >>>     media: ov5640: Rework CSI-2 clock tree
> >>>     media: ov5640: Rework timings programming
> >>>     media: ov5640: Fix 720x480 in RGB888 mode
> >>>     media: ov5640: Rework analog crop rectangles
> >>>     media: ov5640: Re-sort per-mode register tables
> >>>     media: ov5640: Remove ov5640_mode_init_data
> >>>     media: ov5640: Add HBLANK control
> >>>     media: ov5640: Add VBLANK control
> >>>     media: ov5640: Fix durations to comply with FPS
> >>>     media: ov5640: Implement init_cfg
> >>>     media: ov5640: Implement get_selection
> >>>     media: ov5640: Limit frame_interval to DVP mode only
> >>>     media: ov5640: Register device properties
> >>>     media: ov5640: Add RGB565_1X16 format
> >>>     media: ov5640: Add RGB888/BGR888 formats
> >>>     media: ov5640: Restrict sizes to mbus code
> >>>     media: ov5640: Adjust format to bpp in s_fmt
> >>>
> >>>    drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
> >>>    1 file changed, 830 insertions(+), 313 deletions(-)
> >>>
> >>> --
> >>> 2.35.0
> >>>
> >>
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-14 14:38       ` Jacopo Mondi
@ 2022-02-14 15:08         ` Eugen.Hristev
  2022-02-14 18:56           ` Jacopo Mondi
  0 siblings, 1 reply; 64+ messages in thread
From: Eugen.Hristev @ 2022-02-14 15:08 UTC (permalink / raw)
  To: jacopo
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

On 2/14/22 4:38 PM, Jacopo Mondi wrote:
> Hi Eugen,
> 
> On Mon, Feb 14, 2022 at 02:06:02PM +0000, Eugen.Hristev@microchip.com wrote:
>> On 2/11/22 1:25 PM, Jacopo Mondi wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Hi Eugen
>>>
>>>           thanks very much for testing
>>>
>>> On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
>>>> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
>>>>
>>>> Hello Jacopo,
>>>>
>>>>> v1:
>>>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>>>>>
>>>>> A branch for testing based on the most recent media-master is available at
>>>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
>>>>>
>>>>> If anyone with a DVP setup could verify I have not broken their use case
>>>>> I would very much appreciate that :)
>>>>
>>>> I started testing this on my bench.
>>>> So far things look good.
>>>>
>>>
>>> \o/
>>>
>>>> To be able to test this, I have to revert this patch :
>>>> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
>>>>
>>>> Otherwise the sensor will not power up when starting streaming.
>>>>
>>>>
>>>> I have tested several formats, as you worked more on this sensor, could
>>>> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
>>>> 1024x768 ?
>>>
>>> I never tested the sensor driver with a parallel setup I'm afraid.
>>> The idea behind this series is that DVP shouldn't be affected and
>>> continue working like it did.
>>
>> Hi Jacopo,
>>
>> I was hoping that you had more information about the driver than myself.
> 
> Not on DVP mode I'm sorry :(
> 
>> I can tell that the parallel mode is not affected by your series from
>> what I've seen so far.
> 
> That's great, thanks for testing.


I found one change, before your series, I could attempt to capture BGGR 
@ 640x480, now it looks to be gone :

Before:

# v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
         Size Range: 160x120 - 160x120
         Size Range: 176x144 - 176x144
         Size Range: 320x240 - 320x240
         Size Range: 640x480 - 640x480
         Size Range: 720x480 - 720x480
         Size Range: 720x576 - 720x576
         Size Range: 1024x768 - 1024x768
         Size Range: 1280x720 - 1280x720
         Size Range: 1920x1080 - 1920x1080
         Size Range: 2592x1944 - 2592x1944


After:

# v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
         Size Range: 1280x720 - 1280x720
         Size Range: 1920x1080 - 1920x1080
         Size Range: 2592x1944 - 2592x1944


However trying it without your patches, it doesn't work , I don't 
receive frames, and I can't even set 1280x720 at all, I get -EINVAL

So I assume you have been reworking the frame sizes.

With your series, I have tested RGGB at 1280x720 , 1920x1080 .
I also tested YUYV at 640x480 and RGB565_LE at 640x480.

I can't go higher with the YUYV/RGB565, I don't receive frames anymore.
I can't go higher with the bayer to 2592x1944 . But this did not work 
before your patches either.
> 
>>
>>>
>>>> I managed to get it working fine at 640x480 .
>>>>
>>>> The sensor looks to report valid framesizes for this mbus code :
>>>>
>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
>>>> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
>>>>            0x4001: MEDIA_BUS_FMT_JPEG_1X8
>>>>            0x2006: MEDIA_BUS_FMT_UYVY8_2X8
>>>>            0x200f: MEDIA_BUS_FMT_UYVY8_1X16
>>>>            0x2008: MEDIA_BUS_FMT_YUYV8_2X8
>>>>            0x2011: MEDIA_BUS_FMT_YUYV8_1X16
>>>>            0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
>>>>            0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
>>>>            0x1017: MEDIA_BUS_FMT_RGB565_1X16
>>>>            0x100a: MEDIA_BUS_FMT_RGB888_1X24
>>>>            0x1013: MEDIA_BUS_FMT_BGR888_1X24
>>>>            0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
>>>>            0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
>>>>            0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
>>>>            0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
>>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>>>>            Size Range: 160x120 - 160x120
>>>>            Size Range: 176x144 - 176x144
>>>>            Size Range: 320x240 - 320x240
>>>>            Size Range: 640x480 - 640x480
>>>>            Size Range: 720x480 - 720x480
>>>>            Size Range: 720x576 - 720x576
>>>>            Size Range: 1024x768 - 1024x768
>>>>            Size Range: 1280x720 - 1280x720
>>>>            Size Range: 1920x1080 - 1920x1080
>>>>            Size Range: 2592x1944 - 2592x1944
>>>> #
>>>>
>>>> but the ISC does not receive any frames at 1024x768 and 1920x1080.
>>>
>>> Are 1080p and 1024x768 working without this series applied on your
>>> setup ?
>>
>> I remember they weren't working before either.
>>
>> I don't know exactly to which patches to add my Tested-by , as I have
>> not tested the explicit patch behavior for each patch (e.g. where you
>> add HBLANK control, I have not tested that ).
>>
> 
> I think it's good enough making sure I have not broke DVP.
> 
> As you can see the driver now behaves in two different ways in DVP and
> MIPI mode. The DVP works as it used to, and the framerate is
> controlled by s_frame_interval, the frame size is fixed and the PCLK
> is computed dyanically to accomodate the required FPS. In MIPI mode the
> framerate is controlled by changing the vertical blankings. To each
> mode a pixel rate is assigned and userspace changes the frame duration
> by changing blankings. The most obvious gain is that the frame rate is
> controllable in a continuous interval instead of being limited to a
> few fixed values. It is my understanding that all drivers should be
> moved to this model and s_frame_intervall should be dropped, but
> unfortunately some bridge drivers in mainline still deman that.
> 
> If you are interested, I think the DVP mode should be moved to use the
> same mecahnism as MIPI mode. I can't test so I haven't done so in this
> series.
> 
> For now I think it's enough to make sure there are no regressions in
> DVP mode.
> 
> For the tag, I think it would be appropriate to add it to the
> following one:
> 
> 91ae667b0d47 media: ov5640: Limit frame_interval to DVP mode only
> 
>> Is there something particular you would like me to try , except my usual
>> image captures ?
> 
> RGB888 is weird on both the platforms I've tested on and I cannot get
> colors right. Does your platform support RGB888 ?

I can't test this one unfortunately. It's a 1X24 . I have only 8 bits 
connected, so unless you can make this a 3x8 , there isn't anything I 
can do.

> 
> Thanks
>    j
> 
> 
>>
>>
>> Eugen
>>
>>>
>>> Thanks again for testin!
>>>
>>>>
>>>>
>>>> What I can say is that the raw bayer format works at 1920x1080 , frames
>>>> are received correctly.
>>>>
>>>> Thanks,
>>>> Eugen
>>>>
>>>>>
>>>>> v1 -> v2:
>>>>> - rework the modes definition to process the full pixel array
>>>>> - rework get_selection to report the correct BOUND and DEFAULT targets
>>>>> - implement init_cfg
>>>>> - minor style changes as suggested by Laurent
>>>>> - test with 1 data lane
>>>>>
>>>>> Thanks
>>>>>       j
>>>>>
>>>>> Jacopo Mondi (23):
>>>>>      media: ov5640: Add pixel rate to modes
>>>>>      media: ov5604: Re-arrange modes definition
>>>>>      media: ov5640: Add ov5640_is_csi2() function
>>>>>      media: ov5640: Associate bpp with formats
>>>>>      media: ov5640: Add LINK_FREQ control
>>>>>      media: ov5640: Update pixel_rate and link_freq
>>>>>      media: ov5640: Rework CSI-2 clock tree
>>>>>      media: ov5640: Rework timings programming
>>>>>      media: ov5640: Fix 720x480 in RGB888 mode
>>>>>      media: ov5640: Rework analog crop rectangles
>>>>>      media: ov5640: Re-sort per-mode register tables
>>>>>      media: ov5640: Remove ov5640_mode_init_data
>>>>>      media: ov5640: Add HBLANK control
>>>>>      media: ov5640: Add VBLANK control
>>>>>      media: ov5640: Fix durations to comply with FPS
>>>>>      media: ov5640: Implement init_cfg
>>>>>      media: ov5640: Implement get_selection
>>>>>      media: ov5640: Limit frame_interval to DVP mode only
>>>>>      media: ov5640: Register device properties
>>>>>      media: ov5640: Add RGB565_1X16 format
>>>>>      media: ov5640: Add RGB888/BGR888 formats
>>>>>      media: ov5640: Restrict sizes to mbus code
>>>>>      media: ov5640: Adjust format to bpp in s_fmt
>>>>>
>>>>>     drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
>>>>>     1 file changed, 830 insertions(+), 313 deletions(-)
>>>>>
>>>>> --
>>>>> 2.35.0
>>>>>
>>>>
>>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-14 15:08         ` Eugen.Hristev
@ 2022-02-14 18:56           ` Jacopo Mondi
  2022-02-17 14:25             ` Eugen.Hristev
  0 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-14 18:56 UTC (permalink / raw)
  To: Eugen.Hristev
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

Hi Eugen

On Mon, Feb 14, 2022 at 03:08:56PM +0000, Eugen.Hristev@microchip.com wrote:
> On 2/14/22 4:38 PM, Jacopo Mondi wrote:
> > Hi Eugen,
> >
> > On Mon, Feb 14, 2022 at 02:06:02PM +0000, Eugen.Hristev@microchip.com wrote:
> >> On 2/11/22 1:25 PM, Jacopo Mondi wrote:
> >>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >>>
> >>> Hi Eugen
> >>>
> >>>           thanks very much for testing
> >>>
> >>> On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
> >>>> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
> >>>>
> >>>> Hello Jacopo,
> >>>>
> >>>>> v1:
> >>>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
> >>>>>
> >>>>> A branch for testing based on the most recent media-master is available at
> >>>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> >>>>>
> >>>>> If anyone with a DVP setup could verify I have not broken their use case
> >>>>> I would very much appreciate that :)
> >>>>
> >>>> I started testing this on my bench.
> >>>> So far things look good.
> >>>>
> >>>
> >>> \o/
> >>>
> >>>> To be able to test this, I have to revert this patch :
> >>>> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
> >>>>
> >>>> Otherwise the sensor will not power up when starting streaming.
> >>>>
> >>>>
> >>>> I have tested several formats, as you worked more on this sensor, could
> >>>> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
> >>>> 1024x768 ?
> >>>
> >>> I never tested the sensor driver with a parallel setup I'm afraid.
> >>> The idea behind this series is that DVP shouldn't be affected and
> >>> continue working like it did.
> >>
> >> Hi Jacopo,
> >>
> >> I was hoping that you had more information about the driver than myself.
> >
> > Not on DVP mode I'm sorry :(
> >
> >> I can tell that the parallel mode is not affected by your series from
> >> what I've seen so far.
> >
> > That's great, thanks for testing.
>
>
> I found one change, before your series, I could attempt to capture BGGR
> @ 640x480, now it looks to be gone :
>
> Before:
>
> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>          Size Range: 160x120 - 160x120
>          Size Range: 176x144 - 176x144
>          Size Range: 320x240 - 320x240
>          Size Range: 640x480 - 640x480
>          Size Range: 720x480 - 720x480
>          Size Range: 720x576 - 720x576
>          Size Range: 1024x768 - 1024x768
>          Size Range: 1280x720 - 1280x720
>          Size Range: 1920x1080 - 1920x1080
>          Size Range: 2592x1944 - 2592x1944
>
>
> After:
>
> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>          Size Range: 1280x720 - 1280x720
>          Size Range: 1920x1080 - 1920x1080
>          Size Range: 2592x1944 - 2592x1944
>

Right... I'm limiting SRGGB formats to only resolutions > 1280x720
as..

>
> However trying it without your patches, it doesn't work , I don't

... they do not work for me either.

So if they were not working before, maybe it's right not to enumerate
them ?

> receive frames, and I can't even set 1280x720 at all, I get -EINVAL

Be aware that DVP mode prevents you from setting a format if the
currently selected framerate is said to be "not supported" for that
format

>
> So I assume you have been reworking the frame sizes.
>
> With your series, I have tested RGGB at 1280x720 , 1920x1080 .
> I also tested YUYV at 640x480 and RGB565_LE at 640x480.
>
> I can't go higher with the YUYV/RGB565, I don't receive frames anymore.

Ah, I wonder if
07b49ac59fd9 media: ov5640: Fix durations to comply with FPS
82aebf4b7314 media: ov5640: Rework analog crop rectangles

Might have impacted DVP...

Should I keep separate fields for MIPI mode and leave the totals for
DVP untouched ?

Thanks again for your very useful testing


> I can't go higher with the bayer to 2592x1944 . But this did not work
> before your patches either.
> >
> >>
> >>>
> >>>> I managed to get it working fine at 640x480 .
> >>>>
> >>>> The sensor looks to report valid framesizes for this mbus code :
> >>>>
> >>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
> >>>> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
> >>>>            0x4001: MEDIA_BUS_FMT_JPEG_1X8
> >>>>            0x2006: MEDIA_BUS_FMT_UYVY8_2X8
> >>>>            0x200f: MEDIA_BUS_FMT_UYVY8_1X16
> >>>>            0x2008: MEDIA_BUS_FMT_YUYV8_2X8
> >>>>            0x2011: MEDIA_BUS_FMT_YUYV8_1X16
> >>>>            0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
> >>>>            0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
> >>>>            0x1017: MEDIA_BUS_FMT_RGB565_1X16
> >>>>            0x100a: MEDIA_BUS_FMT_RGB888_1X24
> >>>>            0x1013: MEDIA_BUS_FMT_BGR888_1X24
> >>>>            0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
> >>>>            0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
> >>>>            0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
> >>>>            0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
> >>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
> >>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>>>            Size Range: 160x120 - 160x120
> >>>>            Size Range: 176x144 - 176x144
> >>>>            Size Range: 320x240 - 320x240
> >>>>            Size Range: 640x480 - 640x480
> >>>>            Size Range: 720x480 - 720x480
> >>>>            Size Range: 720x576 - 720x576
> >>>>            Size Range: 1024x768 - 1024x768
> >>>>            Size Range: 1280x720 - 1280x720
> >>>>            Size Range: 1920x1080 - 1920x1080
> >>>>            Size Range: 2592x1944 - 2592x1944
> >>>> #
> >>>>
> >>>> but the ISC does not receive any frames at 1024x768 and 1920x1080.
> >>>
> >>> Are 1080p and 1024x768 working without this series applied on your
> >>> setup ?
> >>
> >> I remember they weren't working before either.
> >>
> >> I don't know exactly to which patches to add my Tested-by , as I have
> >> not tested the explicit patch behavior for each patch (e.g. where you
> >> add HBLANK control, I have not tested that ).
> >>
> >
> > I think it's good enough making sure I have not broke DVP.
> >
> > As you can see the driver now behaves in two different ways in DVP and
> > MIPI mode. The DVP works as it used to, and the framerate is
> > controlled by s_frame_interval, the frame size is fixed and the PCLK
> > is computed dyanically to accomodate the required FPS. In MIPI mode the
> > framerate is controlled by changing the vertical blankings. To each
> > mode a pixel rate is assigned and userspace changes the frame duration
> > by changing blankings. The most obvious gain is that the frame rate is
> > controllable in a continuous interval instead of being limited to a
> > few fixed values. It is my understanding that all drivers should be
> > moved to this model and s_frame_intervall should be dropped, but
> > unfortunately some bridge drivers in mainline still deman that.
> >
> > If you are interested, I think the DVP mode should be moved to use the
> > same mecahnism as MIPI mode. I can't test so I haven't done so in this
> > series.
> >
> > For now I think it's enough to make sure there are no regressions in
> > DVP mode.
> >
> > For the tag, I think it would be appropriate to add it to the
> > following one:
> >
> > 91ae667b0d47 media: ov5640: Limit frame_interval to DVP mode only
> >
> >> Is there something particular you would like me to try , except my usual
> >> image captures ?
> >
> > RGB888 is weird on both the platforms I've tested on and I cannot get
> > colors right. Does your platform support RGB888 ?
>
> I can't test this one unfortunately. It's a 1X24 . I have only 8 bits
> connected, so unless you can make this a 3x8 , there isn't anything I
> can do.
>
> >
> > Thanks
> >    j
> >
> >
> >>
> >>
> >> Eugen
> >>
> >>>
> >>> Thanks again for testin!
> >>>
> >>>>
> >>>>
> >>>> What I can say is that the raw bayer format works at 1920x1080 , frames
> >>>> are received correctly.
> >>>>
> >>>> Thanks,
> >>>> Eugen
> >>>>
> >>>>>
> >>>>> v1 -> v2:
> >>>>> - rework the modes definition to process the full pixel array
> >>>>> - rework get_selection to report the correct BOUND and DEFAULT targets
> >>>>> - implement init_cfg
> >>>>> - minor style changes as suggested by Laurent
> >>>>> - test with 1 data lane
> >>>>>
> >>>>> Thanks
> >>>>>       j
> >>>>>
> >>>>> Jacopo Mondi (23):
> >>>>>      media: ov5640: Add pixel rate to modes
> >>>>>      media: ov5604: Re-arrange modes definition
> >>>>>      media: ov5640: Add ov5640_is_csi2() function
> >>>>>      media: ov5640: Associate bpp with formats
> >>>>>      media: ov5640: Add LINK_FREQ control
> >>>>>      media: ov5640: Update pixel_rate and link_freq
> >>>>>      media: ov5640: Rework CSI-2 clock tree
> >>>>>      media: ov5640: Rework timings programming
> >>>>>      media: ov5640: Fix 720x480 in RGB888 mode
> >>>>>      media: ov5640: Rework analog crop rectangles
> >>>>>      media: ov5640: Re-sort per-mode register tables
> >>>>>      media: ov5640: Remove ov5640_mode_init_data
> >>>>>      media: ov5640: Add HBLANK control
> >>>>>      media: ov5640: Add VBLANK control
> >>>>>      media: ov5640: Fix durations to comply with FPS
> >>>>>      media: ov5640: Implement init_cfg
> >>>>>      media: ov5640: Implement get_selection
> >>>>>      media: ov5640: Limit frame_interval to DVP mode only
> >>>>>      media: ov5640: Register device properties
> >>>>>      media: ov5640: Add RGB565_1X16 format
> >>>>>      media: ov5640: Add RGB888/BGR888 formats
> >>>>>      media: ov5640: Restrict sizes to mbus code
> >>>>>      media: ov5640: Adjust format to bpp in s_fmt
> >>>>>
> >>>>>     drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
> >>>>>     1 file changed, 830 insertions(+), 313 deletions(-)
> >>>>>
> >>>>> --
> >>>>> 2.35.0
> >>>>>
> >>>>
> >>
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-14 18:56           ` Jacopo Mondi
@ 2022-02-17 14:25             ` Eugen.Hristev
  2022-02-21  8:51               ` Jacopo Mondi
  0 siblings, 1 reply; 64+ messages in thread
From: Eugen.Hristev @ 2022-02-17 14:25 UTC (permalink / raw)
  To: jacopo
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

On 2/14/22 8:56 PM, Jacopo Mondi wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Hi Eugen
> 
> On Mon, Feb 14, 2022 at 03:08:56PM +0000, Eugen.Hristev@microchip.com wrote:
>> On 2/14/22 4:38 PM, Jacopo Mondi wrote:
>>> Hi Eugen,
>>>
>>> On Mon, Feb 14, 2022 at 02:06:02PM +0000, Eugen.Hristev@microchip.com wrote:
>>>> On 2/11/22 1:25 PM, Jacopo Mondi wrote:
>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>>
>>>>> Hi Eugen
>>>>>
>>>>>            thanks very much for testing
>>>>>
>>>>> On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
>>>>>> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
>>>>>>
>>>>>> Hello Jacopo,
>>>>>>
>>>>>>> v1:
>>>>>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>>>>>>>
>>>>>>> A branch for testing based on the most recent media-master is available at
>>>>>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
>>>>>>>
>>>>>>> If anyone with a DVP setup could verify I have not broken their use case
>>>>>>> I would very much appreciate that :)
>>>>>>
>>>>>> I started testing this on my bench.
>>>>>> So far things look good.
>>>>>>
>>>>>
>>>>> \o/
>>>>>
>>>>>> To be able to test this, I have to revert this patch :
>>>>>> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
>>>>>>
>>>>>> Otherwise the sensor will not power up when starting streaming.
>>>>>>
>>>>>>
>>>>>> I have tested several formats, as you worked more on this sensor, could
>>>>>> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
>>>>>> 1024x768 ?
>>>>>
>>>>> I never tested the sensor driver with a parallel setup I'm afraid.
>>>>> The idea behind this series is that DVP shouldn't be affected and
>>>>> continue working like it did.
>>>>
>>>> Hi Jacopo,
>>>>
>>>> I was hoping that you had more information about the driver than myself.
>>>
>>> Not on DVP mode I'm sorry :(
>>>
>>>> I can tell that the parallel mode is not affected by your series from
>>>> what I've seen so far.
>>>
>>> That's great, thanks for testing.
>>
>>
>> I found one change, before your series, I could attempt to capture BGGR
>> @ 640x480, now it looks to be gone :
>>
>> Before:
>>
>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>>           Size Range: 160x120 - 160x120
>>           Size Range: 176x144 - 176x144
>>           Size Range: 320x240 - 320x240
>>           Size Range: 640x480 - 640x480
>>           Size Range: 720x480 - 720x480
>>           Size Range: 720x576 - 720x576
>>           Size Range: 1024x768 - 1024x768
>>           Size Range: 1280x720 - 1280x720
>>           Size Range: 1920x1080 - 1920x1080
>>           Size Range: 2592x1944 - 2592x1944
>>
>>
>> After:
>>
>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>>           Size Range: 1280x720 - 1280x720
>>           Size Range: 1920x1080 - 1920x1080
>>           Size Range: 2592x1944 - 2592x1944
>>
> 
> Right... I'm limiting SRGGB formats to only resolutions > 1280x720
> as..
> 
>>
>> However trying it without your patches, it doesn't work , I don't
> 
> ... they do not work for me either.
> 
> So if they were not working before, maybe it's right not to enumerate
> them ?
> 
>> receive frames, and I can't even set 1280x720 at all, I get -EINVAL
> 
> Be aware that DVP mode prevents you from setting a format if the
> currently selected framerate is said to be "not supported" for that
> format
> 
>>
>> So I assume you have been reworking the frame sizes.
>>
>> With your series, I have tested RGGB at 1280x720 , 1920x1080 .
>> I also tested YUYV at 640x480 and RGB565_LE at 640x480.
>>
>> I can't go higher with the YUYV/RGB565, I don't receive frames anymore.
> 
> Ah, I wonder if
> 07b49ac59fd9 media: ov5640: Fix durations to comply with FPS
> 82aebf4b7314 media: ov5640: Rework analog crop rectangles
> 
> Might have impacted DVP...
> 
> Should I keep separate fields for MIPI mode and leave the totals for
> DVP untouched ?

Hi Jacopo,

I tested again without your series, and I can capture YUYV directly 
@1280x720 , which does not work anymore with your patches.

The image has some bad pixels in it, but still, capture is pretty good. 
I am not sure whether it's a timing problem on capturing pixels, I 
uploaded it here so you can have a look :

https://ibb.co/Yt8c0dJ

Eugen

> 
> Thanks again for your very useful testing
> 
> 
>> I can't go higher with the bayer to 2592x1944 . But this did not work
>> before your patches either.
>>>
>>>>
>>>>>
>>>>>> I managed to get it working fine at 640x480 .
>>>>>>
>>>>>> The sensor looks to report valid framesizes for this mbus code :
>>>>>>
>>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
>>>>>> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
>>>>>>             0x4001: MEDIA_BUS_FMT_JPEG_1X8
>>>>>>             0x2006: MEDIA_BUS_FMT_UYVY8_2X8
>>>>>>             0x200f: MEDIA_BUS_FMT_UYVY8_1X16
>>>>>>             0x2008: MEDIA_BUS_FMT_YUYV8_2X8
>>>>>>             0x2011: MEDIA_BUS_FMT_YUYV8_1X16
>>>>>>             0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
>>>>>>             0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
>>>>>>             0x1017: MEDIA_BUS_FMT_RGB565_1X16
>>>>>>             0x100a: MEDIA_BUS_FMT_RGB888_1X24
>>>>>>             0x1013: MEDIA_BUS_FMT_BGR888_1X24
>>>>>>             0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
>>>>>>             0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
>>>>>>             0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
>>>>>>             0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
>>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
>>>>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>>>>>>             Size Range: 160x120 - 160x120
>>>>>>             Size Range: 176x144 - 176x144
>>>>>>             Size Range: 320x240 - 320x240
>>>>>>             Size Range: 640x480 - 640x480
>>>>>>             Size Range: 720x480 - 720x480
>>>>>>             Size Range: 720x576 - 720x576
>>>>>>             Size Range: 1024x768 - 1024x768
>>>>>>             Size Range: 1280x720 - 1280x720
>>>>>>             Size Range: 1920x1080 - 1920x1080
>>>>>>             Size Range: 2592x1944 - 2592x1944
>>>>>> #
>>>>>>
>>>>>> but the ISC does not receive any frames at 1024x768 and 1920x1080.
>>>>>
>>>>> Are 1080p and 1024x768 working without this series applied on your
>>>>> setup ?
>>>>
>>>> I remember they weren't working before either.
>>>>
>>>> I don't know exactly to which patches to add my Tested-by , as I have
>>>> not tested the explicit patch behavior for each patch (e.g. where you
>>>> add HBLANK control, I have not tested that ).
>>>>
>>>
>>> I think it's good enough making sure I have not broke DVP.
>>>
>>> As you can see the driver now behaves in two different ways in DVP and
>>> MIPI mode. The DVP works as it used to, and the framerate is
>>> controlled by s_frame_interval, the frame size is fixed and the PCLK
>>> is computed dyanically to accomodate the required FPS. In MIPI mode the
>>> framerate is controlled by changing the vertical blankings. To each
>>> mode a pixel rate is assigned and userspace changes the frame duration
>>> by changing blankings. The most obvious gain is that the frame rate is
>>> controllable in a continuous interval instead of being limited to a
>>> few fixed values. It is my understanding that all drivers should be
>>> moved to this model and s_frame_intervall should be dropped, but
>>> unfortunately some bridge drivers in mainline still deman that.
>>>
>>> If you are interested, I think the DVP mode should be moved to use the
>>> same mecahnism as MIPI mode. I can't test so I haven't done so in this
>>> series.
>>>
>>> For now I think it's enough to make sure there are no regressions in
>>> DVP mode.
>>>
>>> For the tag, I think it would be appropriate to add it to the
>>> following one:
>>>
>>> 91ae667b0d47 media: ov5640: Limit frame_interval to DVP mode only
>>>
>>>> Is there something particular you would like me to try , except my usual
>>>> image captures ?
>>>
>>> RGB888 is weird on both the platforms I've tested on and I cannot get
>>> colors right. Does your platform support RGB888 ?
>>
>> I can't test this one unfortunately. It's a 1X24 . I have only 8 bits
>> connected, so unless you can make this a 3x8 , there isn't anything I
>> can do.
>>
>>>
>>> Thanks
>>>     j
>>>
>>>
>>>>
>>>>
>>>> Eugen
>>>>
>>>>>
>>>>> Thanks again for testin!
>>>>>
>>>>>>
>>>>>>
>>>>>> What I can say is that the raw bayer format works at 1920x1080 , frames
>>>>>> are received correctly.
>>>>>>
>>>>>> Thanks,
>>>>>> Eugen
>>>>>>
>>>>>>>
>>>>>>> v1 -> v2:
>>>>>>> - rework the modes definition to process the full pixel array
>>>>>>> - rework get_selection to report the correct BOUND and DEFAULT targets
>>>>>>> - implement init_cfg
>>>>>>> - minor style changes as suggested by Laurent
>>>>>>> - test with 1 data lane
>>>>>>>
>>>>>>> Thanks
>>>>>>>        j
>>>>>>>
>>>>>>> Jacopo Mondi (23):
>>>>>>>       media: ov5640: Add pixel rate to modes
>>>>>>>       media: ov5604: Re-arrange modes definition
>>>>>>>       media: ov5640: Add ov5640_is_csi2() function
>>>>>>>       media: ov5640: Associate bpp with formats
>>>>>>>       media: ov5640: Add LINK_FREQ control
>>>>>>>       media: ov5640: Update pixel_rate and link_freq
>>>>>>>       media: ov5640: Rework CSI-2 clock tree
>>>>>>>       media: ov5640: Rework timings programming
>>>>>>>       media: ov5640: Fix 720x480 in RGB888 mode
>>>>>>>       media: ov5640: Rework analog crop rectangles
>>>>>>>       media: ov5640: Re-sort per-mode register tables
>>>>>>>       media: ov5640: Remove ov5640_mode_init_data
>>>>>>>       media: ov5640: Add HBLANK control
>>>>>>>       media: ov5640: Add VBLANK control
>>>>>>>       media: ov5640: Fix durations to comply with FPS
>>>>>>>       media: ov5640: Implement init_cfg
>>>>>>>       media: ov5640: Implement get_selection
>>>>>>>       media: ov5640: Limit frame_interval to DVP mode only
>>>>>>>       media: ov5640: Register device properties
>>>>>>>       media: ov5640: Add RGB565_1X16 format
>>>>>>>       media: ov5640: Add RGB888/BGR888 formats
>>>>>>>       media: ov5640: Restrict sizes to mbus code
>>>>>>>       media: ov5640: Adjust format to bpp in s_fmt
>>>>>>>
>>>>>>>      drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
>>>>>>>      1 file changed, 830 insertions(+), 313 deletions(-)
>>>>>>>
>>>>>>> --
>>>>>>> 2.35.0
>>>>>>>
>>>>>>
>>>>
>>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 01/23] media: ov5640: Add pixel rate to modes
  2022-02-10 11:04 ` [PATCH v2 01/23] media: ov5640: Add pixel rate to modes Jacopo Mondi
@ 2022-02-20 11:53   ` Laurent Pinchart
  2022-02-21 20:14     ` Adam Ford
  0 siblings, 1 reply; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 11:53 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:04:36PM +0100, Jacopo Mondi wrote:
> Add to each mode supported by the sensor the ideal pixel rate, as
> defined by Table 2.1 in the chip manual.
> 
> The ideal pixel rate will be used to compute the MIPI CSI-2 clock tree.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/i2c/ov5640.c | 44 +++++++++++++++++++++++++++++++++++---
>  1 file changed, 41 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index db5a19babe67..01f4a075f86e 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -118,6 +118,29 @@ enum ov5640_frame_rate {
>  	OV5640_NUM_FRAMERATES,
>  };
>  
> +enum ov5640_pixel_rate_id {
> +	OV5640_PIXEL_RATE_168M,
> +	OV5640_PIXEL_RATE_148M,
> +	OV5640_PIXEL_RATE_124M,
> +	OV5640_PIXEL_RATE_96M,
> +	OV5640_PIXEL_RATE_48M,
> +	OV5640_NUM_PIXEL_RATES,
> +};
> +
> +/*
> + * The chip manual suggests 24/48/96/192 MHz pixel clocks.
> + *
> + * 192MHz exceeds the sysclk limits; use 168MHz as maximum pixel rate for
> + * full resolution mode @15 FPS.
> + */
> +static const u32 ov5640_pixel_rates[] = {
> +	[OV5640_PIXEL_RATE_168M] = 168000000,
> +	[OV5640_PIXEL_RATE_148M] = 148000000,
> +	[OV5640_PIXEL_RATE_124M] = 124000000,
> +	[OV5640_PIXEL_RATE_96M] = 96000000,
> +	[OV5640_PIXEL_RATE_48M] = 48000000,
> +};
> +
>  enum ov5640_format_mux {
>  	OV5640_FMT_MUX_YUV422 = 0,
>  	OV5640_FMT_MUX_RGB,
> @@ -189,6 +212,7 @@ struct reg_value {
>  struct ov5640_mode_info {
>  	enum ov5640_mode_id id;
>  	enum ov5640_downsize_mode dn_mode;
> +	enum ov5640_pixel_rate_id pixel_rate;
>  	u32 hact;
>  	u32 htot;
>  	u32 vact;
> @@ -565,7 +589,9 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
>  
>  /* power-on sensor init reg table */
>  static const struct ov5640_mode_info ov5640_mode_init_data = {
> -	0, SUBSAMPLING, 640, 1896, 480, 984,
> +	0, SUBSAMPLING,
> +	OV5640_PIXEL_RATE_96M,
> +	640, 1896, 480, 984,
>  	ov5640_init_setting_30fps_VGA,
>  	ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
>  	OV5640_30_FPS,
> @@ -574,51 +600,61 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
>  static const struct ov5640_mode_info
>  ov5640_mode_data[OV5640_NUM_MODES] = {
>  	{OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
> +	 OV5640_PIXEL_RATE_48M,
>  	 160, 1896, 120, 984,
>  	 ov5640_setting_QQVGA_160_120,
>  	 ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
>  	 OV5640_30_FPS},
>  	{OV5640_MODE_QCIF_176_144, SUBSAMPLING,
> +	 OV5640_PIXEL_RATE_48M,
>  	 176, 1896, 144, 984,
>  	 ov5640_setting_QCIF_176_144,
>  	 ARRAY_SIZE(ov5640_setting_QCIF_176_144),
>  	 OV5640_30_FPS},
>  	{OV5640_MODE_QVGA_320_240, SUBSAMPLING,
> +	 OV5640_PIXEL_RATE_48M,
>  	 320, 1896, 240, 984,
>  	 ov5640_setting_QVGA_320_240,
>  	 ARRAY_SIZE(ov5640_setting_QVGA_320_240),
>  	 OV5640_30_FPS},
>  	{OV5640_MODE_VGA_640_480, SUBSAMPLING,
> +	 OV5640_PIXEL_RATE_48M,
>  	 640, 1896, 480, 1080,
>  	 ov5640_setting_VGA_640_480,
>  	 ARRAY_SIZE(ov5640_setting_VGA_640_480),
>  	 OV5640_60_FPS},
>  	{OV5640_MODE_NTSC_720_480, SUBSAMPLING,
> +	 OV5640_PIXEL_RATE_96M,
>  	 720, 1896, 480, 984,
>  	 ov5640_setting_NTSC_720_480,
>  	 ARRAY_SIZE(ov5640_setting_NTSC_720_480),
>  	OV5640_30_FPS},
>  	{OV5640_MODE_PAL_720_576, SUBSAMPLING,
> +	 OV5640_PIXEL_RATE_96M,
>  	 720, 1896, 576, 984,
>  	 ov5640_setting_PAL_720_576,
>  	 ARRAY_SIZE(ov5640_setting_PAL_720_576),
>  	 OV5640_30_FPS},
>  	{OV5640_MODE_XGA_1024_768, SUBSAMPLING,
> +	 OV5640_PIXEL_RATE_96M,
>  	 1024, 1896, 768, 1080,
>  	 ov5640_setting_XGA_1024_768,
>  	 ARRAY_SIZE(ov5640_setting_XGA_1024_768),
>  	 OV5640_30_FPS},
>  	{OV5640_MODE_720P_1280_720, SUBSAMPLING,
> +	 OV5640_PIXEL_RATE_124M,
>  	 1280, 1892, 720, 740,
>  	 ov5640_setting_720P_1280_720,
>  	 ARRAY_SIZE(ov5640_setting_720P_1280_720),
>  	 OV5640_30_FPS},
>  	{OV5640_MODE_1080P_1920_1080, SCALING,
> +	 OV5640_PIXEL_RATE_148M,
>  	 1920, 2500, 1080, 1120,
>  	 ov5640_setting_1080P_1920_1080,
>  	 ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
>  	 OV5640_30_FPS},
>  	{OV5640_MODE_QSXGA_2592_1944, SCALING,
> +	 OV5640_PIXEL_RATE_168M,
>  	 2592, 2844, 1944, 1968,
>  	 ov5640_setting_QSXGA_2592_1944,
>  	 ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
> @@ -2743,6 +2779,7 @@ static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
>  
>  static int ov5640_init_controls(struct ov5640_dev *sensor)
>  {
> +	const struct ov5640_mode_info *mode = sensor->current_mode;
>  	const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
>  	struct ov5640_ctrls *ctrls = &sensor->ctrls;
>  	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
> @@ -2755,8 +2792,9 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
>  
>  	/* Clock related controls */
>  	ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
> -					      0, INT_MAX, 1,
> -					      ov5640_calc_pixel_rate(sensor));
> +				      ov5640_pixel_rates[OV5640_NUM_PIXEL_RATES - 1],
> +				      ov5640_pixel_rates[0], 1,
> +				      ov5640_pixel_rates[mode->pixel_rate]);
>  
>  	/* Auto/manual white balance */
>  	ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 05/23] media: ov5640: Add LINK_FREQ control
  2022-02-10 11:04 ` [PATCH v2 05/23] media: ov5640: Add LINK_FREQ control Jacopo Mondi
@ 2022-02-20 11:55   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 11:55 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:04:40PM +0100, Jacopo Mondi wrote:
> Add the V4L2_CID_LINK_FREQ control to the ov5640 driver.
> Make the control read-only for the moment.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  drivers/media/i2c/ov5640.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 71404d064045..4c3a1fd41095 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -141,6 +141,21 @@ static const u32 ov5640_pixel_rates[] = {
>  	[OV5640_PIXEL_RATE_48M] = 48000000,
>  };
>  
> +/*
> + * MIPI CSI-2 link frequencies.
> + *
> + * Derived from the above defined pixel rate for bpp = (8, 16, 24) and
> + * data_lanes = (1, 2)
> + *
> + * link_freq = (pixel_rate * bpp) / (2 * data_lanes)
> + */
> +static const s64 ov5640_csi2_link_freqs[] = {
> +	992000000, 888000000, 768000000, 744000000, 672000000, 672000000,
> +	592000000, 592000000, 576000000, 576000000, 496000000, 496000000,
> +	384000000, 384000000, 384000000, 336000000, 296000000, 288000000,
> +	248000000, 192000000, 192000000, 192000000, 96000000,
> +};
> +
>  enum ov5640_format_mux {
>  	OV5640_FMT_MUX_YUV422 = 0,
>  	OV5640_FMT_MUX_RGB,
> @@ -270,6 +285,7 @@ struct ov5640_mode_info {
>  struct ov5640_ctrls {
>  	struct v4l2_ctrl_handler handler;
>  	struct v4l2_ctrl *pixel_rate;
> +	struct v4l2_ctrl *link_freq;
>  	struct {
>  		struct v4l2_ctrl *auto_exp;
>  		struct v4l2_ctrl *exposure;
> @@ -2867,6 +2883,11 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
>  				      ov5640_pixel_rates[0], 1,
>  				      ov5640_pixel_rates[mode->pixel_rate]);
>  
> +	ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops,
> +					V4L2_CID_LINK_FREQ,
> +					ARRAY_SIZE(ov5640_csi2_link_freqs) - 1,
> +					4, ov5640_csi2_link_freqs);

You may want to explain somewhere why you've picked 4 as the default.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +
>  	/* Auto/manual white balance */
>  	ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
>  					   V4L2_CID_AUTO_WHITE_BALANCE,
> @@ -2915,6 +2936,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
>  	}
>  
>  	ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +	ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
>  	ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
>  	ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
>  

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 07/23] media: ov5640: Rework CSI-2 clock tree
  2022-02-10 11:04 ` [PATCH v2 07/23] media: ov5640: Rework CSI-2 clock tree Jacopo Mondi
@ 2022-02-20 12:17   ` Laurent Pinchart
  2022-02-21 11:39     ` Jacopo Mondi
  0 siblings, 1 reply; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 12:17 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:04:42PM +0100, Jacopo Mondi wrote:
> Re-work the ov5640_set_mipi_pclk() function to calculate the
> PLL configuration using the pixel_rate and link_freq values set at
> s_fmt time.
> 
> Rework the DVP clock mode settings to calculate the pixel clock
> internally and remove the assumption on the 16bpp format.
> 
> Tested in MIPI CSI-2 mode with 1 and 2 data lanes with:
> - all the sensor supported resolutions in UYVY and RGB565 formats.
> - resolutions >= 1280x720 in RAW Bayer format.
> - resolutions < 1280x720 in RGB888 format.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  drivers/media/i2c/ov5640.c | 189 ++++++++++++++++++-------------------
>  1 file changed, 90 insertions(+), 99 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 50b611697470..eb4789ae6abf 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -90,6 +90,7 @@
>  #define OV5640_REG_POLARITY_CTRL00	0x4740
>  #define OV5640_REG_MIPI_CTRL00		0x4800
>  #define OV5640_REG_DEBUG_MODE		0x4814
> +#define OV5640_REG_PCLK_PERIOD		0x4837
>  #define OV5640_REG_ISP_FORMAT_MUX_CTRL	0x501f
>  #define OV5640_REG_PRE_ISP_TEST_SET1	0x503d
>  #define OV5640_REG_SDE_CTRL0		0x5580
> @@ -922,20 +923,10 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
>   *                                +-----+-----+
>   *                                       +------------> PCLK
>   *
> - * This is deviating from the datasheet at least for the register
> - * 0x3108, since it's said here that the PCLK would be clocked from
> - * the PLL.
> - *
> - * There seems to be also (unverified) constraints:
> + * There seems to be also constraints:
>   *  - the PLL pre-divider output rate should be in the 4-27MHz range
>   *  - the PLL multiplier output rate should be in the 500-1000MHz range
>   *  - PCLK >= SCLK * 2 in YUV, >= SCLK in Raw or JPEG
> - *
> - * In the two latter cases, these constraints are met since our
> - * factors are hardcoded. If we were to change that, we would need to
> - * take this into account. The only varying parts are the PLL
> - * multiplier and the system clock divider, which are shared between
> - * all these clocks so won't cause any issue.
>   */
>  
>  /*
> @@ -954,13 +945,6 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
>  #define OV5640_SYSDIV_MIN	1
>  #define OV5640_SYSDIV_MAX	16
>  
> -/*
> - * Hardcode these values for scaler and non-scaler modes.
> - * FIXME: to be re-calcualted for 1 data lanes setups
> - */
> -#define OV5640_MIPI_DIV_PCLK	2
> -#define OV5640_MIPI_DIV_SCLK	1
> -
>  /*
>   * This is supposed to be ranging from 1 to 2, but the value is always
>   * set to 2 in the vendor kernels.
> @@ -1071,69 +1055,77 @@ static unsigned long ov5640_calc_sys_clk(struct ov5640_dev *sensor,
>   * ov5640_set_mipi_pclk() - Calculate the clock tree configuration values
>   *			    for the MIPI CSI-2 output.
>   *
> - * @rate: The requested bandwidth per lane in bytes per second.
> - *	  'Bandwidth Per Lane' is calculated as:
> - *	  bpl = HTOT * VTOT * FPS * bpp / num_lanes;
> - *
> - * This function use the requested bandwidth to calculate:
> - * - sample_rate = bpl / (bpp / num_lanes);
> - *	         = bpl / (PLL_RDIV * BIT_DIV * PCLK_DIV * MIPI_DIV / num_lanes);
> - *
> - * - mipi_sclk   = bpl / MIPI_DIV / 2; ( / 2 is for CSI-2 DDR)
> - *
> - * with these fixed parameters:
> - *	PLL_RDIV	= 2;
> - *	BIT_DIVIDER	= 2; (MIPI_BIT_MODE == 8 ? 2 : 2,5);
> - *	PCLK_DIV	= 1;
> - *
> - * The MIPI clock generation differs for modes that use the scaler and modes
> - * that do not. In case the scaler is in use, the MIPI_SCLK generates the MIPI
> - * BIT CLk, and thus:
> - *
> - * - mipi_sclk = bpl / MIPI_DIV / 2;
> - *   MIPI_DIV = 1;
> - *
> - * For modes that do not go through the scaler, the MIPI BIT CLOCK is generated
> - * from the pixel clock, and thus:
> - *
> - * - sample_rate = bpl / (bpp / num_lanes);
> - *	         = bpl / (2 * 2 * 1 * MIPI_DIV / num_lanes);
> - *		 = bpl / (4 * MIPI_DIV / num_lanes);
> - * - MIPI_DIV	 = bpp / (4 * num_lanes);
> - *
> - * FIXME: this have been tested with 16bpp and 2 lanes setup only.
> - * MIPI_DIV is fixed to value 2, but it -might- be changed according to the
> - * above formula for setups with 1 lane or image formats with different bpp.
> - *
> - * FIXME: this deviates from the sensor manual documentation which is quite
> - * thin on the MIPI clock tree generation part.
> + * FIXME: tested with 2 lanes only.

Not true anymore, is it ?

>   */
> -static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
> -				unsigned long rate)
> +static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor)
>  {
> -	const struct ov5640_mode_info *mode = sensor->current_mode;
> +	u8 bit_div, mipi_div, p_div, sclk_div, sclk2x_div, root_div;
> +	struct v4l2_mbus_framefmt *fmt = &sensor->fmt;
>  	u8 prediv, mult, sysdiv;
> -	u8 mipi_div;
> +	unsigned long sysclk;
> +	unsigned long sample_rate;
> +	u8 pclk_period;
> +	s64 link_freq;
>  	int ret;
>  
> +	/* Use the link frequency computed at ov5640_update_pixel_rate() time. */
> +	link_freq = ov5640_csi2_link_freqs[sensor->ctrls.link_freq->cur.val];
> +
>  	/*
> -	 * 1280x720 is reported to use 'SUBSAMPLING' only,
> -	 * but according to the sensor manual it goes through the
> -	 * scaler before subsampling.
> +	 * - mipi_div - Additional divider for the MIPI lane clock.
> +	 *
> +	 * Higher link frequencies would make sysclk > 1GHz.
> +	 * Keep the sysclk low and do not divide in the MIPI domain.
>  	 */
> -	if (mode->dn_mode == SCALING ||
> -	   (mode->id == OV5640_MODE_720P_1280_720))
> -		mipi_div = OV5640_MIPI_DIV_SCLK;
> +	if (link_freq > OV5640_LINK_RATE_MAX)
> +		mipi_div = 1;
>  	else
> -		mipi_div = OV5640_MIPI_DIV_PCLK;
> +		mipi_div = 2;
>  
> -	ov5640_calc_sys_clk(sensor, rate, &prediv, &mult, &sysdiv);
> +	sysclk = link_freq * mipi_div;
> +	ov5640_calc_sys_clk(sensor, sysclk, &prediv, &mult, &sysdiv);
>  
> -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0,
> -			     0x0f, OV5640_PLL_CTRL0_MIPI_MODE_8BIT);
> +	/*
> +	 * Adjust PLL parameters to maintain the MIPI_SCLK-to-PCLK ratio;

s/;/:/ ?

> +	 *
> +	 * - root_div = 2 (fixed)
> +	 * - bit_div : MIPI 8-bit = 2
> +	 *	       MIPI 10-bit = 2.5
> +	 * - p_div = 1 (fixed)
> +	 * - pll_div  = (2 lanes ? mipi_div : 2 * mipi_div)

There's no pll_div variable in the code, nothing called "PLL div" in
comments, and nothing in the datasheet either as far as I can tell.
Based on your reply to the v1 review, I think you mean "p_div" instead
of "pll_div". Also, you mentioned there that P_DIV is equal to

- 1 data lane = MIPI_DIV (0x3035[3:0])
- 2 data lane = 2 * MIPI_DIV

while here you write the opposite. MIPI_DIV * number data lanes seems
more logical to me, as the CSI-2 clock frequency should be lower with
more data lanes. You could thus write

	 * - p_div is set by the sensor to mipi_div * number of data lanes

Let's add a blank line here, and

	 *
	 * This results in the following MIPI_SCLK depending on the number
	 * of lanes:
	 *

> +	 *   2 lanes: MIPI_SCLK = (4 or 5) * PCLK
> +	 *   1 lanes: MIPI_SCLK = (8 or 10) * PCLK
> +	 */
> +	root_div = OV5640_PLL_CTRL3_PLL_ROOT_DIV_2;
> +	bit_div =  OV5640_PLL_CTRL0_MIPI_MODE_8BIT;
> +	p_div = OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS;
>  
> -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
> -			     0xff, sysdiv << 4 | mipi_div);
> +	/*
> +	 * Scaler clock:
> +	 * - YUV: PCLK >= 2 * SCLK
> +	 * - RAW or JPEG: PCLK >= SCLK
> +	 * - sclk2x_div = sclk_div / 2
> +	 *
> +	 * TODO: test with JPEG.
> +	 */
> +	sclk_div = ilog2(OV5640_SCLK_ROOT_DIV);
> +	sclk2x_div = ilog2(OV5640_SCLK2X_ROOT_DIV);
> +
> +	/*
> +	 * Set the sample period expressed in ns with 1-bit decimal
> +	 * (0x01=0.5ns).
> +	 */
> +	sample_rate = ov5640_pixel_rates[sensor->current_mode->pixel_rate]
> +		    * (ov5640_code_to_bpp(fmt->code) / 8);
> +	pclk_period = 2000000000U / sample_rate;
> +
> +	/* Program the clock tree registers. */
> +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0, 0x0f, bit_div);
> +	if (ret)
> +		return ret;
> +
> +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1, 0xff,
> +			     (sysdiv << 4) | mipi_div);
>  	if (ret)
>  		return ret;
>  
> @@ -1141,13 +1133,27 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
>  	if (ret)
>  		return ret;
>  
> -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
> -			     0x1f, OV5640_PLL_CTRL3_PLL_ROOT_DIV_2 | prediv);
> +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3, 0x1f,
> +			     root_div | prediv);
> +	if (ret)
> +		return ret;
> +
> +	ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
> +			     (p_div << 4) | (sclk2x_div << 2) | sclk_div);

Bits 5:4 of this register are named "PCLK root divider" in the
datasheet. Can you rename the variable to pclk_div to match the clock
tree diagram in the driver that names it "PCLK Div" ? Another option
would be to name ie pclk_root_div and update the clock tree diagram
accordingly. The p_div mention in the comment above should be renamed
too.

>  	if (ret)
>  		return ret;
>  
> -	return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER,
> -			      0x30, OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS);
> +	return ov5640_write_reg(sensor, OV5640_REG_PCLK_PERIOD, pclk_period);
> +}
> +
> +static u32 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
> +{
> +	u32 rate;
> +
> +	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
> +	rate *= ov5640_framerates[sensor->current_fr];
> +
> +	return rate;
>  }
>  
>  static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
> @@ -1167,11 +1173,16 @@ static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
>  	return _rate / *pll_rdiv / *bit_div / *pclk_div;
>  }
>  
> -static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor, unsigned long rate)
> +static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor)
>  {
>  	u8 prediv, mult, sysdiv, pll_rdiv, bit_div, pclk_div;
> +	u32 rate;
>  	int ret;
>  
> +	rate = ov5640_calc_pixel_rate(sensor);
> +	rate *= ov5640_code_to_bpp(sensor->fmt.code);
> +	rate /= sensor->ep.bus.parallel.bus_width;
> +
>  	ov5640_calc_pclk(sensor, rate, &prediv, &mult, &sysdiv, &pll_rdiv,
>  			 &bit_div, &pclk_div);
>  
> @@ -1696,16 +1707,6 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
>  	return mode;
>  }
>  
> -static u64 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
> -{
> -	u64 rate;
> -
> -	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
> -	rate *= ov5640_framerates[sensor->current_fr];
> -
> -	return rate;
> -}
> -
>  /*
>   * sensor changes between scaling and subsampling, go through
>   * exposure calculation
> @@ -1887,7 +1888,6 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
>  	enum ov5640_downsize_mode dn_mode, orig_dn_mode;
>  	bool auto_gain = sensor->ctrls.auto_gain->val == 1;
>  	bool auto_exp =  sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
> -	unsigned long rate;
>  	int ret;
>  
>  	dn_mode = mode->dn_mode;
> @@ -1906,19 +1906,10 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
>  			goto restore_auto_gain;
>  	}
>  
> -	/*
> -	 * All the formats we support have 16 bits per pixel, seems to require
> -	 * the same rate than YUV, so we can just use 16 bpp all the time.
> -	 */
> -	rate = ov5640_calc_pixel_rate(sensor) * 16;
> -	if (ov5640_is_csi2(sensor)) {
> -		rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes;
> -		ret = ov5640_set_mipi_pclk(sensor, rate);
> -	} else {
> -		rate = rate / sensor->ep.bus.parallel.bus_width;
> -		ret = ov5640_set_dvp_pclk(sensor, rate);
> -	}
> -
> +	if (ov5640_is_csi2(sensor))
> +		ret = ov5640_set_mipi_pclk(sensor);
> +	else
> +		ret = ov5640_set_dvp_pclk(sensor);
>  	if (ret < 0)
>  		return 0;
>  

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 08/23] media: ov5640: Rework timings programming
  2022-02-10 11:04 ` [PATCH v2 08/23] media: ov5640: Rework timings programming Jacopo Mondi
@ 2022-02-20 12:44   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 12:44 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:04:43PM +0100, Jacopo Mondi wrote:
> The current definition of a sensor mode defines timings as follows:
> 
> - hact, vact: Visible width and height
> - htot, vtot: Total sizes including blankings
> 
> This makes difficult to clearly separate the visible sizes from the
> blankings and to make the vertical blanking programmable.
> 
> Rework the sensor modes sizes definition to:
> - Report the analog crop sizes
> - Report the visible crop size
> - Report the total pixels per line as HBLANK is fixed
> - Report the VBLANK value to make it programmable
> 
> Also modify the ov5640_set_timings() function to program all the
> windowing registers are remove them from the per-mode register-value
> tables.
> 
> Do not change the timing values from the ones reported in the register
> tables to maintain bisectability.

That's the way to go, but ... (see below)

> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  drivers/media/i2c/ov5640.c | 441 +++++++++++++++++++++++++------------
>  1 file changed, 296 insertions(+), 145 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index eb4789ae6abf..9ba1b44d21f7 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -61,10 +61,16 @@
>  #define OV5640_REG_AEC_PK_MANUAL	0x3503
>  #define OV5640_REG_AEC_PK_REAL_GAIN	0x350a
>  #define OV5640_REG_AEC_PK_VTS		0x350c
> +#define OV5640_REG_TIMING_HS		0x3800
> +#define OV5640_REG_TIMING_VS		0x3802
> +#define OV5640_REG_TIMING_HW		0x3804
> +#define OV5640_REG_TIMING_VH		0x3806
>  #define OV5640_REG_TIMING_DVPHO		0x3808
>  #define OV5640_REG_TIMING_DVPVO		0x380a
>  #define OV5640_REG_TIMING_HTS		0x380c
>  #define OV5640_REG_TIMING_VTS		0x380e
> +#define OV5640_REG_TIMING_HOFFS		0x3810
> +#define OV5640_REG_TIMING_VOFFS		0x3812
>  #define OV5640_REG_TIMING_TC_REG20	0x3820
>  #define OV5640_REG_TIMING_TC_REG21	0x3821
>  #define OV5640_REG_AEC_CTRL00		0x3a00
> @@ -276,12 +282,17 @@ struct ov5640_mode_info {
>  	enum ov5640_mode_id id;
>  	enum ov5640_downsize_mode dn_mode;
>  	enum ov5640_pixel_rate_id pixel_rate;
> -	u32 hact;
> +	/* Analog crop rectangle. */
> +	struct v4l2_rect analog_crop;
> +	/* Visibile crop: from analog crop top-left corner. */
> +	struct v4l2_rect crop;
> +	/* Total pixels per line: crop.width + fixed hblank. */
>  	u32 htot;
> -	u32 vact;
> -	u32 vtot;
> +	/* Default vertical blanking: frame height = crop.height + vblank. */
> +	u32 vblank_def;
>  	const struct reg_value *reg_data;
>  	u32 reg_data_size;
> +	/* DVP only; ignored in MIPI mode. */
>  	u32 max_fps;
>  };
>  
> @@ -387,11 +398,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
>  	{0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -459,11 +466,7 @@ static const struct reg_value ov5640_setting_VGA_640_480[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -478,11 +481,7 @@ static const struct reg_value ov5640_setting_XGA_1024_768[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -497,11 +496,7 @@ static const struct reg_value ov5640_setting_QVGA_320_240[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -516,11 +511,7 @@ static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -534,11 +525,7 @@ static const struct reg_value ov5640_setting_QCIF_176_144[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -553,11 +540,7 @@ static const struct reg_value ov5640_setting_NTSC_720_480[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -572,11 +555,7 @@ static const struct reg_value ov5640_setting_PAL_720_576[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -591,11 +570,7 @@ static const struct reg_value ov5640_setting_720P_1280_720[] = {
>  	{0x3c07, 0x07, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> -	{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
> +	{0x3815, 0x31, 0, 0},
>  	{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
>  	{0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
> @@ -610,11 +585,7 @@ static const struct reg_value ov5640_setting_1080P_1920_1080[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x11, 0, 0},
> -	{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
> +	{0x3815, 0x11, 0, 0},
>  	{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
>  	{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -625,9 +596,6 @@ static const struct reg_value ov5640_setting_1080P_1920_1080[] = {
>  	{0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0},
>  	{0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> -	{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
> -	{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
> -	{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
>  	{0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
>  	{0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
>  	{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
> @@ -641,11 +609,7 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x11, 0, 0},
> -	{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
> -	{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
> -	{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
> -	{0x3810, 0x00, 0, 0},
> -	{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
> +	{0x3815, 0x11, 0, 0},
>  	{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
>  	{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
>  	{0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
> @@ -658,96 +622,250 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
>  
>  /* power-on sensor init reg table */
>  static const struct ov5640_mode_info ov5640_mode_init_data = {
> -	0, SUBSAMPLING,
> -	OV5640_PIXEL_RATE_96M,
> -	640, 1896, 480, 984,
> -	ov5640_init_setting_30fps_VGA,
> -	ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
> -	OV5640_30_FPS,
> +		.id		= 0,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_96M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 4,
> +			.width	= 2623,
> +			.height	= 1947,

The values here match the above tables given that you write

	OV5640_REG_TIMING_HW = analog_crop->width
	OV5640_REG_TIMING_VH = analog_crop->height

below. However, that's not correct. The HW and VH registers store the X
address end and Y address end respectively, which are equal to left +
width - 1 and top + height - 1. You should thus update the code below to
read

	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW,
				 analog_crop->left + analog_crop->width - 1);
	if (ret < 0)
		return ret;

	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH,
				 analog_crop->top + analog_crop->height - 1);
	if (ret < 0)
		return ret;

and update the analog_crop width and height values in this table
accordingly. All but the last three entries should be

		.analog_crop = {
			.left	= 0,
			.top	= 4,
			.width	= 2624,
			.height	= 1944,
		},

> +		},
> +		.crop = {
> +			.left	= 16,
> +			.top	= 6,
> +			.width	= 640,
> +			.height	= 480,
> +		},
> +		.htot		= 1896,
> +		.vblank_def	= 504,
> +		.reg_data	= ov5640_init_setting_30fps_VGA,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
> +		.max_fps	= OV5640_30_FPS
>  };
>  
>  static const struct ov5640_mode_info
>  ov5640_mode_data[OV5640_NUM_MODES] = {
>  	{
>  		/* 160x120 */
> -		OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
> -		OV5640_PIXEL_RATE_48M,
> -		160, 1896, 120, 984,
> -		ov5640_setting_QQVGA_160_120,
> -		ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
> -		OV5640_30_FPS
> +		.id		= OV5640_MODE_QQVGA_160_120,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_48M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 4,
> +			.width	= 2623,
> +			.height	= 1947,
> +		},
> +		.crop = {
> +			.left	= 16,
> +			.top	= 6,
> +			.width	= 160,
> +			.height	= 120,
> +		},
> +		.htot		= 1896,
> +		.vblank_def	= 864,
> +		.reg_data	= ov5640_setting_QQVGA_160_120,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
> +		.max_fps	= OV5640_30_FPS
>  	}, {
>  		/* 176x144 */
> -		OV5640_MODE_QCIF_176_144, SUBSAMPLING,
> -		OV5640_PIXEL_RATE_48M,
> -		176, 1896, 144, 984,
> -		ov5640_setting_QCIF_176_144,
> -		ARRAY_SIZE(ov5640_setting_QCIF_176_144),
> -		OV5640_30_FPS
> +		.id		= OV5640_MODE_QCIF_176_144,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_48M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 4,
> +			.width	= 2623,
> +			.height	= 1947,
> +		},
> +		.crop = {
> +			.left	= 16,
> +			.top	= 6,
> +			.width	= 176,
> +			.height	= 144,
> +		},
> +		.htot		= 1896,
> +		.vblank_def	= 840,
> +		.reg_data	= ov5640_setting_QCIF_176_144,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QCIF_176_144),
> +		.max_fps	= OV5640_30_FPS
>  	}, {
>  		/* 320x240 */
> -		OV5640_MODE_QVGA_320_240, SUBSAMPLING,
> -		OV5640_PIXEL_RATE_48M,
> -		320, 1896, 240, 984,
> -		ov5640_setting_QVGA_320_240,
> -		ARRAY_SIZE(ov5640_setting_QVGA_320_240),
> -		OV5640_30_FPS
> +		.id		= OV5640_MODE_QVGA_320_240,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_48M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 4,
> +			.width	= 2623,
> +			.height	= 1947,
> +		},
> +		.crop = {
> +			.left	= 16,
> +			.top	= 6,
> +			.width	= 320,
> +			.height	= 240,
> +		},
> +		.htot		= 1896,
> +		.vblank_def	= 744,
> +		.reg_data	= ov5640_setting_QVGA_320_240,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QVGA_320_240),
> +		.max_fps	= OV5640_30_FPS
>  	}, {
>  		/* 640x480 */
> -		OV5640_MODE_VGA_640_480, SUBSAMPLING,
> -		OV5640_PIXEL_RATE_48M,
> -		640, 1896, 480, 1080,
> -		ov5640_setting_VGA_640_480,
> -		ARRAY_SIZE(ov5640_setting_VGA_640_480),
> -		OV5640_60_FPS
> +		.id		= OV5640_MODE_VGA_640_480,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_48M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 4,
> +			.width	= 2623,
> +			.height	= 1947,
> +		},
> +		.crop = {
> +			.left	= 16,
> +			.top	= 6,
> +			.width	= 640,
> +			.height	= 480,
> +		},
> +		.htot		= 1896,
> +		.vblank_def	= 600,
> +		.reg_data	= ov5640_setting_VGA_640_480,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_VGA_640_480),
> +		.max_fps	= OV5640_60_FPS
>  	}, {
>  		/* 720x480 */
> -		OV5640_MODE_NTSC_720_480, SUBSAMPLING,
> -		OV5640_PIXEL_RATE_96M,
> -		720, 1896, 480, 984,
> -		ov5640_setting_NTSC_720_480,
> -		ARRAY_SIZE(ov5640_setting_NTSC_720_480),
> -		OV5640_30_FPS
> +		.id		= OV5640_MODE_NTSC_720_480,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_96M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 4,
> +			.width	= 2623,
> +			.height	= 1947,
> +		},
> +		.crop = {
> +			.left	= 16,
> +			.top	= 60,
> +			.width	= 720,
> +			.height	= 480,
> +		},
> +		.htot		= 1896,
> +		.vblank_def	= 504,
> +		.reg_data	= ov5640_setting_NTSC_720_480,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_NTSC_720_480),
> +		.max_fps	= OV5640_30_FPS
>  	}, {
>  		/* 720x576 */
> -		OV5640_MODE_PAL_720_576, SUBSAMPLING,
> -		OV5640_PIXEL_RATE_96M,
> -		720, 1896, 576, 984,
> -		ov5640_setting_PAL_720_576,
> -		ARRAY_SIZE(ov5640_setting_PAL_720_576),
> -		OV5640_30_FPS
> +		.id		= OV5640_MODE_PAL_720_576,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_96M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 4,
> +			.width	= 2623,
> +			.height	= 1947,
> +		},
> +		.crop = {
> +			.left	= 56,
> +			.top	= 6,
> +			.width	= 720,
> +			.height	= 576,
> +		},
> +		.htot		= 1896,
> +		.vblank_def	= 408,
> +		.reg_data	= ov5640_setting_PAL_720_576,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_PAL_720_576),
> +		.max_fps	= OV5640_30_FPS
>  	}, {
>  		/* 1024x768 */
> -		OV5640_MODE_XGA_1024_768, SUBSAMPLING,
> -		OV5640_PIXEL_RATE_96M,
> -		1024, 1896, 768, 1080,
> -		ov5640_setting_XGA_1024_768,
> -		ARRAY_SIZE(ov5640_setting_XGA_1024_768),
> -		OV5640_30_FPS
> +		.id		= OV5640_MODE_XGA_1024_768,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_96M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 4,
> +			.width	= 2623,
> +			.height	= 1947,
> +		},
> +		.crop = {
> +			.left	= 16,
> +			.top	= 6,
> +			.width	= 1024,
> +			.height	= 768,
> +		},
> +		.htot		= 1896,
> +		.vblank_def	= 312,
> +		.reg_data	= ov5640_setting_XGA_1024_768,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_XGA_1024_768),
> +		.max_fps	= OV5640_30_FPS
>  	}, {
>  		/* 1280x720 */
> -		OV5640_MODE_720P_1280_720, SUBSAMPLING,
> -		OV5640_PIXEL_RATE_124M,
> -		1280, 1892, 720, 740,
> -		ov5640_setting_720P_1280_720,
> -		ARRAY_SIZE(ov5640_setting_720P_1280_720),
> -		OV5640_30_FPS
> +		.id		= OV5640_MODE_720P_1280_720,
> +		.dn_mode	= SUBSAMPLING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_124M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 250,
> +			.width	= 2623,
> +			.height	= 1705,
> +		},

		.analog_crop = {
			.left	= 0,
			.top	= 250,
			.width	= 2624,
			.height	= 1456,
		},

> +		.crop = {
> +			.left	= 16,
> +			.top	= 4,
> +			.width	= 1280,
> +			.height	= 720,
> +		},
> +		.htot		= 1892,
> +		.vblank_def	= 20,
> +		.reg_data	= ov5640_setting_720P_1280_720,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_720P_1280_720),
> +		.max_fps	= OV5640_30_FPS
>  	}, {
>  		/* 1920x1080 */
> -		OV5640_MODE_1080P_1920_1080, SCALING,
> -		OV5640_PIXEL_RATE_148M,
> -		1920, 2500, 1080, 1120,
> -		ov5640_setting_1080P_1920_1080,
> -		ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
> -		OV5640_30_FPS
> +		.id		= OV5640_MODE_1080P_1920_1080,
> +		.dn_mode	= SCALING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_148M,
> +		.analog_crop = {
> +			.left	= 336,
> +			.top	= 434,
> +			.width	= 2287,
> +			.height	= 1521,
> +		},

		.analog_crop = {
			.left	= 336,
			.top	= 434,
			.width	= 1952,
			.height	= 1088,
		},

> +		.crop = {
> +			.left	= 16,
> +			.top	= 4,
> +			.width	= 1920,
> +			.height	= 1080,
> +		},
> +		.htot		= 2500,
> +		.vblank_def	= 40,
> +		.reg_data	= ov5640_setting_1080P_1920_1080,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
> +		.max_fps	= OV5640_30_FPS
>  	}, {
>  		/* 2592x1944 */
> -		OV5640_MODE_QSXGA_2592_1944, SCALING,
> -		OV5640_PIXEL_RATE_168M,
> -		2592, 2844, 1944, 1968,
> -		ov5640_setting_QSXGA_2592_1944,
> -		ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
> -		OV5640_15_FPS
> +		.id		= OV5640_MODE_QSXGA_2592_1944,
> +		.dn_mode	= SCALING,
> +		.pixel_rate	= OV5640_PIXEL_RATE_168M,
> +		.analog_crop = {
> +			.left	= 0,
> +			.top	= 0,
> +			.width	= 2623,
> +			.height	= 1951,
> +		},

		.analog_crop = {
			.left	= 0,
			.top	= 0,
			.width	= 2624,
			.height	= 1952,
		},

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +		.crop = {
> +			.left	= 16,
> +			.top	= 4,
> +			.width	= 2592,
> +			.height	= 1944,
> +		},
> +		.htot		= 2844,
> +		.vblank_def	= 24,
> +		.reg_data	= ov5640_setting_QSXGA_2592_1944,
> +		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
> +		.max_fps	= OV5640_15_FPS
>  	},
>  };
>  
> @@ -1150,7 +1268,8 @@ static u32 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
>  {
>  	u32 rate;
>  
> -	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
> +	rate = sensor->current_mode->htot
> +	     * (sensor->current_mode->crop.height + sensor->current_mode->vblank_def);
>  	rate *= ov5640_framerates[sensor->current_fr];
>  
>  	return rate;
> @@ -1234,17 +1353,21 @@ static int ov5640_set_jpeg_timings(struct ov5640_dev *sensor,
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ov5640_write_reg16(sensor, OV5640_REG_VFIFO_HSIZE, mode->hact);
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_VFIFO_HSIZE,
> +				 mode->crop.width);
>  	if (ret < 0)
>  		return ret;
>  
> -	return ov5640_write_reg16(sensor, OV5640_REG_VFIFO_VSIZE, mode->vact);
> +	return ov5640_write_reg16(sensor, OV5640_REG_VFIFO_VSIZE,
> +				  mode->crop.height);
>  }
>  
>  /* download ov5640 settings to sensor through i2c */
>  static int ov5640_set_timings(struct ov5640_dev *sensor,
>  			      const struct ov5640_mode_info *mode)
>  {
> +	const struct v4l2_rect *analog_crop = &mode->analog_crop;
> +	const struct v4l2_rect *crop = &mode->crop;
>  	int ret;
>  
>  	if (sensor->fmt.code == MEDIA_BUS_FMT_JPEG_1X8) {
> @@ -1253,11 +1376,35 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
>  			return ret;
>  	}
>  
> -	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HS, analog_crop->left);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VS, analog_crop->top);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW, analog_crop->width);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH, analog_crop->height);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HOFFS, crop->left);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VOFFS, crop->top);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, crop->width);
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, crop->height);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -1265,7 +1412,12 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
>  	if (ret < 0)
>  		return ret;
>  
> -	return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS,
> +				 crop->height + mode->vblank_def);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
>  }
>  
>  static int ov5640_load_regs(struct ov5640_dev *sensor,
> @@ -1693,11 +1845,11 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
>  
>  	mode = v4l2_find_nearest_size(ov5640_mode_data,
>  				      ARRAY_SIZE(ov5640_mode_data),
> -				      hact, vact,
> -				      width, height);
> +				      crop.width, crop.height, width, height);
>  
>  	if (!mode ||
> -	    (!nearest && (mode->hact != width || mode->vact != height)))
> +	    (!nearest &&
> +	     (mode->crop.width != width || mode->crop.height != height)))
>  		return NULL;
>  
>  	/* Check to see if the current mode exceeds the max frame rate */
> @@ -2381,8 +2533,8 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
>  	mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true);
>  	if (!mode)
>  		return -EINVAL;
> -	fmt->width = mode->hact;
> -	fmt->height = mode->vact;
> +	fmt->width = mode->crop.width;
> +	fmt->height = mode->crop.height;
>  
>  	if (new_mode)
>  		*new_mode = mode;
> @@ -3014,11 +3166,9 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
>  	if (fse->index >= OV5640_NUM_MODES)
>  		return -EINVAL;
>  
> -	fse->min_width =
> -		ov5640_mode_data[fse->index].hact;
> +	fse->min_width = ov5640_mode_data[fse->index].crop.width;
>  	fse->max_width = fse->min_width;
> -	fse->min_height =
> -		ov5640_mode_data[fse->index].vact;
> +	fse->min_height = ov5640_mode_data[fse->index].crop.height;
>  	fse->max_height = fse->min_height;
>  
>  	return 0;
> @@ -3082,15 +3232,16 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
>  	mode = sensor->current_mode;
>  
>  	frame_rate = ov5640_try_frame_interval(sensor, &fi->interval,
> -					       mode->hact, mode->vact);
> +					       mode->crop.width,
> +					       mode->crop.height);
>  	if (frame_rate < 0) {
>  		/* Always return a valid frame interval value */
>  		fi->interval = sensor->frame_interval;
>  		goto out;
>  	}
>  
> -	mode = ov5640_find_mode(sensor, frame_rate, mode->hact,
> -				mode->vact, true);
> +	mode = ov5640_find_mode(sensor, frame_rate, mode->crop.width,
> +				mode->crop.height, true);
>  	if (!mode) {
>  		ret = -EINVAL;
>  		goto out;

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 09/23] media: ov5640: Fix 720x480 in RGB888 mode
  2022-02-10 11:04 ` [PATCH v2 09/23] media: ov5640: Fix 720x480 in RGB888 mode Jacopo Mondi
@ 2022-02-20 12:50   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 12:50 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:04:44PM +0100, Jacopo Mondi wrote:
> Adjust the left crop of 720x480 to enable capture in RGB888 format,
> which is otherwise broken.

How is it broken ?

> The 56 pixels alignment has been copied from the 720x576 mode.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  drivers/media/i2c/ov5640.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 9ba1b44d21f7..f817f865ad16 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -746,7 +746,7 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.height	= 1947,
>  		},
>  		.crop = {
> -			.left	= 16,
> +			.left	= 56,

The values look weird. The mode has an analog crop width of 2624, and
uses subsampling. After subsampling the width is thus 1312, and a left
offset of 16 or 56 for the crop rectangle thus output an image that
isn't centered.

Regardless, given that the centering issue preexists, if this fixes the
problem,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

>  			.top	= 60,
>  			.width	= 720,
>  			.height	= 480,

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 11/23] media: ov5640: Re-sort per-mode register tables
  2022-02-10 11:04 ` [PATCH v2 11/23] media: ov5640: Re-sort per-mode register tables Jacopo Mondi
@ 2022-02-20 12:52   ` Laurent Pinchart
  2022-02-20 12:59     ` Laurent Pinchart
  0 siblings, 1 reply; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 12:52 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:04:46PM +0100, Jacopo Mondi wrote:
> The per-mode register tables are not sorted by size. Fix it.
> 
> Cosmetic change only.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/i2c/ov5640.c | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 72b78201f089..17835e71665a 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -462,7 +462,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
>  	{0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
>  };
>  
> -static const struct reg_value ov5640_setting_VGA_640_480[] = {
> +static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> @@ -473,11 +473,10 @@ static const struct reg_value ov5640_setting_VGA_640_480[] = {
>  	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
>  	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
>  	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
> -	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> -	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
>  };
>  
> -static const struct reg_value ov5640_setting_XGA_1024_768[] = {
> +static const struct reg_value ov5640_setting_QCIF_176_144[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> @@ -507,7 +506,7 @@ static const struct reg_value ov5640_setting_QVGA_320_240[] = {
>  	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
>  };
>  
> -static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
> +static const struct reg_value ov5640_setting_VGA_640_480[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> @@ -518,10 +517,11 @@ static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
>  	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
>  	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
>  	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
> -	{0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
> +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
>  };
>  
> -static const struct reg_value ov5640_setting_QCIF_176_144[] = {
> +static const struct reg_value ov5640_setting_NTSC_720_480[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> @@ -536,7 +536,7 @@ static const struct reg_value ov5640_setting_QCIF_176_144[] = {
>  	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
>  };
>  
> -static const struct reg_value ov5640_setting_NTSC_720_480[] = {
> +static const struct reg_value ov5640_setting_PAL_720_576[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},
> @@ -551,7 +551,7 @@ static const struct reg_value ov5640_setting_NTSC_720_480[] = {
>  	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
>  };
>  
> -static const struct reg_value ov5640_setting_PAL_720_576[] = {
> +static const struct reg_value ov5640_setting_XGA_1024_768[] = {
>  	{0x3c07, 0x08, 0, 0},
>  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
>  	{0x3814, 0x31, 0, 0},

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [v2.1] media: ov5640: Rework analog crop rectangles
  2022-02-11  9:34   ` [v2.1] " Jacopo Mondi
@ 2022-02-20 12:56     ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 12:56 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Fri, Feb 11, 2022 at 10:34:32AM +0100, Jacopo Mondi wrote:
> The OV5640 pixel array is composed as:
> - vertically: 16 dummy columns, 2592 valid ones and 16 dummy columns for
>   a total of 2624 columns
> - horizontally: 8 optical black lines, 6 dummy ones, 1944 valid and 6
>   dummies for a total of 1964 lines
> 
> Adjust the analog crop rectangle in all modes to:
> - Skip the first 16 dummy columns
> - Skip the first 14 black/dummy lines
> - Pass the whole valid pixel array size to the ISP for all modes except
>   1024x768, 720p and 1080p which are obtained by cropping the valid pixel array.
> 
> Adjust how timings is programmed to comply with the new definitions.
> 
> Tested in RGB565, UYVY, RGB565 and RGB888 modes.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  drivers/media/i2c/ov5640.c | 120 +++++++++++++++++++++----------------
>  1 file changed, 68 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index f817f865ad16..232afd4d906a 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -626,14 +626,14 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
>  		.dn_mode	= SUBSAMPLING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_96M,
>  		.analog_crop = {
> -			.left	= 0,
> -			.top	= 4,
> -			.width	= 2623,
> -			.height	= 1947,
> +			.left	= OV5640_PIXEL_ARRAY_LEFT,
> +			.top	= OV5640_PIXEL_ARRAY_TOP,
> +			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,

These macros are added in 17/23.

>  		},
>  		.crop = {
> -			.left	= 16,
> -			.top	= 6,
> +			.left	= 2,
> +			.top	= 4,
>  			.width	= 640,
>  			.height	= 480,
>  		},
> @@ -644,22 +644,23 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
>  		.max_fps	= OV5640_30_FPS
>  };
> 
> -static const struct ov5640_mode_info
> -ov5640_mode_data[OV5640_NUM_MODES] = {
> +static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  	{
>  		/* 160x120 */
>  		.id		= OV5640_MODE_QQVGA_160_120,
>  		.dn_mode	= SUBSAMPLING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_48M,
>  		.analog_crop = {
> -			.left	= 0,
> -			.top	= 4,
> -			.width	= 2623,
> -			.height	= 1947,
> +			/* Feed the full valid pixel array to the ISP. */
> +			.left	= OV5640_PIXEL_ARRAY_LEFT,
> +			.top	= OV5640_PIXEL_ARRAY_TOP,
> +			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
>  		},
>  		.crop = {
> -			.left	= 16,
> -			.top	= 6,
> +			/* Maintain a minimum digital crop processing margins. */
> +			.left	= 2,
> +			.top	= 4,
>  			.width	= 160,
>  			.height	= 120,
>  		},
> @@ -674,14 +675,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.dn_mode	= SUBSAMPLING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_48M,
>  		.analog_crop = {
> -			.left	= 0,
> -			.top	= 4,
> -			.width	= 2623,
> -			.height	= 1947,
> +			/* Feed the full valid pixel array to the ISP. */
> +			.left	= OV5640_PIXEL_ARRAY_LEFT,
> +			.top	= OV5640_PIXEL_ARRAY_TOP,
> +			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
>  		},
>  		.crop = {
> -			.left	= 16,
> -			.top	= 6,
> +			/* Maintain a minimum digital crop processing margins. */
> +			.left	= 2,
> +			.top	= 4,
>  			.width	= 176,
>  			.height	= 144,
>  		},
> @@ -696,14 +699,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.dn_mode	= SUBSAMPLING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_48M,
>  		.analog_crop = {
> -			.left	= 0,
> -			.top	= 4,
> -			.width	= 2623,
> -			.height	= 1947,
> +			/* Feed the full valid pixel array to the ISP. */
> +			.left	= OV5640_PIXEL_ARRAY_LEFT,
> +			.top	= OV5640_PIXEL_ARRAY_TOP,
> +			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
>  		},
>  		.crop = {
> -			.left	= 16,
> -			.top	= 6,
> +			/* Maintain a minimum digital crop processing margins. */
> +			.left	= 2,
> +			.top	= 4,
>  			.width	= 320,
>  			.height	= 240,
>  		},
> @@ -718,14 +723,16 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.dn_mode	= SUBSAMPLING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_48M,
>  		.analog_crop = {
> -			.left	= 0,
> -			.top	= 4,
> -			.width	= 2623,
> -			.height	= 1947,
> +			/* Feed the full valid pixel array to the ISP. */
> +			.left	= OV5640_PIXEL_ARRAY_LEFT,
> +			.top	= OV5640_PIXEL_ARRAY_TOP,
> +			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
>  		},
>  		.crop = {
> -			.left	= 16,
> -			.top	= 6,
> +			/* Maintain a minimum digital crop processing margins. */
> +			.left	= 2,
> +			.top	= 4,
>  			.width	= 640,
>  			.height	= 480,
>  		},
> @@ -740,12 +747,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.dn_mode	= SUBSAMPLING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_96M,
>  		.analog_crop = {
> -			.left	= 0,
> -			.top	= 4,
> -			.width	= 2623,
> -			.height	= 1947,
> +			/* Feed the full valid pixel array to the ISP. */
> +			.left	= OV5640_PIXEL_ARRAY_LEFT,
> +			.top	= OV5640_PIXEL_ARRAY_TOP,
> +			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
>  		},
>  		.crop = {
> +			/* Maintain a minimum digital crop processing margins. */
>  			.left	= 56,
>  			.top	= 60,
>  			.width	= 720,
> @@ -762,12 +771,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.dn_mode	= SUBSAMPLING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_96M,
>  		.analog_crop = {
> -			.left	= 0,
> -			.top	= 4,
> -			.width	= 2623,
> -			.height	= 1947,
> +			/* Feed the full valid pixel array to the ISP. */
> +			.left	= OV5640_PIXEL_ARRAY_LEFT,
> +			.top	= OV5640_PIXEL_ARRAY_TOP,
> +			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
>  		},
>  		.crop = {
> +			/* Maintain a minimum digital crop processing margins. */
>  			.left	= 56,
>  			.top	= 6,
>  			.width	= 720,
> @@ -786,8 +797,8 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.analog_crop = {
>  			.left	= 0,
>  			.top	= 4,
> -			.width	= 2623,
> -			.height	= 1947,
> +			.width	= OV5640_NATIVE_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
>  		},
>  		.crop = {
>  			.left	= 16,
> @@ -808,8 +819,8 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.analog_crop = {
>  			.left	= 0,
>  			.top	= 250,
> -			.width	= 2623,
> -			.height	= 1705,
> +			.width	= 2624,
> +			.height	= 1456,
>  		},
>  		.crop = {
>  			.left	= 16,
> @@ -828,12 +839,14 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.dn_mode	= SCALING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_148M,
>  		.analog_crop = {
> +			/* Crop the full valid pixel array in the center. */
>  			.left	= 336,
>  			.top	= 434,
> -			.width	= 2287,
> -			.height	= 1521,
> +			.width	= 1952,
> +			.height	= 1088,
>  		},
>  		.crop = {
> +			/* Maintain a larger digital crop processing margins. */
>  			.left	= 16,
>  			.top	= 4,
>  			.width	= 1920,
> @@ -850,16 +863,17 @@ ov5640_mode_data[OV5640_NUM_MODES] = {
>  		.dn_mode	= SCALING,
>  		.pixel_rate	= OV5640_PIXEL_RATE_168M,
>  		.analog_crop = {
> +			/* Give more processing margin to full resolution. */
>  			.left	= 0,
>  			.top	= 0,
> -			.width	= 2623,
> -			.height	= 1951,
> +			.width	= OV5640_NATIVE_WIDTH,
> +			.height	= 1952,
>  		},
>  		.crop = {
>  			.left	= 16,
>  			.top	= 4,
> -			.width	= 2592,
> -			.height	= 1944,
> +			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> +			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
>  		},
>  		.htot		= 2844,
>  		.vblank_def	= 24,
> @@ -1384,11 +1398,13 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
>  	if (ret < 0)
>  		return ret;
> 
> -	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW, analog_crop->width);
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HW,
> +				 analog_crop->width + analog_crop->left - 1);
>  	if (ret < 0)
>  		return ret;
> 
> -	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH, analog_crop->height);
> +	ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VH,
> +				 analog_crop->height + analog_crop->top - 1);

I'd move this to 08/23 as mentioned in the review of that patch.

>  	if (ret < 0)
>  		return ret;
> 

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 12/23] media: ov5640: Remove ov5640_mode_init_data
  2022-02-10 11:04 ` [PATCH v2 12/23] media: ov5640: Remove ov5640_mode_init_data Jacopo Mondi
@ 2022-02-20 12:58   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 12:58 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:04:47PM +0100, Jacopo Mondi wrote:
> The ov5640_mode_init_data is a fictional sensor more which is used to
> program the initial sensor settings.
> 
> It is only used to initialize the sensor and can be replaced
> it with a throw-away mode which just wraps the register table.
> 
> Also rename the register table to drop the format from the name to make
> it clear an actual sensor mode has to be applied after the initial
> programming.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/i2c/ov5640.c | 47 ++++++++------------------------------
>  1 file changed, 10 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 17835e71665a..2a922224ca9d 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -382,7 +382,7 @@ static inline bool ov5640_is_csi2(struct ov5640_dev *sensor)
>   * over i2c.
>   */
>  /* YUV422 UYVY VGA@30fps */
> -static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
> +static const struct reg_value ov5640_init_setting[] = {
>  	{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
>  	{0x3103, 0x03, 0, 0}, {0x3630, 0x36, 0, 0},
>  	{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
> @@ -620,30 +620,6 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
>  	{0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70},
>  };
>  
> -/* power-on sensor init reg table */
> -static const struct ov5640_mode_info ov5640_mode_init_data = {
> -		.id		= 0,
> -		.dn_mode	= SUBSAMPLING,
> -		.pixel_rate	= OV5640_PIXEL_RATE_96M,
> -		.analog_crop = {
> -			.left	= OV5640_PIXEL_ARRAY_LEFT,
> -			.top	= OV5640_PIXEL_ARRAY_TOP,
> -			.width	= OV5640_PIXEL_ARRAY_WIDTH,
> -			.height	= OV5640_PIXEL_ARRAY_HEIGHT,
> -		},
> -		.crop = {
> -			.left	= 2,
> -			.top	= 4,
> -			.width	= 640,
> -			.height	= 480,
> -		},
> -		.htot		= 1896,
> -		.vblank_def	= 504,
> -		.reg_data	= ov5640_init_setting_30fps_VGA,
> -		.reg_data_size	= ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
> -		.max_fps	= OV5640_30_FPS
> -};
> -
>  static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  	{
>  		/* 160x120 */
> @@ -1440,17 +1416,16 @@ static int ov5640_set_timings(struct ov5640_dev *sensor,
>  	return 0;
>  }
>  
> -static int ov5640_load_regs(struct ov5640_dev *sensor,
> -			    const struct ov5640_mode_info *mode)
> +static void ov5640_load_regs(struct ov5640_dev *sensor,
> +			     const struct reg_value *regs, unsigned int regnum)
>  {
> -	const struct reg_value *regs = mode->reg_data;
>  	unsigned int i;
>  	u32 delay_ms;
>  	u16 reg_addr;
>  	u8 mask, val;
>  	int ret = 0;
>  
> -	for (i = 0; i < mode->reg_data_size; ++i, ++regs) {
> +	for (i = 0; i < regnum; ++i, ++regs) {
>  		delay_ms = regs->delay_ms;
>  		reg_addr = regs->reg_addr;
>  		val = regs->val;
> @@ -1472,8 +1447,6 @@ static int ov5640_load_regs(struct ov5640_dev *sensor,
>  		if (delay_ms)
>  			usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
>  	}
> -
> -	return ov5640_set_timings(sensor, mode);
>  }
>  
>  static int ov5640_set_autoexposure(struct ov5640_dev *sensor, bool on)
> @@ -1926,7 +1899,8 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
>  		return ret;
>  
>  	/* Write capture setting */
> -	ret = ov5640_load_regs(sensor, mode);
> +	ov5640_load_regs(sensor, mode->reg_data, mode->reg_data_size);
> +	ret = ov5640_set_timings(sensor, mode);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -2050,7 +2024,8 @@ static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
>  		return -EINVAL;
>  
>  	/* Write capture setting */
> -	return ov5640_load_regs(sensor, mode);
> +	ov5640_load_regs(sensor, mode->reg_data, mode->reg_data_size);
> +	return ov5640_set_timings(sensor, mode);
>  }
>  
>  static int ov5640_set_mode(struct ov5640_dev *sensor)
> @@ -2148,10 +2123,8 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
>  	int ret;
>  
>  	/* first load the initial register values */
> -	ret = ov5640_load_regs(sensor, &ov5640_mode_init_data);
> -	if (ret < 0)
> -		return ret;
> -	sensor->last_mode = &ov5640_mode_init_data;
> +	ov5640_load_regs(sensor, ov5640_init_setting,
> +			 ARRAY_SIZE(ov5640_init_setting));
>  
>  	ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
>  			     (ilog2(OV5640_SCLK2X_ROOT_DIV) << 2) |

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 11/23] media: ov5640: Re-sort per-mode register tables
  2022-02-20 12:52   ` Laurent Pinchart
@ 2022-02-20 12:59     ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 12:59 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

On Sun, Feb 20, 2022 at 02:52:38PM +0200, Laurent Pinchart wrote:
> Hi Jacopo,
> 
> Thank you for the patch.
> 
> On Thu, Feb 10, 2022 at 12:04:46PM +0100, Jacopo Mondi wrote:
> > The per-mode register tables are not sorted by size. Fix it.
> > 
> > Cosmetic change only.
> > 
> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

By the way, now that must tables are identical, could we avoid
duplication ?

> > ---
> >  drivers/media/i2c/ov5640.c | 18 +++++++++---------
> >  1 file changed, 9 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > index 72b78201f089..17835e71665a 100644
> > --- a/drivers/media/i2c/ov5640.c
> > +++ b/drivers/media/i2c/ov5640.c
> > @@ -462,7 +462,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
> >  	{0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
> >  };
> >  
> > -static const struct reg_value ov5640_setting_VGA_640_480[] = {
> > +static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
> >  	{0x3c07, 0x08, 0, 0},
> >  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> >  	{0x3814, 0x31, 0, 0},
> > @@ -473,11 +473,10 @@ static const struct reg_value ov5640_setting_VGA_640_480[] = {
> >  	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> >  	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> >  	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
> > -	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> > -	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> > +	{0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
> >  };
> >  
> > -static const struct reg_value ov5640_setting_XGA_1024_768[] = {
> > +static const struct reg_value ov5640_setting_QCIF_176_144[] = {
> >  	{0x3c07, 0x08, 0, 0},
> >  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> >  	{0x3814, 0x31, 0, 0},
> > @@ -507,7 +506,7 @@ static const struct reg_value ov5640_setting_QVGA_320_240[] = {
> >  	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> >  };
> >  
> > -static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
> > +static const struct reg_value ov5640_setting_VGA_640_480[] = {
> >  	{0x3c07, 0x08, 0, 0},
> >  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> >  	{0x3814, 0x31, 0, 0},
> > @@ -518,10 +517,11 @@ static const struct reg_value ov5640_setting_QQVGA_160_120[] = {
> >  	{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
> >  	{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
> >  	{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
> > -	{0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
> > +	{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
> > +	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> >  };
> >  
> > -static const struct reg_value ov5640_setting_QCIF_176_144[] = {
> > +static const struct reg_value ov5640_setting_NTSC_720_480[] = {
> >  	{0x3c07, 0x08, 0, 0},
> >  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> >  	{0x3814, 0x31, 0, 0},
> > @@ -536,7 +536,7 @@ static const struct reg_value ov5640_setting_QCIF_176_144[] = {
> >  	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> >  };
> >  
> > -static const struct reg_value ov5640_setting_NTSC_720_480[] = {
> > +static const struct reg_value ov5640_setting_PAL_720_576[] = {
> >  	{0x3c07, 0x08, 0, 0},
> >  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> >  	{0x3814, 0x31, 0, 0},
> > @@ -551,7 +551,7 @@ static const struct reg_value ov5640_setting_NTSC_720_480[] = {
> >  	{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
> >  };
> >  
> > -static const struct reg_value ov5640_setting_PAL_720_576[] = {
> > +static const struct reg_value ov5640_setting_XGA_1024_768[] = {
> >  	{0x3c07, 0x08, 0, 0},
> >  	{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
> >  	{0x3814, 0x31, 0, 0},

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 14/23] media: ov5640: Add VBLANK control
  2022-02-10 11:09 ` [PATCH v2 14/23] media: ov5640: Add VBLANK control Jacopo Mondi
@ 2022-02-20 13:01   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 13:01 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: slongerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:09:59PM +0100, Jacopo Mondi wrote:
> Add the VBLANK control which allows to select the duration of the
> frame vertical blankings and allows to control the framerate.
> 
> The VBLANK control also modifies the exposure time range, which cannot
> exceed the maximum frame length.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/i2c/ov5640.c | 53 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index ade9adb43fda..30b706a98eb9 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -29,6 +29,12 @@
>  #define OV5640_XCLK_MIN  6000000
>  #define OV5640_XCLK_MAX 54000000
>  
> +#define OV5640_LINK_RATE_MAX	490000000U
> +
> +/* FIXME: not documented. */
> +#define OV5640_MIN_VBLANK	24
> +#define OV5640_MAX_VTS		1968
> +
>  #define OV5640_DEFAULT_SLAVE_ID 0x3c
>  
>  #define OV5640_LINK_RATE_MAX		490000000U
> @@ -301,6 +307,7 @@ struct ov5640_ctrls {
>  	struct v4l2_ctrl *pixel_rate;
>  	struct v4l2_ctrl *link_freq;
>  	struct v4l2_ctrl *hblank;
> +	struct v4l2_ctrl *vblank;
>  	struct {
>  		struct v4l2_ctrl *auto_exp;
>  		struct v4l2_ctrl *exposure;
> @@ -2553,6 +2560,7 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
>  	const struct ov5640_mode_info *mode = sensor->current_mode;
>  	struct v4l2_mbus_framefmt *fmt = &sensor->fmt;
>  	enum ov5640_pixel_rate_id pixel_rate_id = mode->pixel_rate;
> +	s64 exposure_val, exposure_max;
>  	unsigned int hblank;
>  	unsigned int i = 0;
>  	u32 pixel_rate;
> @@ -2610,6 +2618,20 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
>  	__v4l2_ctrl_modify_range(sensor->ctrls.hblank,
>  				 hblank, hblank, 1, hblank);
>  
> +	__v4l2_ctrl_modify_range(sensor->ctrls.vblank,
> +				 OV5640_MIN_VBLANK,
> +				 OV5640_MAX_VTS - mode->crop.height, 1,
> +				 mode->vblank_def);
> +	__v4l2_ctrl_s_ctrl(sensor->ctrls.vblank, mode->vblank_def);
> +
> +	exposure_max = mode->crop.height + mode->vblank_def - 4;
> +	exposure_val = clamp((s64)sensor->ctrls.exposure->val,
> +			     (s64)sensor->ctrls.exposure->minimum,
> +			     (s64)exposure_max);
> +	__v4l2_ctrl_modify_range(sensor->ctrls.exposure,
> +				 sensor->ctrls.exposure->minimum,
> +				 exposure_max, 1, exposure_val);
> +
>  	return 0;
>  }
>  
> @@ -2982,6 +3004,15 @@ static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
>  			      (BIT(2) | BIT(1)) : 0);
>  }
>  
> +static int ov5640_set_ctrl_vblank(struct ov5640_dev *sensor, int value)
> +{
> +	const struct ov5640_mode_info *mode = sensor->current_mode;
> +
> +	/* Update the VTOT timing register value. */
> +	return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS,
> +				  mode->crop.height + value);
> +}
> +
>  static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
>  {
>  	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
> @@ -3012,10 +3043,23 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
>  {
>  	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
>  	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +	const struct ov5640_mode_info *mode = sensor->current_mode;
> +	unsigned int exp_max;
>  	int ret;
>  
>  	/* v4l2_ctrl_lock() locks our own mutex */
>  
> +	switch (ctrl->id) {
> +	case V4L2_CID_VBLANK:
> +		/* Update the exposure range to the newly programmed vblank. */
> +		exp_max = mode->crop.height + ctrl->val - 4;
> +		__v4l2_ctrl_modify_range(sensor->ctrls.exposure,
> +					 sensor->ctrls.exposure->minimum,
> +					 exp_max, sensor->ctrls.exposure->step,
> +					 mode->vblank_def);
> +		break;
> +	}
> +
>  	/*
>  	 * If the device is not powered up by the host driver do
>  	 * not apply any controls to H/W at this time. Instead
> @@ -3055,6 +3099,9 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
>  	case V4L2_CID_VFLIP:
>  		ret = ov5640_set_ctrl_vflip(sensor, ctrl->val);
>  		break;
> +	case V4L2_CID_VBLANK:
> +		ret = ov5640_set_ctrl_vblank(sensor, ctrl->val);
> +		break;
>  	default:
>  		ret = -EINVAL;
>  		break;
> @@ -3074,6 +3121,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
>  	const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
>  	struct ov5640_ctrls *ctrls = &sensor->ctrls;
>  	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
> +	unsigned int max_vblank;
>  	unsigned int hblank;
>  	int ret;
>  
> @@ -3097,6 +3145,11 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
>  	ctrls->hblank = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HBLANK, hblank,
>  					  hblank, 1, hblank);
>  
> +	max_vblank = OV5640_MAX_VTS - mode->crop.height;
> +	ctrls->vblank = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VBLANK,
> +					  OV5640_MIN_VBLANK, max_vblank,
> +					  1, mode->vblank_def);
> +
>  	/* Auto/manual white balance */
>  	ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
>  					   V4L2_CID_AUTO_WHITE_BALANCE,

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 15/23] media: ov5640: Fix durations to comply with FPS
  2022-02-10 11:10 ` [PATCH v2 15/23] media: ov5640: Fix durations to comply with FPS Jacopo Mondi
@ 2022-02-20 13:03   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 13:03 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: slongerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:10:00PM +0100, Jacopo Mondi wrote:
> Now that the frame duration can be controlled by tuning the VBLANK
> duration, fix all modes to comply with the reported FPS.
> 
> All modes run at 30 FPS except for full-resolution mode 2592x1944
> which runs at 15FPS.
> 
> Tested on a 2 data lanes setup in UYVY and RGB565 modes.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>

I'll trust your calculations.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/i2c/ov5640.c | 30 +++++++++++++++---------------
>  1 file changed, 15 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 30b706a98eb9..dd7ff1bb580f 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -648,8 +648,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.width	= 160,
>  			.height	= 120,
>  		},
> -		.htot		= 1896,
> -		.vblank_def	= 864,
> +		.htot		= 1600,
> +		.vblank_def	= 878,
>  		.reg_data	= ov5640_setting_QQVGA_160_120,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
>  		.max_fps	= OV5640_30_FPS
> @@ -672,8 +672,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.width	= 176,
>  			.height	= 144,
>  		},
> -		.htot		= 1896,
> -		.vblank_def	= 840,
> +		.htot		= 1600,
> +		.vblank_def	= 854,
>  		.reg_data	= ov5640_setting_QCIF_176_144,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QCIF_176_144),
>  		.max_fps	= OV5640_30_FPS
> @@ -696,8 +696,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.width	= 320,
>  			.height	= 240,
>  		},
> -		.htot		= 1896,
> -		.vblank_def	= 744,
> +		.htot		= 1600,
> +		.vblank_def	= 760,
>  		.reg_data	= ov5640_setting_QVGA_320_240,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_QVGA_320_240),
>  		.max_fps	= OV5640_30_FPS
> @@ -720,8 +720,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.width	= 640,
>  			.height	= 480,
>  		},
> -		.htot		= 1896,
> -		.vblank_def	= 600,
> +		.htot		= 1600,
> +		.vblank_def	= 520,
>  		.reg_data	= ov5640_setting_VGA_640_480,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_VGA_640_480),
>  		.max_fps	= OV5640_60_FPS
> @@ -745,7 +745,7 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.height	= 480,
>  		},
>  		.htot		= 1896,
> -		.vblank_def	= 504,
> +		.vblank_def	= 1206,
>  		.reg_data	= ov5640_setting_NTSC_720_480,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_NTSC_720_480),
>  		.max_fps	= OV5640_30_FPS
> @@ -769,7 +769,7 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.height	= 576,
>  		},
>  		.htot		= 1896,
> -		.vblank_def	= 408,
> +		.vblank_def	= 1110,
>  		.reg_data	= ov5640_setting_PAL_720_576,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_PAL_720_576),
>  		.max_fps	= OV5640_30_FPS
> @@ -793,7 +793,7 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.height	= 768,
>  		},
>  		.htot		= 1896,
> -		.vblank_def	= 312,
> +		.vblank_def	= 918,
>  		.reg_data	= ov5640_setting_XGA_1024_768,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_XGA_1024_768),
>  		.max_fps	= OV5640_30_FPS
> @@ -816,8 +816,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.width	= 1280,
>  			.height	= 720,
>  		},
> -		.htot		= 1892,
> -		.vblank_def	= 20,
> +		.htot		= 1600,
> +		.vblank_def	= 560,
>  		.reg_data	= ov5640_setting_720P_1280_720,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_720P_1280_720),
>  		.max_fps	= OV5640_30_FPS
> @@ -840,8 +840,8 @@ static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] = {
>  			.width	= 1920,
>  			.height	= 1080,
>  		},
> -		.htot		= 2500,
> -		.vblank_def	= 40,
> +		.htot		= 2234,
> +		.vblank_def	= 24,
>  		.reg_data	= ov5640_setting_1080P_1920_1080,
>  		.reg_data_size	= ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
>  		.max_fps	= OV5640_30_FPS

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 17/23] media: ov5640: Implement get_selection
  2022-02-10 11:10 ` [PATCH v2 17/23] media: ov5640: Implement get_selection Jacopo Mondi
@ 2022-02-20 13:06   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 13:06 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: slongerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:10:02PM +0100, Jacopo Mondi wrote:
> Implement the get_selection pad operation for the OV5640 sensor driver.
> 
> The supported targets report the sensor's native size, the active pixel
> array size and the analog crop rectangle from which the image is
> produced.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/i2c/ov5640.c | 51 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 8b90fab26d16..4ebb76d95849 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -35,6 +35,13 @@
>  #define OV5640_MIN_VBLANK	24
>  #define OV5640_MAX_VTS		1968
>  
> +#define OV5640_NATIVE_WIDTH		2624
> +#define OV5640_NATIVE_HEIGHT		1964
> +#define OV5640_PIXEL_ARRAY_TOP		14
> +#define OV5640_PIXEL_ARRAY_LEFT		16
> +#define OV5640_PIXEL_ARRAY_WIDTH	2592
> +#define OV5640_PIXEL_ARRAY_HEIGHT	1944
> +
>  #define OV5640_DEFAULT_SLAVE_ID 0x3c
>  
>  #define OV5640_LINK_RATE_MAX		490000000U
> @@ -2693,6 +2700,43 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
>  	return ret;
>  }
>  
> +static int ov5640_get_selection(struct v4l2_subdev *sd,
> +				struct v4l2_subdev_state *sd_state,
> +				struct v4l2_subdev_selection *sel)
> +{
> +	struct ov5640_dev *sensor = to_ov5640_dev(sd);
> +	const struct ov5640_mode_info *mode = sensor->current_mode;
> +
> +	switch (sel->target) {
> +	case V4L2_SEL_TGT_CROP: {
> +		mutex_lock(&sensor->lock);
> +		sel->r = mode->analog_crop;
> +		mutex_unlock(&sensor->lock);
> +
> +		return 0;
> +	}
> +
> +	case V4L2_SEL_TGT_NATIVE_SIZE:
> +	case V4L2_SEL_TGT_CROP_BOUNDS:
> +		sel->r.top = 0;
> +		sel->r.left = 0;
> +		sel->r.width = OV5640_NATIVE_WIDTH;
> +		sel->r.height = OV5640_NATIVE_HEIGHT;
> +
> +		return 0;
> +
> +	case V4L2_SEL_TGT_CROP_DEFAULT:
> +		sel->r.top = OV5640_PIXEL_ARRAY_TOP;
> +		sel->r.left = OV5640_PIXEL_ARRAY_LEFT;
> +		sel->r.width = OV5640_PIXEL_ARRAY_WIDTH;
> +		sel->r.height = OV5640_PIXEL_ARRAY_HEIGHT;
> +
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
>  static int ov5640_set_framefmt(struct ov5640_dev *sensor,
>  			       struct v4l2_mbus_framefmt *format)
>  {
> @@ -3383,9 +3427,15 @@ static int ov5640_init_cfg(struct v4l2_subdev *sd,
>  			   struct v4l2_subdev_state *state)
>  {
>  	struct v4l2_mbus_framefmt *fmt = v4l2_subdev_get_try_format(sd, state, 0);
> +	struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, state, 0);
>  
>  	*fmt = ov5640_default_fmt;
>  
> +	crop->left = OV5640_PIXEL_ARRAY_LEFT;
> +	crop->top = OV5640_PIXEL_ARRAY_TOP;
> +	crop->width = OV5640_PIXEL_ARRAY_WIDTH;
> +	crop->height = OV5640_PIXEL_ARRAY_HEIGHT;
> +
>  	return 0;
>  }
>  
> @@ -3407,6 +3457,7 @@ static const struct v4l2_subdev_pad_ops ov5640_pad_ops = {
>  	.enum_mbus_code = ov5640_enum_mbus_code,
>  	.get_fmt = ov5640_get_fmt,
>  	.set_fmt = ov5640_set_fmt,
> +	.get_selection = ov5640_get_selection,
>  	.enum_frame_size = ov5640_enum_frame_size,
>  	.enum_frame_interval = ov5640_enum_frame_interval,
>  };

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 20/23] media: ov5640: Add RGB565_1X16 format
  2022-02-10 11:10 ` [PATCH v2 20/23] media: ov5640: Add RGB565_1X16 format Jacopo Mondi
@ 2022-02-20 13:07   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 13:07 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: slongerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:10:41PM +0100, Jacopo Mondi wrote:
> The driver already supports the 2X8_[LE|BE] variants of RGB565
> formats.
> 
> As for CSI-2 the 2X8 variants do not apply, add RGB565_1X16 variant
> with little-endian ordering of components as required by the CSI-2
> specifications.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  drivers/media/i2c/ov5640.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index aecc8912099a..3a21f4648acf 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -220,6 +220,10 @@ static const struct ov5640_pixfmt {
>  		.code = MEDIA_BUS_FMT_RGB565_2X8_BE,
>  		.colorspace = V4L2_COLORSPACE_SRGB,
>  		.bpp = 16,
> +	}, {
> +		.code = MEDIA_BUS_FMT_RGB565_1X16,
> +		.colorspace = V4L2_COLORSPACE_SRGB,
> +		.bpp = 16,

Should/could we limit this format to CSI-2 mode ?

>  	}, {
>  		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
>  		.colorspace = V4L2_COLORSPACE_SRGB,
> @@ -2763,6 +2767,7 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
>  		mux = OV5640_FMT_MUX_YUV422;
>  		break;
>  	case MEDIA_BUS_FMT_RGB565_2X8_LE:
> +	case MEDIA_BUS_FMT_RGB565_1X16:
>  		/* RGB565 {g[2:0],b[4:0]},{r[4:0],g[5:3]} */
>  		fmt = 0x6F;
>  		mux = OV5640_FMT_MUX_RGB;

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 21/23] media: ov5640: Add RGB888/BGR888 formats
  2022-02-10 11:10 ` [PATCH v2 21/23] media: ov5640: Add RGB888/BGR888 formats Jacopo Mondi
@ 2022-02-20 13:13   ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 13:13 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: slongerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:10:42PM +0100, Jacopo Mondi wrote:
> Add support for RGB888/BGR888 image formats.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  drivers/media/i2c/ov5640.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index 3a21f4648acf..f894570ac53c 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -224,6 +224,14 @@ static const struct ov5640_pixfmt {
>  		.code = MEDIA_BUS_FMT_RGB565_1X16,
>  		.colorspace = V4L2_COLORSPACE_SRGB,
>  		.bpp = 16,
> +	}, {
> +		.code = MEDIA_BUS_FMT_RGB888_1X24,
> +		.colorspace = V4L2_COLORSPACE_SRGB,
> +		.bpp = 24,
> +	}, {
> +		.code = MEDIA_BUS_FMT_BGR888_1X24,
> +		.colorspace = V4L2_COLORSPACE_SRGB,
> +		.bpp = 16,

bpp = 24

If we can limit MEDIA_BUS_FMT_RGB565_1X16 to CSI-2 mode in the previous
patch, then this should be limited too.

>  	}, {
>  		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
>  		.colorspace = V4L2_COLORSPACE_SRGB,
> @@ -2777,6 +2785,16 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
>  		fmt = 0x61;
>  		mux = OV5640_FMT_MUX_RGB;
>  		break;
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +		/* RGB888: BGR */

The datasheet documents formats 0x22 and 0x23 as BGRBGR... and RGBRGB...
but doesn't tell how that's mapped to the MIPI CSI-2 RGB888 formats
(which is transmitted with the blue bits first). I thus can't tell which
order is correct here. We can fix it later if it turns out not to be
correct.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +		fmt = 0x22;
> +		mux = OV5640_FMT_MUX_RGB;
> +		break;
> +	case MEDIA_BUS_FMT_BGR888_1X24:
> +		/* BGR888: RGB */
> +		fmt = 0x23;
> +		mux = OV5640_FMT_MUX_RGB;
> +		break;
>  	case MEDIA_BUS_FMT_JPEG_1X8:
>  		/* YUV422, YUYV */
>  		fmt = 0x30;

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 22/23] media: ov5640: Restrict sizes to mbus code
  2022-02-10 11:10 ` [PATCH v2 22/23] media: ov5640: Restrict sizes to mbus code Jacopo Mondi
@ 2022-02-20 13:16   ` Laurent Pinchart
  2022-02-21 12:42     ` Jacopo Mondi
  0 siblings, 1 reply; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-20 13:16 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: slongerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media

Hi Jacopo,

Thank you for the patch.

On Thu, Feb 10, 2022 at 12:10:43PM +0100, Jacopo Mondi wrote:
> The ov5640 driver supports different sizes for different mbus_codes.
> In particular:
> 
> - 8bpp modes: high resolution sizes (>= 1280x720)
> - 16bpp modes: all sizes
> - 24bpp modes: low resolutions sizes (< 1280x720)
> 
> Restrict the frame sizes enumerations to the above constraints.
> 
> While at it, make sure the fse->mbus_code parameter is valid, and return
> -EINVAL if it's not.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  drivers/media/i2c/ov5640.c | 20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> index f894570ac53c..81bf547a923e 100644
> --- a/drivers/media/i2c/ov5640.c
> +++ b/drivers/media/i2c/ov5640.c
> @@ -3315,14 +3315,28 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
>  				  struct v4l2_subdev_state *sd_state,
>  				  struct v4l2_subdev_frame_size_enum *fse)
>  {
> +	u32 bpp = ov5640_code_to_bpp(fse->code);
> +	unsigned int index = fse->index;
> +
>  	if (fse->pad != 0)
>  		return -EINVAL;
> -	if (fse->index >= OV5640_NUM_MODES)
> +	if (!bpp)
> +		return -EINVAL;
> +
> +	/* Only low-resolution modes are supported for 24bpp modes. */

s/24bpp modes/24bpp formats/


Do you think this is a limitation of the sensor, or an issue in the
driver ? In the latter case, I'd write

	/* FIXME: High resolution modes don't work in 24bpp formats. */

> +	if (bpp == 24 && index >= OV5640_MODE_720P_1280_720)
> +		return -EINVAL;
> +
> +	/* Only high-resolutions modes are supported for 8bpp formats. */

And here

	/* FIXME: Low resolution modes don't work in 8bpp formats. */

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +	if (bpp == 8)
> +		index += OV5640_MODE_720P_1280_720;
> +
> +	if (index >= OV5640_NUM_MODES)
>  		return -EINVAL;
>  
> -	fse->min_width = ov5640_mode_data[fse->index].crop.width;
> +	fse->min_width = ov5640_mode_data[index].crop.width;
>  	fse->max_width = fse->min_width;
> -	fse->min_height = ov5640_mode_data[fse->index].crop.height;
> +	fse->min_height = ov5640_mode_data[index].crop.height;
>  	fse->max_height = fse->min_height;
>  
>  	return 0;

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-17 14:25             ` Eugen.Hristev
@ 2022-02-21  8:51               ` Jacopo Mondi
  2022-02-21  9:04                 ` Eugen.Hristev
  0 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-21  8:51 UTC (permalink / raw)
  To: Eugen.Hristev
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

Hi Eugen

On Thu, Feb 17, 2022 at 02:25:37PM +0000, Eugen.Hristev@microchip.com wrote:
> On 2/14/22 8:56 PM, Jacopo Mondi wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >
> > Hi Eugen
> >
> > On Mon, Feb 14, 2022 at 03:08:56PM +0000, Eugen.Hristev@microchip.com wrote:
> >> On 2/14/22 4:38 PM, Jacopo Mondi wrote:
> >>> Hi Eugen,
> >>>
> >>> On Mon, Feb 14, 2022 at 02:06:02PM +0000, Eugen.Hristev@microchip.com wrote:
> >>>> On 2/11/22 1:25 PM, Jacopo Mondi wrote:
> >>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >>>>>
> >>>>> Hi Eugen
> >>>>>
> >>>>>            thanks very much for testing
> >>>>>
> >>>>> On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
> >>>>>> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
> >>>>>>
> >>>>>> Hello Jacopo,
> >>>>>>
> >>>>>>> v1:
> >>>>>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
> >>>>>>>
> >>>>>>> A branch for testing based on the most recent media-master is available at
> >>>>>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> >>>>>>>
> >>>>>>> If anyone with a DVP setup could verify I have not broken their use case
> >>>>>>> I would very much appreciate that :)
> >>>>>>
> >>>>>> I started testing this on my bench.
> >>>>>> So far things look good.
> >>>>>>
> >>>>>
> >>>>> \o/
> >>>>>
> >>>>>> To be able to test this, I have to revert this patch :
> >>>>>> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
> >>>>>>
> >>>>>> Otherwise the sensor will not power up when starting streaming.
> >>>>>>
> >>>>>>
> >>>>>> I have tested several formats, as you worked more on this sensor, could
> >>>>>> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
> >>>>>> 1024x768 ?
> >>>>>
> >>>>> I never tested the sensor driver with a parallel setup I'm afraid.
> >>>>> The idea behind this series is that DVP shouldn't be affected and
> >>>>> continue working like it did.
> >>>>
> >>>> Hi Jacopo,
> >>>>
> >>>> I was hoping that you had more information about the driver than myself.
> >>>
> >>> Not on DVP mode I'm sorry :(
> >>>
> >>>> I can tell that the parallel mode is not affected by your series from
> >>>> what I've seen so far.
> >>>
> >>> That's great, thanks for testing.
> >>
> >>
> >> I found one change, before your series, I could attempt to capture BGGR
> >> @ 640x480, now it looks to be gone :
> >>
> >> Before:
> >>
> >> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
> >> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>           Size Range: 160x120 - 160x120
> >>           Size Range: 176x144 - 176x144
> >>           Size Range: 320x240 - 320x240
> >>           Size Range: 640x480 - 640x480
> >>           Size Range: 720x480 - 720x480
> >>           Size Range: 720x576 - 720x576
> >>           Size Range: 1024x768 - 1024x768
> >>           Size Range: 1280x720 - 1280x720
> >>           Size Range: 1920x1080 - 1920x1080
> >>           Size Range: 2592x1944 - 2592x1944
> >>
> >>
> >> After:
> >>
> >> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
> >> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>           Size Range: 1280x720 - 1280x720
> >>           Size Range: 1920x1080 - 1920x1080
> >>           Size Range: 2592x1944 - 2592x1944
> >>
> >
> > Right... I'm limiting SRGGB formats to only resolutions > 1280x720
> > as..
> >
> >>
> >> However trying it without your patches, it doesn't work , I don't
> >
> > ... they do not work for me either.
> >
> > So if they were not working before, maybe it's right not to enumerate
> > them ?
> >
> >> receive frames, and I can't even set 1280x720 at all, I get -EINVAL
> >
> > Be aware that DVP mode prevents you from setting a format if the
> > currently selected framerate is said to be "not supported" for that
> > format
> >
> >>
> >> So I assume you have been reworking the frame sizes.
> >>
> >> With your series, I have tested RGGB at 1280x720 , 1920x1080 .
> >> I also tested YUYV at 640x480 and RGB565_LE at 640x480.
> >>
> >> I can't go higher with the YUYV/RGB565, I don't receive frames anymore.
> >
> > Ah, I wonder if
> > 07b49ac59fd9 media: ov5640: Fix durations to comply with FPS
> > 82aebf4b7314 media: ov5640: Rework analog crop rectangles
> >
> > Might have impacted DVP...
> >
> > Should I keep separate fields for MIPI mode and leave the totals for
> > DVP untouched ?
>
> Hi Jacopo,
>
> I tested again without your series, and I can capture YUYV directly
> @1280x720 , which does not work anymore with your patches.
>
> The image has some bad pixels in it, but still, capture is pretty good.
> I am not sure whether it's a timing problem on capturing pixels, I
> uploaded it here so you can have a look :
>
> https://ibb.co/Yt8c0dJ
>

This is without my series ? Or with it applied ? Sorry for the dumb
question :)

> Eugen
>
> >
> > Thanks again for your very useful testing
> >
> >
> >> I can't go higher with the bayer to 2592x1944 . But this did not work
> >> before your patches either.
> >>>
> >>>>
> >>>>>
> >>>>>> I managed to get it working fine at 640x480 .
> >>>>>>
> >>>>>> The sensor looks to report valid framesizes for this mbus code :
> >>>>>>
> >>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
> >>>>>> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
> >>>>>>             0x4001: MEDIA_BUS_FMT_JPEG_1X8
> >>>>>>             0x2006: MEDIA_BUS_FMT_UYVY8_2X8
> >>>>>>             0x200f: MEDIA_BUS_FMT_UYVY8_1X16
> >>>>>>             0x2008: MEDIA_BUS_FMT_YUYV8_2X8
> >>>>>>             0x2011: MEDIA_BUS_FMT_YUYV8_1X16
> >>>>>>             0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
> >>>>>>             0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
> >>>>>>             0x1017: MEDIA_BUS_FMT_RGB565_1X16
> >>>>>>             0x100a: MEDIA_BUS_FMT_RGB888_1X24
> >>>>>>             0x1013: MEDIA_BUS_FMT_BGR888_1X24
> >>>>>>             0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
> >>>>>>             0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
> >>>>>>             0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
> >>>>>>             0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
> >>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
> >>>>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>>>>>             Size Range: 160x120 - 160x120
> >>>>>>             Size Range: 176x144 - 176x144
> >>>>>>             Size Range: 320x240 - 320x240
> >>>>>>             Size Range: 640x480 - 640x480
> >>>>>>             Size Range: 720x480 - 720x480
> >>>>>>             Size Range: 720x576 - 720x576
> >>>>>>             Size Range: 1024x768 - 1024x768
> >>>>>>             Size Range: 1280x720 - 1280x720
> >>>>>>             Size Range: 1920x1080 - 1920x1080
> >>>>>>             Size Range: 2592x1944 - 2592x1944
> >>>>>> #
> >>>>>>
> >>>>>> but the ISC does not receive any frames at 1024x768 and 1920x1080.
> >>>>>
> >>>>> Are 1080p and 1024x768 working without this series applied on your
> >>>>> setup ?
> >>>>
> >>>> I remember they weren't working before either.
> >>>>
> >>>> I don't know exactly to which patches to add my Tested-by , as I have
> >>>> not tested the explicit patch behavior for each patch (e.g. where you
> >>>> add HBLANK control, I have not tested that ).
> >>>>
> >>>
> >>> I think it's good enough making sure I have not broke DVP.
> >>>
> >>> As you can see the driver now behaves in two different ways in DVP and
> >>> MIPI mode. The DVP works as it used to, and the framerate is
> >>> controlled by s_frame_interval, the frame size is fixed and the PCLK
> >>> is computed dyanically to accomodate the required FPS. In MIPI mode the
> >>> framerate is controlled by changing the vertical blankings. To each
> >>> mode a pixel rate is assigned and userspace changes the frame duration
> >>> by changing blankings. The most obvious gain is that the frame rate is
> >>> controllable in a continuous interval instead of being limited to a
> >>> few fixed values. It is my understanding that all drivers should be
> >>> moved to this model and s_frame_intervall should be dropped, but
> >>> unfortunately some bridge drivers in mainline still deman that.
> >>>
> >>> If you are interested, I think the DVP mode should be moved to use the
> >>> same mecahnism as MIPI mode. I can't test so I haven't done so in this
> >>> series.
> >>>
> >>> For now I think it's enough to make sure there are no regressions in
> >>> DVP mode.
> >>>
> >>> For the tag, I think it would be appropriate to add it to the
> >>> following one:
> >>>
> >>> 91ae667b0d47 media: ov5640: Limit frame_interval to DVP mode only
> >>>
> >>>> Is there something particular you would like me to try , except my usual
> >>>> image captures ?
> >>>
> >>> RGB888 is weird on both the platforms I've tested on and I cannot get
> >>> colors right. Does your platform support RGB888 ?
> >>
> >> I can't test this one unfortunately. It's a 1X24 . I have only 8 bits
> >> connected, so unless you can make this a 3x8 , there isn't anything I
> >> can do.
> >>
> >>>
> >>> Thanks
> >>>     j
> >>>
> >>>
> >>>>
> >>>>
> >>>> Eugen
> >>>>
> >>>>>
> >>>>> Thanks again for testin!
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>> What I can say is that the raw bayer format works at 1920x1080 , frames
> >>>>>> are received correctly.
> >>>>>>
> >>>>>> Thanks,
> >>>>>> Eugen
> >>>>>>
> >>>>>>>
> >>>>>>> v1 -> v2:
> >>>>>>> - rework the modes definition to process the full pixel array
> >>>>>>> - rework get_selection to report the correct BOUND and DEFAULT targets
> >>>>>>> - implement init_cfg
> >>>>>>> - minor style changes as suggested by Laurent
> >>>>>>> - test with 1 data lane
> >>>>>>>
> >>>>>>> Thanks
> >>>>>>>        j
> >>>>>>>
> >>>>>>> Jacopo Mondi (23):
> >>>>>>>       media: ov5640: Add pixel rate to modes
> >>>>>>>       media: ov5604: Re-arrange modes definition
> >>>>>>>       media: ov5640: Add ov5640_is_csi2() function
> >>>>>>>       media: ov5640: Associate bpp with formats
> >>>>>>>       media: ov5640: Add LINK_FREQ control
> >>>>>>>       media: ov5640: Update pixel_rate and link_freq
> >>>>>>>       media: ov5640: Rework CSI-2 clock tree
> >>>>>>>       media: ov5640: Rework timings programming
> >>>>>>>       media: ov5640: Fix 720x480 in RGB888 mode
> >>>>>>>       media: ov5640: Rework analog crop rectangles
> >>>>>>>       media: ov5640: Re-sort per-mode register tables
> >>>>>>>       media: ov5640: Remove ov5640_mode_init_data
> >>>>>>>       media: ov5640: Add HBLANK control
> >>>>>>>       media: ov5640: Add VBLANK control
> >>>>>>>       media: ov5640: Fix durations to comply with FPS
> >>>>>>>       media: ov5640: Implement init_cfg
> >>>>>>>       media: ov5640: Implement get_selection
> >>>>>>>       media: ov5640: Limit frame_interval to DVP mode only
> >>>>>>>       media: ov5640: Register device properties
> >>>>>>>       media: ov5640: Add RGB565_1X16 format
> >>>>>>>       media: ov5640: Add RGB888/BGR888 formats
> >>>>>>>       media: ov5640: Restrict sizes to mbus code
> >>>>>>>       media: ov5640: Adjust format to bpp in s_fmt
> >>>>>>>
> >>>>>>>      drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
> >>>>>>>      1 file changed, 830 insertions(+), 313 deletions(-)
> >>>>>>>
> >>>>>>> --
> >>>>>>> 2.35.0
> >>>>>>>
> >>>>>>
> >>>>
> >>
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-21  8:51               ` Jacopo Mondi
@ 2022-02-21  9:04                 ` Eugen.Hristev
  2022-02-21 11:18                   ` Jacopo Mondi
  2022-02-21 13:31                   ` Jacopo Mondi
  0 siblings, 2 replies; 64+ messages in thread
From: Eugen.Hristev @ 2022-02-21  9:04 UTC (permalink / raw)
  To: jacopo
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

On 2/21/22 10:51 AM, Jacopo Mondi wrote:
> Hi Eugen
> 
> On Thu, Feb 17, 2022 at 02:25:37PM +0000, Eugen.Hristev@microchip.com wrote:
>> On 2/14/22 8:56 PM, Jacopo Mondi wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Hi Eugen
>>>
>>> On Mon, Feb 14, 2022 at 03:08:56PM +0000, Eugen.Hristev@microchip.com wrote:
>>>> On 2/14/22 4:38 PM, Jacopo Mondi wrote:
>>>>> Hi Eugen,
>>>>>
>>>>> On Mon, Feb 14, 2022 at 02:06:02PM +0000, Eugen.Hristev@microchip.com wrote:
>>>>>> On 2/11/22 1:25 PM, Jacopo Mondi wrote:
>>>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>>>>
>>>>>>> Hi Eugen
>>>>>>>
>>>>>>>             thanks very much for testing
>>>>>>>
>>>>>>> On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
>>>>>>>> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
>>>>>>>>
>>>>>>>> Hello Jacopo,
>>>>>>>>
>>>>>>>>> v1:
>>>>>>>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
>>>>>>>>>
>>>>>>>>> A branch for testing based on the most recent media-master is available at
>>>>>>>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
>>>>>>>>>
>>>>>>>>> If anyone with a DVP setup could verify I have not broken their use case
>>>>>>>>> I would very much appreciate that :)
>>>>>>>>
>>>>>>>> I started testing this on my bench.
>>>>>>>> So far things look good.
>>>>>>>>
>>>>>>>
>>>>>>> \o/
>>>>>>>
>>>>>>>> To be able to test this, I have to revert this patch :
>>>>>>>> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
>>>>>>>>
>>>>>>>> Otherwise the sensor will not power up when starting streaming.
>>>>>>>>
>>>>>>>>
>>>>>>>> I have tested several formats, as you worked more on this sensor, could
>>>>>>>> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
>>>>>>>> 1024x768 ?
>>>>>>>
>>>>>>> I never tested the sensor driver with a parallel setup I'm afraid.
>>>>>>> The idea behind this series is that DVP shouldn't be affected and
>>>>>>> continue working like it did.
>>>>>>
>>>>>> Hi Jacopo,
>>>>>>
>>>>>> I was hoping that you had more information about the driver than myself.
>>>>>
>>>>> Not on DVP mode I'm sorry :(
>>>>>
>>>>>> I can tell that the parallel mode is not affected by your series from
>>>>>> what I've seen so far.
>>>>>
>>>>> That's great, thanks for testing.
>>>>
>>>>
>>>> I found one change, before your series, I could attempt to capture BGGR
>>>> @ 640x480, now it looks to be gone :
>>>>
>>>> Before:
>>>>
>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
>>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>>>>            Size Range: 160x120 - 160x120
>>>>            Size Range: 176x144 - 176x144
>>>>            Size Range: 320x240 - 320x240
>>>>            Size Range: 640x480 - 640x480
>>>>            Size Range: 720x480 - 720x480
>>>>            Size Range: 720x576 - 720x576
>>>>            Size Range: 1024x768 - 1024x768
>>>>            Size Range: 1280x720 - 1280x720
>>>>            Size Range: 1920x1080 - 1920x1080
>>>>            Size Range: 2592x1944 - 2592x1944
>>>>
>>>>
>>>> After:
>>>>
>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
>>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>>>>            Size Range: 1280x720 - 1280x720
>>>>            Size Range: 1920x1080 - 1920x1080
>>>>            Size Range: 2592x1944 - 2592x1944
>>>>
>>>
>>> Right... I'm limiting SRGGB formats to only resolutions > 1280x720
>>> as..
>>>
>>>>
>>>> However trying it without your patches, it doesn't work , I don't
>>>
>>> ... they do not work for me either.
>>>
>>> So if they were not working before, maybe it's right not to enumerate
>>> them ?
>>>
>>>> receive frames, and I can't even set 1280x720 at all, I get -EINVAL
>>>
>>> Be aware that DVP mode prevents you from setting a format if the
>>> currently selected framerate is said to be "not supported" for that
>>> format
>>>
>>>>
>>>> So I assume you have been reworking the frame sizes.
>>>>
>>>> With your series, I have tested RGGB at 1280x720 , 1920x1080 .
>>>> I also tested YUYV at 640x480 and RGB565_LE at 640x480.
>>>>
>>>> I can't go higher with the YUYV/RGB565, I don't receive frames anymore.
>>>
>>> Ah, I wonder if
>>> 07b49ac59fd9 media: ov5640: Fix durations to comply with FPS
>>> 82aebf4b7314 media: ov5640: Rework analog crop rectangles
>>>
>>> Might have impacted DVP...
>>>
>>> Should I keep separate fields for MIPI mode and leave the totals for
>>> DVP untouched ?
>>
>> Hi Jacopo,
>>
>> I tested again without your series, and I can capture YUYV directly
>> @1280x720 , which does not work anymore with your patches.
>>
>> The image has some bad pixels in it, but still, capture is pretty good.
>> I am not sure whether it's a timing problem on capturing pixels, I
>> uploaded it here so you can have a look :
>>
>> https://ibb.co/Yt8c0dJ
>>
> 
> This is without my series ? Or with it applied ? Sorry for the dumb
> question :)

This photo is *without* your series. *With* your series, I cannot 
capture YUYV at this resolution at all. No frames received.

> 
>> Eugen
>>
>>>
>>> Thanks again for your very useful testing
>>>
>>>
>>>> I can't go higher with the bayer to 2592x1944 . But this did not work
>>>> before your patches either.
>>>>>
>>>>>>
>>>>>>>
>>>>>>>> I managed to get it working fine at 640x480 .
>>>>>>>>
>>>>>>>> The sensor looks to report valid framesizes for this mbus code :
>>>>>>>>
>>>>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
>>>>>>>> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
>>>>>>>>              0x4001: MEDIA_BUS_FMT_JPEG_1X8
>>>>>>>>              0x2006: MEDIA_BUS_FMT_UYVY8_2X8
>>>>>>>>              0x200f: MEDIA_BUS_FMT_UYVY8_1X16
>>>>>>>>              0x2008: MEDIA_BUS_FMT_YUYV8_2X8
>>>>>>>>              0x2011: MEDIA_BUS_FMT_YUYV8_1X16
>>>>>>>>              0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
>>>>>>>>              0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
>>>>>>>>              0x1017: MEDIA_BUS_FMT_RGB565_1X16
>>>>>>>>              0x100a: MEDIA_BUS_FMT_RGB888_1X24
>>>>>>>>              0x1013: MEDIA_BUS_FMT_BGR888_1X24
>>>>>>>>              0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
>>>>>>>>              0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
>>>>>>>>              0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
>>>>>>>>              0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
>>>>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
>>>>>>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
>>>>>>>>              Size Range: 160x120 - 160x120
>>>>>>>>              Size Range: 176x144 - 176x144
>>>>>>>>              Size Range: 320x240 - 320x240
>>>>>>>>              Size Range: 640x480 - 640x480
>>>>>>>>              Size Range: 720x480 - 720x480
>>>>>>>>              Size Range: 720x576 - 720x576
>>>>>>>>              Size Range: 1024x768 - 1024x768
>>>>>>>>              Size Range: 1280x720 - 1280x720
>>>>>>>>              Size Range: 1920x1080 - 1920x1080
>>>>>>>>              Size Range: 2592x1944 - 2592x1944
>>>>>>>> #
>>>>>>>>
>>>>>>>> but the ISC does not receive any frames at 1024x768 and 1920x1080.
>>>>>>>
>>>>>>> Are 1080p and 1024x768 working without this series applied on your
>>>>>>> setup ?
>>>>>>
>>>>>> I remember they weren't working before either.
>>>>>>
>>>>>> I don't know exactly to which patches to add my Tested-by , as I have
>>>>>> not tested the explicit patch behavior for each patch (e.g. where you
>>>>>> add HBLANK control, I have not tested that ).
>>>>>>
>>>>>
>>>>> I think it's good enough making sure I have not broke DVP.
>>>>>
>>>>> As you can see the driver now behaves in two different ways in DVP and
>>>>> MIPI mode. The DVP works as it used to, and the framerate is
>>>>> controlled by s_frame_interval, the frame size is fixed and the PCLK
>>>>> is computed dyanically to accomodate the required FPS. In MIPI mode the
>>>>> framerate is controlled by changing the vertical blankings. To each
>>>>> mode a pixel rate is assigned and userspace changes the frame duration
>>>>> by changing blankings. The most obvious gain is that the frame rate is
>>>>> controllable in a continuous interval instead of being limited to a
>>>>> few fixed values. It is my understanding that all drivers should be
>>>>> moved to this model and s_frame_intervall should be dropped, but
>>>>> unfortunately some bridge drivers in mainline still deman that.
>>>>>
>>>>> If you are interested, I think the DVP mode should be moved to use the
>>>>> same mecahnism as MIPI mode. I can't test so I haven't done so in this
>>>>> series.
>>>>>
>>>>> For now I think it's enough to make sure there are no regressions in
>>>>> DVP mode.
>>>>>
>>>>> For the tag, I think it would be appropriate to add it to the
>>>>> following one:
>>>>>
>>>>> 91ae667b0d47 media: ov5640: Limit frame_interval to DVP mode only
>>>>>
>>>>>> Is there something particular you would like me to try , except my usual
>>>>>> image captures ?
>>>>>
>>>>> RGB888 is weird on both the platforms I've tested on and I cannot get
>>>>> colors right. Does your platform support RGB888 ?
>>>>
>>>> I can't test this one unfortunately. It's a 1X24 . I have only 8 bits
>>>> connected, so unless you can make this a 3x8 , there isn't anything I
>>>> can do.
>>>>
>>>>>
>>>>> Thanks
>>>>>      j
>>>>>
>>>>>
>>>>>>
>>>>>>
>>>>>> Eugen
>>>>>>
>>>>>>>
>>>>>>> Thanks again for testin!
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> What I can say is that the raw bayer format works at 1920x1080 , frames
>>>>>>>> are received correctly.
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Eugen
>>>>>>>>
>>>>>>>>>
>>>>>>>>> v1 -> v2:
>>>>>>>>> - rework the modes definition to process the full pixel array
>>>>>>>>> - rework get_selection to report the correct BOUND and DEFAULT targets
>>>>>>>>> - implement init_cfg
>>>>>>>>> - minor style changes as suggested by Laurent
>>>>>>>>> - test with 1 data lane
>>>>>>>>>
>>>>>>>>> Thanks
>>>>>>>>>         j
>>>>>>>>>
>>>>>>>>> Jacopo Mondi (23):
>>>>>>>>>        media: ov5640: Add pixel rate to modes
>>>>>>>>>        media: ov5604: Re-arrange modes definition
>>>>>>>>>        media: ov5640: Add ov5640_is_csi2() function
>>>>>>>>>        media: ov5640: Associate bpp with formats
>>>>>>>>>        media: ov5640: Add LINK_FREQ control
>>>>>>>>>        media: ov5640: Update pixel_rate and link_freq
>>>>>>>>>        media: ov5640: Rework CSI-2 clock tree
>>>>>>>>>        media: ov5640: Rework timings programming
>>>>>>>>>        media: ov5640: Fix 720x480 in RGB888 mode
>>>>>>>>>        media: ov5640: Rework analog crop rectangles
>>>>>>>>>        media: ov5640: Re-sort per-mode register tables
>>>>>>>>>        media: ov5640: Remove ov5640_mode_init_data
>>>>>>>>>        media: ov5640: Add HBLANK control
>>>>>>>>>        media: ov5640: Add VBLANK control
>>>>>>>>>        media: ov5640: Fix durations to comply with FPS
>>>>>>>>>        media: ov5640: Implement init_cfg
>>>>>>>>>        media: ov5640: Implement get_selection
>>>>>>>>>        media: ov5640: Limit frame_interval to DVP mode only
>>>>>>>>>        media: ov5640: Register device properties
>>>>>>>>>        media: ov5640: Add RGB565_1X16 format
>>>>>>>>>        media: ov5640: Add RGB888/BGR888 formats
>>>>>>>>>        media: ov5640: Restrict sizes to mbus code
>>>>>>>>>        media: ov5640: Adjust format to bpp in s_fmt
>>>>>>>>>
>>>>>>>>>       drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
>>>>>>>>>       1 file changed, 830 insertions(+), 313 deletions(-)
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> 2.35.0
>>>>>>>>>
>>>>>>>>
>>>>>>
>>>>
>>


^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-21  9:04                 ` Eugen.Hristev
@ 2022-02-21 11:18                   ` Jacopo Mondi
  2022-02-21 13:31                   ` Jacopo Mondi
  1 sibling, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-21 11:18 UTC (permalink / raw)
  To: Eugen.Hristev
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

Hi Eugen

On Mon, Feb 21, 2022 at 09:04:39AM +0000, Eugen.Hristev@microchip.com wrote:
> On 2/21/22 10:51 AM, Jacopo Mondi wrote:
> > Hi Eugen
> >
> > On Thu, Feb 17, 2022 at 02:25:37PM +0000, Eugen.Hristev@microchip.com wrote:
> >> On 2/14/22 8:56 PM, Jacopo Mondi wrote:
> >>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >>>
> >>> Hi Eugen
> >>>
> >>> On Mon, Feb 14, 2022 at 03:08:56PM +0000, Eugen.Hristev@microchip.com wrote:
> >>>> On 2/14/22 4:38 PM, Jacopo Mondi wrote:
> >>>>> Hi Eugen,
> >>>>>
> >>>>> On Mon, Feb 14, 2022 at 02:06:02PM +0000, Eugen.Hristev@microchip.com wrote:
> >>>>>> On 2/11/22 1:25 PM, Jacopo Mondi wrote:
> >>>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >>>>>>>
> >>>>>>> Hi Eugen
> >>>>>>>
> >>>>>>>             thanks very much for testing
> >>>>>>>
> >>>>>>> On Fri, Feb 11, 2022 at 10:09:04AM +0000, Eugen.Hristev@microchip.com wrote:
> >>>>>>>> On 2/10/22 1:04 PM, Jacopo Mondi wrote:
> >>>>>>>>
> >>>>>>>> Hello Jacopo,
> >>>>>>>>
> >>>>>>>>> v1:
> >>>>>>>>> https://patchwork.linuxtv.org/project/linux-media/list/?series=7249
> >>>>>>>>>
> >>>>>>>>> A branch for testing based on the most recent media-master is available at
> >>>>>>>>> https://git.sr.ht/~jmondi_/linux #jmondi/media-master/ov5640-v2
> >>>>>>>>>
> >>>>>>>>> If anyone with a DVP setup could verify I have not broken their use case
> >>>>>>>>> I would very much appreciate that :)
> >>>>>>>>
> >>>>>>>> I started testing this on my bench.
> >>>>>>>> So far things look good.
> >>>>>>>>
> >>>>>>>
> >>>>>>> \o/
> >>>>>>>
> >>>>>>>> To be able to test this, I have to revert this patch :
> >>>>>>>> "media: i2c: ov5640: Remain in power down for DVP mode unless streaming"
> >>>>>>>>
> >>>>>>>> Otherwise the sensor will not power up when starting streaming.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> I have tested several formats, as you worked more on this sensor, could
> >>>>>>>> you tell me, does format YUYV_2x8 work in parallel mode at 1920x1080 or
> >>>>>>>> 1024x768 ?
> >>>>>>>
> >>>>>>> I never tested the sensor driver with a parallel setup I'm afraid.
> >>>>>>> The idea behind this series is that DVP shouldn't be affected and
> >>>>>>> continue working like it did.
> >>>>>>
> >>>>>> Hi Jacopo,
> >>>>>>
> >>>>>> I was hoping that you had more information about the driver than myself.
> >>>>>
> >>>>> Not on DVP mode I'm sorry :(
> >>>>>
> >>>>>> I can tell that the parallel mode is not affected by your series from
> >>>>>> what I've seen so far.
> >>>>>
> >>>>> That's great, thanks for testing.
> >>>>
> >>>>
> >>>> I found one change, before your series, I could attempt to capture BGGR
> >>>> @ 640x480, now it looks to be gone :
> >>>>
> >>>> Before:
> >>>>
> >>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
> >>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>>>            Size Range: 160x120 - 160x120
> >>>>            Size Range: 176x144 - 176x144
> >>>>            Size Range: 320x240 - 320x240
> >>>>            Size Range: 640x480 - 640x480
> >>>>            Size Range: 720x480 - 720x480
> >>>>            Size Range: 720x576 - 720x576
> >>>>            Size Range: 1024x768 - 1024x768
> >>>>            Size Range: 1280x720 - 1280x720
> >>>>            Size Range: 1920x1080 - 1920x1080
> >>>>            Size Range: 2592x1944 - 2592x1944
> >>>>
> >>>>
> >>>> After:
> >>>>
> >>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x3001
> >>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>>>            Size Range: 1280x720 - 1280x720
> >>>>            Size Range: 1920x1080 - 1920x1080
> >>>>            Size Range: 2592x1944 - 2592x1944
> >>>>
> >>>
> >>> Right... I'm limiting SRGGB formats to only resolutions > 1280x720
> >>> as..
> >>>
> >>>>
> >>>> However trying it without your patches, it doesn't work , I don't
> >>>
> >>> ... they do not work for me either.
> >>>
> >>> So if they were not working before, maybe it's right not to enumerate
> >>> them ?
> >>>
> >>>> receive frames, and I can't even set 1280x720 at all, I get -EINVAL
> >>>
> >>> Be aware that DVP mode prevents you from setting a format if the
> >>> currently selected framerate is said to be "not supported" for that
> >>> format
> >>>
> >>>>
> >>>> So I assume you have been reworking the frame sizes.
> >>>>
> >>>> With your series, I have tested RGGB at 1280x720 , 1920x1080 .
> >>>> I also tested YUYV at 640x480 and RGB565_LE at 640x480.
> >>>>
> >>>> I can't go higher with the YUYV/RGB565, I don't receive frames anymore.
> >>>
> >>> Ah, I wonder if
> >>> 07b49ac59fd9 media: ov5640: Fix durations to comply with FPS
> >>> 82aebf4b7314 media: ov5640: Rework analog crop rectangles
> >>>
> >>> Might have impacted DVP...
> >>>
> >>> Should I keep separate fields for MIPI mode and leave the totals for
> >>> DVP untouched ?
> >>
> >> Hi Jacopo,
> >>
> >> I tested again without your series, and I can capture YUYV directly
> >> @1280x720 , which does not work anymore with your patches.
> >>
> >> The image has some bad pixels in it, but still, capture is pretty good.
> >> I am not sure whether it's a timing problem on capturing pixels, I
> >> uploaded it here so you can have a look :
> >>
> >> https://ibb.co/Yt8c0dJ
> >>
> >
> > This is without my series ? Or with it applied ? Sorry for the dumb
> > question :)
>
> This photo is *without* your series. *With* your series, I cannot
> capture YUYV at this resolution at all. No frames received.
>

Ok, thanks for clarifying.

I'll send a new version with the DVP timings and the CSI-2 ones
separated, to make sure parallel mode is less affected as possible.

Thanks
  j

> >
> >> Eugen
> >>
> >>>
> >>> Thanks again for your very useful testing
> >>>
> >>>
> >>>> I can't go higher with the bayer to 2592x1944 . But this did not work
> >>>> before your patches either.
> >>>>>
> >>>>>>
> >>>>>>>
> >>>>>>>> I managed to get it working fine at 640x480 .
> >>>>>>>>
> >>>>>>>> The sensor looks to report valid framesizes for this mbus code :
> >>>>>>>>
> >>>>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
> >>>>>>>> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
> >>>>>>>>              0x4001: MEDIA_BUS_FMT_JPEG_1X8
> >>>>>>>>              0x2006: MEDIA_BUS_FMT_UYVY8_2X8
> >>>>>>>>              0x200f: MEDIA_BUS_FMT_UYVY8_1X16
> >>>>>>>>              0x2008: MEDIA_BUS_FMT_YUYV8_2X8
> >>>>>>>>              0x2011: MEDIA_BUS_FMT_YUYV8_1X16
> >>>>>>>>              0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
> >>>>>>>>              0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
> >>>>>>>>              0x1017: MEDIA_BUS_FMT_RGB565_1X16
> >>>>>>>>              0x100a: MEDIA_BUS_FMT_RGB888_1X24
> >>>>>>>>              0x1013: MEDIA_BUS_FMT_BGR888_1X24
> >>>>>>>>              0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
> >>>>>>>>              0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
> >>>>>>>>              0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
> >>>>>>>>              0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
> >>>>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
> >>>>>>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>>>>>>>              Size Range: 160x120 - 160x120
> >>>>>>>>              Size Range: 176x144 - 176x144
> >>>>>>>>              Size Range: 320x240 - 320x240
> >>>>>>>>              Size Range: 640x480 - 640x480
> >>>>>>>>              Size Range: 720x480 - 720x480
> >>>>>>>>              Size Range: 720x576 - 720x576
> >>>>>>>>              Size Range: 1024x768 - 1024x768
> >>>>>>>>              Size Range: 1280x720 - 1280x720
> >>>>>>>>              Size Range: 1920x1080 - 1920x1080
> >>>>>>>>              Size Range: 2592x1944 - 2592x1944
> >>>>>>>> #
> >>>>>>>>
> >>>>>>>> but the ISC does not receive any frames at 1024x768 and 1920x1080.
> >>>>>>>
> >>>>>>> Are 1080p and 1024x768 working without this series applied on your
> >>>>>>> setup ?
> >>>>>>
> >>>>>> I remember they weren't working before either.
> >>>>>>
> >>>>>> I don't know exactly to which patches to add my Tested-by , as I have
> >>>>>> not tested the explicit patch behavior for each patch (e.g. where you
> >>>>>> add HBLANK control, I have not tested that ).
> >>>>>>
> >>>>>
> >>>>> I think it's good enough making sure I have not broke DVP.
> >>>>>
> >>>>> As you can see the driver now behaves in two different ways in DVP and
> >>>>> MIPI mode. The DVP works as it used to, and the framerate is
> >>>>> controlled by s_frame_interval, the frame size is fixed and the PCLK
> >>>>> is computed dyanically to accomodate the required FPS. In MIPI mode the
> >>>>> framerate is controlled by changing the vertical blankings. To each
> >>>>> mode a pixel rate is assigned and userspace changes the frame duration
> >>>>> by changing blankings. The most obvious gain is that the frame rate is
> >>>>> controllable in a continuous interval instead of being limited to a
> >>>>> few fixed values. It is my understanding that all drivers should be
> >>>>> moved to this model and s_frame_intervall should be dropped, but
> >>>>> unfortunately some bridge drivers in mainline still deman that.
> >>>>>
> >>>>> If you are interested, I think the DVP mode should be moved to use the
> >>>>> same mecahnism as MIPI mode. I can't test so I haven't done so in this
> >>>>> series.
> >>>>>
> >>>>> For now I think it's enough to make sure there are no regressions in
> >>>>> DVP mode.
> >>>>>
> >>>>> For the tag, I think it would be appropriate to add it to the
> >>>>> following one:
> >>>>>
> >>>>> 91ae667b0d47 media: ov5640: Limit frame_interval to DVP mode only
> >>>>>
> >>>>>> Is there something particular you would like me to try , except my usual
> >>>>>> image captures ?
> >>>>>
> >>>>> RGB888 is weird on both the platforms I've tested on and I cannot get
> >>>>> colors right. Does your platform support RGB888 ?
> >>>>
> >>>> I can't test this one unfortunately. It's a 1X24 . I have only 8 bits
> >>>> connected, so unless you can make this a 3x8 , there isn't anything I
> >>>> can do.
> >>>>
> >>>>>
> >>>>> Thanks
> >>>>>      j
> >>>>>
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>> Eugen
> >>>>>>
> >>>>>>>
> >>>>>>> Thanks again for testin!
> >>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> What I can say is that the raw bayer format works at 1920x1080 , frames
> >>>>>>>> are received correctly.
> >>>>>>>>
> >>>>>>>> Thanks,
> >>>>>>>> Eugen
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>> v1 -> v2:
> >>>>>>>>> - rework the modes definition to process the full pixel array
> >>>>>>>>> - rework get_selection to report the correct BOUND and DEFAULT targets
> >>>>>>>>> - implement init_cfg
> >>>>>>>>> - minor style changes as suggested by Laurent
> >>>>>>>>> - test with 1 data lane
> >>>>>>>>>
> >>>>>>>>> Thanks
> >>>>>>>>>         j
> >>>>>>>>>
> >>>>>>>>> Jacopo Mondi (23):
> >>>>>>>>>        media: ov5640: Add pixel rate to modes
> >>>>>>>>>        media: ov5604: Re-arrange modes definition
> >>>>>>>>>        media: ov5640: Add ov5640_is_csi2() function
> >>>>>>>>>        media: ov5640: Associate bpp with formats
> >>>>>>>>>        media: ov5640: Add LINK_FREQ control
> >>>>>>>>>        media: ov5640: Update pixel_rate and link_freq
> >>>>>>>>>        media: ov5640: Rework CSI-2 clock tree
> >>>>>>>>>        media: ov5640: Rework timings programming
> >>>>>>>>>        media: ov5640: Fix 720x480 in RGB888 mode
> >>>>>>>>>        media: ov5640: Rework analog crop rectangles
> >>>>>>>>>        media: ov5640: Re-sort per-mode register tables
> >>>>>>>>>        media: ov5640: Remove ov5640_mode_init_data
> >>>>>>>>>        media: ov5640: Add HBLANK control
> >>>>>>>>>        media: ov5640: Add VBLANK control
> >>>>>>>>>        media: ov5640: Fix durations to comply with FPS
> >>>>>>>>>        media: ov5640: Implement init_cfg
> >>>>>>>>>        media: ov5640: Implement get_selection
> >>>>>>>>>        media: ov5640: Limit frame_interval to DVP mode only
> >>>>>>>>>        media: ov5640: Register device properties
> >>>>>>>>>        media: ov5640: Add RGB565_1X16 format
> >>>>>>>>>        media: ov5640: Add RGB888/BGR888 formats
> >>>>>>>>>        media: ov5640: Restrict sizes to mbus code
> >>>>>>>>>        media: ov5640: Adjust format to bpp in s_fmt
> >>>>>>>>>
> >>>>>>>>>       drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
> >>>>>>>>>       1 file changed, 830 insertions(+), 313 deletions(-)
> >>>>>>>>>
> >>>>>>>>> --
> >>>>>>>>> 2.35.0
> >>>>>>>>>
> >>>>>>>>
> >>>>>>
> >>>>
> >>
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 07/23] media: ov5640: Rework CSI-2 clock tree
  2022-02-20 12:17   ` Laurent Pinchart
@ 2022-02-21 11:39     ` Jacopo Mondi
  2022-02-21 12:12       ` Laurent Pinchart
  0 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-21 11:39 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Laurent

On Sun, Feb 20, 2022 at 02:17:12PM +0200, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Thu, Feb 10, 2022 at 12:04:42PM +0100, Jacopo Mondi wrote:
> > Re-work the ov5640_set_mipi_pclk() function to calculate the
> > PLL configuration using the pixel_rate and link_freq values set at
> > s_fmt time.
> >
> > Rework the DVP clock mode settings to calculate the pixel clock
> > internally and remove the assumption on the 16bpp format.
> >
> > Tested in MIPI CSI-2 mode with 1 and 2 data lanes with:
> > - all the sensor supported resolutions in UYVY and RGB565 formats.
> > - resolutions >= 1280x720 in RAW Bayer format.
> > - resolutions < 1280x720 in RGB888 format.
> >
> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> > ---
> >  drivers/media/i2c/ov5640.c | 189 ++++++++++++++++++-------------------
> >  1 file changed, 90 insertions(+), 99 deletions(-)
> >
> > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > index 50b611697470..eb4789ae6abf 100644
> > --- a/drivers/media/i2c/ov5640.c
> > +++ b/drivers/media/i2c/ov5640.c
> > @@ -90,6 +90,7 @@
> >  #define OV5640_REG_POLARITY_CTRL00	0x4740
> >  #define OV5640_REG_MIPI_CTRL00		0x4800
> >  #define OV5640_REG_DEBUG_MODE		0x4814
> > +#define OV5640_REG_PCLK_PERIOD		0x4837
> >  #define OV5640_REG_ISP_FORMAT_MUX_CTRL	0x501f
> >  #define OV5640_REG_PRE_ISP_TEST_SET1	0x503d
> >  #define OV5640_REG_SDE_CTRL0		0x5580
> > @@ -922,20 +923,10 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
> >   *                                +-----+-----+
> >   *                                       +------------> PCLK
> >   *
> > - * This is deviating from the datasheet at least for the register
> > - * 0x3108, since it's said here that the PCLK would be clocked from
> > - * the PLL.
> > - *
> > - * There seems to be also (unverified) constraints:
> > + * There seems to be also constraints:
> >   *  - the PLL pre-divider output rate should be in the 4-27MHz range
> >   *  - the PLL multiplier output rate should be in the 500-1000MHz range
> >   *  - PCLK >= SCLK * 2 in YUV, >= SCLK in Raw or JPEG
> > - *
> > - * In the two latter cases, these constraints are met since our
> > - * factors are hardcoded. If we were to change that, we would need to
> > - * take this into account. The only varying parts are the PLL
> > - * multiplier and the system clock divider, which are shared between
> > - * all these clocks so won't cause any issue.
> >   */
> >
> >  /*
> > @@ -954,13 +945,6 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
> >  #define OV5640_SYSDIV_MIN	1
> >  #define OV5640_SYSDIV_MAX	16
> >
> > -/*
> > - * Hardcode these values for scaler and non-scaler modes.
> > - * FIXME: to be re-calcualted for 1 data lanes setups
> > - */
> > -#define OV5640_MIPI_DIV_PCLK	2
> > -#define OV5640_MIPI_DIV_SCLK	1
> > -
> >  /*
> >   * This is supposed to be ranging from 1 to 2, but the value is always
> >   * set to 2 in the vendor kernels.
> > @@ -1071,69 +1055,77 @@ static unsigned long ov5640_calc_sys_clk(struct ov5640_dev *sensor,
> >   * ov5640_set_mipi_pclk() - Calculate the clock tree configuration values
> >   *			    for the MIPI CSI-2 output.
> >   *
> > - * @rate: The requested bandwidth per lane in bytes per second.
> > - *	  'Bandwidth Per Lane' is calculated as:
> > - *	  bpl = HTOT * VTOT * FPS * bpp / num_lanes;
> > - *
> > - * This function use the requested bandwidth to calculate:
> > - * - sample_rate = bpl / (bpp / num_lanes);
> > - *	         = bpl / (PLL_RDIV * BIT_DIV * PCLK_DIV * MIPI_DIV / num_lanes);
> > - *
> > - * - mipi_sclk   = bpl / MIPI_DIV / 2; ( / 2 is for CSI-2 DDR)
> > - *
> > - * with these fixed parameters:
> > - *	PLL_RDIV	= 2;
> > - *	BIT_DIVIDER	= 2; (MIPI_BIT_MODE == 8 ? 2 : 2,5);
> > - *	PCLK_DIV	= 1;
> > - *
> > - * The MIPI clock generation differs for modes that use the scaler and modes
> > - * that do not. In case the scaler is in use, the MIPI_SCLK generates the MIPI
> > - * BIT CLk, and thus:
> > - *
> > - * - mipi_sclk = bpl / MIPI_DIV / 2;
> > - *   MIPI_DIV = 1;
> > - *
> > - * For modes that do not go through the scaler, the MIPI BIT CLOCK is generated
> > - * from the pixel clock, and thus:
> > - *
> > - * - sample_rate = bpl / (bpp / num_lanes);
> > - *	         = bpl / (2 * 2 * 1 * MIPI_DIV / num_lanes);
> > - *		 = bpl / (4 * MIPI_DIV / num_lanes);
> > - * - MIPI_DIV	 = bpp / (4 * num_lanes);
> > - *
> > - * FIXME: this have been tested with 16bpp and 2 lanes setup only.
> > - * MIPI_DIV is fixed to value 2, but it -might- be changed according to the
> > - * above formula for setups with 1 lane or image formats with different bpp.
> > - *
> > - * FIXME: this deviates from the sensor manual documentation which is quite
> > - * thin on the MIPI clock tree generation part.
> > + * FIXME: tested with 2 lanes only.
>
> Not true anymore, is it ?
>

Yes, I can drop this

> >   */
> > -static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
> > -				unsigned long rate)
> > +static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor)
> >  {
> > -	const struct ov5640_mode_info *mode = sensor->current_mode;
> > +	u8 bit_div, mipi_div, p_div, sclk_div, sclk2x_div, root_div;
> > +	struct v4l2_mbus_framefmt *fmt = &sensor->fmt;
> >  	u8 prediv, mult, sysdiv;
> > -	u8 mipi_div;
> > +	unsigned long sysclk;
> > +	unsigned long sample_rate;
> > +	u8 pclk_period;
> > +	s64 link_freq;
> >  	int ret;
> >
> > +	/* Use the link frequency computed at ov5640_update_pixel_rate() time. */
> > +	link_freq = ov5640_csi2_link_freqs[sensor->ctrls.link_freq->cur.val];
> > +
> >  	/*
> > -	 * 1280x720 is reported to use 'SUBSAMPLING' only,
> > -	 * but according to the sensor manual it goes through the
> > -	 * scaler before subsampling.
> > +	 * - mipi_div - Additional divider for the MIPI lane clock.
> > +	 *
> > +	 * Higher link frequencies would make sysclk > 1GHz.
> > +	 * Keep the sysclk low and do not divide in the MIPI domain.
> >  	 */
> > -	if (mode->dn_mode == SCALING ||
> > -	   (mode->id == OV5640_MODE_720P_1280_720))
> > -		mipi_div = OV5640_MIPI_DIV_SCLK;
> > +	if (link_freq > OV5640_LINK_RATE_MAX)
> > +		mipi_div = 1;
> >  	else
> > -		mipi_div = OV5640_MIPI_DIV_PCLK;
> > +		mipi_div = 2;
> >
> > -	ov5640_calc_sys_clk(sensor, rate, &prediv, &mult, &sysdiv);
> > +	sysclk = link_freq * mipi_div;
> > +	ov5640_calc_sys_clk(sensor, sysclk, &prediv, &mult, &sysdiv);
> >
> > -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0,
> > -			     0x0f, OV5640_PLL_CTRL0_MIPI_MODE_8BIT);
> > +	/*
> > +	 * Adjust PLL parameters to maintain the MIPI_SCLK-to-PCLK ratio;
>
> s/;/:/ ?
>
> > +	 *
> > +	 * - root_div = 2 (fixed)
> > +	 * - bit_div : MIPI 8-bit = 2
> > +	 *	       MIPI 10-bit = 2.5
> > +	 * - p_div = 1 (fixed)
> > +	 * - pll_div  = (2 lanes ? mipi_div : 2 * mipi_div)
>
> There's no pll_div variable in the code, nothing called "PLL div" in
> comments, and nothing in the datasheet either as far as I can tell.
> Based on your reply to the v1 review, I think you mean "p_div" instead
> of "pll_div". Also, you mentioned there that P_DIV is equal to

Yeah it's P_DIV

>
> - 1 data lane = MIPI_DIV (0x3035[3:0])
> - 2 data lane = 2 * MIPI_DIV
>
> while here you write the opposite. MIPI_DIV * number data lanes seems
> more logical to me, as the CSI-2 clock frequency should be lower with
> more data lanes. You could thus write
>
> 	 * - p_div is set by the sensor to mipi_div * number of data lanes
>
> Let's add a blank line here, and
>
> 	 *
> 	 * This results in the following MIPI_SCLK depending on the number
> 	 * of lanes:
> 	 *

I said so as I got the same reasoning: more lanes = lower pclk freq
But the PLL diagram where I got that comment from says

        P_DIV = mipi2lanes ? r03035[3:0] : 2*r3035[3:0]

Should I assume a typo in the (found on the internet, never really
confirmed) PLL clock diagram ?

Actually being this the pixel clock divider, and being the pixel clock
fed from the sysclk that feed the MIPI clk as well, doesn't it make
sense to have a faster pixel clock when 2 lanes are available to be
capable of reaching higher pixel rates ?

Thing is that this register automatically takes a value, so might it
be a protection to guarantee that with 1 data lane the pixels are
clocked out slow enough for the CSI-2 bus to cope ?

>
> > +	 *   2 lanes: MIPI_SCLK = (4 or 5) * PCLK
> > +	 *   1 lanes: MIPI_SCLK = (8 or 10) * PCLK
> > +	 */
> > +	root_div = OV5640_PLL_CTRL3_PLL_ROOT_DIV_2;
> > +	bit_div =  OV5640_PLL_CTRL0_MIPI_MODE_8BIT;
> > +	p_div = OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS;
> >
> > -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
> > -			     0xff, sysdiv << 4 | mipi_div);
> > +	/*
> > +	 * Scaler clock:
> > +	 * - YUV: PCLK >= 2 * SCLK
> > +	 * - RAW or JPEG: PCLK >= SCLK
> > +	 * - sclk2x_div = sclk_div / 2
> > +	 *
> > +	 * TODO: test with JPEG.
> > +	 */
> > +	sclk_div = ilog2(OV5640_SCLK_ROOT_DIV);
> > +	sclk2x_div = ilog2(OV5640_SCLK2X_ROOT_DIV);
> > +
> > +	/*
> > +	 * Set the sample period expressed in ns with 1-bit decimal
> > +	 * (0x01=0.5ns).
> > +	 */
> > +	sample_rate = ov5640_pixel_rates[sensor->current_mode->pixel_rate]
> > +		    * (ov5640_code_to_bpp(fmt->code) / 8);
> > +	pclk_period = 2000000000U / sample_rate;
> > +
> > +	/* Program the clock tree registers. */
> > +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0, 0x0f, bit_div);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1, 0xff,
> > +			     (sysdiv << 4) | mipi_div);
> >  	if (ret)
> >  		return ret;
> >
> > @@ -1141,13 +1133,27 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
> >  	if (ret)
> >  		return ret;
> >
> > -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
> > -			     0x1f, OV5640_PLL_CTRL3_PLL_ROOT_DIV_2 | prediv);
> > +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3, 0x1f,
> > +			     root_div | prediv);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
> > +			     (p_div << 4) | (sclk2x_div << 2) | sclk_div);
>
> Bits 5:4 of this register are named "PCLK root divider" in the
> datasheet. Can you rename the variable to pclk_div to match the clock
> tree diagram in the driver that names it "PCLK Div" ? Another option
> would be to name ie pclk_root_div and update the clock tree diagram
> accordingly. The p_div mention in the comment above should be renamed
> too.

There already is a root_div, I would avoid repeating it. I'll go for
pclk_div.

>
> >  	if (ret)
> >  		return ret;
> >
> > -	return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER,
> > -			      0x30, OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS);
> > +	return ov5640_write_reg(sensor, OV5640_REG_PCLK_PERIOD, pclk_period);
> > +}
> > +
> > +static u32 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
> > +{
> > +	u32 rate;
> > +
> > +	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
> > +	rate *= ov5640_framerates[sensor->current_fr];
> > +
> > +	return rate;
> >  }
> >
> >  static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
> > @@ -1167,11 +1173,16 @@ static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
> >  	return _rate / *pll_rdiv / *bit_div / *pclk_div;
> >  }
> >
> > -static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor, unsigned long rate)
> > +static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor)
> >  {
> >  	u8 prediv, mult, sysdiv, pll_rdiv, bit_div, pclk_div;
> > +	u32 rate;
> >  	int ret;
> >
> > +	rate = ov5640_calc_pixel_rate(sensor);
> > +	rate *= ov5640_code_to_bpp(sensor->fmt.code);
> > +	rate /= sensor->ep.bus.parallel.bus_width;
> > +
> >  	ov5640_calc_pclk(sensor, rate, &prediv, &mult, &sysdiv, &pll_rdiv,
> >  			 &bit_div, &pclk_div);
> >
> > @@ -1696,16 +1707,6 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
> >  	return mode;
> >  }
> >
> > -static u64 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
> > -{
> > -	u64 rate;
> > -
> > -	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
> > -	rate *= ov5640_framerates[sensor->current_fr];
> > -
> > -	return rate;
> > -}
> > -
> >  /*
> >   * sensor changes between scaling and subsampling, go through
> >   * exposure calculation
> > @@ -1887,7 +1888,6 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
> >  	enum ov5640_downsize_mode dn_mode, orig_dn_mode;
> >  	bool auto_gain = sensor->ctrls.auto_gain->val == 1;
> >  	bool auto_exp =  sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
> > -	unsigned long rate;
> >  	int ret;
> >
> >  	dn_mode = mode->dn_mode;
> > @@ -1906,19 +1906,10 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
> >  			goto restore_auto_gain;
> >  	}
> >
> > -	/*
> > -	 * All the formats we support have 16 bits per pixel, seems to require
> > -	 * the same rate than YUV, so we can just use 16 bpp all the time.
> > -	 */
> > -	rate = ov5640_calc_pixel_rate(sensor) * 16;
> > -	if (ov5640_is_csi2(sensor)) {
> > -		rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes;
> > -		ret = ov5640_set_mipi_pclk(sensor, rate);
> > -	} else {
> > -		rate = rate / sensor->ep.bus.parallel.bus_width;
> > -		ret = ov5640_set_dvp_pclk(sensor, rate);
> > -	}
> > -
> > +	if (ov5640_is_csi2(sensor))
> > +		ret = ov5640_set_mipi_pclk(sensor);
> > +	else
> > +		ret = ov5640_set_dvp_pclk(sensor);
> >  	if (ret < 0)
> >  		return 0;
> >
>
> --
> Regards,
>
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 07/23] media: ov5640: Rework CSI-2 clock tree
  2022-02-21 11:39     ` Jacopo Mondi
@ 2022-02-21 12:12       ` Laurent Pinchart
  0 siblings, 0 replies; 64+ messages in thread
From: Laurent Pinchart @ 2022-02-21 12:12 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Steve Longerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, Eugen.Hristev,
	jbrunet, Mauro Carvalho Chehab, linux-media

Hi Jacopo,

On Mon, Feb 21, 2022 at 12:39:03PM +0100, Jacopo Mondi wrote:
> On Sun, Feb 20, 2022 at 02:17:12PM +0200, Laurent Pinchart wrote:
> > On Thu, Feb 10, 2022 at 12:04:42PM +0100, Jacopo Mondi wrote:
> > > Re-work the ov5640_set_mipi_pclk() function to calculate the
> > > PLL configuration using the pixel_rate and link_freq values set at
> > > s_fmt time.
> > >
> > > Rework the DVP clock mode settings to calculate the pixel clock
> > > internally and remove the assumption on the 16bpp format.
> > >
> > > Tested in MIPI CSI-2 mode with 1 and 2 data lanes with:
> > > - all the sensor supported resolutions in UYVY and RGB565 formats.
> > > - resolutions >= 1280x720 in RAW Bayer format.
> > > - resolutions < 1280x720 in RGB888 format.
> > >
> > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> > > ---
> > >  drivers/media/i2c/ov5640.c | 189 ++++++++++++++++++-------------------
> > >  1 file changed, 90 insertions(+), 99 deletions(-)
> > >
> > > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > > index 50b611697470..eb4789ae6abf 100644
> > > --- a/drivers/media/i2c/ov5640.c
> > > +++ b/drivers/media/i2c/ov5640.c
> > > @@ -90,6 +90,7 @@
> > >  #define OV5640_REG_POLARITY_CTRL00	0x4740
> > >  #define OV5640_REG_MIPI_CTRL00		0x4800
> > >  #define OV5640_REG_DEBUG_MODE		0x4814
> > > +#define OV5640_REG_PCLK_PERIOD		0x4837
> > >  #define OV5640_REG_ISP_FORMAT_MUX_CTRL	0x501f
> > >  #define OV5640_REG_PRE_ISP_TEST_SET1	0x503d
> > >  #define OV5640_REG_SDE_CTRL0		0x5580
> > > @@ -922,20 +923,10 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
> > >   *                                +-----+-----+
> > >   *                                       +------------> PCLK
> > >   *
> > > - * This is deviating from the datasheet at least for the register
> > > - * 0x3108, since it's said here that the PCLK would be clocked from
> > > - * the PLL.
> > > - *
> > > - * There seems to be also (unverified) constraints:
> > > + * There seems to be also constraints:
> > >   *  - the PLL pre-divider output rate should be in the 4-27MHz range
> > >   *  - the PLL multiplier output rate should be in the 500-1000MHz range
> > >   *  - PCLK >= SCLK * 2 in YUV, >= SCLK in Raw or JPEG
> > > - *
> > > - * In the two latter cases, these constraints are met since our
> > > - * factors are hardcoded. If we were to change that, we would need to
> > > - * take this into account. The only varying parts are the PLL
> > > - * multiplier and the system clock divider, which are shared between
> > > - * all these clocks so won't cause any issue.
> > >   */
> > >
> > >  /*
> > > @@ -954,13 +945,6 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
> > >  #define OV5640_SYSDIV_MIN	1
> > >  #define OV5640_SYSDIV_MAX	16
> > >
> > > -/*
> > > - * Hardcode these values for scaler and non-scaler modes.
> > > - * FIXME: to be re-calcualted for 1 data lanes setups
> > > - */
> > > -#define OV5640_MIPI_DIV_PCLK	2
> > > -#define OV5640_MIPI_DIV_SCLK	1
> > > -
> > >  /*
> > >   * This is supposed to be ranging from 1 to 2, but the value is always
> > >   * set to 2 in the vendor kernels.
> > > @@ -1071,69 +1055,77 @@ static unsigned long ov5640_calc_sys_clk(struct ov5640_dev *sensor,
> > >   * ov5640_set_mipi_pclk() - Calculate the clock tree configuration values
> > >   *			    for the MIPI CSI-2 output.
> > >   *
> > > - * @rate: The requested bandwidth per lane in bytes per second.
> > > - *	  'Bandwidth Per Lane' is calculated as:
> > > - *	  bpl = HTOT * VTOT * FPS * bpp / num_lanes;
> > > - *
> > > - * This function use the requested bandwidth to calculate:
> > > - * - sample_rate = bpl / (bpp / num_lanes);
> > > - *	         = bpl / (PLL_RDIV * BIT_DIV * PCLK_DIV * MIPI_DIV / num_lanes);
> > > - *
> > > - * - mipi_sclk   = bpl / MIPI_DIV / 2; ( / 2 is for CSI-2 DDR)
> > > - *
> > > - * with these fixed parameters:
> > > - *	PLL_RDIV	= 2;
> > > - *	BIT_DIVIDER	= 2; (MIPI_BIT_MODE == 8 ? 2 : 2,5);
> > > - *	PCLK_DIV	= 1;
> > > - *
> > > - * The MIPI clock generation differs for modes that use the scaler and modes
> > > - * that do not. In case the scaler is in use, the MIPI_SCLK generates the MIPI
> > > - * BIT CLk, and thus:
> > > - *
> > > - * - mipi_sclk = bpl / MIPI_DIV / 2;
> > > - *   MIPI_DIV = 1;
> > > - *
> > > - * For modes that do not go through the scaler, the MIPI BIT CLOCK is generated
> > > - * from the pixel clock, and thus:
> > > - *
> > > - * - sample_rate = bpl / (bpp / num_lanes);
> > > - *	         = bpl / (2 * 2 * 1 * MIPI_DIV / num_lanes);
> > > - *		 = bpl / (4 * MIPI_DIV / num_lanes);
> > > - * - MIPI_DIV	 = bpp / (4 * num_lanes);
> > > - *
> > > - * FIXME: this have been tested with 16bpp and 2 lanes setup only.
> > > - * MIPI_DIV is fixed to value 2, but it -might- be changed according to the
> > > - * above formula for setups with 1 lane or image formats with different bpp.
> > > - *
> > > - * FIXME: this deviates from the sensor manual documentation which is quite
> > > - * thin on the MIPI clock tree generation part.
> > > + * FIXME: tested with 2 lanes only.
> >
> > Not true anymore, is it ?
> 
> Yes, I can drop this
> 
> > >   */
> > > -static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
> > > -				unsigned long rate)
> > > +static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor)
> > >  {
> > > -	const struct ov5640_mode_info *mode = sensor->current_mode;
> > > +	u8 bit_div, mipi_div, p_div, sclk_div, sclk2x_div, root_div;
> > > +	struct v4l2_mbus_framefmt *fmt = &sensor->fmt;
> > >  	u8 prediv, mult, sysdiv;
> > > -	u8 mipi_div;
> > > +	unsigned long sysclk;
> > > +	unsigned long sample_rate;
> > > +	u8 pclk_period;
> > > +	s64 link_freq;
> > >  	int ret;
> > >
> > > +	/* Use the link frequency computed at ov5640_update_pixel_rate() time. */
> > > +	link_freq = ov5640_csi2_link_freqs[sensor->ctrls.link_freq->cur.val];
> > > +
> > >  	/*
> > > -	 * 1280x720 is reported to use 'SUBSAMPLING' only,
> > > -	 * but according to the sensor manual it goes through the
> > > -	 * scaler before subsampling.
> > > +	 * - mipi_div - Additional divider for the MIPI lane clock.
> > > +	 *
> > > +	 * Higher link frequencies would make sysclk > 1GHz.
> > > +	 * Keep the sysclk low and do not divide in the MIPI domain.
> > >  	 */
> > > -	if (mode->dn_mode == SCALING ||
> > > -	   (mode->id == OV5640_MODE_720P_1280_720))
> > > -		mipi_div = OV5640_MIPI_DIV_SCLK;
> > > +	if (link_freq > OV5640_LINK_RATE_MAX)
> > > +		mipi_div = 1;
> > >  	else
> > > -		mipi_div = OV5640_MIPI_DIV_PCLK;
> > > +		mipi_div = 2;
> > >
> > > -	ov5640_calc_sys_clk(sensor, rate, &prediv, &mult, &sysdiv);
> > > +	sysclk = link_freq * mipi_div;
> > > +	ov5640_calc_sys_clk(sensor, sysclk, &prediv, &mult, &sysdiv);
> > >
> > > -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0,
> > > -			     0x0f, OV5640_PLL_CTRL0_MIPI_MODE_8BIT);
> > > +	/*
> > > +	 * Adjust PLL parameters to maintain the MIPI_SCLK-to-PCLK ratio;
> >
> > s/;/:/ ?
> >
> > > +	 *
> > > +	 * - root_div = 2 (fixed)
> > > +	 * - bit_div : MIPI 8-bit = 2
> > > +	 *	       MIPI 10-bit = 2.5
> > > +	 * - p_div = 1 (fixed)
> > > +	 * - pll_div  = (2 lanes ? mipi_div : 2 * mipi_div)
> >
> > There's no pll_div variable in the code, nothing called "PLL div" in
> > comments, and nothing in the datasheet either as far as I can tell.
> > Based on your reply to the v1 review, I think you mean "p_div" instead
> > of "pll_div". Also, you mentioned there that P_DIV is equal to
> 
> Yeah it's P_DIV
> 
> > - 1 data lane = MIPI_DIV (0x3035[3:0])
> > - 2 data lane = 2 * MIPI_DIV
> >
> > while here you write the opposite. MIPI_DIV * number data lanes seems
> > more logical to me, as the CSI-2 clock frequency should be lower with
> > more data lanes. You could thus write
> >
> > 	 * - p_div is set by the sensor to mipi_div * number of data lanes
> >
> > Let's add a blank line here, and
> >
> > 	 *
> > 	 * This results in the following MIPI_SCLK depending on the number
> > 	 * of lanes:
> > 	 *
> 
> I said so as I got the same reasoning: more lanes = lower pclk freq
> But the PLL diagram where I got that comment from says
> 
>         P_DIV = mipi2lanes ? r03035[3:0] : 2*r3035[3:0]
> 
> Should I assume a typo in the (found on the internet, never really
> confirmed) PLL clock diagram ?

I think you can assume mistakes all over the place ;-)

> Actually being this the pixel clock divider, and being the pixel clock
> fed from the sysclk that feed the MIPI clk as well, doesn't it make
> sense to have a faster pixel clock when 2 lanes are available to be
> capable of reaching higher pixel rates ?
> 
> Thing is that this register automatically takes a value, so might it
> be a protection to guarantee that with 1 data lane the pixels are
> clocked out slow enough for the CSI-2 bus to cope ?

Not really a protection, but indeed, when using two lanes, the serial
clock frequency is divided by two for a given pixel clock frequency. It
means that, for a given serial clock frequency, the pixel clock
frequency is twice as high, so P_DIV should be divided by two.

> > > +	 *   2 lanes: MIPI_SCLK = (4 or 5) * PCLK
> > > +	 *   1 lanes: MIPI_SCLK = (8 or 10) * PCLK
> > > +	 */
> > > +	root_div = OV5640_PLL_CTRL3_PLL_ROOT_DIV_2;
> > > +	bit_div =  OV5640_PLL_CTRL0_MIPI_MODE_8BIT;
> > > +	p_div = OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS;
> > >
> > > -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
> > > -			     0xff, sysdiv << 4 | mipi_div);
> > > +	/*
> > > +	 * Scaler clock:
> > > +	 * - YUV: PCLK >= 2 * SCLK
> > > +	 * - RAW or JPEG: PCLK >= SCLK
> > > +	 * - sclk2x_div = sclk_div / 2
> > > +	 *
> > > +	 * TODO: test with JPEG.
> > > +	 */
> > > +	sclk_div = ilog2(OV5640_SCLK_ROOT_DIV);
> > > +	sclk2x_div = ilog2(OV5640_SCLK2X_ROOT_DIV);
> > > +
> > > +	/*
> > > +	 * Set the sample period expressed in ns with 1-bit decimal
> > > +	 * (0x01=0.5ns).
> > > +	 */
> > > +	sample_rate = ov5640_pixel_rates[sensor->current_mode->pixel_rate]
> > > +		    * (ov5640_code_to_bpp(fmt->code) / 8);
> > > +	pclk_period = 2000000000U / sample_rate;
> > > +
> > > +	/* Program the clock tree registers. */
> > > +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0, 0x0f, bit_div);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1, 0xff,
> > > +			     (sysdiv << 4) | mipi_div);
> > >  	if (ret)
> > >  		return ret;
> > >
> > > @@ -1141,13 +1133,27 @@ static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
> > >  	if (ret)
> > >  		return ret;
> > >
> > > -	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
> > > -			     0x1f, OV5640_PLL_CTRL3_PLL_ROOT_DIV_2 | prediv);
> > > +	ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3, 0x1f,
> > > +			     root_div | prediv);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
> > > +			     (p_div << 4) | (sclk2x_div << 2) | sclk_div);
> >
> > Bits 5:4 of this register are named "PCLK root divider" in the
> > datasheet. Can you rename the variable to pclk_div to match the clock
> > tree diagram in the driver that names it "PCLK Div" ? Another option
> > would be to name ie pclk_root_div and update the clock tree diagram
> > accordingly. The p_div mention in the comment above should be renamed
> > too.
> 
> There already is a root_div, I would avoid repeating it. I'll go for
> pclk_div.
> 
> > >  	if (ret)
> > >  		return ret;
> > >
> > > -	return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER,
> > > -			      0x30, OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS);
> > > +	return ov5640_write_reg(sensor, OV5640_REG_PCLK_PERIOD, pclk_period);
> > > +}
> > > +
> > > +static u32 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
> > > +{
> > > +	u32 rate;
> > > +
> > > +	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
> > > +	rate *= ov5640_framerates[sensor->current_fr];
> > > +
> > > +	return rate;
> > >  }
> > >
> > >  static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
> > > @@ -1167,11 +1173,16 @@ static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
> > >  	return _rate / *pll_rdiv / *bit_div / *pclk_div;
> > >  }
> > >
> > > -static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor, unsigned long rate)
> > > +static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor)
> > >  {
> > >  	u8 prediv, mult, sysdiv, pll_rdiv, bit_div, pclk_div;
> > > +	u32 rate;
> > >  	int ret;
> > >
> > > +	rate = ov5640_calc_pixel_rate(sensor);
> > > +	rate *= ov5640_code_to_bpp(sensor->fmt.code);
> > > +	rate /= sensor->ep.bus.parallel.bus_width;
> > > +
> > >  	ov5640_calc_pclk(sensor, rate, &prediv, &mult, &sysdiv, &pll_rdiv,
> > >  			 &bit_div, &pclk_div);
> > >
> > > @@ -1696,16 +1707,6 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
> > >  	return mode;
> > >  }
> > >
> > > -static u64 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
> > > -{
> > > -	u64 rate;
> > > -
> > > -	rate = sensor->current_mode->vtot * sensor->current_mode->htot;
> > > -	rate *= ov5640_framerates[sensor->current_fr];
> > > -
> > > -	return rate;
> > > -}
> > > -
> > >  /*
> > >   * sensor changes between scaling and subsampling, go through
> > >   * exposure calculation
> > > @@ -1887,7 +1888,6 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
> > >  	enum ov5640_downsize_mode dn_mode, orig_dn_mode;
> > >  	bool auto_gain = sensor->ctrls.auto_gain->val == 1;
> > >  	bool auto_exp =  sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
> > > -	unsigned long rate;
> > >  	int ret;
> > >
> > >  	dn_mode = mode->dn_mode;
> > > @@ -1906,19 +1906,10 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
> > >  			goto restore_auto_gain;
> > >  	}
> > >
> > > -	/*
> > > -	 * All the formats we support have 16 bits per pixel, seems to require
> > > -	 * the same rate than YUV, so we can just use 16 bpp all the time.
> > > -	 */
> > > -	rate = ov5640_calc_pixel_rate(sensor) * 16;
> > > -	if (ov5640_is_csi2(sensor)) {
> > > -		rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes;
> > > -		ret = ov5640_set_mipi_pclk(sensor, rate);
> > > -	} else {
> > > -		rate = rate / sensor->ep.bus.parallel.bus_width;
> > > -		ret = ov5640_set_dvp_pclk(sensor, rate);
> > > -	}
> > > -
> > > +	if (ov5640_is_csi2(sensor))
> > > +		ret = ov5640_set_mipi_pclk(sensor);
> > > +	else
> > > +		ret = ov5640_set_dvp_pclk(sensor);
> > >  	if (ret < 0)
> > >  		return 0;
> > >

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 22/23] media: ov5640: Restrict sizes to mbus code
  2022-02-20 13:16   ` Laurent Pinchart
@ 2022-02-21 12:42     ` Jacopo Mondi
  0 siblings, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-21 12:42 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: slongerbeam, sakari.ailus, hverkuil-cisco, mirela.rabulea,
	xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, eugen.hristev,
	jbrunet, mchehab, linux-media

On Sun, Feb 20, 2022 at 03:16:03PM +0200, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Thu, Feb 10, 2022 at 12:10:43PM +0100, Jacopo Mondi wrote:
> > The ov5640 driver supports different sizes for different mbus_codes.
> > In particular:
> >
> > - 8bpp modes: high resolution sizes (>= 1280x720)
> > - 16bpp modes: all sizes
> > - 24bpp modes: low resolutions sizes (< 1280x720)
> >
> > Restrict the frame sizes enumerations to the above constraints.
> >
> > While at it, make sure the fse->mbus_code parameter is valid, and return
> > -EINVAL if it's not.
> >
> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> > ---
> >  drivers/media/i2c/ov5640.c | 20 +++++++++++++++++---
> >  1 file changed, 17 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > index f894570ac53c..81bf547a923e 100644
> > --- a/drivers/media/i2c/ov5640.c
> > +++ b/drivers/media/i2c/ov5640.c
> > @@ -3315,14 +3315,28 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
> >  				  struct v4l2_subdev_state *sd_state,
> >  				  struct v4l2_subdev_frame_size_enum *fse)
> >  {
> > +	u32 bpp = ov5640_code_to_bpp(fse->code);
> > +	unsigned int index = fse->index;
> > +
> >  	if (fse->pad != 0)
> >  		return -EINVAL;
> > -	if (fse->index >= OV5640_NUM_MODES)
> > +	if (!bpp)
> > +		return -EINVAL;
> > +
> > +	/* Only low-resolution modes are supported for 24bpp modes. */
>
> s/24bpp modes/24bpp formats/
>
>
> Do you think this is a limitation of the sensor, or an issue in the
> driver ? In the latter case, I'd write
>
> 	/* FIXME: High resolution modes don't work in 24bpp formats. */

I think it's expected. From register 0x4300 documentation:

YUV444/RGB888 (not available for full resolution)

So I would expect modes obtained by croppin the full pixel array do
not support RGB888. 1280x720 is said to be obtained by sub-sampling
(the ov5640 applies sub-sampling automatically) so it should be
possible to have it in 24bpp. Maybe it needs an higher pixel clock,
something that will be possible once LINK_FREQ is made adjustable

>
> > +	if (bpp == 24 && index >= OV5640_MODE_720P_1280_720)
> > +		return -EINVAL;
> > +
> > +	/* Only high-resolutions modes are supported for 8bpp formats. */
>
> And here
>
> 	/* FIXME: Low resolution modes don't work in 8bpp formats. */

This one puzzles me as well. The only explanation I have is again that
these modes need a -slower- pixel rate to comply with the CSI-2 link
frequency requirements. I can add a todo indeed.

>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>
> > +	if (bpp == 8)
> > +		index += OV5640_MODE_720P_1280_720;
> > +
> > +	if (index >= OV5640_NUM_MODES)
> >  		return -EINVAL;
> >
> > -	fse->min_width = ov5640_mode_data[fse->index].crop.width;
> > +	fse->min_width = ov5640_mode_data[index].crop.width;
> >  	fse->max_width = fse->min_width;
> > -	fse->min_height = ov5640_mode_data[fse->index].crop.height;
> > +	fse->min_height = ov5640_mode_data[index].crop.height;
> >  	fse->max_height = fse->min_height;
> >
> >  	return 0;
>
> --
> Regards,
>
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI
  2022-02-21  9:04                 ` Eugen.Hristev
  2022-02-21 11:18                   ` Jacopo Mondi
@ 2022-02-21 13:31                   ` Jacopo Mondi
  1 sibling, 0 replies; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-21 13:31 UTC (permalink / raw)
  To: Eugen.Hristev
  Cc: slongerbeam, laurent.pinchart, sakari.ailus, hverkuil-cisco,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	prabhakar.mahadev-lad.rj, aford173, festevam, jbrunet, mchehab,
	linux-media

Hi again Eugen
  one more last favour :)

On Mon, Feb 21, 2022 at 09:04:39AM +0000, Eugen.Hristev@microchip.com wrote:
> On 2/21/22 10:51 AM, Jacopo Mondi wrote:
> > Hi Eugen
> >
> >>>>
> >>>> So I assume you have been reworking the frame sizes.
> >>>>
> >>>> With your series, I have tested RGGB at 1280x720 , 1920x1080 .
> >>>> I also tested YUYV at 640x480 and RGB565_LE at 640x480.
> >>>>
> >>>> I can't go higher with the YUYV/RGB565, I don't receive frames anymore.
> >>>
> >>> Ah, I wonder if
> >>> 07b49ac59fd9 media: ov5640: Fix durations to comply with FPS
> >>> 82aebf4b7314 media: ov5640: Rework analog crop rectangles
> >>>
> >>> Might have impacted DVP...
> >>>
> >>> Should I keep separate fields for MIPI mode and leave the totals for
> >>> DVP untouched ?

Could you try to revert these two ? I'm reworking the series and
knowing where I break DVP might be useful. In example, I think if:

82aebf4b7314 media: ov5640: Rework analog crop rectangles

is harmless it should be kept for DVP as well.

Thanks
   j

> >>
> >> Hi Jacopo,
> >>
> >> I tested again without your series, and I can capture YUYV directly
> >> @1280x720 , which does not work anymore with your patches.
> >>
> >> The image has some bad pixels in it, but still, capture is pretty good.
> >> I am not sure whether it's a timing problem on capturing pixels, I
> >> uploaded it here so you can have a look :
> >>
> >> https://ibb.co/Yt8c0dJ
> >>
> >
> > This is without my series ? Or with it applied ? Sorry for the dumb
> > question :)
>
> This photo is *without* your series. *With* your series, I cannot
> capture YUYV at this resolution at all. No frames received.
>
> >
> >> Eugen
> >>
> >>>
> >>> Thanks again for your very useful testing
> >>>
> >>>
> >>>> I can't go higher with the bayer to 2592x1944 . But this did not work
> >>>> before your patches either.
> >>>>>
> >>>>>>
> >>>>>>>
> >>>>>>>> I managed to get it working fine at 640x480 .
> >>>>>>>>
> >>>>>>>> The sensor looks to report valid framesizes for this mbus code :
> >>>>>>>>
> >>>>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes
> >>>>>>>> \ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0)
> >>>>>>>>              0x4001: MEDIA_BUS_FMT_JPEG_1X8
> >>>>>>>>              0x2006: MEDIA_BUS_FMT_UYVY8_2X8
> >>>>>>>>              0x200f: MEDIA_BUS_FMT_UYVY8_1X16
> >>>>>>>>              0x2008: MEDIA_BUS_FMT_YUYV8_2X8
> >>>>>>>>              0x2011: MEDIA_BUS_FMT_YUYV8_1X16
> >>>>>>>>              0x1008: MEDIA_BUS_FMT_RGB565_2X8_LE
> >>>>>>>>              0x1007: MEDIA_BUS_FMT_RGB565_2X8_BE
> >>>>>>>>              0x1017: MEDIA_BUS_FMT_RGB565_1X16
> >>>>>>>>              0x100a: MEDIA_BUS_FMT_RGB888_1X24
> >>>>>>>>              0x1013: MEDIA_BUS_FMT_BGR888_1X24
> >>>>>>>>              0x3001: MEDIA_BUS_FMT_SBGGR8_1X8
> >>>>>>>>              0x3013: MEDIA_BUS_FMT_SGBRG8_1X8
> >>>>>>>>              0x3002: MEDIA_BUS_FMT_SGRBG8_1X8
> >>>>>>>>              0x3014: MEDIA_BUS_FMT_SRGGB8_1X8
> >>>>>>>> # v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-framesizes pad=0,code=0x2008
> >>>>>>>> ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0)
> >>>>>>>>              Size Range: 160x120 - 160x120
> >>>>>>>>              Size Range: 176x144 - 176x144
> >>>>>>>>              Size Range: 320x240 - 320x240
> >>>>>>>>              Size Range: 640x480 - 640x480
> >>>>>>>>              Size Range: 720x480 - 720x480
> >>>>>>>>              Size Range: 720x576 - 720x576
> >>>>>>>>              Size Range: 1024x768 - 1024x768
> >>>>>>>>              Size Range: 1280x720 - 1280x720
> >>>>>>>>              Size Range: 1920x1080 - 1920x1080
> >>>>>>>>              Size Range: 2592x1944 - 2592x1944
> >>>>>>>> #
> >>>>>>>>
> >>>>>>>> but the ISC does not receive any frames at 1024x768 and 1920x1080.
> >>>>>>>
> >>>>>>> Are 1080p and 1024x768 working without this series applied on your
> >>>>>>> setup ?
> >>>>>>
> >>>>>> I remember they weren't working before either.
> >>>>>>
> >>>>>> I don't know exactly to which patches to add my Tested-by , as I have
> >>>>>> not tested the explicit patch behavior for each patch (e.g. where you
> >>>>>> add HBLANK control, I have not tested that ).
> >>>>>>
> >>>>>
> >>>>> I think it's good enough making sure I have not broke DVP.
> >>>>>
> >>>>> As you can see the driver now behaves in two different ways in DVP and
> >>>>> MIPI mode. The DVP works as it used to, and the framerate is
> >>>>> controlled by s_frame_interval, the frame size is fixed and the PCLK
> >>>>> is computed dyanically to accomodate the required FPS. In MIPI mode the
> >>>>> framerate is controlled by changing the vertical blankings. To each
> >>>>> mode a pixel rate is assigned and userspace changes the frame duration
> >>>>> by changing blankings. The most obvious gain is that the frame rate is
> >>>>> controllable in a continuous interval instead of being limited to a
> >>>>> few fixed values. It is my understanding that all drivers should be
> >>>>> moved to this model and s_frame_intervall should be dropped, but
> >>>>> unfortunately some bridge drivers in mainline still deman that.
> >>>>>
> >>>>> If you are interested, I think the DVP mode should be moved to use the
> >>>>> same mecahnism as MIPI mode. I can't test so I haven't done so in this
> >>>>> series.
> >>>>>
> >>>>> For now I think it's enough to make sure there are no regressions in
> >>>>> DVP mode.
> >>>>>
> >>>>> For the tag, I think it would be appropriate to add it to the
> >>>>> following one:
> >>>>>
> >>>>> 91ae667b0d47 media: ov5640: Limit frame_interval to DVP mode only
> >>>>>
> >>>>>> Is there something particular you would like me to try , except my usual
> >>>>>> image captures ?
> >>>>>
> >>>>> RGB888 is weird on both the platforms I've tested on and I cannot get
> >>>>> colors right. Does your platform support RGB888 ?
> >>>>
> >>>> I can't test this one unfortunately. It's a 1X24 . I have only 8 bits
> >>>> connected, so unless you can make this a 3x8 , there isn't anything I
> >>>> can do.
> >>>>
> >>>>>
> >>>>> Thanks
> >>>>>      j
> >>>>>
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>> Eugen
> >>>>>>
> >>>>>>>
> >>>>>>> Thanks again for testin!
> >>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> What I can say is that the raw bayer format works at 1920x1080 , frames
> >>>>>>>> are received correctly.
> >>>>>>>>
> >>>>>>>> Thanks,
> >>>>>>>> Eugen
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>> v1 -> v2:
> >>>>>>>>> - rework the modes definition to process the full pixel array
> >>>>>>>>> - rework get_selection to report the correct BOUND and DEFAULT targets
> >>>>>>>>> - implement init_cfg
> >>>>>>>>> - minor style changes as suggested by Laurent
> >>>>>>>>> - test with 1 data lane
> >>>>>>>>>
> >>>>>>>>> Thanks
> >>>>>>>>>         j
> >>>>>>>>>
> >>>>>>>>> Jacopo Mondi (23):
> >>>>>>>>>        media: ov5640: Add pixel rate to modes
> >>>>>>>>>        media: ov5604: Re-arrange modes definition
> >>>>>>>>>        media: ov5640: Add ov5640_is_csi2() function
> >>>>>>>>>        media: ov5640: Associate bpp with formats
> >>>>>>>>>        media: ov5640: Add LINK_FREQ control
> >>>>>>>>>        media: ov5640: Update pixel_rate and link_freq
> >>>>>>>>>        media: ov5640: Rework CSI-2 clock tree
> >>>>>>>>>        media: ov5640: Rework timings programming
> >>>>>>>>>        media: ov5640: Fix 720x480 in RGB888 mode
> >>>>>>>>>        media: ov5640: Rework analog crop rectangles
> >>>>>>>>>        media: ov5640: Re-sort per-mode register tables
> >>>>>>>>>        media: ov5640: Remove ov5640_mode_init_data
> >>>>>>>>>        media: ov5640: Add HBLANK control
> >>>>>>>>>        media: ov5640: Add VBLANK control
> >>>>>>>>>        media: ov5640: Fix durations to comply with FPS
> >>>>>>>>>        media: ov5640: Implement init_cfg
> >>>>>>>>>        media: ov5640: Implement get_selection
> >>>>>>>>>        media: ov5640: Limit frame_interval to DVP mode only
> >>>>>>>>>        media: ov5640: Register device properties
> >>>>>>>>>        media: ov5640: Add RGB565_1X16 format
> >>>>>>>>>        media: ov5640: Add RGB888/BGR888 formats
> >>>>>>>>>        media: ov5640: Restrict sizes to mbus code
> >>>>>>>>>        media: ov5640: Adjust format to bpp in s_fmt
> >>>>>>>>>
> >>>>>>>>>       drivers/media/i2c/ov5640.c | 1143 ++++++++++++++++++++++++++----------
> >>>>>>>>>       1 file changed, 830 insertions(+), 313 deletions(-)
> >>>>>>>>>
> >>>>>>>>> --
> >>>>>>>>> 2.35.0
> >>>>>>>>>
> >>>>>>>>
> >>>>>>
> >>>>
> >>
>

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 01/23] media: ov5640: Add pixel rate to modes
  2022-02-20 11:53   ` Laurent Pinchart
@ 2022-02-21 20:14     ` Adam Ford
  2022-02-22  7:48       ` Jacopo Mondi
  0 siblings, 1 reply; 64+ messages in thread
From: Adam Ford @ 2022-02-21 20:14 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Jacopo Mondi, Steve Longerbeam, Sakari Ailus, Hans Verkuil,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	Prabhakar Mahadev Lad, Fabio Estevam, Eugen Hristev,
	Jerome Brunet, Mauro Carvalho Chehab, linux-media

On Sun, Feb 20, 2022 at 5:53 AM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Jacopo,
>
> Thank you for the patch.
>
> On Thu, Feb 10, 2022 at 12:04:36PM +0100, Jacopo Mondi wrote:
> > Add to each mode supported by the sensor the ideal pixel rate, as
> > defined by Table 2.1 in the chip manual.
> >
> > The ideal pixel rate will be used to compute the MIPI CSI-2 clock tree.
> >

I tried this on my imx8mm at a variety of resolutions.  I don't have a
functional display yet, so I couldn't test streaming to a screen, but
I did capture images and encode them into an AVI. From what I can
tell, the exposure seems to handle darker environments better now.
Maybe it's just a placebo effect.  If there are certain resolutions or
formats you want me to test, let me know.

Tested-by: Adam Ford <aford173@gmail.com> #imx8mm-beacon-kit

> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>
> > ---
> >  drivers/media/i2c/ov5640.c | 44 +++++++++++++++++++++++++++++++++++---
> >  1 file changed, 41 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > index db5a19babe67..01f4a075f86e 100644
> > --- a/drivers/media/i2c/ov5640.c
> > +++ b/drivers/media/i2c/ov5640.c
> > @@ -118,6 +118,29 @@ enum ov5640_frame_rate {
> >       OV5640_NUM_FRAMERATES,
> >  };
> >
> > +enum ov5640_pixel_rate_id {
> > +     OV5640_PIXEL_RATE_168M,
> > +     OV5640_PIXEL_RATE_148M,
> > +     OV5640_PIXEL_RATE_124M,
> > +     OV5640_PIXEL_RATE_96M,
> > +     OV5640_PIXEL_RATE_48M,
> > +     OV5640_NUM_PIXEL_RATES,
> > +};
> > +
> > +/*
> > + * The chip manual suggests 24/48/96/192 MHz pixel clocks.
> > + *
> > + * 192MHz exceeds the sysclk limits; use 168MHz as maximum pixel rate for
> > + * full resolution mode @15 FPS.
> > + */
> > +static const u32 ov5640_pixel_rates[] = {
> > +     [OV5640_PIXEL_RATE_168M] = 168000000,
> > +     [OV5640_PIXEL_RATE_148M] = 148000000,
> > +     [OV5640_PIXEL_RATE_124M] = 124000000,
> > +     [OV5640_PIXEL_RATE_96M] = 96000000,
> > +     [OV5640_PIXEL_RATE_48M] = 48000000,
> > +};
> > +
> >  enum ov5640_format_mux {
> >       OV5640_FMT_MUX_YUV422 = 0,
> >       OV5640_FMT_MUX_RGB,
> > @@ -189,6 +212,7 @@ struct reg_value {
> >  struct ov5640_mode_info {
> >       enum ov5640_mode_id id;
> >       enum ov5640_downsize_mode dn_mode;
> > +     enum ov5640_pixel_rate_id pixel_rate;
> >       u32 hact;
> >       u32 htot;
> >       u32 vact;
> > @@ -565,7 +589,9 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
> >
> >  /* power-on sensor init reg table */
> >  static const struct ov5640_mode_info ov5640_mode_init_data = {
> > -     0, SUBSAMPLING, 640, 1896, 480, 984,
> > +     0, SUBSAMPLING,
> > +     OV5640_PIXEL_RATE_96M,
> > +     640, 1896, 480, 984,
> >       ov5640_init_setting_30fps_VGA,
> >       ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
> >       OV5640_30_FPS,
> > @@ -574,51 +600,61 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
> >  static const struct ov5640_mode_info
> >  ov5640_mode_data[OV5640_NUM_MODES] = {
> >       {OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
> > +      OV5640_PIXEL_RATE_48M,
> >        160, 1896, 120, 984,
> >        ov5640_setting_QQVGA_160_120,
> >        ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
> >        OV5640_30_FPS},
> >       {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
> > +      OV5640_PIXEL_RATE_48M,
> >        176, 1896, 144, 984,
> >        ov5640_setting_QCIF_176_144,
> >        ARRAY_SIZE(ov5640_setting_QCIF_176_144),
> >        OV5640_30_FPS},
> >       {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
> > +      OV5640_PIXEL_RATE_48M,
> >        320, 1896, 240, 984,
> >        ov5640_setting_QVGA_320_240,
> >        ARRAY_SIZE(ov5640_setting_QVGA_320_240),
> >        OV5640_30_FPS},
> >       {OV5640_MODE_VGA_640_480, SUBSAMPLING,
> > +      OV5640_PIXEL_RATE_48M,
> >        640, 1896, 480, 1080,
> >        ov5640_setting_VGA_640_480,
> >        ARRAY_SIZE(ov5640_setting_VGA_640_480),
> >        OV5640_60_FPS},
> >       {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
> > +      OV5640_PIXEL_RATE_96M,
> >        720, 1896, 480, 984,
> >        ov5640_setting_NTSC_720_480,
> >        ARRAY_SIZE(ov5640_setting_NTSC_720_480),
> >       OV5640_30_FPS},
> >       {OV5640_MODE_PAL_720_576, SUBSAMPLING,
> > +      OV5640_PIXEL_RATE_96M,
> >        720, 1896, 576, 984,
> >        ov5640_setting_PAL_720_576,
> >        ARRAY_SIZE(ov5640_setting_PAL_720_576),
> >        OV5640_30_FPS},
> >       {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
> > +      OV5640_PIXEL_RATE_96M,
> >        1024, 1896, 768, 1080,
> >        ov5640_setting_XGA_1024_768,
> >        ARRAY_SIZE(ov5640_setting_XGA_1024_768),
> >        OV5640_30_FPS},
> >       {OV5640_MODE_720P_1280_720, SUBSAMPLING,
> > +      OV5640_PIXEL_RATE_124M,
> >        1280, 1892, 720, 740,
> >        ov5640_setting_720P_1280_720,
> >        ARRAY_SIZE(ov5640_setting_720P_1280_720),
> >        OV5640_30_FPS},
> >       {OV5640_MODE_1080P_1920_1080, SCALING,
> > +      OV5640_PIXEL_RATE_148M,
> >        1920, 2500, 1080, 1120,
> >        ov5640_setting_1080P_1920_1080,
> >        ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
> >        OV5640_30_FPS},
> >       {OV5640_MODE_QSXGA_2592_1944, SCALING,
> > +      OV5640_PIXEL_RATE_168M,
> >        2592, 2844, 1944, 1968,
> >        ov5640_setting_QSXGA_2592_1944,
> >        ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
> > @@ -2743,6 +2779,7 @@ static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
> >
> >  static int ov5640_init_controls(struct ov5640_dev *sensor)
> >  {
> > +     const struct ov5640_mode_info *mode = sensor->current_mode;
> >       const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
> >       struct ov5640_ctrls *ctrls = &sensor->ctrls;
> >       struct v4l2_ctrl_handler *hdl = &ctrls->handler;
> > @@ -2755,8 +2792,9 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
> >
> >       /* Clock related controls */
> >       ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
> > -                                           0, INT_MAX, 1,
> > -                                           ov5640_calc_pixel_rate(sensor));
> > +                                   ov5640_pixel_rates[OV5640_NUM_PIXEL_RATES - 1],
> > +                                   ov5640_pixel_rates[0], 1,
> > +                                   ov5640_pixel_rates[mode->pixel_rate]);
> >
> >       /* Auto/manual white balance */
> >       ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
>
> --
> Regards,
>
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 01/23] media: ov5640: Add pixel rate to modes
  2022-02-21 20:14     ` Adam Ford
@ 2022-02-22  7:48       ` Jacopo Mondi
  2022-02-22 19:08         ` Adam Ford
  0 siblings, 1 reply; 64+ messages in thread
From: Jacopo Mondi @ 2022-02-22  7:48 UTC (permalink / raw)
  To: Adam Ford
  Cc: Laurent Pinchart, Steve Longerbeam, Sakari Ailus, Hans Verkuil,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	Prabhakar Mahadev Lad, Fabio Estevam, Eugen Hristev,
	Jerome Brunet, Mauro Carvalho Chehab, linux-media

Hi Adam,

On Mon, Feb 21, 2022 at 02:14:43PM -0600, Adam Ford wrote:
> On Sun, Feb 20, 2022 at 5:53 AM Laurent Pinchart
> <laurent.pinchart@ideasonboard.com> wrote:
> >
> > Hi Jacopo,
> >
> > Thank you for the patch.
> >
> > On Thu, Feb 10, 2022 at 12:04:36PM +0100, Jacopo Mondi wrote:
> > > Add to each mode supported by the sensor the ideal pixel rate, as
> > > defined by Table 2.1 in the chip manual.
> > >
> > > The ideal pixel rate will be used to compute the MIPI CSI-2 clock tree.
> > >
>
> I tried this on my imx8mm at a variety of resolutions.  I don't have a
> functional display yet, so I couldn't test streaming to a screen, but
> I did capture images and encode them into an AVI. From what I can
> tell, the exposure seems to handle darker environments better now.

I noticed the same. Unfortunately I still have to clarify myself how
the auto-exposure target is handled, but yes I noticed the same.

> Maybe it's just a placebo effect.  If there are certain resolutions or
> formats you want me to test, let me know.
>
> Tested-by: Adam Ford <aford173@gmail.com> #imx8mm-beacon-kit
>

Thanks for testing. I was about to send a v3 yesterday but I found out
I need to update all my testing scripts first. There's RGB888 which
has weird colors here, and I never tested JPEG. Do you happen to know
if it's working with this driver ?

Thanks!
   j

> > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> >
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >
> > > ---
> > >  drivers/media/i2c/ov5640.c | 44 +++++++++++++++++++++++++++++++++++---
> > >  1 file changed, 41 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > > index db5a19babe67..01f4a075f86e 100644
> > > --- a/drivers/media/i2c/ov5640.c
> > > +++ b/drivers/media/i2c/ov5640.c
> > > @@ -118,6 +118,29 @@ enum ov5640_frame_rate {
> > >       OV5640_NUM_FRAMERATES,
> > >  };
> > >
> > > +enum ov5640_pixel_rate_id {
> > > +     OV5640_PIXEL_RATE_168M,
> > > +     OV5640_PIXEL_RATE_148M,
> > > +     OV5640_PIXEL_RATE_124M,
> > > +     OV5640_PIXEL_RATE_96M,
> > > +     OV5640_PIXEL_RATE_48M,
> > > +     OV5640_NUM_PIXEL_RATES,
> > > +};
> > > +
> > > +/*
> > > + * The chip manual suggests 24/48/96/192 MHz pixel clocks.
> > > + *
> > > + * 192MHz exceeds the sysclk limits; use 168MHz as maximum pixel rate for
> > > + * full resolution mode @15 FPS.
> > > + */
> > > +static const u32 ov5640_pixel_rates[] = {
> > > +     [OV5640_PIXEL_RATE_168M] = 168000000,
> > > +     [OV5640_PIXEL_RATE_148M] = 148000000,
> > > +     [OV5640_PIXEL_RATE_124M] = 124000000,
> > > +     [OV5640_PIXEL_RATE_96M] = 96000000,
> > > +     [OV5640_PIXEL_RATE_48M] = 48000000,
> > > +};
> > > +
> > >  enum ov5640_format_mux {
> > >       OV5640_FMT_MUX_YUV422 = 0,
> > >       OV5640_FMT_MUX_RGB,
> > > @@ -189,6 +212,7 @@ struct reg_value {
> > >  struct ov5640_mode_info {
> > >       enum ov5640_mode_id id;
> > >       enum ov5640_downsize_mode dn_mode;
> > > +     enum ov5640_pixel_rate_id pixel_rate;
> > >       u32 hact;
> > >       u32 htot;
> > >       u32 vact;
> > > @@ -565,7 +589,9 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
> > >
> > >  /* power-on sensor init reg table */
> > >  static const struct ov5640_mode_info ov5640_mode_init_data = {
> > > -     0, SUBSAMPLING, 640, 1896, 480, 984,
> > > +     0, SUBSAMPLING,
> > > +     OV5640_PIXEL_RATE_96M,
> > > +     640, 1896, 480, 984,
> > >       ov5640_init_setting_30fps_VGA,
> > >       ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
> > >       OV5640_30_FPS,
> > > @@ -574,51 +600,61 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
> > >  static const struct ov5640_mode_info
> > >  ov5640_mode_data[OV5640_NUM_MODES] = {
> > >       {OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
> > > +      OV5640_PIXEL_RATE_48M,
> > >        160, 1896, 120, 984,
> > >        ov5640_setting_QQVGA_160_120,
> > >        ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
> > >        OV5640_30_FPS},
> > >       {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
> > > +      OV5640_PIXEL_RATE_48M,
> > >        176, 1896, 144, 984,
> > >        ov5640_setting_QCIF_176_144,
> > >        ARRAY_SIZE(ov5640_setting_QCIF_176_144),
> > >        OV5640_30_FPS},
> > >       {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
> > > +      OV5640_PIXEL_RATE_48M,
> > >        320, 1896, 240, 984,
> > >        ov5640_setting_QVGA_320_240,
> > >        ARRAY_SIZE(ov5640_setting_QVGA_320_240),
> > >        OV5640_30_FPS},
> > >       {OV5640_MODE_VGA_640_480, SUBSAMPLING,
> > > +      OV5640_PIXEL_RATE_48M,
> > >        640, 1896, 480, 1080,
> > >        ov5640_setting_VGA_640_480,
> > >        ARRAY_SIZE(ov5640_setting_VGA_640_480),
> > >        OV5640_60_FPS},
> > >       {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
> > > +      OV5640_PIXEL_RATE_96M,
> > >        720, 1896, 480, 984,
> > >        ov5640_setting_NTSC_720_480,
> > >        ARRAY_SIZE(ov5640_setting_NTSC_720_480),
> > >       OV5640_30_FPS},
> > >       {OV5640_MODE_PAL_720_576, SUBSAMPLING,
> > > +      OV5640_PIXEL_RATE_96M,
> > >        720, 1896, 576, 984,
> > >        ov5640_setting_PAL_720_576,
> > >        ARRAY_SIZE(ov5640_setting_PAL_720_576),
> > >        OV5640_30_FPS},
> > >       {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
> > > +      OV5640_PIXEL_RATE_96M,
> > >        1024, 1896, 768, 1080,
> > >        ov5640_setting_XGA_1024_768,
> > >        ARRAY_SIZE(ov5640_setting_XGA_1024_768),
> > >        OV5640_30_FPS},
> > >       {OV5640_MODE_720P_1280_720, SUBSAMPLING,
> > > +      OV5640_PIXEL_RATE_124M,
> > >        1280, 1892, 720, 740,
> > >        ov5640_setting_720P_1280_720,
> > >        ARRAY_SIZE(ov5640_setting_720P_1280_720),
> > >        OV5640_30_FPS},
> > >       {OV5640_MODE_1080P_1920_1080, SCALING,
> > > +      OV5640_PIXEL_RATE_148M,
> > >        1920, 2500, 1080, 1120,
> > >        ov5640_setting_1080P_1920_1080,
> > >        ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
> > >        OV5640_30_FPS},
> > >       {OV5640_MODE_QSXGA_2592_1944, SCALING,
> > > +      OV5640_PIXEL_RATE_168M,
> > >        2592, 2844, 1944, 1968,
> > >        ov5640_setting_QSXGA_2592_1944,
> > >        ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
> > > @@ -2743,6 +2779,7 @@ static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
> > >
> > >  static int ov5640_init_controls(struct ov5640_dev *sensor)
> > >  {
> > > +     const struct ov5640_mode_info *mode = sensor->current_mode;
> > >       const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
> > >       struct ov5640_ctrls *ctrls = &sensor->ctrls;
> > >       struct v4l2_ctrl_handler *hdl = &ctrls->handler;
> > > @@ -2755,8 +2792,9 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
> > >
> > >       /* Clock related controls */
> > >       ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
> > > -                                           0, INT_MAX, 1,
> > > -                                           ov5640_calc_pixel_rate(sensor));
> > > +                                   ov5640_pixel_rates[OV5640_NUM_PIXEL_RATES - 1],
> > > +                                   ov5640_pixel_rates[0], 1,
> > > +                                   ov5640_pixel_rates[mode->pixel_rate]);
> > >
> > >       /* Auto/manual white balance */
> > >       ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
> >
> > --
> > Regards,
> >
> > Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

* Re: [PATCH v2 01/23] media: ov5640: Add pixel rate to modes
  2022-02-22  7:48       ` Jacopo Mondi
@ 2022-02-22 19:08         ` Adam Ford
  0 siblings, 0 replies; 64+ messages in thread
From: Adam Ford @ 2022-02-22 19:08 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: Laurent Pinchart, Steve Longerbeam, Sakari Ailus, Hans Verkuil,
	mirela.rabulea, xavier.roumegue, tomi.valkeinen, hugues.fruchet,
	Prabhakar Mahadev Lad, Fabio Estevam, Eugen Hristev,
	Jerome Brunet, Mauro Carvalho Chehab, linux-media

On Tue, Feb 22, 2022 at 1:48 AM Jacopo Mondi <jacopo@jmondi.org> wrote:
>
> Hi Adam,
>
> On Mon, Feb 21, 2022 at 02:14:43PM -0600, Adam Ford wrote:
> > On Sun, Feb 20, 2022 at 5:53 AM Laurent Pinchart
> > <laurent.pinchart@ideasonboard.com> wrote:
> > >
> > > Hi Jacopo,
> > >
> > > Thank you for the patch.
> > >
> > > On Thu, Feb 10, 2022 at 12:04:36PM +0100, Jacopo Mondi wrote:
> > > > Add to each mode supported by the sensor the ideal pixel rate, as
> > > > defined by Table 2.1 in the chip manual.
> > > >
> > > > The ideal pixel rate will be used to compute the MIPI CSI-2 clock tree.
> > > >
> >
> > I tried this on my imx8mm at a variety of resolutions.  I don't have a
> > functional display yet, so I couldn't test streaming to a screen, but
> > I did capture images and encode them into an AVI. From what I can
> > tell, the exposure seems to handle darker environments better now.
>
> I noticed the same. Unfortunately I still have to clarify myself how
> the auto-exposure target is handled, but yes I noticed the same.
>
> > Maybe it's just a placebo effect.  If there are certain resolutions or
> > formats you want me to test, let me know.
> >
> > Tested-by: Adam Ford <aford173@gmail.com> #imx8mm-beacon-kit
> >
>
> Thanks for testing. I was about to send a v3 yesterday but I found out
> I need to update all my testing scripts first. There's RGB888 which
> has weird colors here, and I never tested JPEG. Do you happen to know
> if it's working with this driver ?

I am not sure how to test the JPEG format.  From what I can see, the
8mm doesn't support that video format.  I applied your CSIS series to
Laurent's repo with the ov5640 stuff.  I checked through the tech ref
manual, and it states the CSIS V3.6.3 supports 8 formats of User
defined byte-data packets like JPEG, but I'll have to admit that I'm a
bit out of my knowledge base on how to implement such a thing.

adam
>
> Thanks!
>    j
>
> > > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> > >
> > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > >
> > > > ---
> > > >  drivers/media/i2c/ov5640.c | 44 +++++++++++++++++++++++++++++++++++---
> > > >  1 file changed, 41 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> > > > index db5a19babe67..01f4a075f86e 100644
> > > > --- a/drivers/media/i2c/ov5640.c
> > > > +++ b/drivers/media/i2c/ov5640.c
> > > > @@ -118,6 +118,29 @@ enum ov5640_frame_rate {
> > > >       OV5640_NUM_FRAMERATES,
> > > >  };
> > > >
> > > > +enum ov5640_pixel_rate_id {
> > > > +     OV5640_PIXEL_RATE_168M,
> > > > +     OV5640_PIXEL_RATE_148M,
> > > > +     OV5640_PIXEL_RATE_124M,
> > > > +     OV5640_PIXEL_RATE_96M,
> > > > +     OV5640_PIXEL_RATE_48M,
> > > > +     OV5640_NUM_PIXEL_RATES,
> > > > +};
> > > > +
> > > > +/*
> > > > + * The chip manual suggests 24/48/96/192 MHz pixel clocks.
> > > > + *
> > > > + * 192MHz exceeds the sysclk limits; use 168MHz as maximum pixel rate for
> > > > + * full resolution mode @15 FPS.
> > > > + */
> > > > +static const u32 ov5640_pixel_rates[] = {
> > > > +     [OV5640_PIXEL_RATE_168M] = 168000000,
> > > > +     [OV5640_PIXEL_RATE_148M] = 148000000,
> > > > +     [OV5640_PIXEL_RATE_124M] = 124000000,
> > > > +     [OV5640_PIXEL_RATE_96M] = 96000000,
> > > > +     [OV5640_PIXEL_RATE_48M] = 48000000,
> > > > +};
> > > > +
> > > >  enum ov5640_format_mux {
> > > >       OV5640_FMT_MUX_YUV422 = 0,
> > > >       OV5640_FMT_MUX_RGB,
> > > > @@ -189,6 +212,7 @@ struct reg_value {
> > > >  struct ov5640_mode_info {
> > > >       enum ov5640_mode_id id;
> > > >       enum ov5640_downsize_mode dn_mode;
> > > > +     enum ov5640_pixel_rate_id pixel_rate;
> > > >       u32 hact;
> > > >       u32 htot;
> > > >       u32 vact;
> > > > @@ -565,7 +589,9 @@ static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
> > > >
> > > >  /* power-on sensor init reg table */
> > > >  static const struct ov5640_mode_info ov5640_mode_init_data = {
> > > > -     0, SUBSAMPLING, 640, 1896, 480, 984,
> > > > +     0, SUBSAMPLING,
> > > > +     OV5640_PIXEL_RATE_96M,
> > > > +     640, 1896, 480, 984,
> > > >       ov5640_init_setting_30fps_VGA,
> > > >       ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
> > > >       OV5640_30_FPS,
> > > > @@ -574,51 +600,61 @@ static const struct ov5640_mode_info ov5640_mode_init_data = {
> > > >  static const struct ov5640_mode_info
> > > >  ov5640_mode_data[OV5640_NUM_MODES] = {
> > > >       {OV5640_MODE_QQVGA_160_120, SUBSAMPLING,
> > > > +      OV5640_PIXEL_RATE_48M,
> > > >        160, 1896, 120, 984,
> > > >        ov5640_setting_QQVGA_160_120,
> > > >        ARRAY_SIZE(ov5640_setting_QQVGA_160_120),
> > > >        OV5640_30_FPS},
> > > >       {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
> > > > +      OV5640_PIXEL_RATE_48M,
> > > >        176, 1896, 144, 984,
> > > >        ov5640_setting_QCIF_176_144,
> > > >        ARRAY_SIZE(ov5640_setting_QCIF_176_144),
> > > >        OV5640_30_FPS},
> > > >       {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
> > > > +      OV5640_PIXEL_RATE_48M,
> > > >        320, 1896, 240, 984,
> > > >        ov5640_setting_QVGA_320_240,
> > > >        ARRAY_SIZE(ov5640_setting_QVGA_320_240),
> > > >        OV5640_30_FPS},
> > > >       {OV5640_MODE_VGA_640_480, SUBSAMPLING,
> > > > +      OV5640_PIXEL_RATE_48M,
> > > >        640, 1896, 480, 1080,
> > > >        ov5640_setting_VGA_640_480,
> > > >        ARRAY_SIZE(ov5640_setting_VGA_640_480),
> > > >        OV5640_60_FPS},
> > > >       {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
> > > > +      OV5640_PIXEL_RATE_96M,
> > > >        720, 1896, 480, 984,
> > > >        ov5640_setting_NTSC_720_480,
> > > >        ARRAY_SIZE(ov5640_setting_NTSC_720_480),
> > > >       OV5640_30_FPS},
> > > >       {OV5640_MODE_PAL_720_576, SUBSAMPLING,
> > > > +      OV5640_PIXEL_RATE_96M,
> > > >        720, 1896, 576, 984,
> > > >        ov5640_setting_PAL_720_576,
> > > >        ARRAY_SIZE(ov5640_setting_PAL_720_576),
> > > >        OV5640_30_FPS},
> > > >       {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
> > > > +      OV5640_PIXEL_RATE_96M,
> > > >        1024, 1896, 768, 1080,
> > > >        ov5640_setting_XGA_1024_768,
> > > >        ARRAY_SIZE(ov5640_setting_XGA_1024_768),
> > > >        OV5640_30_FPS},
> > > >       {OV5640_MODE_720P_1280_720, SUBSAMPLING,
> > > > +      OV5640_PIXEL_RATE_124M,
> > > >        1280, 1892, 720, 740,
> > > >        ov5640_setting_720P_1280_720,
> > > >        ARRAY_SIZE(ov5640_setting_720P_1280_720),
> > > >        OV5640_30_FPS},
> > > >       {OV5640_MODE_1080P_1920_1080, SCALING,
> > > > +      OV5640_PIXEL_RATE_148M,
> > > >        1920, 2500, 1080, 1120,
> > > >        ov5640_setting_1080P_1920_1080,
> > > >        ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
> > > >        OV5640_30_FPS},
> > > >       {OV5640_MODE_QSXGA_2592_1944, SCALING,
> > > > +      OV5640_PIXEL_RATE_168M,
> > > >        2592, 2844, 1944, 1968,
> > > >        ov5640_setting_QSXGA_2592_1944,
> > > >        ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
> > > > @@ -2743,6 +2779,7 @@ static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
> > > >
> > > >  static int ov5640_init_controls(struct ov5640_dev *sensor)
> > > >  {
> > > > +     const struct ov5640_mode_info *mode = sensor->current_mode;
> > > >       const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
> > > >       struct ov5640_ctrls *ctrls = &sensor->ctrls;
> > > >       struct v4l2_ctrl_handler *hdl = &ctrls->handler;
> > > > @@ -2755,8 +2792,9 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
> > > >
> > > >       /* Clock related controls */
> > > >       ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
> > > > -                                           0, INT_MAX, 1,
> > > > -                                           ov5640_calc_pixel_rate(sensor));
> > > > +                                   ov5640_pixel_rates[OV5640_NUM_PIXEL_RATES - 1],
> > > > +                                   ov5640_pixel_rates[0], 1,
> > > > +                                   ov5640_pixel_rates[mode->pixel_rate]);
> > > >
> > > >       /* Auto/manual white balance */
> > > >       ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
> > >
> > > --
> > > Regards,
> > >
> > > Laurent Pinchart

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2022-02-22 19:08 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-10 11:04 [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Jacopo Mondi
2022-02-10 11:04 ` [PATCH v2 01/23] media: ov5640: Add pixel rate to modes Jacopo Mondi
2022-02-20 11:53   ` Laurent Pinchart
2022-02-21 20:14     ` Adam Ford
2022-02-22  7:48       ` Jacopo Mondi
2022-02-22 19:08         ` Adam Ford
2022-02-10 11:04 ` [PATCH v2 02/23] media: ov5604: Re-arrange modes definition Jacopo Mondi
2022-02-10 11:04 ` [PATCH v2 03/23] media: ov5640: Add ov5640_is_csi2() function Jacopo Mondi
2022-02-10 11:04 ` [PATCH v2 04/23] media: ov5640: Associate bpp with formats Jacopo Mondi
2022-02-10 11:04 ` [PATCH v2 05/23] media: ov5640: Add LINK_FREQ control Jacopo Mondi
2022-02-20 11:55   ` Laurent Pinchart
2022-02-10 11:04 ` [PATCH v2 06/23] media: ov5640: Update pixel_rate and link_freq Jacopo Mondi
2022-02-10 11:04 ` [PATCH v2 07/23] media: ov5640: Rework CSI-2 clock tree Jacopo Mondi
2022-02-20 12:17   ` Laurent Pinchart
2022-02-21 11:39     ` Jacopo Mondi
2022-02-21 12:12       ` Laurent Pinchart
2022-02-10 11:04 ` [PATCH v2 08/23] media: ov5640: Rework timings programming Jacopo Mondi
2022-02-20 12:44   ` Laurent Pinchart
2022-02-10 11:04 ` [PATCH v2 09/23] media: ov5640: Fix 720x480 in RGB888 mode Jacopo Mondi
2022-02-20 12:50   ` Laurent Pinchart
2022-02-10 11:04 ` [PATCH v2 10/23] media: ov5640: Rework analog crop rectangles Jacopo Mondi
2022-02-11  9:34   ` [v2.1] " Jacopo Mondi
2022-02-20 12:56     ` Laurent Pinchart
2022-02-10 11:04 ` [PATCH v2 11/23] media: ov5640: Re-sort per-mode register tables Jacopo Mondi
2022-02-20 12:52   ` Laurent Pinchart
2022-02-20 12:59     ` Laurent Pinchart
2022-02-10 11:04 ` [PATCH v2 12/23] media: ov5640: Remove ov5640_mode_init_data Jacopo Mondi
2022-02-20 12:58   ` Laurent Pinchart
2022-02-10 11:09 ` [PATCH v2 13/23] media: ov5640: Add HBLANK control Jacopo Mondi
2022-02-10 11:09 ` [PATCH v2 14/23] media: ov5640: Add VBLANK control Jacopo Mondi
2022-02-20 13:01   ` Laurent Pinchart
2022-02-10 11:10 ` [PATCH v2 15/23] media: ov5640: Fix durations to comply with FPS Jacopo Mondi
2022-02-20 13:03   ` Laurent Pinchart
2022-02-10 11:10 ` [PATCH v2 16/23] media: ov5640: Implement init_cfg Jacopo Mondi
2022-02-10 11:10 ` [PATCH v2 17/23] media: ov5640: Implement get_selection Jacopo Mondi
2022-02-20 13:06   ` Laurent Pinchart
2022-02-10 11:10 ` [PATCH v2 18/23] media: ov5640: Limit frame_interval to DVP mode only Jacopo Mondi
2022-02-10 11:10 ` [PATCH v2 19/23] media: ov5640: Register device properties Jacopo Mondi
2022-02-10 11:10 ` [PATCH v2 20/23] media: ov5640: Add RGB565_1X16 format Jacopo Mondi
2022-02-20 13:07   ` Laurent Pinchart
2022-02-10 11:10 ` [PATCH v2 21/23] media: ov5640: Add RGB888/BGR888 formats Jacopo Mondi
2022-02-20 13:13   ` Laurent Pinchart
2022-02-10 11:10 ` [PATCH v2 22/23] media: ov5640: Restrict sizes to mbus code Jacopo Mondi
2022-02-20 13:16   ` Laurent Pinchart
2022-02-21 12:42     ` Jacopo Mondi
2022-02-10 11:10 ` [PATCH v2 23/23] media: ov5640: Adjust format to bpp in s_fmt Jacopo Mondi
2022-02-10 12:03 ` [PATCH v2 00/23] media: ov5640: Rework the clock tree programming for MIPI Tomi Valkeinen
2022-02-10 12:10   ` Tomi Valkeinen
2022-02-10 13:00 ` Tomi Valkeinen
2022-02-10 17:11   ` Jacopo Mondi
2022-02-11  7:55     ` Tomi Valkeinen
2022-02-11  8:01       ` Tomi Valkeinen
2022-02-11  9:36   ` Jacopo Mondi
2022-02-11 10:09 ` Eugen.Hristev
2022-02-11 11:25   ` Jacopo Mondi
2022-02-14 14:06     ` Eugen.Hristev
2022-02-14 14:38       ` Jacopo Mondi
2022-02-14 15:08         ` Eugen.Hristev
2022-02-14 18:56           ` Jacopo Mondi
2022-02-17 14:25             ` Eugen.Hristev
2022-02-21  8:51               ` Jacopo Mondi
2022-02-21  9:04                 ` Eugen.Hristev
2022-02-21 11:18                   ` Jacopo Mondi
2022-02-21 13:31                   ` Jacopo Mondi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.