-
Notifications
You must be signed in to change notification settings - Fork 8.1k
drivers: video: Add Himax HM0360 camera sensor driver #94904
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?
Conversation
f702fc8
to
de61b54
Compare
|
#94894 is only needing a 2nd review... but before some merge conflicts need to be addressed. For this current PR, I just need to find a free slice of time as I'm pretty busy and late with work on USB lately. Thanks for the patience, and apologies for such delay! |
de61b54
to
23e4782
Compare
23e4782
to
77c69c7
Compare
drivers: video Add Himax HM0360 camera sensor driver Adds support for the HM0360 camera. Signed-off-by: Mike S <[email protected]>
77c69c7
to
38143b3
Compare
|
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.
Thank you for this driver!
I have added a few comments, I hope you find them relevant.
You might also want to look at this PR which has already been reviewed, but not yet merged, still could bring some illustrations of how to use the newest video APIs:
https://github.com/zephyrproject-rtos/zephyr/pull/94894/files
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 might have been imported from another driver: SCCB is an OmniVision-specific term, and I think there was no issue with Himax versions.
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 think Zephyr/Linux typically uses snake_case
. In some cases CamelCase is needed though (i.e. use same identifiers as standard documents).
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.
Here, you are reading 2 identifiers following each others and aggregating them in a single uint16_t
, good use-case for a HM0360_REG16
and read both at the same time! :)
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 Linux CCI library is used so that the user does not have to even think about the size of registers.
Here is how it is possible to use it:
#define HM0360_CCI_TEST_PATTERN_MODE HM0360_REG8(0x0601)
...
video_write_cci_reg(&config->bus, HM0360_CCI_TEST_PATTERN_MODE, ctrls->test_pattern.val);
This way, the size of registers is encoded in the registers themselves, and it is possible to forget about low-level details such as address size, data size, or even endianess.
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.
How about naming it HM0360_REG8()
? This way, this hides the fact that the address are 16-bit, which becomes an implementation detail.
If having a doubt about what is sent, the VIDEO_LOG_LEVEL_DBG=y
will print verbosely everything sent on the I2C bus, this way no ambiguity possible.
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 is already checked by the video_format_caps_index
function, so this can be removed.
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.
How about something like this?
highres = (fmt->width > 320); |
That is, if we would want to validate the input, it is possible to do so before the requests hit the driver, so no need to add the validation effort here IMHO. Open to alternative/discussion!
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.
Minor detail: since highres is a boolean, how about:
if (frmival->numerator <= 10) { | |
osc_div = highres ? 0x02 : 0x03; | |
} else if (frmival->numerator <= 30) { | |
osc_div = highres ? 0x01 : 0x02; | |
} else { | |
/* Set to the max possible FPS at this resolution. */ | |
osc_div = highres ? 0x00 : 0x01; | |
} |
if (hm0360_set_frmival(dev, &frmival)) { | ||
printk("ERROR: Unable to set up video format\n"); | ||
return false; | ||
} |
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.
You might want to split the if()
away from the function call so that you can return the original error message, false == 0
meaning "success".
if (hm0360_set_frmival(dev, &frmival)) { | |
printk("ERROR: Unable to set up video format\n"); | |
return false; | |
} | |
ret = hm0360_set_frmival(dev, &frmival); | |
if (ret < 0) { | |
LOG_ERR("ERROR: Unable to set up video format"); | |
return ret; | |
} |
ret |= video_write_cci_reg(&config->bus, HM0360_REG_A16D8(HM0360_COMMAND_UPDATE), | ||
0x01); |
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.
It is tempting to do ret |=
to reduce the volume of error handling code, but this unfortunately does not work as the error code is not just a boolean but carries information about the type of error (i.e. -IEO
from I2C bus, or -EINVAL
if the I2C peripheral is misconfigured).
Would it be possible to convert to the more verbose, but more correct idiom?
ret |= video_write_cci_reg(&config->bus, HM0360_REG_A16D8(HM0360_COMMAND_UPDATE), | |
0x01); | |
ret = video_write_cci_reg(&config->bus, HM0360_REG_A16D8(HM0360_TEST_PATTERN_MODE), | |
ctrls->test_pattern.val & 0x01); | |
if (ret < 0) { | |
return ret; | |
} | |
ret = video_write_cci_reg(&config->bus, HM0360_REG_A16D8(HM0360_COMMAND_UPDATE), | |
0x01); | |
if (ret < 0) { | |
return ret; | |
} |
As an alternative, you can define a local scope for the case
and define a struct video_reg { {...}, {...}, };
with everything, and do a single return write_cci_multiregs()
with the whole table.
Both are equivalent.
The camera supports grayscale in qqvga, qvga and vga resolutions. It has been tested on a arduino giga r1.