All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
@ 2022-07-21  8:35 Laurent Pinchart
  2022-07-21  8:35 ` [PATCH 01/19] media: i2c: imx290: Use device lock for the control handler Laurent Pinchart
                   ` (19 more replies)
  0 siblings, 20 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Hello,

This patch series gathers miscellaneous improvements for the imx290
driver. The most notable changes on the kernel side is patch 07/19 that
simplifies register access, and on the userspace API side patches 14/19,
15/19 and 18/19 that extend the driver with controls and selection
rectangles required by libcamera.

Laurent Pinchart (19):
  media: i2c: imx290: Use device lock for the control handler
  media: i2c: imx290: Print error code when I2C transfer fails
  media: i2c: imx290: Specify HMAX values in decimal
  media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
  media: i2c: imx290: Drop imx290_write_buffered_reg()
  media: i2c: imx290: Drop regmap cache
  media: i2c: imx290: Support variable-sized registers
  media: i2c: imx290: Correct register sizes
  media: i2c: imx290: Simplify error handling when writing registers
  media: i2c: imx290: Define more register macros
  media: i2c: imx290: Add exposure time control
  media: i2c: imx290: Fix max gain value
  media: i2c: imx290: Split control initialization to separate function
  media: i2c: imx290: Implement HBLANK and VBLANK controls
  media: i2c: imx290: Create controls for fwnode properties
  media: i2c: imx290: Move registers with fixed value to init array
  media: i2c: imx290: Factor out format retrieval to separate function
  media: i2c: imx290: Add crop selection targets support
  media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN

 drivers/media/i2c/imx290.c | 781 ++++++++++++++++++++++---------------
 1 file changed, 458 insertions(+), 323 deletions(-)

-- 
Regards,

Laurent Pinchart


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

* [PATCH 01/19] media: i2c: imx290: Use device lock for the control handler
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  9:22   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 02/19] media: i2c: imx290: Print error code when I2C transfer fails Laurent Pinchart
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

The link frequency and pixel rate controls are set without holding the
control handler lock, resulting in kernel warnings. As the value of
those controls depend on the format, the simplest fix is to use the
device lock for the control handler.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 99f2a50d39a4..d97a5fb1d501 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -1043,6 +1043,7 @@ static int imx290_probe(struct i2c_client *client)
 	imx290_entity_init_cfg(&imx290->sd, NULL);
 
 	v4l2_ctrl_handler_init(&imx290->ctrls, 4);
+	imx290->ctrls.lock = &imx290->lock;
 
 	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
 			  V4L2_CID_GAIN, 0, 72, 1, 0);
-- 
Regards,

Laurent Pinchart


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

* [PATCH 02/19] media: i2c: imx290: Print error code when I2C transfer fails
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
  2022-07-21  8:35 ` [PATCH 01/19] media: i2c: imx290: Use device lock for the control handler Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  9:23   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal Laurent Pinchart
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Knowing why I2C transfers fail is useful for debugging. Extend the error
message to print the error code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index d97a5fb1d501..64bd43813dbf 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -370,7 +370,8 @@ static inline int __always_unused imx290_read_reg(struct imx290 *imx290, u16 add
 
 	ret = regmap_read(imx290->regmap, addr, &regval);
 	if (ret) {
-		dev_err(imx290->dev, "I2C read failed for addr: %x\n", addr);
+		dev_err(imx290->dev, "Failed to read register 0x%04x: %d\n",
+			addr, ret);
 		return ret;
 	}
 
@@ -385,7 +386,8 @@ static int imx290_write_reg(struct imx290 *imx290, u16 addr, u8 value)
 
 	ret = regmap_write(imx290->regmap, addr, value);
 	if (ret) {
-		dev_err(imx290->dev, "I2C write failed for addr: %x\n", addr);
+		dev_err(imx290->dev, "Failed to write register 0x%04x: %d\n",
+			addr, ret);
 		return ret;
 	}
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
  2022-07-21  8:35 ` [PATCH 01/19] media: i2c: imx290: Use device lock for the control handler Laurent Pinchart
  2022-07-21  8:35 ` [PATCH 02/19] media: i2c: imx290: Print error code when I2C transfer fails Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  9:18   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 04/19] media: i2c: imx290: Replace macro with explicit ARRAY_SIZE() Laurent Pinchart
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

The HMAX value specifies the total line length in pixels. It's thus more
readable in decimal than hexadecimal. Fix it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 64bd43813dbf..f60a4135dc9c 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -308,7 +308,7 @@ static const struct imx290_mode imx290_modes_2lanes[] = {
 	{
 		.width = 1920,
 		.height = 1080,
-		.hmax = 0x1130,
+		.hmax = 4400,
 		.link_freq_index = FREQ_INDEX_1080P,
 		.data = imx290_1080p_settings,
 		.data_size = ARRAY_SIZE(imx290_1080p_settings),
@@ -316,7 +316,7 @@ static const struct imx290_mode imx290_modes_2lanes[] = {
 	{
 		.width = 1280,
 		.height = 720,
-		.hmax = 0x19c8,
+		.hmax = 6600,
 		.link_freq_index = FREQ_INDEX_720P,
 		.data = imx290_720p_settings,
 		.data_size = ARRAY_SIZE(imx290_720p_settings),
@@ -327,7 +327,7 @@ static const struct imx290_mode imx290_modes_4lanes[] = {
 	{
 		.width = 1920,
 		.height = 1080,
-		.hmax = 0x0898,
+		.hmax = 2200,
 		.link_freq_index = FREQ_INDEX_1080P,
 		.data = imx290_1080p_settings,
 		.data_size = ARRAY_SIZE(imx290_1080p_settings),
@@ -335,7 +335,7 @@ static const struct imx290_mode imx290_modes_4lanes[] = {
 	{
 		.width = 1280,
 		.height = 720,
-		.hmax = 0x0ce4,
+		.hmax = 3300,
 		.link_freq_index = FREQ_INDEX_720P,
 		.data = imx290_720p_settings,
 		.data_size = ARRAY_SIZE(imx290_720p_settings),
-- 
Regards,

Laurent Pinchart


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

* [PATCH 04/19] media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (2 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  9:23   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 05/19] media: i2c: imx290: Drop imx290_write_buffered_reg() Laurent Pinchart
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Use ARRAY_SIZE(imx290->supplies) for code that needs the size of the
array, instead of relying on the IMX290_NUM_SUPPLIES. The result is less
error-prone as it ties the size to the array.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index f60a4135dc9c..9a0c458a3af0 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -790,10 +790,10 @@ static int imx290_get_regulators(struct device *dev, struct imx290 *imx290)
 {
 	unsigned int i;
 
-	for (i = 0; i < IMX290_NUM_SUPPLIES; i++)
+	for (i = 0; i < ARRAY_SIZE(imx290->supplies); i++)
 		imx290->supplies[i].supply = imx290_supply_name[i];
 
-	return devm_regulator_bulk_get(dev, IMX290_NUM_SUPPLIES,
+	return devm_regulator_bulk_get(dev, ARRAY_SIZE(imx290->supplies),
 				       imx290->supplies);
 }
 
@@ -852,7 +852,8 @@ static int imx290_power_on(struct device *dev)
 		return ret;
 	}
 
-	ret = regulator_bulk_enable(IMX290_NUM_SUPPLIES, imx290->supplies);
+	ret = regulator_bulk_enable(ARRAY_SIZE(imx290->supplies),
+				    imx290->supplies);
 	if (ret) {
 		dev_err(dev, "Failed to enable regulators\n");
 		clk_disable_unprepare(imx290->xclk);
@@ -876,7 +877,7 @@ static int imx290_power_off(struct device *dev)
 
 	clk_disable_unprepare(imx290->xclk);
 	gpiod_set_value_cansleep(imx290->rst_gpio, 1);
-	regulator_bulk_disable(IMX290_NUM_SUPPLIES, imx290->supplies);
+	regulator_bulk_disable(ARRAY_SIZE(imx290->supplies), imx290->supplies);
 
 	return 0;
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH 05/19] media: i2c: imx290: Drop imx290_write_buffered_reg()
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (3 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 04/19] media: i2c: imx290: Replace macro with explicit ARRAY_SIZE() Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  9:24   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 06/19] media: i2c: imx290: Drop regmap cache Laurent Pinchart
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

The imx290_write_buffered_reg() function wraps a register write with
register hold, to enable changing multiple registers synchronously. It
is used for the gain only, which is an 8-bit register, defeating its
purpose.

The feature is useful, but should be implemented differently. Drop the
function for now, to prepare for a rework of register access.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 32 +-------------------------------
 1 file changed, 1 insertion(+), 31 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 9a0c458a3af0..f280ded2dac3 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -413,41 +413,11 @@ static int imx290_set_register_array(struct imx290 *imx290,
 	return 0;
 }
 
-static int imx290_write_buffered_reg(struct imx290 *imx290, u16 address_low,
-				     u8 nr_regs, u32 value)
-{
-	unsigned int i;
-	int ret;
-
-	ret = imx290_write_reg(imx290, IMX290_REGHOLD, 0x01);
-	if (ret) {
-		dev_err(imx290->dev, "Error setting hold register\n");
-		return ret;
-	}
-
-	for (i = 0; i < nr_regs; i++) {
-		ret = imx290_write_reg(imx290, address_low + i,
-				       (u8)(value >> (i * 8)));
-		if (ret) {
-			dev_err(imx290->dev, "Error writing buffered registers\n");
-			return ret;
-		}
-	}
-
-	ret = imx290_write_reg(imx290, IMX290_REGHOLD, 0x00);
-	if (ret) {
-		dev_err(imx290->dev, "Error setting hold register\n");
-		return ret;
-	}
-
-	return ret;
-}
-
 static int imx290_set_gain(struct imx290 *imx290, u32 value)
 {
 	int ret;
 
-	ret = imx290_write_buffered_reg(imx290, IMX290_GAIN, 1, value);
+	ret = imx290_write_reg(imx290, IMX290_GAIN, value);
 	if (ret)
 		dev_err(imx290->dev, "Unable to write gain\n");
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH 06/19] media: i2c: imx290: Drop regmap cache
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (4 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 05/19] media: i2c: imx290: Drop imx290_write_buffered_reg() Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  9:27   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 07/19] media: i2c: imx290: Support variable-sized registers Laurent Pinchart
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Only two registers are ever read, and once only. There's no need to
cache values.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index f280ded2dac3..711282126c34 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -97,7 +97,6 @@ static const struct imx290_pixfmt imx290_formats[] = {
 static const struct regmap_config imx290_regmap_config = {
 	.reg_bits = 16,
 	.val_bits = 8,
-	.cache_type = REGCACHE_RBTREE,
 };
 
 static const char * const imx290_test_pattern_menu[] = {
-- 
Regards,

Laurent Pinchart


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

* [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (5 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 06/19] media: i2c: imx290: Drop regmap cache Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  9:43   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 08/19] media: i2c: imx290: Correct register sizes Laurent Pinchart
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

The IMX290 has registers of different sizes. To simplify the code,
handle this in the read/write functions instead of in the callers by
encoding the register size in the symbolic name macros. All registers
are defined as 8-bit for now, a subsequent change will move to larger
registers where applicable.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 352 +++++++++++++++++++------------------
 1 file changed, 180 insertions(+), 172 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 711282126c34..ac58bfe6db7f 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -22,22 +22,28 @@
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
-#define IMX290_STANDBY 0x3000
-#define IMX290_REGHOLD 0x3001
-#define IMX290_XMSTA 0x3002
-#define IMX290_FR_FDG_SEL 0x3009
-#define IMX290_BLKLEVEL_LOW 0x300a
-#define IMX290_BLKLEVEL_HIGH 0x300b
-#define IMX290_GAIN 0x3014
-#define IMX290_HMAX_LOW 0x301c
-#define IMX290_HMAX_HIGH 0x301d
-#define IMX290_PGCTRL 0x308c
-#define IMX290_PHY_LANE_NUM 0x3407
-#define IMX290_CSI_LANE_MODE 0x3443
+#define IMX290_REG_8BIT(n)				((1 << 16) | (n))
+#define IMX290_REG_16BIT(n)				((2 << 16) | (n))
+#define IMX290_REG_24BIT(n)				((3 << 16) | (n))
+#define IMX290_REG_SIZE_SHIFT				16
+#define IMX290_REG_ADDR_MASK				0xffff
 
-#define IMX290_PGCTRL_REGEN BIT(0)
-#define IMX290_PGCTRL_THRU BIT(1)
-#define IMX290_PGCTRL_MODE(n) ((n) << 4)
+#define IMX290_STANDBY					IMX290_REG_8BIT(0x3000)
+#define IMX290_REGHOLD					IMX290_REG_8BIT(0x3001)
+#define IMX290_XMSTA					IMX290_REG_8BIT(0x3002)
+#define IMX290_FR_FDG_SEL				IMX290_REG_8BIT(0x3009)
+#define IMX290_BLKLEVEL_LOW				IMX290_REG_8BIT(0x300a)
+#define IMX290_BLKLEVEL_HIGH				IMX290_REG_8BIT(0x300b)
+#define IMX290_GAIN					IMX290_REG_8BIT(0x3014)
+#define IMX290_HMAX_LOW					IMX290_REG_8BIT(0x301c)
+#define IMX290_HMAX_HIGH				IMX290_REG_8BIT(0x301d)
+#define IMX290_PGCTRL					IMX290_REG_8BIT(0x308c)
+#define IMX290_PHY_LANE_NUM				IMX290_REG_8BIT(0x3407)
+#define IMX290_CSI_LANE_MODE				IMX290_REG_8BIT(0x3443)
+
+#define IMX290_PGCTRL_REGEN				BIT(0)
+#define IMX290_PGCTRL_THRU				BIT(1)
+#define IMX290_PGCTRL_MODE(n)				((n) << 4)
 
 static const char * const imx290_supply_name[] = {
 	"vdda",
@@ -48,7 +54,7 @@ static const char * const imx290_supply_name[] = {
 #define IMX290_NUM_SUPPLIES ARRAY_SIZE(imx290_supply_name)
 
 struct imx290_regval {
-	u16 reg;
+	u32 reg;
 	u8 val;
 };
 
@@ -111,163 +117,163 @@ static const char * const imx290_test_pattern_menu[] = {
 };
 
 static const struct imx290_regval imx290_global_init_settings[] = {
-	{ 0x3007, 0x00 },
-	{ 0x3018, 0x65 },
-	{ 0x3019, 0x04 },
-	{ 0x301a, 0x00 },
-	{ 0x3444, 0x20 },
-	{ 0x3445, 0x25 },
-	{ 0x303a, 0x0c },
-	{ 0x3040, 0x00 },
-	{ 0x3041, 0x00 },
-	{ 0x303c, 0x00 },
-	{ 0x303d, 0x00 },
-	{ 0x3042, 0x9c },
-	{ 0x3043, 0x07 },
-	{ 0x303e, 0x49 },
-	{ 0x303f, 0x04 },
-	{ 0x304b, 0x0a },
-	{ 0x300f, 0x00 },
-	{ 0x3010, 0x21 },
-	{ 0x3012, 0x64 },
-	{ 0x3016, 0x09 },
-	{ 0x3070, 0x02 },
-	{ 0x3071, 0x11 },
-	{ 0x309b, 0x10 },
-	{ 0x309c, 0x22 },
-	{ 0x30a2, 0x02 },
-	{ 0x30a6, 0x20 },
-	{ 0x30a8, 0x20 },
-	{ 0x30aa, 0x20 },
-	{ 0x30ac, 0x20 },
-	{ 0x30b0, 0x43 },
-	{ 0x3119, 0x9e },
-	{ 0x311c, 0x1e },
-	{ 0x311e, 0x08 },
-	{ 0x3128, 0x05 },
-	{ 0x313d, 0x83 },
-	{ 0x3150, 0x03 },
-	{ 0x317e, 0x00 },
-	{ 0x32b8, 0x50 },
-	{ 0x32b9, 0x10 },
-	{ 0x32ba, 0x00 },
-	{ 0x32bb, 0x04 },
-	{ 0x32c8, 0x50 },
-	{ 0x32c9, 0x10 },
-	{ 0x32ca, 0x00 },
-	{ 0x32cb, 0x04 },
-	{ 0x332c, 0xd3 },
-	{ 0x332d, 0x10 },
-	{ 0x332e, 0x0d },
-	{ 0x3358, 0x06 },
-	{ 0x3359, 0xe1 },
-	{ 0x335a, 0x11 },
-	{ 0x3360, 0x1e },
-	{ 0x3361, 0x61 },
-	{ 0x3362, 0x10 },
-	{ 0x33b0, 0x50 },
-	{ 0x33b2, 0x1a },
-	{ 0x33b3, 0x04 },
+	{ IMX290_REG_8BIT(0x3007), 0x00 },
+	{ IMX290_REG_8BIT(0x3018), 0x65 },
+	{ IMX290_REG_8BIT(0x3019), 0x04 },
+	{ IMX290_REG_8BIT(0x301a), 0x00 },
+	{ IMX290_REG_8BIT(0x3444), 0x20 },
+	{ IMX290_REG_8BIT(0x3445), 0x25 },
+	{ IMX290_REG_8BIT(0x303a), 0x0c },
+	{ IMX290_REG_8BIT(0x3040), 0x00 },
+	{ IMX290_REG_8BIT(0x3041), 0x00 },
+	{ IMX290_REG_8BIT(0x303c), 0x00 },
+	{ IMX290_REG_8BIT(0x303d), 0x00 },
+	{ IMX290_REG_8BIT(0x3042), 0x9c },
+	{ IMX290_REG_8BIT(0x3043), 0x07 },
+	{ IMX290_REG_8BIT(0x303e), 0x49 },
+	{ IMX290_REG_8BIT(0x303f), 0x04 },
+	{ IMX290_REG_8BIT(0x304b), 0x0a },
+	{ IMX290_REG_8BIT(0x300f), 0x00 },
+	{ IMX290_REG_8BIT(0x3010), 0x21 },
+	{ IMX290_REG_8BIT(0x3012), 0x64 },
+	{ IMX290_REG_8BIT(0x3016), 0x09 },
+	{ IMX290_REG_8BIT(0x3070), 0x02 },
+	{ IMX290_REG_8BIT(0x3071), 0x11 },
+	{ IMX290_REG_8BIT(0x309b), 0x10 },
+	{ IMX290_REG_8BIT(0x309c), 0x22 },
+	{ IMX290_REG_8BIT(0x30a2), 0x02 },
+	{ IMX290_REG_8BIT(0x30a6), 0x20 },
+	{ IMX290_REG_8BIT(0x30a8), 0x20 },
+	{ IMX290_REG_8BIT(0x30aa), 0x20 },
+	{ IMX290_REG_8BIT(0x30ac), 0x20 },
+	{ IMX290_REG_8BIT(0x30b0), 0x43 },
+	{ IMX290_REG_8BIT(0x3119), 0x9e },
+	{ IMX290_REG_8BIT(0x311c), 0x1e },
+	{ IMX290_REG_8BIT(0x311e), 0x08 },
+	{ IMX290_REG_8BIT(0x3128), 0x05 },
+	{ IMX290_REG_8BIT(0x313d), 0x83 },
+	{ IMX290_REG_8BIT(0x3150), 0x03 },
+	{ IMX290_REG_8BIT(0x317e), 0x00 },
+	{ IMX290_REG_8BIT(0x32b8), 0x50 },
+	{ IMX290_REG_8BIT(0x32b9), 0x10 },
+	{ IMX290_REG_8BIT(0x32ba), 0x00 },
+	{ IMX290_REG_8BIT(0x32bb), 0x04 },
+	{ IMX290_REG_8BIT(0x32c8), 0x50 },
+	{ IMX290_REG_8BIT(0x32c9), 0x10 },
+	{ IMX290_REG_8BIT(0x32ca), 0x00 },
+	{ IMX290_REG_8BIT(0x32cb), 0x04 },
+	{ IMX290_REG_8BIT(0x332c), 0xd3 },
+	{ IMX290_REG_8BIT(0x332d), 0x10 },
+	{ IMX290_REG_8BIT(0x332e), 0x0d },
+	{ IMX290_REG_8BIT(0x3358), 0x06 },
+	{ IMX290_REG_8BIT(0x3359), 0xe1 },
+	{ IMX290_REG_8BIT(0x335a), 0x11 },
+	{ IMX290_REG_8BIT(0x3360), 0x1e },
+	{ IMX290_REG_8BIT(0x3361), 0x61 },
+	{ IMX290_REG_8BIT(0x3362), 0x10 },
+	{ IMX290_REG_8BIT(0x33b0), 0x50 },
+	{ IMX290_REG_8BIT(0x33b2), 0x1a },
+	{ IMX290_REG_8BIT(0x33b3), 0x04 },
 };
 
 static const struct imx290_regval imx290_1080p_settings[] = {
 	/* mode settings */
-	{ 0x3007, 0x00 },
-	{ 0x303a, 0x0c },
-	{ 0x3414, 0x0a },
-	{ 0x3472, 0x80 },
-	{ 0x3473, 0x07 },
-	{ 0x3418, 0x38 },
-	{ 0x3419, 0x04 },
-	{ 0x3012, 0x64 },
-	{ 0x3013, 0x00 },
-	{ 0x305c, 0x18 },
-	{ 0x305d, 0x03 },
-	{ 0x305e, 0x20 },
-	{ 0x305f, 0x01 },
-	{ 0x315e, 0x1a },
-	{ 0x3164, 0x1a },
-	{ 0x3480, 0x49 },
+	{ IMX290_REG_8BIT(0x3007), 0x00 },
+	{ IMX290_REG_8BIT(0x303a), 0x0c },
+	{ IMX290_REG_8BIT(0x3414), 0x0a },
+	{ IMX290_REG_8BIT(0x3472), 0x80 },
+	{ IMX290_REG_8BIT(0x3473), 0x07 },
+	{ IMX290_REG_8BIT(0x3418), 0x38 },
+	{ IMX290_REG_8BIT(0x3419), 0x04 },
+	{ IMX290_REG_8BIT(0x3012), 0x64 },
+	{ IMX290_REG_8BIT(0x3013), 0x00 },
+	{ IMX290_REG_8BIT(0x305c), 0x18 },
+	{ IMX290_REG_8BIT(0x305d), 0x03 },
+	{ IMX290_REG_8BIT(0x305e), 0x20 },
+	{ IMX290_REG_8BIT(0x305f), 0x01 },
+	{ IMX290_REG_8BIT(0x315e), 0x1a },
+	{ IMX290_REG_8BIT(0x3164), 0x1a },
+	{ IMX290_REG_8BIT(0x3480), 0x49 },
 	/* data rate settings */
-	{ 0x3405, 0x10 },
-	{ 0x3446, 0x57 },
-	{ 0x3447, 0x00 },
-	{ 0x3448, 0x37 },
-	{ 0x3449, 0x00 },
-	{ 0x344a, 0x1f },
-	{ 0x344b, 0x00 },
-	{ 0x344c, 0x1f },
-	{ 0x344d, 0x00 },
-	{ 0x344e, 0x1f },
-	{ 0x344f, 0x00 },
-	{ 0x3450, 0x77 },
-	{ 0x3451, 0x00 },
-	{ 0x3452, 0x1f },
-	{ 0x3453, 0x00 },
-	{ 0x3454, 0x17 },
-	{ 0x3455, 0x00 },
+	{ IMX290_REG_8BIT(0x3405), 0x10 },
+	{ IMX290_REG_8BIT(0x3446), 0x57 },
+	{ IMX290_REG_8BIT(0x3447), 0x00 },
+	{ IMX290_REG_8BIT(0x3448), 0x37 },
+	{ IMX290_REG_8BIT(0x3449), 0x00 },
+	{ IMX290_REG_8BIT(0x344a), 0x1f },
+	{ IMX290_REG_8BIT(0x344b), 0x00 },
+	{ IMX290_REG_8BIT(0x344c), 0x1f },
+	{ IMX290_REG_8BIT(0x344d), 0x00 },
+	{ IMX290_REG_8BIT(0x344e), 0x1f },
+	{ IMX290_REG_8BIT(0x344f), 0x00 },
+	{ IMX290_REG_8BIT(0x3450), 0x77 },
+	{ IMX290_REG_8BIT(0x3451), 0x00 },
+	{ IMX290_REG_8BIT(0x3452), 0x1f },
+	{ IMX290_REG_8BIT(0x3453), 0x00 },
+	{ IMX290_REG_8BIT(0x3454), 0x17 },
+	{ IMX290_REG_8BIT(0x3455), 0x00 },
 };
 
 static const struct imx290_regval imx290_720p_settings[] = {
 	/* mode settings */
-	{ 0x3007, 0x10 },
-	{ 0x303a, 0x06 },
-	{ 0x3414, 0x04 },
-	{ 0x3472, 0x00 },
-	{ 0x3473, 0x05 },
-	{ 0x3418, 0xd0 },
-	{ 0x3419, 0x02 },
-	{ 0x3012, 0x64 },
-	{ 0x3013, 0x00 },
-	{ 0x305c, 0x20 },
-	{ 0x305d, 0x00 },
-	{ 0x305e, 0x20 },
-	{ 0x305f, 0x01 },
-	{ 0x315e, 0x1a },
-	{ 0x3164, 0x1a },
-	{ 0x3480, 0x49 },
+	{ IMX290_REG_8BIT(0x3007), 0x10 },
+	{ IMX290_REG_8BIT(0x303a), 0x06 },
+	{ IMX290_REG_8BIT(0x3414), 0x04 },
+	{ IMX290_REG_8BIT(0x3472), 0x00 },
+	{ IMX290_REG_8BIT(0x3473), 0x05 },
+	{ IMX290_REG_8BIT(0x3418), 0xd0 },
+	{ IMX290_REG_8BIT(0x3419), 0x02 },
+	{ IMX290_REG_8BIT(0x3012), 0x64 },
+	{ IMX290_REG_8BIT(0x3013), 0x00 },
+	{ IMX290_REG_8BIT(0x305c), 0x20 },
+	{ IMX290_REG_8BIT(0x305d), 0x00 },
+	{ IMX290_REG_8BIT(0x305e), 0x20 },
+	{ IMX290_REG_8BIT(0x305f), 0x01 },
+	{ IMX290_REG_8BIT(0x315e), 0x1a },
+	{ IMX290_REG_8BIT(0x3164), 0x1a },
+	{ IMX290_REG_8BIT(0x3480), 0x49 },
 	/* data rate settings */
-	{ 0x3405, 0x10 },
-	{ 0x3446, 0x4f },
-	{ 0x3447, 0x00 },
-	{ 0x3448, 0x2f },
-	{ 0x3449, 0x00 },
-	{ 0x344a, 0x17 },
-	{ 0x344b, 0x00 },
-	{ 0x344c, 0x17 },
-	{ 0x344d, 0x00 },
-	{ 0x344e, 0x17 },
-	{ 0x344f, 0x00 },
-	{ 0x3450, 0x57 },
-	{ 0x3451, 0x00 },
-	{ 0x3452, 0x17 },
-	{ 0x3453, 0x00 },
-	{ 0x3454, 0x17 },
-	{ 0x3455, 0x00 },
+	{ IMX290_REG_8BIT(0x3405), 0x10 },
+	{ IMX290_REG_8BIT(0x3446), 0x4f },
+	{ IMX290_REG_8BIT(0x3447), 0x00 },
+	{ IMX290_REG_8BIT(0x3448), 0x2f },
+	{ IMX290_REG_8BIT(0x3449), 0x00 },
+	{ IMX290_REG_8BIT(0x344a), 0x17 },
+	{ IMX290_REG_8BIT(0x344b), 0x00 },
+	{ IMX290_REG_8BIT(0x344c), 0x17 },
+	{ IMX290_REG_8BIT(0x344d), 0x00 },
+	{ IMX290_REG_8BIT(0x344e), 0x17 },
+	{ IMX290_REG_8BIT(0x344f), 0x00 },
+	{ IMX290_REG_8BIT(0x3450), 0x57 },
+	{ IMX290_REG_8BIT(0x3451), 0x00 },
+	{ IMX290_REG_8BIT(0x3452), 0x17 },
+	{ IMX290_REG_8BIT(0x3453), 0x00 },
+	{ IMX290_REG_8BIT(0x3454), 0x17 },
+	{ IMX290_REG_8BIT(0x3455), 0x00 },
 };
 
 static const struct imx290_regval imx290_10bit_settings[] = {
-	{ 0x3005, 0x00},
-	{ 0x3046, 0x00},
-	{ 0x3129, 0x1d},
-	{ 0x317c, 0x12},
-	{ 0x31ec, 0x37},
-	{ 0x3441, 0x0a},
-	{ 0x3442, 0x0a},
-	{ 0x300a, 0x3c},
-	{ 0x300b, 0x00},
+	{ IMX290_REG_8BIT(0x3005), 0x00},
+	{ IMX290_REG_8BIT(0x3046), 0x00},
+	{ IMX290_REG_8BIT(0x3129), 0x1d},
+	{ IMX290_REG_8BIT(0x317c), 0x12},
+	{ IMX290_REG_8BIT(0x31ec), 0x37},
+	{ IMX290_REG_8BIT(0x3441), 0x0a},
+	{ IMX290_REG_8BIT(0x3442), 0x0a},
+	{ IMX290_REG_8BIT(0x300a), 0x3c},
+	{ IMX290_REG_8BIT(0x300b), 0x00},
 };
 
 static const struct imx290_regval imx290_12bit_settings[] = {
-	{ 0x3005, 0x01 },
-	{ 0x3046, 0x01 },
-	{ 0x3129, 0x00 },
-	{ 0x317c, 0x00 },
-	{ 0x31ec, 0x0e },
-	{ 0x3441, 0x0c },
-	{ 0x3442, 0x0c },
-	{ 0x300a, 0xf0 },
-	{ 0x300b, 0x00 },
+	{ IMX290_REG_8BIT(0x3005), 0x01 },
+	{ IMX290_REG_8BIT(0x3046), 0x01 },
+	{ IMX290_REG_8BIT(0x3129), 0x00 },
+	{ IMX290_REG_8BIT(0x317c), 0x00 },
+	{ IMX290_REG_8BIT(0x31ec), 0x0e },
+	{ IMX290_REG_8BIT(0x3441), 0x0c },
+	{ IMX290_REG_8BIT(0x3442), 0x0c },
+	{ IMX290_REG_8BIT(0x300a), 0xf0 },
+	{ IMX290_REG_8BIT(0x300b), 0x00 },
 };
 
 /* supported link frequencies */
@@ -362,33 +368,35 @@ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
 	return container_of(_sd, struct imx290, sd);
 }
 
-static inline int __always_unused imx290_read_reg(struct imx290 *imx290, u16 addr, u8 *value)
+static int __always_unused imx290_read_reg(struct imx290 *imx290, u32 addr, u32 *value)
 {
-	unsigned int regval;
+	u8 data[3] = { 0, 0, 0 };
 	int ret;
 
-	ret = regmap_read(imx290->regmap, addr, &regval);
-	if (ret) {
-		dev_err(imx290->dev, "Failed to read register 0x%04x: %d\n",
-			addr, ret);
+	ret = regmap_raw_read(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
+			      data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
+	if (ret < 0) {
+		dev_err(imx290->dev, "%u-bit read from 0x%04x failed: %d\n",
+			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
+			 addr & IMX290_REG_ADDR_MASK, ret);
 		return ret;
 	}
 
-	*value = regval & 0xff;
-
+	*value = (data[2] << 16) | (data[1] << 8) | data[0];
 	return 0;
 }
 
-static int imx290_write_reg(struct imx290 *imx290, u16 addr, u8 value)
+static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
 {
+	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
 	int ret;
 
-	ret = regmap_write(imx290->regmap, addr, value);
-	if (ret) {
-		dev_err(imx290->dev, "Failed to write register 0x%04x: %d\n",
-			addr, ret);
-		return ret;
-	}
+	ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
+			       data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
+	if (ret < 0)
+		dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
+			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
+			 addr & IMX290_REG_ADDR_MASK, ret);
 
 	return ret;
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH 08/19] media: i2c: imx290: Correct register sizes
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (6 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 07/19] media: i2c: imx290: Support variable-sized registers Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  8:35 ` [PATCH 09/19] media: i2c: imx290: Simplify error handling when writing registers Laurent Pinchart
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Define registers with the appropriate size, using the variable-size
register access mechanism that has just been introduced. This simplifies
the code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 39 +++++++++-----------------------------
 1 file changed, 9 insertions(+), 30 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index ac58bfe6db7f..3f67c4d2417f 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -32,12 +32,11 @@
 #define IMX290_REGHOLD					IMX290_REG_8BIT(0x3001)
 #define IMX290_XMSTA					IMX290_REG_8BIT(0x3002)
 #define IMX290_FR_FDG_SEL				IMX290_REG_8BIT(0x3009)
-#define IMX290_BLKLEVEL_LOW				IMX290_REG_8BIT(0x300a)
-#define IMX290_BLKLEVEL_HIGH				IMX290_REG_8BIT(0x300b)
+#define IMX290_BLKLEVEL					IMX290_REG_16BIT(0x300a)
 #define IMX290_GAIN					IMX290_REG_8BIT(0x3014)
-#define IMX290_HMAX_LOW					IMX290_REG_8BIT(0x301c)
-#define IMX290_HMAX_HIGH				IMX290_REG_8BIT(0x301d)
+#define IMX290_HMAX					IMX290_REG_16BIT(0x301c)
 #define IMX290_PGCTRL					IMX290_REG_8BIT(0x308c)
+#define IMX290_CHIP_ID					IMX290_REG_16BIT(0x319a)
 #define IMX290_PHY_LANE_NUM				IMX290_REG_8BIT(0x3407)
 #define IMX290_CSI_LANE_MODE				IMX290_REG_8BIT(0x3443)
 
@@ -461,8 +460,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 	case V4L2_CID_TEST_PATTERN:
 		if (ctrl->val) {
-			imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00);
-			imx290_write_reg(imx290, IMX290_BLKLEVEL_HIGH, 0x00);
+			imx290_write_reg(imx290, IMX290_BLKLEVEL, 0);
 			usleep_range(10000, 11000);
 			imx290_write_reg(imx290, IMX290_PGCTRL,
 					 (u8)(IMX290_PGCTRL_REGEN |
@@ -472,12 +470,11 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 			imx290_write_reg(imx290, IMX290_PGCTRL, 0x00);
 			usleep_range(10000, 11000);
 			if (imx290->bpp == 10)
-				imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW,
+				imx290_write_reg(imx290, IMX290_BLKLEVEL,
 						 0x3c);
 			else /* 12 bits per pixel */
-				imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW,
+				imx290_write_reg(imx290, IMX290_BLKLEVEL,
 						 0xf0);
-			imx290_write_reg(imx290, IMX290_BLKLEVEL_HIGH, 0x00);
 		}
 		break;
 	default:
@@ -669,25 +666,6 @@ static int imx290_write_current_format(struct imx290 *imx290)
 	return 0;
 }
 
-static int imx290_set_hmax(struct imx290 *imx290, u32 val)
-{
-	int ret;
-
-	ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (val & 0xff));
-	if (ret) {
-		dev_err(imx290->dev, "Error setting HMAX register\n");
-		return ret;
-	}
-
-	ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((val >> 8) & 0xff));
-	if (ret) {
-		dev_err(imx290->dev, "Error setting HMAX register\n");
-		return ret;
-	}
-
-	return 0;
-}
-
 /* Start streaming */
 static int imx290_start_streaming(struct imx290 *imx290)
 {
@@ -716,8 +694,9 @@ static int imx290_start_streaming(struct imx290 *imx290)
 		dev_err(imx290->dev, "Could not set current mode\n");
 		return ret;
 	}
-	ret = imx290_set_hmax(imx290, imx290->current_mode->hmax);
-	if (ret < 0)
+
+	ret = imx290_write_reg(imx290, IMX290_HMAX, imx290->current_mode->hmax);
+	if (ret)
 		return ret;
 
 	/* Apply customized values from user */
-- 
Regards,

Laurent Pinchart


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

* [PATCH 09/19] media: i2c: imx290: Simplify error handling when writing registers
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (7 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 08/19] media: i2c: imx290: Correct register sizes Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21  9:50   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 10/19] media: i2c: imx290: Define more register macros Laurent Pinchart
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Error handling for register writes requires checking the error status of
every single write. This makes the code complex, or incorrect when the
checks are omitted. Simplify this by passing a pointer to an error code
to the imx290_write_reg() function, which allows writing multiple
registers in a row and only checking for errors at the end.

While at it, rename imx290_write_reg() to imx290_write() as there's
nothing else than registers to write, and rename imx290_read_reg()
accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 86 ++++++++++++++------------------------
 1 file changed, 32 insertions(+), 54 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 3f67c4d2417f..5b7f9027b50f 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -367,7 +367,7 @@ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
 	return container_of(_sd, struct imx290, sd);
 }
 
-static int __always_unused imx290_read_reg(struct imx290 *imx290, u32 addr, u32 *value)
+static int __always_unused imx290_read(struct imx290 *imx290, u32 addr, u32 *value)
 {
 	u8 data[3] = { 0, 0, 0 };
 	int ret;
@@ -385,17 +385,23 @@ static int __always_unused imx290_read_reg(struct imx290 *imx290, u32 addr, u32
 	return 0;
 }
 
-static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
+static int imx290_write(struct imx290 *imx290, u32 addr, u32 value, int *err)
 {
 	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
 	int ret;
 
+	if (err && *err)
+		return *err;
+
 	ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
 			       data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
-	if (ret < 0)
+	if (ret < 0) {
 		dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
 			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
 			 addr & IMX290_REG_ADDR_MASK, ret);
+		if (err)
+			*err = ret;
+	}
 
 	return ret;
 }
@@ -408,7 +414,7 @@ static int imx290_set_register_array(struct imx290 *imx290,
 	int ret;
 
 	for (i = 0; i < num_settings; ++i, ++settings) {
-		ret = imx290_write_reg(imx290, settings->reg, settings->val);
+		ret = imx290_write(imx290, settings->reg, settings->val, NULL);
 		if (ret < 0)
 			return ret;
 	}
@@ -419,29 +425,16 @@ static int imx290_set_register_array(struct imx290 *imx290,
 	return 0;
 }
 
-static int imx290_set_gain(struct imx290 *imx290, u32 value)
-{
-	int ret;
-
-	ret = imx290_write_reg(imx290, IMX290_GAIN, value);
-	if (ret)
-		dev_err(imx290->dev, "Unable to write gain\n");
-
-	return ret;
-}
-
 /* Stop streaming */
 static int imx290_stop_streaming(struct imx290 *imx290)
 {
-	int ret;
+	int ret = 0;
 
-	ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x01);
-	if (ret < 0)
-		return ret;
+	imx290_write(imx290, IMX290_STANDBY, 0x01, &ret);
 
 	msleep(30);
 
-	return imx290_write_reg(imx290, IMX290_XMSTA, 0x01);
+	return imx290_write(imx290, IMX290_XMSTA, 0x01, &ret);
 }
 
 static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
@@ -456,25 +449,25 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 
 	switch (ctrl->id) {
 	case V4L2_CID_GAIN:
-		ret = imx290_set_gain(imx290, ctrl->val);
+		ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
 		break;
 	case V4L2_CID_TEST_PATTERN:
 		if (ctrl->val) {
-			imx290_write_reg(imx290, IMX290_BLKLEVEL, 0);
+			imx290_write(imx290, IMX290_BLKLEVEL, 0, &ret);
 			usleep_range(10000, 11000);
-			imx290_write_reg(imx290, IMX290_PGCTRL,
-					 (u8)(IMX290_PGCTRL_REGEN |
-					 IMX290_PGCTRL_THRU |
-					 IMX290_PGCTRL_MODE(ctrl->val)));
+			imx290_write(imx290, IMX290_PGCTRL,
+				     (u8)(IMX290_PGCTRL_REGEN |
+				     IMX290_PGCTRL_THRU |
+				     IMX290_PGCTRL_MODE(ctrl->val)), &ret);
 		} else {
-			imx290_write_reg(imx290, IMX290_PGCTRL, 0x00);
+			imx290_write(imx290, IMX290_PGCTRL, 0x00, &ret);
 			usleep_range(10000, 11000);
 			if (imx290->bpp == 10)
-				imx290_write_reg(imx290, IMX290_BLKLEVEL,
-						 0x3c);
+				imx290_write(imx290, IMX290_BLKLEVEL, 0x3c,
+					     &ret);
 			else /* 12 bits per pixel */
-				imx290_write_reg(imx290, IMX290_BLKLEVEL,
-						 0xf0);
+				imx290_write(imx290, IMX290_BLKLEVEL, 0xf0,
+					     &ret);
 		}
 		break;
 	default:
@@ -695,7 +688,8 @@ static int imx290_start_streaming(struct imx290 *imx290)
 		return ret;
 	}
 
-	ret = imx290_write_reg(imx290, IMX290_HMAX, imx290->current_mode->hmax);
+	ret = imx290_write(imx290, IMX290_HMAX, imx290->current_mode->hmax,
+			   NULL);
 	if (ret)
 		return ret;
 
@@ -706,14 +700,12 @@ static int imx290_start_streaming(struct imx290 *imx290)
 		return ret;
 	}
 
-	ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x00);
-	if (ret < 0)
-		return ret;
+	imx290_write(imx290, IMX290_STANDBY, 0x00, &ret);
 
 	msleep(30);
 
 	/* Start streaming */
-	return imx290_write_reg(imx290, IMX290_XMSTA, 0x00);
+	return imx290_write(imx290, IMX290_XMSTA, 0x00, &ret);
 }
 
 static int imx290_set_stream(struct v4l2_subdev *sd, int enable)
@@ -772,27 +764,13 @@ static int imx290_set_data_lanes(struct imx290 *imx290)
 		 * validated in probe itself
 		 */
 		dev_err(imx290->dev, "Lane configuration not supported\n");
-		ret = -EINVAL;
-		goto exit;
+		return -EINVAL;
 	}
 
-	ret = imx290_write_reg(imx290, IMX290_PHY_LANE_NUM, laneval);
-	if (ret) {
-		dev_err(imx290->dev, "Error setting Physical Lane number register\n");
-		goto exit;
-	}
-
-	ret = imx290_write_reg(imx290, IMX290_CSI_LANE_MODE, laneval);
-	if (ret) {
-		dev_err(imx290->dev, "Error setting CSI Lane mode register\n");
-		goto exit;
-	}
-
-	ret = imx290_write_reg(imx290, IMX290_FR_FDG_SEL, frsel);
-	if (ret)
-		dev_err(imx290->dev, "Error setting FR/FDG SEL register\n");
+	imx290_write(imx290, IMX290_PHY_LANE_NUM, laneval, &ret);
+	imx290_write(imx290, IMX290_CSI_LANE_MODE, laneval, &ret);
+	imx290_write(imx290, IMX290_FR_FDG_SEL, frsel, &ret);
 
-exit:
 	return ret;
 }
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH 10/19] media: i2c: imx290: Define more register macros
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (8 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 09/19] media: i2c: imx290: Simplify error handling when writing registers Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:00   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 11/19] media: i2c: imx290: Add exposure time control Laurent Pinchart
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Define macros for all registers programmed by the driver for which
documentation is available to increase readability. This starts making
use of 16-bit registers in the register arrays, so the value field has
to be increased to 32 bits.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 219 +++++++++++++++++++++----------------
 1 file changed, 124 insertions(+), 95 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 5b7f9027b50f..bec326a83952 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -31,14 +31,73 @@
 #define IMX290_STANDBY					IMX290_REG_8BIT(0x3000)
 #define IMX290_REGHOLD					IMX290_REG_8BIT(0x3001)
 #define IMX290_XMSTA					IMX290_REG_8BIT(0x3002)
+#define IMX290_ADBIT					IMX290_REG_8BIT(0x3005)
+#define IMX290_ADBIT_10BIT				(0 << 0)
+#define IMX290_ADBIT_12BIT				(1 << 0)
+#define IMX290_CTRL_07					IMX290_REG_8BIT(0x3007)
+#define IMX290_VREVERSE					BIT(0)
+#define IMX290_HREVERSE					BIT(1)
+#define IMX290_WINMODE_1080P				(0 << 4)
+#define IMX290_WINMODE_720P				(1 << 4)
+#define IMX290_WINMODE_CROP				(4 << 4)
 #define IMX290_FR_FDG_SEL				IMX290_REG_8BIT(0x3009)
 #define IMX290_BLKLEVEL					IMX290_REG_16BIT(0x300a)
 #define IMX290_GAIN					IMX290_REG_8BIT(0x3014)
+#define IMX290_VMAX					IMX290_REG_24BIT(0x3018)
 #define IMX290_HMAX					IMX290_REG_16BIT(0x301c)
+#define IMX290_SHS1					IMX290_REG_24BIT(0x3020)
+#define IMX290_WINWV_OB					IMX290_REG_8BIT(0x303a)
+#define IMX290_WINPV					IMX290_REG_16BIT(0x303c)
+#define IMX290_WINWV					IMX290_REG_16BIT(0x303e)
+#define IMX290_WINPH					IMX290_REG_16BIT(0x3040)
+#define IMX290_WINWH					IMX290_REG_16BIT(0x3042)
+#define IMX290_OUT_CTRL					IMX290_REG_8BIT(0x3046)
+#define IMX290_ODBIT_10BIT				(0 << 0)
+#define IMX290_ODBIT_12BIT				(1 << 0)
+#define IMX290_OPORTSEL_PARALLEL			(0x0 << 4)
+#define IMX290_OPORTSEL_LVDS_2CH			(0xd << 4)
+#define IMX290_OPORTSEL_LVDS_4CH			(0xe << 4)
+#define IMX290_OPORTSEL_LVDS_8CH			(0xf << 4)
+#define IMX290_XSOUTSEL					IMX290_REG_8BIT(0x304b)
+#define IMX290_XSOUTSEL_XVSOUTSEL_HIGH			(0 << 0)
+#define IMX290_XSOUTSEL_XVSOUTSEL_VSYNC			(2 << 0)
+#define IMX290_XSOUTSEL_XHSOUTSEL_HIGH			(0 << 2)
+#define IMX290_XSOUTSEL_XHSOUTSEL_HSYNC			(2 << 2)
+#define IMX290_INCKSEL1					IMX290_REG_8BIT(0x305c)
+#define IMX290_INCKSEL2					IMX290_REG_8BIT(0x305d)
+#define IMX290_INCKSEL3					IMX290_REG_8BIT(0x305e)
+#define IMX290_INCKSEL4					IMX290_REG_8BIT(0x305f)
 #define IMX290_PGCTRL					IMX290_REG_8BIT(0x308c)
+#define IMX290_ADBIT1					IMX290_REG_8BIT(0x3129)
+#define IMX290_ADBIT1_10BIT				0x1d
+#define IMX290_ADBIT1_12BIT				0x00
+#define IMX290_INCKSEL5					IMX290_REG_8BIT(0x315e)
+#define IMX290_INCKSEL6					IMX290_REG_8BIT(0x3164)
+#define IMX290_ADBIT2					IMX290_REG_8BIT(0x317c)
+#define IMX290_ADBIT2_10BIT				0x12
+#define IMX290_ADBIT2_12BIT				0x00
 #define IMX290_CHIP_ID					IMX290_REG_16BIT(0x319a)
+#define IMX290_ADBIT3					IMX290_REG_16BIT(0x31ec)
+#define IMX290_ADBIT3_10BIT				0x37
+#define IMX290_ADBIT3_12BIT				0x0e
+#define IMX290_REPETITION				IMX290_REG_8BIT(0x3405)
 #define IMX290_PHY_LANE_NUM				IMX290_REG_8BIT(0x3407)
+#define IMX290_OPB_SIZE_V				IMX290_REG_8BIT(0x3414)
+#define IMX290_Y_OUT_SIZE				IMX290_REG_16BIT(0x3418)
+#define IMX290_CSI_DT_FMT				IMX290_REG_16BIT(0x3441)
+#define IMX290_CSI_DT_FMT_RAW10				0x0a0a
+#define IMX290_CSI_DT_FMT_RAW12				0x0c0c
 #define IMX290_CSI_LANE_MODE				IMX290_REG_8BIT(0x3443)
+#define IMX290_EXTCK_FREQ				IMX290_REG_16BIT(0x3444)
+#define IMX290_TCLKPOST					IMX290_REG_16BIT(0x3446)
+#define IMX290_THSZERO					IMX290_REG_16BIT(0x3448)
+#define IMX290_THSPREPARE				IMX290_REG_16BIT(0x344a)
+#define IMX290_TCLKTRAIL				IMX290_REG_16BIT(0x344c)
+#define IMX290_THSTRAIL					IMX290_REG_16BIT(0x344e)
+#define IMX290_TCLKZERO					IMX290_REG_16BIT(0x3450)
+#define IMX290_TCLKPREPARE				IMX290_REG_16BIT(0x3452)
+#define IMX290_TLPX					IMX290_REG_16BIT(0x3454)
+#define IMX290_X_OUT_SIZE				IMX290_REG_16BIT(0x3472)
 
 #define IMX290_PGCTRL_REGEN				BIT(0)
 #define IMX290_PGCTRL_THRU				BIT(1)
@@ -54,7 +113,7 @@ static const char * const imx290_supply_name[] = {
 
 struct imx290_regval {
 	u32 reg;
-	u8 val;
+	u32 val;
 };
 
 struct imx290_mode {
@@ -116,22 +175,16 @@ static const char * const imx290_test_pattern_menu[] = {
 };
 
 static const struct imx290_regval imx290_global_init_settings[] = {
-	{ IMX290_REG_8BIT(0x3007), 0x00 },
-	{ IMX290_REG_8BIT(0x3018), 0x65 },
-	{ IMX290_REG_8BIT(0x3019), 0x04 },
-	{ IMX290_REG_8BIT(0x301a), 0x00 },
-	{ IMX290_REG_8BIT(0x3444), 0x20 },
-	{ IMX290_REG_8BIT(0x3445), 0x25 },
-	{ IMX290_REG_8BIT(0x303a), 0x0c },
-	{ IMX290_REG_8BIT(0x3040), 0x00 },
-	{ IMX290_REG_8BIT(0x3041), 0x00 },
-	{ IMX290_REG_8BIT(0x303c), 0x00 },
-	{ IMX290_REG_8BIT(0x303d), 0x00 },
-	{ IMX290_REG_8BIT(0x3042), 0x9c },
-	{ IMX290_REG_8BIT(0x3043), 0x07 },
-	{ IMX290_REG_8BIT(0x303e), 0x49 },
-	{ IMX290_REG_8BIT(0x303f), 0x04 },
-	{ IMX290_REG_8BIT(0x304b), 0x0a },
+	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
+	{ IMX290_VMAX, 1125 },
+	{ IMX290_EXTCK_FREQ, 0x2520 },
+	{ IMX290_WINWV_OB, 12 },
+	{ IMX290_WINPH, 0 },
+	{ IMX290_WINPV, 0 },
+	{ IMX290_WINWH, 1948 },
+	{ IMX290_WINWV, 1097 },
+	{ IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
+			   IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
 	{ IMX290_REG_8BIT(0x300f), 0x00 },
 	{ IMX290_REG_8BIT(0x3010), 0x21 },
 	{ IMX290_REG_8BIT(0x3012), 0x64 },
@@ -177,102 +230,78 @@ static const struct imx290_regval imx290_global_init_settings[] = {
 
 static const struct imx290_regval imx290_1080p_settings[] = {
 	/* mode settings */
-	{ IMX290_REG_8BIT(0x3007), 0x00 },
-	{ IMX290_REG_8BIT(0x303a), 0x0c },
-	{ IMX290_REG_8BIT(0x3414), 0x0a },
-	{ IMX290_REG_8BIT(0x3472), 0x80 },
-	{ IMX290_REG_8BIT(0x3473), 0x07 },
-	{ IMX290_REG_8BIT(0x3418), 0x38 },
-	{ IMX290_REG_8BIT(0x3419), 0x04 },
+	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
+	{ IMX290_WINWV_OB, 12 },
+	{ IMX290_OPB_SIZE_V, 10 },
+	{ IMX290_X_OUT_SIZE, 1920 },
+	{ IMX290_Y_OUT_SIZE, 1080 },
 	{ IMX290_REG_8BIT(0x3012), 0x64 },
 	{ IMX290_REG_8BIT(0x3013), 0x00 },
-	{ IMX290_REG_8BIT(0x305c), 0x18 },
-	{ IMX290_REG_8BIT(0x305d), 0x03 },
-	{ IMX290_REG_8BIT(0x305e), 0x20 },
-	{ IMX290_REG_8BIT(0x305f), 0x01 },
-	{ IMX290_REG_8BIT(0x315e), 0x1a },
-	{ IMX290_REG_8BIT(0x3164), 0x1a },
+	{ IMX290_INCKSEL1, 0x18 },
+	{ IMX290_INCKSEL2, 0x03 },
+	{ IMX290_INCKSEL3, 0x20 },
+	{ IMX290_INCKSEL4, 0x01 },
+	{ IMX290_INCKSEL5, 0x1a },
+	{ IMX290_INCKSEL6, 0x1a },
 	{ IMX290_REG_8BIT(0x3480), 0x49 },
 	/* data rate settings */
-	{ IMX290_REG_8BIT(0x3405), 0x10 },
-	{ IMX290_REG_8BIT(0x3446), 0x57 },
-	{ IMX290_REG_8BIT(0x3447), 0x00 },
-	{ IMX290_REG_8BIT(0x3448), 0x37 },
-	{ IMX290_REG_8BIT(0x3449), 0x00 },
-	{ IMX290_REG_8BIT(0x344a), 0x1f },
-	{ IMX290_REG_8BIT(0x344b), 0x00 },
-	{ IMX290_REG_8BIT(0x344c), 0x1f },
-	{ IMX290_REG_8BIT(0x344d), 0x00 },
-	{ IMX290_REG_8BIT(0x344e), 0x1f },
-	{ IMX290_REG_8BIT(0x344f), 0x00 },
-	{ IMX290_REG_8BIT(0x3450), 0x77 },
-	{ IMX290_REG_8BIT(0x3451), 0x00 },
-	{ IMX290_REG_8BIT(0x3452), 0x1f },
-	{ IMX290_REG_8BIT(0x3453), 0x00 },
-	{ IMX290_REG_8BIT(0x3454), 0x17 },
-	{ IMX290_REG_8BIT(0x3455), 0x00 },
+	{ IMX290_REPETITION, 0x10 },
+	{ IMX290_TCLKPOST, 87 },
+	{ IMX290_THSZERO, 55 },
+	{ IMX290_THSPREPARE, 31 },
+	{ IMX290_TCLKTRAIL, 31 },
+	{ IMX290_THSTRAIL, 31 },
+	{ IMX290_TCLKZERO, 119 },
+	{ IMX290_TCLKPREPARE, 31 },
+	{ IMX290_TLPX, 23 },
 };
 
 static const struct imx290_regval imx290_720p_settings[] = {
 	/* mode settings */
-	{ IMX290_REG_8BIT(0x3007), 0x10 },
-	{ IMX290_REG_8BIT(0x303a), 0x06 },
-	{ IMX290_REG_8BIT(0x3414), 0x04 },
-	{ IMX290_REG_8BIT(0x3472), 0x00 },
-	{ IMX290_REG_8BIT(0x3473), 0x05 },
-	{ IMX290_REG_8BIT(0x3418), 0xd0 },
-	{ IMX290_REG_8BIT(0x3419), 0x02 },
+	{ IMX290_CTRL_07, IMX290_WINMODE_720P },
+	{ IMX290_WINWV_OB, 6 },
+	{ IMX290_OPB_SIZE_V, 4 },
+	{ IMX290_X_OUT_SIZE, 1280 },
+	{ IMX290_Y_OUT_SIZE, 720 },
 	{ IMX290_REG_8BIT(0x3012), 0x64 },
 	{ IMX290_REG_8BIT(0x3013), 0x00 },
-	{ IMX290_REG_8BIT(0x305c), 0x20 },
-	{ IMX290_REG_8BIT(0x305d), 0x00 },
-	{ IMX290_REG_8BIT(0x305e), 0x20 },
-	{ IMX290_REG_8BIT(0x305f), 0x01 },
-	{ IMX290_REG_8BIT(0x315e), 0x1a },
-	{ IMX290_REG_8BIT(0x3164), 0x1a },
+	{ IMX290_INCKSEL1, 0x20 },
+	{ IMX290_INCKSEL2, 0x00 },
+	{ IMX290_INCKSEL3, 0x20 },
+	{ IMX290_INCKSEL4, 0x01 },
+	{ IMX290_INCKSEL5, 0x1a },
+	{ IMX290_INCKSEL6, 0x1a },
 	{ IMX290_REG_8BIT(0x3480), 0x49 },
 	/* data rate settings */
-	{ IMX290_REG_8BIT(0x3405), 0x10 },
-	{ IMX290_REG_8BIT(0x3446), 0x4f },
-	{ IMX290_REG_8BIT(0x3447), 0x00 },
-	{ IMX290_REG_8BIT(0x3448), 0x2f },
-	{ IMX290_REG_8BIT(0x3449), 0x00 },
-	{ IMX290_REG_8BIT(0x344a), 0x17 },
-	{ IMX290_REG_8BIT(0x344b), 0x00 },
-	{ IMX290_REG_8BIT(0x344c), 0x17 },
-	{ IMX290_REG_8BIT(0x344d), 0x00 },
-	{ IMX290_REG_8BIT(0x344e), 0x17 },
-	{ IMX290_REG_8BIT(0x344f), 0x00 },
-	{ IMX290_REG_8BIT(0x3450), 0x57 },
-	{ IMX290_REG_8BIT(0x3451), 0x00 },
-	{ IMX290_REG_8BIT(0x3452), 0x17 },
-	{ IMX290_REG_8BIT(0x3453), 0x00 },
-	{ IMX290_REG_8BIT(0x3454), 0x17 },
-	{ IMX290_REG_8BIT(0x3455), 0x00 },
+	{ IMX290_REPETITION, 0x10 },
+	{ IMX290_TCLKPOST, 79 },
+	{ IMX290_THSZERO, 47 },
+	{ IMX290_THSPREPARE, 23 },
+	{ IMX290_TCLKTRAIL, 23 },
+	{ IMX290_THSTRAIL, 23 },
+	{ IMX290_TCLKZERO, 87 },
+	{ IMX290_TCLKPREPARE, 23 },
+	{ IMX290_TLPX, 23 },
 };
 
 static const struct imx290_regval imx290_10bit_settings[] = {
-	{ IMX290_REG_8BIT(0x3005), 0x00},
-	{ IMX290_REG_8BIT(0x3046), 0x00},
-	{ IMX290_REG_8BIT(0x3129), 0x1d},
-	{ IMX290_REG_8BIT(0x317c), 0x12},
-	{ IMX290_REG_8BIT(0x31ec), 0x37},
-	{ IMX290_REG_8BIT(0x3441), 0x0a},
-	{ IMX290_REG_8BIT(0x3442), 0x0a},
-	{ IMX290_REG_8BIT(0x300a), 0x3c},
-	{ IMX290_REG_8BIT(0x300b), 0x00},
+	{ IMX290_ADBIT, IMX290_ADBIT_10BIT },
+	{ IMX290_OUT_CTRL, IMX290_ODBIT_10BIT },
+	{ IMX290_ADBIT1, IMX290_ADBIT1_10BIT },
+	{ IMX290_ADBIT2, IMX290_ADBIT2_10BIT },
+	{ IMX290_ADBIT3, IMX290_ADBIT3_10BIT },
+	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW10 },
+	{ IMX290_BLKLEVEL, 60 },
 };
 
 static const struct imx290_regval imx290_12bit_settings[] = {
-	{ IMX290_REG_8BIT(0x3005), 0x01 },
-	{ IMX290_REG_8BIT(0x3046), 0x01 },
-	{ IMX290_REG_8BIT(0x3129), 0x00 },
-	{ IMX290_REG_8BIT(0x317c), 0x00 },
-	{ IMX290_REG_8BIT(0x31ec), 0x0e },
-	{ IMX290_REG_8BIT(0x3441), 0x0c },
-	{ IMX290_REG_8BIT(0x3442), 0x0c },
-	{ IMX290_REG_8BIT(0x300a), 0xf0 },
-	{ IMX290_REG_8BIT(0x300b), 0x00 },
+	{ IMX290_ADBIT, IMX290_ADBIT_12BIT },
+	{ IMX290_OUT_CTRL, IMX290_ODBIT_12BIT },
+	{ IMX290_ADBIT1, IMX290_ADBIT1_12BIT },
+	{ IMX290_ADBIT2, IMX290_ADBIT2_12BIT },
+	{ IMX290_ADBIT3, IMX290_ADBIT3_12BIT },
+	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW12 },
+	{ IMX290_BLKLEVEL, 240 },
 };
 
 /* supported link frequencies */
-- 
Regards,

Laurent Pinchart


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

* [PATCH 11/19] media: i2c: imx290: Add exposure time control
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (9 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 10/19] media: i2c: imx290: Define more register macros Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:01   ` Alexander Stein
  2022-07-21 15:52   ` Dave Stevenson
  2022-07-21  8:35 ` [PATCH 12/19] media: i2c: imx290: Fix max gain value Laurent Pinchart
                   ` (8 subsequent siblings)
  19 siblings, 2 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Support configuring the exposure time, which is expressed as the
complement if the exposure time (frame period minus integration time).
The frame period is currently fixed.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index bec326a83952..3cb024b73ee7 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -103,6 +103,8 @@
 #define IMX290_PGCTRL_THRU				BIT(1)
 #define IMX290_PGCTRL_MODE(n)				((n) << 4)
 
+#define IMX290_VMAX_DEFAULT				1125
+
 static const char * const imx290_supply_name[] = {
 	"vdda",
 	"vddd",
@@ -176,7 +178,7 @@ static const char * const imx290_test_pattern_menu[] = {
 
 static const struct imx290_regval imx290_global_init_settings[] = {
 	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
-	{ IMX290_VMAX, 1125 },
+	{ IMX290_VMAX, IMX290_VMAX_DEFAULT },
 	{ IMX290_EXTCK_FREQ, 0x2520 },
 	{ IMX290_WINWV_OB, 12 },
 	{ IMX290_WINPH, 0 },
@@ -480,6 +482,12 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 	case V4L2_CID_GAIN:
 		ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
 		break;
+
+	case V4L2_CID_EXPOSURE:
+		ret = imx290_write(imx290, IMX290_SHS1,
+				   IMX290_VMAX_DEFAULT - ctrl->val - 1, NULL);
+		break;
+
 	case V4L2_CID_TEST_PATTERN:
 		if (ctrl->val) {
 			imx290_write(imx290, IMX290_BLKLEVEL, 0, &ret);
@@ -1008,12 +1016,16 @@ static int imx290_probe(struct i2c_client *client)
 	 */
 	imx290_entity_init_cfg(&imx290->sd, NULL);
 
-	v4l2_ctrl_handler_init(&imx290->ctrls, 4);
+	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
 	imx290->ctrls.lock = &imx290->lock;
 
 	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
 			  V4L2_CID_GAIN, 0, 72, 1, 0);
 
+	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,
+			  IMX290_VMAX_DEFAULT - 2);
+
 	imx290->link_freq =
 		v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
 				       V4L2_CID_LINK_FREQ,
-- 
Regards,

Laurent Pinchart


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

* [PATCH 12/19] media: i2c: imx290: Fix max gain value
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (10 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 11/19] media: i2c: imx290: Add exposure time control Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:02   ` Alexander Stein
  2022-07-21 16:08   ` Dave Stevenson
  2022-07-21  8:35 ` [PATCH 13/19] media: i2c: imx290: Split control initialization to separate function Laurent Pinchart
                   ` (7 subsequent siblings)
  19 siblings, 2 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

The gain is expressed in multiple of 0.3dB, as a value between 0.0dB
and 72.0dB. The maximum value is thus 240, not 72.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 3cb024b73ee7..1bd464932432 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -1020,7 +1020,7 @@ static int imx290_probe(struct i2c_client *client)
 	imx290->ctrls.lock = &imx290->lock;
 
 	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
-			  V4L2_CID_GAIN, 0, 72, 1, 0);
+			  V4L2_CID_GAIN, 0, 240, 1, 0);
 
 	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
 			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,
-- 
Regards,

Laurent Pinchart


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

* [PATCH 13/19] media: i2c: imx290: Split control initialization to separate function
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (11 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 12/19] media: i2c: imx290: Fix max gain value Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:03   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls Laurent Pinchart
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

The imx290_probe() function is too large. Split control initialzation to
a dedicated function to increase code readability.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 83 ++++++++++++++++++++++----------------
 1 file changed, 48 insertions(+), 35 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 1bd464932432..4408dd3e191f 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -878,6 +878,49 @@ static const struct media_entity_operations imx290_subdev_entity_ops = {
 	.link_validate = v4l2_subdev_link_validate,
 };
 
+static int imx290_ctrl_init(struct imx290 *imx290)
+{
+	int ret;
+
+	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
+	imx290->ctrls.lock = &imx290->lock;
+
+	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+			  V4L2_CID_GAIN, 0, 240, 1, 0);
+
+	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,
+			  IMX290_VMAX_DEFAULT - 2);
+
+	imx290->link_freq =
+		v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
+				       V4L2_CID_LINK_FREQ,
+				       imx290_link_freqs_num(imx290) - 1, 0,
+				       imx290_link_freqs_ptr(imx290));
+	if (imx290->link_freq)
+		imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+	imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+					       V4L2_CID_PIXEL_RATE,
+					       1, INT_MAX, 1,
+					       imx290_calc_pixel_rate(imx290));
+
+	v4l2_ctrl_new_std_menu_items(&imx290->ctrls, &imx290_ctrl_ops,
+				     V4L2_CID_TEST_PATTERN,
+				     ARRAY_SIZE(imx290_test_pattern_menu) - 1,
+				     0, 0, imx290_test_pattern_menu);
+
+	imx290->sd.ctrl_handler = &imx290->ctrls;
+
+	if (imx290->ctrls.error) {
+		ret = imx290->ctrls.error;
+		v4l2_ctrl_handler_free(&imx290->ctrls);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * Returns 0 if all link frequencies used by the driver for the given number
  * of MIPI data lanes are mentioned in the device tree, or the value of the
@@ -1016,41 +1059,10 @@ static int imx290_probe(struct i2c_client *client)
 	 */
 	imx290_entity_init_cfg(&imx290->sd, NULL);
 
-	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
-	imx290->ctrls.lock = &imx290->lock;
-
-	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
-			  V4L2_CID_GAIN, 0, 240, 1, 0);
-
-	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
-			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,
-			  IMX290_VMAX_DEFAULT - 2);
-
-	imx290->link_freq =
-		v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
-				       V4L2_CID_LINK_FREQ,
-				       imx290_link_freqs_num(imx290) - 1, 0,
-				       imx290_link_freqs_ptr(imx290));
-	if (imx290->link_freq)
-		imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
-	imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
-					       V4L2_CID_PIXEL_RATE,
-					       1, INT_MAX, 1,
-					       imx290_calc_pixel_rate(imx290));
-
-	v4l2_ctrl_new_std_menu_items(&imx290->ctrls, &imx290_ctrl_ops,
-				     V4L2_CID_TEST_PATTERN,
-				     ARRAY_SIZE(imx290_test_pattern_menu) - 1,
-				     0, 0, imx290_test_pattern_menu);
-
-	imx290->sd.ctrl_handler = &imx290->ctrls;
-
-	if (imx290->ctrls.error) {
-		dev_err(dev, "Control initialization error %d\n",
-			imx290->ctrls.error);
-		ret = imx290->ctrls.error;
-		goto free_ctrl;
+	ret = imx290_ctrl_init(imx290);
+	if (ret < 0) {
+		dev_err(dev, "Control initialization error %d\n", ret);
+		goto free_mutex;
 	}
 
 	v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
@@ -1091,6 +1103,7 @@ static int imx290_probe(struct i2c_client *client)
 	media_entity_cleanup(&imx290->sd.entity);
 free_ctrl:
 	v4l2_ctrl_handler_free(&imx290->ctrls);
+free_mutex:
 	mutex_destroy(&imx290->lock);
 free_err:
 	v4l2_fwnode_endpoint_free(&ep);
-- 
Regards,

Laurent Pinchart


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

* [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (12 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 13/19] media: i2c: imx290: Split control initialization to separate function Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:05   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 15/19] media: i2c: imx290: Create controls for fwnode properties Laurent Pinchart
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Add support for the V4L2_CID_HBLANK and V4L2_CID_VBLANK controls to the
imx290 driver. Make the controls read-only to start with, to report the
values to userspace for timing calculation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 39 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 4408dd3e191f..7190399f4111 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -146,6 +146,8 @@ struct imx290 {
 	struct v4l2_ctrl_handler ctrls;
 	struct v4l2_ctrl *link_freq;
 	struct v4l2_ctrl *pixel_rate;
+	struct v4l2_ctrl *hblank;
+	struct v4l2_ctrl *vblank;
 
 	struct mutex lock;
 };
@@ -642,6 +644,20 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
 		if (imx290->pixel_rate)
 			__v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
 						 imx290_calc_pixel_rate(imx290));
+
+		if (imx290->hblank) {
+			unsigned int hblank = mode->hmax - mode->width;
+
+			__v4l2_ctrl_modify_range(imx290->hblank, hblank, hblank,
+						 1, hblank);
+		}
+
+		if (imx290->vblank) {
+			unsigned int vblank = IMX290_VMAX_DEFAULT - mode->height;
+
+			__v4l2_ctrl_modify_range(imx290->vblank, vblank, vblank,
+						 1, vblank);
+		}
 	}
 
 	*format = fmt->format;
@@ -880,9 +896,10 @@ static const struct media_entity_operations imx290_subdev_entity_ops = {
 
 static int imx290_ctrl_init(struct imx290 *imx290)
 {
+	unsigned int blank;
 	int ret;
 
-	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
+	v4l2_ctrl_handler_init(&imx290->ctrls, 7);
 	imx290->ctrls.lock = &imx290->lock;
 
 	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
@@ -910,6 +927,26 @@ static int imx290_ctrl_init(struct imx290 *imx290)
 				     ARRAY_SIZE(imx290_test_pattern_menu) - 1,
 				     0, 0, imx290_test_pattern_menu);
 
+	/*
+	 * Horizontal blanking is controlled through the HMAX register, which
+	 * contains a line length in INCK clock units. The INCK frequency is
+	 * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100,
+	 * convert it to a number of pixels based on the nominal pixel rate.
+	 */
+	blank = imx290->current_mode->hmax - imx290->current_mode->width;
+	imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+					   V4L2_CID_HBLANK, blank, blank, 1,
+					   blank);
+	if (imx290->hblank)
+		imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+	blank = IMX290_VMAX_DEFAULT - imx290->current_mode->height;
+	imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+					   V4L2_CID_VBLANK, blank, blank, 1,
+					   blank);
+	if (imx290->vblank)
+		imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
 	imx290->sd.ctrl_handler = &imx290->ctrls;
 
 	if (imx290->ctrls.error) {
-- 
Regards,

Laurent Pinchart


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

* [PATCH 15/19] media: i2c: imx290: Create controls for fwnode properties
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (13 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:06   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array Laurent Pinchart
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Create the V4L2_CID_ORIENTATION and V4L2_CID_ROTATION controls to
expose the corresponding fwnode properties.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 7190399f4111..78772c6327a2 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -896,10 +896,15 @@ static const struct media_entity_operations imx290_subdev_entity_ops = {
 
 static int imx290_ctrl_init(struct imx290 *imx290)
 {
+	struct v4l2_fwnode_device_properties props;
 	unsigned int blank;
 	int ret;
 
-	v4l2_ctrl_handler_init(&imx290->ctrls, 7);
+	ret = v4l2_fwnode_device_parse(imx290->dev, &props);
+	if (ret < 0)
+		return ret;
+
+	v4l2_ctrl_handler_init(&imx290->ctrls, 9);
 	imx290->ctrls.lock = &imx290->lock;
 
 	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
@@ -947,6 +952,9 @@ static int imx290_ctrl_init(struct imx290 *imx290)
 	if (imx290->vblank)
 		imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
+	v4l2_ctrl_new_fwnode_properties(&imx290->ctrls, &imx290_ctrl_ops,
+					&props);
+
 	imx290->sd.ctrl_handler = &imx290->ctrls;
 
 	if (imx290->ctrls.error) {
-- 
Regards,

Laurent Pinchart


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

* [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (14 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 15/19] media: i2c: imx290: Create controls for fwnode properties Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:08   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 17/19] media: i2c: imx290: Factor out format retrieval to separate function Laurent Pinchart
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Registers 0x3012, 0x3013 and 0x3480 are not documented and are set in
the per-mode register arrays with values indentical for all modes. Move
them to the common array.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 78772c6327a2..fc6e87fada1c 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -192,6 +192,7 @@ static const struct imx290_regval imx290_global_init_settings[] = {
 	{ IMX290_REG_8BIT(0x300f), 0x00 },
 	{ IMX290_REG_8BIT(0x3010), 0x21 },
 	{ IMX290_REG_8BIT(0x3012), 0x64 },
+	{ IMX290_REG_8BIT(0x3013), 0x00 },
 	{ IMX290_REG_8BIT(0x3016), 0x09 },
 	{ IMX290_REG_8BIT(0x3070), 0x02 },
 	{ IMX290_REG_8BIT(0x3071), 0x11 },
@@ -230,6 +231,7 @@ static const struct imx290_regval imx290_global_init_settings[] = {
 	{ IMX290_REG_8BIT(0x33b0), 0x50 },
 	{ IMX290_REG_8BIT(0x33b2), 0x1a },
 	{ IMX290_REG_8BIT(0x33b3), 0x04 },
+	{ IMX290_REG_8BIT(0x3480), 0x49 },
 };
 
 static const struct imx290_regval imx290_1080p_settings[] = {
@@ -239,15 +241,12 @@ static const struct imx290_regval imx290_1080p_settings[] = {
 	{ IMX290_OPB_SIZE_V, 10 },
 	{ IMX290_X_OUT_SIZE, 1920 },
 	{ IMX290_Y_OUT_SIZE, 1080 },
-	{ IMX290_REG_8BIT(0x3012), 0x64 },
-	{ IMX290_REG_8BIT(0x3013), 0x00 },
 	{ IMX290_INCKSEL1, 0x18 },
 	{ IMX290_INCKSEL2, 0x03 },
 	{ IMX290_INCKSEL3, 0x20 },
 	{ IMX290_INCKSEL4, 0x01 },
 	{ IMX290_INCKSEL5, 0x1a },
 	{ IMX290_INCKSEL6, 0x1a },
-	{ IMX290_REG_8BIT(0x3480), 0x49 },
 	/* data rate settings */
 	{ IMX290_REPETITION, 0x10 },
 	{ IMX290_TCLKPOST, 87 },
@@ -267,15 +266,12 @@ static const struct imx290_regval imx290_720p_settings[] = {
 	{ IMX290_OPB_SIZE_V, 4 },
 	{ IMX290_X_OUT_SIZE, 1280 },
 	{ IMX290_Y_OUT_SIZE, 720 },
-	{ IMX290_REG_8BIT(0x3012), 0x64 },
-	{ IMX290_REG_8BIT(0x3013), 0x00 },
 	{ IMX290_INCKSEL1, 0x20 },
 	{ IMX290_INCKSEL2, 0x00 },
 	{ IMX290_INCKSEL3, 0x20 },
 	{ IMX290_INCKSEL4, 0x01 },
 	{ IMX290_INCKSEL5, 0x1a },
 	{ IMX290_INCKSEL6, 0x1a },
-	{ IMX290_REG_8BIT(0x3480), 0x49 },
 	/* data rate settings */
 	{ IMX290_REPETITION, 0x10 },
 	{ IMX290_TCLKPOST, 79 },
-- 
Regards,

Laurent Pinchart


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

* [PATCH 17/19] media: i2c: imx290: Factor out format retrieval to separate function
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (15 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:11   ` Alexander Stein
  2022-07-21  8:35 ` [PATCH 18/19] media: i2c: imx290: Add crop selection targets support Laurent Pinchart
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

The driver duplicates the same pattern to access the try or active
format in multiple locations. Factor it out to a separate function.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index fc6e87fada1c..baf9941c5fbe 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -519,6 +519,20 @@ static const struct v4l2_ctrl_ops imx290_ctrl_ops = {
 	.s_ctrl = imx290_set_ctrl,
 };
 
+static struct v4l2_mbus_framefmt *
+imx290_get_pad_format(struct imx290 *imx290, struct v4l2_subdev_state *state,
+		      u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(&imx290->sd, state, 0);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &imx290->current_format;
+	default:
+		return NULL;
+	}
+}
+
 static int imx290_enum_mbus_code(struct v4l2_subdev *sd,
 				 struct v4l2_subdev_state *sd_state,
 				 struct v4l2_subdev_mbus_code_enum *code)
@@ -562,12 +576,7 @@ static int imx290_get_fmt(struct v4l2_subdev *sd,
 
 	mutex_lock(&imx290->lock);
 
-	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
-		framefmt = v4l2_subdev_get_try_format(&imx290->sd, sd_state,
-						      fmt->pad);
-	else
-		framefmt = &imx290->current_format;
-
+	framefmt = imx290_get_pad_format(imx290, sd_state, fmt->which);
 	fmt->format = *framefmt;
 
 	mutex_unlock(&imx290->lock);
@@ -627,10 +636,9 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
 	fmt->format.code = imx290_formats[i].code;
 	fmt->format.field = V4L2_FIELD_NONE;
 
-	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-		format = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
-	} else {
-		format = &imx290->current_format;
+	format = imx290_get_pad_format(imx290, sd_state, fmt->which);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
 		imx290->current_mode = mode;
 		imx290->bpp = imx290_formats[i].bpp;
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH 18/19] media: i2c: imx290: Add crop selection targets support
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (16 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 17/19] media: i2c: imx290: Factor out format retrieval to separate function Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 15:39   ` Dave Stevenson
  2022-07-21  8:35 ` [PATCH 19/19] media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN Laurent Pinchart
  2022-08-23  1:11 ` [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

Implement read-only access to crop selection rectangles to expose the
analogue crop rectangle. The public (leaked) IMX290 documentation is not
very clear on how cropping is implemented and configured exactly, so
the margins may not be entirely accurate.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 94 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index baf9941c5fbe..0cb11ec1cf0f 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -105,6 +105,53 @@
 
 #define IMX290_VMAX_DEFAULT				1125
 
+
+/*
+ * The IMX290 pixel array is organized as follows:
+ *
+ *     +------------------------------------+
+ *     |           Optical Black            |     }  Vertical effective optical black (10)
+ * +---+------------------------------------+---+
+ * |   |                                    |   | }  Effective top margin (8)
+ * |   |   +----------------------------+   |   | \
+ * |   |   |                            |   |   |  |
+ * |   |   |                            |   |   |  |
+ * |   |   |                            |   |   |  |
+ * |   |   |    Recording Pixel Area    |   |   |  | Recommended height (1080)
+ * |   |   |                            |   |   |  |
+ * |   |   |                            |   |   |  |
+ * |   |   |                            |   |   |  |
+ * |   |   +----------------------------+   |   | /
+ * |   |                                    |   | }  Effective bottom margin (8)
+ * +---+------------------------------------+---+
+ *  <-> <-> <--------------------------> <-> <->
+ *                                            \----  Ignored right margin (4)
+ *                                        \--------  Effective right margin (9)
+ *                       \-------------------------  Recommended width (1920)
+ *       \-----------------------------------------  Effective left margin (8)
+ *   \---------------------------------------------  Ignored left margin (4)
+ *
+ * The optical black lines are output over CSI-2 with a separate data type.
+ *
+ * The pixel array is meant to have 1920x1080 usable pixels after image
+ * processing in an ISP. It has 8 (9) extra active pixels usable for color
+ * processing in the ISP on the top and left (bottom and right) sides of the
+ * image. In addition, 4 additional pixels are present on the left and right
+ * sides of the image, documented as "ignored area".
+ *
+ * As far as is understood, all pixels of the pixel array (ignored area, color
+ * processing margins and recording area) can be output by the sensor.
+ */
+
+#define IMX290_PIXEL_ARRAY_WIDTH			1945
+#define IMX290_PIXEL_ARRAY_HEIGHT			1097
+#define IMX920_PIXEL_ARRAY_MARGIN_LEFT			12
+#define IMX920_PIXEL_ARRAY_MARGIN_RIGHT			13
+#define IMX920_PIXEL_ARRAY_MARGIN_TOP			8
+#define IMX920_PIXEL_ARRAY_MARGIN_BOTTOM		9
+#define IMX290_PIXEL_ARRAY_RECORDING_WIDTH		1920
+#define IMX290_PIXEL_ARRAY_RECORDING_HEIGHT		1080
+
 static const char * const imx290_supply_name[] = {
 	"vdda",
 	"vddd",
@@ -671,6 +718,52 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int imx290_get_selection(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *sd_state,
+				struct v4l2_subdev_selection *sel)
+{
+	struct imx290 *imx290 = to_imx290(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP: {
+		format = imx290_get_pad_format(imx290, sd_state, sel->which);
+
+		mutex_lock(&imx290->lock);
+
+		sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP
+			   + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2;
+		sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT
+			    + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2;
+		sel->r.width = format->width;
+		sel->r.height = format->height;
+
+		mutex_unlock(&imx290->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 = IMX290_PIXEL_ARRAY_WIDTH;
+		sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT;
+
+		return 0;
+
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP;
+		sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT;
+		sel->r.width = IMX290_PIXEL_ARRAY_RECORDING_WIDTH;
+		sel->r.height = IMX290_PIXEL_ARRAY_RECORDING_HEIGHT;
+
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
 static int imx290_entity_init_cfg(struct v4l2_subdev *subdev,
 				  struct v4l2_subdev_state *sd_state)
 {
@@ -887,6 +980,7 @@ static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
 	.enum_frame_size = imx290_enum_frame_size,
 	.get_fmt = imx290_get_fmt,
 	.set_fmt = imx290_set_fmt,
+	.get_selection = imx290_get_selection,
 };
 
 static const struct v4l2_subdev_ops imx290_subdev_ops = {
-- 
Regards,

Laurent Pinchart


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

* [PATCH 19/19] media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (17 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 18/19] media: i2c: imx290: Add crop selection targets support Laurent Pinchart
@ 2022-07-21  8:35 ` Laurent Pinchart
  2022-07-21 10:11   ` Alexander Stein
  2022-08-23  1:11 ` [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21  8:35 UTC (permalink / raw)
  To: linux-media; +Cc: Manivannan Sadhasivam, Sakari Ailus

The IMX290 gain register controls the analogue gain. Replace the
V4L2_CID_GAIN control with V4L2_CID_ANALOGUE_GAIN.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/imx290.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
index 0cb11ec1cf0f..871e3e69a8a4 100644
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -524,7 +524,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
 		return 0;
 
 	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
+	case V4L2_CID_ANALOGUE_GAIN:
 		ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
 		break;
 
@@ -1006,7 +1006,7 @@ static int imx290_ctrl_init(struct imx290 *imx290)
 	imx290->ctrls.lock = &imx290->lock;
 
 	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
-			  V4L2_CID_GAIN, 0, 240, 1, 0);
+			  V4L2_CID_ANALOGUE_GAIN, 0, 240, 1, 0);
 
 	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
 			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,
-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal
  2022-07-21  8:35 ` [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal Laurent Pinchart
@ 2022-07-21  9:18   ` Alexander Stein
  2022-07-21 11:31     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21  9:18 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent,

thanks for working on this, I've also some patches on top for imx327 support.

Am Donnerstag, 21. Juli 2022, 10:35:24 CEST schrieb Laurent Pinchart:
> The HMAX value specifies the total line length in pixels. It's thus more
> readable in decimal than hexadecimal. Fix it.

I understand the motivation, pixels are more natural in decimal numbers, but 
e.g. what is 4400 pixels on this sensor? It is only mentioned sparsely and 
3300d is not mentioned at all, 0ce4h is instead.
I also like to have the hexadecimal numbers here as you can find them directly 
in the datasheet. To me this seems more sensible for cross-checking. Just my 
opinion.

Best regards,
Alexander

> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 64bd43813dbf..f60a4135dc9c 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -308,7 +308,7 @@ static const struct imx290_mode imx290_modes_2lanes[] =
> { {
>  		.width = 1920,
>  		.height = 1080,
> -		.hmax = 0x1130,
> +		.hmax = 4400,
>  		.link_freq_index = FREQ_INDEX_1080P,
>  		.data = imx290_1080p_settings,
>  		.data_size = ARRAY_SIZE(imx290_1080p_settings),
> @@ -316,7 +316,7 @@ static const struct imx290_mode imx290_modes_2lanes[] =
> { {
>  		.width = 1280,
>  		.height = 720,
> -		.hmax = 0x19c8,
> +		.hmax = 6600,
>  		.link_freq_index = FREQ_INDEX_720P,
>  		.data = imx290_720p_settings,
>  		.data_size = ARRAY_SIZE(imx290_720p_settings),
> @@ -327,7 +327,7 @@ static const struct imx290_mode imx290_modes_4lanes[] =
> { {
>  		.width = 1920,
>  		.height = 1080,
> -		.hmax = 0x0898,
> +		.hmax = 2200,
>  		.link_freq_index = FREQ_INDEX_1080P,
>  		.data = imx290_1080p_settings,
>  		.data_size = ARRAY_SIZE(imx290_1080p_settings),
> @@ -335,7 +335,7 @@ static const struct imx290_mode imx290_modes_4lanes[] =
> { {
>  		.width = 1280,
>  		.height = 720,
> -		.hmax = 0x0ce4,
> +		.hmax = 3300,
>  		.link_freq_index = FREQ_INDEX_720P,
>  		.data = imx290_720p_settings,
>  		.data_size = ARRAY_SIZE(imx290_720p_settings),





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

* Re: [PATCH 01/19] media: i2c: imx290: Use device lock for the control handler
  2022-07-21  8:35 ` [PATCH 01/19] media: i2c: imx290: Use device lock for the control handler Laurent Pinchart
@ 2022-07-21  9:22   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21  9:22 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:22 CEST schrieb Laurent Pinchart:
> The link frequency and pixel rate controls are set without holding the
> control handler lock, resulting in kernel warnings. As the value of
> those controls depend on the format, the simplest fix is to use the
> device lock for the control handler.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 99f2a50d39a4..d97a5fb1d501 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -1043,6 +1043,7 @@ static int imx290_probe(struct i2c_client *client)
>  	imx290_entity_init_cfg(&imx290->sd, NULL);
> 
>  	v4l2_ctrl_handler_init(&imx290->ctrls, 4);
> +	imx290->ctrls.lock = &imx290->lock;
> 
>  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
>  			  V4L2_CID_GAIN, 0, 72, 1, 0);

Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 02/19] media: i2c: imx290: Print error code when I2C transfer fails
  2022-07-21  8:35 ` [PATCH 02/19] media: i2c: imx290: Print error code when I2C transfer fails Laurent Pinchart
@ 2022-07-21  9:23   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21  9:23 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:23 CEST schrieb Laurent Pinchart:
> Knowing why I2C transfers fail is useful for debugging. Extend the error
> message to print the error code.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index d97a5fb1d501..64bd43813dbf 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -370,7 +370,8 @@ static inline int __always_unused imx290_read_reg(struct
> imx290 *imx290, u16 add
> 
>  	ret = regmap_read(imx290->regmap, addr, &regval);
>  	if (ret) {
> -		dev_err(imx290->dev, "I2C read failed for addr: %x\n", 
addr);
> +		dev_err(imx290->dev, "Failed to read register 0x%04x: 
%d\n",
> +			addr, ret);
>  		return ret;
>  	}
> 
> @@ -385,7 +386,8 @@ static int imx290_write_reg(struct imx290 *imx290, u16
> addr, u8 value)
> 
>  	ret = regmap_write(imx290->regmap, addr, value);
>  	if (ret) {
> -		dev_err(imx290->dev, "I2C write failed for addr: %x\n", 
addr);
> +		dev_err(imx290->dev, "Failed to write register 0x%04x: 
%d\n",
> +			addr, ret);
>  		return ret;
>  	}

Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 04/19] media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
  2022-07-21  8:35 ` [PATCH 04/19] media: i2c: imx290: Replace macro with explicit ARRAY_SIZE() Laurent Pinchart
@ 2022-07-21  9:23   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21  9:23 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:25 CEST schrieb Laurent Pinchart:
> Use ARRAY_SIZE(imx290->supplies) for code that needs the size of the
> array, instead of relying on the IMX290_NUM_SUPPLIES. The result is less
> error-prone as it ties the size to the array.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index f60a4135dc9c..9a0c458a3af0 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -790,10 +790,10 @@ static int imx290_get_regulators(struct device *dev,
> struct imx290 *imx290) {
>  	unsigned int i;
> 
> -	for (i = 0; i < IMX290_NUM_SUPPLIES; i++)
> +	for (i = 0; i < ARRAY_SIZE(imx290->supplies); i++)
>  		imx290->supplies[i].supply = imx290_supply_name[i];
> 
> -	return devm_regulator_bulk_get(dev, IMX290_NUM_SUPPLIES,
> +	return devm_regulator_bulk_get(dev, ARRAY_SIZE(imx290->supplies),
>  				       imx290->supplies);
>  }
> 
> @@ -852,7 +852,8 @@ static int imx290_power_on(struct device *dev)
>  		return ret;
>  	}
> 
> -	ret = regulator_bulk_enable(IMX290_NUM_SUPPLIES, imx290->supplies);
> +	ret = regulator_bulk_enable(ARRAY_SIZE(imx290->supplies),
> +				    imx290->supplies);
>  	if (ret) {
>  		dev_err(dev, "Failed to enable regulators\n");
>  		clk_disable_unprepare(imx290->xclk);
> @@ -876,7 +877,7 @@ static int imx290_power_off(struct device *dev)
> 
>  	clk_disable_unprepare(imx290->xclk);
>  	gpiod_set_value_cansleep(imx290->rst_gpio, 1);
> -	regulator_bulk_disable(IMX290_NUM_SUPPLIES, imx290->supplies);
> +	regulator_bulk_disable(ARRAY_SIZE(imx290->supplies), imx290-
>supplies);
> 
>  	return 0;
>  }

Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 05/19] media: i2c: imx290: Drop imx290_write_buffered_reg()
  2022-07-21  8:35 ` [PATCH 05/19] media: i2c: imx290: Drop imx290_write_buffered_reg() Laurent Pinchart
@ 2022-07-21  9:24   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21  9:24 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:26 CEST schrieb Laurent Pinchart:
> The imx290_write_buffered_reg() function wraps a register write with
> register hold, to enable changing multiple registers synchronously. It
> is used for the gain only, which is an 8-bit register, defeating its
> purpose.
> 
> The feature is useful, but should be implemented differently. Drop the
> function for now, to prepare for a rework of register access.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 32 +-------------------------------
>  1 file changed, 1 insertion(+), 31 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 9a0c458a3af0..f280ded2dac3 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -413,41 +413,11 @@ static int imx290_set_register_array(struct imx290
> *imx290, return 0;
>  }
> 
> -static int imx290_write_buffered_reg(struct imx290 *imx290, u16
> address_low, -				     u8 nr_regs, u32 
value)
> -{
> -	unsigned int i;
> -	int ret;
> -
> -	ret = imx290_write_reg(imx290, IMX290_REGHOLD, 0x01);
> -	if (ret) {
> -		dev_err(imx290->dev, "Error setting hold register\n");
> -		return ret;
> -	}
> -
> -	for (i = 0; i < nr_regs; i++) {
> -		ret = imx290_write_reg(imx290, address_low + i,
> -				       (u8)(value >> (i * 8)));
> -		if (ret) {
> -			dev_err(imx290->dev, "Error writing buffered 
registers\n");
> -			return ret;
> -		}
> -	}
> -
> -	ret = imx290_write_reg(imx290, IMX290_REGHOLD, 0x00);
> -	if (ret) {
> -		dev_err(imx290->dev, "Error setting hold register\n");
> -		return ret;
> -	}
> -
> -	return ret;
> -}
> -
>  static int imx290_set_gain(struct imx290 *imx290, u32 value)
>  {
>  	int ret;
> 
> -	ret = imx290_write_buffered_reg(imx290, IMX290_GAIN, 1, value);
> +	ret = imx290_write_reg(imx290, IMX290_GAIN, value);
>  	if (ret)
>  		dev_err(imx290->dev, "Unable to write gain\n");

Acked-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 06/19] media: i2c: imx290: Drop regmap cache
  2022-07-21  8:35 ` [PATCH 06/19] media: i2c: imx290: Drop regmap cache Laurent Pinchart
@ 2022-07-21  9:27   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21  9:27 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:27 CEST schrieb Laurent Pinchart:
> Only two registers are ever read, and once only. There's no need to
> cache values.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index f280ded2dac3..711282126c34 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -97,7 +97,6 @@ static const struct imx290_pixfmt imx290_formats[] = {
>  static const struct regmap_config imx290_regmap_config = {
>  	.reg_bits = 16,
>  	.val_bits = 8,
> -	.cache_type = REGCACHE_RBTREE,
>  };
> 
>  static const char * const imx290_test_pattern_menu[] = {

Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-21  8:35 ` [PATCH 07/19] media: i2c: imx290: Support variable-sized registers Laurent Pinchart
@ 2022-07-21  9:43   ` Alexander Stein
  2022-07-21 10:54     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21  9:43 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hello Laurent,

thanks for updating the driver.

Am Donnerstag, 21. Juli 2022, 10:35:28 CEST schrieb Laurent Pinchart:
> The IMX290 has registers of different sizes. To simplify the code,
> handle this in the read/write functions instead of in the callers by
> encoding the register size in the symbolic name macros. All registers
> are defined as 8-bit for now, a subsequent change will move to larger
> registers where applicable.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 352 +++++++++++++++++++------------------
>  1 file changed, 180 insertions(+), 172 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 711282126c34..ac58bfe6db7f 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -22,22 +22,28 @@
>  #include <media/v4l2-fwnode.h>
>  #include <media/v4l2-subdev.h>
> 
> -#define IMX290_STANDBY 0x3000
> -#define IMX290_REGHOLD 0x3001
> -#define IMX290_XMSTA 0x3002
> -#define IMX290_FR_FDG_SEL 0x3009
> -#define IMX290_BLKLEVEL_LOW 0x300a
> -#define IMX290_BLKLEVEL_HIGH 0x300b
> -#define IMX290_GAIN 0x3014
> -#define IMX290_HMAX_LOW 0x301c
> -#define IMX290_HMAX_HIGH 0x301d
> -#define IMX290_PGCTRL 0x308c
> -#define IMX290_PHY_LANE_NUM 0x3407
> -#define IMX290_CSI_LANE_MODE 0x3443
> +#define IMX290_REG_8BIT(n)				((1 << 16) | 
(n))
> +#define IMX290_REG_16BIT(n)				((2 << 16) | 
(n))
> +#define IMX290_REG_24BIT(n)				((3 << 16) | 
(n))

IMX290_REG_SIZE_SHIFT instead of 16 here? Not exactly necessary, but use
1U, 2U and 3U instead.

> +#define IMX290_REG_SIZE_SHIFT				16
> +#define IMX290_REG_ADDR_MASK				0xffff
> 
> -#define IMX290_PGCTRL_REGEN BIT(0)
> -#define IMX290_PGCTRL_THRU BIT(1)
> -#define IMX290_PGCTRL_MODE(n) ((n) << 4)
> +#define IMX290_STANDBY					
IMX290_REG_8BIT(0x3000)
> +#define IMX290_REGHOLD					
IMX290_REG_8BIT(0x3001)
> +#define IMX290_XMSTA					
IMX290_REG_8BIT(0x3002)
> +#define IMX290_FR_FDG_SEL				
IMX290_REG_8BIT(0x3009)
> +#define IMX290_BLKLEVEL_LOW				
IMX290_REG_8BIT(0x300a)
> +#define IMX290_BLKLEVEL_HIGH				
IMX290_REG_8BIT(0x300b)
> +#define IMX290_GAIN					
IMX290_REG_8BIT(0x3014)
> +#define IMX290_HMAX_LOW					
IMX290_REG_8BIT(0x301c)
> +#define IMX290_HMAX_HIGH				
IMX290_REG_8BIT(0x301d)
> +#define IMX290_PGCTRL					
IMX290_REG_8BIT(0x308c)
> +#define IMX290_PHY_LANE_NUM				
IMX290_REG_8BIT(0x3407)
> +#define IMX290_CSI_LANE_MODE				
IMX290_REG_8BIT(0x3443)
> +
> +#define IMX290_PGCTRL_REGEN				BIT(0)
> +#define IMX290_PGCTRL_THRU				BIT(1)
> +#define IMX290_PGCTRL_MODE(n)				((n) << 4)
> 
>  static const char * const imx290_supply_name[] = {
>  	"vdda",
> @@ -48,7 +54,7 @@ static const char * const imx290_supply_name[] = {
>  #define IMX290_NUM_SUPPLIES ARRAY_SIZE(imx290_supply_name)
> 
>  struct imx290_regval {
> -	u16 reg;
> +	u32 reg;
>  	u8 val;
>  };
> 
> @@ -111,163 +117,163 @@ static const char * const imx290_test_pattern_menu[]
> = { };
> 
>  static const struct imx290_regval imx290_global_init_settings[] = {
> -	{ 0x3007, 0x00 },
> -	{ 0x3018, 0x65 },
> -	{ 0x3019, 0x04 },
> -	{ 0x301a, 0x00 },
> -	{ 0x3444, 0x20 },
> -	{ 0x3445, 0x25 },
> -	{ 0x303a, 0x0c },
> -	{ 0x3040, 0x00 },
> -	{ 0x3041, 0x00 },
> -	{ 0x303c, 0x00 },
> -	{ 0x303d, 0x00 },
> -	{ 0x3042, 0x9c },
> -	{ 0x3043, 0x07 },
> -	{ 0x303e, 0x49 },
> -	{ 0x303f, 0x04 },
> -	{ 0x304b, 0x0a },
> -	{ 0x300f, 0x00 },
> -	{ 0x3010, 0x21 },
> -	{ 0x3012, 0x64 },
> -	{ 0x3016, 0x09 },
> -	{ 0x3070, 0x02 },
> -	{ 0x3071, 0x11 },
> -	{ 0x309b, 0x10 },
> -	{ 0x309c, 0x22 },
> -	{ 0x30a2, 0x02 },
> -	{ 0x30a6, 0x20 },
> -	{ 0x30a8, 0x20 },
> -	{ 0x30aa, 0x20 },
> -	{ 0x30ac, 0x20 },
> -	{ 0x30b0, 0x43 },
> -	{ 0x3119, 0x9e },
> -	{ 0x311c, 0x1e },
> -	{ 0x311e, 0x08 },
> -	{ 0x3128, 0x05 },
> -	{ 0x313d, 0x83 },
> -	{ 0x3150, 0x03 },
> -	{ 0x317e, 0x00 },
> -	{ 0x32b8, 0x50 },
> -	{ 0x32b9, 0x10 },
> -	{ 0x32ba, 0x00 },
> -	{ 0x32bb, 0x04 },
> -	{ 0x32c8, 0x50 },
> -	{ 0x32c9, 0x10 },
> -	{ 0x32ca, 0x00 },
> -	{ 0x32cb, 0x04 },
> -	{ 0x332c, 0xd3 },
> -	{ 0x332d, 0x10 },
> -	{ 0x332e, 0x0d },
> -	{ 0x3358, 0x06 },
> -	{ 0x3359, 0xe1 },
> -	{ 0x335a, 0x11 },
> -	{ 0x3360, 0x1e },
> -	{ 0x3361, 0x61 },
> -	{ 0x3362, 0x10 },
> -	{ 0x33b0, 0x50 },
> -	{ 0x33b2, 0x1a },
> -	{ 0x33b3, 0x04 },
> +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> +	{ IMX290_REG_8BIT(0x3018), 0x65 },
> +	{ IMX290_REG_8BIT(0x3019), 0x04 },
> +	{ IMX290_REG_8BIT(0x301a), 0x00 },
> +	{ IMX290_REG_8BIT(0x3444), 0x20 },
> +	{ IMX290_REG_8BIT(0x3445), 0x25 },
> +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> +	{ IMX290_REG_8BIT(0x3040), 0x00 },
> +	{ IMX290_REG_8BIT(0x3041), 0x00 },
> +	{ IMX290_REG_8BIT(0x303c), 0x00 },
> +	{ IMX290_REG_8BIT(0x303d), 0x00 },
> +	{ IMX290_REG_8BIT(0x3042), 0x9c },
> +	{ IMX290_REG_8BIT(0x3043), 0x07 },
> +	{ IMX290_REG_8BIT(0x303e), 0x49 },
> +	{ IMX290_REG_8BIT(0x303f), 0x04 },
> +	{ IMX290_REG_8BIT(0x304b), 0x0a },
> +	{ IMX290_REG_8BIT(0x300f), 0x00 },
> +	{ IMX290_REG_8BIT(0x3010), 0x21 },
> +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> +	{ IMX290_REG_8BIT(0x3016), 0x09 },
> +	{ IMX290_REG_8BIT(0x3070), 0x02 },
> +	{ IMX290_REG_8BIT(0x3071), 0x11 },
> +	{ IMX290_REG_8BIT(0x309b), 0x10 },
> +	{ IMX290_REG_8BIT(0x309c), 0x22 },
> +	{ IMX290_REG_8BIT(0x30a2), 0x02 },
> +	{ IMX290_REG_8BIT(0x30a6), 0x20 },
> +	{ IMX290_REG_8BIT(0x30a8), 0x20 },
> +	{ IMX290_REG_8BIT(0x30aa), 0x20 },
> +	{ IMX290_REG_8BIT(0x30ac), 0x20 },
> +	{ IMX290_REG_8BIT(0x30b0), 0x43 },
> +	{ IMX290_REG_8BIT(0x3119), 0x9e },
> +	{ IMX290_REG_8BIT(0x311c), 0x1e },
> +	{ IMX290_REG_8BIT(0x311e), 0x08 },
> +	{ IMX290_REG_8BIT(0x3128), 0x05 },
> +	{ IMX290_REG_8BIT(0x313d), 0x83 },
> +	{ IMX290_REG_8BIT(0x3150), 0x03 },
> +	{ IMX290_REG_8BIT(0x317e), 0x00 },
> +	{ IMX290_REG_8BIT(0x32b8), 0x50 },
> +	{ IMX290_REG_8BIT(0x32b9), 0x10 },
> +	{ IMX290_REG_8BIT(0x32ba), 0x00 },
> +	{ IMX290_REG_8BIT(0x32bb), 0x04 },
> +	{ IMX290_REG_8BIT(0x32c8), 0x50 },
> +	{ IMX290_REG_8BIT(0x32c9), 0x10 },
> +	{ IMX290_REG_8BIT(0x32ca), 0x00 },
> +	{ IMX290_REG_8BIT(0x32cb), 0x04 },
> +	{ IMX290_REG_8BIT(0x332c), 0xd3 },
> +	{ IMX290_REG_8BIT(0x332d), 0x10 },
> +	{ IMX290_REG_8BIT(0x332e), 0x0d },
> +	{ IMX290_REG_8BIT(0x3358), 0x06 },
> +	{ IMX290_REG_8BIT(0x3359), 0xe1 },
> +	{ IMX290_REG_8BIT(0x335a), 0x11 },
> +	{ IMX290_REG_8BIT(0x3360), 0x1e },
> +	{ IMX290_REG_8BIT(0x3361), 0x61 },
> +	{ IMX290_REG_8BIT(0x3362), 0x10 },
> +	{ IMX290_REG_8BIT(0x33b0), 0x50 },
> +	{ IMX290_REG_8BIT(0x33b2), 0x1a },
> +	{ IMX290_REG_8BIT(0x33b3), 0x04 },
>  };
> 
>  static const struct imx290_regval imx290_1080p_settings[] = {
>  	/* mode settings */
> -	{ 0x3007, 0x00 },
> -	{ 0x303a, 0x0c },
> -	{ 0x3414, 0x0a },
> -	{ 0x3472, 0x80 },
> -	{ 0x3473, 0x07 },
> -	{ 0x3418, 0x38 },
> -	{ 0x3419, 0x04 },
> -	{ 0x3012, 0x64 },
> -	{ 0x3013, 0x00 },
> -	{ 0x305c, 0x18 },
> -	{ 0x305d, 0x03 },
> -	{ 0x305e, 0x20 },
> -	{ 0x305f, 0x01 },
> -	{ 0x315e, 0x1a },
> -	{ 0x3164, 0x1a },
> -	{ 0x3480, 0x49 },
> +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> +	{ IMX290_REG_8BIT(0x3414), 0x0a },
> +	{ IMX290_REG_8BIT(0x3472), 0x80 },
> +	{ IMX290_REG_8BIT(0x3473), 0x07 },
> +	{ IMX290_REG_8BIT(0x3418), 0x38 },
> +	{ IMX290_REG_8BIT(0x3419), 0x04 },
> +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> +	{ IMX290_REG_8BIT(0x305c), 0x18 },
> +	{ IMX290_REG_8BIT(0x305d), 0x03 },
> +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> +	{ IMX290_REG_8BIT(0x3480), 0x49 },
>  	/* data rate settings */
> -	{ 0x3405, 0x10 },
> -	{ 0x3446, 0x57 },
> -	{ 0x3447, 0x00 },
> -	{ 0x3448, 0x37 },
> -	{ 0x3449, 0x00 },
> -	{ 0x344a, 0x1f },
> -	{ 0x344b, 0x00 },
> -	{ 0x344c, 0x1f },
> -	{ 0x344d, 0x00 },
> -	{ 0x344e, 0x1f },
> -	{ 0x344f, 0x00 },
> -	{ 0x3450, 0x77 },
> -	{ 0x3451, 0x00 },
> -	{ 0x3452, 0x1f },
> -	{ 0x3453, 0x00 },
> -	{ 0x3454, 0x17 },
> -	{ 0x3455, 0x00 },
> +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> +	{ IMX290_REG_8BIT(0x3446), 0x57 },
> +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> +	{ IMX290_REG_8BIT(0x3448), 0x37 },
> +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> +	{ IMX290_REG_8BIT(0x344a), 0x1f },
> +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> +	{ IMX290_REG_8BIT(0x344c), 0x1f },
> +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> +	{ IMX290_REG_8BIT(0x344e), 0x1f },
> +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> +	{ IMX290_REG_8BIT(0x3450), 0x77 },
> +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> +	{ IMX290_REG_8BIT(0x3452), 0x1f },
> +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> +	{ IMX290_REG_8BIT(0x3455), 0x00 },
>  };
> 
>  static const struct imx290_regval imx290_720p_settings[] = {
>  	/* mode settings */
> -	{ 0x3007, 0x10 },
> -	{ 0x303a, 0x06 },
> -	{ 0x3414, 0x04 },
> -	{ 0x3472, 0x00 },
> -	{ 0x3473, 0x05 },
> -	{ 0x3418, 0xd0 },
> -	{ 0x3419, 0x02 },
> -	{ 0x3012, 0x64 },
> -	{ 0x3013, 0x00 },
> -	{ 0x305c, 0x20 },
> -	{ 0x305d, 0x00 },
> -	{ 0x305e, 0x20 },
> -	{ 0x305f, 0x01 },
> -	{ 0x315e, 0x1a },
> -	{ 0x3164, 0x1a },
> -	{ 0x3480, 0x49 },
> +	{ IMX290_REG_8BIT(0x3007), 0x10 },
> +	{ IMX290_REG_8BIT(0x303a), 0x06 },
> +	{ IMX290_REG_8BIT(0x3414), 0x04 },
> +	{ IMX290_REG_8BIT(0x3472), 0x00 },
> +	{ IMX290_REG_8BIT(0x3473), 0x05 },
> +	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> +	{ IMX290_REG_8BIT(0x3419), 0x02 },
> +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> +	{ IMX290_REG_8BIT(0x305c), 0x20 },
> +	{ IMX290_REG_8BIT(0x305d), 0x00 },
> +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> +	{ IMX290_REG_8BIT(0x3480), 0x49 },
>  	/* data rate settings */
> -	{ 0x3405, 0x10 },
> -	{ 0x3446, 0x4f },
> -	{ 0x3447, 0x00 },
> -	{ 0x3448, 0x2f },
> -	{ 0x3449, 0x00 },
> -	{ 0x344a, 0x17 },
> -	{ 0x344b, 0x00 },
> -	{ 0x344c, 0x17 },
> -	{ 0x344d, 0x00 },
> -	{ 0x344e, 0x17 },
> -	{ 0x344f, 0x00 },
> -	{ 0x3450, 0x57 },
> -	{ 0x3451, 0x00 },
> -	{ 0x3452, 0x17 },
> -	{ 0x3453, 0x00 },
> -	{ 0x3454, 0x17 },
> -	{ 0x3455, 0x00 },
> +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> +	{ IMX290_REG_8BIT(0x3446), 0x4f },
> +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> +	{ IMX290_REG_8BIT(0x3448), 0x2f },
> +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> +	{ IMX290_REG_8BIT(0x344a), 0x17 },
> +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> +	{ IMX290_REG_8BIT(0x344c), 0x17 },
> +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> +	{ IMX290_REG_8BIT(0x344e), 0x17 },
> +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> +	{ IMX290_REG_8BIT(0x3450), 0x57 },
> +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> +	{ IMX290_REG_8BIT(0x3452), 0x17 },
> +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> +	{ IMX290_REG_8BIT(0x3455), 0x00 },
>  };
> 
>  static const struct imx290_regval imx290_10bit_settings[] = {
> -	{ 0x3005, 0x00},
> -	{ 0x3046, 0x00},
> -	{ 0x3129, 0x1d},
> -	{ 0x317c, 0x12},
> -	{ 0x31ec, 0x37},
> -	{ 0x3441, 0x0a},
> -	{ 0x3442, 0x0a},
> -	{ 0x300a, 0x3c},
> -	{ 0x300b, 0x00},
> +	{ IMX290_REG_8BIT(0x3005), 0x00},
> +	{ IMX290_REG_8BIT(0x3046), 0x00},
> +	{ IMX290_REG_8BIT(0x3129), 0x1d},
> +	{ IMX290_REG_8BIT(0x317c), 0x12},
> +	{ IMX290_REG_8BIT(0x31ec), 0x37},
> +	{ IMX290_REG_8BIT(0x3441), 0x0a},
> +	{ IMX290_REG_8BIT(0x3442), 0x0a},
> +	{ IMX290_REG_8BIT(0x300a), 0x3c},
> +	{ IMX290_REG_8BIT(0x300b), 0x00},
>  };
> 
>  static const struct imx290_regval imx290_12bit_settings[] = {
> -	{ 0x3005, 0x01 },
> -	{ 0x3046, 0x01 },
> -	{ 0x3129, 0x00 },
> -	{ 0x317c, 0x00 },
> -	{ 0x31ec, 0x0e },
> -	{ 0x3441, 0x0c },
> -	{ 0x3442, 0x0c },
> -	{ 0x300a, 0xf0 },
> -	{ 0x300b, 0x00 },
> +	{ IMX290_REG_8BIT(0x3005), 0x01 },
> +	{ IMX290_REG_8BIT(0x3046), 0x01 },
> +	{ IMX290_REG_8BIT(0x3129), 0x00 },
> +	{ IMX290_REG_8BIT(0x317c), 0x00 },
> +	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> +	{ IMX290_REG_8BIT(0x3441), 0x0c },
> +	{ IMX290_REG_8BIT(0x3442), 0x0c },
> +	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> +	{ IMX290_REG_8BIT(0x300b), 0x00 },
>  };
> 
>  /* supported link frequencies */
> @@ -362,33 +368,35 @@ static inline struct imx290 *to_imx290(struct
> v4l2_subdev *_sd) return container_of(_sd, struct imx290, sd);
>  }
> 
> -static inline int __always_unused imx290_read_reg(struct imx290 *imx290,
> u16 addr, u8 *value) +static int __always_unused imx290_read_reg(struct
> imx290 *imx290, u32 addr, u32 *value) {
> -	unsigned int regval;
> +	u8 data[3] = { 0, 0, 0 };
>  	int ret;
> 
> -	ret = regmap_read(imx290->regmap, addr, &regval);
> -	if (ret) {
> -		dev_err(imx290->dev, "Failed to read register 0x%04x: 
%d\n",
> -			addr, ret);
> +	ret = regmap_raw_read(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
> +			      data, (addr >> IMX290_REG_SIZE_SHIFT) & 
3);

While I agree with the intention, it fails for some devices, e.g. Vision 
Components MIPI IMX327 C does not support auto-increment and most probably 
also valid for the IMX290 model.
This is similar to the OV9281 variant, see [1].

Reading ID using 16bit register (using later patch) returns:
> imx290 2-001a: chip ID 0xffd0
Using 2 8bit reads:
imx290 2-001a: chip ID 0x07d0

Best regards,
Alexander

[1] https://patchwork.kernel.org/project/linux-media/patch/
20220715074858.875808-7-alexander.stein@ew.tq-group.com/

> +	if (ret < 0) {
> +		dev_err(imx290->dev, "%u-bit read from 0x%04x failed: 
%d\n",
> +			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
> +			 addr & IMX290_REG_ADDR_MASK, ret);
>  		return ret;
>  	}
> 
> -	*value = regval & 0xff;
> -
> +	*value = (data[2] << 16) | (data[1] << 8) | data[0];
>  	return 0;
>  }
> 
> -static int imx290_write_reg(struct imx290 *imx290, u16 addr, u8 value)
> +static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
>  {
> +	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
>  	int ret;
> 
> -	ret = regmap_write(imx290->regmap, addr, value);
> -	if (ret) {
> -		dev_err(imx290->dev, "Failed to write register 0x%04x: 
%d\n",
> -			addr, ret);
> -		return ret;
> -	}
> +	ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
> +			       data, (addr >> IMX290_REG_SIZE_SHIFT) 
& 3);
> +	if (ret < 0)
> +		dev_err(imx290->dev, "%u-bit write to 0x%04x failed: 
%d\n",
> +			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
> +			 addr & IMX290_REG_ADDR_MASK, ret);
> 
>  	return ret;
>  }





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

* Re: [PATCH 09/19] media: i2c: imx290: Simplify error handling when writing registers
  2022-07-21  8:35 ` [PATCH 09/19] media: i2c: imx290: Simplify error handling when writing registers Laurent Pinchart
@ 2022-07-21  9:50   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21  9:50 UTC (permalink / raw)
  To: linux-media; +Cc: Laurent Pinchart, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:30 CEST schrieb Laurent Pinchart:
> Error handling for register writes requires checking the error status of
> every single write. This makes the code complex, or incorrect when the
> checks are omitted. Simplify this by passing a pointer to an error code
> to the imx290_write_reg() function, which allows writing multiple
> registers in a row and only checking for errors at the end.
> 
> While at it, rename imx290_write_reg() to imx290_write() as there's
> nothing else than registers to write, and rename imx290_read_reg()
> accordingly.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 86 ++++++++++++++------------------------
>  1 file changed, 32 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 3f67c4d2417f..5b7f9027b50f 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -367,7 +367,7 @@ static inline struct imx290 *to_imx290(struct
> v4l2_subdev *_sd) return container_of(_sd, struct imx290, sd);
>  }
> 
> -static int __always_unused imx290_read_reg(struct imx290 *imx290, u32 addr,
> u32 *value) +static int __always_unused imx290_read(struct imx290 *imx290,
> u32 addr, u32 *value) {
>  	u8 data[3] = { 0, 0, 0 };
>  	int ret;
> @@ -385,17 +385,23 @@ static int __always_unused imx290_read_reg(struct
> imx290 *imx290, u32 addr, u32 return 0;
>  }
> 
> -static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
> +static int imx290_write(struct imx290 *imx290, u32 addr, u32 value, int
> *err) {
>  	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
>  	int ret;
> 
> +	if (err && *err)
> +		return *err;
> +
>  	ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
>  			       data, (addr >> IMX290_REG_SIZE_SHIFT) 
& 3);
> -	if (ret < 0)
> +	if (ret < 0) {
>  		dev_err(imx290->dev, "%u-bit write to 0x%04x failed: 
%d\n",
>  			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
>  			 addr & IMX290_REG_ADDR_MASK, ret);
> +		if (err)
> +			*err = ret;
> +	}
> 
>  	return ret;
>  }
> @@ -408,7 +414,7 @@ static int imx290_set_register_array(struct imx290
> *imx290, int ret;
> 
>  	for (i = 0; i < num_settings; ++i, ++settings) {
> -		ret = imx290_write_reg(imx290, settings->reg, settings-
>val);
> +		ret = imx290_write(imx290, settings->reg, settings->val, 
NULL);
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -419,29 +425,16 @@ static int imx290_set_register_array(struct imx290
> *imx290, return 0;
>  }
> 
> -static int imx290_set_gain(struct imx290 *imx290, u32 value)
> -{
> -	int ret;
> -
> -	ret = imx290_write_reg(imx290, IMX290_GAIN, value);
> -	if (ret)
> -		dev_err(imx290->dev, "Unable to write gain\n");
> -
> -	return ret;
> -}
> -
>  /* Stop streaming */
>  static int imx290_stop_streaming(struct imx290 *imx290)
>  {
> -	int ret;
> +	int ret = 0;
> 
> -	ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x01);
> -	if (ret < 0)
> -		return ret;
> +	imx290_write(imx290, IMX290_STANDBY, 0x01, &ret);
> 
>  	msleep(30);
> 
> -	return imx290_write_reg(imx290, IMX290_XMSTA, 0x01);
> +	return imx290_write(imx290, IMX290_XMSTA, 0x01, &ret);
>  }
> 
>  static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
> @@ -456,25 +449,25 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
> 
>  	switch (ctrl->id) {
>  	case V4L2_CID_GAIN:
> -		ret = imx290_set_gain(imx290, ctrl->val);
> +		ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, 
NULL);
>  		break;
>  	case V4L2_CID_TEST_PATTERN:
>  		if (ctrl->val) {
> -			imx290_write_reg(imx290, IMX290_BLKLEVEL, 0);
> +			imx290_write(imx290, IMX290_BLKLEVEL, 0, 
&ret);
>  			usleep_range(10000, 11000);
> -			imx290_write_reg(imx290, IMX290_PGCTRL,
> -					 (u8)
(IMX290_PGCTRL_REGEN |
> -					 IMX290_PGCTRL_THRU |
> -					 
IMX290_PGCTRL_MODE(ctrl->val)));
> +			imx290_write(imx290, IMX290_PGCTRL,
> +				     (u8)(IMX290_PGCTRL_REGEN |
> +				     IMX290_PGCTRL_THRU |
> +				     IMX290_PGCTRL_MODE(ctrl-
>val)), &ret);
>  		} else {
> -			imx290_write_reg(imx290, IMX290_PGCTRL, 
0x00);
> +			imx290_write(imx290, IMX290_PGCTRL, 0x00, 
&ret);
>  			usleep_range(10000, 11000);
>  			if (imx290->bpp == 10)
> -				imx290_write_reg(imx290, 
IMX290_BLKLEVEL,
> -						 0x3c);
> +				imx290_write(imx290, 
IMX290_BLKLEVEL, 0x3c,
> +					     &ret);
>  			else /* 12 bits per pixel */
> -				imx290_write_reg(imx290, 
IMX290_BLKLEVEL,
> -						 0xf0);
> +				imx290_write(imx290, 
IMX290_BLKLEVEL, 0xf0,
> +					     &ret);
>  		}
>  		break;
>  	default:
> @@ -695,7 +688,8 @@ static int imx290_start_streaming(struct imx290 *imx290)
> return ret;
>  	}
> 
> -	ret = imx290_write_reg(imx290, IMX290_HMAX, imx290->current_mode-
>hmax);
> +	ret = imx290_write(imx290, IMX290_HMAX, imx290->current_mode->hmax,
> +			   NULL);
>  	if (ret)
>  		return ret;
> 
> @@ -706,14 +700,12 @@ static int imx290_start_streaming(struct imx290
> *imx290) return ret;
>  	}
> 
> -	ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x00);
> -	if (ret < 0)
> -		return ret;
> +	imx290_write(imx290, IMX290_STANDBY, 0x00, &ret);
> 
>  	msleep(30);

Well you introduce a hard 30ms delay when the i2c transfer above fails, but I 
guess that's negligible.

>  	/* Start streaming */
> -	return imx290_write_reg(imx290, IMX290_XMSTA, 0x00);
> +	return imx290_write(imx290, IMX290_XMSTA, 0x00, &ret);
>  }
> 
>  static int imx290_set_stream(struct v4l2_subdev *sd, int enable)
> @@ -772,27 +764,13 @@ static int imx290_set_data_lanes(struct imx290
> *imx290) * validated in probe itself
>  		 */
>  		dev_err(imx290->dev, "Lane configuration not 
supported\n");
> -		ret = -EINVAL;
> -		goto exit;
> +		return -EINVAL;
>  	}
> 
> -	ret = imx290_write_reg(imx290, IMX290_PHY_LANE_NUM, laneval);
> -	if (ret) {
> -		dev_err(imx290->dev, "Error setting Physical Lane number 
register\n");
> -		goto exit;
> -	}
> -
> -	ret = imx290_write_reg(imx290, IMX290_CSI_LANE_MODE, laneval);
> -	if (ret) {
> -		dev_err(imx290->dev, "Error setting CSI Lane mode 
register\n");
> -		goto exit;
> -	}
> -
> -	ret = imx290_write_reg(imx290, IMX290_FR_FDG_SEL, frsel);
> -	if (ret)
> -		dev_err(imx290->dev, "Error setting FR/FDG SEL 
register\n");
> +	imx290_write(imx290, IMX290_PHY_LANE_NUM, laneval, &ret);
> +	imx290_write(imx290, IMX290_CSI_LANE_MODE, laneval, &ret);
> +	imx290_write(imx290, IMX290_FR_FDG_SEL, frsel, &ret);
> 
> -exit:
>  	return ret;
>  }

Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 10/19] media: i2c: imx290: Define more register macros
  2022-07-21  8:35 ` [PATCH 10/19] media: i2c: imx290: Define more register macros Laurent Pinchart
@ 2022-07-21 10:00   ` Alexander Stein
  2022-07-21 11:08     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:00 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent,

thanks for this patch.

Am Donnerstag, 21. Juli 2022, 10:35:31 CEST schrieb Laurent Pinchart:
> Define macros for all registers programmed by the driver for which
> documentation is available to increase readability. This starts making
> use of 16-bit registers in the register arrays, so the value field has
> to be increased to 32 bits.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 219 +++++++++++++++++++++----------------
>  1 file changed, 124 insertions(+), 95 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 5b7f9027b50f..bec326a83952 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -31,14 +31,73 @@
>  #define IMX290_STANDBY					
IMX290_REG_8BIT(0x3000)
>  #define IMX290_REGHOLD					
IMX290_REG_8BIT(0x3001)
>  #define IMX290_XMSTA					
IMX290_REG_8BIT(0x3002)
> +#define IMX290_ADBIT					
IMX290_REG_8BIT(0x3005)
> +#define IMX290_ADBIT_10BIT				(0 << 0)
> +#define IMX290_ADBIT_12BIT				(1 << 0)
> +#define IMX290_CTRL_07					
IMX290_REG_8BIT(0x3007)
> +#define IMX290_VREVERSE					
BIT(0)
> +#define IMX290_HREVERSE					
BIT(1)
> +#define IMX290_WINMODE_1080P				(0 << 4)
> +#define IMX290_WINMODE_720P				(1 << 4)
> +#define IMX290_WINMODE_CROP				(4 << 4)
>  #define IMX290_FR_FDG_SEL				
IMX290_REG_8BIT(0x3009)
>  #define IMX290_BLKLEVEL					
IMX290_REG_16BIT(0x300a)
>  #define IMX290_GAIN					
IMX290_REG_8BIT(0x3014)
> +#define IMX290_VMAX					
IMX290_REG_24BIT(0x3018)
>  #define IMX290_HMAX					
IMX290_REG_16BIT(0x301c)
> +#define IMX290_SHS1					
IMX290_REG_24BIT(0x3020)
> +#define IMX290_WINWV_OB					
IMX290_REG_8BIT(0x303a)
> +#define IMX290_WINPV					
IMX290_REG_16BIT(0x303c)
> +#define IMX290_WINWV					
IMX290_REG_16BIT(0x303e)
> +#define IMX290_WINPH					
IMX290_REG_16BIT(0x3040)
> +#define IMX290_WINWH					
IMX290_REG_16BIT(0x3042)
> +#define IMX290_OUT_CTRL					
IMX290_REG_8BIT(0x3046)
> +#define IMX290_ODBIT_10BIT				(0 << 0)
> +#define IMX290_ODBIT_12BIT				(1 << 0)

ODBIT is fixed 1h for MIPI-CSI-2 output.

> +#define IMX290_OPORTSEL_PARALLEL			(0x0 << 4)
> +#define IMX290_OPORTSEL_LVDS_2CH			(0xd << 4)
> +#define IMX290_OPORTSEL_LVDS_4CH			(0xe << 4)
> +#define IMX290_OPORTSEL_LVDS_8CH			(0xf << 4)

This driver only supports MIPI-CSI-2 output, but these bits are don't care, 
you still want to list them here for completeness?

> +#define IMX290_XSOUTSEL					
IMX290_REG_8BIT(0x304b)
> +#define IMX290_XSOUTSEL_XVSOUTSEL_HIGH			(0 << 0)
> +#define IMX290_XSOUTSEL_XVSOUTSEL_VSYNC			(2 << 0)
> +#define IMX290_XSOUTSEL_XHSOUTSEL_HIGH			(0 << 2)
> +#define IMX290_XSOUTSEL_XHSOUTSEL_HSYNC			(2 << 2)
> +#define IMX290_INCKSEL1					
IMX290_REG_8BIT(0x305c)
> +#define IMX290_INCKSEL2					
IMX290_REG_8BIT(0x305d)
> +#define IMX290_INCKSEL3					
IMX290_REG_8BIT(0x305e)
> +#define IMX290_INCKSEL4					
IMX290_REG_8BIT(0x305f)
>  #define IMX290_PGCTRL					
IMX290_REG_8BIT(0x308c)
> +#define IMX290_ADBIT1					
IMX290_REG_8BIT(0x3129)
> +#define IMX290_ADBIT1_10BIT				0x1d
> +#define IMX290_ADBIT1_12BIT				0x00
> +#define IMX290_INCKSEL5					
IMX290_REG_8BIT(0x315e)
> +#define IMX290_INCKSEL6					
IMX290_REG_8BIT(0x3164)

Any reason to skip the bit defines for both supported input clocks?

> +#define IMX290_ADBIT2					
IMX290_REG_8BIT(0x317c)
> +#define IMX290_ADBIT2_10BIT				0x12
> +#define IMX290_ADBIT2_12BIT				0x00
>  #define IMX290_CHIP_ID					
IMX290_REG_16BIT(0x319a)
> +#define IMX290_ADBIT3					
IMX290_REG_16BIT(0x31ec)
> +#define IMX290_ADBIT3_10BIT				0x37
> +#define IMX290_ADBIT3_12BIT				0x0e
> +#define IMX290_REPETITION				
IMX290_REG_8BIT(0x3405)
>  #define IMX290_PHY_LANE_NUM				
IMX290_REG_8BIT(0x3407)
> +#define IMX290_OPB_SIZE_V				
IMX290_REG_8BIT(0x3414)
> +#define IMX290_Y_OUT_SIZE				
IMX290_REG_16BIT(0x3418)
> +#define IMX290_CSI_DT_FMT				
IMX290_REG_16BIT(0x3441)
> +#define IMX290_CSI_DT_FMT_RAW10				
0x0a0a
> +#define IMX290_CSI_DT_FMT_RAW12				
0x0c0c
>  #define IMX290_CSI_LANE_MODE				
IMX290_REG_8BIT(0x3443)
> +#define IMX290_EXTCK_FREQ				
IMX290_REG_16BIT(0x3444)

Same here.

Regards,
Alexander

> +#define IMX290_TCLKPOST					
IMX290_REG_16BIT(0x3446)
> +#define IMX290_THSZERO					
IMX290_REG_16BIT(0x3448)
> +#define IMX290_THSPREPARE				
IMX290_REG_16BIT(0x344a)
> +#define IMX290_TCLKTRAIL				
IMX290_REG_16BIT(0x344c)
> +#define IMX290_THSTRAIL					
IMX290_REG_16BIT(0x344e)
> +#define IMX290_TCLKZERO					
IMX290_REG_16BIT(0x3450)
> +#define IMX290_TCLKPREPARE				
IMX290_REG_16BIT(0x3452)
> +#define IMX290_TLPX					
IMX290_REG_16BIT(0x3454)
> +#define IMX290_X_OUT_SIZE				
IMX290_REG_16BIT(0x3472)
> 
>  #define IMX290_PGCTRL_REGEN				BIT(0)
>  #define IMX290_PGCTRL_THRU				BIT(1)
> @@ -54,7 +113,7 @@ static const char * const imx290_supply_name[] = {
> 
>  struct imx290_regval {
>  	u32 reg;
> -	u8 val;
> +	u32 val;
>  };
> 
>  struct imx290_mode {
> @@ -116,22 +175,16 @@ static const char * const imx290_test_pattern_menu[] =
> { };
> 
>  static const struct imx290_regval imx290_global_init_settings[] = {
> -	{ IMX290_REG_8BIT(0x3007), 0x00 },
> -	{ IMX290_REG_8BIT(0x3018), 0x65 },
> -	{ IMX290_REG_8BIT(0x3019), 0x04 },
> -	{ IMX290_REG_8BIT(0x301a), 0x00 },
> -	{ IMX290_REG_8BIT(0x3444), 0x20 },
> -	{ IMX290_REG_8BIT(0x3445), 0x25 },
> -	{ IMX290_REG_8BIT(0x303a), 0x0c },
> -	{ IMX290_REG_8BIT(0x3040), 0x00 },
> -	{ IMX290_REG_8BIT(0x3041), 0x00 },
> -	{ IMX290_REG_8BIT(0x303c), 0x00 },
> -	{ IMX290_REG_8BIT(0x303d), 0x00 },
> -	{ IMX290_REG_8BIT(0x3042), 0x9c },
> -	{ IMX290_REG_8BIT(0x3043), 0x07 },
> -	{ IMX290_REG_8BIT(0x303e), 0x49 },
> -	{ IMX290_REG_8BIT(0x303f), 0x04 },
> -	{ IMX290_REG_8BIT(0x304b), 0x0a },
> +	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> +	{ IMX290_VMAX, 1125 },
> +	{ IMX290_EXTCK_FREQ, 0x2520 },
> +	{ IMX290_WINWV_OB, 12 },
> +	{ IMX290_WINPH, 0 },
> +	{ IMX290_WINPV, 0 },
> +	{ IMX290_WINWH, 1948 },
> +	{ IMX290_WINWV, 1097 },
> +	{ IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
> +			   IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
>  	{ IMX290_REG_8BIT(0x300f), 0x00 },
>  	{ IMX290_REG_8BIT(0x3010), 0x21 },
>  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> @@ -177,102 +230,78 @@ static const struct imx290_regval
> imx290_global_init_settings[] = {
> 
>  static const struct imx290_regval imx290_1080p_settings[] = {
>  	/* mode settings */
> -	{ IMX290_REG_8BIT(0x3007), 0x00 },
> -	{ IMX290_REG_8BIT(0x303a), 0x0c },
> -	{ IMX290_REG_8BIT(0x3414), 0x0a },
> -	{ IMX290_REG_8BIT(0x3472), 0x80 },
> -	{ IMX290_REG_8BIT(0x3473), 0x07 },
> -	{ IMX290_REG_8BIT(0x3418), 0x38 },
> -	{ IMX290_REG_8BIT(0x3419), 0x04 },
> +	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> +	{ IMX290_WINWV_OB, 12 },
> +	{ IMX290_OPB_SIZE_V, 10 },
> +	{ IMX290_X_OUT_SIZE, 1920 },
> +	{ IMX290_Y_OUT_SIZE, 1080 },
>  	{ IMX290_REG_8BIT(0x3012), 0x64 },
>  	{ IMX290_REG_8BIT(0x3013), 0x00 },
> -	{ IMX290_REG_8BIT(0x305c), 0x18 },
> -	{ IMX290_REG_8BIT(0x305d), 0x03 },
> -	{ IMX290_REG_8BIT(0x305e), 0x20 },
> -	{ IMX290_REG_8BIT(0x305f), 0x01 },
> -	{ IMX290_REG_8BIT(0x315e), 0x1a },
> -	{ IMX290_REG_8BIT(0x3164), 0x1a },
> +	{ IMX290_INCKSEL1, 0x18 },
> +	{ IMX290_INCKSEL2, 0x03 },
> +	{ IMX290_INCKSEL3, 0x20 },
> +	{ IMX290_INCKSEL4, 0x01 },
> +	{ IMX290_INCKSEL5, 0x1a },
> +	{ IMX290_INCKSEL6, 0x1a },
>  	{ IMX290_REG_8BIT(0x3480), 0x49 },
>  	/* data rate settings */
> -	{ IMX290_REG_8BIT(0x3405), 0x10 },
> -	{ IMX290_REG_8BIT(0x3446), 0x57 },
> -	{ IMX290_REG_8BIT(0x3447), 0x00 },
> -	{ IMX290_REG_8BIT(0x3448), 0x37 },
> -	{ IMX290_REG_8BIT(0x3449), 0x00 },
> -	{ IMX290_REG_8BIT(0x344a), 0x1f },
> -	{ IMX290_REG_8BIT(0x344b), 0x00 },
> -	{ IMX290_REG_8BIT(0x344c), 0x1f },
> -	{ IMX290_REG_8BIT(0x344d), 0x00 },
> -	{ IMX290_REG_8BIT(0x344e), 0x1f },
> -	{ IMX290_REG_8BIT(0x344f), 0x00 },
> -	{ IMX290_REG_8BIT(0x3450), 0x77 },
> -	{ IMX290_REG_8BIT(0x3451), 0x00 },
> -	{ IMX290_REG_8BIT(0x3452), 0x1f },
> -	{ IMX290_REG_8BIT(0x3453), 0x00 },
> -	{ IMX290_REG_8BIT(0x3454), 0x17 },
> -	{ IMX290_REG_8BIT(0x3455), 0x00 },
> +	{ IMX290_REPETITION, 0x10 },
> +	{ IMX290_TCLKPOST, 87 },
> +	{ IMX290_THSZERO, 55 },
> +	{ IMX290_THSPREPARE, 31 },
> +	{ IMX290_TCLKTRAIL, 31 },
> +	{ IMX290_THSTRAIL, 31 },
> +	{ IMX290_TCLKZERO, 119 },
> +	{ IMX290_TCLKPREPARE, 31 },
> +	{ IMX290_TLPX, 23 },
>  };
> 
>  static const struct imx290_regval imx290_720p_settings[] = {
>  	/* mode settings */
> -	{ IMX290_REG_8BIT(0x3007), 0x10 },
> -	{ IMX290_REG_8BIT(0x303a), 0x06 },
> -	{ IMX290_REG_8BIT(0x3414), 0x04 },
> -	{ IMX290_REG_8BIT(0x3472), 0x00 },
> -	{ IMX290_REG_8BIT(0x3473), 0x05 },
> -	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> -	{ IMX290_REG_8BIT(0x3419), 0x02 },
> +	{ IMX290_CTRL_07, IMX290_WINMODE_720P },
> +	{ IMX290_WINWV_OB, 6 },
> +	{ IMX290_OPB_SIZE_V, 4 },
> +	{ IMX290_X_OUT_SIZE, 1280 },
> +	{ IMX290_Y_OUT_SIZE, 720 },
>  	{ IMX290_REG_8BIT(0x3012), 0x64 },
>  	{ IMX290_REG_8BIT(0x3013), 0x00 },
> -	{ IMX290_REG_8BIT(0x305c), 0x20 },
> -	{ IMX290_REG_8BIT(0x305d), 0x00 },
> -	{ IMX290_REG_8BIT(0x305e), 0x20 },
> -	{ IMX290_REG_8BIT(0x305f), 0x01 },
> -	{ IMX290_REG_8BIT(0x315e), 0x1a },
> -	{ IMX290_REG_8BIT(0x3164), 0x1a },
> +	{ IMX290_INCKSEL1, 0x20 },
> +	{ IMX290_INCKSEL2, 0x00 },
> +	{ IMX290_INCKSEL3, 0x20 },
> +	{ IMX290_INCKSEL4, 0x01 },
> +	{ IMX290_INCKSEL5, 0x1a },
> +	{ IMX290_INCKSEL6, 0x1a },
>  	{ IMX290_REG_8BIT(0x3480), 0x49 },
>  	/* data rate settings */
> -	{ IMX290_REG_8BIT(0x3405), 0x10 },
> -	{ IMX290_REG_8BIT(0x3446), 0x4f },
> -	{ IMX290_REG_8BIT(0x3447), 0x00 },
> -	{ IMX290_REG_8BIT(0x3448), 0x2f },
> -	{ IMX290_REG_8BIT(0x3449), 0x00 },
> -	{ IMX290_REG_8BIT(0x344a), 0x17 },
> -	{ IMX290_REG_8BIT(0x344b), 0x00 },
> -	{ IMX290_REG_8BIT(0x344c), 0x17 },
> -	{ IMX290_REG_8BIT(0x344d), 0x00 },
> -	{ IMX290_REG_8BIT(0x344e), 0x17 },
> -	{ IMX290_REG_8BIT(0x344f), 0x00 },
> -	{ IMX290_REG_8BIT(0x3450), 0x57 },
> -	{ IMX290_REG_8BIT(0x3451), 0x00 },
> -	{ IMX290_REG_8BIT(0x3452), 0x17 },
> -	{ IMX290_REG_8BIT(0x3453), 0x00 },
> -	{ IMX290_REG_8BIT(0x3454), 0x17 },
> -	{ IMX290_REG_8BIT(0x3455), 0x00 },
> +	{ IMX290_REPETITION, 0x10 },
> +	{ IMX290_TCLKPOST, 79 },
> +	{ IMX290_THSZERO, 47 },
> +	{ IMX290_THSPREPARE, 23 },
> +	{ IMX290_TCLKTRAIL, 23 },
> +	{ IMX290_THSTRAIL, 23 },
> +	{ IMX290_TCLKZERO, 87 },
> +	{ IMX290_TCLKPREPARE, 23 },
> +	{ IMX290_TLPX, 23 },
>  };
> 
>  static const struct imx290_regval imx290_10bit_settings[] = {
> -	{ IMX290_REG_8BIT(0x3005), 0x00},
> -	{ IMX290_REG_8BIT(0x3046), 0x00},
> -	{ IMX290_REG_8BIT(0x3129), 0x1d},
> -	{ IMX290_REG_8BIT(0x317c), 0x12},
> -	{ IMX290_REG_8BIT(0x31ec), 0x37},
> -	{ IMX290_REG_8BIT(0x3441), 0x0a},
> -	{ IMX290_REG_8BIT(0x3442), 0x0a},
> -	{ IMX290_REG_8BIT(0x300a), 0x3c},
> -	{ IMX290_REG_8BIT(0x300b), 0x00},
> +	{ IMX290_ADBIT, IMX290_ADBIT_10BIT },
> +	{ IMX290_OUT_CTRL, IMX290_ODBIT_10BIT },
> +	{ IMX290_ADBIT1, IMX290_ADBIT1_10BIT },
> +	{ IMX290_ADBIT2, IMX290_ADBIT2_10BIT },
> +	{ IMX290_ADBIT3, IMX290_ADBIT3_10BIT },
> +	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW10 },
> +	{ IMX290_BLKLEVEL, 60 },
>  };
> 
>  static const struct imx290_regval imx290_12bit_settings[] = {
> -	{ IMX290_REG_8BIT(0x3005), 0x01 },
> -	{ IMX290_REG_8BIT(0x3046), 0x01 },
> -	{ IMX290_REG_8BIT(0x3129), 0x00 },
> -	{ IMX290_REG_8BIT(0x317c), 0x00 },
> -	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> -	{ IMX290_REG_8BIT(0x3441), 0x0c },
> -	{ IMX290_REG_8BIT(0x3442), 0x0c },
> -	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> -	{ IMX290_REG_8BIT(0x300b), 0x00 },
> +	{ IMX290_ADBIT, IMX290_ADBIT_12BIT },
> +	{ IMX290_OUT_CTRL, IMX290_ODBIT_12BIT },
> +	{ IMX290_ADBIT1, IMX290_ADBIT1_12BIT },
> +	{ IMX290_ADBIT2, IMX290_ADBIT2_12BIT },
> +	{ IMX290_ADBIT3, IMX290_ADBIT3_12BIT },
> +	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW12 },
> +	{ IMX290_BLKLEVEL, 240 },
>  };
> 
>  /* supported link frequencies */





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

* Re: [PATCH 11/19] media: i2c: imx290: Add exposure time control
  2022-07-21  8:35 ` [PATCH 11/19] media: i2c: imx290: Add exposure time control Laurent Pinchart
@ 2022-07-21 10:01   ` Alexander Stein
  2022-07-21 15:52   ` Dave Stevenson
  1 sibling, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:01 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:32 CEST schrieb Laurent Pinchart:
> Support configuring the exposure time, which is expressed as the
> complement if the exposure time (frame period minus integration time).
> The frame period is currently fixed.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index bec326a83952..3cb024b73ee7 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -103,6 +103,8 @@
>  #define IMX290_PGCTRL_THRU				BIT(1)
>  #define IMX290_PGCTRL_MODE(n)				((n) << 4)
> 
> +#define IMX290_VMAX_DEFAULT				1125
> +
>  static const char * const imx290_supply_name[] = {
>  	"vdda",
>  	"vddd",
> @@ -176,7 +178,7 @@ static const char * const imx290_test_pattern_menu[] = {
> 
>  static const struct imx290_regval imx290_global_init_settings[] = {
>  	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> -	{ IMX290_VMAX, 1125 },
> +	{ IMX290_VMAX, IMX290_VMAX_DEFAULT },
>  	{ IMX290_EXTCK_FREQ, 0x2520 },
>  	{ IMX290_WINWV_OB, 12 },
>  	{ IMX290_WINPH, 0 },
> @@ -480,6 +482,12 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
>  	case V4L2_CID_GAIN:
>  		ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, 
NULL);
>  		break;
> +
> +	case V4L2_CID_EXPOSURE:
> +		ret = imx290_write(imx290, IMX290_SHS1,
> +				   IMX290_VMAX_DEFAULT - ctrl->val 
- 1, NULL);
> +		break;
> +
>  	case V4L2_CID_TEST_PATTERN:
>  		if (ctrl->val) {
>  			imx290_write(imx290, IMX290_BLKLEVEL, 0, 
&ret);
> @@ -1008,12 +1016,16 @@ static int imx290_probe(struct i2c_client *client)
>  	 */
>  	imx290_entity_init_cfg(&imx290->sd, NULL);
> 
> -	v4l2_ctrl_handler_init(&imx290->ctrls, 4);
> +	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
>  	imx290->ctrls.lock = &imx290->lock;
> 
>  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
>  			  V4L2_CID_GAIN, 0, 72, 1, 0);
> 
> +	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> +			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 
2, 1,
> +			  IMX290_VMAX_DEFAULT - 2);
> +
>  	imx290->link_freq =
>  		v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
>  				       V4L2_CID_LINK_FREQ,


Acked-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 12/19] media: i2c: imx290: Fix max gain value
  2022-07-21  8:35 ` [PATCH 12/19] media: i2c: imx290: Fix max gain value Laurent Pinchart
@ 2022-07-21 10:02   ` Alexander Stein
  2022-07-21 16:08   ` Dave Stevenson
  1 sibling, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:02 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:33 CEST schrieb Laurent Pinchart:
> The gain is expressed in multiple of 0.3dB, as a value between 0.0dB
> and 72.0dB. The maximum value is thus 240, not 72.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 3cb024b73ee7..1bd464932432 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -1020,7 +1020,7 @@ static int imx290_probe(struct i2c_client *client)
>  	imx290->ctrls.lock = &imx290->lock;
> 
>  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> -			  V4L2_CID_GAIN, 0, 72, 1, 0);
> +			  V4L2_CID_GAIN, 0, 240, 1, 0);
> 
>  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
>  			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 
2, 1,

Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 13/19] media: i2c: imx290: Split control initialization to separate function
  2022-07-21  8:35 ` [PATCH 13/19] media: i2c: imx290: Split control initialization to separate function Laurent Pinchart
@ 2022-07-21 10:03   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:03 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:34 CEST schrieb Laurent Pinchart:
> The imx290_probe() function is too large. Split control initialzation to
> a dedicated function to increase code readability.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 83 ++++++++++++++++++++++----------------
>  1 file changed, 48 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 1bd464932432..4408dd3e191f 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -878,6 +878,49 @@ static const struct media_entity_operations
> imx290_subdev_entity_ops = { .link_validate = v4l2_subdev_link_validate,
>  };
> 
> +static int imx290_ctrl_init(struct imx290 *imx290)
> +{
> +	int ret;
> +
> +	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
> +	imx290->ctrls.lock = &imx290->lock;
> +
> +	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> +			  V4L2_CID_GAIN, 0, 240, 1, 0);
> +
> +	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> +			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 
2, 1,
> +			  IMX290_VMAX_DEFAULT - 2);
> +
> +	imx290->link_freq =
> +		v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
> +				       V4L2_CID_LINK_FREQ,
> +				       
imx290_link_freqs_num(imx290) - 1, 0,
> +				       
imx290_link_freqs_ptr(imx290));
> +	if (imx290->link_freq)
> +		imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> +	imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, 
&imx290_ctrl_ops,
> +					       
V4L2_CID_PIXEL_RATE,
> +					       1, INT_MAX, 1,
> +					       
imx290_calc_pixel_rate(imx290));
> +
> +	v4l2_ctrl_new_std_menu_items(&imx290->ctrls, &imx290_ctrl_ops,
> +				     V4L2_CID_TEST_PATTERN,
> +				     
ARRAY_SIZE(imx290_test_pattern_menu) - 1,
> +				     0, 0, 
imx290_test_pattern_menu);
> +
> +	imx290->sd.ctrl_handler = &imx290->ctrls;
> +
> +	if (imx290->ctrls.error) {
> +		ret = imx290->ctrls.error;
> +		v4l2_ctrl_handler_free(&imx290->ctrls);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * Returns 0 if all link frequencies used by the driver for the given
> number * of MIPI data lanes are mentioned in the device tree, or the value
> of the @@ -1016,41 +1059,10 @@ static int imx290_probe(struct i2c_client
> *client) */
>  	imx290_entity_init_cfg(&imx290->sd, NULL);
> 
> -	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
> -	imx290->ctrls.lock = &imx290->lock;
> -
> -	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> -			  V4L2_CID_GAIN, 0, 240, 1, 0);
> -
> -	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> -			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 
2, 1,
> -			  IMX290_VMAX_DEFAULT - 2);
> -
> -	imx290->link_freq =
> -		v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
> -				       V4L2_CID_LINK_FREQ,
> -				       
imx290_link_freqs_num(imx290) - 1, 0,
> -				       
imx290_link_freqs_ptr(imx290));
> -	if (imx290->link_freq)
> -		imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> -
> -	imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, 
&imx290_ctrl_ops,
> -					       
V4L2_CID_PIXEL_RATE,
> -					       1, INT_MAX, 1,
> -					       
imx290_calc_pixel_rate(imx290));
> -
> -	v4l2_ctrl_new_std_menu_items(&imx290->ctrls, &imx290_ctrl_ops,
> -				     V4L2_CID_TEST_PATTERN,
> -				     
ARRAY_SIZE(imx290_test_pattern_menu) - 1,
> -				     0, 0, 
imx290_test_pattern_menu);
> -
> -	imx290->sd.ctrl_handler = &imx290->ctrls;
> -
> -	if (imx290->ctrls.error) {
> -		dev_err(dev, "Control initialization error %d\n",
> -			imx290->ctrls.error);
> -		ret = imx290->ctrls.error;
> -		goto free_ctrl;
> +	ret = imx290_ctrl_init(imx290);
> +	if (ret < 0) {
> +		dev_err(dev, "Control initialization error %d\n", ret);
> +		goto free_mutex;
>  	}
> 
>  	v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
> @@ -1091,6 +1103,7 @@ static int imx290_probe(struct i2c_client *client)
>  	media_entity_cleanup(&imx290->sd.entity);
>  free_ctrl:
>  	v4l2_ctrl_handler_free(&imx290->ctrls);
> +free_mutex:
>  	mutex_destroy(&imx290->lock);
>  free_err:
>  	v4l2_fwnode_endpoint_free(&ep);

Acked-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls
  2022-07-21  8:35 ` [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls Laurent Pinchart
@ 2022-07-21 10:05   ` Alexander Stein
  2022-07-21 11:17     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:05 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hello Laurent,

thanks for the patch.

Am Donnerstag, 21. Juli 2022, 10:35:35 CEST schrieb Laurent Pinchart:
> Add support for the V4L2_CID_HBLANK and V4L2_CID_VBLANK controls to the
> imx290 driver. Make the controls read-only to start with, to report the
> values to userspace for timing calculation.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 39 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 38 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 4408dd3e191f..7190399f4111 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -146,6 +146,8 @@ struct imx290 {
>  	struct v4l2_ctrl_handler ctrls;
>  	struct v4l2_ctrl *link_freq;
>  	struct v4l2_ctrl *pixel_rate;
> +	struct v4l2_ctrl *hblank;
> +	struct v4l2_ctrl *vblank;
> 
>  	struct mutex lock;
>  };
> @@ -642,6 +644,20 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
>  		if (imx290->pixel_rate)
>  			__v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
>  						 
imx290_calc_pixel_rate(imx290));
> +
> +		if (imx290->hblank) {
> +			unsigned int hblank = mode->hmax - mode-
>width;
> +
> +			__v4l2_ctrl_modify_range(imx290->hblank, 
hblank, hblank,
> +						 1, hblank);
> +		}
> +
> +		if (imx290->vblank) {
> +			unsigned int vblank = IMX290_VMAX_DEFAULT - 
mode->height;
> +
> +			__v4l2_ctrl_modify_range(imx290->vblank, 
vblank, vblank,
> +						 1, vblank);
> +		}
>  	}
> 
>  	*format = fmt->format;
> @@ -880,9 +896,10 @@ static const struct media_entity_operations
> imx290_subdev_entity_ops = {
> 
>  static int imx290_ctrl_init(struct imx290 *imx290)
>  {
> +	unsigned int blank;
>  	int ret;
> 
> -	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
> +	v4l2_ctrl_handler_init(&imx290->ctrls, 7);
>  	imx290->ctrls.lock = &imx290->lock;
> 
>  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> @@ -910,6 +927,26 @@ static int imx290_ctrl_init(struct imx290 *imx290)
>  				     
ARRAY_SIZE(imx290_test_pattern_menu) - 1,
>  				     0, 0, 
imx290_test_pattern_menu);
> 
> +	/*
> +	 * Horizontal blanking is controlled through the HMAX register, 
which
> +	 * contains a line length in INCK clock units. The INCK frequency 
is
> +	 * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100,
> +	 * convert it to a number of pixels based on the nominal pixel 
rate.
> +	 */

Currently the driver only supports 37.125 MHz, please refer to imx290_probe.

Regards,
Alexander

> +	blank = imx290->current_mode->hmax - imx290->current_mode->width;
> +	imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, 
&imx290_ctrl_ops,
> +					   V4L2_CID_HBLANK, 
blank, blank, 1,
> +					   blank);
> +	if (imx290->hblank)
> +		imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
> +	blank = IMX290_VMAX_DEFAULT - imx290->current_mode->height;
> +	imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, 
&imx290_ctrl_ops,
> +					   V4L2_CID_VBLANK, 
blank, blank, 1,
> +					   blank);
> +	if (imx290->vblank)
> +		imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> +
>  	imx290->sd.ctrl_handler = &imx290->ctrls;
> 
>  	if (imx290->ctrls.error) {





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

* Re: [PATCH 15/19] media: i2c: imx290: Create controls for fwnode properties
  2022-07-21  8:35 ` [PATCH 15/19] media: i2c: imx290: Create controls for fwnode properties Laurent Pinchart
@ 2022-07-21 10:06   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:06 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:36 CEST schrieb Laurent Pinchart:
> Create the V4L2_CID_ORIENTATION and V4L2_CID_ROTATION controls to
> expose the corresponding fwnode properties.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 7190399f4111..78772c6327a2 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -896,10 +896,15 @@ static const struct media_entity_operations
> imx290_subdev_entity_ops = {
> 
>  static int imx290_ctrl_init(struct imx290 *imx290)
>  {
> +	struct v4l2_fwnode_device_properties props;
>  	unsigned int blank;
>  	int ret;
> 
> -	v4l2_ctrl_handler_init(&imx290->ctrls, 7);
> +	ret = v4l2_fwnode_device_parse(imx290->dev, &props);
> +	if (ret < 0)
> +		return ret;
> +
> +	v4l2_ctrl_handler_init(&imx290->ctrls, 9);
>  	imx290->ctrls.lock = &imx290->lock;
> 
>  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> @@ -947,6 +952,9 @@ static int imx290_ctrl_init(struct imx290 *imx290)
>  	if (imx290->vblank)
>  		imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> 
> +	v4l2_ctrl_new_fwnode_properties(&imx290->ctrls, &imx290_ctrl_ops,
> +					&props);
> +
>  	imx290->sd.ctrl_handler = &imx290->ctrls;
> 
>  	if (imx290->ctrls.error) {

Acked-by: Alexander Stein <alexander.stein@ew.tq-group.com>




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

* Re: [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array
  2022-07-21  8:35 ` [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array Laurent Pinchart
@ 2022-07-21 10:08   ` Alexander Stein
  2022-07-21 10:40     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:08 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hello Laurent,

thanks for the path.

Am Donnerstag, 21. Juli 2022, 10:35:37 CEST schrieb Laurent Pinchart:
> Registers 0x3012, 0x3013 and 0x3480 are not documented and are set in
> the per-mode register arrays with values indentical for all modes. Move
> them to the common array.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 78772c6327a2..fc6e87fada1c 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -192,6 +192,7 @@ static const struct imx290_regval
> imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x300f), 0x00 },
>  	{ IMX290_REG_8BIT(0x3010), 0x21 },
>  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> +	{ IMX290_REG_8BIT(0x3013), 0x00 },
>  	{ IMX290_REG_8BIT(0x3016), 0x09 },
>  	{ IMX290_REG_8BIT(0x3070), 0x02 },
>  	{ IMX290_REG_8BIT(0x3071), 0x11 },
> @@ -230,6 +231,7 @@ static const struct imx290_regval
> imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x33b0), 0x50 },
>  	{ IMX290_REG_8BIT(0x33b2), 0x1a },
>  	{ IMX290_REG_8BIT(0x33b3), 0x04 },
> +	{ IMX290_REG_8BIT(0x3480), 0x49 },
>  };
> 
>  static const struct imx290_regval imx290_1080p_settings[] = {
> @@ -239,15 +241,12 @@ static const struct imx290_regval
> imx290_1080p_settings[] = { { IMX290_OPB_SIZE_V, 10 },
>  	{ IMX290_X_OUT_SIZE, 1920 },
>  	{ IMX290_Y_OUT_SIZE, 1080 },
> -	{ IMX290_REG_8BIT(0x3012), 0x64 },
> -	{ IMX290_REG_8BIT(0x3013), 0x00 },
>  	{ IMX290_INCKSEL1, 0x18 },
>  	{ IMX290_INCKSEL2, 0x03 },
>  	{ IMX290_INCKSEL3, 0x20 },
>  	{ IMX290_INCKSEL4, 0x01 },
>  	{ IMX290_INCKSEL5, 0x1a },
>  	{ IMX290_INCKSEL6, 0x1a },
> -	{ IMX290_REG_8BIT(0x3480), 0x49 },
>  	/* data rate settings */
>  	{ IMX290_REPETITION, 0x10 },
>  	{ IMX290_TCLKPOST, 87 },
> @@ -267,15 +266,12 @@ static const struct imx290_regval
> imx290_720p_settings[] = { { IMX290_OPB_SIZE_V, 4 },
>  	{ IMX290_X_OUT_SIZE, 1280 },
>  	{ IMX290_Y_OUT_SIZE, 720 },
> -	{ IMX290_REG_8BIT(0x3012), 0x64 },
> -	{ IMX290_REG_8BIT(0x3013), 0x00 },
>  	{ IMX290_INCKSEL1, 0x20 },
>  	{ IMX290_INCKSEL2, 0x00 },
>  	{ IMX290_INCKSEL3, 0x20 },
>  	{ IMX290_INCKSEL4, 0x01 },
>  	{ IMX290_INCKSEL5, 0x1a },
>  	{ IMX290_INCKSEL6, 0x1a },
> -	{ IMX290_REG_8BIT(0x3480), 0x49 },
>  	/* data rate settings */
>  	{ IMX290_REPETITION, 0x10 },
>  	{ IMX290_TCLKPOST, 79 },

0x3480 is INCKSEL7 for imx327, not sure if that should be set yet for imx290 
(only) driver, without proper imx327 support.

Best regards,
Alexander




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

* Re: [PATCH 17/19] media: i2c: imx290: Factor out format retrieval to separate function
  2022-07-21  8:35 ` [PATCH 17/19] media: i2c: imx290: Factor out format retrieval to separate function Laurent Pinchart
@ 2022-07-21 10:11   ` Alexander Stein
  2022-07-21 10:36     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:11 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hello Laurent,

thanks for your patch.

Am Donnerstag, 21. Juli 2022, 10:35:38 CEST schrieb Laurent Pinchart:
> The driver duplicates the same pattern to access the try or active
> format in multiple locations. Factor it out to a separate function.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 28 ++++++++++++++++++----------
>  1 file changed, 18 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index fc6e87fada1c..baf9941c5fbe 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -519,6 +519,20 @@ static const struct v4l2_ctrl_ops imx290_ctrl_ops = {
>  	.s_ctrl = imx290_set_ctrl,
>  };
> 
> +static struct v4l2_mbus_framefmt *
> +imx290_get_pad_format(struct imx290 *imx290, struct v4l2_subdev_state
> *state, +		      u32 which)
> +{
> +	switch (which) {
> +	case V4L2_SUBDEV_FORMAT_TRY:
> +		return v4l2_subdev_get_try_format(&imx290->sd, state, 
0);
> +	case V4L2_SUBDEV_FORMAT_ACTIVE:
> +		return &imx290->current_format;
> +	default:
> +		return NULL;
> +	}
> +}
> +
>  static int imx290_enum_mbus_code(struct v4l2_subdev *sd,
>  				 struct v4l2_subdev_state 
*sd_state,
>  				 struct v4l2_subdev_mbus_code_enum 
*code)
> @@ -562,12 +576,7 @@ static int imx290_get_fmt(struct v4l2_subdev *sd,
> 
>  	mutex_lock(&imx290->lock);
> 
> -	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
> -		framefmt = v4l2_subdev_get_try_format(&imx290->sd, 
sd_state,
> -						      fmt-
>pad);
> -	else
> -		framefmt = &imx290->current_format;
> -
> +	framefmt = imx290_get_pad_format(imx290, sd_state, fmt->which);
>  	fmt->format = *framefmt;

NULL ptr derence here if 'fmt->which' is neither V4L2_SUBDEV_FORMAT_TRY nor 
V4L2_SUBDEV_FORMAT_ACTIVE. Same for imx290_set_fmt later on.

Best regards,
Alexander

> 
>  	mutex_unlock(&imx290->lock);
> @@ -627,10 +636,9 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
>  	fmt->format.code = imx290_formats[i].code;
>  	fmt->format.field = V4L2_FIELD_NONE;
> 
> -	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> -		format = v4l2_subdev_get_try_format(sd, sd_state, fmt-
>pad);
> -	} else {
> -		format = &imx290->current_format;
> +	format = imx290_get_pad_format(imx290, sd_state, fmt->which);
> +
> +	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
>  		imx290->current_mode = mode;
>  		imx290->bpp = imx290_formats[i].bpp;





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

* Re: [PATCH 19/19] media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN
  2022-07-21  8:35 ` [PATCH 19/19] media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN Laurent Pinchart
@ 2022-07-21 10:11   ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 10:11 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 10:35:40 CEST schrieb Laurent Pinchart:
> The IMX290 gain register controls the analogue gain. Replace the
> V4L2_CID_GAIN control with V4L2_CID_ANALOGUE_GAIN.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 0cb11ec1cf0f..871e3e69a8a4 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -524,7 +524,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
>  		return 0;
> 
>  	switch (ctrl->id) {
> -	case V4L2_CID_GAIN:
> +	case V4L2_CID_ANALOGUE_GAIN:
>  		ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, 
NULL);
>  		break;
> 
> @@ -1006,7 +1006,7 @@ static int imx290_ctrl_init(struct imx290 *imx290)
>  	imx290->ctrls.lock = &imx290->lock;
> 
>  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> -			  V4L2_CID_GAIN, 0, 240, 1, 0);
> +			  V4L2_CID_ANALOGUE_GAIN, 0, 240, 1, 0);
> 
>  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
>  			  V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 
2, 1,

Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>





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

* Re: [PATCH 17/19] media: i2c: imx290: Factor out format retrieval to separate function
  2022-07-21 10:11   ` Alexander Stein
@ 2022-07-21 10:36     ` Laurent Pinchart
  2022-07-21 11:12       ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21 10:36 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Alexander,

On Thu, Jul 21, 2022 at 12:11:31PM +0200, Alexander Stein wrote:
> Am Donnerstag, 21. Juli 2022, 10:35:38 CEST schrieb Laurent Pinchart:
> > The driver duplicates the same pattern to access the try or active
> > format in multiple locations. Factor it out to a separate function.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/i2c/imx290.c | 28 ++++++++++++++++++----------
> >  1 file changed, 18 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index fc6e87fada1c..baf9941c5fbe 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -519,6 +519,20 @@ static const struct v4l2_ctrl_ops imx290_ctrl_ops = {
> >  	.s_ctrl = imx290_set_ctrl,
> >  };
> > 
> > +static struct v4l2_mbus_framefmt *
> > +imx290_get_pad_format(struct imx290 *imx290, struct v4l2_subdev_state *state,
> > +		      u32 which)
> > +{
> > +	switch (which) {
> > +	case V4L2_SUBDEV_FORMAT_TRY:
> > +		return v4l2_subdev_get_try_format(&imx290->sd, state, 0);
> > +	case V4L2_SUBDEV_FORMAT_ACTIVE:
> > +		return &imx290->current_format;
> > +	default:
> > +		return NULL;
> > +	}
> > +}
> > +
> >  static int imx290_enum_mbus_code(struct v4l2_subdev *sd,
> >  				 struct v4l2_subdev_state *sd_state,
> >  				 struct v4l2_subdev_mbus_code_enum *code)
> > @@ -562,12 +576,7 @@ static int imx290_get_fmt(struct v4l2_subdev *sd,
> > 
> >  	mutex_lock(&imx290->lock);
> > 
> > -	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
> > -		framefmt = v4l2_subdev_get_try_format(&imx290->sd, sd_state,
> > -						      fmt->pad);
> > -	else
> > -		framefmt = &imx290->current_format;
> > -
> > +	framefmt = imx290_get_pad_format(imx290, sd_state, fmt->which);
> >  	fmt->format = *framefmt;
> 
> NULL ptr derence here if 'fmt->which' is neither V4L2_SUBDEV_FORMAT_TRY nor 
> V4L2_SUBDEV_FORMAT_ACTIVE. Same for imx290_set_fmt later on.

You're right, but this can't happen, TRY and ACTIVE are the only two
possible values.

> >  	mutex_unlock(&imx290->lock);
> > @@ -627,10 +636,9 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> >  	fmt->format.code = imx290_formats[i].code;
> >  	fmt->format.field = V4L2_FIELD_NONE;
> > 
> > -	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> > -		format = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
> > -	} else {
> > -		format = &imx290->current_format;
> > +	format = imx290_get_pad_format(imx290, sd_state, fmt->which);
> > +
> > +	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> >  		imx290->current_mode = mode;
> >  		imx290->bpp = imx290_formats[i].bpp;

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array
  2022-07-21 10:08   ` Alexander Stein
@ 2022-07-21 10:40     ` Laurent Pinchart
  2022-07-21 11:08       ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21 10:40 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Alexander,

On Thu, Jul 21, 2022 at 12:08:50PM +0200, Alexander Stein wrote:
> Am Donnerstag, 21. Juli 2022, 10:35:37 CEST schrieb Laurent Pinchart:
> > Registers 0x3012, 0x3013 and 0x3480 are not documented and are set in
> > the per-mode register arrays with values indentical for all modes. Move
> > them to the common array.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/i2c/imx290.c | 8 ++------
> >  1 file changed, 2 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index 78772c6327a2..fc6e87fada1c 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -192,6 +192,7 @@ static const struct imx290_regval
> > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x300f), 0x00 },
> >  	{ IMX290_REG_8BIT(0x3010), 0x21 },
> >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> >  	{ IMX290_REG_8BIT(0x3016), 0x09 },
> >  	{ IMX290_REG_8BIT(0x3070), 0x02 },
> >  	{ IMX290_REG_8BIT(0x3071), 0x11 },
> > @@ -230,6 +231,7 @@ static const struct imx290_regval
> > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x33b0), 0x50 },
> >  	{ IMX290_REG_8BIT(0x33b2), 0x1a },
> >  	{ IMX290_REG_8BIT(0x33b3), 0x04 },
> > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> >  };
> > 
> >  static const struct imx290_regval imx290_1080p_settings[] = {
> > @@ -239,15 +241,12 @@ static const struct imx290_regval
> > imx290_1080p_settings[] = { { IMX290_OPB_SIZE_V, 10 },
> >  	{ IMX290_X_OUT_SIZE, 1920 },
> >  	{ IMX290_Y_OUT_SIZE, 1080 },
> > -	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > -	{ IMX290_REG_8BIT(0x3013), 0x00 },
> >  	{ IMX290_INCKSEL1, 0x18 },
> >  	{ IMX290_INCKSEL2, 0x03 },
> >  	{ IMX290_INCKSEL3, 0x20 },
> >  	{ IMX290_INCKSEL4, 0x01 },
> >  	{ IMX290_INCKSEL5, 0x1a },
> >  	{ IMX290_INCKSEL6, 0x1a },
> > -	{ IMX290_REG_8BIT(0x3480), 0x49 },
> >  	/* data rate settings */
> >  	{ IMX290_REPETITION, 0x10 },
> >  	{ IMX290_TCLKPOST, 87 },
> > @@ -267,15 +266,12 @@ static const struct imx290_regval
> > imx290_720p_settings[] = { { IMX290_OPB_SIZE_V, 4 },
> >  	{ IMX290_X_OUT_SIZE, 1280 },
> >  	{ IMX290_Y_OUT_SIZE, 720 },
> > -	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > -	{ IMX290_REG_8BIT(0x3013), 0x00 },
> >  	{ IMX290_INCKSEL1, 0x20 },
> >  	{ IMX290_INCKSEL2, 0x00 },
> >  	{ IMX290_INCKSEL3, 0x20 },
> >  	{ IMX290_INCKSEL4, 0x01 },
> >  	{ IMX290_INCKSEL5, 0x1a },
> >  	{ IMX290_INCKSEL6, 0x1a },
> > -	{ IMX290_REG_8BIT(0x3480), 0x49 },
> >  	/* data rate settings */
> >  	{ IMX290_REPETITION, 0x10 },
> >  	{ IMX290_TCLKPOST, 79 },
> 
> 0x3480 is INCKSEL7 for imx327, not sure if that should be set yet for imx290 
> (only) driver, without proper imx327 support.

Do you mean the register doesn't exist on the IMX290 ? We could make it
conditional on the sensor model, but it's not added by this patch, it
has been there since the first version of the driver, so I'd rather do
that on top.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-21  9:43   ` Alexander Stein
@ 2022-07-21 10:54     ` Laurent Pinchart
  2022-07-21 11:18       ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21 10:54 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Alexander,

On Thu, Jul 21, 2022 at 11:43:47AM +0200, Alexander Stein wrote:
> Am Donnerstag, 21. Juli 2022, 10:35:28 CEST schrieb Laurent Pinchart:
> > The IMX290 has registers of different sizes. To simplify the code,
> > handle this in the read/write functions instead of in the callers by
> > encoding the register size in the symbolic name macros. All registers
> > are defined as 8-bit for now, a subsequent change will move to larger
> > registers where applicable.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/i2c/imx290.c | 352 +++++++++++++++++++------------------
> >  1 file changed, 180 insertions(+), 172 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index 711282126c34..ac58bfe6db7f 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -22,22 +22,28 @@
> >  #include <media/v4l2-fwnode.h>
> >  #include <media/v4l2-subdev.h>
> > 
> > -#define IMX290_STANDBY 0x3000
> > -#define IMX290_REGHOLD 0x3001
> > -#define IMX290_XMSTA 0x3002
> > -#define IMX290_FR_FDG_SEL 0x3009
> > -#define IMX290_BLKLEVEL_LOW 0x300a
> > -#define IMX290_BLKLEVEL_HIGH 0x300b
> > -#define IMX290_GAIN 0x3014
> > -#define IMX290_HMAX_LOW 0x301c
> > -#define IMX290_HMAX_HIGH 0x301d
> > -#define IMX290_PGCTRL 0x308c
> > -#define IMX290_PHY_LANE_NUM 0x3407
> > -#define IMX290_CSI_LANE_MODE 0x3443
> > +#define IMX290_REG_8BIT(n)				((1 << 16) | (n))
> > +#define IMX290_REG_16BIT(n)				((2 << 16) | (n))
> > +#define IMX290_REG_24BIT(n)				((3 << 16) | (n))
> 
> IMX290_REG_SIZE_SHIFT instead of 16 here? Not exactly necessary, but use
> 1U, 2U and 3U instead.

I'll fix that.

> > +#define IMX290_REG_SIZE_SHIFT				16
> > +#define IMX290_REG_ADDR_MASK				0xffff
> > 
> > -#define IMX290_PGCTRL_REGEN BIT(0)
> > -#define IMX290_PGCTRL_THRU BIT(1)
> > -#define IMX290_PGCTRL_MODE(n) ((n) << 4)
> > +#define IMX290_STANDBY					IMX290_REG_8BIT(0x3000)
> > +#define IMX290_REGHOLD					IMX290_REG_8BIT(0x3001)
> > +#define IMX290_XMSTA					IMX290_REG_8BIT(0x3002)
> > +#define IMX290_FR_FDG_SEL				IMX290_REG_8BIT(0x3009)
> > +#define IMX290_BLKLEVEL_LOW				IMX290_REG_8BIT(0x300a)
> > +#define IMX290_BLKLEVEL_HIGH				IMX290_REG_8BIT(0x300b)
> > +#define IMX290_GAIN					IMX290_REG_8BIT(0x3014)
> > +#define IMX290_HMAX_LOW					IMX290_REG_8BIT(0x301c)
> > +#define IMX290_HMAX_HIGH				IMX290_REG_8BIT(0x301d)
> > +#define IMX290_PGCTRL					IMX290_REG_8BIT(0x308c)
> > +#define IMX290_PHY_LANE_NUM				IMX290_REG_8BIT(0x3407)
> > +#define IMX290_CSI_LANE_MODE				IMX290_REG_8BIT(0x3443)
> > +
> > +#define IMX290_PGCTRL_REGEN				BIT(0)
> > +#define IMX290_PGCTRL_THRU				BIT(1)
> > +#define IMX290_PGCTRL_MODE(n)				((n) << 4)
> > 
> >  static const char * const imx290_supply_name[] = {
> >  	"vdda",
> > @@ -48,7 +54,7 @@ static const char * const imx290_supply_name[] = {
> >  #define IMX290_NUM_SUPPLIES ARRAY_SIZE(imx290_supply_name)
> > 
> >  struct imx290_regval {
> > -	u16 reg;
> > +	u32 reg;
> >  	u8 val;
> >  };
> > 
> > @@ -111,163 +117,163 @@ static const char * const imx290_test_pattern_menu[]
> > = { };
> > 
> >  static const struct imx290_regval imx290_global_init_settings[] = {
> > -	{ 0x3007, 0x00 },
> > -	{ 0x3018, 0x65 },
> > -	{ 0x3019, 0x04 },
> > -	{ 0x301a, 0x00 },
> > -	{ 0x3444, 0x20 },
> > -	{ 0x3445, 0x25 },
> > -	{ 0x303a, 0x0c },
> > -	{ 0x3040, 0x00 },
> > -	{ 0x3041, 0x00 },
> > -	{ 0x303c, 0x00 },
> > -	{ 0x303d, 0x00 },
> > -	{ 0x3042, 0x9c },
> > -	{ 0x3043, 0x07 },
> > -	{ 0x303e, 0x49 },
> > -	{ 0x303f, 0x04 },
> > -	{ 0x304b, 0x0a },
> > -	{ 0x300f, 0x00 },
> > -	{ 0x3010, 0x21 },
> > -	{ 0x3012, 0x64 },
> > -	{ 0x3016, 0x09 },
> > -	{ 0x3070, 0x02 },
> > -	{ 0x3071, 0x11 },
> > -	{ 0x309b, 0x10 },
> > -	{ 0x309c, 0x22 },
> > -	{ 0x30a2, 0x02 },
> > -	{ 0x30a6, 0x20 },
> > -	{ 0x30a8, 0x20 },
> > -	{ 0x30aa, 0x20 },
> > -	{ 0x30ac, 0x20 },
> > -	{ 0x30b0, 0x43 },
> > -	{ 0x3119, 0x9e },
> > -	{ 0x311c, 0x1e },
> > -	{ 0x311e, 0x08 },
> > -	{ 0x3128, 0x05 },
> > -	{ 0x313d, 0x83 },
> > -	{ 0x3150, 0x03 },
> > -	{ 0x317e, 0x00 },
> > -	{ 0x32b8, 0x50 },
> > -	{ 0x32b9, 0x10 },
> > -	{ 0x32ba, 0x00 },
> > -	{ 0x32bb, 0x04 },
> > -	{ 0x32c8, 0x50 },
> > -	{ 0x32c9, 0x10 },
> > -	{ 0x32ca, 0x00 },
> > -	{ 0x32cb, 0x04 },
> > -	{ 0x332c, 0xd3 },
> > -	{ 0x332d, 0x10 },
> > -	{ 0x332e, 0x0d },
> > -	{ 0x3358, 0x06 },
> > -	{ 0x3359, 0xe1 },
> > -	{ 0x335a, 0x11 },
> > -	{ 0x3360, 0x1e },
> > -	{ 0x3361, 0x61 },
> > -	{ 0x3362, 0x10 },
> > -	{ 0x33b0, 0x50 },
> > -	{ 0x33b2, 0x1a },
> > -	{ 0x33b3, 0x04 },
> > +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3018), 0x65 },
> > +	{ IMX290_REG_8BIT(0x3019), 0x04 },
> > +	{ IMX290_REG_8BIT(0x301a), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3444), 0x20 },
> > +	{ IMX290_REG_8BIT(0x3445), 0x25 },
> > +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > +	{ IMX290_REG_8BIT(0x3040), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3041), 0x00 },
> > +	{ IMX290_REG_8BIT(0x303c), 0x00 },
> > +	{ IMX290_REG_8BIT(0x303d), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3042), 0x9c },
> > +	{ IMX290_REG_8BIT(0x3043), 0x07 },
> > +	{ IMX290_REG_8BIT(0x303e), 0x49 },
> > +	{ IMX290_REG_8BIT(0x303f), 0x04 },
> > +	{ IMX290_REG_8BIT(0x304b), 0x0a },
> > +	{ IMX290_REG_8BIT(0x300f), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3010), 0x21 },
> > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > +	{ IMX290_REG_8BIT(0x3016), 0x09 },
> > +	{ IMX290_REG_8BIT(0x3070), 0x02 },
> > +	{ IMX290_REG_8BIT(0x3071), 0x11 },
> > +	{ IMX290_REG_8BIT(0x309b), 0x10 },
> > +	{ IMX290_REG_8BIT(0x309c), 0x22 },
> > +	{ IMX290_REG_8BIT(0x30a2), 0x02 },
> > +	{ IMX290_REG_8BIT(0x30a6), 0x20 },
> > +	{ IMX290_REG_8BIT(0x30a8), 0x20 },
> > +	{ IMX290_REG_8BIT(0x30aa), 0x20 },
> > +	{ IMX290_REG_8BIT(0x30ac), 0x20 },
> > +	{ IMX290_REG_8BIT(0x30b0), 0x43 },
> > +	{ IMX290_REG_8BIT(0x3119), 0x9e },
> > +	{ IMX290_REG_8BIT(0x311c), 0x1e },
> > +	{ IMX290_REG_8BIT(0x311e), 0x08 },
> > +	{ IMX290_REG_8BIT(0x3128), 0x05 },
> > +	{ IMX290_REG_8BIT(0x313d), 0x83 },
> > +	{ IMX290_REG_8BIT(0x3150), 0x03 },
> > +	{ IMX290_REG_8BIT(0x317e), 0x00 },
> > +	{ IMX290_REG_8BIT(0x32b8), 0x50 },
> > +	{ IMX290_REG_8BIT(0x32b9), 0x10 },
> > +	{ IMX290_REG_8BIT(0x32ba), 0x00 },
> > +	{ IMX290_REG_8BIT(0x32bb), 0x04 },
> > +	{ IMX290_REG_8BIT(0x32c8), 0x50 },
> > +	{ IMX290_REG_8BIT(0x32c9), 0x10 },
> > +	{ IMX290_REG_8BIT(0x32ca), 0x00 },
> > +	{ IMX290_REG_8BIT(0x32cb), 0x04 },
> > +	{ IMX290_REG_8BIT(0x332c), 0xd3 },
> > +	{ IMX290_REG_8BIT(0x332d), 0x10 },
> > +	{ IMX290_REG_8BIT(0x332e), 0x0d },
> > +	{ IMX290_REG_8BIT(0x3358), 0x06 },
> > +	{ IMX290_REG_8BIT(0x3359), 0xe1 },
> > +	{ IMX290_REG_8BIT(0x335a), 0x11 },
> > +	{ IMX290_REG_8BIT(0x3360), 0x1e },
> > +	{ IMX290_REG_8BIT(0x3361), 0x61 },
> > +	{ IMX290_REG_8BIT(0x3362), 0x10 },
> > +	{ IMX290_REG_8BIT(0x33b0), 0x50 },
> > +	{ IMX290_REG_8BIT(0x33b2), 0x1a },
> > +	{ IMX290_REG_8BIT(0x33b3), 0x04 },
> >  };
> > 
> >  static const struct imx290_regval imx290_1080p_settings[] = {
> >  	/* mode settings */
> > -	{ 0x3007, 0x00 },
> > -	{ 0x303a, 0x0c },
> > -	{ 0x3414, 0x0a },
> > -	{ 0x3472, 0x80 },
> > -	{ 0x3473, 0x07 },
> > -	{ 0x3418, 0x38 },
> > -	{ 0x3419, 0x04 },
> > -	{ 0x3012, 0x64 },
> > -	{ 0x3013, 0x00 },
> > -	{ 0x305c, 0x18 },
> > -	{ 0x305d, 0x03 },
> > -	{ 0x305e, 0x20 },
> > -	{ 0x305f, 0x01 },
> > -	{ 0x315e, 0x1a },
> > -	{ 0x3164, 0x1a },
> > -	{ 0x3480, 0x49 },
> > +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > +	{ IMX290_REG_8BIT(0x3414), 0x0a },
> > +	{ IMX290_REG_8BIT(0x3472), 0x80 },
> > +	{ IMX290_REG_8BIT(0x3473), 0x07 },
> > +	{ IMX290_REG_8BIT(0x3418), 0x38 },
> > +	{ IMX290_REG_8BIT(0x3419), 0x04 },
> > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > +	{ IMX290_REG_8BIT(0x305c), 0x18 },
> > +	{ IMX290_REG_8BIT(0x305d), 0x03 },
> > +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> >  	/* data rate settings */
> > -	{ 0x3405, 0x10 },
> > -	{ 0x3446, 0x57 },
> > -	{ 0x3447, 0x00 },
> > -	{ 0x3448, 0x37 },
> > -	{ 0x3449, 0x00 },
> > -	{ 0x344a, 0x1f },
> > -	{ 0x344b, 0x00 },
> > -	{ 0x344c, 0x1f },
> > -	{ 0x344d, 0x00 },
> > -	{ 0x344e, 0x1f },
> > -	{ 0x344f, 0x00 },
> > -	{ 0x3450, 0x77 },
> > -	{ 0x3451, 0x00 },
> > -	{ 0x3452, 0x1f },
> > -	{ 0x3453, 0x00 },
> > -	{ 0x3454, 0x17 },
> > -	{ 0x3455, 0x00 },
> > +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > +	{ IMX290_REG_8BIT(0x3446), 0x57 },
> > +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3448), 0x37 },
> > +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > +	{ IMX290_REG_8BIT(0x344a), 0x1f },
> > +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > +	{ IMX290_REG_8BIT(0x344c), 0x1f },
> > +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > +	{ IMX290_REG_8BIT(0x344e), 0x1f },
> > +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3450), 0x77 },
> > +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3452), 0x1f },
> > +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > +	{ IMX290_REG_8BIT(0x3455), 0x00 },
> >  };
> > 
> >  static const struct imx290_regval imx290_720p_settings[] = {
> >  	/* mode settings */
> > -	{ 0x3007, 0x10 },
> > -	{ 0x303a, 0x06 },
> > -	{ 0x3414, 0x04 },
> > -	{ 0x3472, 0x00 },
> > -	{ 0x3473, 0x05 },
> > -	{ 0x3418, 0xd0 },
> > -	{ 0x3419, 0x02 },
> > -	{ 0x3012, 0x64 },
> > -	{ 0x3013, 0x00 },
> > -	{ 0x305c, 0x20 },
> > -	{ 0x305d, 0x00 },
> > -	{ 0x305e, 0x20 },
> > -	{ 0x305f, 0x01 },
> > -	{ 0x315e, 0x1a },
> > -	{ 0x3164, 0x1a },
> > -	{ 0x3480, 0x49 },
> > +	{ IMX290_REG_8BIT(0x3007), 0x10 },
> > +	{ IMX290_REG_8BIT(0x303a), 0x06 },
> > +	{ IMX290_REG_8BIT(0x3414), 0x04 },
> > +	{ IMX290_REG_8BIT(0x3472), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3473), 0x05 },
> > +	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> > +	{ IMX290_REG_8BIT(0x3419), 0x02 },
> > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > +	{ IMX290_REG_8BIT(0x305c), 0x20 },
> > +	{ IMX290_REG_8BIT(0x305d), 0x00 },
> > +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> >  	/* data rate settings */
> > -	{ 0x3405, 0x10 },
> > -	{ 0x3446, 0x4f },
> > -	{ 0x3447, 0x00 },
> > -	{ 0x3448, 0x2f },
> > -	{ 0x3449, 0x00 },
> > -	{ 0x344a, 0x17 },
> > -	{ 0x344b, 0x00 },
> > -	{ 0x344c, 0x17 },
> > -	{ 0x344d, 0x00 },
> > -	{ 0x344e, 0x17 },
> > -	{ 0x344f, 0x00 },
> > -	{ 0x3450, 0x57 },
> > -	{ 0x3451, 0x00 },
> > -	{ 0x3452, 0x17 },
> > -	{ 0x3453, 0x00 },
> > -	{ 0x3454, 0x17 },
> > -	{ 0x3455, 0x00 },
> > +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > +	{ IMX290_REG_8BIT(0x3446), 0x4f },
> > +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3448), 0x2f },
> > +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > +	{ IMX290_REG_8BIT(0x344a), 0x17 },
> > +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > +	{ IMX290_REG_8BIT(0x344c), 0x17 },
> > +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > +	{ IMX290_REG_8BIT(0x344e), 0x17 },
> > +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3450), 0x57 },
> > +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3452), 0x17 },
> > +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > +	{ IMX290_REG_8BIT(0x3455), 0x00 },
> >  };
> > 
> >  static const struct imx290_regval imx290_10bit_settings[] = {
> > -	{ 0x3005, 0x00},
> > -	{ 0x3046, 0x00},
> > -	{ 0x3129, 0x1d},
> > -	{ 0x317c, 0x12},
> > -	{ 0x31ec, 0x37},
> > -	{ 0x3441, 0x0a},
> > -	{ 0x3442, 0x0a},
> > -	{ 0x300a, 0x3c},
> > -	{ 0x300b, 0x00},
> > +	{ IMX290_REG_8BIT(0x3005), 0x00},
> > +	{ IMX290_REG_8BIT(0x3046), 0x00},
> > +	{ IMX290_REG_8BIT(0x3129), 0x1d},
> > +	{ IMX290_REG_8BIT(0x317c), 0x12},
> > +	{ IMX290_REG_8BIT(0x31ec), 0x37},
> > +	{ IMX290_REG_8BIT(0x3441), 0x0a},
> > +	{ IMX290_REG_8BIT(0x3442), 0x0a},
> > +	{ IMX290_REG_8BIT(0x300a), 0x3c},
> > +	{ IMX290_REG_8BIT(0x300b), 0x00},
> >  };
> > 
> >  static const struct imx290_regval imx290_12bit_settings[] = {
> > -	{ 0x3005, 0x01 },
> > -	{ 0x3046, 0x01 },
> > -	{ 0x3129, 0x00 },
> > -	{ 0x317c, 0x00 },
> > -	{ 0x31ec, 0x0e },
> > -	{ 0x3441, 0x0c },
> > -	{ 0x3442, 0x0c },
> > -	{ 0x300a, 0xf0 },
> > -	{ 0x300b, 0x00 },
> > +	{ IMX290_REG_8BIT(0x3005), 0x01 },
> > +	{ IMX290_REG_8BIT(0x3046), 0x01 },
> > +	{ IMX290_REG_8BIT(0x3129), 0x00 },
> > +	{ IMX290_REG_8BIT(0x317c), 0x00 },
> > +	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> > +	{ IMX290_REG_8BIT(0x3441), 0x0c },
> > +	{ IMX290_REG_8BIT(0x3442), 0x0c },
> > +	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> > +	{ IMX290_REG_8BIT(0x300b), 0x00 },
> >  };
> > 
> >  /* supported link frequencies */
> > @@ -362,33 +368,35 @@ static inline struct imx290 *to_imx290(struct
> > v4l2_subdev *_sd) return container_of(_sd, struct imx290, sd);
> >  }
> > 
> > -static inline int __always_unused imx290_read_reg(struct imx290 *imx290, u16 addr, u8 *value)
> > +static int __always_unused imx290_read_reg(struct imx290 *imx290, u32 addr, u32 *value) {
> > -	unsigned int regval;
> > +	u8 data[3] = { 0, 0, 0 };
> >  	int ret;
> > 
> > -	ret = regmap_read(imx290->regmap, addr, &regval);
> > -	if (ret) {
> > -		dev_err(imx290->dev, "Failed to read register 0x%04x: %d\n",
> > -			addr, ret);
> > +	ret = regmap_raw_read(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
> > +			      data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
> 
> While I agree with the intention, it fails for some devices, e.g. Vision 
> Components MIPI IMX327 C does not support auto-increment and most probably 
> also valid for the IMX290 model.
> This is similar to the OV9281 variant, see [1].

*sigh* Can't they get their firmware right ? :-( Inserting a
microcontroller between the SoC and sensor is bad enough in itself,
making it mess up I2C access due to firmware bugs is worse.

How far do we need to go in sensor drivers to support messed up hardware
designs that are not related to the sensor at all ? I don't want to
patch all sensor drivers to make I2C read slower because someone
somewhere has taken the sensor and decided to screw up. That doesn't
scale, and hurt all users of these sensors in sane camera modules.

> Reading ID using 16bit register (using later patch) returns:
> > imx290 2-001a: chip ID 0xffd0
> Using 2 8bit reads:
> imx290 2-001a: chip ID 0x07d0
> 
> Best regards,
> Alexander
> 
> [1] https://patchwork.kernel.org/project/linux-media/patch/20220715074858.875808-7-alexander.stein@ew.tq-group.com/
> 
> > +	if (ret < 0) {
> > +		dev_err(imx290->dev, "%u-bit read from 0x%04x failed: %d\n",
> > +			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
> > +			 addr & IMX290_REG_ADDR_MASK, ret);
> >  		return ret;
> >  	}
> > 
> > -	*value = regval & 0xff;
> > -
> > +	*value = (data[2] << 16) | (data[1] << 8) | data[0];
> >  	return 0;
> >  }
> > 
> > -static int imx290_write_reg(struct imx290 *imx290, u16 addr, u8 value)
> > +static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
> >  {
> > +	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
> >  	int ret;
> > 
> > -	ret = regmap_write(imx290->regmap, addr, value);
> > -	if (ret) {
> > -		dev_err(imx290->dev, "Failed to write register 0x%04x: %d\n",
> > -			addr, ret);
> > -		return ret;
> > -	}
> > +	ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
> > +			       data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
> > +	if (ret < 0)
> > +		dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
> > +			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
> > +			 addr & IMX290_REG_ADDR_MASK, ret);
> > 
> >  	return ret;
> >  }

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 10/19] media: i2c: imx290: Define more register macros
  2022-07-21 10:00   ` Alexander Stein
@ 2022-07-21 11:08     ` Laurent Pinchart
  2022-07-21 11:28       ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21 11:08 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Alexander,

On Thu, Jul 21, 2022 at 12:00:55PM +0200, Alexander Stein wrote:
> Am Donnerstag, 21. Juli 2022, 10:35:31 CEST schrieb Laurent Pinchart:
> > Define macros for all registers programmed by the driver for which
> > documentation is available to increase readability. This starts making
> > use of 16-bit registers in the register arrays, so the value field has
> > to be increased to 32 bits.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/i2c/imx290.c | 219 +++++++++++++++++++++----------------
> >  1 file changed, 124 insertions(+), 95 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index 5b7f9027b50f..bec326a83952 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -31,14 +31,73 @@
> >  #define IMX290_STANDBY					IMX290_REG_8BIT(0x3000)
> >  #define IMX290_REGHOLD					IMX290_REG_8BIT(0x3001)
> >  #define IMX290_XMSTA					IMX290_REG_8BIT(0x3002)
> > +#define IMX290_ADBIT					IMX290_REG_8BIT(0x3005)
> > +#define IMX290_ADBIT_10BIT				(0 << 0)
> > +#define IMX290_ADBIT_12BIT				(1 << 0)
> > +#define IMX290_CTRL_07					IMX290_REG_8BIT(0x3007)
> > +#define IMX290_VREVERSE					BIT(0)
> > +#define IMX290_HREVERSE					BIT(1)
> > +#define IMX290_WINMODE_1080P				(0 << 4)
> > +#define IMX290_WINMODE_720P				(1 << 4)
> > +#define IMX290_WINMODE_CROP				(4 << 4)
> >  #define IMX290_FR_FDG_SEL				IMX290_REG_8BIT(0x3009)
> >  #define IMX290_BLKLEVEL					IMX290_REG_16BIT(0x300a)
> >  #define IMX290_GAIN					IMX290_REG_8BIT(0x3014)
> > +#define IMX290_VMAX					IMX290_REG_24BIT(0x3018)
> >  #define IMX290_HMAX					IMX290_REG_16BIT(0x301c)
> > +#define IMX290_SHS1					IMX290_REG_24BIT(0x3020)
> > +#define IMX290_WINWV_OB					IMX290_REG_8BIT(0x303a)
> > +#define IMX290_WINPV					IMX290_REG_16BIT(0x303c)
> > +#define IMX290_WINWV					IMX290_REG_16BIT(0x303e)
> > +#define IMX290_WINPH					IMX290_REG_16BIT(0x3040)
> > +#define IMX290_WINWH					IMX290_REG_16BIT(0x3042)
> > +#define IMX290_OUT_CTRL					IMX290_REG_8BIT(0x3046)
> > +#define IMX290_ODBIT_10BIT				(0 << 0)
> > +#define IMX290_ODBIT_12BIT				(1 << 0)
> 
> ODBIT is fixed 1h for MIPI-CSI-2 output.
> 
> > +#define IMX290_OPORTSEL_PARALLEL			(0x0 << 4)
> > +#define IMX290_OPORTSEL_LVDS_2CH			(0xd << 4)
> > +#define IMX290_OPORTSEL_LVDS_4CH			(0xe << 4)
> > +#define IMX290_OPORTSEL_LVDS_8CH			(0xf << 4)
> 
> This driver only supports MIPI-CSI-2 output, but these bits are don't care, 
> you still want to list them here for completeness?

Yes, it could be useful later.

> > +#define IMX290_XSOUTSEL					IMX290_REG_8BIT(0x304b)
> > +#define IMX290_XSOUTSEL_XVSOUTSEL_HIGH			(0 << 0)
> > +#define IMX290_XSOUTSEL_XVSOUTSEL_VSYNC			(2 << 0)
> > +#define IMX290_XSOUTSEL_XHSOUTSEL_HIGH			(0 << 2)
> > +#define IMX290_XSOUTSEL_XHSOUTSEL_HSYNC			(2 << 2)
> > +#define IMX290_INCKSEL1					IMX290_REG_8BIT(0x305c)
> > +#define IMX290_INCKSEL2					IMX290_REG_8BIT(0x305d)
> > +#define IMX290_INCKSEL3					IMX290_REG_8BIT(0x305e)
> > +#define IMX290_INCKSEL4					IMX290_REG_8BIT(0x305f)
> >  #define IMX290_PGCTRL					IMX290_REG_8BIT(0x308c)
> > +#define IMX290_ADBIT1					IMX290_REG_8BIT(0x3129)
> > +#define IMX290_ADBIT1_10BIT				0x1d
> > +#define IMX290_ADBIT1_12BIT				0x00
> > +#define IMX290_INCKSEL5					IMX290_REG_8BIT(0x315e)
> > +#define IMX290_INCKSEL6					IMX290_REG_8BIT(0x3164)
> 
> Any reason to skip the bit defines for both supported input clocks?

I don't have access to information that describes the bits in those two
registers, just magic values for the 37.125 MHz and 74.25 MHz input
clocks. Would you happen to know more ?

> > +#define IMX290_ADBIT2					IMX290_REG_8BIT(0x317c)
> > +#define IMX290_ADBIT2_10BIT				0x12
> > +#define IMX290_ADBIT2_12BIT				0x00
> >  #define IMX290_CHIP_ID					IMX290_REG_16BIT(0x319a)
> > +#define IMX290_ADBIT3					IMX290_REG_16BIT(0x31ec)
> > +#define IMX290_ADBIT3_10BIT				0x37
> > +#define IMX290_ADBIT3_12BIT				0x0e
> > +#define IMX290_REPETITION				IMX290_REG_8BIT(0x3405)
> >  #define IMX290_PHY_LANE_NUM				IMX290_REG_8BIT(0x3407)
> > +#define IMX290_OPB_SIZE_V				IMX290_REG_8BIT(0x3414)
> > +#define IMX290_Y_OUT_SIZE				IMX290_REG_16BIT(0x3418)
> > +#define IMX290_CSI_DT_FMT				IMX290_REG_16BIT(0x3441)
> > +#define IMX290_CSI_DT_FMT_RAW10				0x0a0a
> > +#define IMX290_CSI_DT_FMT_RAW12				0x0c0c
> >  #define IMX290_CSI_LANE_MODE				IMX290_REG_8BIT(0x3443)
> > +#define IMX290_EXTCK_FREQ				IMX290_REG_16BIT(0x3444)
> 
> Same here.

Same explanation as above :-)

> > +#define IMX290_TCLKPOST					IMX290_REG_16BIT(0x3446)
> > +#define IMX290_THSZERO					IMX290_REG_16BIT(0x3448)
> > +#define IMX290_THSPREPARE				IMX290_REG_16BIT(0x344a)
> > +#define IMX290_TCLKTRAIL				IMX290_REG_16BIT(0x344c)
> > +#define IMX290_THSTRAIL					IMX290_REG_16BIT(0x344e)
> > +#define IMX290_TCLKZERO					IMX290_REG_16BIT(0x3450)
> > +#define IMX290_TCLKPREPARE				IMX290_REG_16BIT(0x3452)
> > +#define IMX290_TLPX					IMX290_REG_16BIT(0x3454)
> > +#define IMX290_X_OUT_SIZE				IMX290_REG_16BIT(0x3472)
> > 
> >  #define IMX290_PGCTRL_REGEN				BIT(0)
> >  #define IMX290_PGCTRL_THRU				BIT(1)
> > @@ -54,7 +113,7 @@ static const char * const imx290_supply_name[] = {
> > 
> >  struct imx290_regval {
> >  	u32 reg;
> > -	u8 val;
> > +	u32 val;
> >  };
> > 
> >  struct imx290_mode {
> > @@ -116,22 +175,16 @@ static const char * const imx290_test_pattern_menu[] =
> > { };
> > 
> >  static const struct imx290_regval imx290_global_init_settings[] = {
> > -	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3018), 0x65 },
> > -	{ IMX290_REG_8BIT(0x3019), 0x04 },
> > -	{ IMX290_REG_8BIT(0x301a), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3444), 0x20 },
> > -	{ IMX290_REG_8BIT(0x3445), 0x25 },
> > -	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > -	{ IMX290_REG_8BIT(0x3040), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3041), 0x00 },
> > -	{ IMX290_REG_8BIT(0x303c), 0x00 },
> > -	{ IMX290_REG_8BIT(0x303d), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3042), 0x9c },
> > -	{ IMX290_REG_8BIT(0x3043), 0x07 },
> > -	{ IMX290_REG_8BIT(0x303e), 0x49 },
> > -	{ IMX290_REG_8BIT(0x303f), 0x04 },
> > -	{ IMX290_REG_8BIT(0x304b), 0x0a },
> > +	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> > +	{ IMX290_VMAX, 1125 },
> > +	{ IMX290_EXTCK_FREQ, 0x2520 },
> > +	{ IMX290_WINWV_OB, 12 },
> > +	{ IMX290_WINPH, 0 },
> > +	{ IMX290_WINPV, 0 },
> > +	{ IMX290_WINWH, 1948 },
> > +	{ IMX290_WINWV, 1097 },
> > +	{ IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
> > +			   IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
> >  	{ IMX290_REG_8BIT(0x300f), 0x00 },
> >  	{ IMX290_REG_8BIT(0x3010), 0x21 },
> >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > @@ -177,102 +230,78 @@ static const struct imx290_regval
> > imx290_global_init_settings[] = {
> > 
> >  static const struct imx290_regval imx290_1080p_settings[] = {
> >  	/* mode settings */
> > -	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > -	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > -	{ IMX290_REG_8BIT(0x3414), 0x0a },
> > -	{ IMX290_REG_8BIT(0x3472), 0x80 },
> > -	{ IMX290_REG_8BIT(0x3473), 0x07 },
> > -	{ IMX290_REG_8BIT(0x3418), 0x38 },
> > -	{ IMX290_REG_8BIT(0x3419), 0x04 },
> > +	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> > +	{ IMX290_WINWV_OB, 12 },
> > +	{ IMX290_OPB_SIZE_V, 10 },
> > +	{ IMX290_X_OUT_SIZE, 1920 },
> > +	{ IMX290_Y_OUT_SIZE, 1080 },
> >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> >  	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > -	{ IMX290_REG_8BIT(0x305c), 0x18 },
> > -	{ IMX290_REG_8BIT(0x305d), 0x03 },
> > -	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > -	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > -	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > -	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > +	{ IMX290_INCKSEL1, 0x18 },
> > +	{ IMX290_INCKSEL2, 0x03 },
> > +	{ IMX290_INCKSEL3, 0x20 },
> > +	{ IMX290_INCKSEL4, 0x01 },
> > +	{ IMX290_INCKSEL5, 0x1a },
> > +	{ IMX290_INCKSEL6, 0x1a },
> >  	{ IMX290_REG_8BIT(0x3480), 0x49 },
> >  	/* data rate settings */
> > -	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > -	{ IMX290_REG_8BIT(0x3446), 0x57 },
> > -	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3448), 0x37 },
> > -	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > -	{ IMX290_REG_8BIT(0x344a), 0x1f },
> > -	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > -	{ IMX290_REG_8BIT(0x344c), 0x1f },
> > -	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > -	{ IMX290_REG_8BIT(0x344e), 0x1f },
> > -	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3450), 0x77 },
> > -	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3452), 0x1f },
> > -	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > -	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > +	{ IMX290_REPETITION, 0x10 },
> > +	{ IMX290_TCLKPOST, 87 },
> > +	{ IMX290_THSZERO, 55 },
> > +	{ IMX290_THSPREPARE, 31 },
> > +	{ IMX290_TCLKTRAIL, 31 },
> > +	{ IMX290_THSTRAIL, 31 },
> > +	{ IMX290_TCLKZERO, 119 },
> > +	{ IMX290_TCLKPREPARE, 31 },
> > +	{ IMX290_TLPX, 23 },
> >  };
> > 
> >  static const struct imx290_regval imx290_720p_settings[] = {
> >  	/* mode settings */
> > -	{ IMX290_REG_8BIT(0x3007), 0x10 },
> > -	{ IMX290_REG_8BIT(0x303a), 0x06 },
> > -	{ IMX290_REG_8BIT(0x3414), 0x04 },
> > -	{ IMX290_REG_8BIT(0x3472), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3473), 0x05 },
> > -	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> > -	{ IMX290_REG_8BIT(0x3419), 0x02 },
> > +	{ IMX290_CTRL_07, IMX290_WINMODE_720P },
> > +	{ IMX290_WINWV_OB, 6 },
> > +	{ IMX290_OPB_SIZE_V, 4 },
> > +	{ IMX290_X_OUT_SIZE, 1280 },
> > +	{ IMX290_Y_OUT_SIZE, 720 },
> >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> >  	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > -	{ IMX290_REG_8BIT(0x305c), 0x20 },
> > -	{ IMX290_REG_8BIT(0x305d), 0x00 },
> > -	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > -	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > -	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > -	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > +	{ IMX290_INCKSEL1, 0x20 },
> > +	{ IMX290_INCKSEL2, 0x00 },
> > +	{ IMX290_INCKSEL3, 0x20 },
> > +	{ IMX290_INCKSEL4, 0x01 },
> > +	{ IMX290_INCKSEL5, 0x1a },
> > +	{ IMX290_INCKSEL6, 0x1a },
> >  	{ IMX290_REG_8BIT(0x3480), 0x49 },
> >  	/* data rate settings */
> > -	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > -	{ IMX290_REG_8BIT(0x3446), 0x4f },
> > -	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3448), 0x2f },
> > -	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > -	{ IMX290_REG_8BIT(0x344a), 0x17 },
> > -	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > -	{ IMX290_REG_8BIT(0x344c), 0x17 },
> > -	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > -	{ IMX290_REG_8BIT(0x344e), 0x17 },
> > -	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3450), 0x57 },
> > -	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3452), 0x17 },
> > -	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > -	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > -	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > +	{ IMX290_REPETITION, 0x10 },
> > +	{ IMX290_TCLKPOST, 79 },
> > +	{ IMX290_THSZERO, 47 },
> > +	{ IMX290_THSPREPARE, 23 },
> > +	{ IMX290_TCLKTRAIL, 23 },
> > +	{ IMX290_THSTRAIL, 23 },
> > +	{ IMX290_TCLKZERO, 87 },
> > +	{ IMX290_TCLKPREPARE, 23 },
> > +	{ IMX290_TLPX, 23 },
> >  };
> > 
> >  static const struct imx290_regval imx290_10bit_settings[] = {
> > -	{ IMX290_REG_8BIT(0x3005), 0x00},
> > -	{ IMX290_REG_8BIT(0x3046), 0x00},
> > -	{ IMX290_REG_8BIT(0x3129), 0x1d},
> > -	{ IMX290_REG_8BIT(0x317c), 0x12},
> > -	{ IMX290_REG_8BIT(0x31ec), 0x37},
> > -	{ IMX290_REG_8BIT(0x3441), 0x0a},
> > -	{ IMX290_REG_8BIT(0x3442), 0x0a},
> > -	{ IMX290_REG_8BIT(0x300a), 0x3c},
> > -	{ IMX290_REG_8BIT(0x300b), 0x00},
> > +	{ IMX290_ADBIT, IMX290_ADBIT_10BIT },
> > +	{ IMX290_OUT_CTRL, IMX290_ODBIT_10BIT },
> > +	{ IMX290_ADBIT1, IMX290_ADBIT1_10BIT },
> > +	{ IMX290_ADBIT2, IMX290_ADBIT2_10BIT },
> > +	{ IMX290_ADBIT3, IMX290_ADBIT3_10BIT },
> > +	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW10 },
> > +	{ IMX290_BLKLEVEL, 60 },
> >  };
> > 
> >  static const struct imx290_regval imx290_12bit_settings[] = {
> > -	{ IMX290_REG_8BIT(0x3005), 0x01 },
> > -	{ IMX290_REG_8BIT(0x3046), 0x01 },
> > -	{ IMX290_REG_8BIT(0x3129), 0x00 },
> > -	{ IMX290_REG_8BIT(0x317c), 0x00 },
> > -	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> > -	{ IMX290_REG_8BIT(0x3441), 0x0c },
> > -	{ IMX290_REG_8BIT(0x3442), 0x0c },
> > -	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> > -	{ IMX290_REG_8BIT(0x300b), 0x00 },
> > +	{ IMX290_ADBIT, IMX290_ADBIT_12BIT },
> > +	{ IMX290_OUT_CTRL, IMX290_ODBIT_12BIT },
> > +	{ IMX290_ADBIT1, IMX290_ADBIT1_12BIT },
> > +	{ IMX290_ADBIT2, IMX290_ADBIT2_12BIT },
> > +	{ IMX290_ADBIT3, IMX290_ADBIT3_12BIT },
> > +	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW12 },
> > +	{ IMX290_BLKLEVEL, 240 },
> >  };
> > 
> >  /* supported link frequencies */

-- 
Regards,

Laurent Pinchart

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

* Re: Re: [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array
  2022-07-21 10:40     ` Laurent Pinchart
@ 2022-07-21 11:08       ` Alexander Stein
  2022-07-21 16:19         ` Dave Stevenson
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 11:08 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hello Laurent,

Am Donnerstag, 21. Juli 2022, 12:40:36 CEST schrieb Laurent Pinchart:
> Hi Alexander,
> 
> On Thu, Jul 21, 2022 at 12:08:50PM +0200, Alexander Stein wrote:
> > Am Donnerstag, 21. Juli 2022, 10:35:37 CEST schrieb Laurent Pinchart:
> > > Registers 0x3012, 0x3013 and 0x3480 are not documented and are set in
> > > the per-mode register arrays with values indentical for all modes. Move
> > > them to the common array.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/media/i2c/imx290.c | 8 ++------
> > >  1 file changed, 2 insertions(+), 6 deletions(-)
> > > 
> > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > index 78772c6327a2..fc6e87fada1c 100644
> > > --- a/drivers/media/i2c/imx290.c
> > > +++ b/drivers/media/i2c/imx290.c
> > > @@ -192,6 +192,7 @@ static const struct imx290_regval
> > > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x300f), 0x00 },
> > > 
> > >  	{ IMX290_REG_8BIT(0x3010), 0x21 },
> > >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > 
> > > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > 
> > >  	{ IMX290_REG_8BIT(0x3016), 0x09 },
> > >  	{ IMX290_REG_8BIT(0x3070), 0x02 },
> > >  	{ IMX290_REG_8BIT(0x3071), 0x11 },
> > > 
> > > @@ -230,6 +231,7 @@ static const struct imx290_regval
> > > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x33b0), 0x50 },
> > > 
> > >  	{ IMX290_REG_8BIT(0x33b2), 0x1a },
> > >  	{ IMX290_REG_8BIT(0x33b3), 0x04 },
> > > 
> > > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > 
> > >  };
> > >  
> > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > > 
> > > @@ -239,15 +241,12 @@ static const struct imx290_regval
> > > imx290_1080p_settings[] = { { IMX290_OPB_SIZE_V, 10 },
> > > 
> > >  	{ IMX290_X_OUT_SIZE, 1920 },
> > >  	{ IMX290_Y_OUT_SIZE, 1080 },
> > > 
> > > -	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > -	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > 
> > >  	{ IMX290_INCKSEL1, 0x18 },
> > >  	{ IMX290_INCKSEL2, 0x03 },
> > >  	{ IMX290_INCKSEL3, 0x20 },
> > >  	{ IMX290_INCKSEL4, 0x01 },
> > >  	{ IMX290_INCKSEL5, 0x1a },
> > >  	{ IMX290_INCKSEL6, 0x1a },
> > > 
> > > -	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > 
> > >  	/* data rate settings */
> > >  	{ IMX290_REPETITION, 0x10 },
> > >  	{ IMX290_TCLKPOST, 87 },
> > > 
> > > @@ -267,15 +266,12 @@ static const struct imx290_regval
> > > imx290_720p_settings[] = { { IMX290_OPB_SIZE_V, 4 },
> > > 
> > >  	{ IMX290_X_OUT_SIZE, 1280 },
> > >  	{ IMX290_Y_OUT_SIZE, 720 },
> > > 
> > > -	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > -	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > 
> > >  	{ IMX290_INCKSEL1, 0x20 },
> > >  	{ IMX290_INCKSEL2, 0x00 },
> > >  	{ IMX290_INCKSEL3, 0x20 },
> > >  	{ IMX290_INCKSEL4, 0x01 },
> > >  	{ IMX290_INCKSEL5, 0x1a },
> > >  	{ IMX290_INCKSEL6, 0x1a },
> > > 
> > > -	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > 
> > >  	/* data rate settings */
> > >  	{ IMX290_REPETITION, 0x10 },
> > >  	{ IMX290_TCLKPOST, 79 },
> > 
> > 0x3480 is INCKSEL7 for imx327, not sure if that should be set yet for
> > imx290 (only) driver, without proper imx327 support.
> 
> Do you mean the register doesn't exist on the IMX290 ? We could make it
> conditional on the sensor model, but it's not added by this patch, it
> has been there since the first version of the driver, so I'd rather do
> that on top.

As far as I know INCKSEL7 is only valid on imx327. On imx290 the whole 
0x300-0x34ff range is reserved.
I agree this should be conditional on the sensor model. If you want to keep 
it, because it is not new, I'm fine with that.

Best regards,
Alexander




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

* Re: Re: [PATCH 17/19] media: i2c: imx290: Factor out format retrieval to separate function
  2022-07-21 10:36     ` Laurent Pinchart
@ 2022-07-21 11:12       ` Alexander Stein
  0 siblings, 0 replies; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 11:12 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent,

Am Donnerstag, 21. Juli 2022, 12:36:35 CEST schrieb Laurent Pinchart:
> Hi Alexander,
> 
> On Thu, Jul 21, 2022 at 12:11:31PM +0200, Alexander Stein wrote:
> > Am Donnerstag, 21. Juli 2022, 10:35:38 CEST schrieb Laurent Pinchart:
> > > The driver duplicates the same pattern to access the try or active
> > > format in multiple locations. Factor it out to a separate function.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/media/i2c/imx290.c | 28 ++++++++++++++++++----------
> > >  1 file changed, 18 insertions(+), 10 deletions(-)
> > > 
> > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > index fc6e87fada1c..baf9941c5fbe 100644
> > > --- a/drivers/media/i2c/imx290.c
> > > +++ b/drivers/media/i2c/imx290.c
> > > @@ -519,6 +519,20 @@ static const struct v4l2_ctrl_ops imx290_ctrl_ops =
> > > {
> > > 
> > >  	.s_ctrl = imx290_set_ctrl,
> > >  
> > >  };
> > > 
> > > +static struct v4l2_mbus_framefmt *
> > > +imx290_get_pad_format(struct imx290 *imx290, struct v4l2_subdev_state
> > > *state, +		      u32 which)
> > > +{
> > > +	switch (which) {
> > > +	case V4L2_SUBDEV_FORMAT_TRY:
> > > +		return v4l2_subdev_get_try_format(&imx290->sd, state, 
0);
> > > +	case V4L2_SUBDEV_FORMAT_ACTIVE:
> > > +		return &imx290->current_format;
> > > +	default:
> > > +		return NULL;
> > > +	}
> > > +}
> > > +
> > > 
> > >  static int imx290_enum_mbus_code(struct v4l2_subdev *sd,
> > >  
> > >  				 struct v4l2_subdev_state 
*sd_state,
> > >  				 struct v4l2_subdev_mbus_code_enum 
*code)
> > > 
> > > @@ -562,12 +576,7 @@ static int imx290_get_fmt(struct v4l2_subdev *sd,
> > > 
> > >  	mutex_lock(&imx290->lock);
> > > 
> > > -	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
> > > -		framefmt = v4l2_subdev_get_try_format(&imx290->sd, 
sd_state,
> > > -						      fmt-
>pad);
> > > -	else
> > > -		framefmt = &imx290->current_format;
> > > -
> > > +	framefmt = imx290_get_pad_format(imx290, sd_state, fmt->which);
> > > 
> > >  	fmt->format = *framefmt;
> > 
> > NULL ptr derence here if 'fmt->which' is neither V4L2_SUBDEV_FORMAT_TRY
> > nor
> > V4L2_SUBDEV_FORMAT_ACTIVE. Same for imx290_set_fmt later on.
> 
> You're right, but this can't happen, TRY and ACTIVE are the only two
> possible values.

fmt (and therefore which) is only a u32, so there is no benefit to treat it 
like an enum. IMHO using the old if-else structure seems better. This might 
also help static code analysis which does not have such background 
information.
If 'which' would be changed to type enum v4l2_subdev_format_whence, the switch 
case seems preferable.

Best regards,
Alexander

> > >  	mutex_unlock(&imx290->lock);
> > > 
> > > @@ -627,10 +636,9 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> > > 
> > >  	fmt->format.code = imx290_formats[i].code;
> > >  	fmt->format.field = V4L2_FIELD_NONE;
> > > 
> > > -	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
> > > -		format = v4l2_subdev_get_try_format(sd, sd_state, fmt-
>pad);
> > > -	} else {
> > > -		format = &imx290->current_format;
> > > +	format = imx290_get_pad_format(imx290, sd_state, fmt->which);
> > > +
> > > +	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
> > > 
> > >  		imx290->current_mode = mode;
> > >  		imx290->bpp = imx290_formats[i].bpp;





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

* Re: [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls
  2022-07-21 10:05   ` Alexander Stein
@ 2022-07-21 11:17     ` Laurent Pinchart
  2022-07-21 11:32       ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21 11:17 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Alexander,

On Thu, Jul 21, 2022 at 12:05:46PM +0200, Alexander Stein wrote:
> Am Donnerstag, 21. Juli 2022, 10:35:35 CEST schrieb Laurent Pinchart:
> > Add support for the V4L2_CID_HBLANK and V4L2_CID_VBLANK controls to the
> > imx290 driver. Make the controls read-only to start with, to report the
> > values to userspace for timing calculation.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/i2c/imx290.c | 39 +++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 38 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index 4408dd3e191f..7190399f4111 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -146,6 +146,8 @@ struct imx290 {
> >  	struct v4l2_ctrl_handler ctrls;
> >  	struct v4l2_ctrl *link_freq;
> >  	struct v4l2_ctrl *pixel_rate;
> > +	struct v4l2_ctrl *hblank;
> > +	struct v4l2_ctrl *vblank;
> > 
> >  	struct mutex lock;
> >  };
> > @@ -642,6 +644,20 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> >  		if (imx290->pixel_rate)
> >  			__v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
> >  						 imx290_calc_pixel_rate(imx290));
> > +
> > +		if (imx290->hblank) {
> > +			unsigned int hblank = mode->hmax - mode->width;
> > +
> > +			__v4l2_ctrl_modify_range(imx290->hblank, hblank, hblank,
> > +						 1, hblank);
> > +		}
> > +
> > +		if (imx290->vblank) {
> > +			unsigned int vblank = IMX290_VMAX_DEFAULT - mode->height;
> > +
> > +			__v4l2_ctrl_modify_range(imx290->vblank, vblank, vblank,
> > +						 1, vblank);
> > +		}
> >  	}
> > 
> >  	*format = fmt->format;
> > @@ -880,9 +896,10 @@ static const struct media_entity_operations imx290_subdev_entity_ops = {
> > 
> >  static int imx290_ctrl_init(struct imx290 *imx290)
> >  {
> > +	unsigned int blank;
> >  	int ret;
> > 
> > -	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
> > +	v4l2_ctrl_handler_init(&imx290->ctrls, 7);
> >  	imx290->ctrls.lock = &imx290->lock;
> > 
> >  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > @@ -910,6 +927,26 @@ static int imx290_ctrl_init(struct imx290 *imx290)
> >  				     ARRAY_SIZE(imx290_test_pattern_menu) - 1,
> >  				     0, 0, imx290_test_pattern_menu);
> > 
> > +	/*
> > +	 * Horizontal blanking is controlled through the HMAX register, which
> > +	 * contains a line length in INCK clock units. The INCK frequency is
> > +	 * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100,
> > +	 * convert it to a number of pixels based on the nominal pixel rate.
> > +	 */
> 
> Currently the driver only supports 37.125 MHz, please refer to imx290_probe.

Indeed. Re-reading the comment, I suspect something is wrong, as hmax is
not converted to pixels here (and is also not fixed to 1100). The only
datasheet I found that is publicly accessed doesn't explain very clearly
how the HMAX value should be computed. Based on your experience with IMX
sensors, would you be able to shed some light on this ?

> > +	blank = imx290->current_mode->hmax - imx290->current_mode->width;
> > +	imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > +					   V4L2_CID_HBLANK, blank, blank, 1,
> > +					   blank);
> > +	if (imx290->hblank)
> > +		imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > +
> > +	blank = IMX290_VMAX_DEFAULT - imx290->current_mode->height;
> > +	imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > +					   V4L2_CID_VBLANK, blank, blank, 1,
> > +					   blank);
> > +	if (imx290->vblank)
> > +		imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > +
> >  	imx290->sd.ctrl_handler = &imx290->ctrls;
> > 
> >  	if (imx290->ctrls.error) {

-- 
Regards,

Laurent Pinchart

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

* Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-21 10:54     ` Laurent Pinchart
@ 2022-07-21 11:18       ` Alexander Stein
  2022-07-21 11:25         ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 11:18 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent,

Am Donnerstag, 21. Juli 2022, 12:54:51 CEST schrieb Laurent Pinchart:
> Hi Alexander,
> 
> On Thu, Jul 21, 2022 at 11:43:47AM +0200, Alexander Stein wrote:
> > Am Donnerstag, 21. Juli 2022, 10:35:28 CEST schrieb Laurent Pinchart:
> > > The IMX290 has registers of different sizes. To simplify the code,
> > > handle this in the read/write functions instead of in the callers by
> > > encoding the register size in the symbolic name macros. All registers
> > > are defined as 8-bit for now, a subsequent change will move to larger
> > > registers where applicable.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/media/i2c/imx290.c | 352 +++++++++++++++++++------------------
> > >  1 file changed, 180 insertions(+), 172 deletions(-)
> > > 
> > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > index 711282126c34..ac58bfe6db7f 100644
> > > --- a/drivers/media/i2c/imx290.c
> > > +++ b/drivers/media/i2c/imx290.c
> > > @@ -22,22 +22,28 @@
> > > 
> > >  #include <media/v4l2-fwnode.h>
> > >  #include <media/v4l2-subdev.h>
> > > 
> > > -#define IMX290_STANDBY 0x3000
> > > -#define IMX290_REGHOLD 0x3001
> > > -#define IMX290_XMSTA 0x3002
> > > -#define IMX290_FR_FDG_SEL 0x3009
> > > -#define IMX290_BLKLEVEL_LOW 0x300a
> > > -#define IMX290_BLKLEVEL_HIGH 0x300b
> > > -#define IMX290_GAIN 0x3014
> > > -#define IMX290_HMAX_LOW 0x301c
> > > -#define IMX290_HMAX_HIGH 0x301d
> > > -#define IMX290_PGCTRL 0x308c
> > > -#define IMX290_PHY_LANE_NUM 0x3407
> > > -#define IMX290_CSI_LANE_MODE 0x3443
> > > +#define IMX290_REG_8BIT(n)				((1 << 16) | 
(n))
> > > +#define IMX290_REG_16BIT(n)				
((2 << 16) | (n))
> > > +#define IMX290_REG_24BIT(n)				
((3 << 16) | (n))
> > 
> > IMX290_REG_SIZE_SHIFT instead of 16 here? Not exactly necessary, but use
> > 1U, 2U and 3U instead.
> 
> I'll fix that.
> 
> > > +#define IMX290_REG_SIZE_SHIFT				
16
> > > +#define IMX290_REG_ADDR_MASK				
0xffff
> > > 
> > > -#define IMX290_PGCTRL_REGEN BIT(0)
> > > -#define IMX290_PGCTRL_THRU BIT(1)
> > > -#define IMX290_PGCTRL_MODE(n) ((n) << 4)
> > > +#define IMX290_STANDBY					
IMX290_REG_8BIT(0x3000)
> > > +#define IMX290_REGHOLD					
IMX290_REG_8BIT(0x3001)
> > > +#define IMX290_XMSTA					
IMX290_REG_8BIT(0x3002)
> > > +#define IMX290_FR_FDG_SEL				
IMX290_REG_8BIT(0x3009)
> > > +#define IMX290_BLKLEVEL_LOW				
IMX290_REG_8BIT(0x300a)
> > > +#define IMX290_BLKLEVEL_HIGH				
IMX290_REG_8BIT(0x300b)
> > > +#define IMX290_GAIN					
IMX290_REG_8BIT(0x3014)
> > > +#define IMX290_HMAX_LOW					
IMX290_REG_8BIT(0x301c)
> > > +#define IMX290_HMAX_HIGH				
IMX290_REG_8BIT(0x301d)
> > > +#define IMX290_PGCTRL					
IMX290_REG_8BIT(0x308c)
> > > +#define IMX290_PHY_LANE_NUM				
IMX290_REG_8BIT(0x3407)
> > > +#define IMX290_CSI_LANE_MODE				
IMX290_REG_8BIT(0x3443)
> > > +
> > > +#define IMX290_PGCTRL_REGEN				
BIT(0)
> > > +#define IMX290_PGCTRL_THRU				BIT(1)
> > > +#define IMX290_PGCTRL_MODE(n)				
((n) << 4)
> > > 
> > >  static const char * const imx290_supply_name[] = {
> > >  
> > >  	"vdda",
> > > 
> > > @@ -48,7 +54,7 @@ static const char * const imx290_supply_name[] = {
> > > 
> > >  #define IMX290_NUM_SUPPLIES ARRAY_SIZE(imx290_supply_name)
> > >  
> > >  struct imx290_regval {
> > > 
> > > -	u16 reg;
> > > +	u32 reg;
> > > 
> > >  	u8 val;
> > >  
> > >  };
> > > 
> > > @@ -111,163 +117,163 @@ static const char * const
> > > imx290_test_pattern_menu[] = { };
> > > 
> > >  static const struct imx290_regval imx290_global_init_settings[] = {
> > > 
> > > -	{ 0x3007, 0x00 },
> > > -	{ 0x3018, 0x65 },
> > > -	{ 0x3019, 0x04 },
> > > -	{ 0x301a, 0x00 },
> > > -	{ 0x3444, 0x20 },
> > > -	{ 0x3445, 0x25 },
> > > -	{ 0x303a, 0x0c },
> > > -	{ 0x3040, 0x00 },
> > > -	{ 0x3041, 0x00 },
> > > -	{ 0x303c, 0x00 },
> > > -	{ 0x303d, 0x00 },
> > > -	{ 0x3042, 0x9c },
> > > -	{ 0x3043, 0x07 },
> > > -	{ 0x303e, 0x49 },
> > > -	{ 0x303f, 0x04 },
> > > -	{ 0x304b, 0x0a },
> > > -	{ 0x300f, 0x00 },
> > > -	{ 0x3010, 0x21 },
> > > -	{ 0x3012, 0x64 },
> > > -	{ 0x3016, 0x09 },
> > > -	{ 0x3070, 0x02 },
> > > -	{ 0x3071, 0x11 },
> > > -	{ 0x309b, 0x10 },
> > > -	{ 0x309c, 0x22 },
> > > -	{ 0x30a2, 0x02 },
> > > -	{ 0x30a6, 0x20 },
> > > -	{ 0x30a8, 0x20 },
> > > -	{ 0x30aa, 0x20 },
> > > -	{ 0x30ac, 0x20 },
> > > -	{ 0x30b0, 0x43 },
> > > -	{ 0x3119, 0x9e },
> > > -	{ 0x311c, 0x1e },
> > > -	{ 0x311e, 0x08 },
> > > -	{ 0x3128, 0x05 },
> > > -	{ 0x313d, 0x83 },
> > > -	{ 0x3150, 0x03 },
> > > -	{ 0x317e, 0x00 },
> > > -	{ 0x32b8, 0x50 },
> > > -	{ 0x32b9, 0x10 },
> > > -	{ 0x32ba, 0x00 },
> > > -	{ 0x32bb, 0x04 },
> > > -	{ 0x32c8, 0x50 },
> > > -	{ 0x32c9, 0x10 },
> > > -	{ 0x32ca, 0x00 },
> > > -	{ 0x32cb, 0x04 },
> > > -	{ 0x332c, 0xd3 },
> > > -	{ 0x332d, 0x10 },
> > > -	{ 0x332e, 0x0d },
> > > -	{ 0x3358, 0x06 },
> > > -	{ 0x3359, 0xe1 },
> > > -	{ 0x335a, 0x11 },
> > > -	{ 0x3360, 0x1e },
> > > -	{ 0x3361, 0x61 },
> > > -	{ 0x3362, 0x10 },
> > > -	{ 0x33b0, 0x50 },
> > > -	{ 0x33b2, 0x1a },
> > > -	{ 0x33b3, 0x04 },
> > > +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3018), 0x65 },
> > > +	{ IMX290_REG_8BIT(0x3019), 0x04 },
> > > +	{ IMX290_REG_8BIT(0x301a), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3444), 0x20 },
> > > +	{ IMX290_REG_8BIT(0x3445), 0x25 },
> > > +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > +	{ IMX290_REG_8BIT(0x3040), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3041), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x303c), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x303d), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3042), 0x9c },
> > > +	{ IMX290_REG_8BIT(0x3043), 0x07 },
> > > +	{ IMX290_REG_8BIT(0x303e), 0x49 },
> > > +	{ IMX290_REG_8BIT(0x303f), 0x04 },
> > > +	{ IMX290_REG_8BIT(0x304b), 0x0a },
> > > +	{ IMX290_REG_8BIT(0x300f), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3010), 0x21 },
> > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > +	{ IMX290_REG_8BIT(0x3016), 0x09 },
> > > +	{ IMX290_REG_8BIT(0x3070), 0x02 },
> > > +	{ IMX290_REG_8BIT(0x3071), 0x11 },
> > > +	{ IMX290_REG_8BIT(0x309b), 0x10 },
> > > +	{ IMX290_REG_8BIT(0x309c), 0x22 },
> > > +	{ IMX290_REG_8BIT(0x30a2), 0x02 },
> > > +	{ IMX290_REG_8BIT(0x30a6), 0x20 },
> > > +	{ IMX290_REG_8BIT(0x30a8), 0x20 },
> > > +	{ IMX290_REG_8BIT(0x30aa), 0x20 },
> > > +	{ IMX290_REG_8BIT(0x30ac), 0x20 },
> > > +	{ IMX290_REG_8BIT(0x30b0), 0x43 },
> > > +	{ IMX290_REG_8BIT(0x3119), 0x9e },
> > > +	{ IMX290_REG_8BIT(0x311c), 0x1e },
> > > +	{ IMX290_REG_8BIT(0x311e), 0x08 },
> > > +	{ IMX290_REG_8BIT(0x3128), 0x05 },
> > > +	{ IMX290_REG_8BIT(0x313d), 0x83 },
> > > +	{ IMX290_REG_8BIT(0x3150), 0x03 },
> > > +	{ IMX290_REG_8BIT(0x317e), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x32b8), 0x50 },
> > > +	{ IMX290_REG_8BIT(0x32b9), 0x10 },
> > > +	{ IMX290_REG_8BIT(0x32ba), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x32bb), 0x04 },
> > > +	{ IMX290_REG_8BIT(0x32c8), 0x50 },
> > > +	{ IMX290_REG_8BIT(0x32c9), 0x10 },
> > > +	{ IMX290_REG_8BIT(0x32ca), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x32cb), 0x04 },
> > > +	{ IMX290_REG_8BIT(0x332c), 0xd3 },
> > > +	{ IMX290_REG_8BIT(0x332d), 0x10 },
> > > +	{ IMX290_REG_8BIT(0x332e), 0x0d },
> > > +	{ IMX290_REG_8BIT(0x3358), 0x06 },
> > > +	{ IMX290_REG_8BIT(0x3359), 0xe1 },
> > > +	{ IMX290_REG_8BIT(0x335a), 0x11 },
> > > +	{ IMX290_REG_8BIT(0x3360), 0x1e },
> > > +	{ IMX290_REG_8BIT(0x3361), 0x61 },
> > > +	{ IMX290_REG_8BIT(0x3362), 0x10 },
> > > +	{ IMX290_REG_8BIT(0x33b0), 0x50 },
> > > +	{ IMX290_REG_8BIT(0x33b2), 0x1a },
> > > +	{ IMX290_REG_8BIT(0x33b3), 0x04 },
> > > 
> > >  };
> > >  
> > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > >  
> > >  	/* mode settings */
> > > 
> > > -	{ 0x3007, 0x00 },
> > > -	{ 0x303a, 0x0c },
> > > -	{ 0x3414, 0x0a },
> > > -	{ 0x3472, 0x80 },
> > > -	{ 0x3473, 0x07 },
> > > -	{ 0x3418, 0x38 },
> > > -	{ 0x3419, 0x04 },
> > > -	{ 0x3012, 0x64 },
> > > -	{ 0x3013, 0x00 },
> > > -	{ 0x305c, 0x18 },
> > > -	{ 0x305d, 0x03 },
> > > -	{ 0x305e, 0x20 },
> > > -	{ 0x305f, 0x01 },
> > > -	{ 0x315e, 0x1a },
> > > -	{ 0x3164, 0x1a },
> > > -	{ 0x3480, 0x49 },
> > > +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > +	{ IMX290_REG_8BIT(0x3414), 0x0a },
> > > +	{ IMX290_REG_8BIT(0x3472), 0x80 },
> > > +	{ IMX290_REG_8BIT(0x3473), 0x07 },
> > > +	{ IMX290_REG_8BIT(0x3418), 0x38 },
> > > +	{ IMX290_REG_8BIT(0x3419), 0x04 },
> > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x305c), 0x18 },
> > > +	{ IMX290_REG_8BIT(0x305d), 0x03 },
> > > +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > 
> > >  	/* data rate settings */
> > > 
> > > -	{ 0x3405, 0x10 },
> > > -	{ 0x3446, 0x57 },
> > > -	{ 0x3447, 0x00 },
> > > -	{ 0x3448, 0x37 },
> > > -	{ 0x3449, 0x00 },
> > > -	{ 0x344a, 0x1f },
> > > -	{ 0x344b, 0x00 },
> > > -	{ 0x344c, 0x1f },
> > > -	{ 0x344d, 0x00 },
> > > -	{ 0x344e, 0x1f },
> > > -	{ 0x344f, 0x00 },
> > > -	{ 0x3450, 0x77 },
> > > -	{ 0x3451, 0x00 },
> > > -	{ 0x3452, 0x1f },
> > > -	{ 0x3453, 0x00 },
> > > -	{ 0x3454, 0x17 },
> > > -	{ 0x3455, 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > +	{ IMX290_REG_8BIT(0x3446), 0x57 },
> > > +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3448), 0x37 },
> > > +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x344a), 0x1f },
> > > +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x344c), 0x1f },
> > > +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x344e), 0x1f },
> > > +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3450), 0x77 },
> > > +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3452), 0x1f },
> > > +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > +	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > 
> > >  };
> > >  
> > >  static const struct imx290_regval imx290_720p_settings[] = {
> > >  
> > >  	/* mode settings */
> > > 
> > > -	{ 0x3007, 0x10 },
> > > -	{ 0x303a, 0x06 },
> > > -	{ 0x3414, 0x04 },
> > > -	{ 0x3472, 0x00 },
> > > -	{ 0x3473, 0x05 },
> > > -	{ 0x3418, 0xd0 },
> > > -	{ 0x3419, 0x02 },
> > > -	{ 0x3012, 0x64 },
> > > -	{ 0x3013, 0x00 },
> > > -	{ 0x305c, 0x20 },
> > > -	{ 0x305d, 0x00 },
> > > -	{ 0x305e, 0x20 },
> > > -	{ 0x305f, 0x01 },
> > > -	{ 0x315e, 0x1a },
> > > -	{ 0x3164, 0x1a },
> > > -	{ 0x3480, 0x49 },
> > > +	{ IMX290_REG_8BIT(0x3007), 0x10 },
> > > +	{ IMX290_REG_8BIT(0x303a), 0x06 },
> > > +	{ IMX290_REG_8BIT(0x3414), 0x04 },
> > > +	{ IMX290_REG_8BIT(0x3472), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3473), 0x05 },
> > > +	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> > > +	{ IMX290_REG_8BIT(0x3419), 0x02 },
> > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x305c), 0x20 },
> > > +	{ IMX290_REG_8BIT(0x305d), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > 
> > >  	/* data rate settings */
> > > 
> > > -	{ 0x3405, 0x10 },
> > > -	{ 0x3446, 0x4f },
> > > -	{ 0x3447, 0x00 },
> > > -	{ 0x3448, 0x2f },
> > > -	{ 0x3449, 0x00 },
> > > -	{ 0x344a, 0x17 },
> > > -	{ 0x344b, 0x00 },
> > > -	{ 0x344c, 0x17 },
> > > -	{ 0x344d, 0x00 },
> > > -	{ 0x344e, 0x17 },
> > > -	{ 0x344f, 0x00 },
> > > -	{ 0x3450, 0x57 },
> > > -	{ 0x3451, 0x00 },
> > > -	{ 0x3452, 0x17 },
> > > -	{ 0x3453, 0x00 },
> > > -	{ 0x3454, 0x17 },
> > > -	{ 0x3455, 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > +	{ IMX290_REG_8BIT(0x3446), 0x4f },
> > > +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3448), 0x2f },
> > > +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x344a), 0x17 },
> > > +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x344c), 0x17 },
> > > +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x344e), 0x17 },
> > > +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3450), 0x57 },
> > > +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3452), 0x17 },
> > > +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > +	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > 
> > >  };
> > >  
> > >  static const struct imx290_regval imx290_10bit_settings[] = {
> > > 
> > > -	{ 0x3005, 0x00},
> > > -	{ 0x3046, 0x00},
> > > -	{ 0x3129, 0x1d},
> > > -	{ 0x317c, 0x12},
> > > -	{ 0x31ec, 0x37},
> > > -	{ 0x3441, 0x0a},
> > > -	{ 0x3442, 0x0a},
> > > -	{ 0x300a, 0x3c},
> > > -	{ 0x300b, 0x00},
> > > +	{ IMX290_REG_8BIT(0x3005), 0x00},
> > > +	{ IMX290_REG_8BIT(0x3046), 0x00},
> > > +	{ IMX290_REG_8BIT(0x3129), 0x1d},
> > > +	{ IMX290_REG_8BIT(0x317c), 0x12},
> > > +	{ IMX290_REG_8BIT(0x31ec), 0x37},
> > > +	{ IMX290_REG_8BIT(0x3441), 0x0a},
> > > +	{ IMX290_REG_8BIT(0x3442), 0x0a},
> > > +	{ IMX290_REG_8BIT(0x300a), 0x3c},
> > > +	{ IMX290_REG_8BIT(0x300b), 0x00},
> > > 
> > >  };
> > >  
> > >  static const struct imx290_regval imx290_12bit_settings[] = {
> > > 
> > > -	{ 0x3005, 0x01 },
> > > -	{ 0x3046, 0x01 },
> > > -	{ 0x3129, 0x00 },
> > > -	{ 0x317c, 0x00 },
> > > -	{ 0x31ec, 0x0e },
> > > -	{ 0x3441, 0x0c },
> > > -	{ 0x3442, 0x0c },
> > > -	{ 0x300a, 0xf0 },
> > > -	{ 0x300b, 0x00 },
> > > +	{ IMX290_REG_8BIT(0x3005), 0x01 },
> > > +	{ IMX290_REG_8BIT(0x3046), 0x01 },
> > > +	{ IMX290_REG_8BIT(0x3129), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x317c), 0x00 },
> > > +	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> > > +	{ IMX290_REG_8BIT(0x3441), 0x0c },
> > > +	{ IMX290_REG_8BIT(0x3442), 0x0c },
> > > +	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> > > +	{ IMX290_REG_8BIT(0x300b), 0x00 },
> > > 
> > >  };
> > >  
> > >  /* supported link frequencies */
> > > 
> > > @@ -362,33 +368,35 @@ static inline struct imx290 *to_imx290(struct
> > > v4l2_subdev *_sd) return container_of(_sd, struct imx290, sd);
> > > 
> > >  }
> > > 
> > > -static inline int __always_unused imx290_read_reg(struct imx290
> > > *imx290, u16 addr, u8 *value) +static int __always_unused
> > > imx290_read_reg(struct imx290 *imx290, u32 addr, u32 *value) {
> > > -	unsigned int regval;
> > > +	u8 data[3] = { 0, 0, 0 };
> > > 
> > >  	int ret;
> > > 
> > > -	ret = regmap_read(imx290->regmap, addr, &regval);
> > > -	if (ret) {
> > > -		dev_err(imx290->dev, "Failed to read register 0x%04x: 
%d\n",
> > > -			addr, ret);
> > > +	ret = regmap_raw_read(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
> > > +			      data, (addr >> IMX290_REG_SIZE_SHIFT) & 
3);
> > 
> > While I agree with the intention, it fails for some devices, e.g. Vision
> > Components MIPI IMX327 C does not support auto-increment and most probably
> > also valid for the IMX290 model.
> > This is similar to the OV9281 variant, see [1].
> 
> *sigh* Can't they get their firmware right ? :-( Inserting a
> microcontroller between the SoC and sensor is bad enough in itself,
> making it mess up I2C access due to firmware bugs is worse.

[1] indicates this is due to NDA compliance.

> How far do we need to go in sensor drivers to support messed up hardware
> designs that are not related to the sensor at all ? I don't want to
> patch all sensor drivers to make I2C read slower because someone
> somewhere has taken the sensor and decided to screw up. That doesn't
> scale, and hurt all users of these sensors in sane camera modules.

A somewhat acceptable solution might be to add a property indicating that 
auto-increment is not supported, so that each byte has to be fetched 
individually.

Best regards,
Alexander

[1] https://github.com/raspberrypi/linux/commit/
58deee7c917e1c3c5e37987c3a89ad19d791f58a

> > Reading ID using 16bit register (using later patch) returns:
> > > imx290 2-001a: chip ID 0xffd0
> > 
> > Using 2 8bit reads:
> > imx290 2-001a: chip ID 0x07d0
> > 
> > Best regards,
> > Alexander
> > 
> > [1]
> > https://patchwork.kernel.org/project/linux-media/patch/20220715074858.875
> > 808-7-alexander.stein@ew.tq-group.com/> 
> > > +	if (ret < 0) {
> > > +		dev_err(imx290->dev, "%u-bit read from 0x%04x failed: 
%d\n",
> > > +			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
> > > +			 addr & IMX290_REG_ADDR_MASK, ret);
> > > 
> > >  		return ret;
> > >  	
> > >  	}
> > > 
> > > -	*value = regval & 0xff;
> > > -
> > > +	*value = (data[2] << 16) | (data[1] << 8) | data[0];
> > > 
> > >  	return 0;
> > >  
> > >  }
> > > 
> > > -static int imx290_write_reg(struct imx290 *imx290, u16 addr, u8 value)
> > > +static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
> > > 
> > >  {
> > > 
> > > +	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
> > > 
> > >  	int ret;
> > > 
> > > -	ret = regmap_write(imx290->regmap, addr, value);
> > > -	if (ret) {
> > > -		dev_err(imx290->dev, "Failed to write register 0x%04x: 
%d\n",
> > > -			addr, ret);
> > > -		return ret;
> > > -	}
> > > +	ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
> > > +			       data, (addr >> IMX290_REG_SIZE_SHIFT) 
& 3);
> > > +	if (ret < 0)
> > > +		dev_err(imx290->dev, "%u-bit write to 0x%04x failed: 
%d\n",
> > > +			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
> > > +			 addr & IMX290_REG_ADDR_MASK, ret);
> > > 
> > >  	return ret;
> > >  
> > >  }





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

* Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-21 11:18       ` Alexander Stein
@ 2022-07-21 11:25         ` Laurent Pinchart
  2022-07-21 11:43           ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21 11:25 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Alexander,

On Thu, Jul 21, 2022 at 01:18:29PM +0200, Alexander Stein wrote:
> Am Donnerstag, 21. Juli 2022, 12:54:51 CEST schrieb Laurent Pinchart:
> > On Thu, Jul 21, 2022 at 11:43:47AM +0200, Alexander Stein wrote:
> > > Am Donnerstag, 21. Juli 2022, 10:35:28 CEST schrieb Laurent Pinchart:
> > > > The IMX290 has registers of different sizes. To simplify the code,
> > > > handle this in the read/write functions instead of in the callers by
> > > > encoding the register size in the symbolic name macros. All registers
> > > > are defined as 8-bit for now, a subsequent change will move to larger
> > > > registers where applicable.
> > > > 
> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > ---
> > > > 
> > > >  drivers/media/i2c/imx290.c | 352 +++++++++++++++++++------------------
> > > >  1 file changed, 180 insertions(+), 172 deletions(-)
> > > > 
> > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > index 711282126c34..ac58bfe6db7f 100644
> > > > --- a/drivers/media/i2c/imx290.c
> > > > +++ b/drivers/media/i2c/imx290.c
> > > > @@ -22,22 +22,28 @@
> > > > 
> > > >  #include <media/v4l2-fwnode.h>
> > > >  #include <media/v4l2-subdev.h>
> > > > 
> > > > -#define IMX290_STANDBY 0x3000
> > > > -#define IMX290_REGHOLD 0x3001
> > > > -#define IMX290_XMSTA 0x3002
> > > > -#define IMX290_FR_FDG_SEL 0x3009
> > > > -#define IMX290_BLKLEVEL_LOW 0x300a
> > > > -#define IMX290_BLKLEVEL_HIGH 0x300b
> > > > -#define IMX290_GAIN 0x3014
> > > > -#define IMX290_HMAX_LOW 0x301c
> > > > -#define IMX290_HMAX_HIGH 0x301d
> > > > -#define IMX290_PGCTRL 0x308c
> > > > -#define IMX290_PHY_LANE_NUM 0x3407
> > > > -#define IMX290_CSI_LANE_MODE 0x3443
> > > > +#define IMX290_REG_8BIT(n)				((1 << 16) | 
> (n))
> > > > +#define IMX290_REG_16BIT(n)				
> ((2 << 16) | (n))
> > > > +#define IMX290_REG_24BIT(n)				
> ((3 << 16) | (n))
> > > 
> > > IMX290_REG_SIZE_SHIFT instead of 16 here? Not exactly necessary, but use
> > > 1U, 2U and 3U instead.
> > 
> > I'll fix that.
> > 
> > > > +#define IMX290_REG_SIZE_SHIFT				
> 16
> > > > +#define IMX290_REG_ADDR_MASK				
> 0xffff
> > > > 
> > > > -#define IMX290_PGCTRL_REGEN BIT(0)
> > > > -#define IMX290_PGCTRL_THRU BIT(1)
> > > > -#define IMX290_PGCTRL_MODE(n) ((n) << 4)
> > > > +#define IMX290_STANDBY					
> IMX290_REG_8BIT(0x3000)
> > > > +#define IMX290_REGHOLD					
> IMX290_REG_8BIT(0x3001)
> > > > +#define IMX290_XMSTA					
> IMX290_REG_8BIT(0x3002)
> > > > +#define IMX290_FR_FDG_SEL				
> IMX290_REG_8BIT(0x3009)
> > > > +#define IMX290_BLKLEVEL_LOW				
> IMX290_REG_8BIT(0x300a)
> > > > +#define IMX290_BLKLEVEL_HIGH				
> IMX290_REG_8BIT(0x300b)
> > > > +#define IMX290_GAIN					
> IMX290_REG_8BIT(0x3014)
> > > > +#define IMX290_HMAX_LOW					
> IMX290_REG_8BIT(0x301c)
> > > > +#define IMX290_HMAX_HIGH				
> IMX290_REG_8BIT(0x301d)
> > > > +#define IMX290_PGCTRL					
> IMX290_REG_8BIT(0x308c)
> > > > +#define IMX290_PHY_LANE_NUM				
> IMX290_REG_8BIT(0x3407)
> > > > +#define IMX290_CSI_LANE_MODE				
> IMX290_REG_8BIT(0x3443)
> > > > +
> > > > +#define IMX290_PGCTRL_REGEN				
> BIT(0)
> > > > +#define IMX290_PGCTRL_THRU				BIT(1)
> > > > +#define IMX290_PGCTRL_MODE(n)				
> ((n) << 4)
> > > > 
> > > >  static const char * const imx290_supply_name[] = {
> > > >  
> > > >  	"vdda",
> > > > 
> > > > @@ -48,7 +54,7 @@ static const char * const imx290_supply_name[] = {
> > > > 
> > > >  #define IMX290_NUM_SUPPLIES ARRAY_SIZE(imx290_supply_name)
> > > >  
> > > >  struct imx290_regval {
> > > > 
> > > > -	u16 reg;
> > > > +	u32 reg;
> > > > 
> > > >  	u8 val;
> > > >  
> > > >  };
> > > > 
> > > > @@ -111,163 +117,163 @@ static const char * const
> > > > imx290_test_pattern_menu[] = { };
> > > > 
> > > >  static const struct imx290_regval imx290_global_init_settings[] = {
> > > > 
> > > > -	{ 0x3007, 0x00 },
> > > > -	{ 0x3018, 0x65 },
> > > > -	{ 0x3019, 0x04 },
> > > > -	{ 0x301a, 0x00 },
> > > > -	{ 0x3444, 0x20 },
> > > > -	{ 0x3445, 0x25 },
> > > > -	{ 0x303a, 0x0c },
> > > > -	{ 0x3040, 0x00 },
> > > > -	{ 0x3041, 0x00 },
> > > > -	{ 0x303c, 0x00 },
> > > > -	{ 0x303d, 0x00 },
> > > > -	{ 0x3042, 0x9c },
> > > > -	{ 0x3043, 0x07 },
> > > > -	{ 0x303e, 0x49 },
> > > > -	{ 0x303f, 0x04 },
> > > > -	{ 0x304b, 0x0a },
> > > > -	{ 0x300f, 0x00 },
> > > > -	{ 0x3010, 0x21 },
> > > > -	{ 0x3012, 0x64 },
> > > > -	{ 0x3016, 0x09 },
> > > > -	{ 0x3070, 0x02 },
> > > > -	{ 0x3071, 0x11 },
> > > > -	{ 0x309b, 0x10 },
> > > > -	{ 0x309c, 0x22 },
> > > > -	{ 0x30a2, 0x02 },
> > > > -	{ 0x30a6, 0x20 },
> > > > -	{ 0x30a8, 0x20 },
> > > > -	{ 0x30aa, 0x20 },
> > > > -	{ 0x30ac, 0x20 },
> > > > -	{ 0x30b0, 0x43 },
> > > > -	{ 0x3119, 0x9e },
> > > > -	{ 0x311c, 0x1e },
> > > > -	{ 0x311e, 0x08 },
> > > > -	{ 0x3128, 0x05 },
> > > > -	{ 0x313d, 0x83 },
> > > > -	{ 0x3150, 0x03 },
> > > > -	{ 0x317e, 0x00 },
> > > > -	{ 0x32b8, 0x50 },
> > > > -	{ 0x32b9, 0x10 },
> > > > -	{ 0x32ba, 0x00 },
> > > > -	{ 0x32bb, 0x04 },
> > > > -	{ 0x32c8, 0x50 },
> > > > -	{ 0x32c9, 0x10 },
> > > > -	{ 0x32ca, 0x00 },
> > > > -	{ 0x32cb, 0x04 },
> > > > -	{ 0x332c, 0xd3 },
> > > > -	{ 0x332d, 0x10 },
> > > > -	{ 0x332e, 0x0d },
> > > > -	{ 0x3358, 0x06 },
> > > > -	{ 0x3359, 0xe1 },
> > > > -	{ 0x335a, 0x11 },
> > > > -	{ 0x3360, 0x1e },
> > > > -	{ 0x3361, 0x61 },
> > > > -	{ 0x3362, 0x10 },
> > > > -	{ 0x33b0, 0x50 },
> > > > -	{ 0x33b2, 0x1a },
> > > > -	{ 0x33b3, 0x04 },
> > > > +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3018), 0x65 },
> > > > +	{ IMX290_REG_8BIT(0x3019), 0x04 },
> > > > +	{ IMX290_REG_8BIT(0x301a), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3444), 0x20 },
> > > > +	{ IMX290_REG_8BIT(0x3445), 0x25 },
> > > > +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > > +	{ IMX290_REG_8BIT(0x3040), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3041), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x303c), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x303d), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3042), 0x9c },
> > > > +	{ IMX290_REG_8BIT(0x3043), 0x07 },
> > > > +	{ IMX290_REG_8BIT(0x303e), 0x49 },
> > > > +	{ IMX290_REG_8BIT(0x303f), 0x04 },
> > > > +	{ IMX290_REG_8BIT(0x304b), 0x0a },
> > > > +	{ IMX290_REG_8BIT(0x300f), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3010), 0x21 },
> > > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > > +	{ IMX290_REG_8BIT(0x3016), 0x09 },
> > > > +	{ IMX290_REG_8BIT(0x3070), 0x02 },
> > > > +	{ IMX290_REG_8BIT(0x3071), 0x11 },
> > > > +	{ IMX290_REG_8BIT(0x309b), 0x10 },
> > > > +	{ IMX290_REG_8BIT(0x309c), 0x22 },
> > > > +	{ IMX290_REG_8BIT(0x30a2), 0x02 },
> > > > +	{ IMX290_REG_8BIT(0x30a6), 0x20 },
> > > > +	{ IMX290_REG_8BIT(0x30a8), 0x20 },
> > > > +	{ IMX290_REG_8BIT(0x30aa), 0x20 },
> > > > +	{ IMX290_REG_8BIT(0x30ac), 0x20 },
> > > > +	{ IMX290_REG_8BIT(0x30b0), 0x43 },
> > > > +	{ IMX290_REG_8BIT(0x3119), 0x9e },
> > > > +	{ IMX290_REG_8BIT(0x311c), 0x1e },
> > > > +	{ IMX290_REG_8BIT(0x311e), 0x08 },
> > > > +	{ IMX290_REG_8BIT(0x3128), 0x05 },
> > > > +	{ IMX290_REG_8BIT(0x313d), 0x83 },
> > > > +	{ IMX290_REG_8BIT(0x3150), 0x03 },
> > > > +	{ IMX290_REG_8BIT(0x317e), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x32b8), 0x50 },
> > > > +	{ IMX290_REG_8BIT(0x32b9), 0x10 },
> > > > +	{ IMX290_REG_8BIT(0x32ba), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x32bb), 0x04 },
> > > > +	{ IMX290_REG_8BIT(0x32c8), 0x50 },
> > > > +	{ IMX290_REG_8BIT(0x32c9), 0x10 },
> > > > +	{ IMX290_REG_8BIT(0x32ca), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x32cb), 0x04 },
> > > > +	{ IMX290_REG_8BIT(0x332c), 0xd3 },
> > > > +	{ IMX290_REG_8BIT(0x332d), 0x10 },
> > > > +	{ IMX290_REG_8BIT(0x332e), 0x0d },
> > > > +	{ IMX290_REG_8BIT(0x3358), 0x06 },
> > > > +	{ IMX290_REG_8BIT(0x3359), 0xe1 },
> > > > +	{ IMX290_REG_8BIT(0x335a), 0x11 },
> > > > +	{ IMX290_REG_8BIT(0x3360), 0x1e },
> > > > +	{ IMX290_REG_8BIT(0x3361), 0x61 },
> > > > +	{ IMX290_REG_8BIT(0x3362), 0x10 },
> > > > +	{ IMX290_REG_8BIT(0x33b0), 0x50 },
> > > > +	{ IMX290_REG_8BIT(0x33b2), 0x1a },
> > > > +	{ IMX290_REG_8BIT(0x33b3), 0x04 },
> > > > 
> > > >  };
> > > >  
> > > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > > >  
> > > >  	/* mode settings */
> > > > 
> > > > -	{ 0x3007, 0x00 },
> > > > -	{ 0x303a, 0x0c },
> > > > -	{ 0x3414, 0x0a },
> > > > -	{ 0x3472, 0x80 },
> > > > -	{ 0x3473, 0x07 },
> > > > -	{ 0x3418, 0x38 },
> > > > -	{ 0x3419, 0x04 },
> > > > -	{ 0x3012, 0x64 },
> > > > -	{ 0x3013, 0x00 },
> > > > -	{ 0x305c, 0x18 },
> > > > -	{ 0x305d, 0x03 },
> > > > -	{ 0x305e, 0x20 },
> > > > -	{ 0x305f, 0x01 },
> > > > -	{ 0x315e, 0x1a },
> > > > -	{ 0x3164, 0x1a },
> > > > -	{ 0x3480, 0x49 },
> > > > +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > > +	{ IMX290_REG_8BIT(0x3414), 0x0a },
> > > > +	{ IMX290_REG_8BIT(0x3472), 0x80 },
> > > > +	{ IMX290_REG_8BIT(0x3473), 0x07 },
> > > > +	{ IMX290_REG_8BIT(0x3418), 0x38 },
> > > > +	{ IMX290_REG_8BIT(0x3419), 0x04 },
> > > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x305c), 0x18 },
> > > > +	{ IMX290_REG_8BIT(0x305d), 0x03 },
> > > > +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > > +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > > +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > > +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > > 
> > > >  	/* data rate settings */
> > > > 
> > > > -	{ 0x3405, 0x10 },
> > > > -	{ 0x3446, 0x57 },
> > > > -	{ 0x3447, 0x00 },
> > > > -	{ 0x3448, 0x37 },
> > > > -	{ 0x3449, 0x00 },
> > > > -	{ 0x344a, 0x1f },
> > > > -	{ 0x344b, 0x00 },
> > > > -	{ 0x344c, 0x1f },
> > > > -	{ 0x344d, 0x00 },
> > > > -	{ 0x344e, 0x1f },
> > > > -	{ 0x344f, 0x00 },
> > > > -	{ 0x3450, 0x77 },
> > > > -	{ 0x3451, 0x00 },
> > > > -	{ 0x3452, 0x1f },
> > > > -	{ 0x3453, 0x00 },
> > > > -	{ 0x3454, 0x17 },
> > > > -	{ 0x3455, 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > > +	{ IMX290_REG_8BIT(0x3446), 0x57 },
> > > > +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3448), 0x37 },
> > > > +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x344a), 0x1f },
> > > > +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x344c), 0x1f },
> > > > +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x344e), 0x1f },
> > > > +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3450), 0x77 },
> > > > +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3452), 0x1f },
> > > > +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > > +	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > > 
> > > >  };
> > > >  
> > > >  static const struct imx290_regval imx290_720p_settings[] = {
> > > >  
> > > >  	/* mode settings */
> > > > 
> > > > -	{ 0x3007, 0x10 },
> > > > -	{ 0x303a, 0x06 },
> > > > -	{ 0x3414, 0x04 },
> > > > -	{ 0x3472, 0x00 },
> > > > -	{ 0x3473, 0x05 },
> > > > -	{ 0x3418, 0xd0 },
> > > > -	{ 0x3419, 0x02 },
> > > > -	{ 0x3012, 0x64 },
> > > > -	{ 0x3013, 0x00 },
> > > > -	{ 0x305c, 0x20 },
> > > > -	{ 0x305d, 0x00 },
> > > > -	{ 0x305e, 0x20 },
> > > > -	{ 0x305f, 0x01 },
> > > > -	{ 0x315e, 0x1a },
> > > > -	{ 0x3164, 0x1a },
> > > > -	{ 0x3480, 0x49 },
> > > > +	{ IMX290_REG_8BIT(0x3007), 0x10 },
> > > > +	{ IMX290_REG_8BIT(0x303a), 0x06 },
> > > > +	{ IMX290_REG_8BIT(0x3414), 0x04 },
> > > > +	{ IMX290_REG_8BIT(0x3472), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3473), 0x05 },
> > > > +	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> > > > +	{ IMX290_REG_8BIT(0x3419), 0x02 },
> > > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x305c), 0x20 },
> > > > +	{ IMX290_REG_8BIT(0x305d), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > > +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > > +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > > +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > > 
> > > >  	/* data rate settings */
> > > > 
> > > > -	{ 0x3405, 0x10 },
> > > > -	{ 0x3446, 0x4f },
> > > > -	{ 0x3447, 0x00 },
> > > > -	{ 0x3448, 0x2f },
> > > > -	{ 0x3449, 0x00 },
> > > > -	{ 0x344a, 0x17 },
> > > > -	{ 0x344b, 0x00 },
> > > > -	{ 0x344c, 0x17 },
> > > > -	{ 0x344d, 0x00 },
> > > > -	{ 0x344e, 0x17 },
> > > > -	{ 0x344f, 0x00 },
> > > > -	{ 0x3450, 0x57 },
> > > > -	{ 0x3451, 0x00 },
> > > > -	{ 0x3452, 0x17 },
> > > > -	{ 0x3453, 0x00 },
> > > > -	{ 0x3454, 0x17 },
> > > > -	{ 0x3455, 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > > +	{ IMX290_REG_8BIT(0x3446), 0x4f },
> > > > +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3448), 0x2f },
> > > > +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x344a), 0x17 },
> > > > +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x344c), 0x17 },
> > > > +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x344e), 0x17 },
> > > > +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3450), 0x57 },
> > > > +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3452), 0x17 },
> > > > +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > > +	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > > 
> > > >  };
> > > >  
> > > >  static const struct imx290_regval imx290_10bit_settings[] = {
> > > > 
> > > > -	{ 0x3005, 0x00},
> > > > -	{ 0x3046, 0x00},
> > > > -	{ 0x3129, 0x1d},
> > > > -	{ 0x317c, 0x12},
> > > > -	{ 0x31ec, 0x37},
> > > > -	{ 0x3441, 0x0a},
> > > > -	{ 0x3442, 0x0a},
> > > > -	{ 0x300a, 0x3c},
> > > > -	{ 0x300b, 0x00},
> > > > +	{ IMX290_REG_8BIT(0x3005), 0x00},
> > > > +	{ IMX290_REG_8BIT(0x3046), 0x00},
> > > > +	{ IMX290_REG_8BIT(0x3129), 0x1d},
> > > > +	{ IMX290_REG_8BIT(0x317c), 0x12},
> > > > +	{ IMX290_REG_8BIT(0x31ec), 0x37},
> > > > +	{ IMX290_REG_8BIT(0x3441), 0x0a},
> > > > +	{ IMX290_REG_8BIT(0x3442), 0x0a},
> > > > +	{ IMX290_REG_8BIT(0x300a), 0x3c},
> > > > +	{ IMX290_REG_8BIT(0x300b), 0x00},
> > > > 
> > > >  };
> > > >  
> > > >  static const struct imx290_regval imx290_12bit_settings[] = {
> > > > 
> > > > -	{ 0x3005, 0x01 },
> > > > -	{ 0x3046, 0x01 },
> > > > -	{ 0x3129, 0x00 },
> > > > -	{ 0x317c, 0x00 },
> > > > -	{ 0x31ec, 0x0e },
> > > > -	{ 0x3441, 0x0c },
> > > > -	{ 0x3442, 0x0c },
> > > > -	{ 0x300a, 0xf0 },
> > > > -	{ 0x300b, 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x3005), 0x01 },
> > > > +	{ IMX290_REG_8BIT(0x3046), 0x01 },
> > > > +	{ IMX290_REG_8BIT(0x3129), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x317c), 0x00 },
> > > > +	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> > > > +	{ IMX290_REG_8BIT(0x3441), 0x0c },
> > > > +	{ IMX290_REG_8BIT(0x3442), 0x0c },
> > > > +	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> > > > +	{ IMX290_REG_8BIT(0x300b), 0x00 },
> > > > 
> > > >  };
> > > >  
> > > >  /* supported link frequencies */
> > > > 
> > > > @@ -362,33 +368,35 @@ static inline struct imx290 *to_imx290(struct
> > > > v4l2_subdev *_sd) return container_of(_sd, struct imx290, sd);
> > > > 
> > > >  }
> > > > 
> > > > -static inline int __always_unused imx290_read_reg(struct imx290 *imx290, u16 addr, u8 *value)
> > > > +static int __always_unused imx290_read_reg(struct imx290 *imx290, u32 addr, u32 *value) {
> > > > -	unsigned int regval;
> > > > +	u8 data[3] = { 0, 0, 0 };
> > > > 
> > > >  	int ret;
> > > > 
> > > > -	ret = regmap_read(imx290->regmap, addr, &regval);
> > > > -	if (ret) {
> > > > -		dev_err(imx290->dev, "Failed to read register 0x%04x: %d\n",
> > > > -			addr, ret);
> > > > +	ret = regmap_raw_read(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
> > > > +			      data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
> > > 
> > > While I agree with the intention, it fails for some devices, e.g. Vision
> > > Components MIPI IMX327 C does not support auto-increment and most probably
> > > also valid for the IMX290 model.
> > > This is similar to the OV9281 variant, see [1].
> > 
> > *sigh* Can't they get their firmware right ? :-( Inserting a
> > microcontroller between the SoC and sensor is bad enough in itself,
> > making it mess up I2C access due to firmware bugs is worse.
> 
> [1] indicates this is due to NDA compliance.

I don't buy that, sorry. That's not the reason, and even if it were, it
wouldn't excuse breaking auto-increment on read.

> > How far do we need to go in sensor drivers to support messed up hardware
> > designs that are not related to the sensor at all ? I don't want to
> > patch all sensor drivers to make I2C read slower because someone
> > somewhere has taken the sensor and decided to screw up. That doesn't
> > scale, and hurt all users of these sensors in sane camera modules.
> 
> A somewhat acceptable solution might be to add a property indicating that 
> auto-increment is not supported, so that each byte has to be fetched 
> individually.

I would be fine with that. It should then be handled in the I2C core or
regmap layer.

> [1] https://github.com/raspberrypi/linux/commit/
> 58deee7c917e1c3c5e37987c3a89ad19d791f58a
> 
> > > Reading ID using 16bit register (using later patch) returns:
> > > > imx290 2-001a: chip ID 0xffd0
> > > 
> > > Using 2 8bit reads:
> > > imx290 2-001a: chip ID 0x07d0
> > > 
> > > Best regards,
> > > Alexander
> > > 
> > > [1]
> > > https://patchwork.kernel.org/project/linux-media/patch/20220715074858.875
> > > 808-7-alexander.stein@ew.tq-group.com/> 
> > > > +	if (ret < 0) {
> > > > +		dev_err(imx290->dev, "%u-bit read from 0x%04x failed: %d\n",
> > > > +			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
> > > > +			 addr & IMX290_REG_ADDR_MASK, ret);
> > > > 
> > > >  		return ret;
> > > >  	
> > > >  	}
> > > > 
> > > > -	*value = regval & 0xff;
> > > > -
> > > > +	*value = (data[2] << 16) | (data[1] << 8) | data[0];
> > > > 
> > > >  	return 0;
> > > >  
> > > >  }
> > > > 
> > > > -static int imx290_write_reg(struct imx290 *imx290, u16 addr, u8 value)
> > > > +static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
> > > > 
> > > >  {
> > > > 
> > > > +	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
> > > > 
> > > >  	int ret;
> > > > 
> > > > -	ret = regmap_write(imx290->regmap, addr, value);
> > > > -	if (ret) {
> > > > -		dev_err(imx290->dev, "Failed to write register 0x%04x: %d\n",
> > > > -			addr, ret);
> > > > -		return ret;
> > > > -	}
> > > > +	ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
> > > > +			       data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
> > > > +	if (ret < 0)
> > > > +		dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
> > > > +			 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
> > > > +			 addr & IMX290_REG_ADDR_MASK, ret);
> > > > 
> > > >  	return ret;
> > > >  
> > > >  }

-- 
Regards,

Laurent Pinchart

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

* Re: Re: [PATCH 10/19] media: i2c: imx290: Define more register macros
  2022-07-21 11:08     ` Laurent Pinchart
@ 2022-07-21 11:28       ` Alexander Stein
  2022-10-16  4:27         ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 11:28 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent,

Am Donnerstag, 21. Juli 2022, 13:08:05 CEST schrieb Laurent Pinchart:
> Hi Alexander,
> 
> On Thu, Jul 21, 2022 at 12:00:55PM +0200, Alexander Stein wrote:
> > Am Donnerstag, 21. Juli 2022, 10:35:31 CEST schrieb Laurent Pinchart:
> > > Define macros for all registers programmed by the driver for which
> > > documentation is available to increase readability. This starts making
> > > use of 16-bit registers in the register arrays, so the value field has
> > > to be increased to 32 bits.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/media/i2c/imx290.c | 219 +++++++++++++++++++++----------------
> > >  1 file changed, 124 insertions(+), 95 deletions(-)
> > > 
> > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > index 5b7f9027b50f..bec326a83952 100644
> > > --- a/drivers/media/i2c/imx290.c
> > > +++ b/drivers/media/i2c/imx290.c
> > > @@ -31,14 +31,73 @@
> > > 
> > >  #define IMX290_STANDBY					
IMX290_REG_8BIT(0x3000)
> > >  #define IMX290_REGHOLD					
IMX290_REG_8BIT(0x3001)
> > >  #define IMX290_XMSTA					
IMX290_REG_8BIT(0x3002)
> > > 
> > > +#define IMX290_ADBIT					
IMX290_REG_8BIT(0x3005)
> > > +#define IMX290_ADBIT_10BIT				(0 << 0)
> > > +#define IMX290_ADBIT_12BIT				(1 << 0)
> > > +#define IMX290_CTRL_07					
IMX290_REG_8BIT(0x3007)
> > > +#define IMX290_VREVERSE					
BIT(0)
> > > +#define IMX290_HREVERSE					
BIT(1)
> > > +#define IMX290_WINMODE_1080P				
(0 << 4)
> > > +#define IMX290_WINMODE_720P				
(1 << 4)
> > > +#define IMX290_WINMODE_CROP				
(4 << 4)
> > > 
> > >  #define IMX290_FR_FDG_SEL				
IMX290_REG_8BIT(0x3009)
> > >  #define IMX290_BLKLEVEL					
IMX290_REG_16BIT(0x300a)
> > >  #define IMX290_GAIN					
IMX290_REG_8BIT(0x3014)
> > > 
> > > +#define IMX290_VMAX					
IMX290_REG_24BIT(0x3018)
> > > 
> > >  #define IMX290_HMAX					
IMX290_REG_16BIT(0x301c)
> > > 
> > > +#define IMX290_SHS1					
IMX290_REG_24BIT(0x3020)
> > > +#define IMX290_WINWV_OB					
IMX290_REG_8BIT(0x303a)
> > > +#define IMX290_WINPV					
IMX290_REG_16BIT(0x303c)
> > > +#define IMX290_WINWV					
IMX290_REG_16BIT(0x303e)
> > > +#define IMX290_WINPH					
IMX290_REG_16BIT(0x3040)
> > > +#define IMX290_WINWH					
IMX290_REG_16BIT(0x3042)
> > > +#define IMX290_OUT_CTRL					
IMX290_REG_8BIT(0x3046)
> > > +#define IMX290_ODBIT_10BIT				(0 << 0)
> > > +#define IMX290_ODBIT_12BIT				(1 << 0)
> > 
> > ODBIT is fixed 1h for MIPI-CSI-2 output.
> > 
> > > +#define IMX290_OPORTSEL_PARALLEL			(0x0 << 4)
> > > +#define IMX290_OPORTSEL_LVDS_2CH			(0xd << 4)
> > > +#define IMX290_OPORTSEL_LVDS_4CH			(0xe << 4)
> > > +#define IMX290_OPORTSEL_LVDS_8CH			(0xf << 4)
> > 
> > This driver only supports MIPI-CSI-2 output, but these bits are don't
> > care,
> > you still want to list them here for completeness?
> 
> Yes, it could be useful later.

Ok, fine with me.

> > > +#define IMX290_XSOUTSEL					
IMX290_REG_8BIT(0x304b)
> > > +#define IMX290_XSOUTSEL_XVSOUTSEL_HIGH			
(0 << 0)
> > > +#define IMX290_XSOUTSEL_XVSOUTSEL_VSYNC			
(2 << 0)
> > > +#define IMX290_XSOUTSEL_XHSOUTSEL_HIGH			
(0 << 2)
> > > +#define IMX290_XSOUTSEL_XHSOUTSEL_HSYNC			
(2 << 2)
> > > +#define IMX290_INCKSEL1					
IMX290_REG_8BIT(0x305c)
> > > +#define IMX290_INCKSEL2					
IMX290_REG_8BIT(0x305d)
> > > +#define IMX290_INCKSEL3					
IMX290_REG_8BIT(0x305e)
> > > +#define IMX290_INCKSEL4					
IMX290_REG_8BIT(0x305f)
> > > 
> > >  #define IMX290_PGCTRL					
IMX290_REG_8BIT(0x308c)
> > > 
> > > +#define IMX290_ADBIT1					
IMX290_REG_8BIT(0x3129)
> > > +#define IMX290_ADBIT1_10BIT				
0x1d
> > > +#define IMX290_ADBIT1_12BIT				
0x00
> > > +#define IMX290_INCKSEL5					
IMX290_REG_8BIT(0x315e)
> > > +#define IMX290_INCKSEL6					
IMX290_REG_8BIT(0x3164)
> > 
> > Any reason to skip the bit defines for both supported input clocks?
> 
> I don't have access to information that describes the bits in those two
> registers, just magic values for the 37.125 MHz and 74.25 MHz input
> clocks. Would you happen to know more ?

See [1] and line 354 as well. This register is depending on the external 
clock.

[1] https://github.com/tq-systems/linux-tqmaxx/blob/TQMa8-fslc-5.10-2.1.x-imx/
drivers/media/i2c/imx290.c#L344

> > > +#define IMX290_ADBIT2					
IMX290_REG_8BIT(0x317c)
> > > +#define IMX290_ADBIT2_10BIT				
0x12
> > > +#define IMX290_ADBIT2_12BIT				
0x00
> > > 
> > >  #define IMX290_CHIP_ID					
IMX290_REG_16BIT(0x319a)
> > > 
> > > +#define IMX290_ADBIT3					
IMX290_REG_16BIT(0x31ec)
> > > +#define IMX290_ADBIT3_10BIT				
0x37
> > > +#define IMX290_ADBIT3_12BIT				
0x0e
> > > +#define IMX290_REPETITION				
IMX290_REG_8BIT(0x3405)
> > > 
> > >  #define IMX290_PHY_LANE_NUM				
IMX290_REG_8BIT(0x3407)
> > > 
> > > +#define IMX290_OPB_SIZE_V				
IMX290_REG_8BIT(0x3414)
> > > +#define IMX290_Y_OUT_SIZE				
IMX290_REG_16BIT(0x3418)
> > > +#define IMX290_CSI_DT_FMT				
IMX290_REG_16BIT(0x3441)
> > > +#define IMX290_CSI_DT_FMT_RAW10				
0x0a0a
> > > +#define IMX290_CSI_DT_FMT_RAW12				
0x0c0c
> > > 
> > >  #define IMX290_CSI_LANE_MODE				
IMX290_REG_8BIT(0x3443)
> > > 
> > > +#define IMX290_EXTCK_FREQ				
IMX290_REG_16BIT(0x3444)
> > 
> > Same here.
> 
> Same explanation as above :-)

This register also depends on external clock, see [2] and line 228 as well.

[2] https://github.com/tq-systems/linux-tqmaxx/blob/TQMa8-fslc-5.10-2.1.x-imx/
drivers/media/i2c/imx290.c#L218

Best regards,
Alexander

> > > +#define IMX290_TCLKPOST					
IMX290_REG_16BIT(0x3446)
> > > +#define IMX290_THSZERO					
IMX290_REG_16BIT(0x3448)
> > > +#define IMX290_THSPREPARE				
IMX290_REG_16BIT(0x344a)
> > > +#define IMX290_TCLKTRAIL				
IMX290_REG_16BIT(0x344c)
> > > +#define IMX290_THSTRAIL					
IMX290_REG_16BIT(0x344e)
> > > +#define IMX290_TCLKZERO					
IMX290_REG_16BIT(0x3450)
> > > +#define IMX290_TCLKPREPARE				
IMX290_REG_16BIT(0x3452)
> > > +#define IMX290_TLPX					
IMX290_REG_16BIT(0x3454)
> > > +#define IMX290_X_OUT_SIZE				
IMX290_REG_16BIT(0x3472)
> > > 
> > >  #define IMX290_PGCTRL_REGEN				
BIT(0)
> > >  #define IMX290_PGCTRL_THRU				BIT(1)
> > > 
> > > @@ -54,7 +113,7 @@ static const char * const imx290_supply_name[] = {
> > > 
> > >  struct imx290_regval {
> > >  
> > >  	u32 reg;
> > > 
> > > -	u8 val;
> > > +	u32 val;
> > > 
> > >  };
> > >  
> > >  struct imx290_mode {
> > > 
> > > @@ -116,22 +175,16 @@ static const char * const
> > > imx290_test_pattern_menu[] = { };
> > > 
> > >  static const struct imx290_regval imx290_global_init_settings[] = {
> > > 
> > > -	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3018), 0x65 },
> > > -	{ IMX290_REG_8BIT(0x3019), 0x04 },
> > > -	{ IMX290_REG_8BIT(0x301a), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3444), 0x20 },
> > > -	{ IMX290_REG_8BIT(0x3445), 0x25 },
> > > -	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > -	{ IMX290_REG_8BIT(0x3040), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3041), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x303c), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x303d), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3042), 0x9c },
> > > -	{ IMX290_REG_8BIT(0x3043), 0x07 },
> > > -	{ IMX290_REG_8BIT(0x303e), 0x49 },
> > > -	{ IMX290_REG_8BIT(0x303f), 0x04 },
> > > -	{ IMX290_REG_8BIT(0x304b), 0x0a },
> > > +	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> > > +	{ IMX290_VMAX, 1125 },
> > > +	{ IMX290_EXTCK_FREQ, 0x2520 },
> > > +	{ IMX290_WINWV_OB, 12 },
> > > +	{ IMX290_WINPH, 0 },
> > > +	{ IMX290_WINPV, 0 },
> > > +	{ IMX290_WINWH, 1948 },
> > > +	{ IMX290_WINWV, 1097 },
> > > +	{ IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
> > > +			   IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
> > > 
> > >  	{ IMX290_REG_8BIT(0x300f), 0x00 },
> > >  	{ IMX290_REG_8BIT(0x3010), 0x21 },
> > >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > 
> > > @@ -177,102 +230,78 @@ static const struct imx290_regval
> > > imx290_global_init_settings[] = {
> > > 
> > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > >  
> > >  	/* mode settings */
> > > 
> > > -	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > -	{ IMX290_REG_8BIT(0x3414), 0x0a },
> > > -	{ IMX290_REG_8BIT(0x3472), 0x80 },
> > > -	{ IMX290_REG_8BIT(0x3473), 0x07 },
> > > -	{ IMX290_REG_8BIT(0x3418), 0x38 },
> > > -	{ IMX290_REG_8BIT(0x3419), 0x04 },
> > > +	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> > > +	{ IMX290_WINWV_OB, 12 },
> > > +	{ IMX290_OPB_SIZE_V, 10 },
> > > +	{ IMX290_X_OUT_SIZE, 1920 },
> > > +	{ IMX290_Y_OUT_SIZE, 1080 },
> > > 
> > >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > >  	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > 
> > > -	{ IMX290_REG_8BIT(0x305c), 0x18 },
> > > -	{ IMX290_REG_8BIT(0x305d), 0x03 },
> > > -	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > -	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > -	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > -	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > +	{ IMX290_INCKSEL1, 0x18 },
> > > +	{ IMX290_INCKSEL2, 0x03 },
> > > +	{ IMX290_INCKSEL3, 0x20 },
> > > +	{ IMX290_INCKSEL4, 0x01 },
> > > +	{ IMX290_INCKSEL5, 0x1a },
> > > +	{ IMX290_INCKSEL6, 0x1a },
> > > 
> > >  	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > >  	/* data rate settings */
> > > 
> > > -	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > -	{ IMX290_REG_8BIT(0x3446), 0x57 },
> > > -	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3448), 0x37 },
> > > -	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x344a), 0x1f },
> > > -	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x344c), 0x1f },
> > > -	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x344e), 0x1f },
> > > -	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3450), 0x77 },
> > > -	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3452), 0x1f },
> > > -	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > -	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > +	{ IMX290_REPETITION, 0x10 },
> > > +	{ IMX290_TCLKPOST, 87 },
> > > +	{ IMX290_THSZERO, 55 },
> > > +	{ IMX290_THSPREPARE, 31 },
> > > +	{ IMX290_TCLKTRAIL, 31 },
> > > +	{ IMX290_THSTRAIL, 31 },
> > > +	{ IMX290_TCLKZERO, 119 },
> > > +	{ IMX290_TCLKPREPARE, 31 },
> > > +	{ IMX290_TLPX, 23 },
> > > 
> > >  };
> > >  
> > >  static const struct imx290_regval imx290_720p_settings[] = {
> > >  
> > >  	/* mode settings */
> > > 
> > > -	{ IMX290_REG_8BIT(0x3007), 0x10 },
> > > -	{ IMX290_REG_8BIT(0x303a), 0x06 },
> > > -	{ IMX290_REG_8BIT(0x3414), 0x04 },
> > > -	{ IMX290_REG_8BIT(0x3472), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3473), 0x05 },
> > > -	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> > > -	{ IMX290_REG_8BIT(0x3419), 0x02 },
> > > +	{ IMX290_CTRL_07, IMX290_WINMODE_720P },
> > > +	{ IMX290_WINWV_OB, 6 },
> > > +	{ IMX290_OPB_SIZE_V, 4 },
> > > +	{ IMX290_X_OUT_SIZE, 1280 },
> > > +	{ IMX290_Y_OUT_SIZE, 720 },
> > > 
> > >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > >  	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > 
> > > -	{ IMX290_REG_8BIT(0x305c), 0x20 },
> > > -	{ IMX290_REG_8BIT(0x305d), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > -	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > -	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > -	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > +	{ IMX290_INCKSEL1, 0x20 },
> > > +	{ IMX290_INCKSEL2, 0x00 },
> > > +	{ IMX290_INCKSEL3, 0x20 },
> > > +	{ IMX290_INCKSEL4, 0x01 },
> > > +	{ IMX290_INCKSEL5, 0x1a },
> > > +	{ IMX290_INCKSEL6, 0x1a },
> > > 
> > >  	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > >  	/* data rate settings */
> > > 
> > > -	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > -	{ IMX290_REG_8BIT(0x3446), 0x4f },
> > > -	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3448), 0x2f },
> > > -	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x344a), 0x17 },
> > > -	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x344c), 0x17 },
> > > -	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x344e), 0x17 },
> > > -	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3450), 0x57 },
> > > -	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3452), 0x17 },
> > > -	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > -	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > +	{ IMX290_REPETITION, 0x10 },
> > > +	{ IMX290_TCLKPOST, 79 },
> > > +	{ IMX290_THSZERO, 47 },
> > > +	{ IMX290_THSPREPARE, 23 },
> > > +	{ IMX290_TCLKTRAIL, 23 },
> > > +	{ IMX290_THSTRAIL, 23 },
> > > +	{ IMX290_TCLKZERO, 87 },
> > > +	{ IMX290_TCLKPREPARE, 23 },
> > > +	{ IMX290_TLPX, 23 },
> > > 
> > >  };
> > >  
> > >  static const struct imx290_regval imx290_10bit_settings[] = {
> > > 
> > > -	{ IMX290_REG_8BIT(0x3005), 0x00},
> > > -	{ IMX290_REG_8BIT(0x3046), 0x00},
> > > -	{ IMX290_REG_8BIT(0x3129), 0x1d},
> > > -	{ IMX290_REG_8BIT(0x317c), 0x12},
> > > -	{ IMX290_REG_8BIT(0x31ec), 0x37},
> > > -	{ IMX290_REG_8BIT(0x3441), 0x0a},
> > > -	{ IMX290_REG_8BIT(0x3442), 0x0a},
> > > -	{ IMX290_REG_8BIT(0x300a), 0x3c},
> > > -	{ IMX290_REG_8BIT(0x300b), 0x00},
> > > +	{ IMX290_ADBIT, IMX290_ADBIT_10BIT },
> > > +	{ IMX290_OUT_CTRL, IMX290_ODBIT_10BIT },
> > > +	{ IMX290_ADBIT1, IMX290_ADBIT1_10BIT },
> > > +	{ IMX290_ADBIT2, IMX290_ADBIT2_10BIT },
> > > +	{ IMX290_ADBIT3, IMX290_ADBIT3_10BIT },
> > > +	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW10 },
> > > +	{ IMX290_BLKLEVEL, 60 },
> > > 
> > >  };
> > >  
> > >  static const struct imx290_regval imx290_12bit_settings[] = {
> > > 
> > > -	{ IMX290_REG_8BIT(0x3005), 0x01 },
> > > -	{ IMX290_REG_8BIT(0x3046), 0x01 },
> > > -	{ IMX290_REG_8BIT(0x3129), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x317c), 0x00 },
> > > -	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> > > -	{ IMX290_REG_8BIT(0x3441), 0x0c },
> > > -	{ IMX290_REG_8BIT(0x3442), 0x0c },
> > > -	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> > > -	{ IMX290_REG_8BIT(0x300b), 0x00 },
> > > +	{ IMX290_ADBIT, IMX290_ADBIT_12BIT },
> > > +	{ IMX290_OUT_CTRL, IMX290_ODBIT_12BIT },
> > > +	{ IMX290_ADBIT1, IMX290_ADBIT1_12BIT },
> > > +	{ IMX290_ADBIT2, IMX290_ADBIT2_12BIT },
> > > +	{ IMX290_ADBIT3, IMX290_ADBIT3_12BIT },
> > > +	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW12 },
> > > +	{ IMX290_BLKLEVEL, 240 },
> > > 
> > >  };
> > >  
> > >  /* supported link frequencies */





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

* Re: [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal
  2022-07-21  9:18   ` Alexander Stein
@ 2022-07-21 11:31     ` Laurent Pinchart
  2022-07-21 11:54       ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21 11:31 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Alexander,

On Thu, Jul 21, 2022 at 11:18:24AM +0200, Alexander Stein wrote:
> Hi Laurent,
> 
> thanks for working on this, I've also some patches on top for imx327 support.

I'm using an IMX327 with this driver without any need for additional
patches :-) I'd be happy to test our patches though.

> Am Donnerstag, 21. Juli 2022, 10:35:24 CEST schrieb Laurent Pinchart:
> > The HMAX value specifies the total line length in pixels. It's thus more
> > readable in decimal than hexadecimal. Fix it.
> 
> I understand the motivation, pixels are more natural in decimal numbers, but 
> e.g. what is 4400 pixels on this sensor? It is only mentioned sparsely and 
> 3300d is not mentioned at all, 0ce4h is instead.

I'm not even sure if HMAX is expressed in pixels or in cycles of some
internal clock different than the pixel clocks.

> I also like to have the hexadecimal numbers here as you can find them directly 
> in the datasheet. To me this seems more sensible for cross-checking. Just my 
> opinion.

It's a matter of readability of the driver code vs. matching with the
datasheet. I have a preference for decimal numbers here, but I don't
mind too much. What I would actually like is dropping the hmax value
from the imx290_mode structure and computing it dynamically based on a
hblank value set by userspace. Do you think you could help me doing so ?
:-)

> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/i2c/imx290.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index 64bd43813dbf..f60a4135dc9c 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -308,7 +308,7 @@ static const struct imx290_mode imx290_modes_2lanes[] =
> > { {
> >  		.width = 1920,
> >  		.height = 1080,
> > -		.hmax = 0x1130,
> > +		.hmax = 4400,
> >  		.link_freq_index = FREQ_INDEX_1080P,
> >  		.data = imx290_1080p_settings,
> >  		.data_size = ARRAY_SIZE(imx290_1080p_settings),
> > @@ -316,7 +316,7 @@ static const struct imx290_mode imx290_modes_2lanes[] =
> > { {
> >  		.width = 1280,
> >  		.height = 720,
> > -		.hmax = 0x19c8,
> > +		.hmax = 6600,
> >  		.link_freq_index = FREQ_INDEX_720P,
> >  		.data = imx290_720p_settings,
> >  		.data_size = ARRAY_SIZE(imx290_720p_settings),
> > @@ -327,7 +327,7 @@ static const struct imx290_mode imx290_modes_4lanes[] =
> > { {
> >  		.width = 1920,
> >  		.height = 1080,
> > -		.hmax = 0x0898,
> > +		.hmax = 2200,
> >  		.link_freq_index = FREQ_INDEX_1080P,
> >  		.data = imx290_1080p_settings,
> >  		.data_size = ARRAY_SIZE(imx290_1080p_settings),
> > @@ -335,7 +335,7 @@ static const struct imx290_mode imx290_modes_4lanes[] =
> > { {
> >  		.width = 1280,
> >  		.height = 720,
> > -		.hmax = 0x0ce4,
> > +		.hmax = 3300,
> >  		.link_freq_index = FREQ_INDEX_720P,
> >  		.data = imx290_720p_settings,
> >  		.data_size = ARRAY_SIZE(imx290_720p_settings),

-- 
Regards,

Laurent Pinchart

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

* Re: Re: [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls
  2022-07-21 11:17     ` Laurent Pinchart
@ 2022-07-21 11:32       ` Alexander Stein
  2022-07-21 16:37         ` Dave Stevenson
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 11:32 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent,

Am Donnerstag, 21. Juli 2022, 13:17:21 CEST schrieb Laurent Pinchart:
> Hi Alexander,
> 
> On Thu, Jul 21, 2022 at 12:05:46PM +0200, Alexander Stein wrote:
> > Am Donnerstag, 21. Juli 2022, 10:35:35 CEST schrieb Laurent Pinchart:
> > > Add support for the V4L2_CID_HBLANK and V4L2_CID_VBLANK controls to the
> > > imx290 driver. Make the controls read-only to start with, to report the
> > > values to userspace for timing calculation.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/media/i2c/imx290.c | 39 +++++++++++++++++++++++++++++++++++++-
> > >  1 file changed, 38 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > index 4408dd3e191f..7190399f4111 100644
> > > --- a/drivers/media/i2c/imx290.c
> > > +++ b/drivers/media/i2c/imx290.c
> > > @@ -146,6 +146,8 @@ struct imx290 {
> > > 
> > >  	struct v4l2_ctrl_handler ctrls;
> > >  	struct v4l2_ctrl *link_freq;
> > >  	struct v4l2_ctrl *pixel_rate;
> > > 
> > > +	struct v4l2_ctrl *hblank;
> > > +	struct v4l2_ctrl *vblank;
> > > 
> > >  	struct mutex lock;
> > >  
> > >  };
> > > 
> > > @@ -642,6 +644,20 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> > > 
> > >  		if (imx290->pixel_rate)
> > >  		
> > >  			__v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
> > >  			
> > >  						 
imx290_calc_pixel_rate(imx290));
> > > 
> > > +
> > > +		if (imx290->hblank) {
> > > +			unsigned int hblank = mode->hmax - mode-
>width;
> > > +
> > > +			__v4l2_ctrl_modify_range(imx290->hblank, 
hblank, hblank,
> > > +						 1, hblank);
> > > +		}
> > > +
> > > +		if (imx290->vblank) {
> > > +			unsigned int vblank = IMX290_VMAX_DEFAULT - 
mode->height;
> > > +
> > > +			__v4l2_ctrl_modify_range(imx290->vblank, 
vblank, vblank,
> > > +						 1, vblank);
> > > +		}
> > > 
> > >  	}
> > >  	
> > >  	*format = fmt->format;
> > > 
> > > @@ -880,9 +896,10 @@ static const struct media_entity_operations
> > > imx290_subdev_entity_ops = {> > 
> > >  static int imx290_ctrl_init(struct imx290 *imx290)
> > >  {
> > > 
> > > +	unsigned int blank;
> > > 
> > >  	int ret;
> > > 
> > > -	v4l2_ctrl_handler_init(&imx290->ctrls, 5);
> > > +	v4l2_ctrl_handler_init(&imx290->ctrls, 7);
> > > 
> > >  	imx290->ctrls.lock = &imx290->lock;
> > >  	
> > >  	v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > > 
> > > @@ -910,6 +927,26 @@ static int imx290_ctrl_init(struct imx290 *imx290)
> > > 
> > >  				     
ARRAY_SIZE(imx290_test_pattern_menu) - 1,
> > >  				     0, 0, 
imx290_test_pattern_menu);
> > > 
> > > +	/*
> > > +	 * Horizontal blanking is controlled through the HMAX register, 
which
> > > +	 * contains a line length in INCK clock units. The INCK frequency 
is
> > > +	 * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100,
> > > +	 * convert it to a number of pixels based on the nominal pixel 
rate.
> > > +	 */
> > 
> > Currently the driver only supports 37.125 MHz, please refer to
> > imx290_probe.
> Indeed. Re-reading the comment, I suspect something is wrong, as hmax is
> not converted to pixels here (and is also not fixed to 1100). The only
> datasheet I found that is publicly accessed doesn't explain very clearly
> how the HMAX value should be computed. Based on your experience with IMX
> sensors, would you be able to shed some light on this ?

Can you share the link to this datasheet you found?
Sorry, my experience is more like try and error. I don't fully understand this 
as well, but apparently this depends on frame rate select (FRSEL).

Best regards,
Alexander

> > > +	blank = imx290->current_mode->hmax - imx290->current_mode->width;
> > > +	imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, 
&imx290_ctrl_ops,
> > > +					   V4L2_CID_HBLANK, 
blank, blank, 1,
> > > +					   blank);
> > > +	if (imx290->hblank)
> > > +		imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > +
> > > +	blank = IMX290_VMAX_DEFAULT - imx290->current_mode->height;
> > > +	imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, 
&imx290_ctrl_ops,
> > > +					   V4L2_CID_VBLANK, 
blank, blank, 1,
> > > +					   blank);
> > > +	if (imx290->vblank)
> > > +		imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > +
> > > 
> > >  	imx290->sd.ctrl_handler = &imx290->ctrls;
> > >  	
> > >  	if (imx290->ctrls.error) {





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

* Re: Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-21 11:25         ` Laurent Pinchart
@ 2022-07-21 11:43           ` Alexander Stein
  2022-07-22 14:37             ` Sakari Ailus
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 11:43 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Am Donnerstag, 21. Juli 2022, 13:25:17 CEST schrieb Laurent Pinchart:
> Hi Alexander,
> 
> On Thu, Jul 21, 2022 at 01:18:29PM +0200, Alexander Stein wrote:
> > Am Donnerstag, 21. Juli 2022, 12:54:51 CEST schrieb Laurent Pinchart:
> > > On Thu, Jul 21, 2022 at 11:43:47AM +0200, Alexander Stein wrote:
> > > > Am Donnerstag, 21. Juli 2022, 10:35:28 CEST schrieb Laurent Pinchart:
> > > > > The IMX290 has registers of different sizes. To simplify the code,
> > > > > handle this in the read/write functions instead of in the callers by
> > > > > encoding the register size in the symbolic name macros. All
> > > > > registers
> > > > > are defined as 8-bit for now, a subsequent change will move to
> > > > > larger
> > > > > registers where applicable.
> > > > > 
> > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > > ---
> > > > > 
> > > > >  drivers/media/i2c/imx290.c | 352
> > > > >  +++++++++++++++++++------------------
> > > > >  1 file changed, 180 insertions(+), 172 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > > index 711282126c34..ac58bfe6db7f 100644
> > > > > --- a/drivers/media/i2c/imx290.c
> > > > > +++ b/drivers/media/i2c/imx290.c
> > > > > @@ -22,22 +22,28 @@
> > > > > 
> > > > >  #include <media/v4l2-fwnode.h>
> > > > >  #include <media/v4l2-subdev.h>
> > > > > 
> > > > > -#define IMX290_STANDBY 0x3000
> > > > > -#define IMX290_REGHOLD 0x3001
> > > > > -#define IMX290_XMSTA 0x3002
> > > > > -#define IMX290_FR_FDG_SEL 0x3009
> > > > > -#define IMX290_BLKLEVEL_LOW 0x300a
> > > > > -#define IMX290_BLKLEVEL_HIGH 0x300b
> > > > > -#define IMX290_GAIN 0x3014
> > > > > -#define IMX290_HMAX_LOW 0x301c
> > > > > -#define IMX290_HMAX_HIGH 0x301d
> > > > > -#define IMX290_PGCTRL 0x308c
> > > > > -#define IMX290_PHY_LANE_NUM 0x3407
> > > > > -#define IMX290_CSI_LANE_MODE 0x3443
> > > > > +#define IMX290_REG_8BIT(n)				
((1 << 16) |
> > 
> > (n))
> > 
> > > > > +#define IMX290_REG_16BIT(n)
> > 
> > ((2 << 16) | (n))
> > 
> > > > > +#define IMX290_REG_24BIT(n)
> > 
> > ((3 << 16) | (n))
> > 
> > > > IMX290_REG_SIZE_SHIFT instead of 16 here? Not exactly necessary, but
> > > > use
> > > > 1U, 2U and 3U instead.
> > > 
> > > I'll fix that.
> > > 
> > > > > +#define IMX290_REG_SIZE_SHIFT
> > 
> > 16
> > 
> > > > > +#define IMX290_REG_ADDR_MASK
> > 
> > 0xffff
> > 
> > > > > -#define IMX290_PGCTRL_REGEN BIT(0)
> > > > > -#define IMX290_PGCTRL_THRU BIT(1)
> > > > > -#define IMX290_PGCTRL_MODE(n) ((n) << 4)
> > > > > +#define IMX290_STANDBY
> > 
> > IMX290_REG_8BIT(0x3000)
> > 
> > > > > +#define IMX290_REGHOLD
> > 
> > IMX290_REG_8BIT(0x3001)
> > 
> > > > > +#define IMX290_XMSTA
> > 
> > IMX290_REG_8BIT(0x3002)
> > 
> > > > > +#define IMX290_FR_FDG_SEL
> > 
> > IMX290_REG_8BIT(0x3009)
> > 
> > > > > +#define IMX290_BLKLEVEL_LOW
> > 
> > IMX290_REG_8BIT(0x300a)
> > 
> > > > > +#define IMX290_BLKLEVEL_HIGH
> > 
> > IMX290_REG_8BIT(0x300b)
> > 
> > > > > +#define IMX290_GAIN
> > 
> > IMX290_REG_8BIT(0x3014)
> > 
> > > > > +#define IMX290_HMAX_LOW
> > 
> > IMX290_REG_8BIT(0x301c)
> > 
> > > > > +#define IMX290_HMAX_HIGH
> > 
> > IMX290_REG_8BIT(0x301d)
> > 
> > > > > +#define IMX290_PGCTRL
> > 
> > IMX290_REG_8BIT(0x308c)
> > 
> > > > > +#define IMX290_PHY_LANE_NUM
> > 
> > IMX290_REG_8BIT(0x3407)
> > 
> > > > > +#define IMX290_CSI_LANE_MODE
> > 
> > IMX290_REG_8BIT(0x3443)
> > 
> > > > > +
> > > > > +#define IMX290_PGCTRL_REGEN
> > 
> > BIT(0)
> > 
> > > > > +#define IMX290_PGCTRL_THRU				
BIT(1)
> > > > > +#define IMX290_PGCTRL_MODE(n)
> > 
> > ((n) << 4)
> > 
> > > > >  static const char * const imx290_supply_name[] = {
> > > > >  
> > > > >  	"vdda",
> > > > > 
> > > > > @@ -48,7 +54,7 @@ static const char * const imx290_supply_name[] = {
> > > > > 
> > > > >  #define IMX290_NUM_SUPPLIES ARRAY_SIZE(imx290_supply_name)
> > > > >  
> > > > >  struct imx290_regval {
> > > > > 
> > > > > -	u16 reg;
> > > > > +	u32 reg;
> > > > > 
> > > > >  	u8 val;
> > > > >  
> > > > >  };
> > > > > 
> > > > > @@ -111,163 +117,163 @@ static const char * const
> > > > > imx290_test_pattern_menu[] = { };
> > > > > 
> > > > >  static const struct imx290_regval imx290_global_init_settings[] = {
> > > > > 
> > > > > -	{ 0x3007, 0x00 },
> > > > > -	{ 0x3018, 0x65 },
> > > > > -	{ 0x3019, 0x04 },
> > > > > -	{ 0x301a, 0x00 },
> > > > > -	{ 0x3444, 0x20 },
> > > > > -	{ 0x3445, 0x25 },
> > > > > -	{ 0x303a, 0x0c },
> > > > > -	{ 0x3040, 0x00 },
> > > > > -	{ 0x3041, 0x00 },
> > > > > -	{ 0x303c, 0x00 },
> > > > > -	{ 0x303d, 0x00 },
> > > > > -	{ 0x3042, 0x9c },
> > > > > -	{ 0x3043, 0x07 },
> > > > > -	{ 0x303e, 0x49 },
> > > > > -	{ 0x303f, 0x04 },
> > > > > -	{ 0x304b, 0x0a },
> > > > > -	{ 0x300f, 0x00 },
> > > > > -	{ 0x3010, 0x21 },
> > > > > -	{ 0x3012, 0x64 },
> > > > > -	{ 0x3016, 0x09 },
> > > > > -	{ 0x3070, 0x02 },
> > > > > -	{ 0x3071, 0x11 },
> > > > > -	{ 0x309b, 0x10 },
> > > > > -	{ 0x309c, 0x22 },
> > > > > -	{ 0x30a2, 0x02 },
> > > > > -	{ 0x30a6, 0x20 },
> > > > > -	{ 0x30a8, 0x20 },
> > > > > -	{ 0x30aa, 0x20 },
> > > > > -	{ 0x30ac, 0x20 },
> > > > > -	{ 0x30b0, 0x43 },
> > > > > -	{ 0x3119, 0x9e },
> > > > > -	{ 0x311c, 0x1e },
> > > > > -	{ 0x311e, 0x08 },
> > > > > -	{ 0x3128, 0x05 },
> > > > > -	{ 0x313d, 0x83 },
> > > > > -	{ 0x3150, 0x03 },
> > > > > -	{ 0x317e, 0x00 },
> > > > > -	{ 0x32b8, 0x50 },
> > > > > -	{ 0x32b9, 0x10 },
> > > > > -	{ 0x32ba, 0x00 },
> > > > > -	{ 0x32bb, 0x04 },
> > > > > -	{ 0x32c8, 0x50 },
> > > > > -	{ 0x32c9, 0x10 },
> > > > > -	{ 0x32ca, 0x00 },
> > > > > -	{ 0x32cb, 0x04 },
> > > > > -	{ 0x332c, 0xd3 },
> > > > > -	{ 0x332d, 0x10 },
> > > > > -	{ 0x332e, 0x0d },
> > > > > -	{ 0x3358, 0x06 },
> > > > > -	{ 0x3359, 0xe1 },
> > > > > -	{ 0x335a, 0x11 },
> > > > > -	{ 0x3360, 0x1e },
> > > > > -	{ 0x3361, 0x61 },
> > > > > -	{ 0x3362, 0x10 },
> > > > > -	{ 0x33b0, 0x50 },
> > > > > -	{ 0x33b2, 0x1a },
> > > > > -	{ 0x33b3, 0x04 },
> > > > > +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3018), 0x65 },
> > > > > +	{ IMX290_REG_8BIT(0x3019), 0x04 },
> > > > > +	{ IMX290_REG_8BIT(0x301a), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3444), 0x20 },
> > > > > +	{ IMX290_REG_8BIT(0x3445), 0x25 },
> > > > > +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > > > +	{ IMX290_REG_8BIT(0x3040), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3041), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x303c), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x303d), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3042), 0x9c },
> > > > > +	{ IMX290_REG_8BIT(0x3043), 0x07 },
> > > > > +	{ IMX290_REG_8BIT(0x303e), 0x49 },
> > > > > +	{ IMX290_REG_8BIT(0x303f), 0x04 },
> > > > > +	{ IMX290_REG_8BIT(0x304b), 0x0a },
> > > > > +	{ IMX290_REG_8BIT(0x300f), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3010), 0x21 },
> > > > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > +	{ IMX290_REG_8BIT(0x3016), 0x09 },
> > > > > +	{ IMX290_REG_8BIT(0x3070), 0x02 },
> > > > > +	{ IMX290_REG_8BIT(0x3071), 0x11 },
> > > > > +	{ IMX290_REG_8BIT(0x309b), 0x10 },
> > > > > +	{ IMX290_REG_8BIT(0x309c), 0x22 },
> > > > > +	{ IMX290_REG_8BIT(0x30a2), 0x02 },
> > > > > +	{ IMX290_REG_8BIT(0x30a6), 0x20 },
> > > > > +	{ IMX290_REG_8BIT(0x30a8), 0x20 },
> > > > > +	{ IMX290_REG_8BIT(0x30aa), 0x20 },
> > > > > +	{ IMX290_REG_8BIT(0x30ac), 0x20 },
> > > > > +	{ IMX290_REG_8BIT(0x30b0), 0x43 },
> > > > > +	{ IMX290_REG_8BIT(0x3119), 0x9e },
> > > > > +	{ IMX290_REG_8BIT(0x311c), 0x1e },
> > > > > +	{ IMX290_REG_8BIT(0x311e), 0x08 },
> > > > > +	{ IMX290_REG_8BIT(0x3128), 0x05 },
> > > > > +	{ IMX290_REG_8BIT(0x313d), 0x83 },
> > > > > +	{ IMX290_REG_8BIT(0x3150), 0x03 },
> > > > > +	{ IMX290_REG_8BIT(0x317e), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x32b8), 0x50 },
> > > > > +	{ IMX290_REG_8BIT(0x32b9), 0x10 },
> > > > > +	{ IMX290_REG_8BIT(0x32ba), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x32bb), 0x04 },
> > > > > +	{ IMX290_REG_8BIT(0x32c8), 0x50 },
> > > > > +	{ IMX290_REG_8BIT(0x32c9), 0x10 },
> > > > > +	{ IMX290_REG_8BIT(0x32ca), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x32cb), 0x04 },
> > > > > +	{ IMX290_REG_8BIT(0x332c), 0xd3 },
> > > > > +	{ IMX290_REG_8BIT(0x332d), 0x10 },
> > > > > +	{ IMX290_REG_8BIT(0x332e), 0x0d },
> > > > > +	{ IMX290_REG_8BIT(0x3358), 0x06 },
> > > > > +	{ IMX290_REG_8BIT(0x3359), 0xe1 },
> > > > > +	{ IMX290_REG_8BIT(0x335a), 0x11 },
> > > > > +	{ IMX290_REG_8BIT(0x3360), 0x1e },
> > > > > +	{ IMX290_REG_8BIT(0x3361), 0x61 },
> > > > > +	{ IMX290_REG_8BIT(0x3362), 0x10 },
> > > > > +	{ IMX290_REG_8BIT(0x33b0), 0x50 },
> > > > > +	{ IMX290_REG_8BIT(0x33b2), 0x1a },
> > > > > +	{ IMX290_REG_8BIT(0x33b3), 0x04 },
> > > > > 
> > > > >  };
> > > > >  
> > > > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > > > >  
> > > > >  	/* mode settings */
> > > > > 
> > > > > -	{ 0x3007, 0x00 },
> > > > > -	{ 0x303a, 0x0c },
> > > > > -	{ 0x3414, 0x0a },
> > > > > -	{ 0x3472, 0x80 },
> > > > > -	{ 0x3473, 0x07 },
> > > > > -	{ 0x3418, 0x38 },
> > > > > -	{ 0x3419, 0x04 },
> > > > > -	{ 0x3012, 0x64 },
> > > > > -	{ 0x3013, 0x00 },
> > > > > -	{ 0x305c, 0x18 },
> > > > > -	{ 0x305d, 0x03 },
> > > > > -	{ 0x305e, 0x20 },
> > > > > -	{ 0x305f, 0x01 },
> > > > > -	{ 0x315e, 0x1a },
> > > > > -	{ 0x3164, 0x1a },
> > > > > -	{ 0x3480, 0x49 },
> > > > > +	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > > > +	{ IMX290_REG_8BIT(0x3414), 0x0a },
> > > > > +	{ IMX290_REG_8BIT(0x3472), 0x80 },
> > > > > +	{ IMX290_REG_8BIT(0x3473), 0x07 },
> > > > > +	{ IMX290_REG_8BIT(0x3418), 0x38 },
> > > > > +	{ IMX290_REG_8BIT(0x3419), 0x04 },
> > > > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x305c), 0x18 },
> > > > > +	{ IMX290_REG_8BIT(0x305d), 0x03 },
> > > > > +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > > > +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > > > +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > > > +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > > > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > > > 
> > > > >  	/* data rate settings */
> > > > > 
> > > > > -	{ 0x3405, 0x10 },
> > > > > -	{ 0x3446, 0x57 },
> > > > > -	{ 0x3447, 0x00 },
> > > > > -	{ 0x3448, 0x37 },
> > > > > -	{ 0x3449, 0x00 },
> > > > > -	{ 0x344a, 0x1f },
> > > > > -	{ 0x344b, 0x00 },
> > > > > -	{ 0x344c, 0x1f },
> > > > > -	{ 0x344d, 0x00 },
> > > > > -	{ 0x344e, 0x1f },
> > > > > -	{ 0x344f, 0x00 },
> > > > > -	{ 0x3450, 0x77 },
> > > > > -	{ 0x3451, 0x00 },
> > > > > -	{ 0x3452, 0x1f },
> > > > > -	{ 0x3453, 0x00 },
> > > > > -	{ 0x3454, 0x17 },
> > > > > -	{ 0x3455, 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > > > +	{ IMX290_REG_8BIT(0x3446), 0x57 },
> > > > > +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3448), 0x37 },
> > > > > +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x344a), 0x1f },
> > > > > +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x344c), 0x1f },
> > > > > +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x344e), 0x1f },
> > > > > +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3450), 0x77 },
> > > > > +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3452), 0x1f },
> > > > > +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > > > +	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > > > 
> > > > >  };
> > > > >  
> > > > >  static const struct imx290_regval imx290_720p_settings[] = {
> > > > >  
> > > > >  	/* mode settings */
> > > > > 
> > > > > -	{ 0x3007, 0x10 },
> > > > > -	{ 0x303a, 0x06 },
> > > > > -	{ 0x3414, 0x04 },
> > > > > -	{ 0x3472, 0x00 },
> > > > > -	{ 0x3473, 0x05 },
> > > > > -	{ 0x3418, 0xd0 },
> > > > > -	{ 0x3419, 0x02 },
> > > > > -	{ 0x3012, 0x64 },
> > > > > -	{ 0x3013, 0x00 },
> > > > > -	{ 0x305c, 0x20 },
> > > > > -	{ 0x305d, 0x00 },
> > > > > -	{ 0x305e, 0x20 },
> > > > > -	{ 0x305f, 0x01 },
> > > > > -	{ 0x315e, 0x1a },
> > > > > -	{ 0x3164, 0x1a },
> > > > > -	{ 0x3480, 0x49 },
> > > > > +	{ IMX290_REG_8BIT(0x3007), 0x10 },
> > > > > +	{ IMX290_REG_8BIT(0x303a), 0x06 },
> > > > > +	{ IMX290_REG_8BIT(0x3414), 0x04 },
> > > > > +	{ IMX290_REG_8BIT(0x3472), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3473), 0x05 },
> > > > > +	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> > > > > +	{ IMX290_REG_8BIT(0x3419), 0x02 },
> > > > > +	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > +	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x305c), 0x20 },
> > > > > +	{ IMX290_REG_8BIT(0x305d), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > > > +	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > > > +	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > > > +	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > > > +	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > > > 
> > > > >  	/* data rate settings */
> > > > > 
> > > > > -	{ 0x3405, 0x10 },
> > > > > -	{ 0x3446, 0x4f },
> > > > > -	{ 0x3447, 0x00 },
> > > > > -	{ 0x3448, 0x2f },
> > > > > -	{ 0x3449, 0x00 },
> > > > > -	{ 0x344a, 0x17 },
> > > > > -	{ 0x344b, 0x00 },
> > > > > -	{ 0x344c, 0x17 },
> > > > > -	{ 0x344d, 0x00 },
> > > > > -	{ 0x344e, 0x17 },
> > > > > -	{ 0x344f, 0x00 },
> > > > > -	{ 0x3450, 0x57 },
> > > > > -	{ 0x3451, 0x00 },
> > > > > -	{ 0x3452, 0x17 },
> > > > > -	{ 0x3453, 0x00 },
> > > > > -	{ 0x3454, 0x17 },
> > > > > -	{ 0x3455, 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > > > +	{ IMX290_REG_8BIT(0x3446), 0x4f },
> > > > > +	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3448), 0x2f },
> > > > > +	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x344a), 0x17 },
> > > > > +	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x344c), 0x17 },
> > > > > +	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x344e), 0x17 },
> > > > > +	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3450), 0x57 },
> > > > > +	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3452), 0x17 },
> > > > > +	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > > > +	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > > > 
> > > > >  };
> > > > >  
> > > > >  static const struct imx290_regval imx290_10bit_settings[] = {
> > > > > 
> > > > > -	{ 0x3005, 0x00},
> > > > > -	{ 0x3046, 0x00},
> > > > > -	{ 0x3129, 0x1d},
> > > > > -	{ 0x317c, 0x12},
> > > > > -	{ 0x31ec, 0x37},
> > > > > -	{ 0x3441, 0x0a},
> > > > > -	{ 0x3442, 0x0a},
> > > > > -	{ 0x300a, 0x3c},
> > > > > -	{ 0x300b, 0x00},
> > > > > +	{ IMX290_REG_8BIT(0x3005), 0x00},
> > > > > +	{ IMX290_REG_8BIT(0x3046), 0x00},
> > > > > +	{ IMX290_REG_8BIT(0x3129), 0x1d},
> > > > > +	{ IMX290_REG_8BIT(0x317c), 0x12},
> > > > > +	{ IMX290_REG_8BIT(0x31ec), 0x37},
> > > > > +	{ IMX290_REG_8BIT(0x3441), 0x0a},
> > > > > +	{ IMX290_REG_8BIT(0x3442), 0x0a},
> > > > > +	{ IMX290_REG_8BIT(0x300a), 0x3c},
> > > > > +	{ IMX290_REG_8BIT(0x300b), 0x00},
> > > > > 
> > > > >  };
> > > > >  
> > > > >  static const struct imx290_regval imx290_12bit_settings[] = {
> > > > > 
> > > > > -	{ 0x3005, 0x01 },
> > > > > -	{ 0x3046, 0x01 },
> > > > > -	{ 0x3129, 0x00 },
> > > > > -	{ 0x317c, 0x00 },
> > > > > -	{ 0x31ec, 0x0e },
> > > > > -	{ 0x3441, 0x0c },
> > > > > -	{ 0x3442, 0x0c },
> > > > > -	{ 0x300a, 0xf0 },
> > > > > -	{ 0x300b, 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x3005), 0x01 },
> > > > > +	{ IMX290_REG_8BIT(0x3046), 0x01 },
> > > > > +	{ IMX290_REG_8BIT(0x3129), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x317c), 0x00 },
> > > > > +	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> > > > > +	{ IMX290_REG_8BIT(0x3441), 0x0c },
> > > > > +	{ IMX290_REG_8BIT(0x3442), 0x0c },
> > > > > +	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> > > > > +	{ IMX290_REG_8BIT(0x300b), 0x00 },
> > > > > 
> > > > >  };
> > > > >  
> > > > >  /* supported link frequencies */
> > > > > 
> > > > > @@ -362,33 +368,35 @@ static inline struct imx290 *to_imx290(struct
> > > > > v4l2_subdev *_sd) return container_of(_sd, struct imx290, sd);
> > > > > 
> > > > >  }
> > > > > 
> > > > > -static inline int __always_unused imx290_read_reg(struct imx290
> > > > > *imx290, u16 addr, u8 *value) +static int __always_unused
> > > > > imx290_read_reg(struct imx290 *imx290, u32 addr, u32 *value) {
> > > > > -	unsigned int regval;
> > > > > +	u8 data[3] = { 0, 0, 0 };
> > > > > 
> > > > >  	int ret;
> > > > > 
> > > > > -	ret = regmap_read(imx290->regmap, addr, &regval);
> > > > > -	if (ret) {
> > > > > -		dev_err(imx290->dev, "Failed to read register 
0x%04x: %d\n",
> > > > > -			addr, ret);
> > > > > +	ret = regmap_raw_read(imx290->regmap, addr & 
IMX290_REG_ADDR_MASK,
> > > > > +			      data, (addr >> 
IMX290_REG_SIZE_SHIFT) & 3);
> > > > 
> > > > While I agree with the intention, it fails for some devices, e.g.
> > > > Vision
> > > > Components MIPI IMX327 C does not support auto-increment and most
> > > > probably
> > > > also valid for the IMX290 model.
> > > > This is similar to the OV9281 variant, see [1].
> > > 
> > > *sigh* Can't they get their firmware right ? :-( Inserting a
> > > microcontroller between the SoC and sensor is bad enough in itself,
> > > making it mess up I2C access due to firmware bugs is worse.
> > 
> > [1] indicates this is due to NDA compliance.
> 
> I don't buy that, sorry. That's not the reason, and even if it were, it
> wouldn't excuse breaking auto-increment on read.

I expect other (valid) sensor registers can't be read as well. And to prevent 
circumventing that by using auto-increment, it is blocked completely.
It's hassle I agree.

> > > How far do we need to go in sensor drivers to support messed up hardware
> > > designs that are not related to the sensor at all ? I don't want to
> > > patch all sensor drivers to make I2C read slower because someone
> > > somewhere has taken the sensor and decided to screw up. That doesn't
> > > scale, and hurt all users of these sensors in sane camera modules.
> > 
> > A somewhat acceptable solution might be to add a property indicating that
> > auto-increment is not supported, so that each byte has to be fetched
> > individually.
> 
> I would be fine with that. It should then be handled in the I2C core or
> regmap layer.

Nice the following snippet does the trick already:
---8<---
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -221,6 +221,7 @@ static const struct imx290_pixfmt imx290_formats[] = {
 static const struct regmap_config imx290_regmap_config = {
        .reg_bits = 16,
        .val_bits = 8,
+       .use_single_read = true,
 };
 
 static const char * const imx290_test_pattern_menu[] = {
---8<---

As this affects the VC OV9281 as well, any suggestions for a common property?

Best regards,
Alexander

> > [1] https://github.com/raspberrypi/linux/commit/
> > 58deee7c917e1c3c5e37987c3a89ad19d791f58a
> > 
> > > > Reading ID using 16bit register (using later patch) returns:
> > > > > imx290 2-001a: chip ID 0xffd0
> > > > 
> > > > Using 2 8bit reads:
> > > > imx290 2-001a: chip ID 0x07d0
> > > > 
> > > > Best regards,
> > > > Alexander
> > > > 
> > > > [1]
> > > > https://patchwork.kernel.org/project/linux-media/patch/20220715074858.
> > > > 875
> > > > 808-7-alexander.stein@ew.tq-group.com/>
> > > > 
> > > > > +	if (ret < 0) {
> > > > > +		dev_err(imx290->dev, "%u-bit read from 0x%04x 
failed: %d\n",
> > > > > +			 ((addr >> IMX290_REG_SIZE_SHIFT) 
& 3) * 8,
> > > > > +			 addr & IMX290_REG_ADDR_MASK, 
ret);
> > > > > 
> > > > >  		return ret;
> > > > >  	
> > > > >  	}
> > > > > 
> > > > > -	*value = regval & 0xff;
> > > > > -
> > > > > +	*value = (data[2] << 16) | (data[1] << 8) | data[0];
> > > > > 
> > > > >  	return 0;
> > > > >  
> > > > >  }
> > > > > 
> > > > > -static int imx290_write_reg(struct imx290 *imx290, u16 addr, u8
> > > > > value)
> > > > > +static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32
> > > > > value)
> > > > > 
> > > > >  {
> > > > > 
> > > > > +	u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value 
>> 16 };
> > > > > 
> > > > >  	int ret;
> > > > > 
> > > > > -	ret = regmap_write(imx290->regmap, addr, value);
> > > > > -	if (ret) {
> > > > > -		dev_err(imx290->dev, "Failed to write 
register 0x%04x: %d\n",
> > > > > -			addr, ret);
> > > > > -		return ret;
> > > > > -	}
> > > > > +	ret = regmap_raw_write(imx290->regmap, addr &
> > > > > IMX290_REG_ADDR_MASK,
> > > > > +			       data, (addr >> 
IMX290_REG_SIZE_SHIFT) & 3);
> > > > > +	if (ret < 0)
> > > > > +		dev_err(imx290->dev, "%u-bit write to 0x%04x 
failed: %d\n",
> > > > > +			 ((addr >> IMX290_REG_SIZE_SHIFT) 
& 3) * 8,
> > > > > +			 addr & IMX290_REG_ADDR_MASK, 
ret);
> > > > > 
> > > > >  	return ret;
> > > > >  
> > > > >  }





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

* Re: Re: [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal
  2022-07-21 11:31     ` Laurent Pinchart
@ 2022-07-21 11:54       ` Alexander Stein
  2022-07-21 12:04         ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-21 11:54 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent,

Am Donnerstag, 21. Juli 2022, 13:31:56 CEST schrieb Laurent Pinchart:
> Hi Alexander,
> 
> On Thu, Jul 21, 2022 at 11:18:24AM +0200, Alexander Stein wrote:
> > Hi Laurent,
> > 
> > thanks for working on this, I've also some patches on top for imx327
> > support.
> I'm using an IMX327 with this driver without any need for additional
> patches :-) I'd be happy to test our patches though.

Same for me, but I feel unpleasent writing to reserved bits ;-)

> > Am Donnerstag, 21. Juli 2022, 10:35:24 CEST schrieb Laurent Pinchart:
> > > The HMAX value specifies the total line length in pixels. It's thus more
> > > readable in decimal than hexadecimal. Fix it.
> > 
> > I understand the motivation, pixels are more natural in decimal numbers,
> > but e.g. what is 4400 pixels on this sensor? It is only mentioned
> > sparsely and 3300d is not mentioned at all, 0ce4h is instead.
> 
> I'm not even sure if HMAX is expressed in pixels or in cycles of some
> internal clock different than the pixel clocks.
> 
> > I also like to have the hexadecimal numbers here as you can find them
> > directly in the datasheet. To me this seems more sensible for
> > cross-checking. Just my opinion.
> 
> It's a matter of readability of the driver code vs. matching with the
> datasheet. I have a preference for decimal numbers here, but I don't
> mind too much. What I would actually like is dropping the hmax value
> from the imx290_mode structure and computing it dynamically based on a
> hblank value set by userspace. Do you think you could help me doing so ?

Well, in my patch stack there is one adding vmax to this struct ;-)
It works without modification but this is essentially the so called 'long 
exposure operation'.
Reducing vmax on 720p increases the FPS, so this is a sensible thing to do. 
The exposure has to be recalculated from that (dynamic) vmax value.

But computing those values completely dynamically seems a sensible thing to 
do. Until it is fully understood I would prefer keeping hexadecimal values.
I mean do you know why it is 4400 pixels for 1080p and 6600 for 720p on 2 
lanes?

I know this is part of your [1] branch. So I'll post my patches once this 
series is settled.

Best regards,
Alexander

[1] https://gitlab.com/ideasonboard/nxp/linux/-/commits/pinchartl/v5.19/
sensors/imx

> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/media/i2c/imx290.c | 8 ++++----
> > >  1 file changed, 4 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > index 64bd43813dbf..f60a4135dc9c 100644
> > > --- a/drivers/media/i2c/imx290.c
> > > +++ b/drivers/media/i2c/imx290.c
> > > @@ -308,7 +308,7 @@ static const struct imx290_mode
> > > imx290_modes_2lanes[] =
> > > { {
> > > 
> > >  		.width = 1920,
> > >  		.height = 1080,
> > > 
> > > -		.hmax = 0x1130,
> > > +		.hmax = 4400,
> > > 
> > >  		.link_freq_index = FREQ_INDEX_1080P,
> > >  		.data = imx290_1080p_settings,
> > >  		.data_size = ARRAY_SIZE(imx290_1080p_settings),
> > > 
> > > @@ -316,7 +316,7 @@ static const struct imx290_mode
> > > imx290_modes_2lanes[] =
> > > { {
> > > 
> > >  		.width = 1280,
> > >  		.height = 720,
> > > 
> > > -		.hmax = 0x19c8,
> > > +		.hmax = 6600,
> > > 
> > >  		.link_freq_index = FREQ_INDEX_720P,
> > >  		.data = imx290_720p_settings,
> > >  		.data_size = ARRAY_SIZE(imx290_720p_settings),
> > > 
> > > @@ -327,7 +327,7 @@ static const struct imx290_mode
> > > imx290_modes_4lanes[] =
> > > { {
> > > 
> > >  		.width = 1920,
> > >  		.height = 1080,
> > > 
> > > -		.hmax = 0x0898,
> > > +		.hmax = 2200,
> > > 
> > >  		.link_freq_index = FREQ_INDEX_1080P,
> > >  		.data = imx290_1080p_settings,
> > >  		.data_size = ARRAY_SIZE(imx290_1080p_settings),
> > > 
> > > @@ -335,7 +335,7 @@ static const struct imx290_mode
> > > imx290_modes_4lanes[] =
> > > { {
> > > 
> > >  		.width = 1280,
> > >  		.height = 720,
> > > 
> > > -		.hmax = 0x0ce4,
> > > +		.hmax = 3300,
> > > 
> > >  		.link_freq_index = FREQ_INDEX_720P,
> > >  		.data = imx290_720p_settings,
> > >  		.data_size = ARRAY_SIZE(imx290_720p_settings),





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

* Re: Re: [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal
  2022-07-21 11:54       ` Alexander Stein
@ 2022-07-21 12:04         ` Laurent Pinchart
  0 siblings, 0 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-21 12:04 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Alexander,

On Thu, Jul 21, 2022 at 01:54:18PM +0200, Alexander Stein wrote:
> Am Donnerstag, 21. Juli 2022, 13:31:56 CEST schrieb Laurent Pinchart:
> > On Thu, Jul 21, 2022 at 11:18:24AM +0200, Alexander Stein wrote:
> > > Hi Laurent,
> > > 
> > > thanks for working on this, I've also some patches on top for imx327
> > > support.
> > 
> > I'm using an IMX327 with this driver without any need for additional
> > patches :-) I'd be happy to test our patches though.
> 
> Same for me, but I feel unpleasent writing to reserved bits ;-)
> 
> > > Am Donnerstag, 21. Juli 2022, 10:35:24 CEST schrieb Laurent Pinchart:
> > > > The HMAX value specifies the total line length in pixels. It's thus more
> > > > readable in decimal than hexadecimal. Fix it.
> > > 
> > > I understand the motivation, pixels are more natural in decimal numbers,
> > > but e.g. what is 4400 pixels on this sensor? It is only mentioned
> > > sparsely and 3300d is not mentioned at all, 0ce4h is instead.
> > 
> > I'm not even sure if HMAX is expressed in pixels or in cycles of some
> > internal clock different than the pixel clocks.
> > 
> > > I also like to have the hexadecimal numbers here as you can find them
> > > directly in the datasheet. To me this seems more sensible for
> > > cross-checking. Just my opinion.
> > 
> > It's a matter of readability of the driver code vs. matching with the
> > datasheet. I have a preference for decimal numbers here, but I don't
> > mind too much. What I would actually like is dropping the hmax value
> > from the imx290_mode structure and computing it dynamically based on a
> > hblank value set by userspace. Do you think you could help me doing so ?
> 
> Well, in my patch stack there is one adding vmax to this struct ;-)
> It works without modification but this is essentially the so called 'long 
> exposure operation'.
> Reducing vmax on 720p increases the FPS, so this is a sensible thing to do. 
> The exposure has to be recalculated from that (dynamic) vmax value.

vmax should be easier as that's expressed in lines, so you can more
easily map it to V4L2_CID_VBLANK.

> But computing those values completely dynamically seems a sensible thing to 
> do. Until it is fully understood I would prefer keeping hexadecimal values.
> I mean do you know why it is 4400 pixels for 1080p and 6600 for 720p on 2 
> lanes?

I think it may not expressed in pixels, but in units of some other
internal clock, whose frequency is different for different numbers of
lanes.

> I know this is part of your [1] branch. So I'll post my patches once this 
> series is settled.
> 
> [1] https://gitlab.com/ideasonboard/nxp/linux/-/commits/pinchartl/v5.19/
> sensors/imx
> 
> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > ---
> > > > 
> > > >  drivers/media/i2c/imx290.c | 8 ++++----
> > > >  1 file changed, 4 insertions(+), 4 deletions(-)
> > > > 
> > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > index 64bd43813dbf..f60a4135dc9c 100644
> > > > --- a/drivers/media/i2c/imx290.c
> > > > +++ b/drivers/media/i2c/imx290.c
> > > > @@ -308,7 +308,7 @@ static const struct imx290_mode
> > > > imx290_modes_2lanes[] =
> > > > { {
> > > > 
> > > >  		.width = 1920,
> > > >  		.height = 1080,
> > > > 
> > > > -		.hmax = 0x1130,
> > > > +		.hmax = 4400,
> > > > 
> > > >  		.link_freq_index = FREQ_INDEX_1080P,
> > > >  		.data = imx290_1080p_settings,
> > > >  		.data_size = ARRAY_SIZE(imx290_1080p_settings),
> > > > 
> > > > @@ -316,7 +316,7 @@ static const struct imx290_mode
> > > > imx290_modes_2lanes[] =
> > > > { {
> > > > 
> > > >  		.width = 1280,
> > > >  		.height = 720,
> > > > 
> > > > -		.hmax = 0x19c8,
> > > > +		.hmax = 6600,
> > > > 
> > > >  		.link_freq_index = FREQ_INDEX_720P,
> > > >  		.data = imx290_720p_settings,
> > > >  		.data_size = ARRAY_SIZE(imx290_720p_settings),
> > > > 
> > > > @@ -327,7 +327,7 @@ static const struct imx290_mode
> > > > imx290_modes_4lanes[] =
> > > > { {
> > > > 
> > > >  		.width = 1920,
> > > >  		.height = 1080,
> > > > 
> > > > -		.hmax = 0x0898,
> > > > +		.hmax = 2200,
> > > > 
> > > >  		.link_freq_index = FREQ_INDEX_1080P,
> > > >  		.data = imx290_1080p_settings,
> > > >  		.data_size = ARRAY_SIZE(imx290_1080p_settings),
> > > > 
> > > > @@ -335,7 +335,7 @@ static const struct imx290_mode
> > > > imx290_modes_4lanes[] =
> > > > { {
> > > > 
> > > >  		.width = 1280,
> > > >  		.height = 720,
> > > > 
> > > > -		.hmax = 0x0ce4,
> > > > +		.hmax = 3300,
> > > > 
> > > >  		.link_freq_index = FREQ_INDEX_720P,
> > > >  		.data = imx290_720p_settings,
> > > >  		.data_size = ARRAY_SIZE(imx290_720p_settings),

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/19] media: i2c: imx290: Add crop selection targets support
  2022-07-21  8:35 ` [PATCH 18/19] media: i2c: imx290: Add crop selection targets support Laurent Pinchart
@ 2022-07-21 15:39   ` Dave Stevenson
  2022-10-16  5:53     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Dave Stevenson @ 2022-07-21 15:39 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent

On Thu, 21 Jul 2022 at 09:36, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Implement read-only access to crop selection rectangles to expose the
> analogue crop rectangle. The public (leaked) IMX290 documentation is not
> very clear on how cropping is implemented and configured exactly, so
> the margins may not be entirely accurate.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 94 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 94 insertions(+)
>
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index baf9941c5fbe..0cb11ec1cf0f 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -105,6 +105,53 @@
>
>  #define IMX290_VMAX_DEFAULT                            1125
>
> +
> +/*
> + * The IMX290 pixel array is organized as follows:
> + *
> + *     +------------------------------------+
> + *     |           Optical Black            |     }  Vertical effective optical black (10)
> + * +---+------------------------------------+---+
> + * |   |                                    |   | }  Effective top margin (8)
> + * |   |   +----------------------------+   |   | \
> + * |   |   |                            |   |   |  |
> + * |   |   |                            |   |   |  |
> + * |   |   |                            |   |   |  |
> + * |   |   |    Recording Pixel Area    |   |   |  | Recommended height (1080)
> + * |   |   |                            |   |   |  |
> + * |   |   |                            |   |   |  |
> + * |   |   |                            |   |   |  |
> + * |   |   +----------------------------+   |   | /
> + * |   |                                    |   | }  Effective bottom margin (8)

I have an official datasheet from Sony. "Effective margin for colour
processing" at the bottom is stated to be 9 lines, not 8. That also
makes the numbers then tally of total height being 8 + 1080 + 9 =
1097.

Otherwise I agree with the numbers you quote here.

My datasheet does go into how window mode is configured, however
window mode is not being used.
The register sets present in the driver set the output image size to
1920x1080 or 1280x720 of the overall 1945x1097 pixels. They differ
slightly from the definitions given in the datasheet for the Full HD
1080p and HD720p modes which read out 1945x1097 and 1297x725 pixels
respectively (assuming I've read it correctly). Exactly how those
extra pixels are cropped off isn't defined, but I'd suspect it was the
top left portion of the full image.

If you want 100% defined cropping for each mode then that should be
achievable using window mode.

  Dave

> + * +---+------------------------------------+---+
> + *  <-> <-> <--------------------------> <-> <->
> + *                                            \----  Ignored right margin (4)
> + *                                        \--------  Effective right margin (9)
> + *                       \-------------------------  Recommended width (1920)
> + *       \-----------------------------------------  Effective left margin (8)
> + *   \---------------------------------------------  Ignored left margin (4)
> + *
> + * The optical black lines are output over CSI-2 with a separate data type.
> + *
> + * The pixel array is meant to have 1920x1080 usable pixels after image
> + * processing in an ISP. It has 8 (9) extra active pixels usable for color
> + * processing in the ISP on the top and left (bottom and right) sides of the
> + * image. In addition, 4 additional pixels are present on the left and right
> + * sides of the image, documented as "ignored area".
> + *
> + * As far as is understood, all pixels of the pixel array (ignored area, color
> + * processing margins and recording area) can be output by the sensor.
> + */
> +
> +#define IMX290_PIXEL_ARRAY_WIDTH                       1945
> +#define IMX290_PIXEL_ARRAY_HEIGHT                      1097
> +#define IMX920_PIXEL_ARRAY_MARGIN_LEFT                 12
> +#define IMX920_PIXEL_ARRAY_MARGIN_RIGHT                        13
> +#define IMX920_PIXEL_ARRAY_MARGIN_TOP                  8
> +#define IMX920_PIXEL_ARRAY_MARGIN_BOTTOM               9
> +#define IMX290_PIXEL_ARRAY_RECORDING_WIDTH             1920
> +#define IMX290_PIXEL_ARRAY_RECORDING_HEIGHT            1080
> +
>  static const char * const imx290_supply_name[] = {
>         "vdda",
>         "vddd",
> @@ -671,6 +718,52 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
>         return 0;
>  }
>
> +static int imx290_get_selection(struct v4l2_subdev *sd,
> +                               struct v4l2_subdev_state *sd_state,
> +                               struct v4l2_subdev_selection *sel)
> +{
> +       struct imx290 *imx290 = to_imx290(sd);
> +       struct v4l2_mbus_framefmt *format;
> +
> +       switch (sel->target) {
> +       case V4L2_SEL_TGT_CROP: {
> +               format = imx290_get_pad_format(imx290, sd_state, sel->which);
> +
> +               mutex_lock(&imx290->lock);
> +
> +               sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP
> +                          + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2;
> +               sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT
> +                           + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2;
> +               sel->r.width = format->width;
> +               sel->r.height = format->height;
> +
> +               mutex_unlock(&imx290->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 = IMX290_PIXEL_ARRAY_WIDTH;
> +               sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT;
> +
> +               return 0;
> +
> +       case V4L2_SEL_TGT_CROP_DEFAULT:
> +               sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP;
> +               sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT;
> +               sel->r.width = IMX290_PIXEL_ARRAY_RECORDING_WIDTH;
> +               sel->r.height = IMX290_PIXEL_ARRAY_RECORDING_HEIGHT;
> +
> +               return 0;
> +
> +       default:
> +               return -EINVAL;
> +       }
> +}
> +
>  static int imx290_entity_init_cfg(struct v4l2_subdev *subdev,
>                                   struct v4l2_subdev_state *sd_state)
>  {
> @@ -887,6 +980,7 @@ static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
>         .enum_frame_size = imx290_enum_frame_size,
>         .get_fmt = imx290_get_fmt,
>         .set_fmt = imx290_set_fmt,
> +       .get_selection = imx290_get_selection,
>  };
>
>  static const struct v4l2_subdev_ops imx290_subdev_ops = {
> --
> Regards,
>
> Laurent Pinchart
>

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

* Re: [PATCH 11/19] media: i2c: imx290: Add exposure time control
  2022-07-21  8:35 ` [PATCH 11/19] media: i2c: imx290: Add exposure time control Laurent Pinchart
  2022-07-21 10:01   ` Alexander Stein
@ 2022-07-21 15:52   ` Dave Stevenson
  1 sibling, 0 replies; 81+ messages in thread
From: Dave Stevenson @ 2022-07-21 15:52 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

On Thu, 21 Jul 2022 at 09:36, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Support configuring the exposure time, which is expressed as the
> complement if the exposure time (frame period minus integration time).

s/if/of

Ranges confirmed to be in accordance with the datasheet.

With the commit text typo fixed:
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> The frame period is currently fixed.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index bec326a83952..3cb024b73ee7 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -103,6 +103,8 @@
>  #define IMX290_PGCTRL_THRU                             BIT(1)
>  #define IMX290_PGCTRL_MODE(n)                          ((n) << 4)
>
> +#define IMX290_VMAX_DEFAULT                            1125
> +
>  static const char * const imx290_supply_name[] = {
>         "vdda",
>         "vddd",
> @@ -176,7 +178,7 @@ static const char * const imx290_test_pattern_menu[] = {
>
>  static const struct imx290_regval imx290_global_init_settings[] = {
>         { IMX290_CTRL_07, IMX290_WINMODE_1080P },
> -       { IMX290_VMAX, 1125 },
> +       { IMX290_VMAX, IMX290_VMAX_DEFAULT },
>         { IMX290_EXTCK_FREQ, 0x2520 },
>         { IMX290_WINWV_OB, 12 },
>         { IMX290_WINPH, 0 },
> @@ -480,6 +482,12 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
>         case V4L2_CID_GAIN:
>                 ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
>                 break;
> +
> +       case V4L2_CID_EXPOSURE:
> +               ret = imx290_write(imx290, IMX290_SHS1,
> +                                  IMX290_VMAX_DEFAULT - ctrl->val - 1, NULL);
> +               break;
> +
>         case V4L2_CID_TEST_PATTERN:
>                 if (ctrl->val) {
>                         imx290_write(imx290, IMX290_BLKLEVEL, 0, &ret);
> @@ -1008,12 +1016,16 @@ static int imx290_probe(struct i2c_client *client)
>          */
>         imx290_entity_init_cfg(&imx290->sd, NULL);
>
> -       v4l2_ctrl_handler_init(&imx290->ctrls, 4);
> +       v4l2_ctrl_handler_init(&imx290->ctrls, 5);
>         imx290->ctrls.lock = &imx290->lock;
>
>         v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
>                           V4L2_CID_GAIN, 0, 72, 1, 0);
>
> +       v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> +                         V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,
> +                         IMX290_VMAX_DEFAULT - 2);
> +
>         imx290->link_freq =
>                 v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
>                                        V4L2_CID_LINK_FREQ,
> --
> Regards,
>
> Laurent Pinchart
>

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

* Re: [PATCH 12/19] media: i2c: imx290: Fix max gain value
  2022-07-21  8:35 ` [PATCH 12/19] media: i2c: imx290: Fix max gain value Laurent Pinchart
  2022-07-21 10:02   ` Alexander Stein
@ 2022-07-21 16:08   ` Dave Stevenson
  2022-10-16  4:51     ` Laurent Pinchart
  1 sibling, 1 reply; 81+ messages in thread
From: Dave Stevenson @ 2022-07-21 16:08 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

On Thu, 21 Jul 2022 at 09:36, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> The gain is expressed in multiple of 0.3dB, as a value between 0.0dB
> and 72.0dB. The maximum value is thus 240, not 72.

At this point in the series I'll agree with you as it is for V4L2_CID_GAIN.
However later in the series you convert to V4L2_CID_ANALOGUE_GAIN, and
there I disagree.

The register is for a combined 0-30dB of analogue gain, and 0-42dB of
digital gain, both in 0.3dB steps.
V4L2_CID_GAIN can have a range of 0-240.
V4L2_CID_ANALOGUE_GAIN has a range of 0-100.

Minor additional point: IMX327 is the previous version of this and
only goes up to 1080p60 instead of 1080p120 (10bit only). That
supports 0-29.4dB of analogue gain, and 42dB of digital gain, for a
max value of 238. If using the definition for analogue gain only, then
you may end up with 0.6dB of digital gain instead, but it will work.
IMX462 is the newer version and supports 1080p120 in 10 or 12bit. I
don't have a full datasheet for it, but the product brief lists
0-29.4dB of analogue, and 42dB of digital gain, same as IMX327.
Seeing as the 120fps modes are not implemented in this driver, it
currently supports all 3 models.

  Dave

> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/imx290.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> index 3cb024b73ee7..1bd464932432 100644
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -1020,7 +1020,7 @@ static int imx290_probe(struct i2c_client *client)
>         imx290->ctrls.lock = &imx290->lock;
>
>         v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> -                         V4L2_CID_GAIN, 0, 72, 1, 0);
> +                         V4L2_CID_GAIN, 0, 240, 1, 0);
>
>         v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
>                           V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,
> --
> Regards,
>
> Laurent Pinchart
>

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

* Re: Re: [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array
  2022-07-21 11:08       ` Alexander Stein
@ 2022-07-21 16:19         ` Dave Stevenson
  2022-07-22  5:53           ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Dave Stevenson @ 2022-07-21 16:19 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Laurent Pinchart, linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent and Alexander

On Thu, 21 Jul 2022 at 12:08, Alexander Stein
<alexander.stein@ew.tq-group.com> wrote:
>
> Hello Laurent,
>
> Am Donnerstag, 21. Juli 2022, 12:40:36 CEST schrieb Laurent Pinchart:
> > Hi Alexander,
> >
> > On Thu, Jul 21, 2022 at 12:08:50PM +0200, Alexander Stein wrote:
> > > Am Donnerstag, 21. Juli 2022, 10:35:37 CEST schrieb Laurent Pinchart:
> > > > Registers 0x3012, 0x3013 and 0x3480 are not documented and are set in
> > > > the per-mode register arrays with values indentical for all modes. Move
> > > > them to the common array.
> > > >
> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > ---
> > > >
> > > >  drivers/media/i2c/imx290.c | 8 ++------
> > > >  1 file changed, 2 insertions(+), 6 deletions(-)
> > > >
> > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > index 78772c6327a2..fc6e87fada1c 100644
> > > > --- a/drivers/media/i2c/imx290.c
> > > > +++ b/drivers/media/i2c/imx290.c
> > > > @@ -192,6 +192,7 @@ static const struct imx290_regval
> > > > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x300f), 0x00 },
> > > >
> > > >   { IMX290_REG_8BIT(0x3010), 0x21 },
> > > >   { IMX290_REG_8BIT(0x3012), 0x64 },
> > > >
> > > > + { IMX290_REG_8BIT(0x3013), 0x00 },
> > > >
> > > >   { IMX290_REG_8BIT(0x3016), 0x09 },
> > > >   { IMX290_REG_8BIT(0x3070), 0x02 },
> > > >   { IMX290_REG_8BIT(0x3071), 0x11 },
> > > >
> > > > @@ -230,6 +231,7 @@ static const struct imx290_regval
> > > > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x33b0), 0x50 },
> > > >
> > > >   { IMX290_REG_8BIT(0x33b2), 0x1a },
> > > >   { IMX290_REG_8BIT(0x33b3), 0x04 },
> > > >
> > > > + { IMX290_REG_8BIT(0x3480), 0x49 },
> > > >
> > > >  };
> > > >
> > > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > > >
> > > > @@ -239,15 +241,12 @@ static const struct imx290_regval
> > > > imx290_1080p_settings[] = { { IMX290_OPB_SIZE_V, 10 },
> > > >
> > > >   { IMX290_X_OUT_SIZE, 1920 },
> > > >   { IMX290_Y_OUT_SIZE, 1080 },
> > > >
> > > > - { IMX290_REG_8BIT(0x3012), 0x64 },
> > > > - { IMX290_REG_8BIT(0x3013), 0x00 },
> > > >
> > > >   { IMX290_INCKSEL1, 0x18 },
> > > >   { IMX290_INCKSEL2, 0x03 },
> > > >   { IMX290_INCKSEL3, 0x20 },
> > > >   { IMX290_INCKSEL4, 0x01 },
> > > >   { IMX290_INCKSEL5, 0x1a },
> > > >   { IMX290_INCKSEL6, 0x1a },
> > > >
> > > > - { IMX290_REG_8BIT(0x3480), 0x49 },
> > > >
> > > >   /* data rate settings */
> > > >   { IMX290_REPETITION, 0x10 },
> > > >   { IMX290_TCLKPOST, 87 },
> > > >
> > > > @@ -267,15 +266,12 @@ static const struct imx290_regval
> > > > imx290_720p_settings[] = { { IMX290_OPB_SIZE_V, 4 },
> > > >
> > > >   { IMX290_X_OUT_SIZE, 1280 },
> > > >   { IMX290_Y_OUT_SIZE, 720 },
> > > >
> > > > - { IMX290_REG_8BIT(0x3012), 0x64 },
> > > > - { IMX290_REG_8BIT(0x3013), 0x00 },
> > > >
> > > >   { IMX290_INCKSEL1, 0x20 },
> > > >   { IMX290_INCKSEL2, 0x00 },
> > > >   { IMX290_INCKSEL3, 0x20 },
> > > >   { IMX290_INCKSEL4, 0x01 },
> > > >   { IMX290_INCKSEL5, 0x1a },
> > > >   { IMX290_INCKSEL6, 0x1a },
> > > >
> > > > - { IMX290_REG_8BIT(0x3480), 0x49 },
> > > >
> > > >   /* data rate settings */
> > > >   { IMX290_REPETITION, 0x10 },
> > > >   { IMX290_TCLKPOST, 79 },
> > >
> > > 0x3480 is INCKSEL7 for imx327, not sure if that should be set yet for
> > > imx290 (only) driver, without proper imx327 support.
> >
> > Do you mean the register doesn't exist on the IMX290 ? We could make it
> > conditional on the sensor model, but it's not added by this patch, it
> > has been there since the first version of the driver, so I'd rather do
> > that on top.
>
> As far as I know INCKSEL7 is only valid on imx327. On imx290 the whole
> 0x300-0x34ff range is reserved.

IMX290_CSI_LANE_MODE to select the number of CSI2 data lanes is
0x3443, so clearly the whole range is not reserved.

> I agree this should be conditional on the sensor model. If you want to keep
> it, because it is not new, I'm fine with that.

0x3840 is documented in my IMX290 datasheet as being INCKSEL7. 0x49
for 37.125MHz clock. 0x92 for 74.25MHz (default).
Removing it *will* break this driver for existing platforms as the
rest of the code configures a 37.125MHz clock.

See [1] for adding 74.25MHz clock support.

  Dave

[1] https://github.com/raspberrypi/linux/commit/125f7e7ef1194d4849c74b25c87d18aea9de2de7

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

* Re: Re: [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls
  2022-07-21 11:32       ` Alexander Stein
@ 2022-07-21 16:37         ` Dave Stevenson
  2022-10-16  6:10           ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Dave Stevenson @ 2022-07-21 16:37 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Laurent Pinchart, linux-media, Manivannan Sadhasivam, Sakari Ailus

On Thu, 21 Jul 2022 at 12:32, Alexander Stein
<alexander.stein@ew.tq-group.com> wrote:
>
> Hi Laurent,
>
> Am Donnerstag, 21. Juli 2022, 13:17:21 CEST schrieb Laurent Pinchart:
> > Hi Alexander,
> >
> > On Thu, Jul 21, 2022 at 12:05:46PM +0200, Alexander Stein wrote:
> > > Am Donnerstag, 21. Juli 2022, 10:35:35 CEST schrieb Laurent Pinchart:
> > > > Add support for the V4L2_CID_HBLANK and V4L2_CID_VBLANK controls to the
> > > > imx290 driver. Make the controls read-only to start with, to report the
> > > > values to userspace for timing calculation.
> > > >
> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > ---
> > > >
> > > >  drivers/media/i2c/imx290.c | 39 +++++++++++++++++++++++++++++++++++++-
> > > >  1 file changed, 38 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > index 4408dd3e191f..7190399f4111 100644
> > > > --- a/drivers/media/i2c/imx290.c
> > > > +++ b/drivers/media/i2c/imx290.c
> > > > @@ -146,6 +146,8 @@ struct imx290 {
> > > >
> > > >   struct v4l2_ctrl_handler ctrls;
> > > >   struct v4l2_ctrl *link_freq;
> > > >   struct v4l2_ctrl *pixel_rate;
> > > >
> > > > + struct v4l2_ctrl *hblank;
> > > > + struct v4l2_ctrl *vblank;
> > > >
> > > >   struct mutex lock;
> > > >
> > > >  };
> > > >
> > > > @@ -642,6 +644,20 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> > > >
> > > >           if (imx290->pixel_rate)
> > > >
> > > >                   __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
> > > >
> > > >
> imx290_calc_pixel_rate(imx290));
> > > >
> > > > +
> > > > +         if (imx290->hblank) {
> > > > +                 unsigned int hblank = mode->hmax - mode-
> >width;
> > > > +
> > > > +                 __v4l2_ctrl_modify_range(imx290->hblank,
> hblank, hblank,
> > > > +                                          1, hblank);
> > > > +         }
> > > > +
> > > > +         if (imx290->vblank) {
> > > > +                 unsigned int vblank = IMX290_VMAX_DEFAULT -
> mode->height;
> > > > +
> > > > +                 __v4l2_ctrl_modify_range(imx290->vblank,
> vblank, vblank,
> > > > +                                          1, vblank);
> > > > +         }
> > > >
> > > >   }
> > > >
> > > >   *format = fmt->format;
> > > >
> > > > @@ -880,9 +896,10 @@ static const struct media_entity_operations
> > > > imx290_subdev_entity_ops = {> >
> > > >  static int imx290_ctrl_init(struct imx290 *imx290)
> > > >  {
> > > >
> > > > + unsigned int blank;
> > > >
> > > >   int ret;
> > > >
> > > > - v4l2_ctrl_handler_init(&imx290->ctrls, 5);
> > > > + v4l2_ctrl_handler_init(&imx290->ctrls, 7);
> > > >
> > > >   imx290->ctrls.lock = &imx290->lock;
> > > >
> > > >   v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > > >
> > > > @@ -910,6 +927,26 @@ static int imx290_ctrl_init(struct imx290 *imx290)
> > > >
> > > >
> ARRAY_SIZE(imx290_test_pattern_menu) - 1,
> > > >                                0, 0,
> imx290_test_pattern_menu);
> > > >
> > > > + /*
> > > > +  * Horizontal blanking is controlled through the HMAX register,
> which
> > > > +  * contains a line length in INCK clock units. The INCK frequency
> is
> > > > +  * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100,
> > > > +  * convert it to a number of pixels based on the nominal pixel
> rate.
> > > > +  */
> > >
> > > Currently the driver only supports 37.125 MHz, please refer to
> > > imx290_probe.
> > Indeed. Re-reading the comment, I suspect something is wrong, as hmax is
> > not converted to pixels here (and is also not fixed to 1100). The only
> > datasheet I found that is publicly accessed doesn't explain very clearly
> > how the HMAX value should be computed. Based on your experience with IMX
> > sensors, would you be able to shed some light on this ?

It is pretty much a standard HTS setting based on a pixel rate that is
fixed at 148.5MPix/s. Likewise VMAX is equivalent to a traditional
VTS.
I've been through the same path in
https://github.com/raspberrypi/linux/commits/rpi-5.15.y/drivers/media/i2c/imx290.c

> Can you share the link to this datasheet you found?
> Sorry, my experience is more like try and error. I don't fully understand this
> as well, but apparently this depends on frame rate select (FRSEL).

FRSEL is the one difference between IMX327 and IMX290 (and presumably
IMX462 too). IMX290 adds "0" as a valid value for 120/100fps mode.
However there is no need to change FRSEL for standard frame rate
control - you can set it at 0x01 and get a full range of frame rates
through VMAX and HMAX. If you wished to extend that range for slower
rates, you could conditionally set it to 0x2 to double the frame time.

  Dave

> Best regards,
> Alexander
>
> > > > + blank = imx290->current_mode->hmax - imx290->current_mode->width;
> > > > + imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls,
> &imx290_ctrl_ops,
> > > > +                                    V4L2_CID_HBLANK,
> blank, blank, 1,
> > > > +                                    blank);
> > > > + if (imx290->hblank)
> > > > +         imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > > +
> > > > + blank = IMX290_VMAX_DEFAULT - imx290->current_mode->height;
> > > > + imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls,
> &imx290_ctrl_ops,
> > > > +                                    V4L2_CID_VBLANK,
> blank, blank, 1,
> > > > +                                    blank);
> > > > + if (imx290->vblank)
> > > > +         imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > > +
> > > >
> > > >   imx290->sd.ctrl_handler = &imx290->ctrls;
> > > >
> > > >   if (imx290->ctrls.error) {
>
>
>
>

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

* Re: Re: Re: [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array
  2022-07-21 16:19         ` Dave Stevenson
@ 2022-07-22  5:53           ` Alexander Stein
  2022-07-22  9:10             ` Dave Stevenson
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-22  5:53 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Laurent Pinchart, linux-media, Manivannan Sadhasivam, Sakari Ailus

Hello Dave,

Am Donnerstag, 21. Juli 2022, 18:19:56 CEST schrieb Dave Stevenson:
> Hi Laurent and Alexander
> 
> On Thu, 21 Jul 2022 at 12:08, Alexander Stein
> 
> <alexander.stein@ew.tq-group.com> wrote:
> > Hello Laurent,
> > 
> > Am Donnerstag, 21. Juli 2022, 12:40:36 CEST schrieb Laurent Pinchart:
> > > Hi Alexander,
> > > 
> > > On Thu, Jul 21, 2022 at 12:08:50PM +0200, Alexander Stein wrote:
> > > > Am Donnerstag, 21. Juli 2022, 10:35:37 CEST schrieb Laurent Pinchart:
> > > > > Registers 0x3012, 0x3013 and 0x3480 are not documented and are set
> > > > > in
> > > > > the per-mode register arrays with values indentical for all modes.
> > > > > Move
> > > > > them to the common array.
> > > > > 
> > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > > ---
> > > > > 
> > > > >  drivers/media/i2c/imx290.c | 8 ++------
> > > > >  1 file changed, 2 insertions(+), 6 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > > index 78772c6327a2..fc6e87fada1c 100644
> > > > > --- a/drivers/media/i2c/imx290.c
> > > > > +++ b/drivers/media/i2c/imx290.c
> > > > > @@ -192,6 +192,7 @@ static const struct imx290_regval
> > > > > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x300f), 0x00 },
> > > > > 
> > > > >   { IMX290_REG_8BIT(0x3010), 0x21 },
> > > > >   { IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > 
> > > > > + { IMX290_REG_8BIT(0x3013), 0x00 },
> > > > > 
> > > > >   { IMX290_REG_8BIT(0x3016), 0x09 },
> > > > >   { IMX290_REG_8BIT(0x3070), 0x02 },
> > > > >   { IMX290_REG_8BIT(0x3071), 0x11 },
> > > > > 
> > > > > @@ -230,6 +231,7 @@ static const struct imx290_regval
> > > > > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x33b0), 0x50 },
> > > > > 
> > > > >   { IMX290_REG_8BIT(0x33b2), 0x1a },
> > > > >   { IMX290_REG_8BIT(0x33b3), 0x04 },
> > > > > 
> > > > > + { IMX290_REG_8BIT(0x3480), 0x49 },
> > > > > 
> > > > >  };
> > > > >  
> > > > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > > > > 
> > > > > @@ -239,15 +241,12 @@ static const struct imx290_regval
> > > > > imx290_1080p_settings[] = { { IMX290_OPB_SIZE_V, 10 },
> > > > > 
> > > > >   { IMX290_X_OUT_SIZE, 1920 },
> > > > >   { IMX290_Y_OUT_SIZE, 1080 },
> > > > > 
> > > > > - { IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > - { IMX290_REG_8BIT(0x3013), 0x00 },
> > > > > 
> > > > >   { IMX290_INCKSEL1, 0x18 },
> > > > >   { IMX290_INCKSEL2, 0x03 },
> > > > >   { IMX290_INCKSEL3, 0x20 },
> > > > >   { IMX290_INCKSEL4, 0x01 },
> > > > >   { IMX290_INCKSEL5, 0x1a },
> > > > >   { IMX290_INCKSEL6, 0x1a },
> > > > > 
> > > > > - { IMX290_REG_8BIT(0x3480), 0x49 },
> > > > > 
> > > > >   /* data rate settings */
> > > > >   { IMX290_REPETITION, 0x10 },
> > > > >   { IMX290_TCLKPOST, 87 },
> > > > > 
> > > > > @@ -267,15 +266,12 @@ static const struct imx290_regval
> > > > > imx290_720p_settings[] = { { IMX290_OPB_SIZE_V, 4 },
> > > > > 
> > > > >   { IMX290_X_OUT_SIZE, 1280 },
> > > > >   { IMX290_Y_OUT_SIZE, 720 },
> > > > > 
> > > > > - { IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > - { IMX290_REG_8BIT(0x3013), 0x00 },
> > > > > 
> > > > >   { IMX290_INCKSEL1, 0x20 },
> > > > >   { IMX290_INCKSEL2, 0x00 },
> > > > >   { IMX290_INCKSEL3, 0x20 },
> > > > >   { IMX290_INCKSEL4, 0x01 },
> > > > >   { IMX290_INCKSEL5, 0x1a },
> > > > >   { IMX290_INCKSEL6, 0x1a },
> > > > > 
> > > > > - { IMX290_REG_8BIT(0x3480), 0x49 },
> > > > > 
> > > > >   /* data rate settings */
> > > > >   { IMX290_REPETITION, 0x10 },
> > > > >   { IMX290_TCLKPOST, 79 },
> > > > 
> > > > 0x3480 is INCKSEL7 for imx327, not sure if that should be set yet for
> > > > imx290 (only) driver, without proper imx327 support.
> > > 
> > > Do you mean the register doesn't exist on the IMX290 ? We could make it
> > > conditional on the sensor model, but it's not added by this patch, it
> > > has been there since the first version of the driver, so I'd rather do
> > > that on top.
> > 
> > As far as I know INCKSEL7 is only valid on imx327. On imx290 the whole
> > 0x300-0x34ff range is reserved.
> 
> IMX290_CSI_LANE_MODE to select the number of CSI2 data lanes is
> 0x3443, so clearly the whole range is not reserved.

You are right, I was looking at the wrong table, my bad.

> > I agree this should be conditional on the sensor model. If you want to
> > keep
> > it, because it is not new, I'm fine with that.
> 
> 0x3840 is documented in my IMX290 datasheet as being INCKSEL7. 0x49
> for 37.125MHz clock. 0x92 for 74.25MHz (default).
> Removing it *will* break this driver for existing platforms as the
> rest of the code configures a 37.125MHz clock.

I guess you mean 0x3480, just a small typo. Just to be sure.
Interesting, the datasheet for imx290 I found doesn't contain INCKSEL7 at all. 
But good to know, that this register applies to imx290 as well.
Thanks for that information.

Best regards,
Alexander

> See [1] for adding 74.25MHz clock support.
> 
>   Dave
> 
> [1]
> https://github.com/raspberrypi/linux/commit/125f7e7ef1194d4849c74b25c87d18a
> ea9de2de7





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

* Re: Re: Re: [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array
  2022-07-22  5:53           ` Alexander Stein
@ 2022-07-22  9:10             ` Dave Stevenson
  0 siblings, 0 replies; 81+ messages in thread
From: Dave Stevenson @ 2022-07-22  9:10 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Laurent Pinchart, linux-media, Manivannan Sadhasivam, Sakari Ailus

On Fri, 22 Jul 2022 at 06:53, Alexander Stein
<alexander.stein@ew.tq-group.com> wrote:
>
> Hello Dave,
>
> Am Donnerstag, 21. Juli 2022, 18:19:56 CEST schrieb Dave Stevenson:
> > Hi Laurent and Alexander
> >
> > On Thu, 21 Jul 2022 at 12:08, Alexander Stein
> >
> > <alexander.stein@ew.tq-group.com> wrote:
> > > Hello Laurent,
> > >
> > > Am Donnerstag, 21. Juli 2022, 12:40:36 CEST schrieb Laurent Pinchart:
> > > > Hi Alexander,
> > > >
> > > > On Thu, Jul 21, 2022 at 12:08:50PM +0200, Alexander Stein wrote:
> > > > > Am Donnerstag, 21. Juli 2022, 10:35:37 CEST schrieb Laurent Pinchart:
> > > > > > Registers 0x3012, 0x3013 and 0x3480 are not documented and are set
> > > > > > in
> > > > > > the per-mode register arrays with values indentical for all modes.
> > > > > > Move
> > > > > > them to the common array.
> > > > > >
> > > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > > > ---
> > > > > >
> > > > > >  drivers/media/i2c/imx290.c | 8 ++------
> > > > > >  1 file changed, 2 insertions(+), 6 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > > > index 78772c6327a2..fc6e87fada1c 100644
> > > > > > --- a/drivers/media/i2c/imx290.c
> > > > > > +++ b/drivers/media/i2c/imx290.c
> > > > > > @@ -192,6 +192,7 @@ static const struct imx290_regval
> > > > > > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x300f), 0x00 },
> > > > > >
> > > > > >   { IMX290_REG_8BIT(0x3010), 0x21 },
> > > > > >   { IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > >
> > > > > > + { IMX290_REG_8BIT(0x3013), 0x00 },
> > > > > >
> > > > > >   { IMX290_REG_8BIT(0x3016), 0x09 },
> > > > > >   { IMX290_REG_8BIT(0x3070), 0x02 },
> > > > > >   { IMX290_REG_8BIT(0x3071), 0x11 },
> > > > > >
> > > > > > @@ -230,6 +231,7 @@ static const struct imx290_regval
> > > > > > imx290_global_init_settings[] = { { IMX290_REG_8BIT(0x33b0), 0x50 },
> > > > > >
> > > > > >   { IMX290_REG_8BIT(0x33b2), 0x1a },
> > > > > >   { IMX290_REG_8BIT(0x33b3), 0x04 },
> > > > > >
> > > > > > + { IMX290_REG_8BIT(0x3480), 0x49 },
> > > > > >
> > > > > >  };
> > > > > >
> > > > > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > > > > >
> > > > > > @@ -239,15 +241,12 @@ static const struct imx290_regval
> > > > > > imx290_1080p_settings[] = { { IMX290_OPB_SIZE_V, 10 },
> > > > > >
> > > > > >   { IMX290_X_OUT_SIZE, 1920 },
> > > > > >   { IMX290_Y_OUT_SIZE, 1080 },
> > > > > >
> > > > > > - { IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > > - { IMX290_REG_8BIT(0x3013), 0x00 },
> > > > > >
> > > > > >   { IMX290_INCKSEL1, 0x18 },
> > > > > >   { IMX290_INCKSEL2, 0x03 },
> > > > > >   { IMX290_INCKSEL3, 0x20 },
> > > > > >   { IMX290_INCKSEL4, 0x01 },
> > > > > >   { IMX290_INCKSEL5, 0x1a },
> > > > > >   { IMX290_INCKSEL6, 0x1a },
> > > > > >
> > > > > > - { IMX290_REG_8BIT(0x3480), 0x49 },
> > > > > >
> > > > > >   /* data rate settings */
> > > > > >   { IMX290_REPETITION, 0x10 },
> > > > > >   { IMX290_TCLKPOST, 87 },
> > > > > >
> > > > > > @@ -267,15 +266,12 @@ static const struct imx290_regval
> > > > > > imx290_720p_settings[] = { { IMX290_OPB_SIZE_V, 4 },
> > > > > >
> > > > > >   { IMX290_X_OUT_SIZE, 1280 },
> > > > > >   { IMX290_Y_OUT_SIZE, 720 },
> > > > > >
> > > > > > - { IMX290_REG_8BIT(0x3012), 0x64 },
> > > > > > - { IMX290_REG_8BIT(0x3013), 0x00 },
> > > > > >
> > > > > >   { IMX290_INCKSEL1, 0x20 },
> > > > > >   { IMX290_INCKSEL2, 0x00 },
> > > > > >   { IMX290_INCKSEL3, 0x20 },
> > > > > >   { IMX290_INCKSEL4, 0x01 },
> > > > > >   { IMX290_INCKSEL5, 0x1a },
> > > > > >   { IMX290_INCKSEL6, 0x1a },
> > > > > >
> > > > > > - { IMX290_REG_8BIT(0x3480), 0x49 },
> > > > > >
> > > > > >   /* data rate settings */
> > > > > >   { IMX290_REPETITION, 0x10 },
> > > > > >   { IMX290_TCLKPOST, 79 },
> > > > >
> > > > > 0x3480 is INCKSEL7 for imx327, not sure if that should be set yet for
> > > > > imx290 (only) driver, without proper imx327 support.
> > > >
> > > > Do you mean the register doesn't exist on the IMX290 ? We could make it
> > > > conditional on the sensor model, but it's not added by this patch, it
> > > > has been there since the first version of the driver, so I'd rather do
> > > > that on top.
> > >
> > > As far as I know INCKSEL7 is only valid on imx327. On imx290 the whole
> > > 0x300-0x34ff range is reserved.
> >
> > IMX290_CSI_LANE_MODE to select the number of CSI2 data lanes is
> > 0x3443, so clearly the whole range is not reserved.
>
> You are right, I was looking at the wrong table, my bad.
>
> > > I agree this should be conditional on the sensor model. If you want to
> > > keep
> > > it, because it is not new, I'm fine with that.
> >
> > 0x3840 is documented in my IMX290 datasheet as being INCKSEL7. 0x49
> > for 37.125MHz clock. 0x92 for 74.25MHz (default).
> > Removing it *will* break this driver for existing platforms as the
> > rest of the code configures a 37.125MHz clock.
>
> I guess you mean 0x3480, just a small typo. Just to be sure.
> Interesting, the datasheet for imx290 I found doesn't contain INCKSEL7 at all.
> But good to know, that this register applies to imx290 as well.
> Thanks for that information.

Yes, typo of 0x3840 vs 0x3480.

I did spend a fair amount of time looking at IMX327 / IMX290 a while
back, and do have datasheets, so happy to help out with reviews. I
really ought to clean up my patches and send them to the list, but
I'll wait for Laurent's set here to be merged first (assuming that
doesn't become too drawn out).

  Dave

> Best regards,
> Alexander
>
> > See [1] for adding 74.25MHz clock support.
> >
> >   Dave
> >
> > [1]
> > https://github.com/raspberrypi/linux/commit/125f7e7ef1194d4849c74b25c87d18a
> > ea9de2de7
>
>
>
>

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

* Re: Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-21 11:43           ` Alexander Stein
@ 2022-07-22 14:37             ` Sakari Ailus
  2022-07-23 23:06               ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Sakari Ailus @ 2022-07-22 14:37 UTC (permalink / raw)
  To: Alexander Stein; +Cc: Laurent Pinchart, linux-media, Manivannan Sadhasivam

Hi Alexander,

On Thu, Jul 21, 2022 at 01:43:54PM +0200, Alexander Stein wrote:
...
> Nice the following snippet does the trick already:
> ---8<---
> --- a/drivers/media/i2c/imx290.c
> +++ b/drivers/media/i2c/imx290.c
> @@ -221,6 +221,7 @@ static const struct imx290_pixfmt imx290_formats[] = {
>  static const struct regmap_config imx290_regmap_config = {
>         .reg_bits = 16,
>         .val_bits = 8,
> +       .use_single_read = true,
>  };
>  
>  static const char * const imx290_test_pattern_menu[] = {
> ---8<---
> 
> As this affects the VC OV9281 as well, any suggestions for a common property?

If there's a 1:1 I²C mux in there between the host and the sensor, should
it be in DT as well? I'm not entirely certain it's necessary.

The property could be called e.g. "single-octet-read". I think this should
probably be documented in I²C bindings (or even regmap).

-- 
Regards,

Sakari Ailus

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

* Re: Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-22 14:37             ` Sakari Ailus
@ 2022-07-23 23:06               ` Laurent Pinchart
  2022-07-25  6:49                 ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-07-23 23:06 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: Alexander Stein, linux-media, Manivannan Sadhasivam

Hi Sakari,

On Fri, Jul 22, 2022 at 05:37:53PM +0300, Sakari Ailus wrote:
> Hi Alexander,
> 
> On Thu, Jul 21, 2022 at 01:43:54PM +0200, Alexander Stein wrote:
> ...
> > Nice the following snippet does the trick already:
> > ---8<---
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -221,6 +221,7 @@ static const struct imx290_pixfmt imx290_formats[] = {
> >  static const struct regmap_config imx290_regmap_config = {
> >         .reg_bits = 16,
> >         .val_bits = 8,
> > +       .use_single_read = true,
> >  };
> >  
> >  static const char * const imx290_test_pattern_menu[] = {
> > ---8<---
> > 
> > As this affects the VC OV9281 as well, any suggestions for a common property?
> 
> If there's a 1:1 I²C mux in there between the host and the sensor, should
> it be in DT as well? I'm not entirely certain it's necessary.

The microcontroller also the sensor clock and power supplies, so it has
to be modelled in DT in any case. I was trying to avoid exposing it as
an I2C mux, but maybe we'll have to bite the bullet...

I've implement support for two camera modules from Vision Components but
haven't submitted patches yet. See [1] and [2] for DT examples and [3]
for the driver that handles the microcontroller.

Note that one purpose of the microcontroller is to configure the sensor
automatically. It can be queried through I2C for a list of supported
modes, and it can also reconfigure the sensor fully when a mode is
selected. This is meant to enable development of a single driver that
will cover all modules, regardless of which camera sensor it integrates.
I'm not sure what words you will use to voice your opinion on this
design, but I think I already agree :-)

[1] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx296.dts
[2] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx327.dts
[3] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/drivers/media/i2c/vc-mipi.c

> The property could be called e.g. "single-octet-read". I think this should
> probably be documented in I²C bindings (or even regmap).

I like the idea of making it a DT property global to all I2C devices. It
should ideally be parsed by the I2C core or by regmap.

-- 
Regards,

Laurent Pinchart

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

* Re: Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-23 23:06               ` Laurent Pinchart
@ 2022-07-25  6:49                 ` Alexander Stein
  2022-08-23  1:08                   ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-07-25  6:49 UTC (permalink / raw)
  To: Sakari Ailus, Laurent Pinchart; +Cc: linux-media, Manivannan Sadhasivam

Hi Laurent & Sakari,

Am Sonntag, 24. Juli 2022, 01:06:29 CEST schrieb Laurent Pinchart:
> Hi Sakari,
> 
> On Fri, Jul 22, 2022 at 05:37:53PM +0300, Sakari Ailus wrote:
> > Hi Alexander,
> > 
> > On Thu, Jul 21, 2022 at 01:43:54PM +0200, Alexander Stein wrote:
> > ...
> > 
> > > Nice the following snippet does the trick already:
> > > ---8<---
> > > --- a/drivers/media/i2c/imx290.c
> > > +++ b/drivers/media/i2c/imx290.c
> > > @@ -221,6 +221,7 @@ static const struct imx290_pixfmt imx290_formats[] =
> > > {
> > > 
> > >  static const struct regmap_config imx290_regmap_config = {
> > >  
> > >         .reg_bits = 16,
> > >         .val_bits = 8,
> > > 
> > > +       .use_single_read = true,
> > > 
> > >  };
> > >  
> > >  static const char * const imx290_test_pattern_menu[] = {
> > > 
> > > ---8<---
> > > 
> > > As this affects the VC OV9281 as well, any suggestions for a common
> > > property?> 
> > If there's a 1:1 I²C mux in there between the host and the sensor, should
> > it be in DT as well? I'm not entirely certain it's necessary.
> 
> The microcontroller also the sensor clock and power supplies, so it has
> to be modelled in DT in any case. I was trying to avoid exposing it as
> an I2C mux, but maybe we'll have to bite the bullet...

What is the benefit about exposing a I2C mux? The needed regmap config option 
is configured completely independent to this.

> I've implement support for two camera modules from Vision Components but
> haven't submitted patches yet. See [1] and [2] for DT examples and [3]
> for the driver that handles the microcontroller.
> 
> Note that one purpose of the microcontroller is to configure the sensor
> automatically. It can be queried through I2C for a list of supported
> modes, and it can also reconfigure the sensor fully when a mode is
> selected. This is meant to enable development of a single driver that
> will cover all modules, regardless of which camera sensor it integrates.
> I'm not sure what words you will use to voice your opinion on this
> design, but I think I already agree :-)
> 
> [1]
> https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/ne
> xt/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx296.dts [2]
> https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/ne
> xt/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx327.dts [3]
> https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/ne
> xt/drivers/media/i2c/vc-mipi.c
> > The property could be called e.g. "single-octet-read". I think this should
> > probably be documented in I²C bindings (or even regmap).
> 
> I like the idea of making it a DT property global to all I2C devices. It
> should ideally be parsed by the I2C core or by regmap.

I agree with adding this as a regmap option, like 'big-endian' & friends, but 
not so much for I2C core. IMHO the core should only be interested in handling 
messages and transfers. Setting up those correctly is a matter for drivers 
(which in turn use regmap).

Best regards,
Alexander




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

* Re: Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-07-25  6:49                 ` Alexander Stein
@ 2022-08-23  1:08                   ` Laurent Pinchart
  2022-08-23  2:51                     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-08-23  1:08 UTC (permalink / raw)
  To: Alexander Stein; +Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam

Hi Alexander,

On Mon, Jul 25, 2022 at 08:49:40AM +0200, Alexander Stein wrote:
> Am Sonntag, 24. Juli 2022, 01:06:29 CEST schrieb Laurent Pinchart:
> > On Fri, Jul 22, 2022 at 05:37:53PM +0300, Sakari Ailus wrote:
> > > On Thu, Jul 21, 2022 at 01:43:54PM +0200, Alexander Stein wrote:
> > > ...
> > > 
> > > > Nice the following snippet does the trick already:
> > > > ---8<---
> > > > --- a/drivers/media/i2c/imx290.c
> > > > +++ b/drivers/media/i2c/imx290.c
> > > > @@ -221,6 +221,7 @@ static const struct imx290_pixfmt imx290_formats[] =
> > > > {
> > > >  static const struct regmap_config imx290_regmap_config = {
> > > >         .reg_bits = 16,
> > > >         .val_bits = 8,
> > > > +       .use_single_read = true,
> > > >  };
> > > >  
> > > >  static const char * const imx290_test_pattern_menu[] = {
> > > > 
> > > > ---8<---
> > > > 
> > > > As this affects the VC OV9281 as well, any suggestions for a common
> > > > property?
> > > 
> > > If there's a 1:1 I²C mux in there between the host and the sensor, should
> > > it be in DT as well? I'm not entirely certain it's necessary.
> > 
> > The microcontroller also the sensor clock and power supplies, so it has
> > to be modelled in DT in any case. I was trying to avoid exposing it as
> > an I2C mux, but maybe we'll have to bite the bullet...
> 
> What is the benefit about exposing a I2C mux? The needed regmap config option 
> is configured completely independent to this.

If the I2C mux in the camera module messes up I2C transfers, the related
quirks need to be handled somewhere, and a specific mux driver device in
DT could be a good place to report that. There may be other options
though.

> > I've implement support for two camera modules from Vision Components but
> > haven't submitted patches yet. See [1] and [2] for DT examples and [3]
> > for the driver that handles the microcontroller.
> > 
> > Note that one purpose of the microcontroller is to configure the sensor
> > automatically. It can be queried through I2C for a list of supported
> > modes, and it can also reconfigure the sensor fully when a mode is
> > selected. This is meant to enable development of a single driver that
> > will cover all modules, regardless of which camera sensor it integrates.
> > I'm not sure what words you will use to voice your opinion on this
> > design, but I think I already agree :-)
> > 
> > [1] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx296.dts
> > [2] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx327.dts
> > [3] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/drivers/media/i2c/vc-mipi.c
> > 
> > > The property could be called e.g. "single-octet-read". I think this should
> > > probably be documented in I²C bindings (or even regmap).
> > 
> > I like the idea of making it a DT property global to all I2C devices. It
> > should ideally be parsed by the I2C core or by regmap.
> 
> I agree with adding this as a regmap option, like 'big-endian' & friends, but 
> not so much for I2C core. IMHO the core should only be interested in handling 
> messages and transfers. Setting up those correctly is a matter for drivers 
> (which in turn use regmap).

I don't want to polute a large number of sensor drivers because of
questionable design decisions of a particular module vendor. This type
of quirk needs to be handled outside of the sensor driver.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
                   ` (18 preceding siblings ...)
  2022-07-21  8:35 ` [PATCH 19/19] media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN Laurent Pinchart
@ 2022-08-23  1:11 ` Laurent Pinchart
  2022-10-10 10:31   ` Dave Stevenson
  19 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-08-23  1:11 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: linux-media, Manivannan Sadhasivam

Hi Sakari,

Could you already pick up patches 01/19, 02/19, 04/19, 05/19 and 06/19
in your tree ? Your opinion on 03/19 woud be appreciated too, I think
it's a candidate for merge as well.

On Thu, Jul 21, 2022 at 11:35:21AM +0300, Laurent Pinchart wrote:
> Hello,
> 
> This patch series gathers miscellaneous improvements for the imx290
> driver. The most notable changes on the kernel side is patch 07/19 that
> simplifies register access, and on the userspace API side patches 14/19,
> 15/19 and 18/19 that extend the driver with controls and selection
> rectangles required by libcamera.
> 
> Laurent Pinchart (19):
>   media: i2c: imx290: Use device lock for the control handler
>   media: i2c: imx290: Print error code when I2C transfer fails
>   media: i2c: imx290: Specify HMAX values in decimal
>   media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
>   media: i2c: imx290: Drop imx290_write_buffered_reg()
>   media: i2c: imx290: Drop regmap cache
>   media: i2c: imx290: Support variable-sized registers
>   media: i2c: imx290: Correct register sizes
>   media: i2c: imx290: Simplify error handling when writing registers
>   media: i2c: imx290: Define more register macros
>   media: i2c: imx290: Add exposure time control
>   media: i2c: imx290: Fix max gain value
>   media: i2c: imx290: Split control initialization to separate function
>   media: i2c: imx290: Implement HBLANK and VBLANK controls
>   media: i2c: imx290: Create controls for fwnode properties
>   media: i2c: imx290: Move registers with fixed value to init array
>   media: i2c: imx290: Factor out format retrieval to separate function
>   media: i2c: imx290: Add crop selection targets support
>   media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN
> 
>  drivers/media/i2c/imx290.c | 781 ++++++++++++++++++++++---------------
>  1 file changed, 458 insertions(+), 323 deletions(-)

-- 
Regards,

Laurent Pinchart

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

* Re: Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-08-23  1:08                   ` Laurent Pinchart
@ 2022-08-23  2:51                     ` Laurent Pinchart
  2022-08-23  7:19                       ` Alexander Stein
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-08-23  2:51 UTC (permalink / raw)
  To: Alexander Stein; +Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam

Hi Alexander,

On Tue, Aug 23, 2022 at 04:08:20AM +0300, Laurent Pinchart wrote:
> On Mon, Jul 25, 2022 at 08:49:40AM +0200, Alexander Stein wrote:
> > Am Sonntag, 24. Juli 2022, 01:06:29 CEST schrieb Laurent Pinchart:
> > > On Fri, Jul 22, 2022 at 05:37:53PM +0300, Sakari Ailus wrote:
> > > > On Thu, Jul 21, 2022 at 01:43:54PM +0200, Alexander Stein wrote:
> > > > ...
> > > > 
> > > > > Nice the following snippet does the trick already:
> > > > > ---8<---
> > > > > --- a/drivers/media/i2c/imx290.c
> > > > > +++ b/drivers/media/i2c/imx290.c
> > > > > @@ -221,6 +221,7 @@ static const struct imx290_pixfmt imx290_formats[] =
> > > > > {
> > > > >  static const struct regmap_config imx290_regmap_config = {
> > > > >         .reg_bits = 16,
> > > > >         .val_bits = 8,
> > > > > +       .use_single_read = true,
> > > > >  };
> > > > >  
> > > > >  static const char * const imx290_test_pattern_menu[] = {
> > > > > 
> > > > > ---8<---
> > > > > 
> > > > > As this affects the VC OV9281 as well, any suggestions for a common
> > > > > property?
> > > > 
> > > > If there's a 1:1 I²C mux in there between the host and the sensor, should
> > > > it be in DT as well? I'm not entirely certain it's necessary.
> > > 
> > > The microcontroller also the sensor clock and power supplies, so it has
> > > to be modelled in DT in any case. I was trying to avoid exposing it as
> > > an I2C mux, but maybe we'll have to bite the bullet...
> > 
> > What is the benefit about exposing a I2C mux? The needed regmap config option 
> > is configured completely independent to this.
> 
> If the I2C mux in the camera module messes up I2C transfers, the related
> quirks need to be handled somewhere, and a specific mux driver device in
> DT could be a good place to report that. There may be other options
> though.
> 
> > > I've implement support for two camera modules from Vision Components but
> > > haven't submitted patches yet. See [1] and [2] for DT examples and [3]
> > > for the driver that handles the microcontroller.
> > > 
> > > Note that one purpose of the microcontroller is to configure the sensor
> > > automatically. It can be queried through I2C for a list of supported
> > > modes, and it can also reconfigure the sensor fully when a mode is
> > > selected. This is meant to enable development of a single driver that
> > > will cover all modules, regardless of which camera sensor it integrates.
> > > I'm not sure what words you will use to voice your opinion on this
> > > design, but I think I already agree :-)
> > > 
> > > [1] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx296.dts
> > > [2] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx327.dts
> > > [3] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/drivers/media/i2c/vc-mipi.c
> > > 
> > > > The property could be called e.g. "single-octet-read". I think this should
> > > > probably be documented in I²C bindings (or even regmap).
> > > 
> > > I like the idea of making it a DT property global to all I2C devices. It
> > > should ideally be parsed by the I2C core or by regmap.
> > 
> > I agree with adding this as a regmap option, like 'big-endian' & friends, but 
> > not so much for I2C core. IMHO the core should only be interested in handling 
> > messages and transfers. Setting up those correctly is a matter for drivers 
> > (which in turn use regmap).
> 
> I don't want to polute a large number of sensor drivers because of
> questionable design decisions of a particular module vendor. This type
> of quirk needs to be handled outside of the sensor driver.

Given that the chip ID is only read to print it to the kernel log, and
that an incorrectly read ID will not prevent the driver from probing or
affect its behaviour in any way, would you object to merging this patch,
with the single read issue to support the Vision Components module being
handled later ?

-- 
Regards,

Laurent Pinchart

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

* Re: Re: Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-08-23  2:51                     ` Laurent Pinchart
@ 2022-08-23  7:19                       ` Alexander Stein
  2022-10-16  5:36                         ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Alexander Stein @ 2022-08-23  7:19 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam

Hello Laurent,

Am Dienstag, 23. August 2022, 04:51:20 CEST schrieb Laurent Pinchart:
> Hi Alexander,
> 
> On Tue, Aug 23, 2022 at 04:08:20AM +0300, Laurent Pinchart wrote:
> > On Mon, Jul 25, 2022 at 08:49:40AM +0200, Alexander Stein wrote:
> > > Am Sonntag, 24. Juli 2022, 01:06:29 CEST schrieb Laurent Pinchart:
> > > > On Fri, Jul 22, 2022 at 05:37:53PM +0300, Sakari Ailus wrote:
> > > > > On Thu, Jul 21, 2022 at 01:43:54PM +0200, Alexander Stein wrote:
> > > > > ...
> > > > > 
> > > > > > Nice the following snippet does the trick already:
> > > > > > ---8<---
> > > > > > --- a/drivers/media/i2c/imx290.c
> > > > > > +++ b/drivers/media/i2c/imx290.c
> > > > > > @@ -221,6 +221,7 @@ static const struct imx290_pixfmt
> > > > > > imx290_formats[] =
> > > > > > {
> > > > > > 
> > > > > >  static const struct regmap_config imx290_regmap_config = {
> > > > > >  
> > > > > >         .reg_bits = 16,
> > > > > >         .val_bits = 8,
> > > > > > 
> > > > > > +       .use_single_read = true,
> > > > > > 
> > > > > >  };
> > > > > >  
> > > > > >  static const char * const imx290_test_pattern_menu[] = {
> > > > > > 
> > > > > > ---8<---
> > > > > > 
> > > > > > As this affects the VC OV9281 as well, any suggestions for a
> > > > > > common
> > > > > > property?
> > > > > 
> > > > > If there's a 1:1 I²C mux in there between the host and the sensor,
> > > > > should
> > > > > it be in DT as well? I'm not entirely certain it's necessary.
> > > > 
> > > > The microcontroller also the sensor clock and power supplies, so it
> > > > has
> > > > to be modelled in DT in any case. I was trying to avoid exposing it as
> > > > an I2C mux, but maybe we'll have to bite the bullet...
> > > 
> > > What is the benefit about exposing a I2C mux? The needed regmap config
> > > option is configured completely independent to this.
> > 
> > If the I2C mux in the camera module messes up I2C transfers, the related
> > quirks need to be handled somewhere, and a specific mux driver device in
> > DT could be a good place to report that. There may be other options
> > though.

From a logical point of view, a i2c mux seems to be correct, but in the end 
this quirk is handled by regmap which parses device specific properties.
Adding a (mux) bus property which is applied to all devices seems to be a 
hassle, IMHO.
Taking Sakari's suggestion of 'single-octet-read' property where in the DT 
bindings this should be added?

> > > > I've implement support for two camera modules from Vision Components
> > > > but
> > > > haven't submitted patches yet. See [1] and [2] for DT examples and [3]
> > > > for the driver that handles the microcontroller.
> > > > 
> > > > Note that one purpose of the microcontroller is to configure the
> > > > sensor
> > > > automatically. It can be queried through I2C for a list of supported
> > > > modes, and it can also reconfigure the sensor fully when a mode is
> > > > selected. This is meant to enable development of a single driver that
> > > > will cover all modules, regardless of which camera sensor it
> > > > integrates.
> > > > I'm not sure what words you will use to voice your opinion on this
> > > > design, but I think I already agree :-)
> > > > 
> > > > [1]
> > > > https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/
> > > > isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx296.dts
> > > > [2]
> > > > https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/
> > > > isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx327.dts
> > > > [3]
> > > > https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/
> > > > isp/next/drivers/media/i2c/vc-mipi.c> > > 
> > > > > The property could be called e.g. "single-octet-read". I think this
> > > > > should
> > > > > probably be documented in I²C bindings (or even regmap).
> > > > 
> > > > I like the idea of making it a DT property global to all I2C devices.
> > > > It
> > > > should ideally be parsed by the I2C core or by regmap.
> > > 
> > > I agree with adding this as a regmap option, like 'big-endian' &
> > > friends, but not so much for I2C core. IMHO the core should only be
> > > interested in handling messages and transfers. Setting up those
> > > correctly is a matter for drivers (which in turn use regmap).
> > 
> > I don't want to polute a large number of sensor drivers because of
> > questionable design decisions of a particular module vendor. This type
> > of quirk needs to be handled outside of the sensor driver.
> 
> Given that the chip ID is only read to print it to the kernel log, and
> that an incorrectly read ID will not prevent the driver from probing or
> affect its behaviour in any way, would you object to merging this patch,
> with the single read issue to support the Vision Components module being
> handled later ?

No objection here. This problem is and should stay outside of the sensor 
driver. VC platform integration is an additional step.

Best regards,
Alexander




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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-08-23  1:11 ` [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
@ 2022-10-10 10:31   ` Dave Stevenson
  2022-10-16  5:37     ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Dave Stevenson @ 2022-10-10 10:31 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam

Hi Laurent

Do you have plans for a v2 on this patch set? I also have a number of
patches for imx290 and there's little point in causing grief to each
other with conflicts.
Or I could take the non-controversial patches from your set and send a
combined patch set?

Thanks
  Dave

On Tue, 23 Aug 2022 at 02:12, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Sakari,
>
> Could you already pick up patches 01/19, 02/19, 04/19, 05/19 and 06/19
> in your tree ? Your opinion on 03/19 woud be appreciated too, I think
> it's a candidate for merge as well.
>
> On Thu, Jul 21, 2022 at 11:35:21AM +0300, Laurent Pinchart wrote:
> > Hello,
> >
> > This patch series gathers miscellaneous improvements for the imx290
> > driver. The most notable changes on the kernel side is patch 07/19 that
> > simplifies register access, and on the userspace API side patches 14/19,
> > 15/19 and 18/19 that extend the driver with controls and selection
> > rectangles required by libcamera.
> >
> > Laurent Pinchart (19):
> >   media: i2c: imx290: Use device lock for the control handler
> >   media: i2c: imx290: Print error code when I2C transfer fails
> >   media: i2c: imx290: Specify HMAX values in decimal
> >   media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
> >   media: i2c: imx290: Drop imx290_write_buffered_reg()
> >   media: i2c: imx290: Drop regmap cache
> >   media: i2c: imx290: Support variable-sized registers
> >   media: i2c: imx290: Correct register sizes
> >   media: i2c: imx290: Simplify error handling when writing registers
> >   media: i2c: imx290: Define more register macros
> >   media: i2c: imx290: Add exposure time control
> >   media: i2c: imx290: Fix max gain value
> >   media: i2c: imx290: Split control initialization to separate function
> >   media: i2c: imx290: Implement HBLANK and VBLANK controls
> >   media: i2c: imx290: Create controls for fwnode properties
> >   media: i2c: imx290: Move registers with fixed value to init array
> >   media: i2c: imx290: Factor out format retrieval to separate function
> >   media: i2c: imx290: Add crop selection targets support
> >   media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN
> >
> >  drivers/media/i2c/imx290.c | 781 ++++++++++++++++++++++---------------
> >  1 file changed, 458 insertions(+), 323 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart

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

* Re: Re: [PATCH 10/19] media: i2c: imx290: Define more register macros
  2022-07-21 11:28       ` Alexander Stein
@ 2022-10-16  4:27         ` Laurent Pinchart
  0 siblings, 0 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-10-16  4:27 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

On Thu, Jul 21, 2022 at 01:28:34PM +0200, Alexander Stein wrote:
> Am Donnerstag, 21. Juli 2022, 13:08:05 CEST schrieb Laurent Pinchart:
> > On Thu, Jul 21, 2022 at 12:00:55PM +0200, Alexander Stein wrote:
> > > Am Donnerstag, 21. Juli 2022, 10:35:31 CEST schrieb Laurent Pinchart:
> > > > Define macros for all registers programmed by the driver for which
> > > > documentation is available to increase readability. This starts making
> > > > use of 16-bit registers in the register arrays, so the value field has
> > > > to be increased to 32 bits.
> > > > 
> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > ---
> > > > 
> > > >  drivers/media/i2c/imx290.c | 219 +++++++++++++++++++++----------------
> > > >  1 file changed, 124 insertions(+), 95 deletions(-)
> > > > 
> > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > index 5b7f9027b50f..bec326a83952 100644
> > > > --- a/drivers/media/i2c/imx290.c
> > > > +++ b/drivers/media/i2c/imx290.c
> > > > @@ -31,14 +31,73 @@
> > > >  #define IMX290_STANDBY					 IMX290_REG_8BIT(0x3000)
> > > >  #define IMX290_REGHOLD					 IMX290_REG_8BIT(0x3001)
> > > >  #define IMX290_XMSTA					 IMX290_REG_8BIT(0x3002)
> > > > +#define IMX290_ADBIT					 IMX290_REG_8BIT(0x3005)
> > > > +#define IMX290_ADBIT_10BIT				(0 << 0)
> > > > +#define IMX290_ADBIT_12BIT				(1 << 0)
> > > > +#define IMX290_CTRL_07					 IMX290_REG_8BIT(0x3007)
> > > > +#define IMX290_VREVERSE					 BIT(0)
> > > > +#define IMX290_HREVERSE					 BIT(1)
> > > > +#define IMX290_WINMODE_1080P				 (0 << 4)
> > > > +#define IMX290_WINMODE_720P				 (1 << 4)
> > > > +#define IMX290_WINMODE_CROP				 (4 << 4)
> > > >  #define IMX290_FR_FDG_SEL				 IMX290_REG_8BIT(0x3009)
> > > >  #define IMX290_BLKLEVEL					 IMX290_REG_16BIT(0x300a)
> > > >  #define IMX290_GAIN					 IMX290_REG_8BIT(0x3014)
> > > > +#define IMX290_VMAX					 IMX290_REG_24BIT(0x3018)
> > > >  #define IMX290_HMAX					 IMX290_REG_16BIT(0x301c)
> > > > +#define IMX290_SHS1					 IMX290_REG_24BIT(0x3020)
> > > > +#define IMX290_WINWV_OB					 IMX290_REG_8BIT(0x303a)
> > > > +#define IMX290_WINPV					 IMX290_REG_16BIT(0x303c)
> > > > +#define IMX290_WINWV					 IMX290_REG_16BIT(0x303e)
> > > > +#define IMX290_WINPH					 IMX290_REG_16BIT(0x3040)
> > > > +#define IMX290_WINWH					 IMX290_REG_16BIT(0x3042)
> > > > +#define IMX290_OUT_CTRL					 IMX290_REG_8BIT(0x3046)
> > > > +#define IMX290_ODBIT_10BIT				(0 << 0)
> > > > +#define IMX290_ODBIT_12BIT				(1 << 0)
> > > 
> > > ODBIT is fixed 1h for MIPI-CSI-2 output.
> > > 
> > > > +#define IMX290_OPORTSEL_PARALLEL			(0x0 << 4)
> > > > +#define IMX290_OPORTSEL_LVDS_2CH			(0xd << 4)
> > > > +#define IMX290_OPORTSEL_LVDS_4CH			(0xe << 4)
> > > > +#define IMX290_OPORTSEL_LVDS_8CH			(0xf << 4)
> > > 
> > > This driver only supports MIPI-CSI-2 output, but these bits are don't care,
> > > you still want to list them here for completeness?
> > 
> > Yes, it could be useful later.
> 
> Ok, fine with me.
> 
> > > > +#define IMX290_XSOUTSEL					 IMX290_REG_8BIT(0x304b)
> > > > +#define IMX290_XSOUTSEL_XVSOUTSEL_HIGH			 (0 << 0)
> > > > +#define IMX290_XSOUTSEL_XVSOUTSEL_VSYNC			 (2 << 0)
> > > > +#define IMX290_XSOUTSEL_XHSOUTSEL_HIGH			 (0 << 2)
> > > > +#define IMX290_XSOUTSEL_XHSOUTSEL_HSYNC			 (2 << 2)
> > > > +#define IMX290_INCKSEL1					 IMX290_REG_8BIT(0x305c)
> > > > +#define IMX290_INCKSEL2					 IMX290_REG_8BIT(0x305d)
> > > > +#define IMX290_INCKSEL3					 IMX290_REG_8BIT(0x305e)
> > > > +#define IMX290_INCKSEL4					 IMX290_REG_8BIT(0x305f)
> > > >  #define IMX290_PGCTRL					 IMX290_REG_8BIT(0x308c)
> > > > +#define IMX290_ADBIT1					 IMX290_REG_8BIT(0x3129)
> > > > +#define IMX290_ADBIT1_10BIT				 0x1d
> > > > +#define IMX290_ADBIT1_12BIT				 0x00
> > > > +#define IMX290_INCKSEL5					 IMX290_REG_8BIT(0x315e)
> > > > +#define IMX290_INCKSEL6					 IMX290_REG_8BIT(0x3164)
> > > 
> > > Any reason to skip the bit defines for both supported input clocks?
> > 
> > I don't have access to information that describes the bits in those two
> > registers, just magic values for the 37.125 MHz and 74.25 MHz input
> > clocks. Would you happen to know more ?
> 
> See [1] and line 354 as well. This register is depending on the external 
> clock.
> 
> [1] https://github.com/tq-systems/linux-tqmaxx/blob/TQMa8-fslc-5.10-2.1.x-imx/drivers/media/i2c/imx290.c#L344

Right, but I don't know what those values mean. I'm defining in this
patch macros for register addresses and bits that have a known name.
Magic values are left as hex constants in the register arrays or code. A
subsequent patch could address that if desired.

> > > > +#define IMX290_ADBIT2					 IMX290_REG_8BIT(0x317c)
> > > > +#define IMX290_ADBIT2_10BIT				 0x12
> > > > +#define IMX290_ADBIT2_12BIT				 0x00
> > > >  #define IMX290_CHIP_ID					 IMX290_REG_16BIT(0x319a)
> > > > +#define IMX290_ADBIT3					 IMX290_REG_16BIT(0x31ec)
> > > > +#define IMX290_ADBIT3_10BIT				 0x37
> > > > +#define IMX290_ADBIT3_12BIT				 0x0e
> > > > +#define IMX290_REPETITION				 IMX290_REG_8BIT(0x3405)
> > > >  #define IMX290_PHY_LANE_NUM				 IMX290_REG_8BIT(0x3407)
> > > > +#define IMX290_OPB_SIZE_V				 IMX290_REG_8BIT(0x3414)
> > > > +#define IMX290_Y_OUT_SIZE				 IMX290_REG_16BIT(0x3418)
> > > > +#define IMX290_CSI_DT_FMT				 IMX290_REG_16BIT(0x3441)
> > > > +#define IMX290_CSI_DT_FMT_RAW10				 0x0a0a
> > > > +#define IMX290_CSI_DT_FMT_RAW12				 0x0c0c
> > > >  #define IMX290_CSI_LANE_MODE				 IMX290_REG_8BIT(0x3443)
> > > > +#define IMX290_EXTCK_FREQ				 IMX290_REG_16BIT(0x3444)
> > > 
> > > Same here.
> > 
> > Same explanation as above :-)
> 
> This register also depends on external clock, see [2] and line 228 as well.
> 
> [2] https://github.com/tq-systems/linux-tqmaxx/blob/TQMa8-fslc-5.10-2.1.x-imx/drivers/media/i2c/imx290.c#L218
> 
> > > > +#define IMX290_TCLKPOST					 IMX290_REG_16BIT(0x3446)
> > > > +#define IMX290_THSZERO					 IMX290_REG_16BIT(0x3448)
> > > > +#define IMX290_THSPREPARE				 IMX290_REG_16BIT(0x344a)
> > > > +#define IMX290_TCLKTRAIL				 IMX290_REG_16BIT(0x344c)
> > > > +#define IMX290_THSTRAIL					 IMX290_REG_16BIT(0x344e)
> > > > +#define IMX290_TCLKZERO					 IMX290_REG_16BIT(0x3450)
> > > > +#define IMX290_TCLKPREPARE				 IMX290_REG_16BIT(0x3452)
> > > > +#define IMX290_TLPX					 IMX290_REG_16BIT(0x3454)
> > > > +#define IMX290_X_OUT_SIZE				 IMX290_REG_16BIT(0x3472)
> > > > 
> > > >  #define IMX290_PGCTRL_REGEN				 BIT(0)
> > > >  #define IMX290_PGCTRL_THRU				BIT(1)
> > > > 
> > > > @@ -54,7 +113,7 @@ static const char * const imx290_supply_name[] = {
> > > > 
> > > >  struct imx290_regval {
> > > >  	u32 reg;
> > > > -	u8 val;
> > > > +	u32 val;
> > > >  };
> > > >  
> > > >  struct imx290_mode {
> > > > @@ -116,22 +175,16 @@ static const char * const imx290_test_pattern_menu[] = { };
> > > > 
> > > >  static const struct imx290_regval imx290_global_init_settings[] = {
> > > > 
> > > > -	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3018), 0x65 },
> > > > -	{ IMX290_REG_8BIT(0x3019), 0x04 },
> > > > -	{ IMX290_REG_8BIT(0x301a), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3444), 0x20 },
> > > > -	{ IMX290_REG_8BIT(0x3445), 0x25 },
> > > > -	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > > -	{ IMX290_REG_8BIT(0x3040), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3041), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x303c), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x303d), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3042), 0x9c },
> > > > -	{ IMX290_REG_8BIT(0x3043), 0x07 },
> > > > -	{ IMX290_REG_8BIT(0x303e), 0x49 },
> > > > -	{ IMX290_REG_8BIT(0x303f), 0x04 },
> > > > -	{ IMX290_REG_8BIT(0x304b), 0x0a },
> > > > +	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> > > > +	{ IMX290_VMAX, 1125 },
> > > > +	{ IMX290_EXTCK_FREQ, 0x2520 },
> > > > +	{ IMX290_WINWV_OB, 12 },
> > > > +	{ IMX290_WINPH, 0 },
> > > > +	{ IMX290_WINPV, 0 },
> > > > +	{ IMX290_WINWH, 1948 },
> > > > +	{ IMX290_WINWV, 1097 },
> > > > +	{ IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
> > > > +			   IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
> > > >  	{ IMX290_REG_8BIT(0x300f), 0x00 },
> > > >  	{ IMX290_REG_8BIT(0x3010), 0x21 },
> > > >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > > @@ -177,102 +230,78 @@ static const struct imx290_regval imx290_global_init_settings[] = {
> > > > 
> > > >  static const struct imx290_regval imx290_1080p_settings[] = {
> > > >  	/* mode settings */
> > > > -	{ IMX290_REG_8BIT(0x3007), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x303a), 0x0c },
> > > > -	{ IMX290_REG_8BIT(0x3414), 0x0a },
> > > > -	{ IMX290_REG_8BIT(0x3472), 0x80 },
> > > > -	{ IMX290_REG_8BIT(0x3473), 0x07 },
> > > > -	{ IMX290_REG_8BIT(0x3418), 0x38 },
> > > > -	{ IMX290_REG_8BIT(0x3419), 0x04 },
> > > > +	{ IMX290_CTRL_07, IMX290_WINMODE_1080P },
> > > > +	{ IMX290_WINWV_OB, 12 },
> > > > +	{ IMX290_OPB_SIZE_V, 10 },
> > > > +	{ IMX290_X_OUT_SIZE, 1920 },
> > > > +	{ IMX290_Y_OUT_SIZE, 1080 },
> > > >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > >  	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x305c), 0x18 },
> > > > -	{ IMX290_REG_8BIT(0x305d), 0x03 },
> > > > -	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > > -	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > > -	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > > -	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > > +	{ IMX290_INCKSEL1, 0x18 },
> > > > +	{ IMX290_INCKSEL2, 0x03 },
> > > > +	{ IMX290_INCKSEL3, 0x20 },
> > > > +	{ IMX290_INCKSEL4, 0x01 },
> > > > +	{ IMX290_INCKSEL5, 0x1a },
> > > > +	{ IMX290_INCKSEL6, 0x1a },
> > > >  	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > >  	/* data rate settings */
> > > > -	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > > -	{ IMX290_REG_8BIT(0x3446), 0x57 },
> > > > -	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3448), 0x37 },
> > > > -	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x344a), 0x1f },
> > > > -	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x344c), 0x1f },
> > > > -	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x344e), 0x1f },
> > > > -	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3450), 0x77 },
> > > > -	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3452), 0x1f },
> > > > -	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > > -	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > > +	{ IMX290_REPETITION, 0x10 },
> > > > +	{ IMX290_TCLKPOST, 87 },
> > > > +	{ IMX290_THSZERO, 55 },
> > > > +	{ IMX290_THSPREPARE, 31 },
> > > > +	{ IMX290_TCLKTRAIL, 31 },
> > > > +	{ IMX290_THSTRAIL, 31 },
> > > > +	{ IMX290_TCLKZERO, 119 },
> > > > +	{ IMX290_TCLKPREPARE, 31 },
> > > > +	{ IMX290_TLPX, 23 },
> > > >  };
> > > >  
> > > >  static const struct imx290_regval imx290_720p_settings[] = {
> > > >  	/* mode settings */
> > > > -	{ IMX290_REG_8BIT(0x3007), 0x10 },
> > > > -	{ IMX290_REG_8BIT(0x303a), 0x06 },
> > > > -	{ IMX290_REG_8BIT(0x3414), 0x04 },
> > > > -	{ IMX290_REG_8BIT(0x3472), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3473), 0x05 },
> > > > -	{ IMX290_REG_8BIT(0x3418), 0xd0 },
> > > > -	{ IMX290_REG_8BIT(0x3419), 0x02 },
> > > > +	{ IMX290_CTRL_07, IMX290_WINMODE_720P },
> > > > +	{ IMX290_WINWV_OB, 6 },
> > > > +	{ IMX290_OPB_SIZE_V, 4 },
> > > > +	{ IMX290_X_OUT_SIZE, 1280 },
> > > > +	{ IMX290_Y_OUT_SIZE, 720 },
> > > >  	{ IMX290_REG_8BIT(0x3012), 0x64 },
> > > >  	{ IMX290_REG_8BIT(0x3013), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x305c), 0x20 },
> > > > -	{ IMX290_REG_8BIT(0x305d), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x305e), 0x20 },
> > > > -	{ IMX290_REG_8BIT(0x305f), 0x01 },
> > > > -	{ IMX290_REG_8BIT(0x315e), 0x1a },
> > > > -	{ IMX290_REG_8BIT(0x3164), 0x1a },
> > > > +	{ IMX290_INCKSEL1, 0x20 },
> > > > +	{ IMX290_INCKSEL2, 0x00 },
> > > > +	{ IMX290_INCKSEL3, 0x20 },
> > > > +	{ IMX290_INCKSEL4, 0x01 },
> > > > +	{ IMX290_INCKSEL5, 0x1a },
> > > > +	{ IMX290_INCKSEL6, 0x1a },
> > > >  	{ IMX290_REG_8BIT(0x3480), 0x49 },
> > > >  	/* data rate settings */
> > > > -	{ IMX290_REG_8BIT(0x3405), 0x10 },
> > > > -	{ IMX290_REG_8BIT(0x3446), 0x4f },
> > > > -	{ IMX290_REG_8BIT(0x3447), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3448), 0x2f },
> > > > -	{ IMX290_REG_8BIT(0x3449), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x344a), 0x17 },
> > > > -	{ IMX290_REG_8BIT(0x344b), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x344c), 0x17 },
> > > > -	{ IMX290_REG_8BIT(0x344d), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x344e), 0x17 },
> > > > -	{ IMX290_REG_8BIT(0x344f), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3450), 0x57 },
> > > > -	{ IMX290_REG_8BIT(0x3451), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3452), 0x17 },
> > > > -	{ IMX290_REG_8BIT(0x3453), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x3454), 0x17 },
> > > > -	{ IMX290_REG_8BIT(0x3455), 0x00 },
> > > > +	{ IMX290_REPETITION, 0x10 },
> > > > +	{ IMX290_TCLKPOST, 79 },
> > > > +	{ IMX290_THSZERO, 47 },
> > > > +	{ IMX290_THSPREPARE, 23 },
> > > > +	{ IMX290_TCLKTRAIL, 23 },
> > > > +	{ IMX290_THSTRAIL, 23 },
> > > > +	{ IMX290_TCLKZERO, 87 },
> > > > +	{ IMX290_TCLKPREPARE, 23 },
> > > > +	{ IMX290_TLPX, 23 },
> > > >  };
> > > >  
> > > >  static const struct imx290_regval imx290_10bit_settings[] = {
> > > > -	{ IMX290_REG_8BIT(0x3005), 0x00},
> > > > -	{ IMX290_REG_8BIT(0x3046), 0x00},
> > > > -	{ IMX290_REG_8BIT(0x3129), 0x1d},
> > > > -	{ IMX290_REG_8BIT(0x317c), 0x12},
> > > > -	{ IMX290_REG_8BIT(0x31ec), 0x37},
> > > > -	{ IMX290_REG_8BIT(0x3441), 0x0a},
> > > > -	{ IMX290_REG_8BIT(0x3442), 0x0a},
> > > > -	{ IMX290_REG_8BIT(0x300a), 0x3c},
> > > > -	{ IMX290_REG_8BIT(0x300b), 0x00},
> > > > +	{ IMX290_ADBIT, IMX290_ADBIT_10BIT },
> > > > +	{ IMX290_OUT_CTRL, IMX290_ODBIT_10BIT },
> > > > +	{ IMX290_ADBIT1, IMX290_ADBIT1_10BIT },
> > > > +	{ IMX290_ADBIT2, IMX290_ADBIT2_10BIT },
> > > > +	{ IMX290_ADBIT3, IMX290_ADBIT3_10BIT },
> > > > +	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW10 },
> > > > +	{ IMX290_BLKLEVEL, 60 },
> > > >  };
> > > >  
> > > >  static const struct imx290_regval imx290_12bit_settings[] = {
> > > > -	{ IMX290_REG_8BIT(0x3005), 0x01 },
> > > > -	{ IMX290_REG_8BIT(0x3046), 0x01 },
> > > > -	{ IMX290_REG_8BIT(0x3129), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x317c), 0x00 },
> > > > -	{ IMX290_REG_8BIT(0x31ec), 0x0e },
> > > > -	{ IMX290_REG_8BIT(0x3441), 0x0c },
> > > > -	{ IMX290_REG_8BIT(0x3442), 0x0c },
> > > > -	{ IMX290_REG_8BIT(0x300a), 0xf0 },
> > > > -	{ IMX290_REG_8BIT(0x300b), 0x00 },
> > > > +	{ IMX290_ADBIT, IMX290_ADBIT_12BIT },
> > > > +	{ IMX290_OUT_CTRL, IMX290_ODBIT_12BIT },
> > > > +	{ IMX290_ADBIT1, IMX290_ADBIT1_12BIT },
> > > > +	{ IMX290_ADBIT2, IMX290_ADBIT2_12BIT },
> > > > +	{ IMX290_ADBIT3, IMX290_ADBIT3_12BIT },
> > > > +	{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW12 },
> > > > +	{ IMX290_BLKLEVEL, 240 },
> > > >  };
> > > >  
> > > >  /* supported link frequencies */

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 12/19] media: i2c: imx290: Fix max gain value
  2022-07-21 16:08   ` Dave Stevenson
@ 2022-10-16  4:51     ` Laurent Pinchart
  0 siblings, 0 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-10-16  4:51 UTC (permalink / raw)
  To: Dave Stevenson; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Dave,

On Thu, Jul 21, 2022 at 05:08:37PM +0100, Dave Stevenson wrote:
> On Thu, 21 Jul 2022 at 09:36, Laurent Pinchart wrote:
> >
> > The gain is expressed in multiple of 0.3dB, as a value between 0.0dB
> > and 72.0dB. The maximum value is thus 240, not 72.
> 
> At this point in the series I'll agree with you as it is for V4L2_CID_GAIN.
> However later in the series you convert to V4L2_CID_ANALOGUE_GAIN, and
> there I disagree.
> 
> The register is for a combined 0-30dB of analogue gain, and 0-42dB of
> digital gain, both in 0.3dB steps.
> V4L2_CID_GAIN can have a range of 0-240.
> V4L2_CID_ANALOGUE_GAIN has a range of 0-100.

Good point, I had missed that. I'll fix it.

> Minor additional point: IMX327 is the previous version of this and
> only goes up to 1080p60 instead of 1080p120 (10bit only). That
> supports 0-29.4dB of analogue gain, and 42dB of digital gain, for a
> max value of 238. If using the definition for analogue gain only, then
> you may end up with 0.6dB of digital gain instead, but it will work.
> IMX462 is the newer version and supports 1080p120 in 10 or 12bit. I
> don't have a full datasheet for it, but the product brief lists
> 0-29.4dB of analogue, and 42dB of digital gain, same as IMX327.
> Seeing as the 120fps modes are not implemented in this driver, it
> currently supports all 3 models.

Why does it have to be so complicated ? :-) I'll see what I can do.

> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/i2c/imx290.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index 3cb024b73ee7..1bd464932432 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -1020,7 +1020,7 @@ static int imx290_probe(struct i2c_client *client)
> >         imx290->ctrls.lock = &imx290->lock;
> >
> >         v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > -                         V4L2_CID_GAIN, 0, 72, 1, 0);
> > +                         V4L2_CID_GAIN, 0, 240, 1, 0);
> >
> >         v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> >                           V4L2_CID_EXPOSURE, 1, IMX290_VMAX_DEFAULT - 2, 1,

-- 
Regards,

Laurent Pinchart

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

* Re: Re: Re: Re: [PATCH 07/19] media: i2c: imx290: Support variable-sized registers
  2022-08-23  7:19                       ` Alexander Stein
@ 2022-10-16  5:36                         ` Laurent Pinchart
  0 siblings, 0 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-10-16  5:36 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam, Wolfram Sang

Hi Alexander,

CC'ing Wolfram.

On Tue, Aug 23, 2022 at 09:19:36AM +0200, Alexander Stein wrote:
> Am Dienstag, 23. August 2022, 04:51:20 CEST schrieb Laurent Pinchart:
> > On Tue, Aug 23, 2022 at 04:08:20AM +0300, Laurent Pinchart wrote:
> > > On Mon, Jul 25, 2022 at 08:49:40AM +0200, Alexander Stein wrote:
> > > > Am Sonntag, 24. Juli 2022, 01:06:29 CEST schrieb Laurent Pinchart:
> > > > > On Fri, Jul 22, 2022 at 05:37:53PM +0300, Sakari Ailus wrote:
> > > > > > On Thu, Jul 21, 2022 at 01:43:54PM +0200, Alexander Stein wrote:
> > > > > > ...
> > > > > > 
> > > > > > > Nice the following snippet does the trick already:
> > > > > > > ---8<---
> > > > > > > --- a/drivers/media/i2c/imx290.c
> > > > > > > +++ b/drivers/media/i2c/imx290.c
> > > > > > > @@ -221,6 +221,7 @@ static const struct imx290_pixfmt imx290_formats[] =
> > > > > > > {
> > > > > > >  static const struct regmap_config imx290_regmap_config = {
> > > > > > >         .reg_bits = 16,
> > > > > > >         .val_bits = 8,
> > > > > > > +       .use_single_read = true,
> > > > > > >  };
> > > > > > >  
> > > > > > >  static const char * const imx290_test_pattern_menu[] = {
> > > > > > > ---8<---
> > > > > > > 
> > > > > > > As this affects the VC OV9281 as well, any suggestions for a common
> > > > > > > property?
> > > > > > 
> > > > > > If there's a 1:1 I²C mux in there between the host and the sensor, should
> > > > > > it be in DT as well? I'm not entirely certain it's necessary.
> > > > > 
> > > > > The microcontroller also the sensor clock and power supplies, so it has
> > > > > to be modelled in DT in any case. I was trying to avoid exposing it as
> > > > > an I2C mux, but maybe we'll have to bite the bullet...
> > > > 
> > > > What is the benefit about exposing a I2C mux? The needed regmap config
> > > > option is configured completely independent to this.
> > > 
> > > If the I2C mux in the camera module messes up I2C transfers, the related
> > > quirks need to be handled somewhere, and a specific mux driver device in
> > > DT could be a good place to report that. There may be other options
> > > though.
> 
> From a logical point of view, a i2c mux seems to be correct, but in the end 
> this quirk is handled by regmap which parses device specific properties.
> Adding a (mux) bus property which is applied to all devices seems to be a 
> hassle, IMHO.
> Taking Sakari's suggestion of 'single-octet-read' property where in the DT 
> bindings this should be added?

Wolfram, any opinion on this ? More context is available earlier in this
mail thread, but tl;dr, the camera module vendor has interposed a
microcontroller between the host and the camera sensor on the I2C bus,
and it messes up I2C reads by breaking auto-increment (it also disallows
reading everything but a small set of white-listed registers). Writes go
through without a problem.

> > > > > I've implement support for two camera modules from Vision Components but
> > > > > haven't submitted patches yet. See [1] and [2] for DT examples and [3]
> > > > > for the driver that handles the microcontroller.
> > > > > 
> > > > > Note that one purpose of the microcontroller is to configure the sensor
> > > > > automatically. It can be queried through I2C for a list of supported
> > > > > modes, and it can also reconfigure the sensor fully when a mode is
> > > > > selected. This is meant to enable development of a single driver that
> > > > > will cover all modules, regardless of which camera sensor it integrates.
> > > > > I'm not sure what words you will use to voice your opinion on this
> > > > > design, but I think I already agree :-)
> > > > > 
> > > > > [1] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx296.dts
> > > > > [2] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/arch/arm64/boot/dts/freescale/imx8mp-maivin-csi1-imx327.dts
> > > > > [3] https://gitlab.com/ideasonboard/nxp/linux/-/blob/pinchartl/v5.19/dev/isp/next/drivers/media/i2c/vc-mipi.c
> > > > > 
> > > > > > The property could be called e.g. "single-octet-read". I think this should
> > > > > > probably be documented in I²C bindings (or even regmap).
> > > > > 
> > > > > I like the idea of making it a DT property global to all I2C devices. It
> > > > > should ideally be parsed by the I2C core or by regmap.
> > > > 
> > > > I agree with adding this as a regmap option, like 'big-endian' &
> > > > friends, but not so much for I2C core. IMHO the core should only be
> > > > interested in handling messages and transfers. Setting up those
> > > > correctly is a matter for drivers (which in turn use regmap).
> > > 
> > > I don't want to polute a large number of sensor drivers because of
> > > questionable design decisions of a particular module vendor. This type
> > > of quirk needs to be handled outside of the sensor driver.
> > 
> > Given that the chip ID is only read to print it to the kernel log, and
> > that an incorrectly read ID will not prevent the driver from probing or
> > affect its behaviour in any way, would you object to merging this patch,
> > with the single read issue to support the Vision Components module being
> > handled later ?
> 
> No objection here. This problem is and should stay outside of the sensor 
> driver. VC platform integration is an additional step.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-10-10 10:31   ` Dave Stevenson
@ 2022-10-16  5:37     ` Laurent Pinchart
  2022-10-16  7:34       ` Dave Stevenson
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-10-16  5:37 UTC (permalink / raw)
  To: Dave Stevenson; +Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam

Hi Dave,

On Mon, Oct 10, 2022 at 11:31:33AM +0100, Dave Stevenson wrote:
> Hi Laurent
> 
> Do you have plans for a v2 on this patch set? I also have a number of
> patches for imx290 and there's little point in causing grief to each
> other with conflicts.
> Or I could take the non-controversial patches from your set and send a
> combined patch set?

I'm working on a v2, I'll send it shortly. Do I assume correctly you'll
submit IMX327 support on top ? :-)

> On Tue, 23 Aug 2022 at 02:12, Laurent Pinchart wrote:
> >
> > Hi Sakari,
> >
> > Could you already pick up patches 01/19, 02/19, 04/19, 05/19 and 06/19
> > in your tree ? Your opinion on 03/19 woud be appreciated too, I think
> > it's a candidate for merge as well.
> >
> > On Thu, Jul 21, 2022 at 11:35:21AM +0300, Laurent Pinchart wrote:
> > > Hello,
> > >
> > > This patch series gathers miscellaneous improvements for the imx290
> > > driver. The most notable changes on the kernel side is patch 07/19 that
> > > simplifies register access, and on the userspace API side patches 14/19,
> > > 15/19 and 18/19 that extend the driver with controls and selection
> > > rectangles required by libcamera.
> > >
> > > Laurent Pinchart (19):
> > >   media: i2c: imx290: Use device lock for the control handler
> > >   media: i2c: imx290: Print error code when I2C transfer fails
> > >   media: i2c: imx290: Specify HMAX values in decimal
> > >   media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
> > >   media: i2c: imx290: Drop imx290_write_buffered_reg()
> > >   media: i2c: imx290: Drop regmap cache
> > >   media: i2c: imx290: Support variable-sized registers
> > >   media: i2c: imx290: Correct register sizes
> > >   media: i2c: imx290: Simplify error handling when writing registers
> > >   media: i2c: imx290: Define more register macros
> > >   media: i2c: imx290: Add exposure time control
> > >   media: i2c: imx290: Fix max gain value
> > >   media: i2c: imx290: Split control initialization to separate function
> > >   media: i2c: imx290: Implement HBLANK and VBLANK controls
> > >   media: i2c: imx290: Create controls for fwnode properties
> > >   media: i2c: imx290: Move registers with fixed value to init array
> > >   media: i2c: imx290: Factor out format retrieval to separate function
> > >   media: i2c: imx290: Add crop selection targets support
> > >   media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN
> > >
> > >  drivers/media/i2c/imx290.c | 781 ++++++++++++++++++++++---------------
> > >  1 file changed, 458 insertions(+), 323 deletions(-)

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/19] media: i2c: imx290: Add crop selection targets support
  2022-07-21 15:39   ` Dave Stevenson
@ 2022-10-16  5:53     ` Laurent Pinchart
  0 siblings, 0 replies; 81+ messages in thread
From: Laurent Pinchart @ 2022-10-16  5:53 UTC (permalink / raw)
  To: Dave Stevenson; +Cc: linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Dave,

On Thu, Jul 21, 2022 at 04:39:08PM +0100, Dave Stevenson wrote:
> On Thu, 21 Jul 2022 at 09:36, Laurent Pinchart wrote:
> > Implement read-only access to crop selection rectangles to expose the
> > analogue crop rectangle. The public (leaked) IMX290 documentation is not
> > very clear on how cropping is implemented and configured exactly, so
> > the margins may not be entirely accurate.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/media/i2c/imx290.c | 94 ++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 94 insertions(+)
> >
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index baf9941c5fbe..0cb11ec1cf0f 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -105,6 +105,53 @@
> >
> >  #define IMX290_VMAX_DEFAULT                            1125
> >
> > +
> > +/*
> > + * The IMX290 pixel array is organized as follows:
> > + *
> > + *     +------------------------------------+
> > + *     |           Optical Black            |     }  Vertical effective optical black (10)
> > + * +---+------------------------------------+---+
> > + * |   |                                    |   | }  Effective top margin (8)
> > + * |   |   +----------------------------+   |   | \
> > + * |   |   |                            |   |   |  |
> > + * |   |   |                            |   |   |  |
> > + * |   |   |                            |   |   |  |
> > + * |   |   |    Recording Pixel Area    |   |   |  | Recommended height (1080)
> > + * |   |   |                            |   |   |  |
> > + * |   |   |                            |   |   |  |
> > + * |   |   |                            |   |   |  |
> > + * |   |   +----------------------------+   |   | /
> > + * |   |                                    |   | }  Effective bottom margin (8)
> 
> I have an official datasheet from Sony. "Effective margin for colour
> processing" at the bottom is stated to be 9 lines, not 8. That also
> makes the numbers then tally of total height being 8 + 1080 + 9 =
> 1097.

Will fix in v2. The value in the text and macro is correct, only the
diagram has an issue.

> Otherwise I agree with the numbers you quote here.
> 
> My datasheet does go into how window mode is configured, however
> window mode is not being used.
> The register sets present in the driver set the output image size to
> 1920x1080 or 1280x720 of the overall 1945x1097 pixels. They differ
> slightly from the definitions given in the datasheet for the Full HD
> 1080p and HD720p modes which read out 1945x1097 and 1297x725 pixels
> respectively (assuming I've read it correctly). Exactly how those
> extra pixels are cropped off isn't defined, but I'd suspect it was the
> top left portion of the full image.
> 
> If you want 100% defined cropping for each mode then that should be
> achievable using window mode.

I'd like that, but one thing at a time :-) I may experiment if I can
find free time.

> > + * +---+------------------------------------+---+
> > + *  <-> <-> <--------------------------> <-> <->
> > + *                                            \----  Ignored right margin (4)
> > + *                                        \--------  Effective right margin (9)
> > + *                       \-------------------------  Recommended width (1920)
> > + *       \-----------------------------------------  Effective left margin (8)
> > + *   \---------------------------------------------  Ignored left margin (4)
> > + *
> > + * The optical black lines are output over CSI-2 with a separate data type.
> > + *
> > + * The pixel array is meant to have 1920x1080 usable pixels after image
> > + * processing in an ISP. It has 8 (9) extra active pixels usable for color
> > + * processing in the ISP on the top and left (bottom and right) sides of the
> > + * image. In addition, 4 additional pixels are present on the left and right
> > + * sides of the image, documented as "ignored area".
> > + *
> > + * As far as is understood, all pixels of the pixel array (ignored area, color
> > + * processing margins and recording area) can be output by the sensor.
> > + */
> > +
> > +#define IMX290_PIXEL_ARRAY_WIDTH                       1945
> > +#define IMX290_PIXEL_ARRAY_HEIGHT                      1097
> > +#define IMX920_PIXEL_ARRAY_MARGIN_LEFT                 12
> > +#define IMX920_PIXEL_ARRAY_MARGIN_RIGHT                        13
> > +#define IMX920_PIXEL_ARRAY_MARGIN_TOP                  8
> > +#define IMX920_PIXEL_ARRAY_MARGIN_BOTTOM               9
> > +#define IMX290_PIXEL_ARRAY_RECORDING_WIDTH             1920
> > +#define IMX290_PIXEL_ARRAY_RECORDING_HEIGHT            1080
> > +
> >  static const char * const imx290_supply_name[] = {
> >         "vdda",
> >         "vddd",
> > @@ -671,6 +718,52 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> >         return 0;
> >  }
> >
> > +static int imx290_get_selection(struct v4l2_subdev *sd,
> > +                               struct v4l2_subdev_state *sd_state,
> > +                               struct v4l2_subdev_selection *sel)
> > +{
> > +       struct imx290 *imx290 = to_imx290(sd);
> > +       struct v4l2_mbus_framefmt *format;
> > +
> > +       switch (sel->target) {
> > +       case V4L2_SEL_TGT_CROP: {
> > +               format = imx290_get_pad_format(imx290, sd_state, sel->which);
> > +
> > +               mutex_lock(&imx290->lock);
> > +
> > +               sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP
> > +                          + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2;
> > +               sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT
> > +                           + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2;
> > +               sel->r.width = format->width;
> > +               sel->r.height = format->height;
> > +
> > +               mutex_unlock(&imx290->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 = IMX290_PIXEL_ARRAY_WIDTH;
> > +               sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT;
> > +
> > +               return 0;
> > +
> > +       case V4L2_SEL_TGT_CROP_DEFAULT:
> > +               sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP;
> > +               sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT;
> > +               sel->r.width = IMX290_PIXEL_ARRAY_RECORDING_WIDTH;
> > +               sel->r.height = IMX290_PIXEL_ARRAY_RECORDING_HEIGHT;
> > +
> > +               return 0;
> > +
> > +       default:
> > +               return -EINVAL;
> > +       }
> > +}
> > +
> >  static int imx290_entity_init_cfg(struct v4l2_subdev *subdev,
> >                                   struct v4l2_subdev_state *sd_state)
> >  {
> > @@ -887,6 +980,7 @@ static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
> >         .enum_frame_size = imx290_enum_frame_size,
> >         .get_fmt = imx290_get_fmt,
> >         .set_fmt = imx290_set_fmt,
> > +       .get_selection = imx290_get_selection,
> >  };
> >
> >  static const struct v4l2_subdev_ops imx290_subdev_ops = {

-- 
Regards,

Laurent Pinchart

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

* Re: Re: [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls
  2022-07-21 16:37         ` Dave Stevenson
@ 2022-10-16  6:10           ` Laurent Pinchart
  2022-10-17 13:46             ` Dave Stevenson
  0 siblings, 1 reply; 81+ messages in thread
From: Laurent Pinchart @ 2022-10-16  6:10 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Alexander Stein, linux-media, Manivannan Sadhasivam, Sakari Ailus

Hello,

On Thu, Jul 21, 2022 at 05:37:23PM +0100, Dave Stevenson wrote:
> On Thu, 21 Jul 2022 at 12:32, Alexander Stein wrote:
> > Am Donnerstag, 21. Juli 2022, 13:17:21 CEST schrieb Laurent Pinchart:
> > > On Thu, Jul 21, 2022 at 12:05:46PM +0200, Alexander Stein wrote:
> > > > Am Donnerstag, 21. Juli 2022, 10:35:35 CEST schrieb Laurent Pinchart:
> > > > > Add support for the V4L2_CID_HBLANK and V4L2_CID_VBLANK controls to the
> > > > > imx290 driver. Make the controls read-only to start with, to report the
> > > > > values to userspace for timing calculation.
> > > > >
> > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > > ---
> > > > >
> > > > >  drivers/media/i2c/imx290.c | 39 +++++++++++++++++++++++++++++++++++++-
> > > > >  1 file changed, 38 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > > index 4408dd3e191f..7190399f4111 100644
> > > > > --- a/drivers/media/i2c/imx290.c
> > > > > +++ b/drivers/media/i2c/imx290.c
> > > > > @@ -146,6 +146,8 @@ struct imx290 {
> > > > >   struct v4l2_ctrl_handler ctrls;
> > > > >   struct v4l2_ctrl *link_freq;
> > > > >   struct v4l2_ctrl *pixel_rate;
> > > > > + struct v4l2_ctrl *hblank;
> > > > > + struct v4l2_ctrl *vblank;
> > > > >   struct mutex lock;
> > > > >  };
> > > > >
> > > > > @@ -642,6 +644,20 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> > > > >           if (imx290->pixel_rate)
> > > > >                   __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
> > > > >                                            imx290_calc_pixel_rate(imx290));
> > > > > +
> > > > > +         if (imx290->hblank) {
> > > > > +                 unsigned int hblank = mode->hmax - mode->width;
> > > > > +
> > > > > +                 __v4l2_ctrl_modify_range(imx290->hblank, hblank, hblank,
> > > > > +                                          1, hblank);
> > > > > +         }
> > > > > +
> > > > > +         if (imx290->vblank) {
> > > > > +                 unsigned int vblank = IMX290_VMAX_DEFAULT - mode->height;
> > > > > +
> > > > > +                 __v4l2_ctrl_modify_range(imx290->vblank, vblank, vblank,
> > > > > +                                          1, vblank);
> > > > > +         }
> > > > >   }
> > > > >
> > > > >   *format = fmt->format;
> > > > > @@ -880,9 +896,10 @@ static const struct media_entity_operations imx290_subdev_entity_ops = {
> > > > > 
> > > > >  static int imx290_ctrl_init(struct imx290 *imx290)
> > > > >  {
> > > > > + unsigned int blank;
> > > > >   int ret;
> > > > >
> > > > > - v4l2_ctrl_handler_init(&imx290->ctrls, 5);
> > > > > + v4l2_ctrl_handler_init(&imx290->ctrls, 7);
> > > > >   imx290->ctrls.lock = &imx290->lock;
> > > > >
> > > > >   v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > > > > @@ -910,6 +927,26 @@ static int imx290_ctrl_init(struct imx290 *imx290)
> > > > >                                ARRAY_SIZE(imx290_test_pattern_menu) - 1,
> > > > >                                0, 0, imx290_test_pattern_menu);
> > > > >
> > > > > + /*
> > > > > +  * Horizontal blanking is controlled through the HMAX register, which
> > > > > +  * contains a line length in INCK clock units. The INCK frequency is
> > > > > +  * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100,
> > > > > +  * convert it to a number of pixels based on the nominal pixel rate.
> > > > > +  */
> > > >
> > > > Currently the driver only supports 37.125 MHz, please refer to
> > > > imx290_probe.
> > > 
> > > Indeed. Re-reading the comment, I suspect something is wrong, as hmax is
> > > not converted to pixels here (and is also not fixed to 1100).

I'll drop the comment in v2.

> > > The only
> > > datasheet I found that is publicly accessed doesn't explain very clearly
> > > how the HMAX value should be computed. Based on your experience with IMX
> > > sensors, would you be able to shed some light on this ?
> 
> It is pretty much a standard HTS setting based on a pixel rate that is
> fixed at 148.5MPix/s.

I'm following you for HTS, but not for the fixed pixel rate. Could you
elaborate ?

> Likewise VMAX is equivalent to a traditional VTS.

Yes, that one is easy.

> I've been through the same path in
> https://github.com/raspberrypi/linux/commits/rpi-5.15.y/drivers/media/i2c/imx290.c
> 
> > Can you share the link to this datasheet you found?

https://static6.arrow.com/aropdfconversion/c0c7efde6571c768020a72f59b226308b9669e45/sony_imx290lqr-c_datasheet.pdf

> > Sorry, my experience is more like try and error. I don't fully understand this
> > as well, but apparently this depends on frame rate select (FRSEL).
> 
> FRSEL is the one difference between IMX327 and IMX290 (and presumably
> IMX462 too). IMX290 adds "0" as a valid value for 120/100fps mode.
> However there is no need to change FRSEL for standard frame rate
> control - you can set it at 0x01 and get a full range of frame rates
> through VMAX and HMAX. If you wished to extend that range for slower
> rates, you could conditionally set it to 0x2 to double the frame time.
> 
> > > > > + blank = imx290->current_mode->hmax - imx290->current_mode->width;
> > > > > + imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > > > > +                                    V4L2_CID_HBLANK, blank, blank, 1,
> > > > > +                                    blank);
> > > > > + if (imx290->hblank)
> > > > > +         imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > > > +
> > > > > + blank = IMX290_VMAX_DEFAULT - imx290->current_mode->height;
> > > > > + imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > > > > +                                    V4L2_CID_VBLANK, blank, blank, 1,
> > > > > +                                    blank);
> > > > > + if (imx290->vblank)
> > > > > +         imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > > > +
> > > > >
> > > > >   imx290->sd.ctrl_handler = &imx290->ctrls;
> > > > >
> > > > >   if (imx290->ctrls.error) {

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-10-16  5:37     ` Laurent Pinchart
@ 2022-10-16  7:34       ` Dave Stevenson
  2022-10-17 18:07         ` Dave Stevenson
  0 siblings, 1 reply; 81+ messages in thread
From: Dave Stevenson @ 2022-10-16  7:34 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam

Hi Laurent

On Sun, 16 Oct 2022 at 06:37, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Dave,
>
> On Mon, Oct 10, 2022 at 11:31:33AM +0100, Dave Stevenson wrote:
> > Hi Laurent
> >
> > Do you have plans for a v2 on this patch set? I also have a number of
> > patches for imx290 and there's little point in causing grief to each
> > other with conflicts.
> > Or I could take the non-controversial patches from your set and send a
> > combined patch set?
>
> I'm working on a v2, I'll send it shortly. Do I assume correctly you'll
> submit IMX327 support on top ? :-)

Thanks - I'll review it tomorrow and sort my patches on top again.

This driver is effectively IMX327 - max 1920x1080@60fps in 12 bit.

IMX290 adds a 1920x1080@120fps 10bit only mode which isn't currently
supported by the driver. I have patches to add 10bit support, but I
don't increase the frame rate in them.

IMX462 adds that 1920x1080@120fps mode in both 10 and 12 bit, but
again I haven't looked at adding support, partly as I don't have a
datasheet for that variant. I may see if the change for 120fps 10bit
on imx290 works in 12 bit mode for IMX462.
For IMX290, 1080p120 needs a link frequency of 445.5MHz on 4 lanes to
be supported (2 lanes not permitted), so there will be more link
frequency messing required to support it. The basic numbers say that
is fast enough for 12bit as well, so there's hope.

  Dave

> > On Tue, 23 Aug 2022 at 02:12, Laurent Pinchart wrote:
> > >
> > > Hi Sakari,
> > >
> > > Could you already pick up patches 01/19, 02/19, 04/19, 05/19 and 06/19
> > > in your tree ? Your opinion on 03/19 woud be appreciated too, I think
> > > it's a candidate for merge as well.
> > >
> > > On Thu, Jul 21, 2022 at 11:35:21AM +0300, Laurent Pinchart wrote:
> > > > Hello,
> > > >
> > > > This patch series gathers miscellaneous improvements for the imx290
> > > > driver. The most notable changes on the kernel side is patch 07/19 that
> > > > simplifies register access, and on the userspace API side patches 14/19,
> > > > 15/19 and 18/19 that extend the driver with controls and selection
> > > > rectangles required by libcamera.
> > > >
> > > > Laurent Pinchart (19):
> > > >   media: i2c: imx290: Use device lock for the control handler
> > > >   media: i2c: imx290: Print error code when I2C transfer fails
> > > >   media: i2c: imx290: Specify HMAX values in decimal
> > > >   media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
> > > >   media: i2c: imx290: Drop imx290_write_buffered_reg()
> > > >   media: i2c: imx290: Drop regmap cache
> > > >   media: i2c: imx290: Support variable-sized registers
> > > >   media: i2c: imx290: Correct register sizes
> > > >   media: i2c: imx290: Simplify error handling when writing registers
> > > >   media: i2c: imx290: Define more register macros
> > > >   media: i2c: imx290: Add exposure time control
> > > >   media: i2c: imx290: Fix max gain value
> > > >   media: i2c: imx290: Split control initialization to separate function
> > > >   media: i2c: imx290: Implement HBLANK and VBLANK controls
> > > >   media: i2c: imx290: Create controls for fwnode properties
> > > >   media: i2c: imx290: Move registers with fixed value to init array
> > > >   media: i2c: imx290: Factor out format retrieval to separate function
> > > >   media: i2c: imx290: Add crop selection targets support
> > > >   media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN
> > > >
> > > >  drivers/media/i2c/imx290.c | 781 ++++++++++++++++++++++---------------
> > > >  1 file changed, 458 insertions(+), 323 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart

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

* Re: Re: [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls
  2022-10-16  6:10           ` Laurent Pinchart
@ 2022-10-17 13:46             ` Dave Stevenson
  0 siblings, 0 replies; 81+ messages in thread
From: Dave Stevenson @ 2022-10-17 13:46 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Alexander Stein, linux-media, Manivannan Sadhasivam, Sakari Ailus

Hi Laurent

On Sun, 16 Oct 2022 at 07:11, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hello,
>
> On Thu, Jul 21, 2022 at 05:37:23PM +0100, Dave Stevenson wrote:
> > On Thu, 21 Jul 2022 at 12:32, Alexander Stein wrote:
> > > Am Donnerstag, 21. Juli 2022, 13:17:21 CEST schrieb Laurent Pinchart:
> > > > On Thu, Jul 21, 2022 at 12:05:46PM +0200, Alexander Stein wrote:
> > > > > Am Donnerstag, 21. Juli 2022, 10:35:35 CEST schrieb Laurent Pinchart:
> > > > > > Add support for the V4L2_CID_HBLANK and V4L2_CID_VBLANK controls to the
> > > > > > imx290 driver. Make the controls read-only to start with, to report the
> > > > > > values to userspace for timing calculation.
> > > > > >
> > > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > > > > ---
> > > > > >
> > > > > >  drivers/media/i2c/imx290.c | 39 +++++++++++++++++++++++++++++++++++++-
> > > > > >  1 file changed, 38 insertions(+), 1 deletion(-)
> > > > > >
> > > > > > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > > > > > index 4408dd3e191f..7190399f4111 100644
> > > > > > --- a/drivers/media/i2c/imx290.c
> > > > > > +++ b/drivers/media/i2c/imx290.c
> > > > > > @@ -146,6 +146,8 @@ struct imx290 {
> > > > > >   struct v4l2_ctrl_handler ctrls;
> > > > > >   struct v4l2_ctrl *link_freq;
> > > > > >   struct v4l2_ctrl *pixel_rate;
> > > > > > + struct v4l2_ctrl *hblank;
> > > > > > + struct v4l2_ctrl *vblank;
> > > > > >   struct mutex lock;
> > > > > >  };
> > > > > >
> > > > > > @@ -642,6 +644,20 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> > > > > >           if (imx290->pixel_rate)
> > > > > >                   __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
> > > > > >                                            imx290_calc_pixel_rate(imx290));
> > > > > > +
> > > > > > +         if (imx290->hblank) {
> > > > > > +                 unsigned int hblank = mode->hmax - mode->width;
> > > > > > +
> > > > > > +                 __v4l2_ctrl_modify_range(imx290->hblank, hblank, hblank,
> > > > > > +                                          1, hblank);
> > > > > > +         }
> > > > > > +
> > > > > > +         if (imx290->vblank) {
> > > > > > +                 unsigned int vblank = IMX290_VMAX_DEFAULT - mode->height;
> > > > > > +
> > > > > > +                 __v4l2_ctrl_modify_range(imx290->vblank, vblank, vblank,
> > > > > > +                                          1, vblank);
> > > > > > +         }
> > > > > >   }
> > > > > >
> > > > > >   *format = fmt->format;
> > > > > > @@ -880,9 +896,10 @@ static const struct media_entity_operations imx290_subdev_entity_ops = {
> > > > > >
> > > > > >  static int imx290_ctrl_init(struct imx290 *imx290)
> > > > > >  {
> > > > > > + unsigned int blank;
> > > > > >   int ret;
> > > > > >
> > > > > > - v4l2_ctrl_handler_init(&imx290->ctrls, 5);
> > > > > > + v4l2_ctrl_handler_init(&imx290->ctrls, 7);
> > > > > >   imx290->ctrls.lock = &imx290->lock;
> > > > > >
> > > > > >   v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > > > > > @@ -910,6 +927,26 @@ static int imx290_ctrl_init(struct imx290 *imx290)
> > > > > >                                ARRAY_SIZE(imx290_test_pattern_menu) - 1,
> > > > > >                                0, 0, imx290_test_pattern_menu);
> > > > > >
> > > > > > + /*
> > > > > > +  * Horizontal blanking is controlled through the HMAX register, which
> > > > > > +  * contains a line length in INCK clock units. The INCK frequency is
> > > > > > +  * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100,
> > > > > > +  * convert it to a number of pixels based on the nominal pixel rate.
> > > > > > +  */
> > > > >
> > > > > Currently the driver only supports 37.125 MHz, please refer to
> > > > > imx290_probe.
> > > >
> > > > Indeed. Re-reading the comment, I suspect something is wrong, as hmax is
> > > > not converted to pixels here (and is also not fixed to 1100).
>
> I'll drop the comment in v2.
>
> > > > The only
> > > > datasheet I found that is publicly accessed doesn't explain very clearly
> > > > how the HMAX value should be computed. Based on your experience with IMX
> > > > sensors, would you be able to shed some light on this ?
> >
> > It is pretty much a standard HTS setting based on a pixel rate that is
> > fixed at 148.5MPix/s.
>
> I'm following you for HTS, but not for the fixed pixel rate. Could you
> elaborate ?

If you work through the numbers you'll find the pixel rate for the
720p mode in the current driver is wrong.

As documented in the datasheet (page 50), the link rate is dropped
from 445.5Mbit/s for 1080p60 in 4 lane mode to 297Mbit/s for 720p60.
The behaviour of the LINK_FREQ control is therefore correct (I've
checked it on an oscilloscope too).

If you look at the HMAX and VMAX numbers for the 720p mode on page 71,
VMAX is 0x2ee (750 decimal), and HMAX is 0x0ce4 (3300 decimal) for
60fps. The driver uses these numbers too in advertising VBLANK and
HBLANK. All good so far.

750 * 3300 * 60(fps) = 148500000, which is the same pixel rate as for
1080p, and not related to the link frequency selected by the mode.
The sensor array can run faster than the CSI block, and
imx290_calc_pixel_rate() is totally bogus.

PIXEL_RATE != LINK_FREQ.

> > Likewise VMAX is equivalent to a traditional VTS.
>
> Yes, that one is easy.
>
> > I've been through the same path in
> > https://github.com/raspberrypi/linux/commits/rpi-5.15.y/drivers/media/i2c/imx290.c
> >
> > > Can you share the link to this datasheet you found?
>
> https://static6.arrow.com/aropdfconversion/c0c7efde6571c768020a72f59b226308b9669e45/sony_imx290lqr-c_datasheet.pdf

Thanks - it's helpful to be able to quote a public source rather than
risk upsetting vendors by quoting their confidential datasheets.

  Dave

> > > Sorry, my experience is more like try and error. I don't fully understand this
> > > as well, but apparently this depends on frame rate select (FRSEL).
> >
> > FRSEL is the one difference between IMX327 and IMX290 (and presumably
> > IMX462 too). IMX290 adds "0" as a valid value for 120/100fps mode.
> > However there is no need to change FRSEL for standard frame rate
> > control - you can set it at 0x01 and get a full range of frame rates
> > through VMAX and HMAX. If you wished to extend that range for slower
> > rates, you could conditionally set it to 0x2 to double the frame time.
> >
> > > > > > + blank = imx290->current_mode->hmax - imx290->current_mode->width;
> > > > > > + imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > > > > > +                                    V4L2_CID_HBLANK, blank, blank, 1,
> > > > > > +                                    blank);
> > > > > > + if (imx290->hblank)
> > > > > > +         imx290->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > > > > +
> > > > > > + blank = IMX290_VMAX_DEFAULT - imx290->current_mode->height;
> > > > > > + imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
> > > > > > +                                    V4L2_CID_VBLANK, blank, blank, 1,
> > > > > > +                                    blank);
> > > > > > + if (imx290->vblank)
> > > > > > +         imx290->vblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > > > > +
> > > > > >
> > > > > >   imx290->sd.ctrl_handler = &imx290->ctrls;
> > > > > >
> > > > > >   if (imx290->ctrls.error) {
>
> --
> Regards,
>
> Laurent Pinchart

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-10-16  7:34       ` Dave Stevenson
@ 2022-10-17 18:07         ` Dave Stevenson
  2022-10-18 13:43           ` Dave Stevenson
  2022-10-19 10:33           ` Sakari Ailus
  0 siblings, 2 replies; 81+ messages in thread
From: Dave Stevenson @ 2022-10-17 18:07 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam

Hi Laurent

On Sun, 16 Oct 2022 at 08:34, Dave Stevenson
<dave.stevenson@raspberrypi.com> wrote:
>
> Hi Laurent
>
> On Sun, 16 Oct 2022 at 06:37, Laurent Pinchart
> <laurent.pinchart@ideasonboard.com> wrote:
> >
> > Hi Dave,
> >
> > On Mon, Oct 10, 2022 at 11:31:33AM +0100, Dave Stevenson wrote:
> > > Hi Laurent
> > >
> > > Do you have plans for a v2 on this patch set? I also have a number of
> > > patches for imx290 and there's little point in causing grief to each
> > > other with conflicts.
> > > Or I could take the non-controversial patches from your set and send a
> > > combined patch set?
> >
> > I'm working on a v2, I'll send it shortly. Do I assume correctly you'll
> > submit IMX327 support on top ? :-)
>
> Thanks - I'll review it tomorrow and sort my patches on top again.

I've reworked my patches on top of yours. It gives r/w VBLANK and
HBLANK, and corrects PIXEL_RATE.
I'm testing on our 6.0 branch, but
https://github.com/6by9/linux/commits/linuxtv_imx290/drivers/media/i2c
is against the linux-media branch.

I've messed something up in the "media: i2c: imx290: Support 60fps in
2 lane operation" patch at present - I'm looking into what has gone
wrong, as the earlier versions of that patch worked fine. The branch
will get force-pushed once I've fixed it.

> This driver is effectively IMX327 - max 1920x1080@60fps in 12 bit.
>
> IMX290 adds a 1920x1080@120fps 10bit only mode which isn't currently
> supported by the driver. I have patches to add 10bit support, but I
> don't increase the frame rate in them.
>
> IMX462 adds that 1920x1080@120fps mode in both 10 and 12 bit, but
> again I haven't looked at adding support, partly as I don't have a
> datasheet for that variant. I may see if the change for 120fps 10bit
> on imx290 works in 12 bit mode for IMX462.
> For IMX290, 1080p120 needs a link frequency of 445.5MHz on 4 lanes to
> be supported (2 lanes not permitted), so there will be more link
> frequency messing required to support it. The basic numbers say that
> is fast enough for 12bit as well, so there's hope.

I guess seeing as I'm messing with the clock setup, I may as well keep
going and look at the 120fps modes. It's a little trickier as the Pi
ISP will be on the edge at those rates, but it should be good enough.

There is an awkward question with regard link-frequencies. Is there a
need to support multiple sets of link-frequency, or do we support any
set of 2?
ie for imx290, on 4 lanes do we want:
- 891Mbit/s for 1080p120 10bit
- 445.5Mbit/s for 1080p60 10 or 12 bit
- 594Mbit/s for 720p120 10bit
- 297Mbit/s for 720p60 10 and 12 bit
all to be present in DT?
If only 891 and 594 then you're limited to 10 bit images, but
otherwise it should be fully functional. The max frame interval would
be half that of 445.5 and 297 though, so there are compromises, but
who/what then controls the link_frequency to switch between the
ranges?

I can see another can of worms being opened here!

  Dave

>   Dave
>
> > > On Tue, 23 Aug 2022 at 02:12, Laurent Pinchart wrote:
> > > >
> > > > Hi Sakari,
> > > >
> > > > Could you already pick up patches 01/19, 02/19, 04/19, 05/19 and 06/19
> > > > in your tree ? Your opinion on 03/19 woud be appreciated too, I think
> > > > it's a candidate for merge as well.
> > > >
> > > > On Thu, Jul 21, 2022 at 11:35:21AM +0300, Laurent Pinchart wrote:
> > > > > Hello,
> > > > >
> > > > > This patch series gathers miscellaneous improvements for the imx290
> > > > > driver. The most notable changes on the kernel side is patch 07/19 that
> > > > > simplifies register access, and on the userspace API side patches 14/19,
> > > > > 15/19 and 18/19 that extend the driver with controls and selection
> > > > > rectangles required by libcamera.
> > > > >
> > > > > Laurent Pinchart (19):
> > > > >   media: i2c: imx290: Use device lock for the control handler
> > > > >   media: i2c: imx290: Print error code when I2C transfer fails
> > > > >   media: i2c: imx290: Specify HMAX values in decimal
> > > > >   media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
> > > > >   media: i2c: imx290: Drop imx290_write_buffered_reg()
> > > > >   media: i2c: imx290: Drop regmap cache
> > > > >   media: i2c: imx290: Support variable-sized registers
> > > > >   media: i2c: imx290: Correct register sizes
> > > > >   media: i2c: imx290: Simplify error handling when writing registers
> > > > >   media: i2c: imx290: Define more register macros
> > > > >   media: i2c: imx290: Add exposure time control
> > > > >   media: i2c: imx290: Fix max gain value
> > > > >   media: i2c: imx290: Split control initialization to separate function
> > > > >   media: i2c: imx290: Implement HBLANK and VBLANK controls
> > > > >   media: i2c: imx290: Create controls for fwnode properties
> > > > >   media: i2c: imx290: Move registers with fixed value to init array
> > > > >   media: i2c: imx290: Factor out format retrieval to separate function
> > > > >   media: i2c: imx290: Add crop selection targets support
> > > > >   media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN
> > > > >
> > > > >  drivers/media/i2c/imx290.c | 781 ++++++++++++++++++++++---------------
> > > > >  1 file changed, 458 insertions(+), 323 deletions(-)
> >
> > --
> > Regards,
> >
> > Laurent Pinchart

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-10-17 18:07         ` Dave Stevenson
@ 2022-10-18 13:43           ` Dave Stevenson
  2022-10-19 10:33           ` Sakari Ailus
  1 sibling, 0 replies; 81+ messages in thread
From: Dave Stevenson @ 2022-10-18 13:43 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Sakari Ailus, linux-media, Manivannan Sadhasivam

On Mon, 17 Oct 2022 at 19:07, Dave Stevenson
<dave.stevenson@raspberrypi.com> wrote:
>
> Hi Laurent
>
> On Sun, 16 Oct 2022 at 08:34, Dave Stevenson
> <dave.stevenson@raspberrypi.com> wrote:
> >
> > Hi Laurent
> >
> > On Sun, 16 Oct 2022 at 06:37, Laurent Pinchart
> > <laurent.pinchart@ideasonboard.com> wrote:
> > >
> > > Hi Dave,
> > >
> > > On Mon, Oct 10, 2022 at 11:31:33AM +0100, Dave Stevenson wrote:
> > > > Hi Laurent
> > > >
> > > > Do you have plans for a v2 on this patch set? I also have a number of
> > > > patches for imx290 and there's little point in causing grief to each
> > > > other with conflicts.
> > > > Or I could take the non-controversial patches from your set and send a
> > > > combined patch set?
> > >
> > > I'm working on a v2, I'll send it shortly. Do I assume correctly you'll
> > > submit IMX327 support on top ? :-)
> >
> > Thanks - I'll review it tomorrow and sort my patches on top again.
>
> I've reworked my patches on top of yours. It gives r/w VBLANK and
> HBLANK, and corrects PIXEL_RATE.
> I'm testing on our 6.0 branch, but
> https://github.com/6by9/linux/commits/linuxtv_imx290/drivers/media/i2c
> is against the linux-media branch.
>
> I've messed something up in the "media: i2c: imx290: Support 60fps in
> 2 lane operation" patch at present - I'm looking into what has gone
> wrong, as the earlier versions of that patch worked fine. The branch
> will get force-pushed once I've fixed it.

Sorted and branch updated.
1080p or 720p, up to 60fps, 10 or 12bit, on 2 or 4 lanes all working.

> > This driver is effectively IMX327 - max 1920x1080@60fps in 12 bit.
> >
> > IMX290 adds a 1920x1080@120fps 10bit only mode which isn't currently
> > supported by the driver. I have patches to add 10bit support, but I
> > don't increase the frame rate in them.
> >
> > IMX462 adds that 1920x1080@120fps mode in both 10 and 12 bit, but
> > again I haven't looked at adding support, partly as I don't have a
> > datasheet for that variant. I may see if the change for 120fps 10bit
> > on imx290 works in 12 bit mode for IMX462.
> > For IMX290, 1080p120 needs a link frequency of 445.5MHz on 4 lanes to
> > be supported (2 lanes not permitted), so there will be more link
> > frequency messing required to support it. The basic numbers say that
> > is fast enough for 12bit as well, so there's hope.
>
> I guess seeing as I'm messing with the clock setup, I may as well keep
> going and look at the 120fps modes. It's a little trickier as the Pi
> ISP will be on the edge at those rates, but it should be good enough.

I've got 120fps working on an IMX462 as 720p 10 or 12bit, and as 1080p
10bit. 1080p 12 bit goes psychedelic!

From that I've noted that the CSI-2 TCLKPOST, THSZERO, THSPREPARE, etc
settings (0x3446-0x3455) are all common to a link frequency, so it
probably makes more sense to separate them out based on that. I'll
look to rework my 2 lane 60fps patch based on that, and then consider
extending it for 120fps.

As another quirk, the HMAX register switches to units of 2 pixels when
FR_SEL = 0 for 120fps. FR_SEL = 2 (30fps mode) and it's 1/2 a pixel.

  Dave

> There is an awkward question with regard link-frequencies. Is there a
> need to support multiple sets of link-frequency, or do we support any
> set of 2?
> ie for imx290, on 4 lanes do we want:
> - 891Mbit/s for 1080p120 10bit
> - 445.5Mbit/s for 1080p60 10 or 12 bit
> - 594Mbit/s for 720p120 10bit
> - 297Mbit/s for 720p60 10 and 12 bit
> all to be present in DT?
> If only 891 and 594 then you're limited to 10 bit images, but
> otherwise it should be fully functional. The max frame interval would
> be half that of 445.5 and 297 though, so there are compromises, but
> who/what then controls the link_frequency to switch between the
> ranges?
>
> I can see another can of worms being opened here!
>
>   Dave
>
> >   Dave
> >
> > > > On Tue, 23 Aug 2022 at 02:12, Laurent Pinchart wrote:
> > > > >
> > > > > Hi Sakari,
> > > > >
> > > > > Could you already pick up patches 01/19, 02/19, 04/19, 05/19 and 06/19
> > > > > in your tree ? Your opinion on 03/19 woud be appreciated too, I think
> > > > > it's a candidate for merge as well.
> > > > >
> > > > > On Thu, Jul 21, 2022 at 11:35:21AM +0300, Laurent Pinchart wrote:
> > > > > > Hello,
> > > > > >
> > > > > > This patch series gathers miscellaneous improvements for the imx290
> > > > > > driver. The most notable changes on the kernel side is patch 07/19 that
> > > > > > simplifies register access, and on the userspace API side patches 14/19,
> > > > > > 15/19 and 18/19 that extend the driver with controls and selection
> > > > > > rectangles required by libcamera.
> > > > > >
> > > > > > Laurent Pinchart (19):
> > > > > >   media: i2c: imx290: Use device lock for the control handler
> > > > > >   media: i2c: imx290: Print error code when I2C transfer fails
> > > > > >   media: i2c: imx290: Specify HMAX values in decimal
> > > > > >   media: i2c: imx290: Replace macro with explicit ARRAY_SIZE()
> > > > > >   media: i2c: imx290: Drop imx290_write_buffered_reg()
> > > > > >   media: i2c: imx290: Drop regmap cache
> > > > > >   media: i2c: imx290: Support variable-sized registers
> > > > > >   media: i2c: imx290: Correct register sizes
> > > > > >   media: i2c: imx290: Simplify error handling when writing registers
> > > > > >   media: i2c: imx290: Define more register macros
> > > > > >   media: i2c: imx290: Add exposure time control
> > > > > >   media: i2c: imx290: Fix max gain value
> > > > > >   media: i2c: imx290: Split control initialization to separate function
> > > > > >   media: i2c: imx290: Implement HBLANK and VBLANK controls
> > > > > >   media: i2c: imx290: Create controls for fwnode properties
> > > > > >   media: i2c: imx290: Move registers with fixed value to init array
> > > > > >   media: i2c: imx290: Factor out format retrieval to separate function
> > > > > >   media: i2c: imx290: Add crop selection targets support
> > > > > >   media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN
> > > > > >
> > > > > >  drivers/media/i2c/imx290.c | 781 ++++++++++++++++++++++---------------
> > > > > >  1 file changed, 458 insertions(+), 323 deletions(-)
> > >
> > > --
> > > Regards,
> > >
> > > Laurent Pinchart

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-10-17 18:07         ` Dave Stevenson
  2022-10-18 13:43           ` Dave Stevenson
@ 2022-10-19 10:33           ` Sakari Ailus
  2022-10-19 11:38             ` Dave Stevenson
  1 sibling, 1 reply; 81+ messages in thread
From: Sakari Ailus @ 2022-10-19 10:33 UTC (permalink / raw)
  To: Dave Stevenson; +Cc: Laurent Pinchart, linux-media, Manivannan Sadhasivam

Hi Dave,

On Mon, Oct 17, 2022 at 07:07:20PM +0100, Dave Stevenson wrote:
> Hi Laurent
> 
> On Sun, 16 Oct 2022 at 08:34, Dave Stevenson
> <dave.stevenson@raspberrypi.com> wrote:
> >
> > Hi Laurent
> >
> > On Sun, 16 Oct 2022 at 06:37, Laurent Pinchart
> > <laurent.pinchart@ideasonboard.com> wrote:
> > >
> > > Hi Dave,
> > >
> > > On Mon, Oct 10, 2022 at 11:31:33AM +0100, Dave Stevenson wrote:
> > > > Hi Laurent
> > > >
> > > > Do you have plans for a v2 on this patch set? I also have a number of
> > > > patches for imx290 and there's little point in causing grief to each
> > > > other with conflicts.
> > > > Or I could take the non-controversial patches from your set and send a
> > > > combined patch set?
> > >
> > > I'm working on a v2, I'll send it shortly. Do I assume correctly you'll
> > > submit IMX327 support on top ? :-)
> >
> > Thanks - I'll review it tomorrow and sort my patches on top again.
> 
> I've reworked my patches on top of yours. It gives r/w VBLANK and
> HBLANK, and corrects PIXEL_RATE.
> I'm testing on our 6.0 branch, but
> https://github.com/6by9/linux/commits/linuxtv_imx290/drivers/media/i2c
> is against the linux-media branch.
> 
> I've messed something up in the "media: i2c: imx290: Support 60fps in
> 2 lane operation" patch at present - I'm looking into what has gone
> wrong, as the earlier versions of that patch worked fine. The branch
> will get force-pushed once I've fixed it.
> 
> > This driver is effectively IMX327 - max 1920x1080@60fps in 12 bit.
> >
> > IMX290 adds a 1920x1080@120fps 10bit only mode which isn't currently
> > supported by the driver. I have patches to add 10bit support, but I
> > don't increase the frame rate in them.
> >
> > IMX462 adds that 1920x1080@120fps mode in both 10 and 12 bit, but
> > again I haven't looked at adding support, partly as I don't have a
> > datasheet for that variant. I may see if the change for 120fps 10bit
> > on imx290 works in 12 bit mode for IMX462.
> > For IMX290, 1080p120 needs a link frequency of 445.5MHz on 4 lanes to
> > be supported (2 lanes not permitted), so there will be more link
> > frequency messing required to support it. The basic numbers say that
> > is fast enough for 12bit as well, so there's hope.
> 
> I guess seeing as I'm messing with the clock setup, I may as well keep
> going and look at the 120fps modes. It's a little trickier as the Pi
> ISP will be on the edge at those rates, but it should be good enough.
> 
> There is an awkward question with regard link-frequencies. Is there a
> need to support multiple sets of link-frequency, or do we support any
> set of 2?
> ie for imx290, on 4 lanes do we want:
> - 891Mbit/s for 1080p120 10bit
> - 445.5Mbit/s for 1080p60 10 or 12 bit
> - 594Mbit/s for 720p120 10bit
> - 297Mbit/s for 720p60 10 and 12 bit
> all to be present in DT?
> If only 891 and 594 then you're limited to 10 bit images, but
> otherwise it should be fully functional. The max frame interval would
> be half that of 445.5 and 297 though, so there are compromises, but
> who/what then controls the link_frequency to switch between the
> ranges?

It's up to the user space to set that control in a general case. I guess
there are no specific rules on how many you should put to DT, but generally
those that are useful should be there.

I wonder why 12 bpp output isn't possible at the double frequency. Of
course it is possible the sensor's clock tree makes that impossible but it
is still unusual.

> 
> I can see another can of worms being opened here!

If this is what the sensor does, how else it should be operated?

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-10-19 10:33           ` Sakari Ailus
@ 2022-10-19 11:38             ` Dave Stevenson
  2022-10-19 13:27               ` Sakari Ailus
  0 siblings, 1 reply; 81+ messages in thread
From: Dave Stevenson @ 2022-10-19 11:38 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: Laurent Pinchart, linux-media, Manivannan Sadhasivam

Hi Sakari

Thanks for the response

On Wed, 19 Oct 2022 at 11:33, Sakari Ailus <sakari.ailus@iki.fi> wrote:
>
> Hi Dave,
>
> On Mon, Oct 17, 2022 at 07:07:20PM +0100, Dave Stevenson wrote:
> > Hi Laurent
> >
> > On Sun, 16 Oct 2022 at 08:34, Dave Stevenson
> > <dave.stevenson@raspberrypi.com> wrote:
> > >
> > > Hi Laurent
> > >
> > > On Sun, 16 Oct 2022 at 06:37, Laurent Pinchart
> > > <laurent.pinchart@ideasonboard.com> wrote:
> > > >
> > > > Hi Dave,
> > > >
> > > > On Mon, Oct 10, 2022 at 11:31:33AM +0100, Dave Stevenson wrote:
> > > > > Hi Laurent
> > > > >
> > > > > Do you have plans for a v2 on this patch set? I also have a number of
> > > > > patches for imx290 and there's little point in causing grief to each
> > > > > other with conflicts.
> > > > > Or I could take the non-controversial patches from your set and send a
> > > > > combined patch set?
> > > >
> > > > I'm working on a v2, I'll send it shortly. Do I assume correctly you'll
> > > > submit IMX327 support on top ? :-)
> > >
> > > Thanks - I'll review it tomorrow and sort my patches on top again.
> >
> > I've reworked my patches on top of yours. It gives r/w VBLANK and
> > HBLANK, and corrects PIXEL_RATE.
> > I'm testing on our 6.0 branch, but
> > https://github.com/6by9/linux/commits/linuxtv_imx290/drivers/media/i2c
> > is against the linux-media branch.
> >
> > I've messed something up in the "media: i2c: imx290: Support 60fps in
> > 2 lane operation" patch at present - I'm looking into what has gone
> > wrong, as the earlier versions of that patch worked fine. The branch
> > will get force-pushed once I've fixed it.
> >
> > > This driver is effectively IMX327 - max 1920x1080@60fps in 12 bit.
> > >
> > > IMX290 adds a 1920x1080@120fps 10bit only mode which isn't currently
> > > supported by the driver. I have patches to add 10bit support, but I
> > > don't increase the frame rate in them.
> > >
> > > IMX462 adds that 1920x1080@120fps mode in both 10 and 12 bit, but
> > > again I haven't looked at adding support, partly as I don't have a
> > > datasheet for that variant. I may see if the change for 120fps 10bit
> > > on imx290 works in 12 bit mode for IMX462.
> > > For IMX290, 1080p120 needs a link frequency of 445.5MHz on 4 lanes to
> > > be supported (2 lanes not permitted), so there will be more link
> > > frequency messing required to support it. The basic numbers say that
> > > is fast enough for 12bit as well, so there's hope.
> >
> > I guess seeing as I'm messing with the clock setup, I may as well keep
> > going and look at the 120fps modes. It's a little trickier as the Pi
> > ISP will be on the edge at those rates, but it should be good enough.
> >
> > There is an awkward question with regard link-frequencies. Is there a
> > need to support multiple sets of link-frequency, or do we support any
> > set of 2?
> > ie for imx290, on 4 lanes do we want:
> > - 891Mbit/s for 1080p120 10bit
> > - 445.5Mbit/s for 1080p60 10 or 12 bit
> > - 594Mbit/s for 720p120 10bit
> > - 297Mbit/s for 720p60 10 and 12 bit
> > all to be present in DT?
> > If only 891 and 594 then you're limited to 10 bit images, but
> > otherwise it should be fully functional. The max frame interval would
> > be half that of 445.5 and 297 though, so there are compromises, but
> > who/what then controls the link_frequency to switch between the
> > ranges?
>
> It's up to the user space to set that control in a general case. I guess
> there are no specific rules on how many you should put to DT, but generally
> those that are useful should be there.

Does the driver have to support multiple sets of link frequencies
simultaneously?

The way the driver is currently written you have one link freq for
1080p and one for 720p (2/3rds the rate used for 1080p). You could
retain using only 2 link frequencies at a time.

If DT/ACPI gives us 222.75MHz and 148.5MHz on 4 lanes, or 445.5MHz and
297MHz on 2 lanes, with IMX327, IMX290 or IMX462, then use the current
configuration that can do 0.03 to 60fps as RAW10 or RAW12.
If DT/ACPI gives us 445.5MHz and 297MHz on 4 lanes and are on an
IMX290 (not IMX327), then use a new configuration that can do 0.06 to
120fps as RAW10 only.
If DT/ACPI gives us 445.5MHz and 297MHz on 4 lanes and are on an
IMX462, then use a new configuration that can do 0.06 to 120fps as
RAW10 or RAW12.
If the configuration doesn't fall into any of these categories, then
it is rejected.

Whoever is putting together the DT/ACPI for the device can then choose
whether they value the lower minimum frame rate and RAW12, or the
higher frame rate but are prepared to sacrifice RAW12. (As we use
dtoverlays, we can add overrides so that person is the end user).
Trying to cram that lot in so that it can all be used simultaneously
will get quite ugly - the register configuration is not quite as
simple as one might hope, and you'd be filtering the permitted modes
and bit depths all over the place.

As I mentioned at the Media Summit in Dublin I've had users wanting
IMX462 for astronomy use cases, so halving the max exposure time by
dropping the current max 60fps configuration won't be popular. I guess
you could incorrectly use an IMX327 compatible string in the DT when
using an IMX290/462 to force the behaviour, but that feels even more
of a hack.

> I wonder why 12 bpp output isn't possible at the double frequency. Of
> course it is possible the sensor's clock tree makes that impossible but it
> is still unusual.

It is a little weird. As noted in the later emails, I have put
together settings to get 120fps running, and have tried it on both
IMX462 and IMX290.

720p120 RAW12 works fine on both, as do 720p120 and 1080p120 in RAW10.
However 1080p120 RAW12 doesn't work on either, so I suspect it is
something in the CSI2 block configuration that can't quite hit that
data rate without further changes. I'll see if Sony wants to be
friendly with datasheets for the IMX462.

> >
> > I can see another can of worms being opened here!
>
> If this is what the sensor does, how else it should be operated?

As above, link frequency remains read only based on DT or ACPI, and
that then restricts the configurations that are possible.

I've never seen a good userspace example of using
V4L2_CID_LINK_FREQUENCY, so without that it always seems to be a
setting that is generally only used by the CSI-2 receiver to adapt
appropriately to the data rate.
To my mind it falls into the same category as binning and cropping -
it's lovely to expose the full feature set, but that is just passing
the buck to some heuristics in userspace. Generally the user of the
camera doesn't care (they just want their camera to work) so
realistically you're looking at libcamera, and it doesn't necessarily
have sufficient information about the sensor or use case to make a
good decision.

  Dave

> --
> Kind regards,
>
> Sakari Ailus

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-10-19 11:38             ` Dave Stevenson
@ 2022-10-19 13:27               ` Sakari Ailus
  2023-01-14 16:03                 ` Laurent Pinchart
  0 siblings, 1 reply; 81+ messages in thread
From: Sakari Ailus @ 2022-10-19 13:27 UTC (permalink / raw)
  To: Dave Stevenson; +Cc: Laurent Pinchart, linux-media, Manivannan Sadhasivam

Hi Dave,

On Wed, Oct 19, 2022 at 12:38:21PM +0100, Dave Stevenson wrote:
> Hi Sakari
> 
> Thanks for the response
> 
> On Wed, 19 Oct 2022 at 11:33, Sakari Ailus <sakari.ailus@iki.fi> wrote:
> >
> > Hi Dave,
> >
> > On Mon, Oct 17, 2022 at 07:07:20PM +0100, Dave Stevenson wrote:
> > > Hi Laurent
> > >
> > > On Sun, 16 Oct 2022 at 08:34, Dave Stevenson
> > > <dave.stevenson@raspberrypi.com> wrote:
> > > >
> > > > Hi Laurent
> > > >
> > > > On Sun, 16 Oct 2022 at 06:37, Laurent Pinchart
> > > > <laurent.pinchart@ideasonboard.com> wrote:
> > > > >
> > > > > Hi Dave,
> > > > >
> > > > > On Mon, Oct 10, 2022 at 11:31:33AM +0100, Dave Stevenson wrote:
> > > > > > Hi Laurent
> > > > > >
> > > > > > Do you have plans for a v2 on this patch set? I also have a number of
> > > > > > patches for imx290 and there's little point in causing grief to each
> > > > > > other with conflicts.
> > > > > > Or I could take the non-controversial patches from your set and send a
> > > > > > combined patch set?
> > > > >
> > > > > I'm working on a v2, I'll send it shortly. Do I assume correctly you'll
> > > > > submit IMX327 support on top ? :-)
> > > >
> > > > Thanks - I'll review it tomorrow and sort my patches on top again.
> > >
> > > I've reworked my patches on top of yours. It gives r/w VBLANK and
> > > HBLANK, and corrects PIXEL_RATE.
> > > I'm testing on our 6.0 branch, but
> > > https://github.com/6by9/linux/commits/linuxtv_imx290/drivers/media/i2c
> > > is against the linux-media branch.
> > >
> > > I've messed something up in the "media: i2c: imx290: Support 60fps in
> > > 2 lane operation" patch at present - I'm looking into what has gone
> > > wrong, as the earlier versions of that patch worked fine. The branch
> > > will get force-pushed once I've fixed it.
> > >
> > > > This driver is effectively IMX327 - max 1920x1080@60fps in 12 bit.
> > > >
> > > > IMX290 adds a 1920x1080@120fps 10bit only mode which isn't currently
> > > > supported by the driver. I have patches to add 10bit support, but I
> > > > don't increase the frame rate in them.
> > > >
> > > > IMX462 adds that 1920x1080@120fps mode in both 10 and 12 bit, but
> > > > again I haven't looked at adding support, partly as I don't have a
> > > > datasheet for that variant. I may see if the change for 120fps 10bit
> > > > on imx290 works in 12 bit mode for IMX462.
> > > > For IMX290, 1080p120 needs a link frequency of 445.5MHz on 4 lanes to
> > > > be supported (2 lanes not permitted), so there will be more link
> > > > frequency messing required to support it. The basic numbers say that
> > > > is fast enough for 12bit as well, so there's hope.
> > >
> > > I guess seeing as I'm messing with the clock setup, I may as well keep
> > > going and look at the 120fps modes. It's a little trickier as the Pi
> > > ISP will be on the edge at those rates, but it should be good enough.
> > >
> > > There is an awkward question with regard link-frequencies. Is there a
> > > need to support multiple sets of link-frequency, or do we support any
> > > set of 2?
> > > ie for imx290, on 4 lanes do we want:
> > > - 891Mbit/s for 1080p120 10bit
> > > - 445.5Mbit/s for 1080p60 10 or 12 bit
> > > - 594Mbit/s for 720p120 10bit
> > > - 297Mbit/s for 720p60 10 and 12 bit
> > > all to be present in DT?
> > > If only 891 and 594 then you're limited to 10 bit images, but
> > > otherwise it should be fully functional. The max frame interval would
> > > be half that of 445.5 and 297 though, so there are compromises, but
> > > who/what then controls the link_frequency to switch between the
> > > ranges?
> >
> > It's up to the user space to set that control in a general case. I guess
> > there are no specific rules on how many you should put to DT, but generally
> > those that are useful should be there.
> 
> Does the driver have to support multiple sets of link frequencies
> simultaneously?

It's up to the driver. A driver may support fewer features than the
hardware allows, and with sensors this is commonly the case. So I don't
think this would be special somehow. Of course if a driver supports just
one and the DT has more, the end result may not be desirable in terms of
what actually works.

With e.g. CCS the user can choose any link frequency for which there is a
valid PLL tree configuration with current settings. Depending on e.g. the
bit depth, for instance, some frequencies may be unavailable.

> 
> The way the driver is currently written you have one link freq for
> 1080p and one for 720p (2/3rds the rate used for 1080p). You could
> retain using only 2 link frequencies at a time.
> 
> If DT/ACPI gives us 222.75MHz and 148.5MHz on 4 lanes, or 445.5MHz and
> 297MHz on 2 lanes, with IMX327, IMX290 or IMX462, then use the current
> configuration that can do 0.03 to 60fps as RAW10 or RAW12.
> If DT/ACPI gives us 445.5MHz and 297MHz on 4 lanes and are on an
> IMX290 (not IMX327), then use a new configuration that can do 0.06 to
> 120fps as RAW10 only.
> If DT/ACPI gives us 445.5MHz and 297MHz on 4 lanes and are on an
> IMX462, then use a new configuration that can do 0.06 to 120fps as
> RAW10 or RAW12.
> If the configuration doesn't fall into any of these categories, then
> it is rejected.

Seems reasonable.

> 
> Whoever is putting together the DT/ACPI for the device can then choose
> whether they value the lower minimum frame rate and RAW12, or the
> higher frame rate but are prepared to sacrifice RAW12. (As we use
> dtoverlays, we can add overrides so that person is the end user).
> Trying to cram that lot in so that it can all be used simultaneously
> will get quite ugly - the register configuration is not quite as
> simple as one might hope, and you'd be filtering the permitted modes
> and bit depths all over the place.
> 
> As I mentioned at the Media Summit in Dublin I've had users wanting
> IMX462 for astronomy use cases, so halving the max exposure time by
> dropping the current max 60fps configuration won't be popular. I guess
> you could incorrectly use an IMX327 compatible string in the DT when
> using an IMX290/462 to force the behaviour, but that feels even more
> of a hack.
> 
> > I wonder why 12 bpp output isn't possible at the double frequency. Of
> > course it is possible the sensor's clock tree makes that impossible but it
> > is still unusual.
> 
> It is a little weird. As noted in the later emails, I have put
> together settings to get 120fps running, and have tried it on both
> IMX462 and IMX290.
> 
> 720p120 RAW12 works fine on both, as do 720p120 and 1080p120 in RAW10.
> However 1080p120 RAW12 doesn't work on either, so I suspect it is
> something in the CSI2 block configuration that can't quite hit that
> data rate without further changes. I'll see if Sony wants to be
> friendly with datasheets for the IMX462.

The receiver block driver could refuse to streamon if the pixel rate * bpp
is too high. But I understand in this case it shouldn't be a limitation.
And it doesn't really help the user to find which configurations would
work.

> 
> > >
> > > I can see another can of worms being opened here!
> >
> > If this is what the sensor does, how else it should be operated?
> 
> As above, link frequency remains read only based on DT or ACPI, and
> that then restricts the configurations that are possible.
> 
> I've never seen a good userspace example of using
> V4L2_CID_LINK_FREQUENCY, so without that it always seems to be a
> setting that is generally only used by the CSI-2 receiver to adapt
> appropriately to the data rate.
> To my mind it falls into the same category as binning and cropping -
> it's lovely to expose the full feature set, but that is just passing
> the buck to some heuristics in userspace. Generally the user of the
> camera doesn't care (they just want their camera to work) so
> realistically you're looking at libcamera, and it doesn't necessarily
> have sufficient information about the sensor or use case to make a
> good decision.

The CCS driver changes the link frequency based on other configuration
(mbus code) if the selected one cannot be used.

As this is a board specific configuration, fixing these values for a sensor
is not a feasible approach in libcamera.

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements
  2022-10-19 13:27               ` Sakari Ailus
@ 2023-01-14 16:03                 ` Laurent Pinchart
  0 siblings, 0 replies; 81+ messages in thread
From: Laurent Pinchart @ 2023-01-14 16:03 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: Dave Stevenson, linux-media, Manivannan Sadhasivam

Hello,

On Wed, Oct 19, 2022 at 04:27:13PM +0300, Sakari Ailus wrote:
> On Wed, Oct 19, 2022 at 12:38:21PM +0100, Dave Stevenson wrote:
> > On Wed, 19 Oct 2022 at 11:33, Sakari Ailus wrote:
> > > On Mon, Oct 17, 2022 at 07:07:20PM +0100, Dave Stevenson wrote:
> > > > On Sun, 16 Oct 2022 at 08:34, Dave Stevenson wrote:
> > > > > On Sun, 16 Oct 2022 at 06:37, Laurent Pinchart wrote:
> > > > > > On Mon, Oct 10, 2022 at 11:31:33AM +0100, Dave Stevenson wrote:
> > > > > > > Hi Laurent
> > > > > > >
> > > > > > > Do you have plans for a v2 on this patch set? I also have a number of
> > > > > > > patches for imx290 and there's little point in causing grief to each
> > > > > > > other with conflicts.
> > > > > > > Or I could take the non-controversial patches from your set and send a
> > > > > > > combined patch set?
> > > > > >
> > > > > > I'm working on a v2, I'll send it shortly. Do I assume correctly you'll
> > > > > > submit IMX327 support on top ? :-)
> > > > >
> > > > > Thanks - I'll review it tomorrow and sort my patches on top again.
> > > >
> > > > I've reworked my patches on top of yours. It gives r/w VBLANK and
> > > > HBLANK, and corrects PIXEL_RATE.
> > > > I'm testing on our 6.0 branch, but
> > > > https://github.com/6by9/linux/commits/linuxtv_imx290/drivers/media/i2c
> > > > is against the linux-media branch.
> > > >
> > > > I've messed something up in the "media: i2c: imx290: Support 60fps in
> > > > 2 lane operation" patch at present - I'm looking into what has gone
> > > > wrong, as the earlier versions of that patch worked fine. The branch
> > > > will get force-pushed once I've fixed it.
> > > >
> > > > > This driver is effectively IMX327 - max 1920x1080@60fps in 12 bit.
> > > > >
> > > > > IMX290 adds a 1920x1080@120fps 10bit only mode which isn't currently
> > > > > supported by the driver. I have patches to add 10bit support, but I
> > > > > don't increase the frame rate in them.
> > > > >
> > > > > IMX462 adds that 1920x1080@120fps mode in both 10 and 12 bit, but
> > > > > again I haven't looked at adding support, partly as I don't have a
> > > > > datasheet for that variant. I may see if the change for 120fps 10bit
> > > > > on imx290 works in 12 bit mode for IMX462.
> > > > > For IMX290, 1080p120 needs a link frequency of 445.5MHz on 4 lanes to
> > > > > be supported (2 lanes not permitted), so there will be more link
> > > > > frequency messing required to support it. The basic numbers say that
> > > > > is fast enough for 12bit as well, so there's hope.
> > > >
> > > > I guess seeing as I'm messing with the clock setup, I may as well keep
> > > > going and look at the 120fps modes. It's a little trickier as the Pi
> > > > ISP will be on the edge at those rates, but it should be good enough.
> > > >
> > > > There is an awkward question with regard link-frequencies. Is there a
> > > > need to support multiple sets of link-frequency, or do we support any
> > > > set of 2?
> > > > ie for imx290, on 4 lanes do we want:
> > > > - 891Mbit/s for 1080p120 10bit
> > > > - 445.5Mbit/s for 1080p60 10 or 12 bit
> > > > - 594Mbit/s for 720p120 10bit
> > > > - 297Mbit/s for 720p60 10 and 12 bit
> > > > all to be present in DT?
> > > > If only 891 and 594 then you're limited to 10 bit images, but
> > > > otherwise it should be fully functional. The max frame interval would
> > > > be half that of 445.5 and 297 though, so there are compromises, but
> > > > who/what then controls the link_frequency to switch between the
> > > > ranges?
> > >
> > > It's up to the user space to set that control in a general case. I guess
> > > there are no specific rules on how many you should put to DT, but generally
> > > those that are useful should be there.
> > 
> > Does the driver have to support multiple sets of link frequencies
> > simultaneously?
> 
> It's up to the driver. A driver may support fewer features than the
> hardware allows, and with sensors this is commonly the case. So I don't
> think this would be special somehow. Of course if a driver supports just
> one and the DT has more, the end result may not be desirable in terms of
> what actually works.
> 
> With e.g. CCS the user can choose any link frequency for which there is a
> valid PLL tree configuration with current settings. Depending on e.g. the
> bit depth, for instance, some frequencies may be unavailable.
> 
> > The way the driver is currently written you have one link freq for
> > 1080p and one for 720p (2/3rds the rate used for 1080p). You could
> > retain using only 2 link frequencies at a time.
> > 
> > If DT/ACPI gives us 222.75MHz and 148.5MHz on 4 lanes, or 445.5MHz and
> > 297MHz on 2 lanes, with IMX327, IMX290 or IMX462, then use the current
> > configuration that can do 0.03 to 60fps as RAW10 or RAW12.
> > If DT/ACPI gives us 445.5MHz and 297MHz on 4 lanes and are on an
> > IMX290 (not IMX327), then use a new configuration that can do 0.06 to
> > 120fps as RAW10 only.
> > If DT/ACPI gives us 445.5MHz and 297MHz on 4 lanes and are on an
> > IMX462, then use a new configuration that can do 0.06 to 120fps as
> > RAW10 or RAW12.
> > If the configuration doesn't fall into any of these categories, then
> > it is rejected.
> 
> Seems reasonable.
> 
> > Whoever is putting together the DT/ACPI for the device can then choose
> > whether they value the lower minimum frame rate and RAW12, or the
> > higher frame rate but are prepared to sacrifice RAW12. (As we use
> > dtoverlays, we can add overrides so that person is the end user).
> > Trying to cram that lot in so that it can all be used simultaneously
> > will get quite ugly - the register configuration is not quite as
> > simple as one might hope, and you'd be filtering the permitted modes
> > and bit depths all over the place.
> > 
> > As I mentioned at the Media Summit in Dublin I've had users wanting
> > IMX462 for astronomy use cases, so halving the max exposure time by
> > dropping the current max 60fps configuration won't be popular. I guess
> > you could incorrectly use an IMX327 compatible string in the DT when
> > using an IMX290/462 to force the behaviour, but that feels even more
> > of a hack.
> > 
> > > I wonder why 12 bpp output isn't possible at the double frequency. Of
> > > course it is possible the sensor's clock tree makes that impossible but it
> > > is still unusual.
> > 
> > It is a little weird. As noted in the later emails, I have put
> > together settings to get 120fps running, and have tried it on both
> > IMX462 and IMX290.
> > 
> > 720p120 RAW12 works fine on both, as do 720p120 and 1080p120 in RAW10.
> > However 1080p120 RAW12 doesn't work on either, so I suspect it is
> > something in the CSI2 block configuration that can't quite hit that
> > data rate without further changes. I'll see if Sony wants to be
> > friendly with datasheets for the IMX462.
> 
> The receiver block driver could refuse to streamon if the pixel rate * bpp
> is too high. But I understand in this case it shouldn't be a limitation.
> And it doesn't really help the user to find which configurations would
> work.
> 
> > > > I can see another can of worms being opened here!
> > >
> > > If this is what the sensor does, how else it should be operated?
> > 
> > As above, link frequency remains read only based on DT or ACPI, and
> > that then restricts the configurations that are possible.
> > 
> > I've never seen a good userspace example of using
> > V4L2_CID_LINK_FREQUENCY, so without that it always seems to be a
> > setting that is generally only used by the CSI-2 receiver to adapt
> > appropriately to the data rate.
> > To my mind it falls into the same category as binning and cropping -
> > it's lovely to expose the full feature set, but that is just passing
> > the buck to some heuristics in userspace. Generally the user of the
> > camera doesn't care (they just want their camera to work) so
> > realistically you're looking at libcamera, and it doesn't necessarily
> > have sufficient information about the sensor or use case to make a
> > good decision.
> 
> The CCS driver changes the link frequency based on other configuration
> (mbus code) if the selected one cannot be used.
> 
> As this is a board specific configuration, fixing these values for a sensor
> is not a feasible approach in libcamera.

I'm with Dave here, I've never seen a good example of how userspace
should use the V4L2_CID_LINK_FREQUENCY control, or even of how the
frequencies listed in DT should be picked (for sensors that can
accommodate a wide range of link frequencies). Sakari, as you've been
the one who pushed for control of the link frequency from userspace,
could you enlighten us ? :-)

-- 
Regards,

Laurent Pinchart

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

end of thread, other threads:[~2023-01-14 16:03 UTC | newest]

Thread overview: 81+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-21  8:35 [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
2022-07-21  8:35 ` [PATCH 01/19] media: i2c: imx290: Use device lock for the control handler Laurent Pinchart
2022-07-21  9:22   ` Alexander Stein
2022-07-21  8:35 ` [PATCH 02/19] media: i2c: imx290: Print error code when I2C transfer fails Laurent Pinchart
2022-07-21  9:23   ` Alexander Stein
2022-07-21  8:35 ` [PATCH 03/19] media: i2c: imx290: Specify HMAX values in decimal Laurent Pinchart
2022-07-21  9:18   ` Alexander Stein
2022-07-21 11:31     ` Laurent Pinchart
2022-07-21 11:54       ` Alexander Stein
2022-07-21 12:04         ` Laurent Pinchart
2022-07-21  8:35 ` [PATCH 04/19] media: i2c: imx290: Replace macro with explicit ARRAY_SIZE() Laurent Pinchart
2022-07-21  9:23   ` Alexander Stein
2022-07-21  8:35 ` [PATCH 05/19] media: i2c: imx290: Drop imx290_write_buffered_reg() Laurent Pinchart
2022-07-21  9:24   ` Alexander Stein
2022-07-21  8:35 ` [PATCH 06/19] media: i2c: imx290: Drop regmap cache Laurent Pinchart
2022-07-21  9:27   ` Alexander Stein
2022-07-21  8:35 ` [PATCH 07/19] media: i2c: imx290: Support variable-sized registers Laurent Pinchart
2022-07-21  9:43   ` Alexander Stein
2022-07-21 10:54     ` Laurent Pinchart
2022-07-21 11:18       ` Alexander Stein
2022-07-21 11:25         ` Laurent Pinchart
2022-07-21 11:43           ` Alexander Stein
2022-07-22 14:37             ` Sakari Ailus
2022-07-23 23:06               ` Laurent Pinchart
2022-07-25  6:49                 ` Alexander Stein
2022-08-23  1:08                   ` Laurent Pinchart
2022-08-23  2:51                     ` Laurent Pinchart
2022-08-23  7:19                       ` Alexander Stein
2022-10-16  5:36                         ` Laurent Pinchart
2022-07-21  8:35 ` [PATCH 08/19] media: i2c: imx290: Correct register sizes Laurent Pinchart
2022-07-21  8:35 ` [PATCH 09/19] media: i2c: imx290: Simplify error handling when writing registers Laurent Pinchart
2022-07-21  9:50   ` Alexander Stein
2022-07-21  8:35 ` [PATCH 10/19] media: i2c: imx290: Define more register macros Laurent Pinchart
2022-07-21 10:00   ` Alexander Stein
2022-07-21 11:08     ` Laurent Pinchart
2022-07-21 11:28       ` Alexander Stein
2022-10-16  4:27         ` Laurent Pinchart
2022-07-21  8:35 ` [PATCH 11/19] media: i2c: imx290: Add exposure time control Laurent Pinchart
2022-07-21 10:01   ` Alexander Stein
2022-07-21 15:52   ` Dave Stevenson
2022-07-21  8:35 ` [PATCH 12/19] media: i2c: imx290: Fix max gain value Laurent Pinchart
2022-07-21 10:02   ` Alexander Stein
2022-07-21 16:08   ` Dave Stevenson
2022-10-16  4:51     ` Laurent Pinchart
2022-07-21  8:35 ` [PATCH 13/19] media: i2c: imx290: Split control initialization to separate function Laurent Pinchart
2022-07-21 10:03   ` Alexander Stein
2022-07-21  8:35 ` [PATCH 14/19] media: i2c: imx290: Implement HBLANK and VBLANK controls Laurent Pinchart
2022-07-21 10:05   ` Alexander Stein
2022-07-21 11:17     ` Laurent Pinchart
2022-07-21 11:32       ` Alexander Stein
2022-07-21 16:37         ` Dave Stevenson
2022-10-16  6:10           ` Laurent Pinchart
2022-10-17 13:46             ` Dave Stevenson
2022-07-21  8:35 ` [PATCH 15/19] media: i2c: imx290: Create controls for fwnode properties Laurent Pinchart
2022-07-21 10:06   ` Alexander Stein
2022-07-21  8:35 ` [PATCH 16/19] media: i2c: imx290: Move registers with fixed value to init array Laurent Pinchart
2022-07-21 10:08   ` Alexander Stein
2022-07-21 10:40     ` Laurent Pinchart
2022-07-21 11:08       ` Alexander Stein
2022-07-21 16:19         ` Dave Stevenson
2022-07-22  5:53           ` Alexander Stein
2022-07-22  9:10             ` Dave Stevenson
2022-07-21  8:35 ` [PATCH 17/19] media: i2c: imx290: Factor out format retrieval to separate function Laurent Pinchart
2022-07-21 10:11   ` Alexander Stein
2022-07-21 10:36     ` Laurent Pinchart
2022-07-21 11:12       ` Alexander Stein
2022-07-21  8:35 ` [PATCH 18/19] media: i2c: imx290: Add crop selection targets support Laurent Pinchart
2022-07-21 15:39   ` Dave Stevenson
2022-10-16  5:53     ` Laurent Pinchart
2022-07-21  8:35 ` [PATCH 19/19] media: i2c: imx290: Replace GAIN control with ANALOGUE_GAIN Laurent Pinchart
2022-07-21 10:11   ` Alexander Stein
2022-08-23  1:11 ` [PATCH 00/19] media: i2c: imx290: Miscellaneous improvements Laurent Pinchart
2022-10-10 10:31   ` Dave Stevenson
2022-10-16  5:37     ` Laurent Pinchart
2022-10-16  7:34       ` Dave Stevenson
2022-10-17 18:07         ` Dave Stevenson
2022-10-18 13:43           ` Dave Stevenson
2022-10-19 10:33           ` Sakari Ailus
2022-10-19 11:38             ` Dave Stevenson
2022-10-19 13:27               ` Sakari Ailus
2023-01-14 16:03                 ` Laurent Pinchart

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.