I added support for the Raspberry Pi V2 camera for a board I was working on and had to port the kernel driver for it I did get 640x480 video at 90FPS working.
When looking through the Rapsberry Pi kernel I couldn't find the I2C incantation to configure the IMX219 so I ended up using a logic analyzer to capture various settings as well as looking over other kernel drivers.
Here should be the sequence of steps to get the camera running:
The I2C Address of the camera is 0x10
The first value is the register address and the rest is the data to send to that address. I still have some of my commented code in there when I experimented with it. The platform I was using only supported 10-bit CSI so the clock settings at the end are configured for 10-bit data, but there are comments showing how to configure 8-bit data output.
Also this code expects an input clock of 24MHz
/* software reset */
{0x0103, 0x01},
{0x0100, 0x00},
/* Access Code needed to access registers over 0x3000 */
{0x30EB, 0x05},
{0x30EB, 0x0C},
{0x300A, 0xFF},
{0x300B, 0xFF},
{0x30EB, 0x05},
{0x30EB, 0x09},
/* number of csi lanes = 2 (1 + 1) */
{0x0114, 0x01},
/* dphy control: Auto */
{0x0128, 0x00},
/* external clock frequency = 24MHz */
{0x012A, 0x18}, // 24 MHz
{0x012B, 0x00}, // 000 KHz
//Configure the camera for 640x480 (1280x720 with 2X2 binning)
// analogue gain setting
{0x0157, 0x00},
// Frame Length: 569
{0x0160, 0x01}, {0x0161, 0x89},
//Coarse Time = 565 (Exposure, can be adjusted while the camera is running)
{0x015A, 0x02}, {0x015B, 0x35},
// Line Length: 3559
{0x0162, 0x0D}, {0x0163, 0xE8},
// Window Width: 2279 - 1000 = 1280 - 1
// crop_rect.left: 1000
{0x0164, 0x03}, {0x0165, 0xE8},
// crop_rect.width: 2279
{0x0166, 0x08}, {0x0167, 0xE7},
// Window Height: 1711 - 752 = 960 - 1 (2 X 480)
// crop_rect.top: 752
{0x0168, 0x02}, {0x0169, 0xF0},
// crop_rect.height: 1711
{0x016A, 0x06}, {0x016B, 0xAF},
// image width = 640
{0x016C, 0x02}, {0x016D, 0x80},
// image height = 480
{0x016E, 0x01}, {0x016F, 0xE0},
/* X odd increment */
//{0x0170, 0x03},
{0x0170, 0x01},
/* Y odd increment */
//{0x0171, 0x03},
{0x0171, 0x01},
/* Binning Mode: X (2) */
//{0x0174, 0x04},
{0x0174, 0x03}, //2X Analog Binning
//{0x0174, 0x00},
/* Binning Mode: Y (2) */
{0x0175, 0x03}, //2X Analog Binning
//{0x0175, 0x00},
//{0x0175, 0x02},
// {0x0176, 0x01},
// {0x0177, 0x01},
//Clock Settings
// CSI data format
{0x018C, 0x0A}, {0x018D, 0x0A}, //10-Bits
//{0x018C, 0x08}, {0x018D, 0x08}, //8-Bits
// PIXEL CLOCK USED TO DRIVE SENSOR)
// VTPXCK_DIV: 4: 1/4, 5: 1/5, 8: 1/8, 10: 1/10
{0x0301, 0x05}, // 10-bit configuration
//{0x0301, 0x04}, // 8-bit configuration
// VTSYS_DIV = 1: Divide by 1
{0x0303, 0x01},
// PREPLLCK_VT_DIV: 1: 1/1, 2: 1/2, 3: 1/3
{0x0304, 0x03}, //MUST BE 3 FOR 24MHz
// PREPLLCK_OP_DIV: 1: 1/1, 2: 1/2, 3: 1/3
{0x0305, 0x03}, //MUST BE 3 FOR 24MHz
// PLL_VT_MPY = 57 (Multiplier)
{0x0306, 0x00}, {0x0307, 0x39},
// OPPXCK_DIV (pixel bit depth): 8:1/8 10:1/10
{0x0309, 0x0A}, //10-Bits
//{0x0309, 0x08}, //8-Bits
// OPSYSCK_DIV (divide by two for double data rate): 1:1/2
{0x030B, 0x01},
// PLL_OP_MPY = 114 (Multiplier)
{0x030C, 0x00}, {0x030D, 0x72},
//Pixel Clock (10-bit Config): EXCLK_FREQ / PREPLLLCK_VT_DIV * PLL_VT_MPY / VTPXCK_DIV: 24MHz / 3 * 57 / 5 = 91 MHz
// CIS tunning
{0x455E, 0x00},
{0x471E, 0x4B},
{0x4767, 0x0F},
{0x4750, 0x14},
{0x4540, 0x00},
{0x47B4, 0x14},
{0x4713, 0x30},
{0x478B, 0x10},
{0x478F, 0x10},
{0x4793, 0x10},
{0x4797, 0x0E},
{0x479B, 0x0E},
//Start Video Stream
{ 0x0100, 0x01 }, /* mode select streaming on */
This doesn't cover the exposure time or gain:
The exposure time is controlled by:
EXPOSURE SETTINGS
MINIMUM:
{0x015A, 0x00} {0x015B, 0x01}
MAXIMUM:
{0x015A, 0x0D}, {0x015B, 0xE3}
GAIN SETTINGS
MINIMUM:
{0x0157, 0x01}, {0x0158, 0x00}
MAXIMUM:
{0x0157, 0x10}, {0x0158, 0x00}
I wish I could spend more time testing this out but at least someone can get started with this.
Dave