Skip to content

drivers: video: add imx219 sensor (RPi Cam v2) #88011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

josuah
Copy link
Collaborator

@josuah josuah commented Apr 2, 2025

Split out of:

Dependency:

This was only tested on hardware that is out-of-tree and at 1920x1080 resolution for now (which will be submitted upstream in maybe April):

It works well though.
If you would rather have it submitted before #88003 is merged, let me know, I will refactor it so it can be merged earlier.

P.S.: Thank you Alan Shaju for the original work adapted into this PR!

@josuah
Copy link
Collaborator Author

josuah commented Apr 2, 2025

Force-push:

@decsny decsny requested review from ngphibang and JiafeiPan April 2, 2025 15:51
@dleach02
Copy link
Member

dleach02 commented Apr 2, 2025

@josuah please put this PR into draft mode until the dependent PRs merged.

@andrewnyland
Copy link

Is there any way we can help with this? Looks great so far

@josuah
Copy link
Collaborator Author

josuah commented May 13, 2025

Is there any way we can help with this? Looks great so far

It might be possible yes! I need to rebase this driver on the latest main (like we did here) and then test again on our own platform https://tinyclunx33.tinyvision.ai/

And then it will be possible to test it on any of the Zephyr platform that supports MIPI/CSI, which for now is mostly the i.MXRT1170 and friends, but more are coming!

I will have more time next week to prepare the way a little bit more...

Thank you for offering your help!

@josuah
Copy link
Collaborator Author

josuah commented Jun 1, 2025

Short update on this: I will wait reception of i.MXRT1160 and STM32N6 kits, then remove the library from it, to make it more like the IMX335.

The approach of the "table-only" image sensor driver library was too rigid and does not fit how firmware/driver developers grasp image sensors. Better build tools that fit the community than make the community fit the tools! :)

Alain Volmat added 2 commits June 22, 2025 14:17
Following renaming of the raspberry csi connector nexus,
rename all places when csi 22pins is mentioned to only keep
csi instead.

Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
Following renaming of the raspberry csi connector nexus,
rename all places when csi 22pins is mentioned to only keep
csi instead.

Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
josuah added 2 commits June 24, 2025 15:56
Only VIDEO_CID_ANALOGUE_GAIN and VIDEO_CID_GAIN were defined. Also add
the complementary VIDEO_CID_DIGITAL_GAIN.

Signed-off-by: Josuah Demangeon <me@josuah.net>
Switch to zephyr-keep-sorted-start/stop to keep checking the new
driver imports are always sorted, which reduces chances of git
conflict while adding new drivers from separate branches.

Signed-off-by: Josuah Demangeon <me@josuah.net>
josuah and others added 4 commits June 24, 2025 22:03
Add support for the Sony IMX219 CSI sensor.
This sensor supports resolution of 3280x2464 in RGGB bayer format
either 8 or 10 bits and using 2 or 4 CSI lanes.
Only 10 bits on 2 CSI lanes is currently supported, and only in
1920x1080 pixel resolution using cropping.

Signed-off-by: Josuah Demangeon <me@josuah.net>
Co-authored-by: Alan Shaju <alanshaju@rideltech.com>
Co-authored-by: Alain Volmat <alain.volmat@foss.st.com>
Build the IMX219 image sensor driver on the build-all tests.
No interconnection with any other device is done, which is not mandatory
at the time as no link-related parameter is used.

Signed-off-by: Josuah Demangeon <me@josuah.net>
Add a shield for the Raspberry Pi Camera Module 2, featuring the IMX219
sensor. This module is suitable for bot the "normal" and "No IR" (no
infra-red) variants and uses the rasapberry pi connector.

Signed-off-by: Josuah Demangeon <me@josuah.net>
Co-authored-by: Alain Volmat <alain.volmat@foss.st.com>
Add board specific .conf files for the stm32n6570_dk.

Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
@josuah
Copy link
Collaborator Author

josuah commented Jun 24, 2025

Force-push:

  • Rebase on top of latest Zephyr
  • Fix bugs preventing it to be built and run [1]
  • Set correct board name
  • Integrate improvement from @avolmat-st branch
  • Reduce the default exposure

[1]: I had to modify our SDK to support shields so I could test this thing end-to-end.

@josuah josuah marked this pull request as ready for review June 24, 2025 22:04
@github-actions github-actions bot added platform: NXP Drivers NXP Semiconductors, drivers platform: STM32 ST Micro STM32 labels Jun 24, 2025
@josuah josuah removed the request for review from dleach02 June 24, 2025 22:18
@josuah josuah marked this pull request as draft June 24, 2025 22:18
@josuah
Copy link
Collaborator Author

josuah commented Jun 24, 2025

I realize this is now dependent on this PR, so setting as draft in the meantime:

Copy link

/* Custom defaults */
{IMX219_REG_BINNING_MODE_H, 0x00}, /* No binning */
{IMX219_REG_BINNING_MODE_V, 0x00} /* No binning */,
{IMX219_REG_DIGITAL_GAIN, 5000},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that at init time DIGITAL_GAIN is set to 5000 while within the ctrl init, .def is 0x100. Is that on purpose ? Also, maybe a macro containing DIGITAL_GAIN would help here, being used here and within the ctrl_init function ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense, I will adjust.

{IMX219_REG_BINNING_MODE_H, 0x00}, /* No binning */
{IMX219_REG_BINNING_MODE_V, 0x00} /* No binning */,
{IMX219_REG_DIGITAL_GAIN, 5000},
{IMX219_REG_ANALOG_GAIN, 240},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as for DIGITAL_GAIN

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense, I will adjust.

{IMX219_REG_BINNING_MODE_V, 0x00} /* No binning */,
{IMX219_REG_DIGITAL_GAIN, 5000},
{IMX219_REG_ANALOG_GAIN, 240},
{IMX219_REG_INTEGRATION_TIME, 100},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, value matches so that's ok, but here as well, a macro would help to ensure that init value and ctrl def value are same. That's a general comment for stuff that are set via control.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense, I will adjust.

{IMX219_REG_ORIENTATION, 0x03},
};

static const struct video_reg imx219_fmt_raw8_regs[] = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: in case you want to save few bytes of ROM, this could be a video_reg8

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

video_reg8 got introduced after this original implementation, I need to upgrade imx219.c to it, yes.

{IMX219_REG_OPPXCK_DIV, 8},
};

static const struct video_reg imx219_fmt_raw10_regs[] = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: in case you want to save few bytes of ROM, this could be a video_reg8

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

video_reg8 got introduced after this original implementation, I need to upgrade imx219.c to it, yes.

Copy link
Collaborator Author

@josuah josuah Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[about this PR]
I kept the documented registers as video_reg (variable size) for now, but instead:

  • removed IMX219_REG_OPPXCK_DIV which was configured to the same value afterward, only 4 bytes wasted
  • converted all the undocumented vendor registers to video_reg16 36 bytes spared.

[further-discussion]
I wish to avoid mixing CCI and non-CCI registers both with name IMX219_REG_xxx to avoid confusion. Maybe it needs a naming convention in the future... How about IMX219_CCI_xxx for CCI registers, IMX219_REG_xxx for video_reg8/video_reg16? There is no need to differentiate between 16-bit and 8-bit address inside of a same driver. This also allows to define both a CCI and a non-CCI version in case a register needs to be used in both context.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advantage of using SENSORNAME_CCI_ and SENSORNAME_REG_ convention is that everything written before CCI integration (i.e. GC2145) is already compatible, and the naming convention can be applied as sensors are converted to CCI (if they need to).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this naming convention. Very good idea.

return ret;
}

fmt.width = imx219_fmts[0].width_min;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: those 3 lines could be set directly on the line:

struct video_format = { .... }; at the beginning of the function

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, better get ahead of Coverity.

return ret;
}

ret = video_write_cci_reg(&cfg->i2c, IMX219_REG_MODE_SELECT, IMX219_MODE_SELECT_STREAMING);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the SELECT_STREAMING should only be done at set_stream time, not set_fmt.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point, better avoid too much "enable/disable" traffic.

return -EINVAL;
}

ret = video_write_cci_reg(&cfg->i2c, IMX219_REG_MODE_SELECT, IMX219_MODE_SELECT_STANDBY);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see now, doing this full review and looking at other drivers that there is no "protection" against changing the format while the sensor is already streaming. This is not an issue to this only driver, some other also have this issue.
This could be dangerous since this could lead to issues on the receiver side.
That's something to make keep for later on and not block since driver merge, but something to keep in mind.

I would however avoid on purpose stopping the streaming here and enabling it again later on since I think set_stream (false) should be called first prior to changing a format or a frmival.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point, better avoid too much "enable/disable" traffic.


video_closest_frmival(dev, &fie);

ret = video_write_cci_reg(&cfg->i2c, IMX219_REG_MODE_SELECT, IMX219_MODE_SELECT_STANDBY);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same point as for set_fmt, this probably shouldn't change the mode here since normally at that stage the sensor should not be streaming.
Or at least, it should first check the status since with current code it will always start streaming even if set_stream has not been called.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point, better avoid too much "enable/disable" traffic.


test_i2c_imx219: imx219@10 {
compatible = "sony,imx219";
reg = <0x7>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reg = 0x10 ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build_all test does not actually run anywhere, and I2C addresses are just incrementing numbers just to avoid address clash.

The @10 better be corrected to @7 though, that is true!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, test_i2c_mipid02 should be @8, test_i2c_ov9655 @9, and test_i2c_imx219 @A

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: GPIO area: Shields Shields (add-on boards) area: Video Video subsystem platform: NXP Drivers NXP Semiconductors, drivers platform: STM32 ST Micro STM32
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants