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

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

 

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

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

/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/sundesheng125原创,转载请注明出处,谢谢!

/*****************************************************************************************************/

       如果想快速的调试出图像,从下到上自己做一套会非常耗费时间,也不利于调试,那还是利用现有的资源来做。笔者就是基于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                 = 1
csi_mname                = "7181c"
csi_twi_id               = 1
csi_twi_addr             = 0x42
csi_if                   = 0

csi_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驱动的修改等。敬请期待!

全志R16的android4.4.2平台点亮gc2145(evb30) 版本:V1.1 1、配置ov2640在android层配置的分辨率为vga(预览/拍照/录像) 注意:系统自带的快拍APP就在这里查找分辨率参数发送到camera的HAL层。 这里得分辨率设置为:拍照1600x1200,预览640x480 驱动里面搜索可以设置为:1600x1200, 1280x720(花屏), 800x600(分辨率不能切换到这里), 640x480 提取分辨率的小知识: R:\wyb\gc2145_parrotv1.1_r16m\lichee\linux-3.4\drivers\media\video\sunxi-vfe\device\gc2145.c 搜索:_regs[] static struct regval_list sensor_default_regs[] = { (默认分辨率是VGA分辨率:640x480) /* 1600X1200 UXGA capture */ static struct regval_list sensor_uxga_regs[] ={ /* 800X600 SVGA,30fps*/ static struct regval_list sensor_svga_regs[] = //1280*720---init---/// static struct regval_list gc2145_hd720_regs[] = { R:\wyb\gc2145_parrotv1.1_r16m\android\device\softwinner\astar-evb30\configs\camera.cfg ;------------------------------------------------------------------------------- ; 用于camera的配置 ; ; 采用格式: ; key = key_value ; 注意: 每个key需要顶格写; ; key_value紧跟着key后面的等号后面, 位于同一行中; ; key_value限制大小为256字节以内; ; ;------------------------------------------------------------------------------- ;------------------------------------------------------------------------------- ; exif information of "make" and "model" ;------------------------------------------------------------------------------- key_camera_exif_make = MAKE_A31S key_camera_exif_model = MODEL_A31ST ;------------------------------------------------------------------------------- ; 1 for single camera, 2 for double camera ;------------------------------------------------------------------------------- number_of_camera = 1 ;------------------------------------------------------------------------------- ; CAMERA_FACING_BACK ; gc0307 gc2145 ;------------------------------------------------------------------------------- camera_id = 0 ;------------------------------------------------------------------------------- ; 1 for CAMERA_FACING_FRONT ; 0 for CAMERA_FACING_BACK ;------------------------------------------------------------------------------- camera_facing = 0 ;------------------------------------------------------------------------------- ; 1 for camera without isp(using built-in isp of Axx) ; 0 for camera with isp ;------------------------------------------------------------------------------- use_builtin_isp = 0 ;------------------------------------------------------------------------------- ; camera orientation (0, 90, 180, 270) ;------------------------------------------------------------------------------- camera_orientation = 90 ;------------------------------------------------------------------------------- ; driver device name ;------------------------------------------------------------------------------- camera_device = /dev/video0 ;------------------------------------------------------------------------------- ; device id ; for two camera devices with one CSI ;------------------------------------------------------------------------------- device_id = 0 used_preview_size = 1 key_support_preview_size = 640x480 key_default_preview_size = 640x480 used_picture_size = 1 ;key_support_picture_size = 1600x1200, 1280x720, 800x600, 640x480 key_support_picture_size = 1600x1200, 640x480 key_default_picture_size = 640x480 used_flash_mode = 0 key_support_flash_mode = on,off,auto key_default_flash_mode = on used_color_effect=0 key_support_color_effect = none,mono,negative,sepia,aqua key_default_color_effect = none used_frame_rate = 1 key_support_frame_rate = 10 key_default_frame_rate = 10 used_focus_mode = 0 key_support_focus_mode = auto,infinity,macro,fixed,continuous-video,continuous-picture key_default_focus_mode = auto used_scene_mode = 0 key_support_scene_mode = auto,portrait,landscape,night,night-portrait,theatre,beach,snow,sunset,steadyphoto,fireworks,sports,party,candlelight,barcode key_default_scene_mode = auto used_white_balance = 0 key_support_white_balance = auto,incandescent,fluorescent,warm-fluorescent,daylight,cloudy-daylight key_default_white_balance = auto used_exposure_compensation = 1 key_max_exposure_compensation = 3 key_min_exposure_compensation = -3 key_step_exposure_compensation = 1 key_default_exposure_compensation = 0 2、在init.rc(init.sun8i.rc)中加载gc2145.ko这个驱动模块。 R:\wyb\gc2145_parrotv1.1_r16m\android\device\softwinner\astar-evb30\init.sun8i.rc #csi module insmod /system/vendor/modules/videobuf-core.ko insmod /system/vendor/modules/videobuf-dma-contig.ko insmod /system/vendor/modules/cam_detect.ko #insmod /system/vendor/modules/actuator.ko #insmod /system/vendor/modules/ad5820_act.ko insmod /system/vendor/modules/cci.ko insmod /system/vendor/modules/vfe_os.ko insmod /system/vendor/modules/vfe_subdev.ko #insmod /system/vendor/modules/gc0307.ko #insmod /system/vendor/modules/gc0308.ko #insmod /system/vendor/modules/ov2035.ko #insmod /system/vendor/modules/ov2640.ko #insmod /system/vendor/modules/ov5640.ko insmod /system/vendor/modules/gc2145.ko insmod /system/vendor/modules/vfe_v4l2.ko 启动之后实际加载的摄像头的驱动模块: shell@astar-evb30:/ $ shell@astar-evb30:/ $ lsmod gt82x 9849 0 - Live 0x00000000 sunxi_schw 12559 0 - Live 0x00000000 (O) rtl8150 9023 0 - Live 0x00000000 sunxi_keyboard 3021 0 - Live 0x00000000 sw_device 13916 0 - Live 0x00000000 uvcvideo 61212 0 - Live 0x00000000 videobuf2_vmalloc 2600 1 uvcvideo, Live 0x00000000 videobuf2_memops 2366 1 videobuf2_vmalloc, Live 0x00000000 videobuf2_core 18902 1 uvcvideo, Live 0x00000000 vfe_v4l2 445492 1 - Live 0x00000000 gc2145 12782 0 - Live 0x00000000 vfe_subdev 4523 2 vfe_v4l2,gc2145, Live 0x00000000 vfe_os 3951 2 vfe_v4l2,vfe_subdev, Live 0x00000000 cci 21775 2 vfe_v4l2,gc2145, Live 0x00000000 videobuf_dma_contig 5567 1 vfe_v4l2, Live 0x00000000 videobuf_core 16520 2 vfe_v4l2,videobuf_dma_contig, Live 0x00000000 bcm_btlpm 7442 0 - Live 0x00000000 bcmdhd 629907 0 - Live 0x00000000 mali 210546 20 - Live 0x00000000 (O) lcd 41263 0 - Live 0x00000000 disp 992816 8 mali,lcd, Live 0x00000000 nand 282782 0 - Live 0x00000000 (O) shell@astar-evb30:/ $ 3、(可选操作)没有/dev/video1,只有/dev/video0 R:\wyb\gc2145_parrotv1.1_r16m\android\device\softwinner\astar-evb30\ueventd.sun8i.rc /dev/video0 0666 media media #/dev/video1 0666 media media 4、驱动程序:gc2145.c及其V4L2的适配层。 配置gc2145.c的编译选项,只需要修改device目录中的Makefile打开gc2145即可: R:\wyb\gc2145_parrotv1.1_r16m\lichee\linux-3.4\drivers\media\video\sunxi-vfe\device\gc2145.c (请严重注意,全志R16的parrotv1.1/android4.4.2的SDK里面是没有,只有android6.0下有) R:\wyb\gc2145_parrotv1.1_r16m\lichee\linux-3.4\drivers\media\video\sunxi-vfe\device\Makefile obj-m += gc2145.o obj-m += gc2155.o (这两个不用修改:) R:\wyb\test_ov2640_r16\lichee\linux-3.4\drivers\media\video\sunxi-vfe\Kconfig R:\wyb\test_ov2640_r16\lichee\linux-3.4\drivers\media\video\sunxi-vfe\Makefile R:\wyb\gc2145_parrotv1.1_r16m\lichee\linux-3.4\drivers\media\video\sunxi-vfe\sensor_info.c struct sensor_item sensor_list_t[] = { // name i2c_addr sensor type sensor size sensor max pclk (请参照OV2640/GC2155配置) { "gc2145" , 0x78, SENSOR_YUV , PIXEL_NUM_2M , CORE_CLK_RATE_FOR_2M}, { "ov2640" , 0x60, SENSOR_YUV , PIXEL_NUM_2M , CORE_CLK_RATE_FOR_2M}, …… }; 5、 R:\wyb\gc2145_parrotv1.1_r16m\lichee\tools\pack\chips\sun8iw5p1\configs\evb-30\sys_config.fex [power_sply] dcdc1_vol = 3000 dcdc2_vol = 1100 dcdc3_vol = 1200 dcdc4_vol = 0 dcdc5_vol = 1500 aldo2_vol = 2500 aldo3_vol = 3000 dldo3_vol = 3300 eldo1_vol = 2800 eldo2_vol = 1800 eldo3_vol = 1800 ;gldo1_vol = 3300 ldoio0_vol = 2800 ldoio1_vol = 3300 ;-------------------------------------------------------------------------------- ;vip (video input port) configuration ;vip_used: 0:disable 1:enable ;vip_mode: 0:sample one interface to one buffer 1:sample two interface to one buffer ;vip_dev_qty: The quantity of devices linked to capture bus ; ;vip_define_sensor_list: If you want use sensor detect function, please set vip_define_sensor_list = 1, and ; verify that file /system/etc/hawkview/sensor_list_cfg.ini is properly configured! ; ;vip_dev(x)_pos: sensor position, "rear" or "front", if vip_define_sensor_list = 1,vip_dev(x)_pos must be configured! ; ;vip_dev(x)_isp_used 0:not use isp 1:use isp ;vip_dev(x)_fmt: 0:yuv 1:bayer raw rgb ;vip_dev(x)_stby_mode: 0:not shut down power at standby 1:shut down power at standby ;vip_dev(x)_vflip: flip in vertical direction 0:disable 1:enable ;vip_dev(x)_hflip: flip in horizontal direction 0:disable 1:enable ;vip_dev(x)_iovdd: camera module io power handle string, pmu power supply ;vip_dev(x)_iovdd_vol: camera module io power voltage, pmu power supply ;vip_dev(x)_avdd: camera module analog power handle string, pmu power supply ;vip_dev(x)_avdd_vol: camera module analog power voltage, pmu power supply ;vip_dev(x)_dvdd: camera module core power handle string, pmu power supply ;vip_dev(x)_dvdd_vol: camera module core power voltage, pmu power supply ;vip_dev(x)_afvdd: camera module vcm power handle string, pmu power supply ;vip_dev(x)_afvdd_vol: camera module vcm power voltage, pmu power supply ;x indicates the index of the devices which are linked to the same capture bus ;fill voltage in uV, e.g. iovdd = 2.8V, vip_devx_iovdd_vol = 2800000 ;fill handle string as below: ;axp22_eldo3 ;axp22_dldo4 ;axp22_eldo2 ;fill handle string "" when not using any pmu power supply ;-------------------------------------------------------------------------------- [csi0] vip_used = 1 vip_mode = 0 vip_dev_qty = 1 vip_define_sensor_list = 0 vip_csi_pck = port:PE00<2><default><default><default> vip_csi_mck = port:PE01<2><default><default><default> vip_csi_hsync = port:PE02<2><default><default><default> vip_csi_vsync = port:PE03<2><default><default><default> vip_csi_d0 = port:PE04<2><default><default><default> vip_csi_d1 = port:PE05<2><default><default><default> vip_csi_d2 = port:PE06<2><default><default><default> vip_csi_d3 = port:PE07<2><default><default><default> vip_csi_d4 = port:PE08<2><default><default><default> vip_csi_d5 = port:PE09<2><default><default><default> vip_csi_d6 = port:PE10<2><default><default><default> vip_csi_d7 = port:PE11<2><default><default><default> vip_csi_sck = port:PE12<2><default><default><default> vip_csi_sda = port:PE13<2><default><default><default> vip_dev0_mname = "gc2145" vip_dev0_pos = "rear" vip_dev0_lane = 1 vip_dev0_twi_id = 2 vip_dev0_twi_addr = 0x78 vip_dev0_isp_used = 0 vip_dev0_fmt = 0 vip_dev0_stby_mode = 0 vip_dev0_vflip = 0 vip_dev0_hflip = 0 vip_dev0_iovdd = "" vip_dev0_iovdd_vol = 2800000 vip_dev0_avdd = "axp22_ldoio0" vip_dev0_avdd_vol = 2800000 vip_dev0_dvdd = "axp22_ldoio1" vip_dev0_dvdd_vol = 1800000 vip_dev0_afvdd = "" vip_dev0_afvdd_vol = 2800000 vip_dev0_power_en = vip_dev0_reset = port:PE14<1><default><default><0> vip_dev0_pwdn = port:PE15<1><default><default><1> vip_dev0_flash_en = vip_dev0_flash_mode = vip_dev0_af_pwdn = (可选配置:) ;---------------------------------------------------------------------------------- ;usb configuration ;usb_used: usb controller enable, 0-disable, 1-enable ;usb_port_type: usb mode: 0-device, 1-host, 2-otg ;usb_detect_type: usb hotplug detect mode, 0-none, 1-vbus/id detect, 2-id/dpdm detect ;usb_id_gpio: usb id detect IO ;usb_det_vbus_gpio: usb vbus detect IO, "axp_ctrl" for axp ;usb_drv_vbus_gpio: usb dirve vbus IO ;usb_restrict_gpio: usb current restrict IO ;usb_restric_flag: usb current restrict flag ;---------------------------------------------------------------------------------- [usbc0] usb_used = 1 usb_port_type = 0 power_start = 3 6、开发板上摄像头的I2C挂载在TWI2上面了,逻辑是需要打开的(但是不打开也能够用,很奇怪!): ;---------------------------------------------------------------------------------- ;i2c configuration ; twi_used = twix enable ;---------------------------------------------------------------------------------- [twi0] twi_used = 1 twi_scl = port:PH02<2><default><default><default> twi_sda = port:PH03<2><default><default><default> [twi1] twi_used = 1 twi_scl = port:PH04<2><default><default><default> twi_sda = port:PH05<2><default><default><default> [twi2] twi_used = 0 twi_scl = port:PE12<3><default><default><default> twi_sda = port:PE13<3><default><default><default> 直接配置摄像头的I2C了: vip_csi_sck = port:PE12<2><default><default><default> vip_csi_sda = port:PE13<2><default><default><default> 不过奇怪的是,摄像头并没有向其它平台那样生成设备节点: shell@astar-evb30:/ $ shell@astar-evb30:/ $ cd /sys/class/i2c-adapter shell@astar-evb30:/sys/class/i2c-adapter $ shell@astar-evb30:/sys/class/i2c-adapter $ shell@astar-evb30:/sys/class/i2c-adapter $ ll lrwxrwxrwx root root 1970-01-01 08:00 i2c-0 -> ../../devices/platform/twi.0/i2c-0 lrwxrwxrwx root root 1970-01-01 08:00 i2c-1 -> ../../devices/platform/twi.1/i2c-1 shell@astar-evb30:/sys/class/i2c-adapter $ 可能是全志R16的驱动程序不太规范吧!没有通过i2c_detect来注册2-003C这个节点。 直接在驱动程序中读取I2C,还是对的。0xF0/0xF1 device ID = 0x2145。 #define V4L2_IDENT_SENSOR 0x2145 /* * The gc2145 sits on i2c with ID 0x78 */ #define I2C_ADDR 0x78 #define SENSOR_NAME "gc2145"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值