This series is divided into 3-4 articles, because too many articles will be messy.
V4l2 video drivers mainly involve the following knowledge points:
Camera knowledge (You can view the chip manual provided by the camera manufacturer.)
You need to know the features of the selected camera, including the access control method, configuration methods of various parameters, and signal output types.
Camera decoder, controller (The Controller Chip Manual contains camera-related register settings, such as 2410, which mainly sets the relevant control function to enable the chip's internal architecture.)
If the camera outputs analog data, you must be familiar with the decoder configuration. After the digital video signal enters the camera controller, you must be familiar with the operations of the camera controller.
V4l2 API and Data Structure Control (It mainly refers to some v4l2 operations required by the user space, and then the corresponding driver must be implemented at the underlying layer for these operations.)
Before writing a driver, familiarize yourself with the method for accessing v4l2 and the data structure designed by the application.
V4l2 driver architecture (This is the underlying write driver that provides the corresponding access interface for the user space. You can refer to/Drivers/Media/video // zc301/zc301_core.cZc301 video driver code in
It is an example of a very well-developed v4l2 architecture provided by the kernel. It can basically be modified based on it!)
Finally, compile a video driver that complies with v4l2 specifications.
No. 1 camera knowledge
Ov9650 camera. Do not talk about it for the moment. First, let's take a look at the camera decoder, Controller, and the camera controllers of different master chips.
static struct ov9650_reg{unsigned char subaddr;unsigned char value;}regs[] = {/* OV9650 intialization parameter table for VGA application */{0x12, 0x40},// Camera Soft reset. Self cleared after reset.{CHIP_DELAY, 10},{0x11,0x81},{0x6a,0x3e},{0x3b,0x09},{0x13,0xe0},{0x01,0x80},{0x02,0x80},{0x00,0x00},{0x10,0x00},{0x13,0xe5},{0x39,0x43},{0x38,0x12},{0x37,0x91},{0x35,0x91},{0x0e,0xa0},{0x1e,0x04},{0xA8,0x80},{0x14,0x40},{0x04,0x00},{0x0c,0x04},{0x0d,0x80},{0x18,0xc6},{0x17,0x26},{0x32,0xad},{0x03,0x00},{0x1a,0x3d},{0x19,0x01},{0x3f,0xa6},{0x14,0x2e},{0x15,0x10},{0x41,0x02},{0x42,0x08},{0x1b,0x00},{0x16,0x06},{0x33,0xe2},{0x34,0xbf},{0x96,0x04},{0x3a,0x00},{0x8e,0x00},{0x3c,0x77},{0x8B,0x06},{0x94,0x88},{0x95,0x88},{0x40,0xc1},{0x29,0x3f},{0x0f,0x42},{0x3d,0x92},{0x69,0x40},{0x5C,0xb9},{0x5D,0x96},{0x5E,0x10},{0x59,0xc0},{0x5A,0xaf},{0x5B,0x55},{0x43,0xf0},{0x44,0x10},{0x45,0x68},{0x46,0x96},{0x47,0x60},{0x48,0x80},{0x5F,0xe0},{0x60,0x8c},{0x61,0x20},{0xa5,0xd9},{0xa4,0x74},{0x8d,0x02},{0x13,0xe7},{0x4f,0x3a},{0x50,0x3d},{0x51,0x03},{0x52,0x12},{0x53,0x26},{0x54,0x38},{0x55,0x40},{0x56,0x40},{0x57,0x40},{0x58,0x0d},{0x8C,0x23},{0x3E,0x02},{0xa9,0xb8},{0xaa,0x92},{0xab,0x0a},{0x8f,0xdf},{0x90,0x00},{0x91,0x00},{0x9f,0x00},{0xa0,0x00},{0x3A,0x01},{0x24,0x70},{0x25,0x64},{0x26,0xc3},{0x2a,0x00},{0x2b,0x00},{0x6c,0x40},{0x6d,0x30},{0x6e,0x4b},{0x6f,0x60},{0x70,0x70},{0x71,0x70},{0x72,0x70},{0x73,0x70},{0x74,0x60},{0x75,0x60},{0x76,0x50},{0x77,0x48},{0x78,0x3a},{0x79,0x2e},{0x7a,0x28},{0x7b,0x22},{0x7c,0x04},{0x7d,0x07},{0x7e,0x10},{0x7f,0x28},{0x80,0x36},{0x81,0x44},{0x82,0x52},{0x83,0x60},{0x84,0x6c},{0x85,0x78},{0x86,0x8c},{0x87,0x9e},{0x88,0xbb},{0x89,0xd2},{0x8a,0xe6},};
The above is the address of the register that needs to write ov9650 sequentially and the written value (transmitted using I2C subsystem)
The I2C subsystem transmission has been analyzed. The platform device resources can be initialized in the Board file:
1. Modify VI Drivers/I2C/busses/kconfig
Modify
Config i2c_s3c2410
Tristate "S3C2410 I2C driver"
Depends on arch_s3c2410 | arch_initi64xx
Help
Say y here to include support for I2C controller in
Samsung S3C2410 Based System-on-chip devices.
Is:
Config i2c_s3c2410
Tristate "S3C2410 I2C driver"
Depends on arch_s3c2410 | arch_initi64xx | arch_s5pc100
Help
Say y here to include support for I2C controller in
Samsung S3C2410 Based System-on-chip devices.
2. Configure and re-compile the kernel
$ Make menuconfig
Device Drivers --->
<*> I2C support --->
<*> I2C Device Interface
I2C hardware bus support --->
<*> S3C2410 I2C driver
3. Modify vi arch/ARM/mach-s5pc100/mach-smdkc100.c
View the schematic can know that the camera is connected to the I2C-0 or 1, assuming on 1, according to the schematic modified i2c_devs1 add ov9650 content, mainly ov9650 address, this can be found in the chip manual as 0x60.
Why is it 0x30? I have discussed this in another I2C subsystem analysis. Explanations for links
Modify:
Static struct i2c_board_info i2c_devs1 [] _ initdata = {
};
Is:
Static struct i2c_board_info i2c_devs1 [] _ initdata = {
{
I2c_board_info ("ov9650", 0x30 ),
},
};
Add information about s5pc100 camera controller platform device. You can view the information in s5pc100 chip manual.
Static struct resource initi_camif_resource [] = {
[0] = {
. Start = 0xee200000,
. End = 0xee200000 + sz_1m-1,
. Flags = ioresource_mem,
},
[1] = {
. Start = irq_fimc0,
. End = irq_fimc0,
. Flags = ioresource_irq,
}
};
Static u64 initi_device_camif_dmamask = 0 xfffffffful;
Struct platform_device initi_device_camif = {
. Name = "s5pc100-camif ",
. ID = 0,
. Num_resources = array_size (initi_camif_resource ),
. Resource = maid,
. Dev = {
. Dma_mask = & cloud_device_camif_dmamask,
. Coherent_dma_mask = 0 xfffffffful
}
};
Export_symbol (initi_device_camif );
Register the camera control platform device:
In smdkc100_devices, add
Static struct platform_device * smdkc100_devices [] _ initdata = {
& Amp; initi_device_camif, // Add content
};
4. Add a Driver (video)
Make menuconfig
Device Drivers --->
<*> Multimedia support --->
<*> Video for Linux
[*] Enable video for Linux API 1 (Deprecated) (new)
[*] Video capture adapters (new) --->
[*] V4l USB devices (new) --->
<*> USB video class (UVC)
[*] UVC input events Device Support (new)
<*> USB zc0301 [p] webcam support (Deprecated)
The device has been registered!
/* Write a register */
Static int ov9650_reg_write (struct i2c_client * client, u8 Reg, u8 Val)
{
Int ret;
U8 _ Val;
Unsigned char data [2] = {Reg, Val };
Struct i2c_msg MSG = {
. ADDR = client-> ADDR,
. Flags = 0,
. Len = 2,
. Buf = data,
};
// Construct i2c_msg
Ret = i2c_transfer (client-> adapter, & MSG, 1); // exchange a group of messages between the I2C adapter and the I2C Device
Return 0;
}
Static void ov9650_init_regs (void)
{
Int I;
For (I = 0; I <array_size (regs); I ++)
{
If (regs [I]. subaddr = 0xff)
{
Mdelay (regs [I]. value );
Continue;
}
Ov9650_reg_write (ov9650_client, regs [I]. subaddr, regs [I]. value );
}
}
At this point, the camera register has been initialized through the I2C bus.
The next section will explainCamera decoder and controller.