-
Notifications
You must be signed in to change notification settings - Fork 7.6k
drivers: video: emul-imager: use the emulated I2C bus #87937
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
base: main
Are you sure you want to change the base?
drivers: video: emul-imager: use the emulated I2C bus #87937
Conversation
00ea6a3
to
0a23ada
Compare
The emul imager now uses the emul i2c which is initialized with
|
0a23ada
to
11783a5
Compare
Force-push:
I went with I can switch to i.e. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Increase the CONFIG_VIDEO_IMAGER_INIT_PRIORITY
to 65 resolves the issue but it is a bit unusual as in general, all image sensors are initialized with priority CONFIG_VIDEO_INIT_PRIORITY = 60
.
I see that there is the I2C_EMUL driver, why can't we just use this instead of making a customized one ? I suppose you need some different behavior for the transfer_i2c function that i2c_emul cannot support ? If yes, can we emulate the read/write register so that it can be used with i2c_emul ?
Another thought is that I2C EMUL is an emulated driver but surprisingly, it can set its init priority to 50 (equal to the real i2c init priority), so I wonder if we can set the emul imager i2c the same way so that we don't need to change the imager priority as currently ?
Just some thoughts for us to dig deeper.
see below instead.
Maybe I missed something... Current situation: Lines 338 to 339 in c47926e
zephyr/drivers/video/video_emul_imager.c Lines 428 to 430 in c47926e
zephyr/drivers/video/video_emul_rx.c Lines 298 to 299 in c47926e
Between external sensors and on-chip video peripheral, the priority is sometimes in one direction, sometimes in the other direction?
The assumption is that the on-chip video RX will know whether it is initialized before or after, and the external chip is less likely to have this requirement. A solution for this would be splitting
I am not a big fan of my own proposal, as it's much nicer to have just one or two init priorities. |
No such requirement thankfully!
It seems like it is already set to 50 after all? 🤔 |
Yes, the i2c_emul driver is clearly initialized with
But in the emul imager, the emul imager i2c is defined as:
which does not specifiy an init priority, that made me think it will use the Maybe we can check this in the build/ ? Maybe I am wrong, if so, appologize for the mistake ! |
Good idea!
Max priority level (999 got introduced)
|
799f98d
to
d65b699
Compare
Cherry-picking your commit with All drivers (including imagers) use It took me long enough to get that but I think now we are good. 😅 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't see any usage of CONFIG_EMUL_INIT_PRIORITY
neither.
Anyways, I think with :
#define EMUL_I2C_DEFINE(inst) \
EMUL_DT_INST_DEFINE(inst, &emul_imager_init_i2c, NULL, NULL, &emul_imager_i2c_api, NULL);
DT_INST_FOREACH_STATUS_OKAY(EMUL_I2C_DEFINE)
it will take the inst of the i2c0
node of the native_sim.dts
which is drived by the i2c_emul driver which is initialized with priority 50. So, everything is fine.
i2c0: i2c@100 {
status = "okay";
compatible = "zephyr,i2c-emul-controller"; => this is i2c_emul driver.
I was a bit confused because of CONFIG_EMUL_INIT_PRIORITY (which has no role here) and because in video_emul_imager.c there are two DT_INST_FOREACH_STATUS_OKAY() calls so I was not sure which instant is used (the i2c or the imager) ...
Thanks and sorry for my confusion.
Better check twice than cause random CI failure for everyone 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR updates the emulated image sensor drivers to use a dedicated I2C emulator rather than ad-hoc register emulation. Key changes include:
- Adjusting the initialization priority in the video emulation receiver driver.
- Replacing hard-coded register accesses in the imagers with proper I2C calls.
- Introducing an emulated I2C transfer function and related API for the image sensor.
Reviewed Changes
Copilot reviewed 2 out of 6 changed files in this pull request and generated no comments.
File | Description |
---|---|
drivers/video/video_emul_rx.c | Update of the initialization macro to use a dedicated init priority. |
drivers/video/video_emul_imager.c | Replacement of ad-hoc register emulation with I2C read/write operations and addition of a simulated I2C bus. |
Files not reviewed (4)
- drivers/video/Kconfig.emul_imager: Language not supported
- drivers/video/Kconfig.emul_rx: Language not supported
- tests/drivers/video/api/app.overlay: Language not supported
- tests/drivers/video/api/prj.conf: Language not supported
d65b699
to
1690457
Compare
Add a library for the Camera Common Interface, part of the MIPI CSI protocol standard defining methods to configure a camera device over I2C, such as which size for the register address/data. Signed-off-by: Josuah Demangeon <me@josuah.net>
Replace the ad-hoc register emulation by the dedicated I2C emulator, making it usable with the same APIs as every other image sensors. Signed-off-by: Josuah Demangeon <me@josuah.net>
The Emul Rx needs to be initialized after the camera sensor which is generally initialized with CONFIG_VIDEO_INIT_PRIORITY. This is currently true "by chance" due to the order the linker links the object files. This linker order is not easily controlled, so use an explicit priority value to ensure this requirement. Signed-off-by: Phi Bang Nguyen <phibang.nguyen@nxp.com>
Force-push:
|
drivers/video/video_emul_imager.c
Outdated
#define EMUL_IMAGER_REG_FORMAT EMUL_IMAGER_REG8(0x0a) | ||
#define EMUL_IMAGER_PATTERN_OFF EMUL_IMAGER_REG8(0x00) | ||
#define EMUL_IMAGER_PATTERN_BARS1 EMUL_IMAGER_REG8(0x01) | ||
#define EMUL_IMAGER_PATTERN_BARS2 EMUL_IMAGER_REG8(0x02) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This emul imager is all based on 8bit registers as far as I see, so why not using the 8bits variants of accessor ?
so video_reg8 etc so there is no need to change all.
Reason why I am pointing this is the code at the very end of the driver
static uint8_t fake_regs[UINT8_MAX] = {
[EMUL_IMAGER_REG_SENSOR_ID] = EMUL_IMAGER_SENSOR_ID, [EMUL_IMAGER_REG_SENSOR_ID & VIDEO_REG_ADDR_MASK] = EMUL_IMAGER_SENSOR_ID,
}; };
in which there is this mask using VIDEO_REG_ADDR_MASK in order to just keep the address. I feel that VIDEO_REG_ADDR_MASK is part if the CCI helper more than all drivers and normally drivers might not have to use this macro which is here for the helper to "construct" the addresses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly:
a. The imaginary hardware needs to cover as many edge cases as possible
b. On top of this model, the implementation needs to be as straightforward as possible.
Rather than forcing _REG8()
macros in the implementation (b.), I must tune the hardware model (a.) so that it covers the edge cases where the CCI library helps (so it can be tested). Otherwise this test driver will be a bit clumsy like now. :D
normally drivers might not have to use this macro
Real drivers would not have any of the code below /* Simulated I2C bus */
but this part still needs to be improved you are right!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am referring to basically instead of using struct video_reg { }, use the struct video_reg8 { }.
The on a per register access, use:
video_write_cci_reg(&cfg->i2c, SENSORNAME_REG8(EMUL_IMAGER_REG_CUSTOM), data->ctrls.custom.val);
and
video_write_cci_multiregs8 instead of video_write_cci_multiregs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
video_write_cci_multiregs8
instead ofvideo_write_cci_multiregs
I agree and am currently converting it. Would you rather do it for only the initial registers (the vendor blobs)? Or all the extra documented regsiters?
video_write_cci_reg(&cfg->i2c, SENSORNAME_REG8(EMUL_IMAGER_REG_CUSTOM), data->ctrls.custom.val);
Could I ask your opinion on this:
First we make a model that permits us to to forget about the register size anywhere in the driver.
Second we do not use it and still use a manual API.
We do not necessarily need to impose a "greater model" that we do not want to use, maybe the simplicity of...
#define EMUL_IMAGER_REG_CUSTOM 0x12
video_write_reg(&cfg->i2c, EMUL_IMAGER_REG8, EMUL_IMAGER_REG_CUSTOM, data->ctrls.custom.val);
... is what we always wanted?
Or was it a special case where all registers are 8-bit, where a "degraded" model is better, for the sake of simplicity and avoiding casting:
#define EMUL_IMAGER_REG_CUSTOM EMUL_IMAGER_REG8(0x12)
struct video_reg8 init_regs[] = {
{(uint8_t)EMUL_IMAGER_REG_CUSTOM, 123},
{...},
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The practical issue I saw with...
video_write_cci_reg(&cfg->i2c, SENSORNAME_REG8(EMUL_IMAGER_REG_CUSTOM), data->ctrls.custom.val);
... is that in such case:
- some drivers use
#define SENSORNAME_REG_YYY 0x203
only, - some drivers use
#define SENSORNAME_REG_YYY SENSORNAME_REG8(0x203)
only, - some dirvers use a mix of both depending if they are included on a
multireg8()
or not
The CCI library does not help abstracting the register sizes in such case.
So maybe this is not the right model and the CCI library abstracts too much and comes in the way rather than takes the complexity out of the way?
Note that even after it's merged it is possible to fine-tune the API for some use-cases I suppose...
|
Use the newly introduced CCI library instead of local implementation of I2C read/write commands. Modify the emulated imager registers to make the need for the CCI library appear. Signed-off-by: Josuah Demangeon <me@josuah.net>
Dependency:
Split out of:
Downstream:
Replace the ad-hoc register emulation by the dedicated I2C emulator, making it usable with the same APIs as every other image sensors.