kernel与用户层接口之字符设备接口

kernel与用户层接口之字符设备接口:


两种方法: 

1.  register_chrdev方法

2.  platform_driver方法


platform_driver方法原理:

platform_driver和platform_device的name名字名字必须匹配才能实现device和driver的绑定?

(1)在内核初始化时kernel_init()->do_basic_setup()->driver_init()->platform_bus_init()初始化platform_bus(虚拟总线);

(2)设备注册的时候platform_device_register()->platform_device_add()->(pdev->dev.bus = &platform_bus_type)把设备挂在虚拟的platform bus下;

(3)驱动注册的时候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev(),对每个挂在虚拟的platform bus的设备作__driver_attach()->driver_probe_device(),判断drv->bus->match()是否存在并且是否执行成功,此时通过指针执行platform_match,比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),如果相符就调用really_probe(实际就是执行的相应设备的platform_driver->probe(platform_device),注意platform_drv_probe的_dev参数是由bus_for_each_dev的next_device获得)开始真正的探测加载,如果probe成功则绑定该设备到该驱动。

      当进入probe函数后,需要获取设备的资源信息,根据参数type所指定类型,例如IORESOURCE_MEM,来分别获取指定的资源。
struct resource * platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);当然,也可以固定资源类型,如获取资源中的中断号:struct int platform_get_irq(struct platform_device *dev, unsigned int num);

      probe函数一般完成硬件设备使能,struct resource的获取以及虚拟地址的动态映射和具体类型设备的注册(因为平台设备只是一种虚拟的设备类型);remove函数完成硬件设备的关闭,struct resource以及虚拟地址的动态映射的释放和具体类型设备的注销。只要和内核本身运行依赖性不大的外围设备 ( 换句话说只要不在内核运行所需的一个最小系统之内的设备 ), 相对独立的拥有各自独自的资源 (addresses and IRQs) ,都可以用platform_driver 实现。如:lcd,usb,uart 等,都可以用platfrom_driver 写,而timer,irq等最小系统之内的设备则最好不用platfrom_driver 机制,实际上内核实现也是这样的。



从linux内核2.6的某个版本之后,devfs不复存在,udev成为devfs的替代。提醒一点,udev是应用层的,不要试图在内核的配置选项里找到它;加入对udev的支持很简单,在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用device_create创建对应的设备。

大致用法如下:

        struct class *myclass ;
        class_create(THIS_MODULE, “my_device_driver”);
        device_create(myclass, NULL, MKDEV(major_num, minor_num), NULL, “my_device”);


这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备文件。

我们在刚开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点,实际上Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在 /dev目录下创建相应设备节点,并在卸载模块时删除该节点,当然前提条件是用户空间移植了udev。

内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。

这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。


struct class和device_create(…) 以及device_create(…)都定义在/include/linux/device.h中,使用的时候一定要包含这个头文件.


[cpp]  view plain copy
  1. /* 
  2.  * drivers/video/Tcc_overlay.c 
  3.  * 
  4.  * Copyright (C) 2004 Telechips, Inc.  
  5.  * 
  6.  * Video-for-Linux (Version 2) graphic capture driver 
  7.  * 
  8.  *  
  9.  * This package is free software; you can redistribute it and/or modify  
  10.  * it under the terms of the GNU General Public License version 2 as 
  11.  * published by the Free Software Foundation.  
  12.  *  
  13.  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR  
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED  
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.  
  16.  * 
  17.  */  
  18. #include <linux/module.h>  
  19. #include <linux/kernel.h>  
  20. #include <linux/errno.h>  
  21. #include <linux/string.h>  
  22. #include <linux/mm.h>  
  23. #include <linux/slab.h>  
  24. #include <linux/delay.h>  
  25. #include <linux/fb.h>  
  26. #include <linux/init.h>  
  27. #include <linux/dma-mapping.h>  
  28. #include <linux/interrupt.h>  
  29. #include <linux/workqueue.h>  
  30. #include <linux/wait.h>  
  31. #include <linux/platform_device.h>  
  32. #include <linux/clk.h>  
  33. #include <linux/videodev.h>  
  34. #include <linux/miscdevice.h>  
  35.   
  36. #include <asm/io.h>  
  37. #include <asm/uaccess.h>  
  38. #include <asm/div64.h>  
  39. #include <asm/mach/map.h>  
  40. #include <linux/poll.h>  
  41.   
  42. #include <mach/bsp.h>  
  43.   
  44. #include <mach/tcc_fb.h>  
  45. #include <mach/tcc_overlay_ioctl.h>  
  46. #include <mach/tccfb_ioctrl.h>  
  47.   
  48. #if 0  
  49. static int debug       = 1;  
  50. #else  
  51. static int debug       = 0;  
  52. #endif  
  53.   
  54. #define dprintk(msg...) if (debug) { printk( "tcc_overlay: " msg); }  
  55.   
  56. #define PLATFORM_DEVICE  
  57.   
  58. #define DEVICE_NAME         "overlay"  
  59. #ifdef PLATFORM_DEVICE  
  60. #define DEV_MINOR   202  
  61. #else  
  62. #define MAJOR_ID    202  
  63. #define MINOR_ID    1  
  64. #endif  
  65.   
  66. //#define OVERLAY_CNT_DEFAULT 2  
  67.   
  68. static struct clk *overlay_lcdc_clk;  
  69.   
  70. static overlay_config_t overlay_cfg;  
  71. static struct v4l2_format overlay_fmt;  
  72.   
  73. /* LCD Overlay Setting*/  
  74. #define IMG_INTL            0  
  75. #define IMG_AEN             0  
  76. #define IMG_CEN             0  
  77. #define IMG_IEN             1  
  78. #define IMG_AOPT            2  
  79. #define IMG_ASEL            0  
  80. #define IMG_PD              0  
  81. #define IMG_Y2RMD           1  
  82. #define IMG_Y2R             1  
  83. #define IMG_BR              0  
  84.   
  85. #define IMG_RGB565_FMT              10  //RGB888  
  86. #define IMG_RGB888_FMT              12  //RGB888  
  87. #define IMG_RGBYUV420_FMT         24    //RGB888  
  88. #define IMG_RGBYUV422SP_FMT         25  //RGB888  
  89. #define IMG_RGBYUV422SQ_FMT         26  //RGB888  
  90. #define IMG_RGBYUV420I_FMT         28   //YUV420_INTERLEAVED  
  91.   
  92. #define IMG_POSITION_Y      0  
  93. #define IMG_POSITION_X      0  
  94. #define IMG_HEIGHT          LCD_HEIGHT  
  95. #define IMG_WIDTH               LCD_WIDTH  
  96. #define IMG_AVAL0               95  
  97. #define IMG_AVAL1               95  
  98. static PLCDC        pLCDC1;  
  99. static volatile PLCDC_CHANNEL pLCDC1_CH0;  
  100. static unsigned char start_en = 0;  
  101. static unsigned char wait_restart = 0;  
  102. static unsigned char pos_reset = 0;  
  103.   
  104. static unsigned char overlay_en_count = 0;  
  105. unsigned char tcc_overlay_use = 0;  
  106.   
  107. //#define VC_OVERLAY_PROFILE // CAM_28pin, GPIO_D24  
  108. #ifdef VC_OVERLAY_PROFILE  
  109. static unsigned char toggle_int = 0;  
  110. #endif  
  111.   
  112. extern struct display_platform_data tcc_display_data;  
  113. extern OUTPUT_SELECT_MODE   Output_SelectMode;  
  114.   
  115. void tccxxx_overlay_check_priority(void);  
  116. unsigned char tccxxx_overlay_use(void)  
  117. {  
  118.     return tcc_overlay_use;  
  119. }  
  120. EXPORT_SYMBOL(tccxxx_overlay_use);  
  121.   
  122. void tccxxx_overlay_start(void)  
  123. {  
  124.     tccxxx_overlay_check_priority();  
  125.   
  126.     if(!start_en){  
  127.         dprintk("call start en \n");          
  128.         start_en = 1;  
  129.     }  
  130. }  
  131. EXPORT_SYMBOL(tccxxx_overlay_start);  
  132.   
  133. extern int range_is_allowed(unsigned long pfn, unsigned long size);  
  134. static int tccxxx_overlay_mmap(struct file *file, struct vm_area_struct *vma)  
  135. {  
  136.     if(range_is_allowed(vma->vm_pgoff, vma->vm_end - vma->vm_start) < 0){  
  137.         printk(KERN_ERR  "overlay: this address is not allowed \n");  
  138.         return -EAGAIN;  
  139.     }  
  140.   
  141.     vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);  
  142.     if(remap_pfn_range(vma,vma->vm_start, vma->vm_pgoff , vma->vm_end - vma->vm_start, vma->vm_page_prot))  
  143.     {  
  144.         return -EAGAIN;  
  145.     }  
  146.   
  147.     vma->vm_ops  = NULL;  
  148.     vma->vm_flags    |= VM_IO;  
  149.     vma->vm_flags    |= VM_RESERVED;  
  150.       
  151.     return 0;  
  152. }  
  153.   
  154.   
  155. DECLARE_WAIT_QUEUE_HEAD(overlay_wait);  
  156.   
  157. static unsigned int tccxxx_overlay_poll(struct file *file, struct poll_table_struct *wait)  
  158. {  
  159.     dprintk(" tccxxx_overlay_poll wait[%d][%d]!!!\n", (unsigned)wait, (unsigned)&overlay_wait);  
  160.     poll_wait(file, &(overlay_wait), wait);   
  161.     dprintk(" tccxxx_overlay_poll finish[%d][%d]!!!\n", (unsigned)wait, (unsigned)&overlay_wait);     
  162.     return POLLIN;  
  163. }  
  164.   
  165. static int tccxxx_overlay_get_pos(overlay_config_t * arg )  
  166. {  
  167.     overlay_config_t pos;  
  168.   
  169.     pos.sx      = overlay_cfg.sx;  
  170.     pos.sy      = overlay_cfg.sy;  
  171.     pos.width   = overlay_cfg.width;  
  172.     pos.height  = overlay_cfg.height;  
  173.     dprintk(" Overlay -> Get Position :: (%d,%d) | (%d,%d) \n", overlay_cfg.sx, overlay_cfg.sy, overlay_cfg.width, overlay_cfg.height);  
  174.       
  175.     if(copy_to_user((overlay_config_t *)arg, &pos, sizeof(overlay_config_t)))  
  176.         return -EFAULT;  
  177.   
  178.     return 0;  
  179. }  
  180.   
  181. static int tccxxx_overlay_get_screenInfo(overlay_config_t * arg )  
  182. {  
  183.     struct lcd_panel *panel;  
  184.     unsigned int screen_width, screen_height;  
  185.   
  186.     overlay_config_t screen_info;  
  187.   
  188.     panel = tccfb_get_panel();  
  189.     screen_width      = panel->xres;  
  190.     screen_height     = panel->yres;  
  191.   
  192. #if defined(CONFIG_TCC_HDMI_UI_SIZE_1280_720)  
  193.     if(tcc_display_data.resolution == 1)  
  194.     {  
  195.         screen_width      = 720;  
  196.         screen_height     = 576;  
  197.     }  
  198.     else if(tcc_display_data.resolution == 2)  
  199.     {  
  200.         screen_width      = 800;  
  201.         screen_height     = 480;  
  202.     }  
  203. #endif    
  204.   
  205.     screen_info.sx      = 0;  
  206.     screen_info.sy      = 0;  
  207.     screen_info.width   = screen_width;  
  208.     screen_info.height  = screen_height;  
  209.       
  210.     dprintk(" Overlay -> Get ScreenInfo :: (%d,%d) | (%d,%d) \n", screen_info.sx, screen_info.sy, screen_info.width, screen_info.height);  
  211.       
  212.     if(copy_to_user((overlay_config_t *)arg, &screen_info, sizeof(overlay_config_t)))  
  213.         return -EFAULT;  
  214.   
  215.     return 0;  
  216. }  
  217.   
  218. void tccxxx_overlay_fmt_set(unsigned int fmt)  
  219. {  
  220.     dprintk(" Overlay -> S_FMT :: format = 0x%x(RGB565-0x%x, YUV420-0x%x, YUV420inter-0x%x) \n", fmt, V4L2_PIX_FMT_RGB565,V4L2_PIX_FMT_YVU420, V4L2_PIX_FMT_NV12);  
  221.   
  222.     if(fmt == V4L2_PIX_FMT_RGB565)  
  223.     {  
  224.         BITCSET (pLCDC1->LI0C, 0x1f<< 0,   (IMG_RGB565_FMT) <<  0); // format  
  225.         BITCSET (pLCDC1->LI0O, 0x0000FFFF,   overlay_cfg.width * 2); // format  
  226.         BITCSET (pLCDC1->LI0C, 0x1<<  8,   (0)  <<  8); // y2r converter enable  
  227.     }  
  228.     else if(fmt == V4L2_PIX_FMT_NV12)  
  229.     {  
  230.         BITCSET (pLCDC1->LI0C, 0x1f<< 0,   (IMG_RGBYUV420I_FMT) <<  0); // format  
  231.         BITCSET (pLCDC1->LI0O, 0xFFFFFFFF,   ((overlay_cfg.width)<<16) | (overlay_cfg.width)); // format             
  232.         BITCSET (pLCDC1->LI0C, 0x1<<  8,   (IMG_Y2R)  <<  8); // y2r converter enable  
  233.     }  
  234.     else if(fmt == V4L2_PIX_FMT_YUV422P)  
  235.     {  
  236.         BITCSET (pLCDC1->LI0C, 0x1f<< 0,   (IMG_RGBYUV422SQ_FMT) <<  0); // format  
  237.         BITCSET (pLCDC1->LI0O, 0x0000FFFF,   overlay_cfg.width * 2); // format  
  238.         BITCSET (pLCDC1->LI0C, 0x1<<  8,   (IMG_Y2R)  <<  8); // y2r converter enable  
  239.     }  
  240.     else  
  241.     {  
  242.         BITCSET (pLCDC1->LI0C, 0x1f<< 0,   (IMG_RGBYUV420_FMT) <<    0); // format  
  243.         BITCSET (pLCDC1->LI0O, 0xFFFFFFFF,   ((overlay_cfg.width/2)<<16) | (overlay_cfg.width)); // format               
  244.         BITCSET (pLCDC1->LI0C, 0x1<<  8,   (IMG_Y2R)  <<  8); // y2r converter enable  
  245.     }  
  246. }  
  247.   
  248. void tccxxx_overlay_check_priority(void)  
  249. {  
  250.     unsigned int ch0_region, ch1_region;  
  251.     PLCDC pLCD;  
  252.   
  253. #if !defined(CONFIG_ARCH_TCC92XX)     
  254.     if(Output_SelectMode != OUTPUT_SELECT_NONE)  
  255.     {     
  256.         pLCD = (volatile PLCDC)tcc_p2v(HwLCDC0_BASE);  
  257.     }  
  258.     else  
  259. #endif  
  260.     {  
  261.         pLCD = (volatile PLCDC)tcc_p2v(HwLCDC1_BASE);  
  262.     }  
  263.       
  264.     if((pLCD->LI1C & Hw28) && (pLCD->LI0C & Hw28))  
  265.     {  
  266.         ch0_region = (pLCD->LI0S&0xFFFF) * ((pLCD->LI0S >> 16)&0xFFFF);  
  267.         ch1_region = (pLCD->LI1S&0xFFFF) * ((pLCD->LI1S >> 16)&0xFFFF);  
  268.           
  269.         if(ch0_region < ch1_region)  
  270.         {  
  271.             // 2 > 0 > 1            
  272.             dprintk(" CH_priority :%d: (2 > 0 > 1) %d x %d < %d x %d \n", Output_SelectMode,   
  273.                         (pLCD->LI0S&0xFFFF), ((pLCD->LI0S >> 16)&0xFFFF), (pLCD->LI1S&0xFFFF), ((pLCD->LI1S >> 16)&0xFFFF));  
  274.             BITCSET (pLCD->LCTRL, HwLCTRL_OVP, 0x3<<1);  
  275.         }  
  276.         else  
  277.         {  
  278.             // 2 > 1 > 0            
  279.             dprintk(" CH_priority :: (2 > 1 > 0) %d x %d < %d x %d \n", Output_SelectMode,   
  280.                         (pLCD->LI0S&0xFFFF), ((pLCD->LI0S >> 16)&0xFFFF), (pLCD->LI1S&0xFFFF), ((pLCD->LI1S >> 16)&0xFFFF));  
  281.             BITCSET (pLCD->LCTRL, HwLCTRL_OVP, 0x5<<1);  
  282.         }  
  283.     }  
  284.     else  
  285.     {  
  286.         BITCSET (pLCD->LCTRL, HwLCTRL_OVP, 0x5<<1);  
  287.     }  
  288.   
  289.     return;  
  290. }  
  291.   
  292. void tccxxx_overlay_common_enable(void)  
  293. {  
  294.     unsigned int reg = 0, alpha_type = 0;     
  295.     unsigned int chroma_en;  
  296.     unsigned int alpha_blending_en;  
  297.     unsigned int chromaR, chromaG, chromaB, alpha_value;  
  298.   
  299.     if(!overlay_en_count)  
  300.     {  
  301.         reg = pLCDC1->LI2C;  
  302.         reg= (reg & 0x1F);//RGB888  
  303.           
  304.         if(reg == 0xC) // RGB888  
  305.         {  
  306.             chroma_en = 0;  
  307.             alpha_value = 200;  
  308.             alpha_type = 1;  
  309.             alpha_blending_en = 1;//1;  
  310.             chromaR = chromaG = chromaB = 0x00;  
  311.         }  
  312.         else  
  313.         {  
  314.             chroma_en = 1;  
  315.             alpha_value = 200;  
  316.             alpha_type = 0;  
  317.             alpha_blending_en = 0;//1;  
  318.             chromaR = chromaG = chromaB = 0x00;  
  319.         }  
  320.           
  321.         // overlay �Ӽ�  
  322.         BITCSET (pLCDC1->LI2C,   0x1<< 30,  (alpha_blending_en)    << 30); // alpha enable  
  323.         BITCSET (pLCDC1->LI2C, 0x1<< 29,   (chroma_en)  << 29); // chroma-keying  
  324.           
  325.         BITCSET (pLCDC1->LI2KR, 0xff <<  0, (chromaR)  <<  0); // key  
  326.         BITCSET (pLCDC1->LI2KR, 0xff << 16, (0xF8) << 16); // keymask  
  327.         BITCSET (pLCDC1->LI2KG, 0xff <<  0, (chromaG)  <<  0); // key  
  328.         BITCSET (pLCDC1->LI2KG, 0xff << 16, (0xFC) << 16); // keymask  
  329.         BITCSET (pLCDC1->LI2KB, 0xff <<  0, (chromaB)  <<  0); // key  
  330.         BITCSET (pLCDC1->LI2KB, 0xff << 16, (0xF8) << 16); // keymask  
  331.           
  332.         // alpha_value 0~255  -- 0~100% ����   
  333.         BITCSET (pLCDC1->LI2A, 0xffff <<16,  (alpha_value)<< 16); // alpha1  
  334.         BITCSET (pLCDC1->LI2A, 0xffff << 0,  (alpha_value)<<  0); // alpha0  
  335.         BITCSET (pLCDC1->LI2C, 0x3<< 25,   (IMG_AOPT)  << 25); // alpha opt  
  336.         BITCSET (pLCDC1->LI2C, 0x1<< 24,   (alpha_type)  << 24); // alpha select    
  337.   
  338. #if !defined(CONFIG_ARCH_TCC92XX)  
  339.         BITCSET (pLCDC1->LI2C, HwLCT_RU, HwLCT_RU); //Image update   
  340. #endif  
  341.     }  
  342.   
  343.     if(overlay_en_count < 2) //max overlay is 2.  
  344.         overlay_en_count++;  
  345.     dprintk("Enable :: overlay_en_count = %d \n", overlay_en_count);  
  346. }  
  347. EXPORT_SYMBOL(tccxxx_overlay_common_enable);  
  348.   
  349. void tccxxx_overlay_common_disable(int channel)  
  350. {  
  351.     dprintk("overlay disable ch:%d output mode:%d \n", channel, Output_SelectMode);  
  352.   
  353.     if(channel == 0)  
  354.     {  
  355. #if !defined(CONFIG_ARCH_TCC92XX)     
  356.         if(Output_SelectMode != OUTPUT_SELECT_NONE)  
  357.         {             
  358.             PLCDC pLCDC0 = (volatile PLCDC)tcc_p2v(HwLCDC0_BASE);  
  359.   
  360.             if(pLCDC0->LI0C & Hw28)  
  361.             {  
  362.                 BITCSET (pLCDC0->LI0C, 0x1<< 28, (0)<<28); // lcdc channel enable  
  363.                 BITCSET (pLCDC0->LI0C, HwLCT_RU, HwLCT_RU); //Image update  
  364.             }  
  365.         }  
  366. #endif  
  367.   
  368.         if(!(pLCDC1->LI0C & Hw28))  
  369.             return;  
  370.     }  
  371.     else if(channel == 1)  
  372.     {  
  373.         if(!(pLCDC1->LI1C & Hw28))  
  374.             return;  
  375.     }  
  376.     else  
  377.     {  
  378.         //to do  
  379.     }  
  380.   
  381.     if(overlay_en_count > 0)  
  382.         overlay_en_count--;  
  383.   
  384.   
  385.     if((!overlay_en_count)  
  386.         #if defined(CONFIG_ARCH_TCC92XX)  
  387.         && (Output_SelectMode == OUTPUT_SELECT_NONE)  
  388.         #endif  
  389.     )  
  390.     {  
  391. #if !defined(CONFIG_TCC_EXCLUSIVE_UI_LAYER)  
  392.         BITCSET (pLCDC1->LI2C,  0x1<< 30,  (0)  << 30); // alpha enable  
  393.         BITCSET (pLCDC1->LI2C, 0x1<< 29,    (0)  << 29); // chroma-keying  
  394.   
  395. #if !defined(CONFIG_ARCH_TCC92XX)  
  396.         BITCSET (pLCDC1->LI2C, HwLCT_RU, HwLCT_RU); //Image update   
  397. #endif  
  398. #endif  
  399.     }  
  400.   
  401.     #if defined(CONFIG_ARCH_TCC92XX)  
  402.     if(Output_SelectMode == OUTPUT_SELECT_NONE)  
  403.     #endif  
  404.     {  
  405.         if(channel == 0)  
  406.         {  
  407.             BITCSET (pLCDC1->LI0C, 0x1<< 28,   (0)  << 28); // lcdc channel enable  
  408. #if !defined(CONFIG_ARCH_TCC92XX)  
  409.             BITCSET (pLCDC1->LI0C, HwLCT_RU, HwLCT_RU); //Image update  
  410. #endif  
  411.         }  
  412.         else if(channel == 1)  
  413.         {  
  414.             BITCSET (pLCDC1->LI1C, 0x1<< 28,   (0)  << 28); // lcdc channel enable  
  415. #if !defined(CONFIG_ARCH_TCC92XX)  
  416.             BITCSET (pLCDC1->LI1C, HwLCT_RU, HwLCT_RU); //Image update  
  417. #endif  
  418.         }  
  419.         else  
  420.         {  
  421.               
  422.         }  
  423.     }  
  424.       
  425.     dprintk("Disable :: overlay_en_count = %d \n", overlay_en_count);  
  426. }  
  427. EXPORT_SYMBOL(tccxxx_overlay_common_disable);  
  428.   
  429. int tccxxx_overlay_q_buffer(unsigned int* arg )  
  430. {  
  431.     unsigned int curY_phyAddr, curU_phyAddr, curV_phyAddr;  
  432.   
  433.     if(copy_from_user(&curY_phyAddr, (unsigned int *)arg, sizeof(unsigned int)))  
  434.         return -EFAULT;  
  435.   
  436. //  dprintk(" Overlay -> Q_Buffer :: buffer = 0x%x pos_reset:%d start_en:%d\n", curY_phyAddr, pos_reset, start_en);  
  437.   
  438. #ifdef VC_OVERLAY_PROFILE  
  439.     if(toggle_int)  
  440.     {  
  441.         (HwGPIOD->GPEN |= Hw24); (HwGPIOD->GPDAT |= Hw24);  
  442.         toggle_int = 0;  
  443.     }  
  444.     else  
  445.     {  
  446.         (HwGPIOD->GPEN |= Hw24); (HwGPIOD->GPDAT &= ~Hw24);  
  447.         toggle_int = 1;  
  448.     }  
  449. #endif  
  450.   
  451.     //in case position reset in streamming.  
  452.     if(pos_reset)  
  453.     {  
  454.         pos_reset = 0;  
  455.         // position  
  456.         BITCSET (pLCDC1->LI0P, 0xffff<< 16, (overlay_cfg.sy)  << 16); // position y  
  457.         BITCSET (pLCDC1->LI0P, 0xffff<<  0, (overlay_cfg.sx)  <<  0); // position x  
  458.           
  459.         // size  
  460.         BITCSET (pLCDC1->LI0S, 0xffff<< 16, (overlay_cfg.height) << 16); // height  
  461.         BITCSET (pLCDC1->LI0S, 0xffff<<  0, (overlay_cfg.width) <<   0); // width  
  462.           
  463.         tccxxx_overlay_fmt_set(overlay_fmt.fmt.pix.pixelformat);          
  464.     }  
  465.   
  466.     // image address  
  467.     curU_phyAddr = GET_ADDR_YUV42X_spU(curY_phyAddr, overlay_cfg.width, overlay_cfg.height);   
  468.     curV_phyAddr = GET_ADDR_YUV420_spV(curU_phyAddr, overlay_cfg.width, overlay_cfg.height);  
  469.       
  470.     BITCSET (pLCDC1->LI0BA0, 0xFFFFFFFF,  curY_phyAddr); // address0  
  471.     BITCSET (pLCDC1->LI0BA1, 0xFFFFFFFF,  curU_phyAddr); // address1   
  472.     BITCSET (pLCDC1->LI0BA2, 0xFFFFFFFF,  curV_phyAddr); // address2  
  473.   
  474.     if(!start_en)  
  475.     {  
  476.         tccxxx_overlay_common_enable();  
  477.         tccxxx_overlay_fmt_set(overlay_fmt.fmt.pix.pixelformat);  
  478.         BITCLR (pLCDC1->LI0C, HwLIC_INTL);                // not interlace format  
  479.         BITSET(pLCDC1->LCTRL, Hw0);    
  480.         start_en = 1;  
  481.     }  
  482.       
  483.     if(!(pLCDC1->LI0C & Hw28)){  
  484.         BITCSET (pLCDC1->LI0C, 0x1<<28,    (1)  << 28); // Enable Image  
  485.     }  
  486.   
  487.     tccxxx_overlay_check_priority();  
  488. #if !defined(CONFIG_ARCH_TCC92XX)  
  489.     BITCSET (pLCDC1->LI0C, HwLCT_RU, HwLCT_RU); //Image update  
  490. #endif  
  491.     return 0;  
  492. }  
  493.   
  494.   
  495. static int tccxxx_overlay_disable(void)  
  496. {  
  497.     BITSCLR (pLCDC1->LI0C, 0x1<<28,    (1)  << 28); // Disable Image  
  498.   
  499. #if !defined(CONFIG_ARCH_TCC92XX)  
  500.     BITCSET (pLCDC1->LI0C, HwLCT_RU, HwLCT_RU); //Image update  
  501. #endif  
  502.   
  503.     wait_restart = 1;  
  504.   
  505.     return 0;  
  506. }  
  507.   
  508.   
  509. static int tccxxx_overlay_set_pos(overlay_config_t * arg )  
  510. {  
  511.     struct lcd_panel *panel = tccfb_get_panel();  
  512.     unsigned int screen_width, screen_height;  
  513.   
  514.     overlay_config_t pos;  
  515.   
  516.       
  517.     if(copy_from_user(&pos, (overlay_config_t *)arg, sizeof(overlay_config_t)))  
  518.         return -EFAULT;  
  519.   
  520.     if(!start_en)  
  521.     {  
  522.         BITSCLR (pLCDC1->LI0C, 0x1<<28,    (1)  << 28); // Disable Image  
  523.         wait_restart = 1;  
  524.     }  
  525.   
  526.     overlay_cfg.sx      =   pos.sx;       
  527.     overlay_cfg.sy      =   pos.sy;       
  528.     overlay_cfg.width   =   pos.width;  
  529.   
  530.     if(overlay_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 || overlay_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)  
  531.         overlay_cfg.width   =   ((overlay_cfg.width+3) >> 2)<<2;  
  532.     else  
  533.         overlay_cfg.width   =   ((overlay_cfg.width+15) >> 4)<<4;  
  534.       
  535.     overlay_cfg.height  =   pos.height;  
  536.   
  537.     screen_width      = panel->xres;  
  538.     screen_height     = panel->yres;  
  539. #if defined(CONFIG_TCC_HDMI_UI_SIZE_1280_720)  
  540.     if(tcc_display_data.resolution == 1)  
  541.     {  
  542.         screen_width      = 720;  
  543.         screen_height     = 576;  
  544.     }  
  545.     else if(tcc_display_data.resolution == 2)  
  546.     {  
  547.         screen_width      = 800;  
  548.         screen_height     = 480;  
  549.     }  
  550. #endif  
  551.   
  552.     if(overlay_cfg.sx + overlay_cfg.width > screen_width)  
  553.     {  
  554.         if(overlay_cfg.width > screen_width)  
  555.         {  
  556.             overlay_cfg.sx = 0;  
  557.             overlay_cfg.width = screen_width;  
  558.         }  
  559.         else  
  560.         {         
  561.             overlay_cfg.sx = (screen_width - overlay_cfg.width)/2;            
  562.         }  
  563.     }  
  564.   
  565.     if(overlay_cfg.sy + overlay_cfg.height > screen_height)  
  566.     {  
  567.         if(overlay_cfg.height > screen_height)  
  568.         {  
  569.             overlay_cfg.sy = 0;  
  570.             overlay_cfg.height = screen_height;  
  571.         }  
  572.         else  
  573.         {         
  574.             overlay_cfg.sy = (screen_height - overlay_cfg.height)/2;              
  575.         }  
  576.     }  
  577.       
  578.     dprintk(" Overlay -> Set Position adjust :: (%d,%d) | (%d,%d) \n", overlay_cfg.sx, overlay_cfg.sy, overlay_cfg.width, overlay_cfg.height);  
  579.   
  580.     //in case position reset in streamming.  
  581.     if(start_en)  
  582.     {  
  583.         pos_reset = 1;  
  584.         return 0;  
  585.     }  
  586.   
  587.     // position  
  588.     BITCSET (pLCDC1->LI0P, 0xffff<< 16, (overlay_cfg.sy)  << 16); // position y  
  589.     BITCSET (pLCDC1->LI0P, 0xffff<<  0, (overlay_cfg.sx)  <<  0); // position x  
  590.   
  591.     // size  
  592.     BITCSET (pLCDC1->LI0S, 0xffff<< 16, (overlay_cfg.height) << 16); // height  
  593.     BITCSET (pLCDC1->LI0S, 0xffff<<  0, (overlay_cfg.width) <<  0); // width  
  594.   
  595.     tccxxx_overlay_fmt_set(overlay_fmt.fmt.pix.pixelformat);  
  596.   
  597. #if !defined(CONFIG_ARCH_TCC92XX)  
  598.     BITCSET (pLCDC1->LI0C, HwLCT_RU, HwLCT_RU); //Image update  
  599. #endif  
  600.   
  601.     return 0;  
  602. }  
  603.   
  604. static int tccxxx_overlay_set_configure(overlay_config_t* arg)  
  605. {  
  606.     unsigned int screen_width, screen_height;  
  607.     struct lcd_panel *panel = tccfb_get_panel();  
  608.     overlay_config_t config;  
  609.   
  610.     if(copy_from_user(&config, (overlay_config_t *)arg, sizeof(overlay_config_t)))  
  611.         return -EFAULT;  
  612.   
  613.     overlay_fmt.fmt.pix.width       = config.width;  
  614.     overlay_fmt.fmt.pix.height      = config.height ;  
  615.     overlay_fmt.fmt.pix.pixelformat = config.format;  
  616.     dprintk(" Overlay -> S_FMT :: size(%d,%d), format = 0x%x(RGB565-0x%x, YUV420-0x%x, YUV420inter-0x%x) \n", overlay_fmt.fmt.pix.width, overlay_fmt.fmt.pix.height, overlay_fmt.fmt.pix.pixelformat, V4L2_PIX_FMT_RGB565,V4L2_PIX_FMT_YVU420, V4L2_PIX_FMT_NV12);  
  617.   
  618.     overlay_cfg.sx      =   config.sx;    
  619.     overlay_cfg.sy      =   config.sy;        
  620.     overlay_cfg.width   =   overlay_fmt.fmt.pix.width;    
  621.     if(overlay_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 || overlay_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)  
  622.         overlay_cfg.width   =   ((overlay_cfg.width+3) >> 2)<<2;  
  623.     else  
  624.         overlay_cfg.width   =   ((overlay_cfg.width+15) >> 4)<<4;  
  625.     overlay_cfg.height  =   overlay_fmt.fmt.pix.height;  
  626.   
  627.     screen_width      = panel->xres;  
  628.     screen_height     = panel->yres;  
  629. #if defined(CONFIG_TCC_HDMI_UI_SIZE_1280_720)  
  630.     if(tcc_display_data.resolution == 1)  
  631.     {  
  632.         screen_width      = 720;  
  633.         screen_height     = 576;  
  634.     }  
  635.     else if(tcc_display_data.resolution == 2)  
  636.     {  
  637.         screen_width      = 800;  
  638.         screen_height     = 480;  
  639.     }  
  640. #endif  
  641.   
  642.     if(overlay_cfg.sx + overlay_cfg.width > screen_width)  
  643.     {  
  644.         if(overlay_cfg.width > screen_width)  
  645.         {  
  646.             overlay_cfg.sx = 0;  
  647.             overlay_cfg.width = screen_width;  
  648.         }  
  649.         else  
  650.         {         
  651.             overlay_cfg.sx = (screen_width - overlay_cfg.width)/2;            
  652.         }  
  653.     }  
  654.   
  655.     if(overlay_cfg.sy + overlay_cfg.height > screen_height)  
  656.     {  
  657.         if(overlay_cfg.height > screen_height)  
  658.         {  
  659.             overlay_cfg.sy = 0;  
  660.             overlay_cfg.height = screen_height;  
  661.         }  
  662.         else  
  663.         {         
  664.             overlay_cfg.sy = (screen_height - overlay_cfg.height)/2;              
  665.         }  
  666.     }  
  667.   
  668.     dprintk(" Overlay -> S_FMT :: Real => size(%d,%d ~ %d,%d) \n", overlay_cfg.sx, overlay_cfg.sy, overlay_cfg.width, overlay_cfg.height);  
  669.   
  670.     // position  
  671.     BITCSET (pLCDC1->LI0P, 0xffff<< 16, (overlay_cfg.sy)  << 16); // position y  
  672.     BITCSET (pLCDC1->LI0P, 0xffff<<  0, (overlay_cfg.sx)  <<  0); // position x  
  673.   
  674.     // size  
  675.     BITCSET (pLCDC1->LI0S, 0xffff<< 16, (overlay_cfg.height) << 16); // height  
  676.     BITCSET (pLCDC1->LI0S, 0xffff<<  0, (overlay_cfg.width) <<  0); // width  
  677.   
  678.   
  679.     tccxxx_overlay_fmt_set(overlay_fmt.fmt.pix.pixelformat);  
  680.   
  681.     BITCLR(pLCDC1->LI0C, HwLIC_SRC);  
  682.   
  683. #if !defined(CONFIG_ARCH_TCC92XX)  
  684.     BITCSET (pLCDC1->LI0C, HwLCT_RU, HwLCT_RU); //Image update  
  685. #endif  
  686.   
  687.     return 0;  
  688. }  
  689.   
  690. static int overlay_forbid;  
  691. static int tccxxx_overlay_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)  
  692. {  
  693.     int intArg;  
  694.   
  695. #if 0  
  696.     if(Output_SelectMode != OUTPUT_SELECT_NONE)  
  697.         return 0;  
  698.     //if(overlay_forbid && (cmd != OVERLAY_FORBID))  
  699.     //  return 0;  
  700. #endif//  
  701.   
  702.     switch(cmd)  
  703.     {  
  704.         case OVERLAY_FORBID:  
  705.             if(copy_from_user(&intArg, (int *)arg, sizeof(int)))  
  706.                 return -EFAULT;  
  707.             overlay_forbid = intArg;  
  708.             return 0;  
  709.   
  710.         case OVERLAY_GET_POSITION:  
  711.             return tccxxx_overlay_get_pos((overlay_config_t*)arg);  
  712.   
  713.         case OVERLAY_GET_SCREEN_INFO:  
  714.             return tccxxx_overlay_get_screenInfo((overlay_config_t*)arg);  
  715.   
  716.         case OVERLAY_SET_POSITION:  
  717.             return tccxxx_overlay_set_pos((overlay_config_t*)arg);  
  718.   
  719.         case OVERLAY_QUEUE_BUFFER:  
  720.             return tccxxx_overlay_q_buffer((unsigned int*)arg);  
  721.   
  722.         case OVERLAY_SET_CONFIGURE:  
  723.             return tccxxx_overlay_set_configure((overlay_config_t*)arg);  
  724.   
  725.         case OVERLAY_SET_DISABLE:  
  726.             return tccxxx_overlay_disable();  
  727.   
  728.   
  729.         default:  
  730.             dprintk(" Unsupported IOCTL(%d)!!!\n", cmd);        
  731.             break;            
  732.         }  
  733.   
  734.         return 0;  
  735.     }  
  736.   
  737. static int tccxxx_overlay_release(struct inode *inode, struct file *file)  
  738. {  
  739.     start_en = 0;  
  740.     wait_restart = 0;  
  741.     tcc_overlay_use--;  
  742.     dprintk(" ===========> tccxxx_overlay_release num:%d \n", tcc_overlay_use);  
  743.   
  744.     tccxxx_overlay_common_disable(0);  
  745.   
  746.     clk_disable(overlay_lcdc_clk);  
  747.   
  748.     return 0;  
  749. }  
  750.   
  751. static int tccxxx_overlay_open(struct inode *inode, struct file *file)  
  752. {  
  753.     tcc_overlay_use++;  
  754.     clk_enable(overlay_lcdc_clk);  
  755.   
  756.     if(tcc_overlay_use > 1)  
  757.     {  
  758.         start_en = 0;  
  759.         wait_restart = 0;  
  760.         tcc_overlay_use--;  
  761.         dprintk(" ===========> forced close num:%d \n", tcc_overlay_use);  
  762.   
  763.         tccxxx_overlay_common_disable(0);  
  764.         clk_disable(overlay_lcdc_clk);  
  765.     }  
  766.   
  767.     dprintk(" ===========> tccxxx_overlay_open num:%d \n", tcc_overlay_use);  
  768.   
  769.     return 0;     
  770. }  
  771.   
  772. static struct file_operations tcc_overlay_fops =   
  773. {  
  774.     .owner          = THIS_MODULE,  
  775.     .poll           = tccxxx_overlay_poll,  
  776.     .ioctl          = tccxxx_overlay_ioctl,  
  777.     .mmap           = tccxxx_overlay_mmap,  
  778.     .open           = tccxxx_overlay_open,  
  779.     .release        = tccxxx_overlay_release,  
  780. };  
  781.   
  782. #ifdef PLATFORM_DEVICE  
  783. static struct miscdevice overlay_misc_device =  
  784. {  
  785.     DEV_MINOR,  
  786.     DEVICE_NAME,  
  787.     &tcc_overlay_fops,  
  788. };  
  789.   
  790. static int __init tcc_overlay_probe(struct platform_device *pdev)  
  791. {  
  792.     overlay_lcdc_clk = clk_get(0, "lcdc1");  
  793.     BUG_ON(overlay_lcdc_clk == NULL);  
  794.   
  795.     pLCDC1 = (volatile PLCDC)tcc_p2v(HwLCDC1_BASE);  
  796. #ifdef CONFIG_ARCH_TCC92XX  
  797.     pLCDC1_CH0 = (volatile PLCDC_CHANNEL)tcc_p2v(pLCDC1->LI0C);  
  798. #else  
  799.     pLCDC1_CH0 = (volatile PLCDC_CHANNEL)tcc_p2v(HwLCDC1_CH_BASE(0));  
  800. #endif//  
  801.   
  802.     if (misc_register(&overlay_misc_device))  
  803.     {  
  804.         dprintk(KERN_WARNING "OVERLAY: Couldn't register device %d.\n", DEV_MINOR);  
  805.         return -EBUSY;  
  806.     }  
  807.   
  808.     return 0;  
  809. }  
  810.   
  811. static int tcc_overlay_remove(struct platform_device *pdev)  
  812. {  
  813.     misc_deregister(&overlay_misc_device);  
  814.   
  815.     return 0;  
  816. }  
  817.   
  818. #ifdef CONFIG_PM  
  819. static volatile LCDC_CHANNEL LCDC1_CH0_BackUp;  
  820.   
  821. static int tcc_overlay_suspend(struct platform_device *pdev, pm_message_t state)  
  822. {  
  823.     if(tcc_overlay_use != 0)  
  824.     {     
  825.         printk("tcc_overlay_suspend %d opened\n", tcc_overlay_use);  
  826.   
  827.         LCDC1_CH0_BackUp = *pLCDC1_CH0;  
  828.           
  829.         clk_disable(overlay_lcdc_clk);  
  830.     }  
  831.       
  832.     return 0;  
  833. }  
  834.   
  835. static int tcc_overlay_resume(struct platform_device *pdev)  
  836. {  
  837.     if(tcc_overlay_use != 0)  
  838.     {     
  839.         printk("tcc_overlay_resume %d opened\n", tcc_overlay_use);  
  840.           
  841.         clk_enable(overlay_lcdc_clk);  
  842.   
  843.         *pLCDC1_CH0 = LCDC1_CH0_BackUp;  
  844.     }  
  845.       
  846.     return 0;  
  847. }  
  848.   
  849. #else //CONFIG_PM  
  850. #define tcc_overlay_suspend NULL  
  851. #define tcc_overlay_resume NULL  
  852. #endif //CONFIG_PM  
  853.   
  854. static struct platform_device tcc_overlay_device = {  
  855.     .name   = "tcc_overlay",  
  856.     .dev    = {  
  857.         .release    = NULL,  
  858.     },  
  859.     .id = 0,  
  860. };  
  861.   
  862. static struct platform_driver tcc_overlay_driver = {  
  863.     .driver         = {  
  864.          .name   = "tcc_overlay",  
  865.          .owner  = THIS_MODULE,  
  866.     },  
  867.     .probe          = tcc_overlay_probe,  
  868.     .remove         = tcc_overlay_remove,  
  869.     .suspend        = tcc_overlay_suspend,  
  870.     .resume         = tcc_overlay_resume,  
  871. };  
  872. #endif  
  873.   
  874.   
  875. static void __exit  
  876. tccxxx_overlay_cleanup(void)  
  877. {  
  878. #ifdef PLATFORM_DEVICE  
  879.     platform_driver_unregister(&tcc_overlay_driver);  
  880.     platform_device_unregister(&tcc_overlay_device);  
  881. #else  
  882.     unregister_chrdev(MAJOR_ID, DEVICE_NAME);  
  883. #endif  
  884.   
  885.     dprintk(" ===========> tccxxx_overlay_cleanup \n");  
  886.       
  887.     return;  
  888. }  
  889.   
  890. static char banner[] __initdata = KERN_INFO "TCC Overlay driver initializing\n";  
  891.   
  892. #ifndef PLATFORM_DEVICE  
  893. static struct class *overlay_class;  
  894. #endif  
  895.   
  896. static int __init   
  897. tccxxx_overlay_init(void)  
  898. {  
  899.     printk(banner);  
  900.   
  901. #ifdef PLATFORM_DEVICE  
  902.     platform_device_register(&tcc_overlay_device);  
  903.     platform_driver_register(&tcc_overlay_driver);  
  904. #else  
  905.     register_chrdev(MAJOR_ID, DEVICE_NAME, &tcc_overlay_fops);  
  906.   
  907.     overlay_class = class_create(THIS_MODULE, DEVICE_NAME);  
  908.     device_create(overlay_class,NULL,MKDEV(MAJOR_ID,MINOR_ID),NULL,DEVICE_NAME);  
  909.   
  910.     overlay_lcdc_clk = clk_get(0, "lcdc1");  
  911.     BUG_ON(overlay_lcdc_clk == NULL);  
  912.     pLCDC1  = (volatile PLCDC)tcc_p2v(HwLCDC1_BASE);      
  913. #endif  
  914.   
  915.     return 0;  
  916. }  
  917.   
  918.   
  919. MODULE_AUTHOR("Telechips.");  
  920. MODULE_DESCRIPTION("TCC Video for Linux overlay driver");  
  921. MODULE_LICENSE("GPL");  
  922.   
  923.   
  924. module_init(tccxxx_overlay_init);  
  925. module_exit(tccxxx_overlay_cleanup);  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值