现在的位置: 首页 > 综合 > 正文

S5PV210 Android camera S_INPUT实现

2013年10月24日 ⁄ 综合 ⁄ 共 4101字 ⁄ 字号 评论关闭

三星平台的capture设备节点是/dev/fimc0,但是平台可能存在多个摄像头,更特殊的情况是一个video ADC芯片外接多个模拟摄像头,这几天研究了下如何选择capture的摄像头,做个总结。

先对摄像头做个分类,

1. CMM CameraCompact Module 摄像头模组;

2. VIDEO ADC + 模拟摄像头。

视频源的选择是通过VIDIOC_S_INPUT来实现的,这里的视频源既可以是上面第一类的CMM,也可以是第二类的ADC加一个模拟摄像头,video ADC挂几个模拟摄像头就对应几个视频源。

三星FIMC框架为每一个视频源定义了一个结构,以mach-smdkc110.c为例。

1901 static struct s3c_platform_fimc fimc_plat_lsi = {
1902     .srclk_name = "mout_mpll",
1903     .clk_name   = "sclk_fimc",
1904     .lclk_name  = "sclk_fimc_lclk",
1905     .clk_rate   = 166750000,
1906 #if defined(CONFIG_VIDEO_S5K4EA)
1907     .default_cam    = CAMERA_CSI_C,
1908 #else
1909 #ifdef CAM_ITU_CH_A
1910     .default_cam    = CAMERA_PAR_A,
1911 #else
1912     .default_cam    = CAMERA_PAR_B,
1913 #endif
1914 #endif
1915     .camera     = {
1916 #ifdef CONFIG_VIDEO_S5K4ECGX
1917             &s5k4ecgx,
1918 #endif
1919 #ifdef CONFIG_VIDEO_S5KA3DFX
1920             &s5ka3dfx,
1921 #endif
1922 #ifdef CONFIG_VIDEO_S5K4BA
1923             &s5k4ba,
1924 #endif
1925 #ifdef CONFIG_VIDEO_S5K4EA
1926             &s5k4ea,
1927 #endif
1928 #ifdef CONFIG_VIDEO_CAM8000
1929             &cam8000,
1930 #endif
1931 #ifdef CONFIG_VIDEO_TW9912
1932             &tw9912_1,
1933             &tw9912_2,
1934 #endif
1935     },
1936     .hw_ver     = 0x43,
1937 };

1918 ~ 1938 .camera成员定义了系统可能的视频源,其中s5k4ecgx, s5ka3dfx, s5k4ba, s5k4ea是四个CMM模组, cam8000原生代码的Video ADC,tw9912_1和tw9912_2是我定义的两个camera 视频源,为什么一个TW9912 Video ADC要定义成两个,这是因为在我的项目中TW9912存在两路输入,一个是CVBS另外一个是YPbPr,我认为他们和 TW9912组成了两个camera 视频源。

下面代码演示了如何区分这两个camera通道

1831 static struct s3c_platform_camera tw9912_1 = {
1832     .id     = CAMERA_PAR_A,
1833     .type       = CAM_TYPE_ITU,
1834     .fmt        = ITU_656_YCBCR422_8BIT,
1835     .order422   = CAM_ORDER422_8BIT_CBYCRY,
1836     .i2c_busnum = 1,
1837     .info       = &tw9912_1_i2c_info,
1838     .pixelformat = V4L2_PIX_FMT_YUYV,
1839     .srclk_name = "mout_mpll",
1840     .clk_name   = "sclk_cam0",
1841     .clk_rate   = 44000000,
1842     .line_length = 1440,
1843     .width      = 720,
1844     .height     = 576,
1845     .window     = {
1846         .left   = 0,
1847         .top    = 0,
1848         .width  = 720,
1849         .height = 576,
1850     },
1851
1852     /* Polarity */
1853     .inv_pclk   = 0,
1854     .inv_vsync  = 0,
1855     .inv_href   = 0,
1856     .inv_hsync  = 0,
1857
1858     .initialized    = 0,
1859     /*
1860      * It is too late to call camera sensor poweron in fimc_camera_init
1861      * so we move power function to board init
1862      */
1863     .cam_power  = NULL,
1864 };

1866 static struct s3c_platform_camera tw9912_2 = {
1867     .id     = CAMERA_PAR_A,
1868     .type       = CAM_TYPE_ITU,
1869     .fmt        = ITU_656_YCBCR422_8BIT,
1870     .order422   = CAM_ORDER422_8BIT_CBYCRY,
1871     .i2c_busnum = 1,
1872     .info       = &tw9912_2_i2c_info,
1873     .pixelformat = V4L2_PIX_FMT_YUYV,
1874     .srclk_name = "mout_mpll",
1875     .clk_name   = "sclk_cam0",
1876     .clk_rate   = 44000000,
1877     .line_length = 1440,
1878     .width      = 720,
1879     .height     = 576,
1880     .window     = {
1881         .left   = 0,
1882         .top    = 0,
1883         .width  = 720,
1884         .height = 576,
1885     },
1886
1887     /* Polarity */
1888     .inv_pclk   = 0,
1889     .inv_vsync  = 0,
1890     .inv_href   = 0,
1891     .inv_hsync  = 0,
1892
1893     .initialized    = 0,
1894     /*
1895      * It is too late to call camera sensor poweron in fimc_camera_init
1896      * so we move power function to board init
1897      */
1898     .cam_power  = NULL,
1899 };

他们唯一不同的地方在于.info成员,分别为tw9912_1_i2c_info 和tw9912_2_i2c_info

1796 static struct tw9912_platform_data tw9912_1_plat = {
1797     .default_width = 720,
1798     .default_height = 576,
1799     .pixelformat = V4L2_PIX_FMT_YUYV,
1800     .ifsel = 0,
1801     .ysel = 0,
1802     .csel = 0,
1803     .vsel = 0,
1804     .cam_reset = tw9912_reset,
1805 };
1806
1807 static struct tw9912_platform_data tw9912_2_plat = {
1808     .default_width = 720,
1809     .default_height = 576,
1810     .pixelformat = V4L2_PIX_FMT_YUYV,
1811     .ifsel = 0x20,
1812     .ysel = 0x08,
1813     .csel = 0x2,
1814     .vsel = 0,
1815     .cam_reset = tw9912_reset,
1816 };  
1817
1818 static struct i2c_board_info  tw9912_1_i2c_info = {
1819     I2C_BOARD_INFO("tw9912", (0x88 >> 1)),
1820     .platform_data = &tw9912_1_plat,
1821 };  
1822
1823 static struct i2c_board_info  tw9912_2_i2c_info = {
1824     I2C_BOARD_INFO("tw9912", (0x88 >> 1)),
1825     .platform_data = &tw9912_2_plat,
1826 };  

i2c_board_info不同的地方是ifsel, ysel, csel, vsel成员,这几个成员对应着tw9912 0x02寄存器(input format)寄存器位

这是tw9912_1和tw9912_2唯一有差别的地方。

当上层调用VIDIOC_S_INPUT时,调用路径如下

fimc_s_input->fimc_configure_subdev->v4l2_i2c_new_subdev_board->v4l2_subdev_call(sd, core, s_config, info->irq, info->platform_data)->

v4l2_subdev_call(sd, core, s_config, info->irq, info->platform_data)调用sd->ops->core->s_config, 这个函数需要在tw9912驱动中实现,info->platform_data就是在mach-smkvc110.c中定义的tw9912_1_i2c_info或者tw9912_2_i2c_info,因此在s_config实现中就可以根据i2c_board_info.platform_data中的ifsel, ysel,
csel, vsel来设置tw9912的输入

总结一下:

1. video ADC芯片驱动要通过s_config来实现视频源的切换

2. 为video ADC的每个输入创建一个s3c_platform_camera 结构,通过i2c_board_info.platform_data来体现输入的差异性

转载自:http://blog.csdn.net/kickxxx/article/details/7789951

 

抱歉!评论已关闭.