2021-06-16 13:33:48

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 00/15] media: gmsl: Reliability improvements

Hello,
series following:
v1: https://patchwork.linuxtv.org/project/linux-media/list/?series=4650
v2: https://patchwork.linuxtv.org/project/linux-media/list/?series=4861
v3: https://patchwork.linuxtv.org/project/linux-media/list/?series=4904
v4: https://patchwork.linuxtv.org/project/linux-media/list/?series=5149

I've dropped from this version the last two patches of the previous version
as it is still subject to discussion.

Compared to the previous version I've collected review tags and fixed some
minors in the commit messages.

I've tested on Eagle with RDACM20 and compared to the full series the success
rate is slightly lower (1 error on 20 boots) but still better than the current
mainline version.

On top of this series a rework of the initialization sequence deferring
resulting from Hans suggestions will follow.

Hans, can a pull request for this series be sent for v5.14 ?
I applied it on top of
https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=for-v5.14j
and found no issues.

Thanks
j

Jacopo Mondi (15):
media: i2c: max9286: Adjust parameters indent
media: i2c: max9286: Rename reverse_channel_mv
media: i2c: max9286: Cache channel amplitude
media: i2c: max9286: Define high channel amplitude
media: i2c: max9286: Rework comments in .bound()
media: i2c: max9271: Check max9271_write() return
media: i2c: max9271: Introduce wake_up() function
media: i2c: rdacm21: Add delay after OV490 reset
media: i2c: rdacm21: Fix OV10640 powerup
media: i2c: rdacm21: Power up OV10640 before OV490
media: i2c: rdacm20: Enable noise immunity
media: i2c: rdacm20: Embed 'serializer' field
media: i2c: rdacm20: Report camera module name
media: i2c: rdacm20: Check return values
media: i2c: rdacm20: Re-work ov10635 reset

drivers/media/i2c/max9271.c | 42 +++++++++++++++----
drivers/media/i2c/max9271.h | 9 ++++
drivers/media/i2c/max9286.c | 41 +++++++++---------
drivers/media/i2c/rdacm20.c | 84 +++++++++++++++++++++----------------
drivers/media/i2c/rdacm21.c | 67 +++++++++++++++++++----------
5 files changed, 161 insertions(+), 82 deletions(-)

--
2.31.1


2021-06-16 13:33:49

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 01/15] media: i2c: max9286: Adjust parameters indent

The parameters to max9286_i2c_mux_configure() fits on the previous
line. Adjust it.

Cosmetic change only.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
---
drivers/media/i2c/max9286.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index 6fd4d59fcc72..1d9951215868 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -287,9 +287,8 @@ static int max9286_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)

priv->mux_channel = chan;

- max9286_i2c_mux_configure(priv,
- MAX9286_FWDCCEN(chan) |
- MAX9286_REVCCEN(chan));
+ max9286_i2c_mux_configure(priv, MAX9286_FWDCCEN(chan) |
+ MAX9286_REVCCEN(chan));

return 0;
}
--
2.31.1

2021-06-16 13:34:26

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 04/15] media: i2c: max9286: Define high channel amplitude

Provide a macro to define the reverse channel amplitude to
be used to compensate the remote serializer noise immunity.

While at it, update a comment.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/max9286.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index ed1cdefe7c30..9124d5fa6ea3 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -113,6 +113,7 @@
#define MAX9286_REV_TRF(n) ((n) << 4)
#define MAX9286_REV_AMP(n) ((((n) - 30) / 10) << 1) /* in mV */
#define MAX9286_REV_AMP_X BIT(0)
+#define MAX9286_REV_AMP_HIGH 170
/* Register 0x3f */
#define MAX9286_EN_REV_CFG BIT(6)
#define MAX9286_REV_FLEN(n) ((n) - 20)
@@ -567,12 +568,12 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
* channels:
*
* - Increase the reverse channel amplitude to compensate for the
- * remote ends high threshold, if not done already
+ * remote ends high threshold
* - Verify all configuration links are properly detected
* - Disable auto-ack as communication on the control channel are now
* stable.
*/
- max9286_reverse_channel_setup(priv, 170);
+ max9286_reverse_channel_setup(priv, MAX9286_REV_AMP_HIGH);
max9286_check_config_link(priv, priv->source_mask);

/*
--
2.31.1

2021-06-16 13:35:49

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 05/15] media: i2c: max9286: Rework comments in .bound()

Rephrase a comment in .bound() callback to make it clear we register
a subdev notifier and remove a redundant comment about disabling i2c
auto-ack.

No functional changes intended.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/max9286.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index 9124d5fa6ea3..e1c7173f2d00 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -556,9 +556,9 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
subdev->name, src_pad, index);

/*
- * We can only register v4l2_async_notifiers, which do not provide a
- * means to register a complete callback. bound_sources allows us to
- * identify when all remote serializers have completed their probe.
+ * As we register a subdev notifiers we won't get a .complete() callback
+ * here, so we have to use bound_sources to identify when all remote
+ * serializers have probed.
*/
if (priv->bound_sources != priv->source_mask)
return 0;
@@ -575,11 +575,6 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
*/
max9286_reverse_channel_setup(priv, MAX9286_REV_AMP_HIGH);
max9286_check_config_link(priv, priv->source_mask);
-
- /*
- * Re-configure I2C with local acknowledge disabled after cameras have
- * probed.
- */
max9286_configure_i2c(priv, false);

return max9286_set_pixelrate(priv);
--
2.31.1

2021-06-16 13:36:38

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 06/15] media: i2c: max9271: Check max9271_write() return

Check the return value of the max9271_write() function in the
max9271 library driver.

While at it, modify an existing condition to be made identical
to other checks.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/max9271.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/media/i2c/max9271.c b/drivers/media/i2c/max9271.c
index c495582dcff6..2c7dc7fb9846 100644
--- a/drivers/media/i2c/max9271.c
+++ b/drivers/media/i2c/max9271.c
@@ -106,7 +106,10 @@ int max9271_set_serial_link(struct max9271_device *dev, bool enable)
* Short delays here appear to show bit-errors in the writes following.
* Therefore a conservative delay seems best here.
*/
- max9271_write(dev, 0x04, val);
+ ret = max9271_write(dev, 0x04, val);
+ if (ret < 0)
+ return ret;
+
usleep_range(5000, 8000);

return 0;
@@ -118,7 +121,7 @@ int max9271_configure_i2c(struct max9271_device *dev, u8 i2c_config)
int ret;

ret = max9271_write(dev, 0x0d, i2c_config);
- if (ret)
+ if (ret < 0)
return ret;

/* The delay required after an I2C bus configuration change is not
@@ -143,7 +146,10 @@ int max9271_set_high_threshold(struct max9271_device *dev, bool enable)
* Enable or disable reverse channel high threshold to increase
* immunity to power supply noise.
*/
- max9271_write(dev, 0x08, enable ? ret | BIT(0) : ret & ~BIT(0));
+ ret = max9271_write(dev, 0x08, enable ? ret | BIT(0) : ret & ~BIT(0));
+ if (ret < 0)
+ return ret;
+
usleep_range(2000, 2500);

return 0;
@@ -152,6 +158,8 @@ EXPORT_SYMBOL_GPL(max9271_set_high_threshold);

int max9271_configure_gmsl_link(struct max9271_device *dev)
{
+ int ret;
+
/*
* Configure the GMSL link:
*
@@ -162,16 +170,24 @@ int max9271_configure_gmsl_link(struct max9271_device *dev)
*
* TODO: Make the GMSL link configuration parametric.
*/
- max9271_write(dev, 0x07, MAX9271_DBL | MAX9271_HVEN |
- MAX9271_EDC_1BIT_PARITY);
+ ret = max9271_write(dev, 0x07, MAX9271_DBL | MAX9271_HVEN |
+ MAX9271_EDC_1BIT_PARITY);
+ if (ret < 0)
+ return ret;
+
usleep_range(5000, 8000);

/*
* Adjust spread spectrum to +4% and auto-detect pixel clock
* and serial link rate.
*/
- max9271_write(dev, 0x02, MAX9271_SPREAD_SPECT_4 | MAX9271_R02_RES |
- MAX9271_PCLK_AUTODETECT | MAX9271_SERIAL_AUTODETECT);
+ ret = max9271_write(dev, 0x02,
+ MAX9271_SPREAD_SPECT_4 | MAX9271_R02_RES |
+ MAX9271_PCLK_AUTODETECT |
+ MAX9271_SERIAL_AUTODETECT);
+ if (ret < 0)
+ return ret;
+
usleep_range(5000, 8000);

return 0;
--
2.31.1

2021-06-16 13:38:30

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 08/15] media: i2c: rdacm21: Add delay after OV490 reset

Add a delay after the OV490 chip is put in reset state. The reset
signal shall be held low for at least 250 useconds.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
---
drivers/media/i2c/rdacm21.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c
index 553e3f03752b..6be8ce130e78 100644
--- a/drivers/media/i2c/rdacm21.c
+++ b/drivers/media/i2c/rdacm21.c
@@ -469,7 +469,10 @@ static int rdacm21_initialize(struct rdacm21_device *dev)
if (ret)
return ret;

- /* Enable GPIO1 and hold OV490 in reset during max9271 configuration. */
+ /*
+ * Enable GPIO1 and hold OV490 in reset during max9271 configuration.
+ * The reset signal has to be asserted for at least 250 useconds.
+ */
ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;
@@ -477,6 +480,7 @@ static int rdacm21_initialize(struct rdacm21_device *dev)
ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;
+ usleep_range(250, 500);

ret = max9271_configure_gmsl_link(&dev->serializer);
if (ret)
--
2.31.1

2021-06-16 13:38:30

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 07/15] media: i2c: max9271: Introduce wake_up() function

The MAX9271 chip manual prescribes a delay of 5 milliseconds
after the chip exits from low power state.

Add a new function to the max9271 library driver that wakes up the chip
with a dummy i2c transaction and implements the correct delay of 5
milliseconds after the chip exits from low power state.

Use the newly introduced function in the rdacm20 and rdacm21 camera
drivers. The former was not respecting the required delay while the
latter was waiting for a too-short timeout.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/max9271.c | 12 ++++++++++++
drivers/media/i2c/max9271.h | 9 +++++++++
drivers/media/i2c/rdacm20.c | 4 +---
drivers/media/i2c/rdacm21.c | 5 +----
4 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/media/i2c/max9271.c b/drivers/media/i2c/max9271.c
index 2c7dc7fb9846..ff86c8c4ea61 100644
--- a/drivers/media/i2c/max9271.c
+++ b/drivers/media/i2c/max9271.c
@@ -80,6 +80,18 @@ static int max9271_pclk_detect(struct max9271_device *dev)
return -EIO;
}

+void max9271_wake_up(struct max9271_device *dev)
+{
+ /*
+ * Use the chip default address as this function has to be called
+ * before any other one.
+ */
+ dev->client->addr = MAX9271_DEFAULT_ADDR;
+ i2c_smbus_read_byte(dev->client);
+ usleep_range(5000, 8000);
+}
+EXPORT_SYMBOL_GPL(max9271_wake_up);
+
int max9271_set_serial_link(struct max9271_device *dev, bool enable)
{
int ret;
diff --git a/drivers/media/i2c/max9271.h b/drivers/media/i2c/max9271.h
index d78fb21441e9..dc5e4e70ba6f 100644
--- a/drivers/media/i2c/max9271.h
+++ b/drivers/media/i2c/max9271.h
@@ -85,6 +85,15 @@ struct max9271_device {
struct i2c_client *client;
};

+/**
+ * max9271_wake_up() - Wake up the serializer by issuing an i2c transaction
+ * @dev: The max9271 device
+ *
+ * This function shall be called before any other interaction with the
+ * serializer.
+ */
+void max9271_wake_up(struct max9271_device *dev);
+
/**
* max9271_set_serial_link() - Enable/disable serial link
* @dev: The max9271 device
diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index 90eb73f0e6e9..c1a717153303 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -455,9 +455,7 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
unsigned int retry = 3;
int ret;

- /* Verify communication with the MAX9271: ping to wakeup. */
- dev->serializer->client->addr = MAX9271_DEFAULT_ADDR;
- i2c_smbus_read_byte(dev->serializer->client);
+ max9271_wake_up(dev->serializer);

/* Serial link disabled during config as it needs a valid pixel clock. */
ret = max9271_set_serial_link(dev->serializer, false);
diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c
index 179d107f494c..553e3f03752b 100644
--- a/drivers/media/i2c/rdacm21.c
+++ b/drivers/media/i2c/rdacm21.c
@@ -450,10 +450,7 @@ static int rdacm21_initialize(struct rdacm21_device *dev)
{
int ret;

- /* Verify communication with the MAX9271: ping to wakeup. */
- dev->serializer.client->addr = MAX9271_DEFAULT_ADDR;
- i2c_smbus_read_byte(dev->serializer.client);
- usleep_range(3000, 5000);
+ max9271_wake_up(&dev->serializer);

/* Enable reverse channel and disable the serial link. */
ret = max9271_set_serial_link(&dev->serializer, false);
--
2.31.1

2021-06-16 13:39:29

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 10/15] media: i2c: rdacm21: Power up OV10640 before OV490

The current RDACM21 initialization routine powers up the OV10640 image
sensor after the OV490 ISP. The ISP is programmed with a firmare loaded
from an embedded serial flash that (most probably) tries to interact and
program also the image sensor connected to the ISP.

As described in commit "media: i2c: rdacm21: Fix OV10640 powerup" the
image sensor powerdown signal is kept high by an internal pull up
resistor and occasionally fails to startup correctly if the powerdown
line is not asserted explicitely. Failures in the OV10640 startup causes
the OV490 firmware to fail to boot correctly resulting in the camera
module initialization to fail consequentially.

Fix this by powering up the OV10640 image sensor before testing the
OV490 firmware boot completion, by splitting the ov10640_initialize()
function in an ov10640_power_up() one and an ov10640_check_id() one.

Also make sure the OV10640 identification procedure gives enough time to
the image sensor to resume after the programming phase performed by the
OV490 firmware by repeating the ID read procedure.

This commit fixes a sporadic start-up error triggered by a failure to
detect the OV490 firmware boot completion:
rdacm21 8-0054: Timeout waiting for firmware boot

Fixes: a59f853b3b4b ("media: i2c: Add driver for RDACM21 camera module")
Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/rdacm21.c | 46 ++++++++++++++++++++++++++-----------
1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c
index 7c0a4a84340a..43c41cb800a4 100644
--- a/drivers/media/i2c/rdacm21.c
+++ b/drivers/media/i2c/rdacm21.c
@@ -69,6 +69,7 @@
#define OV490_ISP_VSIZE_LOW 0x80820062
#define OV490_ISP_VSIZE_HIGH 0x80820063

+#define OV10640_PID_TIMEOUT 20
#define OV10640_ID_HIGH 0xa6
#define OV10640_CHIP_ID 0x300a
#define OV10640_PIXEL_RATE 55000000
@@ -329,10 +330,8 @@ static const struct v4l2_subdev_ops rdacm21_subdev_ops = {
.pad = &rdacm21_subdev_pad_ops,
};

-static int ov10640_initialize(struct rdacm21_device *dev)
+static void ov10640_power_up(struct rdacm21_device *dev)
{
- u8 val;
-
/* Enable GPIO0#0 (reset) and GPIO1#0 (pwdn) as output lines. */
ov490_write_reg(dev, OV490_GPIO_SEL0, OV490_GPIO0);
ov490_write_reg(dev, OV490_GPIO_SEL1, OV490_SPWDN0);
@@ -347,18 +346,35 @@ static int ov10640_initialize(struct rdacm21_device *dev)
usleep_range(1500, 3000);
ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, OV490_GPIO0);
usleep_range(3000, 5000);
+}

- /* Read OV10640 ID to test communications. */
- ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR, OV490_SCCB_SLAVE_READ);
- ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH, OV10640_CHIP_ID >> 8);
- ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW, OV10640_CHIP_ID & 0xff);
-
- /* Trigger SCCB slave transaction and give it some time to complete. */
- ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER);
- usleep_range(1000, 1500);
+static int ov10640_check_id(struct rdacm21_device *dev)
+{
+ unsigned int i;
+ u8 val;

- ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val);
- if (val != OV10640_ID_HIGH) {
+ /* Read OV10640 ID to test communications. */
+ for (i = 0; i < OV10640_PID_TIMEOUT; ++i) {
+ ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR,
+ OV490_SCCB_SLAVE_READ);
+ ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH,
+ OV10640_CHIP_ID >> 8);
+ ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW,
+ OV10640_CHIP_ID & 0xff);
+
+ /*
+ * Trigger SCCB slave transaction and give it some time
+ * to complete.
+ */
+ ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER);
+ usleep_range(1000, 1500);
+
+ ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val);
+ if (val == OV10640_ID_HIGH)
+ break;
+ usleep_range(1000, 1500);
+ }
+ if (i == OV10640_PID_TIMEOUT) {
dev_err(dev->dev, "OV10640 ID mismatch: (0x%02x)\n", val);
return -ENODEV;
}
@@ -374,6 +390,8 @@ static int ov490_initialize(struct rdacm21_device *dev)
unsigned int i;
int ret;

+ ov10640_power_up(dev);
+
/*
* Read OV490 Id to test communications. Give it up to 40msec to
* exit from reset.
@@ -411,7 +429,7 @@ static int ov490_initialize(struct rdacm21_device *dev)
return -ENODEV;
}

- ret = ov10640_initialize(dev);
+ ret = ov10640_check_id(dev);
if (ret)
return ret;

--
2.31.1

2021-06-16 13:39:29

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 09/15] media: i2c: rdacm21: Fix OV10640 powerup

The OV10640 image sensor powerdown signal is controlled by the first
line of the OV490 GPIO pad #1, but the pad #0 identifier
OV490_GPIO_OUTPUT_VALUE0 was erroneously used. As a result the image
sensor powerdown signal was never asserted but was left floating and
kept high by an internal pull-up resistor, causing sporadic failures
during the image sensor startup phase.

Fix this by using the correct GPIO pad identifier and wait the mandatory
1.5 millisecond delay after the powerup lane is asserted. The reset
delay is not characterized in the chip manual if not as "255 XVCLK +
initialization". Wait for at least 3 milliseconds to guarantee the SCCB
bus is available.

While at it also fix the reset sequence, as the reset line was released
before the powerdown one, and the line was not cycled.

This commit fixes a sporadic start-up error triggered by a failure to
read the OV10640 chip ID:
rdacm21 8-0054: OV10640 ID mismatch: (0x01)

Fixes: a59f853b3b4b ("media: i2c: Add driver for RDACM21 camera module")
Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/rdacm21.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c
index 6be8ce130e78..7c0a4a84340a 100644
--- a/drivers/media/i2c/rdacm21.c
+++ b/drivers/media/i2c/rdacm21.c
@@ -333,13 +333,19 @@ static int ov10640_initialize(struct rdacm21_device *dev)
{
u8 val;

- /* Power-up OV10640 by setting RESETB and PWDNB pins high. */
+ /* Enable GPIO0#0 (reset) and GPIO1#0 (pwdn) as output lines. */
ov490_write_reg(dev, OV490_GPIO_SEL0, OV490_GPIO0);
ov490_write_reg(dev, OV490_GPIO_SEL1, OV490_SPWDN0);
ov490_write_reg(dev, OV490_GPIO_DIRECTION0, OV490_GPIO0);
ov490_write_reg(dev, OV490_GPIO_DIRECTION1, OV490_SPWDN0);
+
+ /* Power up OV10640 and then reset it. */
+ ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE1, OV490_SPWDN0);
+ usleep_range(1500, 3000);
+
+ ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, 0x00);
+ usleep_range(1500, 3000);
ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, OV490_GPIO0);
- ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, OV490_SPWDN0);
usleep_range(3000, 5000);

/* Read OV10640 ID to test communications. */
--
2.31.1

2021-06-16 13:39:30

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 11/15] media: i2c: rdacm20: Enable noise immunity

Enable the noise immunity threshold at the end of the rdacm20
initialization routine.

The rdacm20 camera module has been so far tested with a startup
delay that allowed the embedded MCU to program the serializer. If
the initialization routine is run before the MCU programs the
serializer and the image sensor and their addresses gets changed
by the rdacm20 driver it is required to manually enable the noise
immunity threshold to make the communication on the control channel
more reliable.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
---
drivers/media/i2c/rdacm20.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index c1a717153303..5e0314a2b1ca 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -539,7 +539,19 @@ static int rdacm20_initialize(struct rdacm20_device *dev)

dev_info(dev->dev, "Identified MAX9271 + OV10635 device\n");

- return 0;
+ /*
+ * Set reverse channel high threshold to increase noise immunity.
+ *
+ * This should be compensated by increasing the reverse channel
+ * amplitude on the remote deserializer side.
+ *
+ * TODO Inspect the embedded MCU programming sequence to make sure
+ * there are no conflicts with the configuration applied here.
+ *
+ * TODO Clarify the embedded MCU startup delay to avoid write
+ * collisions on the I2C bus.
+ */
+ return max9271_set_high_threshold(&dev->serializer, true);
}

static int rdacm20_probe(struct i2c_client *client)
--
2.31.1

2021-06-16 13:39:30

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 12/15] media: i2c: rdacm20: Embed 'serializer' field

There's no reason to allocate dynamically the 'serializer' field in
the driver structure.

Embed the field and adjust all its users in the driver.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/rdacm20.c | 36 +++++++++++++++---------------------
1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index 5e0314a2b1ca..029af8fd7485 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -312,7 +312,7 @@ static const struct ov10635_reg {

struct rdacm20_device {
struct device *dev;
- struct max9271_device *serializer;
+ struct max9271_device serializer;
struct i2c_client *sensor;
struct v4l2_subdev sd;
struct media_pad pad;
@@ -399,7 +399,7 @@ static int rdacm20_s_stream(struct v4l2_subdev *sd, int enable)
{
struct rdacm20_device *dev = sd_to_rdacm20(sd);

- return max9271_set_serial_link(dev->serializer, enable);
+ return max9271_set_serial_link(&dev->serializer, enable);
}

static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
@@ -455,10 +455,10 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
unsigned int retry = 3;
int ret;

- max9271_wake_up(dev->serializer);
+ max9271_wake_up(&dev->serializer);

/* Serial link disabled during config as it needs a valid pixel clock. */
- ret = max9271_set_serial_link(dev->serializer, false);
+ ret = max9271_set_serial_link(&dev->serializer, false);
if (ret)
return ret;

@@ -466,35 +466,35 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
* Ensure that we have a good link configuration before attempting to
* identify the device.
*/
- max9271_configure_i2c(dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
- MAX9271_I2CSLVTO_1024US |
- MAX9271_I2CMSTBT_105KBPS);
+ max9271_configure_i2c(&dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
+ MAX9271_I2CSLVTO_1024US |
+ MAX9271_I2CMSTBT_105KBPS);

- max9271_configure_gmsl_link(dev->serializer);
+ max9271_configure_gmsl_link(&dev->serializer);

- ret = max9271_verify_id(dev->serializer);
+ ret = max9271_verify_id(&dev->serializer);
if (ret < 0)
return ret;

- ret = max9271_set_address(dev->serializer, dev->addrs[0]);
+ ret = max9271_set_address(&dev->serializer, dev->addrs[0]);
if (ret < 0)
return ret;
- dev->serializer->client->addr = dev->addrs[0];
+ dev->serializer.client->addr = dev->addrs[0];

/*
* Reset the sensor by cycling the OV10635 reset signal connected to the
* MAX9271 GPIO1 and verify communication with the OV10635.
*/
- ret = max9271_enable_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;

- ret = max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;
usleep_range(10000, 15000);

- ret = max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;
usleep_range(10000, 15000);
@@ -564,13 +564,7 @@ static int rdacm20_probe(struct i2c_client *client)
if (!dev)
return -ENOMEM;
dev->dev = &client->dev;
-
- dev->serializer = devm_kzalloc(&client->dev, sizeof(*dev->serializer),
- GFP_KERNEL);
- if (!dev->serializer)
- return -ENOMEM;
-
- dev->serializer->client = client;
+ dev->serializer.client = client;

ret = of_property_read_u32_array(client->dev.of_node, "reg",
dev->addrs, 2);
--
2.31.1

2021-06-16 13:39:40

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 15/15] media: i2c: rdacm20: Re-work ov10635 reset

The OV10635 image sensor embedded in the camera module is currently
reset after the MAX9271 initialization with two long delays that were
most probably not correctly characterized.

Re-work the image sensor reset procedure by holding the chip in reset
during the MAX9271 configuration, removing the long sleep delays and
only wait after the chip exits from reset for 350-500 microseconds
interval, which is larger than the minimum (2048 * (1 / XVCLK)) timeout
characterized in the chip manual.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/rdacm20.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index e6fed86a3281..cb725c2778c0 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -473,6 +473,19 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
if (ret)
return ret;

+ /*
+ * Hold OV10635 in reset during max9271 configuration. The reset signal
+ * has to be asserted for at least 200 microseconds.
+ */
+ ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
+ if (ret)
+ return ret;
+
+ ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
+ if (ret)
+ return ret;
+ usleep_range(200, 500);
+
ret = max9271_configure_gmsl_link(&dev->serializer);
if (ret)
return ret;
@@ -487,22 +500,14 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
dev->serializer.client->addr = dev->addrs[0];

/*
- * Reset the sensor by cycling the OV10635 reset signal connected to the
- * MAX9271 GPIO1 and verify communication with the OV10635.
+ * Release ov10635 from reset and initialize it. The image sensor
+ * requires at least 2048 XVCLK cycles (85 micro-seconds at 24MHz)
+ * before being available. Stay safe and wait up to 500 micro-seconds.
*/
- ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
- if (ret)
- return ret;
-
- ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
- if (ret)
- return ret;
- usleep_range(10000, 15000);
-
ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;
- usleep_range(10000, 15000);
+ usleep_range(100, 500);

again:
ret = ov10635_read16(dev, OV10635_PID);
--
2.31.1

2021-06-16 13:39:42

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 13/15] media: i2c: rdacm20: Report camera module name

When the device is identified the driver currently reports the
names of the chips embedded in the camera module.

Report the name of the camera module itself instead.
Cosmetic change only.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/rdacm20.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index 029af8fd7485..f1819bfa165d 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -537,7 +537,7 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
if (ret)
return ret;

- dev_info(dev->dev, "Identified MAX9271 + OV10635 device\n");
+ dev_info(dev->dev, "Identified RDACM20 camera module\n");

/*
* Set reverse channel high threshold to increase noise immunity.
--
2.31.1

2021-06-16 13:39:59

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 14/15] media: i2c: rdacm20: Check return values

The camera module initialization routine does not check the return
value of a few functions. Fix that.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/rdacm20.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index f1819bfa165d..e6fed86a3281 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -466,11 +466,16 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
* Ensure that we have a good link configuration before attempting to
* identify the device.
*/
- max9271_configure_i2c(&dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
- MAX9271_I2CSLVTO_1024US |
- MAX9271_I2CMSTBT_105KBPS);
+ ret = max9271_configure_i2c(&dev->serializer,
+ MAX9271_I2CSLVSH_469NS_234NS |
+ MAX9271_I2CSLVTO_1024US |
+ MAX9271_I2CMSTBT_105KBPS);
+ if (ret)
+ return ret;

- max9271_configure_gmsl_link(&dev->serializer);
+ ret = max9271_configure_gmsl_link(&dev->serializer);
+ if (ret)
+ return ret;

ret = max9271_verify_id(&dev->serializer);
if (ret < 0)
--
2.31.1

2021-06-16 18:25:53

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 02/15] media: i2c: max9286: Rename reverse_channel_mv

Rename the reverse_channel_mv variable to init_rev_chan_mv as
the next patch will cache the reverse channel amplitude in
a new driver variable.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/max9286.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index 1d9951215868..82ec05e96cb7 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -163,7 +163,8 @@ struct max9286_priv {
unsigned int mux_channel;
bool mux_open;

- u32 reverse_channel_mv;
+ /* The initial reverse control channel amplitude. */
+ u32 init_rev_chan_mv;

struct v4l2_ctrl_handler ctrls;
struct v4l2_ctrl *pixelrate;
@@ -563,7 +564,7 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
* - Disable auto-ack as communication on the control channel are now
* stable.
*/
- if (priv->reverse_channel_mv < 170)
+ if (priv->init_rev_chan_mv < 170)
max9286_reverse_channel_setup(priv, 170);
max9286_check_config_link(priv, priv->source_mask);

@@ -971,7 +972,7 @@ static int max9286_setup(struct max9286_priv *priv)
* only. This should be disabled after the mux is initialised.
*/
max9286_configure_i2c(priv, true);
- max9286_reverse_channel_setup(priv, priv->reverse_channel_mv);
+ max9286_reverse_channel_setup(priv, priv->init_rev_chan_mv);

/*
* Enable GMSL links, mask unused ones and autodetect link
@@ -1236,9 +1237,9 @@ static int max9286_parse_dt(struct max9286_priv *priv)
if (of_property_read_u32(dev->of_node,
"maxim,reverse-channel-microvolt",
&reverse_channel_microvolt))
- priv->reverse_channel_mv = 170;
+ priv->init_rev_chan_mv = 170;
else
- priv->reverse_channel_mv = reverse_channel_microvolt / 1000U;
+ priv->init_rev_chan_mv = reverse_channel_microvolt / 1000U;

priv->route_mask = priv->source_mask;

--
2.31.1

2021-06-16 18:31:27

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH v5 03/15] media: i2c: max9286: Cache channel amplitude

Cache the current channel amplitude in a driver variable
to skip updating it if the newly requested value is the same
as the currently configured one.

Signed-off-by: Jacopo Mondi <[email protected]>
Reviewed-by: Kieran Bingham <[email protected]>
Reviewed-by: Laurent Pinchart <[email protected]>
---
drivers/media/i2c/max9286.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
index 82ec05e96cb7..ed1cdefe7c30 100644
--- a/drivers/media/i2c/max9286.c
+++ b/drivers/media/i2c/max9286.c
@@ -165,6 +165,7 @@ struct max9286_priv {

/* The initial reverse control channel amplitude. */
u32 init_rev_chan_mv;
+ u32 rev_chan_mv;

struct v4l2_ctrl_handler ctrls;
struct v4l2_ctrl *pixelrate;
@@ -341,8 +342,15 @@ static void max9286_configure_i2c(struct max9286_priv *priv, bool localack)
static void max9286_reverse_channel_setup(struct max9286_priv *priv,
unsigned int chan_amplitude)
{
+ u8 chan_config;
+
+ if (priv->rev_chan_mv == chan_amplitude)
+ return;
+
+ priv->rev_chan_mv = chan_amplitude;
+
/* Reverse channel transmission time: default to 1. */
- u8 chan_config = MAX9286_REV_TRF(1);
+ chan_config = MAX9286_REV_TRF(1);

/*
* Reverse channel setup.
@@ -564,8 +572,7 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
* - Disable auto-ack as communication on the control channel are now
* stable.
*/
- if (priv->init_rev_chan_mv < 170)
- max9286_reverse_channel_setup(priv, 170);
+ max9286_reverse_channel_setup(priv, 170);
max9286_check_config_link(priv, priv->source_mask);

/*
--
2.31.1

2021-06-17 02:40:12

by Kieran Bingham

[permalink] [raw]
Subject: Re: [PATCH v5 10/15] media: i2c: rdacm21: Power up OV10640 before OV490

Hi Jacopo,

Hrm - this seems to be the only one in this series without my RB tag, so
lets take a look.


On 16/06/2021 13:46, Jacopo Mondi wrote:
> The current RDACM21 initialization routine powers up the OV10640 image
> sensor after the OV490 ISP. The ISP is programmed with a firmare loaded

s/firmare/firmware/

> from an embedded serial flash that (most probably) tries to interact and
> program also the image sensor connected to the ISP.
>
> As described in commit "media: i2c: rdacm21: Fix OV10640 powerup" the
> image sensor powerdown signal is kept high by an internal pull up
> resistor and occasionally fails to startup correctly if the powerdown
> line is not asserted explicitely. Failures in the OV10640 startup causes

s/explicitely/explicitly/


> the OV490 firmware to fail to boot correctly resulting in the camera
> module initialization to fail consequentially.
>
> Fix this by powering up the OV10640 image sensor before testing the
> OV490 firmware boot completion, by splitting the ov10640_initialize()
> function in an ov10640_power_up() one and an ov10640_check_id() one.
>
> Also make sure the OV10640 identification procedure gives enough time to
> the image sensor to resume after the programming phase performed by the
> OV490 firmware by repeating the ID read procedure.
>
> This commit fixes a sporadic start-up error triggered by a failure to
> detect the OV490 firmware boot completion:
> rdacm21 8-0054: Timeout waiting for firmware boot
>
> Fixes: a59f853b3b4b ("media: i2c: Add driver for RDACM21 camera module")
> Signed-off-by: Jacopo Mondi <[email protected]>

Reviewed-by: Kieran Bingham <[email protected]>

> Reviewed-by: Laurent Pinchart <[email protected]>
> ---
> drivers/media/i2c/rdacm21.c | 46 ++++++++++++++++++++++++++-----------
> 1 file changed, 32 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c
> index 7c0a4a84340a..43c41cb800a4 100644
> --- a/drivers/media/i2c/rdacm21.c
> +++ b/drivers/media/i2c/rdacm21.c
> @@ -69,6 +69,7 @@
> #define OV490_ISP_VSIZE_LOW 0x80820062
> #define OV490_ISP_VSIZE_HIGH 0x80820063
>
> +#define OV10640_PID_TIMEOUT 20
> #define OV10640_ID_HIGH 0xa6
> #define OV10640_CHIP_ID 0x300a
> #define OV10640_PIXEL_RATE 55000000
> @@ -329,10 +330,8 @@ static const struct v4l2_subdev_ops rdacm21_subdev_ops = {
> .pad = &rdacm21_subdev_pad_ops,
> };
>
> -static int ov10640_initialize(struct rdacm21_device *dev)
> +static void ov10640_power_up(struct rdacm21_device *dev)
> {
> - u8 val;
> -
> /* Enable GPIO0#0 (reset) and GPIO1#0 (pwdn) as output lines. */
> ov490_write_reg(dev, OV490_GPIO_SEL0, OV490_GPIO0);
> ov490_write_reg(dev, OV490_GPIO_SEL1, OV490_SPWDN0);
> @@ -347,18 +346,35 @@ static int ov10640_initialize(struct rdacm21_device *dev)
> usleep_range(1500, 3000);
> ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, OV490_GPIO0);
> usleep_range(3000, 5000);
> +}
>
> - /* Read OV10640 ID to test communications. */
> - ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR, OV490_SCCB_SLAVE_READ);
> - ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH, OV10640_CHIP_ID >> 8);
> - ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW, OV10640_CHIP_ID & 0xff);
> -
> - /* Trigger SCCB slave transaction and give it some time to complete. */
> - ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER);
> - usleep_range(1000, 1500);
> +static int ov10640_check_id(struct rdacm21_device *dev)
> +{
> + unsigned int i;
> + u8 val;
>
> - ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val);
> - if (val != OV10640_ID_HIGH) {
> + /* Read OV10640 ID to test communications. */
> + for (i = 0; i < OV10640_PID_TIMEOUT; ++i) {
> + ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR,
> + OV490_SCCB_SLAVE_READ);
> + ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH,
> + OV10640_CHIP_ID >> 8);
> + ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW,
> + OV10640_CHIP_ID & 0xff);
> +
> + /*
> + * Trigger SCCB slave transaction and give it some time
> + * to complete.
> + */
> + ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER);
> + usleep_range(1000, 1500);
> +
> + ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val);
> + if (val == OV10640_ID_HIGH)
> + break;
> + usleep_range(1000, 1500);
> + }
> + if (i == OV10640_PID_TIMEOUT) {
> dev_err(dev->dev, "OV10640 ID mismatch: (0x%02x)\n", val);
> return -ENODEV;
> }
> @@ -374,6 +390,8 @@ static int ov490_initialize(struct rdacm21_device *dev)
> unsigned int i;
> int ret;
>
> + ov10640_power_up(dev);
> +
> /*
> * Read OV490 Id to test communications. Give it up to 40msec to
> * exit from reset.
> @@ -411,7 +429,7 @@ static int ov490_initialize(struct rdacm21_device *dev)
> return -ENODEV;
> }
>
> - ret = ov10640_initialize(dev);
> + ret = ov10640_check_id(dev);
> if (ret)
> return ret;
>
>

2021-06-17 02:41:17

by Laurent Pinchart

[permalink] [raw]
Subject: Re: [PATCH v5 12/15] media: i2c: rdacm20: Embed 'serializer' field

Hi Jacopo,

Thank you for the patch.

This should be moved before 11/15 to avoid a bisection breakage (or
11/15 should be fixed, and this patch updated accordingly).

On Wed, Jun 16, 2021 at 02:46:13PM +0200, Jacopo Mondi wrote:
> There's no reason to allocate dynamically the 'serializer' field in
> the driver structure.
>
> Embed the field and adjust all its users in the driver.
>
> Signed-off-by: Jacopo Mondi <[email protected]>
> Reviewed-by: Kieran Bingham <[email protected]>
> Reviewed-by: Laurent Pinchart <[email protected]>
> ---
> drivers/media/i2c/rdacm20.c | 36 +++++++++++++++---------------------
> 1 file changed, 15 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
> index 5e0314a2b1ca..029af8fd7485 100644
> --- a/drivers/media/i2c/rdacm20.c
> +++ b/drivers/media/i2c/rdacm20.c
> @@ -312,7 +312,7 @@ static const struct ov10635_reg {
>
> struct rdacm20_device {
> struct device *dev;
> - struct max9271_device *serializer;
> + struct max9271_device serializer;
> struct i2c_client *sensor;
> struct v4l2_subdev sd;
> struct media_pad pad;
> @@ -399,7 +399,7 @@ static int rdacm20_s_stream(struct v4l2_subdev *sd, int enable)
> {
> struct rdacm20_device *dev = sd_to_rdacm20(sd);
>
> - return max9271_set_serial_link(dev->serializer, enable);
> + return max9271_set_serial_link(&dev->serializer, enable);
> }
>
> static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
> @@ -455,10 +455,10 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
> unsigned int retry = 3;
> int ret;
>
> - max9271_wake_up(dev->serializer);
> + max9271_wake_up(&dev->serializer);
>
> /* Serial link disabled during config as it needs a valid pixel clock. */
> - ret = max9271_set_serial_link(dev->serializer, false);
> + ret = max9271_set_serial_link(&dev->serializer, false);
> if (ret)
> return ret;
>
> @@ -466,35 +466,35 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
> * Ensure that we have a good link configuration before attempting to
> * identify the device.
> */
> - max9271_configure_i2c(dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
> - MAX9271_I2CSLVTO_1024US |
> - MAX9271_I2CMSTBT_105KBPS);
> + max9271_configure_i2c(&dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
> + MAX9271_I2CSLVTO_1024US |
> + MAX9271_I2CMSTBT_105KBPS);
>
> - max9271_configure_gmsl_link(dev->serializer);
> + max9271_configure_gmsl_link(&dev->serializer);
>
> - ret = max9271_verify_id(dev->serializer);
> + ret = max9271_verify_id(&dev->serializer);
> if (ret < 0)
> return ret;
>
> - ret = max9271_set_address(dev->serializer, dev->addrs[0]);
> + ret = max9271_set_address(&dev->serializer, dev->addrs[0]);
> if (ret < 0)
> return ret;
> - dev->serializer->client->addr = dev->addrs[0];
> + dev->serializer.client->addr = dev->addrs[0];
>
> /*
> * Reset the sensor by cycling the OV10635 reset signal connected to the
> * MAX9271 GPIO1 and verify communication with the OV10635.
> */
> - ret = max9271_enable_gpios(dev->serializer, MAX9271_GPIO1OUT);
> + ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> if (ret)
> return ret;
>
> - ret = max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
> + ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> if (ret)
> return ret;
> usleep_range(10000, 15000);
>
> - ret = max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
> + ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> if (ret)
> return ret;
> usleep_range(10000, 15000);
> @@ -564,13 +564,7 @@ static int rdacm20_probe(struct i2c_client *client)
> if (!dev)
> return -ENOMEM;
> dev->dev = &client->dev;
> -
> - dev->serializer = devm_kzalloc(&client->dev, sizeof(*dev->serializer),
> - GFP_KERNEL);
> - if (!dev->serializer)
> - return -ENOMEM;
> -
> - dev->serializer->client = client;
> + dev->serializer.client = client;
>
> ret = of_property_read_u32_array(client->dev.of_node, "reg",
> dev->addrs, 2);

--
Regards,

Laurent Pinchart

2021-06-17 06:20:08

by Hans Verkuil

[permalink] [raw]
Subject: Re: [PATCH v5 12/15] media: i2c: rdacm20: Embed 'serializer' field

On 17/06/2021 02:14, Laurent Pinchart wrote:
> Hi Jacopo,
>
> Thank you for the patch.
>
> This should be moved before 11/15 to avoid a bisection breakage (or
> 11/15 should be fixed, and this patch updated accordingly).

Good catch!

Jacopo, I dropped the PR I made. It you just want to swap patch 11 and 12,
then I can do that, if you want more extensive changes, then I need a v6.

Let me know what you want.

Hans

>
> On Wed, Jun 16, 2021 at 02:46:13PM +0200, Jacopo Mondi wrote:
>> There's no reason to allocate dynamically the 'serializer' field in
>> the driver structure.
>>
>> Embed the field and adjust all its users in the driver.
>>
>> Signed-off-by: Jacopo Mondi <[email protected]>
>> Reviewed-by: Kieran Bingham <[email protected]>
>> Reviewed-by: Laurent Pinchart <[email protected]>
>> ---
>> drivers/media/i2c/rdacm20.c | 36 +++++++++++++++---------------------
>> 1 file changed, 15 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
>> index 5e0314a2b1ca..029af8fd7485 100644
>> --- a/drivers/media/i2c/rdacm20.c
>> +++ b/drivers/media/i2c/rdacm20.c
>> @@ -312,7 +312,7 @@ static const struct ov10635_reg {
>>
>> struct rdacm20_device {
>> struct device *dev;
>> - struct max9271_device *serializer;
>> + struct max9271_device serializer;
>> struct i2c_client *sensor;
>> struct v4l2_subdev sd;
>> struct media_pad pad;
>> @@ -399,7 +399,7 @@ static int rdacm20_s_stream(struct v4l2_subdev *sd, int enable)
>> {
>> struct rdacm20_device *dev = sd_to_rdacm20(sd);
>>
>> - return max9271_set_serial_link(dev->serializer, enable);
>> + return max9271_set_serial_link(&dev->serializer, enable);
>> }
>>
>> static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
>> @@ -455,10 +455,10 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
>> unsigned int retry = 3;
>> int ret;
>>
>> - max9271_wake_up(dev->serializer);
>> + max9271_wake_up(&dev->serializer);
>>
>> /* Serial link disabled during config as it needs a valid pixel clock. */
>> - ret = max9271_set_serial_link(dev->serializer, false);
>> + ret = max9271_set_serial_link(&dev->serializer, false);
>> if (ret)
>> return ret;
>>
>> @@ -466,35 +466,35 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
>> * Ensure that we have a good link configuration before attempting to
>> * identify the device.
>> */
>> - max9271_configure_i2c(dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
>> - MAX9271_I2CSLVTO_1024US |
>> - MAX9271_I2CMSTBT_105KBPS);
>> + max9271_configure_i2c(&dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
>> + MAX9271_I2CSLVTO_1024US |
>> + MAX9271_I2CMSTBT_105KBPS);
>>
>> - max9271_configure_gmsl_link(dev->serializer);
>> + max9271_configure_gmsl_link(&dev->serializer);
>>
>> - ret = max9271_verify_id(dev->serializer);
>> + ret = max9271_verify_id(&dev->serializer);
>> if (ret < 0)
>> return ret;
>>
>> - ret = max9271_set_address(dev->serializer, dev->addrs[0]);
>> + ret = max9271_set_address(&dev->serializer, dev->addrs[0]);
>> if (ret < 0)
>> return ret;
>> - dev->serializer->client->addr = dev->addrs[0];
>> + dev->serializer.client->addr = dev->addrs[0];
>>
>> /*
>> * Reset the sensor by cycling the OV10635 reset signal connected to the
>> * MAX9271 GPIO1 and verify communication with the OV10635.
>> */
>> - ret = max9271_enable_gpios(dev->serializer, MAX9271_GPIO1OUT);
>> + ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
>> if (ret)
>> return ret;
>>
>> - ret = max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
>> + ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
>> if (ret)
>> return ret;
>> usleep_range(10000, 15000);
>>
>> - ret = max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
>> + ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
>> if (ret)
>> return ret;
>> usleep_range(10000, 15000);
>> @@ -564,13 +564,7 @@ static int rdacm20_probe(struct i2c_client *client)
>> if (!dev)
>> return -ENOMEM;
>> dev->dev = &client->dev;
>> -
>> - dev->serializer = devm_kzalloc(&client->dev, sizeof(*dev->serializer),
>> - GFP_KERNEL);
>> - if (!dev->serializer)
>> - return -ENOMEM;
>> -
>> - dev->serializer->client = client;
>> + dev->serializer.client = client;
>>
>> ret = of_property_read_u32_array(client->dev.of_node, "reg",
>> dev->addrs, 2);
>

2021-06-17 07:51:07

by jacopo mondi

[permalink] [raw]
Subject: Re: [PATCH v5 12/15] media: i2c: rdacm20: Embed 'serializer' field

Hello,

On Thu, Jun 17, 2021 at 08:18:42AM +0200, Hans Verkuil wrote:
> On 17/06/2021 02:14, Laurent Pinchart wrote:
> > Hi Jacopo,
> >
> > Thank you for the patch.
> >
> > This should be moved before 11/15 to avoid a bisection breakage (or
> > 11/15 should be fixed, and this patch updated accordingly).
>
> Good catch!

Good catch indeed... Sorry about this I shuffled patches around
multiple times and missed this one

>
> Jacopo, I dropped the PR I made. It you just want to swap patch 11 and 12,
> then I can do that, if you want more extensive changes, then I need a v6.
>
> Let me know what you want.

I think swapping 11 and 12 is enough, thanks for handling it.
(BTW there's one additional tag from Kieran to collect which is not in
v5. Would you like a v6 for that ?)

Thanks
j

>
> Hans
>
> >
> > On Wed, Jun 16, 2021 at 02:46:13PM +0200, Jacopo Mondi wrote:
> >> There's no reason to allocate dynamically the 'serializer' field in
> >> the driver structure.
> >>
> >> Embed the field and adjust all its users in the driver.
> >>
> >> Signed-off-by: Jacopo Mondi <[email protected]>
> >> Reviewed-by: Kieran Bingham <[email protected]>
> >> Reviewed-by: Laurent Pinchart <[email protected]>
> >> ---
> >> drivers/media/i2c/rdacm20.c | 36 +++++++++++++++---------------------
> >> 1 file changed, 15 insertions(+), 21 deletions(-)
> >>
> >> diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
> >> index 5e0314a2b1ca..029af8fd7485 100644
> >> --- a/drivers/media/i2c/rdacm20.c
> >> +++ b/drivers/media/i2c/rdacm20.c
> >> @@ -312,7 +312,7 @@ static const struct ov10635_reg {
> >>
> >> struct rdacm20_device {
> >> struct device *dev;
> >> - struct max9271_device *serializer;
> >> + struct max9271_device serializer;
> >> struct i2c_client *sensor;
> >> struct v4l2_subdev sd;
> >> struct media_pad pad;
> >> @@ -399,7 +399,7 @@ static int rdacm20_s_stream(struct v4l2_subdev *sd, int enable)
> >> {
> >> struct rdacm20_device *dev = sd_to_rdacm20(sd);
> >>
> >> - return max9271_set_serial_link(dev->serializer, enable);
> >> + return max9271_set_serial_link(&dev->serializer, enable);
> >> }
> >>
> >> static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
> >> @@ -455,10 +455,10 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
> >> unsigned int retry = 3;
> >> int ret;
> >>
> >> - max9271_wake_up(dev->serializer);
> >> + max9271_wake_up(&dev->serializer);
> >>
> >> /* Serial link disabled during config as it needs a valid pixel clock. */
> >> - ret = max9271_set_serial_link(dev->serializer, false);
> >> + ret = max9271_set_serial_link(&dev->serializer, false);
> >> if (ret)
> >> return ret;
> >>
> >> @@ -466,35 +466,35 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
> >> * Ensure that we have a good link configuration before attempting to
> >> * identify the device.
> >> */
> >> - max9271_configure_i2c(dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
> >> - MAX9271_I2CSLVTO_1024US |
> >> - MAX9271_I2CMSTBT_105KBPS);
> >> + max9271_configure_i2c(&dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
> >> + MAX9271_I2CSLVTO_1024US |
> >> + MAX9271_I2CMSTBT_105KBPS);
> >>
> >> - max9271_configure_gmsl_link(dev->serializer);
> >> + max9271_configure_gmsl_link(&dev->serializer);
> >>
> >> - ret = max9271_verify_id(dev->serializer);
> >> + ret = max9271_verify_id(&dev->serializer);
> >> if (ret < 0)
> >> return ret;
> >>
> >> - ret = max9271_set_address(dev->serializer, dev->addrs[0]);
> >> + ret = max9271_set_address(&dev->serializer, dev->addrs[0]);
> >> if (ret < 0)
> >> return ret;
> >> - dev->serializer->client->addr = dev->addrs[0];
> >> + dev->serializer.client->addr = dev->addrs[0];
> >>
> >> /*
> >> * Reset the sensor by cycling the OV10635 reset signal connected to the
> >> * MAX9271 GPIO1 and verify communication with the OV10635.
> >> */
> >> - ret = max9271_enable_gpios(dev->serializer, MAX9271_GPIO1OUT);
> >> + ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> >> if (ret)
> >> return ret;
> >>
> >> - ret = max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
> >> + ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> >> if (ret)
> >> return ret;
> >> usleep_range(10000, 15000);
> >>
> >> - ret = max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
> >> + ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> >> if (ret)
> >> return ret;
> >> usleep_range(10000, 15000);
> >> @@ -564,13 +564,7 @@ static int rdacm20_probe(struct i2c_client *client)
> >> if (!dev)
> >> return -ENOMEM;
> >> dev->dev = &client->dev;
> >> -
> >> - dev->serializer = devm_kzalloc(&client->dev, sizeof(*dev->serializer),
> >> - GFP_KERNEL);
> >> - if (!dev->serializer)
> >> - return -ENOMEM;
> >> -
> >> - dev->serializer->client = client;
> >> + dev->serializer.client = client;
> >>
> >> ret = of_property_read_u32_array(client->dev.of_node, "reg",
> >> dev->addrs, 2);
> >
>

2021-06-17 08:15:52

by Hans Verkuil

[permalink] [raw]
Subject: Re: [PATCH v5 12/15] media: i2c: rdacm20: Embed 'serializer' field

On 17/06/2021 09:42, Jacopo Mondi wrote:
> Hello,
>
> On Thu, Jun 17, 2021 at 08:18:42AM +0200, Hans Verkuil wrote:
>> On 17/06/2021 02:14, Laurent Pinchart wrote:
>>> Hi Jacopo,
>>>
>>> Thank you for the patch.
>>>
>>> This should be moved before 11/15 to avoid a bisection breakage (or
>>> 11/15 should be fixed, and this patch updated accordingly).
>>
>> Good catch!
>
> Good catch indeed... Sorry about this I shuffled patches around
> multiple times and missed this one
>
>>
>> Jacopo, I dropped the PR I made. It you just want to swap patch 11 and 12,
>> then I can do that, if you want more extensive changes, then I need a v6.
>>
>> Let me know what you want.
>
> I think swapping 11 and 12 is enough, thanks for handling it.
> (BTW there's one additional tag from Kieran to collect which is not in
> v5. Would you like a v6 for that ?)

Updated the PR and added Kieran's tag. So no need for you to do anything.

Regards,

Hans

>
> Thanks
> j
>
>>
>> Hans
>>
>>>
>>> On Wed, Jun 16, 2021 at 02:46:13PM +0200, Jacopo Mondi wrote:
>>>> There's no reason to allocate dynamically the 'serializer' field in
>>>> the driver structure.
>>>>
>>>> Embed the field and adjust all its users in the driver.
>>>>
>>>> Signed-off-by: Jacopo Mondi <[email protected]>
>>>> Reviewed-by: Kieran Bingham <[email protected]>
>>>> Reviewed-by: Laurent Pinchart <[email protected]>
>>>> ---
>>>> drivers/media/i2c/rdacm20.c | 36 +++++++++++++++---------------------
>>>> 1 file changed, 15 insertions(+), 21 deletions(-)
>>>>
>>>> diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
>>>> index 5e0314a2b1ca..029af8fd7485 100644
>>>> --- a/drivers/media/i2c/rdacm20.c
>>>> +++ b/drivers/media/i2c/rdacm20.c
>>>> @@ -312,7 +312,7 @@ static const struct ov10635_reg {
>>>>
>>>> struct rdacm20_device {
>>>> struct device *dev;
>>>> - struct max9271_device *serializer;
>>>> + struct max9271_device serializer;
>>>> struct i2c_client *sensor;
>>>> struct v4l2_subdev sd;
>>>> struct media_pad pad;
>>>> @@ -399,7 +399,7 @@ static int rdacm20_s_stream(struct v4l2_subdev *sd, int enable)
>>>> {
>>>> struct rdacm20_device *dev = sd_to_rdacm20(sd);
>>>>
>>>> - return max9271_set_serial_link(dev->serializer, enable);
>>>> + return max9271_set_serial_link(&dev->serializer, enable);
>>>> }
>>>>
>>>> static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
>>>> @@ -455,10 +455,10 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
>>>> unsigned int retry = 3;
>>>> int ret;
>>>>
>>>> - max9271_wake_up(dev->serializer);
>>>> + max9271_wake_up(&dev->serializer);
>>>>
>>>> /* Serial link disabled during config as it needs a valid pixel clock. */
>>>> - ret = max9271_set_serial_link(dev->serializer, false);
>>>> + ret = max9271_set_serial_link(&dev->serializer, false);
>>>> if (ret)
>>>> return ret;
>>>>
>>>> @@ -466,35 +466,35 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
>>>> * Ensure that we have a good link configuration before attempting to
>>>> * identify the device.
>>>> */
>>>> - max9271_configure_i2c(dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
>>>> - MAX9271_I2CSLVTO_1024US |
>>>> - MAX9271_I2CMSTBT_105KBPS);
>>>> + max9271_configure_i2c(&dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
>>>> + MAX9271_I2CSLVTO_1024US |
>>>> + MAX9271_I2CMSTBT_105KBPS);
>>>>
>>>> - max9271_configure_gmsl_link(dev->serializer);
>>>> + max9271_configure_gmsl_link(&dev->serializer);
>>>>
>>>> - ret = max9271_verify_id(dev->serializer);
>>>> + ret = max9271_verify_id(&dev->serializer);
>>>> if (ret < 0)
>>>> return ret;
>>>>
>>>> - ret = max9271_set_address(dev->serializer, dev->addrs[0]);
>>>> + ret = max9271_set_address(&dev->serializer, dev->addrs[0]);
>>>> if (ret < 0)
>>>> return ret;
>>>> - dev->serializer->client->addr = dev->addrs[0];
>>>> + dev->serializer.client->addr = dev->addrs[0];
>>>>
>>>> /*
>>>> * Reset the sensor by cycling the OV10635 reset signal connected to the
>>>> * MAX9271 GPIO1 and verify communication with the OV10635.
>>>> */
>>>> - ret = max9271_enable_gpios(dev->serializer, MAX9271_GPIO1OUT);
>>>> + ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
>>>> if (ret)
>>>> return ret;
>>>>
>>>> - ret = max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
>>>> + ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
>>>> if (ret)
>>>> return ret;
>>>> usleep_range(10000, 15000);
>>>>
>>>> - ret = max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
>>>> + ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
>>>> if (ret)
>>>> return ret;
>>>> usleep_range(10000, 15000);
>>>> @@ -564,13 +564,7 @@ static int rdacm20_probe(struct i2c_client *client)
>>>> if (!dev)
>>>> return -ENOMEM;
>>>> dev->dev = &client->dev;
>>>> -
>>>> - dev->serializer = devm_kzalloc(&client->dev, sizeof(*dev->serializer),
>>>> - GFP_KERNEL);
>>>> - if (!dev->serializer)
>>>> - return -ENOMEM;
>>>> -
>>>> - dev->serializer->client = client;
>>>> + dev->serializer.client = client;
>>>>
>>>> ret = of_property_read_u32_array(client->dev.of_node, "reg",
>>>> dev->addrs, 2);
>>>
>>

2021-06-17 08:22:33

by jacopo mondi

[permalink] [raw]
Subject: Re: [PATCH v5 12/15] media: i2c: rdacm20: Embed 'serializer' field


On Thu, Jun 17, 2021 at 10:12:26AM +0200, Hans Verkuil wrote:
> On 17/06/2021 09:42, Jacopo Mondi wrote:
> > Hello,
> >
> > On Thu, Jun 17, 2021 at 08:18:42AM +0200, Hans Verkuil wrote:
> >> On 17/06/2021 02:14, Laurent Pinchart wrote:
> >>> Hi Jacopo,
> >>>
> >>> Thank you for the patch.
> >>>
> >>> This should be moved before 11/15 to avoid a bisection breakage (or
> >>> 11/15 should be fixed, and this patch updated accordingly).
> >>
> >> Good catch!
> >
> > Good catch indeed... Sorry about this I shuffled patches around
> > multiple times and missed this one
> >
> >>
> >> Jacopo, I dropped the PR I made. It you just want to swap patch 11 and 12,
> >> then I can do that, if you want more extensive changes, then I need a v6.
> >>
> >> Let me know what you want.
> >
> > I think swapping 11 and 12 is enough, thanks for handling it.
> > (BTW there's one additional tag from Kieran to collect which is not in
> > v5. Would you like a v6 for that ?)
>
> Updated the PR and added Kieran's tag. So no need for you to do anything.

Thanks a lot then and sorry for hiccup

>
> Regards,
>
> Hans
>
> >
> > Thanks
> > j
> >
> >>
> >> Hans
> >>
> >>>
> >>> On Wed, Jun 16, 2021 at 02:46:13PM +0200, Jacopo Mondi wrote:
> >>>> There's no reason to allocate dynamically the 'serializer' field in
> >>>> the driver structure.
> >>>>
> >>>> Embed the field and adjust all its users in the driver.
> >>>>
> >>>> Signed-off-by: Jacopo Mondi <[email protected]>
> >>>> Reviewed-by: Kieran Bingham <[email protected]>
> >>>> Reviewed-by: Laurent Pinchart <[email protected]>
> >>>> ---
> >>>> drivers/media/i2c/rdacm20.c | 36 +++++++++++++++---------------------
> >>>> 1 file changed, 15 insertions(+), 21 deletions(-)
> >>>>
> >>>> diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
> >>>> index 5e0314a2b1ca..029af8fd7485 100644
> >>>> --- a/drivers/media/i2c/rdacm20.c
> >>>> +++ b/drivers/media/i2c/rdacm20.c
> >>>> @@ -312,7 +312,7 @@ static const struct ov10635_reg {
> >>>>
> >>>> struct rdacm20_device {
> >>>> struct device *dev;
> >>>> - struct max9271_device *serializer;
> >>>> + struct max9271_device serializer;
> >>>> struct i2c_client *sensor;
> >>>> struct v4l2_subdev sd;
> >>>> struct media_pad pad;
> >>>> @@ -399,7 +399,7 @@ static int rdacm20_s_stream(struct v4l2_subdev *sd, int enable)
> >>>> {
> >>>> struct rdacm20_device *dev = sd_to_rdacm20(sd);
> >>>>
> >>>> - return max9271_set_serial_link(dev->serializer, enable);
> >>>> + return max9271_set_serial_link(&dev->serializer, enable);
> >>>> }
> >>>>
> >>>> static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
> >>>> @@ -455,10 +455,10 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
> >>>> unsigned int retry = 3;
> >>>> int ret;
> >>>>
> >>>> - max9271_wake_up(dev->serializer);
> >>>> + max9271_wake_up(&dev->serializer);
> >>>>
> >>>> /* Serial link disabled during config as it needs a valid pixel clock. */
> >>>> - ret = max9271_set_serial_link(dev->serializer, false);
> >>>> + ret = max9271_set_serial_link(&dev->serializer, false);
> >>>> if (ret)
> >>>> return ret;
> >>>>
> >>>> @@ -466,35 +466,35 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
> >>>> * Ensure that we have a good link configuration before attempting to
> >>>> * identify the device.
> >>>> */
> >>>> - max9271_configure_i2c(dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
> >>>> - MAX9271_I2CSLVTO_1024US |
> >>>> - MAX9271_I2CMSTBT_105KBPS);
> >>>> + max9271_configure_i2c(&dev->serializer, MAX9271_I2CSLVSH_469NS_234NS |
> >>>> + MAX9271_I2CSLVTO_1024US |
> >>>> + MAX9271_I2CMSTBT_105KBPS);
> >>>>
> >>>> - max9271_configure_gmsl_link(dev->serializer);
> >>>> + max9271_configure_gmsl_link(&dev->serializer);
> >>>>
> >>>> - ret = max9271_verify_id(dev->serializer);
> >>>> + ret = max9271_verify_id(&dev->serializer);
> >>>> if (ret < 0)
> >>>> return ret;
> >>>>
> >>>> - ret = max9271_set_address(dev->serializer, dev->addrs[0]);
> >>>> + ret = max9271_set_address(&dev->serializer, dev->addrs[0]);
> >>>> if (ret < 0)
> >>>> return ret;
> >>>> - dev->serializer->client->addr = dev->addrs[0];
> >>>> + dev->serializer.client->addr = dev->addrs[0];
> >>>>
> >>>> /*
> >>>> * Reset the sensor by cycling the OV10635 reset signal connected to the
> >>>> * MAX9271 GPIO1 and verify communication with the OV10635.
> >>>> */
> >>>> - ret = max9271_enable_gpios(dev->serializer, MAX9271_GPIO1OUT);
> >>>> + ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> >>>> if (ret)
> >>>> return ret;
> >>>>
> >>>> - ret = max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
> >>>> + ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> >>>> if (ret)
> >>>> return ret;
> >>>> usleep_range(10000, 15000);
> >>>>
> >>>> - ret = max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
> >>>> + ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
> >>>> if (ret)
> >>>> return ret;
> >>>> usleep_range(10000, 15000);
> >>>> @@ -564,13 +564,7 @@ static int rdacm20_probe(struct i2c_client *client)
> >>>> if (!dev)
> >>>> return -ENOMEM;
> >>>> dev->dev = &client->dev;
> >>>> -
> >>>> - dev->serializer = devm_kzalloc(&client->dev, sizeof(*dev->serializer),
> >>>> - GFP_KERNEL);
> >>>> - if (!dev->serializer)
> >>>> - return -ENOMEM;
> >>>> -
> >>>> - dev->serializer->client = client;
> >>>> + dev->serializer.client = client;
> >>>>
> >>>> ret = of_property_read_u32_array(client->dev.of_node, "reg",
> >>>> dev->addrs, 2);
> >>>
> >>
>