全志平台boot里TVD倒车显示功能开发

 倒车显示分两个部分,前端处理好视频输入信号,准备好内容,后端显示驱动再来把内容显示到LCD上。很明显,前端是TVD模块来处理的,后端是有DE模块来处理的,我们接下来先分析一下TVD模块怎么工作的。

      首先,需要加载驱动打开设备驱动,如果有需要还可以执行IOCTL操作,跟在linux系统里操作驱动的IOCTL类似。代码如下:

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

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. ret = wBoot_driver_install("c:\\drv_tvd.drv");  
  2. if(ret != 0)  
  3. {  
  4.     DMSG_PANIC("ERR: wBoot_driver_install drv_tvd driver failed\n");  
  5.     return -1;  
  6. }  
  7.   
  8.    ret = wBoot_script_parser_fetch("tvin_para", "tvin_reverse_channel_num", &reverseChannel, 1);  
  9. if(ret)  
  10. {  
  11.     __inf("unable to find tvin_para tvin_reverse_channel_num value\n");  
  12. }  
  13.   
  14.   
  15. __inf("BoardInit_TVD: reverseChannel=%x\n", reverseChannel);  
  16. TVDTransferToDRVInfo.ch = reverseChannel;  
  17. //open tvd devices , we transfer some TVD parameter to driver  
  18. tvd_hd = wBoot_driver_open(EGON2_EMOD_TYPE_DRV_TVD, &TVDTransferToDRVInfo);  
  19. if(tvd_hd == NULL)  
  20. {  
  21.     DMSG_PANIC("ERR: open drv_tvd driver failed\n");  
  22.     return -1;  
  23. }  
[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. ret = wBoot_driver_install("c:\\drv_tvd.drv");  
  2. if(ret != 0)  
  3. {  
  4.     DMSG_PANIC("ERR: wBoot_driver_install drv_tvd driver failed\n");  
  5.     return -1;  
  6. }  
  7.   
  8.    ret = wBoot_script_parser_fetch("tvin_para", "tvin_reverse_channel_num", &reverseChannel, 1);  
  9. if(ret)  
  10. {  
  11.     __inf("unable to find tvin_para tvin_reverse_channel_num value\n");  
  12. }  
  13.   
  14.   
  15. __inf("BoardInit_TVD: reverseChannel=%x\n", reverseChannel);  
  16. TVDTransferToDRVInfo.ch = reverseChannel;  
  17. //open tvd devices , we transfer some TVD parameter to driver  
  18. tvd_hd = wBoot_driver_open(EGON2_EMOD_TYPE_DRV_TVD, &TVDTransferToDRVInfo);  
  19. if(tvd_hd == NULL)  
  20. {  
  21.     DMSG_PANIC("ERR: open drv_tvd driver failed\n");  
  22.     return -1;  
  23. }  

       加载驱动会执行到init接口,打开设备的时候会执行open接口,对应接口在上一篇文章中有介绍到。那么,我们可以再open的接口里对TVD    模块做一些必要的设置,当然一些模块的参数,我们可以再open的时候传给TVD的驱动,也就是传给DRV_TVD_OPEN函数接口。笔者根据需要传了一些控制参数进去,比如选择的TVD channel通道号,因为TVD有4个channel;显示的视频信号格式是NTSC信号还是PAL的信号,这样可以加快初始化,加快出正确的图像;以及Y/C的buffer地址,这里是为了让display这边方便的拿到显示buffer的地址,当然申请buffer放到TVD驱动里也是可以的,但是对应显示驱动就得晚于TVD驱动执行,这个问题其实也有人写一个固定的安全内存地址,其实也可以,只是感觉不灵活。

      下面就说说TVD的具体驱动,首先TVD需要设置的是CLK,没有CLK什么都是扯,主要是ahb bus、tvd模块、DRAM、PLL3  VIDEO相关的clock,大致如下:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.     ccm_clock_disable(TVD_CKID);  
  2.     ccm_clock_enable(TVD_CKID);  
  3.     set_wbit(CCM_DRAMCLK_GATE_CTRL, 0x1U<<4);//tvd   
  4.     if(mode<4)  
  5.     {  
  6.         put_wvalue(CCM_PLL3_VIDEO_CTRL,0x80105000);  
  7.         put_wvalue(CCM_TVD_SCLK_CTRL,0x8000800a);  
  8.     }  
  9.     else  
  10.     {  
  11.         put_wvalue(CCM_PLL3_VIDEO_CTRL,0x8010905a);  
  12.         put_wvalue(CCM_TVD_SCLK_CTRL,0x80008004);  
  13.     }  
  14.   
  15.   
  16. void ccm_clock_enable(u32 clk_id)  
  17. {  
  18.     switch(clk_id>>8) {  
  19.         case AXI_BUS:  
  20.             set_wbit(CCM_AXI_GATE_CTRL, 0x1U<<(clk_id&0xff));  
  21.             break;  
  22.         case AHB_BUS0:  
  23.             set_wbit(CCM_AHB_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  24.             break;  
  25.         case AHB_BUS1:  
  26.             set_wbit(CCM_AHB_GATE1_CTRL, 0x1U<<(clk_id&0xff));  
  27.             break;  
  28.         case APB0_BUS0:  
  29.             set_wbit(CCM_APB0_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  30.             break;  
  31.         case APB1_BUS0:  
  32.             set_wbit(CCM_APB1_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  33.             break;  
  34.     }  
  35. }  
  36.   
  37. void ccm_clock_disable(u32 clk_id)  
  38. {  
  39.     switch(clk_id>>8) {  
  40.         case AXI_BUS:  
  41.             clr_wbit(CCM_AXI_GATE_CTRL, 0x1U<<(clk_id&0xff));  
  42.             break;  
  43.         case AHB_BUS0:  
  44.             clr_wbit(CCM_AHB_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  45.             break;  
  46.         case AHB_BUS1:  
  47.             clr_wbit(CCM_AHB_GATE1_CTRL, 0x1U<<(clk_id&0xff));  
  48.             break;  
  49.         case APB0_BUS0:  
  50.             clr_wbit(CCM_APB0_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  51.             break;  
  52.         case APB1_BUS0:  
  53.             clr_wbit(CCM_APB1_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  54.             break;  
  55.     }  
  56. }  
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.     ccm_clock_disable(TVD_CKID);  
  2.     ccm_clock_enable(TVD_CKID);  
  3.     set_wbit(CCM_DRAMCLK_GATE_CTRL, 0x1U<<4);//tvd  
  4.     if(mode<4)  
  5.     {  
  6.         put_wvalue(CCM_PLL3_VIDEO_CTRL,0x80105000);  
  7.         put_wvalue(CCM_TVD_SCLK_CTRL,0x8000800a);  
  8.     }  
  9.     else  
  10.     {  
  11.         put_wvalue(CCM_PLL3_VIDEO_CTRL,0x8010905a);  
  12.         put_wvalue(CCM_TVD_SCLK_CTRL,0x80008004);  
  13.     }  
  14.   
  15.   
  16. void ccm_clock_enable(u32 clk_id)  
  17. {  
  18.     switch(clk_id>>8) {  
  19.         case AXI_BUS:  
  20.             set_wbit(CCM_AXI_GATE_CTRL, 0x1U<<(clk_id&0xff));  
  21.             break;  
  22.         case AHB_BUS0:  
  23.             set_wbit(CCM_AHB_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  24.             break;  
  25.         case AHB_BUS1:  
  26.             set_wbit(CCM_AHB_GATE1_CTRL, 0x1U<<(clk_id&0xff));  
  27.             break;  
  28.         case APB0_BUS0:  
  29.             set_wbit(CCM_APB0_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  30.             break;  
  31.         case APB1_BUS0:  
  32.             set_wbit(CCM_APB1_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  33.             break;  
  34.     }  
  35. }  
  36.   
  37. void ccm_clock_disable(u32 clk_id)  
  38. {  
  39.     switch(clk_id>>8) {  
  40.         case AXI_BUS:  
  41.             clr_wbit(CCM_AXI_GATE_CTRL, 0x1U<<(clk_id&0xff));  
  42.             break;  
  43.         case AHB_BUS0:  
  44.             clr_wbit(CCM_AHB_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  45.             break;  
  46.         case AHB_BUS1:  
  47.             clr_wbit(CCM_AHB_GATE1_CTRL, 0x1U<<(clk_id&0xff));  
  48.             break;  
  49.         case APB0_BUS0:  
  50.             clr_wbit(CCM_APB0_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  51.             break;  
  52.         case APB1_BUS0:  
  53.             clr_wbit(CCM_APB1_GATE0_CTRL, 0x1U<<(clk_id&0xff));  
  54.             break;  
  55.     }  
  56. }  

        接着就是控制TVD模块具体的寄存器了,使能必不可少,IRQ设置不可少,对比度、亮度、饱和度等,当然还有其他的一堆,初步的值是全志提供的,但是为了更好的显示效果,主要是匹配你这个产品的屏参吧,那我们就看一段NTSC的参数吧!

 

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.     put_wvalue( TVD_BASE + 0x00080x00590900); //notch width 0059_0100   
  2.     put_wvalue( TVD_BASE + 0x000c, 0x00000010); //YC sep   
  3.     put_wvalue( TVD_BASE + 0x00100x008A32DD); //sync height   
  4.     put_wvalue( TVD_BASE + 0x00140x800000a0); //adjust YC delay   
  5.     put_wvalue( TVD_BASE + 0x00180x00002080); //adjust luma brightness   
  6.     put_wvalue( TVD_BASE + 0x001c, 0x008a0080); //chroma AGC target   
  7.     put_wvalue( TVD_BASE + 0x00240x0682810a); //DISABLE AGC GATE KILL!!!!!!!!!!!!!!!!!   
  8.     put_wvalue( TVD_BASE + 0x00280x00006440); //0000_6440    0000_5838   
  9.     put_wvalue( TVD_BASE + 0x00340x20000000); //2000_0000    2400_0000   
  10.     put_wvalue( TVD_BASE + 0x00440x50824632); //burst gate   
  11.     put_wvalue( TVD_BASE + 0x004c, 0x0e70106c); //NO CLAMP DURING VSYNC!!!!!!!!!!!!!!!!!   
  12.     put_wvalue( TVD_BASE + 0x00540x00000025); //peak en   
  13.     put_wvalue( TVD_BASE + 0x006c, 0x00fffa0a); //YC separation config   
  14.     put_wvalue( TVD_BASE + 0x00800x00500082); //hactive start and width   
  15.     put_wvalue( TVD_BASE + 0x00840x00610022); //vactive start and height   
  16.     put_wvalue( TVD_BASE + 0x00300x21f07c1f); //21f0_7c1f    262E_8BA2   
  17.     put_wvalue( TVD_BASE + 0x002c, 0x0000CB74);  
  18.     put_wvalue( TVD_BASE + 0x00740x000003c3); //chroma edge enhance   
  19.     put_wvalue( TVD_BASE + 0x050c, 0x0000000b);  
  20.     put_wvalue( TVD_BASE + 0x051c, 0x00100000);  
  21.   
  22. put_wvalue( TVD_BASE + 0x0134 + ch * 0x100, y<<16 | x);  
  23. put_wvalue( TVD_BASE + 0x0138 + ch * 0x100, len);  
  24.   
  25. put_wvalue( TVD_BASE + 0x0100 + ch * 0x100, addr0);  
  26. put_wvalue( TVD_BASE + 0x0110 + ch * 0x100, addr1);  
  27. put_wvalue( TVD_BASE + 0x0104 + ch * 0x100, addr2);  
  28. put_wvalue( TVD_BASE + 0x0114 + ch * 0x100, addr3);  
  29. put_wvalue( TVD_BASE + 0x0108 + ch * 0x100, addr4);  
  30. put_wvalue( TVD_BASE + 0x0118 + ch * 0x100, addr5);  
  31. put_wvalue( TVD_BASE + 0x010c + ch * 0x100, addr6);  
  32. put_wvalue( TVD_BASE + 0x011c + ch * 0x100, addr7);  
  33. put_wvalue( TVD_BASE + 0x0130 + ch * 0x100, frame<<26   | is_mb<<24 |       \                                       hsample<<12 | is_yuv422<<4 | 0x1);  
  34.   
  35.        put_wvalue(TVD_BASE+0x0148,0xf1ffffff);//int//int en//frame end, overflow, underflow   
  36.        put_wvalue(TVD_BASE+0x0140,0xffffffff);//clear irq//frame end, overflow, underflow   
  37.        put_wvalue(TVD_BASE+0x014c,0xffffffff);//address change error   
  38.        put_wvalue(TVD_BASE+0x0150,0x00000000);//int en//lock unlock   
  39.        put_wvalue(TVD_BASE+0x0154,0x0000ffff);//clear irq//lock unlock    
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.     put_wvalue( TVD_BASE + 0x00080x00590900); //notch width 0059_0100  
  2.     put_wvalue( TVD_BASE + 0x000c, 0x00000010); //YC sep  
  3.     put_wvalue( TVD_BASE + 0x00100x008A32DD); //sync height  
  4.     put_wvalue( TVD_BASE + 0x00140x800000a0); //adjust YC delay  
  5.     put_wvalue( TVD_BASE + 0x00180x00002080); //adjust luma brightness  
  6.     put_wvalue( TVD_BASE + 0x001c, 0x008a0080); //chroma AGC target  
  7.     put_wvalue( TVD_BASE + 0x00240x0682810a); //DISABLE AGC GATE KILL!!!!!!!!!!!!!!!!!  
  8.     put_wvalue( TVD_BASE + 0x00280x00006440); //0000_6440    0000_5838  
  9.     put_wvalue( TVD_BASE + 0x00340x20000000); //2000_0000    2400_0000  
  10.     put_wvalue( TVD_BASE + 0x00440x50824632); //burst gate  
  11.     put_wvalue( TVD_BASE + 0x004c, 0x0e70106c); //NO CLAMP DURING VSYNC!!!!!!!!!!!!!!!!!  
  12.     put_wvalue( TVD_BASE + 0x00540x00000025); //peak en  
  13.     put_wvalue( TVD_BASE + 0x006c, 0x00fffa0a); //YC separation config  
  14.     put_wvalue( TVD_BASE + 0x00800x00500082); //hactive start and width  
  15.     put_wvalue( TVD_BASE + 0x00840x00610022); //vactive start and height  
  16.     put_wvalue( TVD_BASE + 0x00300x21f07c1f); //21f0_7c1f    262E_8BA2  
  17.     put_wvalue( TVD_BASE + 0x002c, 0x0000CB74);  
  18.     put_wvalue( TVD_BASE + 0x00740x000003c3); //chroma edge enhance  
  19.     put_wvalue( TVD_BASE + 0x050c, 0x0000000b);  
  20.     put_wvalue( TVD_BASE + 0x051c, 0x00100000);  
  21.   
  22. put_wvalue( TVD_BASE + 0x0134 + ch * 0x100, y<<16 | x);  
  23. put_wvalue( TVD_BASE + 0x0138 + ch * 0x100, len);  
  24.   
  25. put_wvalue( TVD_BASE + 0x0100 + ch * 0x100, addr0);  
  26. put_wvalue( TVD_BASE + 0x0110 + ch * 0x100, addr1);  
  27. put_wvalue( TVD_BASE + 0x0104 + ch * 0x100, addr2);  
  28. put_wvalue( TVD_BASE + 0x0114 + ch * 0x100, addr3);  
  29. put_wvalue( TVD_BASE + 0x0108 + ch * 0x100, addr4);  
  30. put_wvalue( TVD_BASE + 0x0118 + ch * 0x100, addr5);  
  31. put_wvalue( TVD_BASE + 0x010c + ch * 0x100, addr6);  
  32. put_wvalue( TVD_BASE + 0x011c + ch * 0x100, addr7);  
  33. put_wvalue( TVD_BASE + 0x0130 + ch * 0x100, frame<<26   | is_mb<<24 |       \                                       hsample<<12 | is_yuv422<<4 | 0x1);  
  34.   
  35.        put_wvalue(TVD_BASE+0x0148,0xf1ffffff);//int//int en//frame end, overflow, underflow  
  36.        put_wvalue(TVD_BASE+0x0140,0xffffffff);//clear irq//frame end, overflow, underflow  
  37.        put_wvalue(TVD_BASE+0x014c,0xffffffff);//address change error  
  38.        put_wvalue(TVD_BASE+0x0150,0x00000000);//int en//lock unlock  
  39.        put_wvalue(TVD_BASE+0x0154,0x0000ffff);//clear irq//lock unlock    

        这些程序一走,数据就差不多出来了。那么接下来就准备显示吧!

       显示这部分在boot里面也已经是支持了的,但是需要自己去改造成自己需要的。首先模块的初始化还是借用boot里面已经支持的BoardInit_Display()接口,除此之前就需要自己动手来做了。比如要设置显示layer具体参数,比如显示的宽高、buffer的地址、显示的格式、是否是UV combined模式等,也不少。除此之外还得打开layer,因为申请layer已经在BoardInit_Display()接口里完成了。笔者的NTSC的显示参数大致如下:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. memset((&layer_para), 0sizeof(layer_para));  
  2. layer_para.fb.size.width        = 704;  
  3. layer_para.fb.size.height       = 480;  
  4. layer_para.fb.addr[0]           = (__u32)TVDTransferToDRVInfo.addrYx;//TVD_ADDR_Y0;   
  5. layer_para.fb.addr[1]           = (__u32)TVDTransferToDRVInfo.addrCx;//TVD_ADDR_C0;   
  6. layer_para.fb.mode = DISP_MOD_NON_MB_UV_COMBINED;  
  7. layer_para.fb.format = DISP_FORMAT_YUV422;  
  8. layer_para.fb.br_swap = 0;  
  9. layer_para.fb.seq = DISP_SEQ_UYVY;  
  10. layer_para.ck_enable        = 0;  
  11. layer_para.mode           = DISP_LAYER_WORK_MODE_SCALER;  
  12. layer_para.alpha_en       = 1;  
  13. layer_para.alpha_val      = 0xff;  
  14. layer_para.pipe           = 0;  
  15. layer_para.src_win.x      = 15;  
  16. layer_para.src_win.y      = 10;  
  17. layer_para.src_win.width  = 688;  
  18. layer_para.src_win.height = 470;  
  19. layer_para.scn_win.x      = 0;  
  20. layer_para.scn_win.y      = 0;  
  21. layer_para.scn_win.width  = De_GetSceenWidth();  
  22. layer_para.scn_win.height = De_GetSceenHeight();  
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. memset((&layer_para), 0sizeof(layer_para));  
  2. layer_para.fb.size.width        = 704;  
  3. layer_para.fb.size.height       = 480;  
  4. layer_para.fb.addr[0]           = (__u32)TVDTransferToDRVInfo.addrYx;//TVD_ADDR_Y0;  
  5. layer_para.fb.addr[1]           = (__u32)TVDTransferToDRVInfo.addrCx;//TVD_ADDR_C0;  
  6. layer_para.fb.mode = DISP_MOD_NON_MB_UV_COMBINED;  
  7. layer_para.fb.format = DISP_FORMAT_YUV422;  
  8. layer_para.fb.br_swap = 0;  
  9. layer_para.fb.seq = DISP_SEQ_UYVY;  
  10. layer_para.ck_enable        = 0;  
  11. layer_para.mode           = DISP_LAYER_WORK_MODE_SCALER;  
  12. layer_para.alpha_en       = 1;  
  13. layer_para.alpha_val      = 0xff;  
  14. layer_para.pipe           = 0;  
  15. layer_para.src_win.x      = 15;  
  16. layer_para.src_win.y      = 10;  
  17. layer_para.src_win.width  = 688;  
  18. layer_para.src_win.height = 470;  
  19. layer_para.scn_win.x      = 0;  
  20. layer_para.scn_win.y      = 0;  
  21. layer_para.scn_win.width  = De_GetSceenWidth();  
  22. layer_para.scn_win.height = De_GetSceenHeight();  

        通过以上的简单分析,倒车显示是基本OK了。但是记得退出倒车的时候要关闭显示,关闭TVD,卸载对应驱动。到此,基本上整个过程就分析完了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值