A Simple tutor for writing i.MX6 mipi driver, use adv7480 as an example

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

A Simple tutor for writing i.MX6 mipi driver, use adv7480 as an example

5,596 Views
wallyyeh
Contributor V

Hello, folks:

   It's been a month since fighting with the i.MX6 mipi driver, I realize how dumb I am during writing i.MX6 device mipi driver; so I write this article for someone like me - whom is hopeless and frighten by this damn mipi protocol.

 

    Our case is using adv7480 as TV-in function(HDMI in, and yuv422 out) on i.MX6DL, 2 mipi data lanes, attach to <CSI0, IPU0, virtual channel 0>, and wanna grab some picture form it. I choose v4l2grab for grab picture from mipi, download location: GitHub - twam/v4l2grab: utility for grabbing JPEGs from V4L2 devices

 

    By the way, the SDK I'm using is SDK_3.0.35-4.1.0; you may use different SDK but you need to fight with arm device tree files by yourself.

 

   OK, the first step is to tell kernel you have the device, one can see how to do this by reference my patch file: 0001-add-adv7480-platform-data.patch

I strongly recommend using CSI0, IPU0, and virtual channel 0.  since every device *must* set the virtual channel, and the reasonable default value is 0; so if you doesn't know how to set your device's virtual channel, just use 0 on your board file.

 

   Second, the mipi driver, I also attached it(adv7480_mipi_driver_patches.zip).

patch 0001 is just add an V4L2 ID for adv7480.

patch 0002 add an func "mipi_csi2_reset_with_dphy_freq" for driver use. the main idea is dynamic change i.MX6 Dphy frequency to match the adv7480 mipi data lane output.

if someone is confused with "pixel clock", "mipi clock lane frequency", "mipi data lane frequency", following is an simple explanation:

141713_141713.jpgunnamed.jpg

and pixel clock can get from this website: VGA Signal Timing

 

patch 0003 is for v4l2grab only, don't know why it call v4l2 ioctl "VIDIOC_S_FMT" but kernel will use "VIDIOC_TRY_FMT" instead.

patch 0004 is the entire adv7480 driver, basically I just swallow the i2c commends from ov5640_mipi.c and fill my own, then change it's func name with "adv7480"。

I will explain some important part:

1. adv7480_init_mode(), I found after mipi_csi2_reset_with_dphy_freq() or mipi_csi2_reset() called, you *must* turn off device's output and turn it on again! or you will got

mipi_csi2_dphy_status alwaly be 0x200 or 0x230, it means i.MX6 can't get the clock form device.

2. most v4l2 ioctl is not implemented, only ioctl_s_parm() and ioctl_g_parm() are implemented.

3. adv7480 have totally 12 i2c clients inside the chip, so we also need to add a argument "address" for different sub i2c client's address.

 

   adv7480_mipi_tvin.c will register an v4l2 device by mxc_v4l2_capture.c called. and mxc_v4l2_capture.c will make a device node - /dev/video0. that's the node we can use v4l2grac to grab some picture - ./vl42grab -o /tmp/test.jpg.

 

p.s: since i.MX6 DL mipi bandwidth is small, you can only retrieve picture while input resolution is lower than 1280x800. if anyone want grab 1920x1080. you must use i.MX6Q and use 4 mipi data lanes.

Original Attachment has been moved to: 0001-add-adv7480-platform-data.patch.zip

Original Attachment has been moved to: adv7480_mipi_driver_patches.zip

Labels (1)
Tags (1)
3 Replies

2,231 Views
jasongaiser
Contributor II

I noticed your driver is using bt656 clock mode which is contrary to the guidance of the imx6 data sheet.  The data sheet recommends using non-gated mode when working with MIPI.  Based on my copy of mxc_v4l2_capture.c, you'd want to set clock_curr to -1 in order to use non-gated mode.  I'm also guessing you'd want to disable AV codes in the 7480 but I am less sure about that at this point.

Did you ever capture video from the 7480 or just single frames?  If you're just capturing single frames, it's possible you didn't see the issues which we're encountering when using your driver(incorrect frame sizes, garbage data between frames).

Anyway, thanks for the reference driver.  It seems like a good starting point.

2,231 Views
dehuanxin
Contributor III

Hi, Waly,

By "turn off" do you mean "set all MIPI siganls, i.e. data_x_p/data_x_n and clk_p/clk_n to 0 or  LP11/STOP_STATE(about 1.2V single ended)", or hi-z?

1. adv7480_init_mode(), I found after mipi_csi2_reset_with_dphy_freq() or mipi_csi2_reset() called, you *must* turn off device's output and turn it on again! or you will got

mipi_csi2_dphy_status alwaly be 0x200 or 0x230, it means i.MX6 can't get the clock form device.

0 Kudos

2,231 Views
wallyyeh
Contributor V

Hi, Dehuan:

   Sorry, not an expert, so I didn't know if just reset LP11/STOP_STATE could solve the case or not.

In my experience, every time I call mipi_csi2_reset_with_dphy_freq() or mipi_csi2_reset(), I must reset my mipi device by bunch of i2c command. you can see my patch:「0004-add-adv7480-mipi-driver.patch」 I need issue out bunch of i2c commands for reset adv7480 at line 387 of /kernel/drivers/media/video/mxc/capture/adv7480_mipi_tvin.c :

adv7480_download_firmware(adv7480_init_params_after_mapped_another_i2c, ARRAY_SIZE(adv7480_init_params_after_mapped_another_i2c));

0 Kudos