Getting an ADV7180 camera driver to work on Toradex Apalis i.mx6

Published:

Recently Toradex released a new Freescale i.MX 6-based SoM with a capable quad-core CPU (a dual-core version is also available).

The module is compatible with the Apalis standard introduced by Toradex, featuring, among other things, PCI-express and Gigabit Ethernet – easily guessed, typical applications include high data-throughput and media processing.

While this is a new product from Toradex, the i.MX 6 has been on the market for a while and a lot of software exists for this popular and well-received Freescale platform.
The hardest thing however is usually to find the right blocks and put them together, so in this tutorial we will show how to easily get a V4L (Video4Linux) camera setup running on an i.MX 6 Apalis platform, in this case – the feature-rich Ixora baseboard.

For our tests we used the analogue camera module offered by Toradex via their webshop – it is the fourth item counting from the bottom on a nice list of accessories which can be purchased off-the-shelf.

Below is a screenshot of the end result we want to achieve (Antmicro cups are unfortunately not yet available for sale):

ADV7180 i.MX6 setup

Getting cameras to work on the i.MX processors is relatively more complicated compared to similar platforms.
This is because the CPU contains two hardware units called IPU (Image Processing Unit) responsible for gathering the data from cameras with serial and parallel interfaces.

This requires the V4L2 layer inside the Linux kernel to pack additional drivers that manage these units.

The kernel provided by Toradex (we used commit no 75c0ddf8b632063136925b57fc21cdc4563e3927) has these drivers in the drivers/media/video/mxc/capture/ directory.
The kernel driver for the ADV7180 used in the Analogue Camera Module is also there.

Note that this kernel driver tree has two ADV7180 drivers where only the one stored in the above directory is IPU-compatible.
Assuming you would like to make the ADV chip to work with your Apalis board, the Linux .config file has to include a bunch of drivers for IPU/MXC layer plus the ADV7180 camera driver itself (see the list of attached files below).

The next step would be letting Linux know that we have an additional device onboard.

Toradex provides a 3.0.35 kernel which means we have to deal with altering a board file instead of a device tree (DTS).
The board file is located in arch/arm/mach-mx6/board-apalis_imx6.c.
The main trick is to define the entry in capture_data structure as follows so that the kernel knows at init time that it should register the camera driver:

static struct fsl_mxc_capture_platform_data capture_data[] = {
    {
        .ipu = 0,
        .csi = 0,
        .mclk_source = 0,
        .is_mipi = 0,
    },
};

Note a slight terminology mismatch here: CSI in this case means Camera Sensor Interface not Camera Serial Interface which is a multiplexed additional input to the IPU for MIPI devices.
Since iMX6 has two IPUs this structure might have additional entries.

All the devices are registered with an imx6q_add_v4l2_capture function inside the board init function.
For the I2C line of the driver we need to define additional ADV7180 data that notifies the kernal about the initialization process of the driver itself, its power on/off functions and the I2C address associated with it:

static void adv7180_io_init(void)
{
    IOMUX_SETUP(csi0_sensor_pads);

    if (cpu_is_mx6q())
        mxc_iomux_set_gpr_register(1, 19, 1, 1);
    else
        mxc_iomux_set_gpr_register(13, 0, 3, 4);
}

static struct fsl_mxc_tvin_platform_data adv7180_data = {
    .pwdn = adv7180_pwdn,
    .io_init = adv7180_io_init,
    .cvbs = true,
    .ipu = 0,
    .csi = 0,
};

static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
    {
        I2C_BOARD_INFO("adv7180", 0x21),
        .platform_data = (void *)&adv7180_data,
    },
};

Note that depending on your setup, the I2C address could be different.
The ready-to-use diff file with the alterations mentioned above and some tweaks can be found as an attachment to this post (see below).
With these alterations we’re ready to compile the kernel and modules:

make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -j 16 uImage
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -j 16 modules

Once the board is up and running the next thing to do is to replace the libmfw_gst_tvsrc.so library.
The old version provided with the rootfs from Toradex does not work with the ADV7180 driver.
You can download it from Freescale’s forum.

Since we compiled all the drivers as modules we need to load them:

insmod ipu_csi_enc.ko
insmod ipu_bg_overlay_sdc.ko
insmod ipu_still.ko
insmod ipu_fg_overlay_sdc.ko
insmod ipu_prp_enc.ko
insmod camera_sensor_clock.ko
insmod adv7180_tvin.ko
insmod mxc_v4l2_capture.ko

Now we’re ready to test the camera with the gstreamer-0.10:

gst-launch-0.10 tvsrc ! mfw_v4lsink disp_width=720 disp_height=576

Voila! You can now start doing all sorts of processing on your camera feed.

This post is the beginning of a series of posts on Toradex technologies (which is not to mean we will stop writing about anything else!), the efect of a long-lasting cooperation between Toradex and Antmicro.
If you have suggestions of things you’d like to see written about, write to us at contact@antmicro.com.

Attachments: