DM6467的OV5642 Linux驱动程序开发(二)——Linux内核修改
来源:互联网 发布:vba连接oracle数据库 编辑:程序博客网 时间:2024/04/30 11:33
1 修改vpif驱动程序
由于ov5642是由vpif进行管理,而原先的vpif驱动程序不支持sensorraw格式,所以需要修改vpif驱动程序以兼容sensor raw格式,这时首先需要参考原先在CCS中调试好的vpif寄存器配置。对于sensor视频输入,vpif的寄存器配置比较简单,如下所示。
channel0->regs->FLD0_Y_STRTADR = ( ( Uint32 )RawData );
VPIF_CHCTRL0 = 0 // Capture Parameters
| ( 1 << 31 ) // Data phase changes at falling edge of the input clock
| ( 1 << 28 ) // Data width: 10-bit
| ( 480 << 16 ) // Line interrupt: 480 lines
| ( 1 << 14 ) // Invert incoming VSYNC
| ( 1 << 12 ) // Input Frame
| ( 1 << 10 ) // Progressive Format
| ( 1 << 7 ) // Frame interrupt to CPU: top and bottom field
| ( 1 << 2 ); // CCD/CMOS video capture mode
channel0->regs->IMG_LINE_OFFSET = 640 * 2 * 2;
VPIF_CHCTRL1 = 0 // Capture Parameters
| ( 1 << 31 ) // Data phase changes at falling edge of the input clock
| ( 1 << 10 ) // Progressive Format
| ( 1 << 7 ) // Frame interrupt to CPU: top and bottom field
| ( 1 << 2 ); // CCD/CMOS video capture mode
channel1->regs->IMG_LINE_OFFSET = 640 * 2 * 2;
只要配置好vpif的寄存器,那么vpif就可以获取ov5642传来的视频数据,所以这是修改vpif驱动程序时的主要工作,剩下的部分主要就是添加一些定义,修改一些函数以扩展其兼容性。
修改vpif时有以下几部分比较重要:
(1) 配置vpif寄存器。
配置vpif寄存器的函数是vpif.c文件中的config_vpif_params(),需要在其中添加判断是否当前的视频输入格式为CCD/CMOS,如果是则需要按照以下代码配置vpif的channel 0和channel 1。其中,红色部分为添加的代码,下同。
/* Set the polarity of various pins */
vpif_wr_bit(reg, VPIF_CH_FID_POLARITY_BIT, vpifparams->iface.fid_pol);
vpif_wr_bit(reg, VPIF_CH_V_VALID_POLARITY_BIT, vpifparams->iface.vd_pol);
vpif_wr_bit(reg, VPIF_CH_H_VALID_POLARITY_BIT, vpifparams->iface.hd_pol);
/* Data phase changes at falling edge of input clock */
vpif_wr_bit(reg, VPIF_CH_CLK_EDGE_CTRL_BIT, 0x1);
/* top and bottom field interrupt */
vpif_wr_bit(reg, 7, 0x1);
/* frame based storage */
vpif_wr_bit(reg, VPIF_CH_INPUT_FIELD_FRAME_BIT, 0x1);
/* Set data width */
vpif_wr_bit(reg, VPIF_CH_DATA_WIDTH_BIT, 0x1);
/* Set frame height in lines interrupt */
value = regr(reg);
value &= ~(((unsigned int)(0xfff)) << VPIF_CH0_INTERVAL_LINE_INT_BIT);
value |= ((480) << VPIF_CH0_INTERVAL_LINE_INT_BIT);
regw(value, reg);
/* set channel 1 regs */
value = 0x0;
reg = vpifregs[1].ch_ctrl;
regw(value, reg);
vpif_wr_bit(reg, VPIF_CH_CLK_EDGE_CTRL_BIT, 0x1);//VPIF_CH_CLK_EDGE_CTRL_BIT(31)
vpif_wr_bit(reg, VPIF_CAPTURE_CH_NIP, 0x1);//VPIF_CAPTURE_CH_NIP (10)
vpif_wr_bit(reg, 7, 0x1);//VPIF_CH_INT_CTRL_BIT (6) top and bottom
vpif_wr_bit(reg, VPIF_CH_YC_MUX_BIT, 0x0);//VPIF_CH_YC_MUX_BIT (3)
vpif_wr_bit(reg, VPIF_CH_DATA_MODE_BIT, 0x1);//VPIF_CH_DATA_MODE_BIT (2)
vpif_wr_bit(reg, VPIF_CH_SDR_FMT_BIT, 0x0);//VPIF_CH_SDR_FMT_BIT (4)
regw(640 *2 * 2, vpifregs[1].line_offset);// 10-bit VGA CMOS Camera input
(2) 添加对CCD/CMOS的支持。
这主要通过定义一个结构体来实现:staticconst struct vpif_channel_config_params ch_params[]。该结构体用来记录vpif支持的视频输入格式以及一些重要参数。要添加对CCD/CMOS的支持,需要在其中添加以下定义。
static const struct vpif_channel_config_params ch_params[] = {
{
"PAL_BDGHIK", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313,
336, 624, 625, 0, 1, 0, V4L2_STD_625_50,
},
{
"1080P-60", 1920, 1080, 60, 1, 0, 272, 1920, 1, 42, 1122, 0,
0, 0, 1125, 0, 0, 1, V4L2_STD_1080P_60,
},
{ "CAMERA-VGA", 640, 480, 15, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
480, 1, 0, 0, V4L2_STD_CAMERA_VGA,
},
};
(3) 在V4L2框架中添加CCD/CMOS支持。
首先,需要在/include/linux/videodev2.c中添加宏定义以支持ov5642输入的视频格式。
#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000)
#define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000)
/* ATSC/HDTV */
#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000)
#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000)
/* camera */
#define V4L2_STD_CAMERA_VGA ((v4l2_std_id)0x10000000)
//#define V4L2_STD_CAMERA_PAL ((v4l2_std_id)0x20000000)
//#define V4L2_STD_CAMERA_720P ((v4l2_std_id)0x40000000)
//#define V4L2_STD_CAMERA_1080P ((v4l2_std_id)0x80000000)
然后,需要在/driver/media/video/v4l2-ioctl.c中添加相关定义。
{ V4L2_STD_SECAM_L, "SECAM-L" },
{ V4L2_STD_SECAM_LC, "SECAM-Lc" },
{ V4L2_STD_CAMERA_VGA, "CAMERA-VGA"},
{ 0, "Unknown" }
};
(4) 在CCD/CMOS模式时使能channel 1。
在使用sensor模式输入视频时,需要使用vpif的两个channel,所以,在使能channel0时需要使能channel 1。
if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
(common->started == 2) ||
(ch->video.stdid == V4L2_STD_CAMERA_VGA)) {
channel1_intr_assert();
channel1_intr_enable(1);
enable_channel1(1);
}
(5) 编写CCD/CMOS模式时的vpif buffer地址设置函数。
当vpif为sensor raw输入时,vpif存储视频帧的4个ddr2地址寄存器只需要配置一个就行了,而当输入为标清或者高清时都需要配置4个寄存器,所以这里需要修改。
首先,在/driver/media/video/davinci/vpif.h中添加对应的函数。
/* inline function to set buffer addresses in case of raw bayer mode */
static inline void ch0_set_videobuf_addr_raw(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA);
regw(0, VPIF_CH0_BTM_STRT_ADD_LUMA);
regw(0, VPIF_CH0_TOP_STRT_ADD_CHROMA);
regw(0, VPIF_CH0_BTM_STRT_ADD_CHROMA);
}
然后,在/driver/media/video/davinci/vpif_capture.c的vpif_config_addr()函数中配置该函数为sensorraw输入模式时的地址配置函数。
static void vpif_config_addr(struct channel_obj *ch, int muxmode)
{
struct common_obj *common;
vpif_dbg(2, debug, "vpif_config_addr\n");
common = &(ch->common[VPIF_VIDEO_INDEX]);
if (VPIF_CHANNEL1_VIDEO == ch->channel_id)
common->set_addr = ch1_set_videobuf_addr;
else if (2 == muxmode)
common->set_addr = ch0_set_videobuf_addr_yc_nmux;
else if (ch->vpifparams.std_info.capture_format == 1)
common->set_addr = ch0_set_videobuf_addr_raw;
else
common->set_addr = ch0_set_videobuf_addr;
}
(6)通过CPLD选通使能ov5642。
由于系统默认是只使能了tvp5150,而ov5642是处于reset状态,所以需要通过CPLD使能ov5642才能使其工作,这需要在/arch/arm/mach-davinci/board-dm646x-evm.c中修改setup_vpif_input_channel_mode函数来实现。
static int setup_vpif_input_channel_mode(u8 mux_mode, u8 capture_format)
{
……
if (mux_mode) {
val &= VPIF_INPUT_TWO_CHANNEL;
value |= VIDCH1CLK;
value1 |= VIDCH1CLKSRCCH1;
} else if (!mux_mode && !capture_format){
val |= VPIF_INPUT_ONE_CHANNEL;
value &= ~VIDCH1CLK;
value1 &= VIDCH1CLKSRCCH0;
} else if (!mux_mode && capture_format) { // CCD/CMOS input
val = 0xbf;//val |= VPIF_INPUT_ONE_CHANNEL;
value &= ~VIDCH1CLK;
value1 &= VIDCH1CLKSRCCH0;
}
……
}
(7)添加ov5642的vpif子设备定义。
这需要在/arch/arm/mach-davinci/board-dm646x-evm.c首先添加以下定义。
static struct vpif_subdev_info vpif_capture_sdev_info[] = {
#ifndef CONFIG_VIDEO_TVP7002
{
.name = "tvp5150",
.board_info = {
I2C_BOARD_INFO("tvp5150", 0x5d),
//.platform_data = &tvp5150_pdata,
},
.input = TVP5150_COMPOSITE0,
.output = TVP5150_NORMAL,
.can_route = 1,
.vpif_if = {
.if_type = VPIF_IF_BT656,
.hd_pol = 1,
.vd_pol = 1,
.fid_pol = 0,
},
},
{
.name = "ov5642",
.board_info = {
I2C_BOARD_INFO("ov5642", 0x3c),
},
.input = 0,
.output = 0,
.can_route = 0,
.vpif_if = {
.if_type = VPIF_IF_RAW_BAYER,
.hd_pol = 0,
.vd_pol = 1,
.fid_pol = 0,
},
},
然后,还需要在该文件中添加vpif channel0的输入设备定义。
static const struct vpif_input dm6467_ch0_inputs[] = {
{
.input = {
.index = 0,
.name = "Composite",
.type = V4L2_INPUT_TYPE_CAMERA,
.std = V4L2_STD_PAL,
},
.subdev_name = "tvp5150",
},
{
.input = {
.index = 0,
.name = "Camera",
.type = V4L2_INPUT_TYPE_CAMERA,
.std = V4L2_STD_CAMERA_VGA,
},
.subdev_name = "ov5642",
},
对于vpif驱动程序的修改,除了以上部分,其实还改了很多很多地方,但上面这些是主要部分,其他都是一些细节问题,主要是一些参数设置的函数没有考虑到兼容sensor raw输入。至于要看所有的改动可以查看已经编好的内核中的相应文件。
- DM6467的OV5642 Linux驱动程序开发(二)——Linux内核修改
- DM6467的OV5642 Linux驱动程序开发(一)——V4L2框架结构
- DM6467的OV5642 Linux驱动程序开发(三)——驱动测试
- 基于DM6467的OV5642视频采集编码程序设计(1)——Codec Engine修改
- 基于DM6467的OV5642视频采集编码程序设计(1)——Codec Engine修改
- 基于DM6467的TVP7002 Linux驱动程序开发
- 基于DM6467的OV5642视频采集编码程序设计(2)——Encode Demo测试
- 基于DM6467的OV5642视频采集编码程序设计(2)——Encode Demo测试
- 基于DM6467的OV5642视频采集编码程序设计(3)——PAL格式输入及其他调试
- 基于DM6467的OV5642视频采集编码程序设计(3)——PAL格式输入及其他调试
- 在ccs7下进行DM6467的开发(5):Linux内核编译
- davinci DM6467——linux开发环境搭建
- 《精通Linux设备驱动程序开发》——内核
- 《精通Linux设备驱动程序开发》——内核组件
- Linux内核驱动程序初始化顺序的调整----修改版
- Android中linux内核模块--开发设备驱动程序 && 上层接口实施 (二)
- 《Linux设备驱动程序》——内核的数据类型
- 在ccs7下进行DM6467的开发(2):在Linux下安装ccs
- SQL语言(1)
- SCI论文攻略---完整版!!!!
- HDU 1256 画8
- Hibernate不能自动建表解决办法及Hibernate不同数据库的连接及SQL方言
- 常见的进程调度算法
- DM6467的OV5642 Linux驱动程序开发(二)——Linux内核修改
- Codeforces Round #207 (Div. 2) C. Knight Tournament
- 一个程序有多个选择屏幕以及一个程序调用多个程序
- 记一次CSR上线及总结
- DM6467的OV5642 Linux驱动程序开发(三)——驱动测试
- linux下通过yum安装svn及配置
- Silverlight玻璃边框样式的按钮
- HG5520A型多用表校准仪
- java学习01-基础知识与环境配置