当前位置: 代码迷 >> 移动开发 >> 基于avd7181c解决视频输入效果差的有关问题<一>驱动移植、调试手记
  详细解决方案

基于avd7181c解决视频输入效果差的有关问题<一>驱动移植、调试手记

热度:3598   发布时间:2013-02-26 00:00:00.0
基于avd7181c解决视频输入效果差的问题<一>---驱动移植、调试手记

基于avd7181c解决视频输入效果差的问题<>---驱动移植、调试手记

 

          做过全志A10平台的人都知道,在视频输入方面,虽然有4TV Decoder,但是做的效果真的不敢恭维。笔者基于全志平台做车载互动娱乐系统以及车载导航主机,客户对视频输入效果有强烈要求,怎么办呢?

加芯片弥补平台的不足。笔者选用的是AVD7181C芯片,可以支持CVBS\S-Video\YPbPr\RGB等多种输入格式,通过该芯片可以输出YUV 4:2:2信号、656信号。YPbPr输入信号的情况下,输出YUV 4:2:2信号,CVBS视频输入的情况下,输出656信号。刚好这两种格式全志平台的CSI都可以支持。那怎么调试呢?

         如果想快速的调试出图像,从下到上自己做一套会非常耗费时间,也不利于调试,那还是利用现有的资源来做。笔者就是基于android camera APK来完成前期调试的,我们就把AVD7181C芯片当着是一颗camera芯片,利用camera应用来完成yuv的数据存取以及显示,我们负责把底层打通就可以了。

         第一步:基于一个具体camera驱动移植到AVD7181C上。笔者基于gc0308驱动来做的。复制一份改个名字,把里面所有关于gc0308寄存器设置的数组都先清空,这个时候代码就会减少几百行,留着下面的驱动框架,iic操作sensor_read, sensor_write接口也留着。在其他地方都可以大刀阔斧的砍下去,留一个空函数即可。大结构代码如下:

static const struct v4l2_subdev_core_ops sensor_core_ops = {	.g_chip_ident = sensor_g_chip_ident,	.g_ctrl = sensor_g_ctrl,	.s_ctrl = sensor_s_ctrl,	.queryctrl = sensor_queryctrl,	.reset = sensor_reset,	.init = sensor_init,	.s_power = sensor_power,	.ioctl = sensor_ioctl,};static const struct v4l2_subdev_video_ops sensor_video_ops = {	.enum_mbus_fmt = sensor_enum_fmt,//linux-3.0	.try_mbus_fmt = sensor_try_fmt,//linux-3.0	.s_mbus_fmt = sensor_s_fmt,//linux-3.0	.s_parm = sensor_s_parm,//linux-3.0	.g_parm = sensor_g_parm,//linux-3.0};static const struct v4l2_subdev_ops sensor_ops = {	.core = &sensor_core_ops,	.video = &sensor_video_ops,};/* ----------------------------------------------------------------------- */static int sensor_probe(struct i2c_client *client,			const struct i2c_device_id *id){	struct v4l2_subdev *sd;	struct sensor_info *info;	struct regval_list regs;        int ret = -1;        int i = 0;        avd7181c_dev_dbg("fuction=%s, line=%d\n",__FUNCTION__, __LINE__);	info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL);	if (info == NULL)		return -ENOMEM;	sd = &info->sd;	v4l2_i2c_subdev_init(sd, client, &sensor_ops);	info->ccm_info = &ccm_info_con;		info->gain = 0;	info->wb = 0;	info->clrfx = 0;  avd7181c_dev_dbg("fuction=%s, line=%d\n",__FUNCTION__, __LINE__);	init_avd7181c_proc();	gsd = sd;	return 0;}static int sensor_remove(struct i2c_client *client){	struct v4l2_subdev *sd = i2c_get_clientdata(client);	v4l2_device_unregister_subdev(sd);	kfree(to_state(sd));	return 0;}static const struct i2c_device_id sensor_id[] = {	{ "7181c", 0 },	{ }};MODULE_DEVICE_TABLE(i2c, sensor_id);static struct i2c_driver sensor_driver = {	.driver = {		.owner = THIS_MODULE,	  .name = "7181c",	},	.probe = sensor_probe,	.remove = sensor_remove,	.id_table = sensor_id,};

 

         第二步:根据需要的视频输入格式写好对应寄存器设置。如果需要支持CVBS就加一个cvbs格式的一长串寄存器,ypbpr也一样。笔者以ypbpr为例,列出部分寄存器设置:

 static const struct regval_list reg_ypbpr[]={{{0x05},{0x01}},// ; PRIM_MODE = 001b COMP{{0x06},{0x06}},// ; VID_STD for 525P 2x1{{0x03},{0x08}},{{0xC3},{0x46}},// ; ADC1 to Ain4, ADC0 to Ain6, {{0xC4},{0xB5}},// ; ADC2 to Ain5 and enables manual override of mux{{0x1D},{0x47}},// ; Enable 28.63636MHz crystal{{0x3A},{0x11}},// ; Set Latch Clock 01b. Power down ADC3.{{0x3B},{0x81}},// ; Enable Internal Bias {{0x3C},{0x3d}},// ; PLL QPUMP to 011b {{0x6B},{0x83}}, //0xc3,//0x83,// ; 422 8bit out {{0xC9},{0x00}},// ; SDR mode#if 1{{0x73},{0xD0}},// ; Enable Manual Gain and set CH_A gain{{0x74},{0xE6}},// ; Set CH_A and CH_B Gain - 0FAh{{0x75},{0x81}},// ; Set CH_B and CH_C Gain{{0x76},{0xa0}},// ; Set CH_C Gain{{0x77},{0x06}},{{0x78},{0x08}},{{0x79},{0x02}},{{0x7A},{0x00}},#endif...........}

         第三部:在设置fmt的接口中去控制输入格式。在sensor_s_fmt函数中可以去控制是选择CVBS还是ypbpr,当然是通过这个接口中传递下来的参数来控制。这部分完全可以自定义,笔者介绍一下ypbpr 480P情况下的设置:

	info->fmt = sensor_fmt;	info->width = 720;	info->height = 480;	       /*write reg_ypbpr  setting*/	ret = sensor_write_array(sd, reg_ypbpr , ARRAY_SIZE(reg_ypbpr)); //reg_ypbpr	avd7181c_dev_dbg("==========sensor_write at wirte reg_ypbpr ret=%d\n", ret); 

         第四步:为了调试方便增加便捷调试功能。怎么才能在运行的时候,可以很便利的去修改寄存器,读出当前设置的寄存器值呢?可以通过proc来完成。通过串口来输入控制命令,这样想读哪个寄存器就读哪个寄存器,想怎么调试方便,就可以按需要很方便的去调试。

static void init_avd7181c_proc(void){	struct proc_dir_entry *read_r, *write_r;	avd7181c_dev_dbg("%s\n", __func__);	dir = proc_mkdir("avd7181ctest", NULL);	read_r = create_proc_entry("read_r", 0666, dir);	if (read_r)		read_r->write_proc = avd7181cTest_proc_read;	write_r  = create_proc_entry("write_r", 0666, dir);	if (write_r)		write_r->write_proc = avd7181cTest_proc_write;}

         第五步:在system_config1.fex中添加配置。主要是打开csi,设置名称、iic地址等,还有就是复位、standby供电的gpio设置。

csi_used                 = 1csi_mname                = "7181c"csi_twi_id               = 1csi_twi_addr             = 0x42csi_if                   = 0csi_d15                  = csi_reset                = port:PH13<1><default><default><0>csi_power_en             = port:PI11<1><default><default><0>csi_stby                 = port:PH18<1><default><default><0>csi_reset_b              = 

          通过以上几步,我们已经搭建好一个初步的AVD7181C驱动框架,编译通过就可以跑测试了。笔者使用DVD输出ypbpr信号给AVD7181C,在camera apk中查看图像。先贴一副截屏图像: 

 

 

        在这个调试过程中,笔者遇到了很多的问题,多问问,多试试,一步步解决,总能解决好。笔者将在后续文章中介绍遇到的AVD7181C iic读寄存器兼容性问题、CVBS输入情况下CSI驱动的修改等。敬请期待!

  相关解决方案