Omnivision OV5642 Camera Driver for Linux

Published on September 4, 2010

Archived Notice

This article has been archived and may contain broken links, photos and out-of-date information. If you have any questions, please Contact Us.

The first release of our OV5642 camera driver for the i.MX51 is now available on branch boundary20100824 of our kernel git repository. There are still some quirks, and only three resolutions are currently working, but we've had some customer requests for a pre-release so we're publishing early. The driver is a fairly vanilla V4L2 driver in that it supports the normal set of ioctl calls for streaming:

  • VIDIOC_QUERYCAP to validate that capture and streaming are supported
  • VIDIOC_S_FMT to set the capture format
  • VIDIOC_REQBUFS to ask for buffers
  • VIDIOC_QUERYBUF to find out about buffer alignment and such
  • VIDIOC_QBUF/VIDIOC_DQBUF for queuing and dequeuing buffers
  • mmap() for memory-mapping the buffers
Currently tested resolutions include:
  • VGA/YUV/30fps
  • 480x272/YUV/30fps
  • 2592x1944/YUV/7.5fps
There are a number of notable omissions from this release:
  • Only automatic brightness and contrast control are supported
  • Only YUV format data is currently support (NV12). The Omnivision camera contains support for JPEG encoding with thumbnail data, but we're not yet certain how this should map to V4L calls.
  • No support for still image capture is present. We're not certain at the moment how the driver should expose this to applications.
There are also a couple of notable bugs in this release:
  • Something is initialized incorrectly during the first use of the camera that causes improper synchronization.
  • The driver may take a few seconds to lock into vertical sync with the camera
Having said all of that, the driver and camera appear to be very stable after initialization and capable of pumping VGA sized data into the i.MX51 VPU encoder at 30fps. Because of the limitations of the i.MX51 VPU, we'll top out at D1 (720x576) resolution along the camera->vpu pipeline as soon as we get D1 resolution working in the camera driver. I'll publish another post with details of the camera driver design and a second with sample applications. Meanwhile, the following is a quick-start guide to usage.

Configuration and compilation

The camera module can be selected using the kernel's menuconfig from Drivers/Multimedia support/Video Capture Adapters/Boundary Devices Video For Linux Camera. The sub-options for which camera to support and which camera interface are there for future use. Only CSI0/OV5642 are currently supported. It has only been tested as a kernel module, not statically linked into the kernel. It directly conflicts with the Freescale camera Driver (MXC Video For Linux Camera), so that must be deselected. The nitrogen_defconfig configuration now compiles this driver as a kernel module by default.

Run-time notes

Because of the size of the register set of the OV5642 needed for each resolution, and because we've been tweaking the Omnivision registers, the set of supported resolutions is defined by a 'firmware' file using the Linux kernel's request_firmware() interface. The firmware file is a binary representation of the camera resolution and register set. It can be compiled from the text files in the drivers/media/video/boundary/settings/ directory. The program defined in make_ov5640_settings.c is used to compile a set of text files into a firmware image. The firmware image is currently loaded each time the camera device is opened. We anticipate changing this for production use to speed up camera access. In the meantime, it has proven very useful to be able to compile a new firmware file and re-run a test without unloading and reloading the driver. The program defined in read_ov5640_settings.c will produce text output from a binary file so you can validate it. It has also served as a nice test for the compilation process. Both make_ov5640_settings and read_ov5640_settings are simple "C" programs that should be compilable on any Posix-compliant system that has zlib installed. I've  been compiling like this on my development PC: user@host:~/linux-bd/drivers/media/video/boundary$ gcc -o make_ov5640_settings make_ov5640_settings.c -lz user@host:~/linux-bd/drivers/media/video/boundary$ gcc -o read_ov5640_settings read_ov5640_settings.c -lz Most testing to date has been on an LTIB-based platform, which uses udev for firmware loading. On that system, the settings file should be placed in /lib/firmware/ov5640.bin. If the driver can't find the firmware file, it will return -EINVAL and produce a message in dmesg stating this: ov5640_load_fw: firmware not available: -2