Skip to content

Conversation

mjs513
Copy link

@mjs513 mjs513 commented Aug 24, 2025

The camera supports grayscale in qqvga, qvga and vga resolutions. It has been tested on a arduino giga r1.

@zephyrbot zephyrbot added the area: Video Video subsystem label Aug 24, 2025
@mjs513 mjs513 changed the title Add Himax HM0360 camera sensor driver drivers: video: Add Himax HM0360 camera sensor driver Aug 24, 2025
@mjs513 mjs513 force-pushed the add-HM0360-video-driver branch from f702fc8 to de61b54 Compare August 25, 2025 15:20
Copy link

@KurtE
Copy link
Contributor

KurtE commented Oct 11, 2025

@mjs513 @NinoSc @josuah - Was just curious about what the status of the hm01b0(#94894) and hm0360 (this one).
Was looking to see which ones to try again to work with multiple cameras defined...

@josuah
Copy link
Contributor

josuah commented Oct 11, 2025

#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.
I do take note that this is being slow, and wish to go back to this as soon as I get a chance!

Thanks for the patience, and apologies for such delay!

@mjs513
Copy link
Author

mjs513 commented Oct 15, 2025

@KurtE - @josuah

Since no one has looked at this yet I had some time from the OV7675 driver so I kind of redid the HM0360 with some lessons learned (probably still have indent issues) and also updated it to use the video cci commands. Figured that would be a better way to go.

Mike

@mjs513 mjs513 force-pushed the add-HM0360-video-driver branch from 23e4782 to 77c69c7 Compare October 15, 2025 23:17
drivers: video Add Himax HM0360 camera sensor driver

Adds support for the HM0360 camera.

Signed-off-by: Mike S <[email protected]>
@mjs513 mjs513 force-pushed the add-HM0360-video-driver branch from 77c69c7 to 38143b3 Compare October 16, 2025 00:17
Copy link

Copy link
Contributor

@josuah josuah left a 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

Comment on lines 775 to 781
Copy link
Contributor

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.

Copy link
Contributor

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).

Comment on lines 785 to 798
Copy link
Contributor

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! :)

Comment on lines 866 to 870
Copy link
Contributor

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.

Copy link
Contributor

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.

Comment on lines 648 to 651
Copy link
Contributor

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.

Comment on lines 570 to 590
Copy link
Contributor

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?

Suggested change
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!

Comment on lines 594 to 603
Copy link
Contributor

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:

Suggested change
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;
}

Comment on lines +830 to +833
if (hm0360_set_frmival(dev, &frmival)) {
printk("ERROR: Unable to set up video format\n");
return false;
}
Copy link
Contributor

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".

Suggested change
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;
}

Comment on lines +868 to +869
ret |= video_write_cci_reg(&config->bus, HM0360_REG_A16D8(HM0360_COMMAND_UPDATE),
0x01);
Copy link
Contributor

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?

Suggested change
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants