zoukankan      html  css  js  c++  java
  • 代码示例_LCD控制


      1 #include <linux/module.h>
      2 #include <linux/kernel.h>
      3 #include <linux/errno.h>
      4 #include <linux/string.h>
      5 #include <linux/mm.h>
      6 #include <linux/slab.h>
      7 #include <linux/delay.h>
      8 #include <linux/fb.h>
      9 #include <linux/init.h>
     10 #include <linux/dma-mapping.h>
     11 #include <linux/interrupt.h>
     12 #include <linux/workqueue.h>
     13 #include <linux/wait.h>
     14 #include <linux/platform_device.h>
     15 #include <linux/clk.h> 
     16 #include <asm/io.h>
     17 #include <asm/uaccess.h>
     18 #include <asm/div64.h> 
     19 #include <asm/mach/map.h>
     20 #include <asm/types.h>
     21 
     22 #define LCD_BASE 0x11400000
     23 #define LCD_F0 (LCD_BASE+0x0180)
     24 #define LCD_F1 (LCD_BASE+0x01A0)
     25 #define LCD_F2 (LCD_BASE+0x01C0)
     26 #define LCD_F3 (LCD_BASE+0x01E0)
     27 #define LCD_PWM (LCD_BASE+0x00A0)
     28 #define LCD_PWM_BASE 0x139D0000
     29 #define LCD_PWM_TCFG0 (LCD_PWM_BASE+0x0000)
     30 #define LCD_PWM_TCFG1 (LCD_PWM_BASE+0x0004)
     31 #define LCD_PWM_TCON  (LCD_PWM_BASE+0x0008)
     32 #define LCD_PWM_TCNTB1 (LCD_PWM_BASE+0x0018)
     33 #define LCD_PWM_TCMPB1 (LCD_PWM_BASE+0x001C)
     34 
     35 #define BLK_FLAG 1
     36 
     37  //模块信息
     38 
     39  MODULE_LICENSE("Dual BSD/GPL");
     40 
     41 
     42 
     43 static struct fb_info * my_fbInfo = NULL;
     44 static int myLcdBpp = 32;//位深
     45 static short myPaletteSize = 256; //调色板大小
     46 static unsigned int myXvSize = 1024; //缓冲列大小
     47 static unsigned int myYvSize = 768; //缓冲行大小
     48 static unsigned int pseudo_palette [16];//调色板数组,被fb_info->pseudo_palette调用
     49 
     50 //IO管脚寄存器
     51 static unsigned int * __iomem gpf0con;
     52 static unsigned int * __iomem gpf1con;
     53 static unsigned int * __iomem gpf2con;
     54 static unsigned int * __iomem gpf3con;
     55 static unsigned int * __iomem gpd0con;//pwm控制
     56 static unsigned int * __iomem gpd0dat;
     57 
     58 //pwm寄存器
     59 static unsigned int * __iomem tcfg0;
     60 static unsigned int * __iomem tcfg1;
     61 static unsigned int * __iomem tcon;
     62 static unsigned int * __iomem tcntb1;
     63 static unsigned int * __iomem tcmpb1;
     64 
     65 //时钟相关寄存器
     66 static unsigned int * __iomem clk_div_lcd;//lcd时钟分频
     67 static unsigned int * __iomem clk_src_lcd0;//lcd时钟源
     68 static unsigned int * __iomem lcdblk_cfg;//显示控制寄存器
     69 static unsigned int * __iomem lcdblk_cfg2;//显示控制寄存器
     70 
     71 //lcd寄存器
     72 static unsigned int * __iomem vidcon0;//Configures video output format and displays enable/disable.
     73 static unsigned int * __iomem vidcon1;//Specifies RGB I/F control signal
     74 static unsigned int * __iomem vidcon2;//Specifies output data format control.
     75 static unsigned int * __iomem vidtcon0;//Configures video output timing and determines the size of display
     76 static unsigned int * __iomem vidtcon1;//Configures video output timing and determines the size of display
     77 static unsigned int * __iomem vidtcon2;//Configures video output timing and determines the size of display
     78 static unsigned int * __iomem wincon0;//Specifies window0 feature setting
     79 static unsigned int * __iomem vidoso0a;//Specifies window position setting
     80 static unsigned int * __iomem vidoso0b;//Specifies window position setting
     81 static unsigned int * __iomem vidoso0c;//Specifies On Screen Display (OSD) size setting.
     82 static unsigned int * __iomem shaadowcon;//Specifies shadow control register
     83 static unsigned int * __iomem winchmap2;//Specifies window color control
     84 static unsigned int * __iomem vidw00add0b0;//Specifies source image address setting
     85 static unsigned int * __iomem vidw00add1b0;//Specifies source image address setting
     86 static unsigned int * __iomem win0map;//Specifies window color control
     87 static unsigned int * __iomem vidw00add2;//Specifies source image address setting
     88 
     89 ////static T_LCD_REG * __iomem lcdBase;
     90 /* from pxafb.c */
     91 /*
     92 struct fb_bitfield {  //fb缓存的RGB位域,该结构描述每一个像素显示缓冲区的组织方式,
     93                     //假如为RGB565模式,R占5位=bit[11:15]G占6位=bit[10:5] B占5位=bit[4:0]
     94   __u32 offset;     // beginning of bitfield 位域偏移:red=11 ,green=5 blue=0
     95   __u32 length;   // length of bitfield  位域长度 red=5 green=6 blue=5 
     96   __u32 msb_right;//!= 0 : Most significant bit is */  /*msb_right!=0=>MSB在右边 
     97  }; 
     98  
     99 */ 
    100 
    101 static inline unsigned int chan_to_field(unsigned int chan,struct fb_bitfield *bf)
    102 {    
    103     /*内核中的单色都是16位,默认从左到右排列,比如G颜色[0x1f],那么chan就等于0XF800*/
    104     chan&= 0xffff;
    105     chan >>= 16 - bf->length;//右移,将数据靠到位0上
    106     return chan << bf->offset;//左移一定偏移值,放入16色数据中对应的位置
    107 }
    108 
    109 ////设置调色板函数,供内核调用
    110 static int my_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, unsigned int transp, struct fb_info *info)
    111 {
    112     unsigned int val = 0;
    113     //用red,green,blue三个颜色值构造出16色数据val
    114     switch(info->fix.visual){
    115            case FB_VISUAL_TRUECOLOR: //true-color,use pseudo_palette
    116                         if(regno < 16){
    117                                 u32 *pal = info-> pseudo_palette;
    118                                 val  = chan_to_field(red,&info->var.red);
    119                                 val |= chan_to_field(green,&info->var.green);
    120                                 val |= chan_to_field(blue,&info->var.blue);
    121                                 pal[regno] = val;
    122                         }
    123                         break;
    124            default :
    125                     return 1; // 未知类型
    126     }
    127 
    128     return 0;
    129 
    130 }
    131 
    132 static struct fb_ops my_fb_ops = {
    133             .owner = THIS_MODULE,
    134             .fb_setcolreg = my_fb_setcolreg,//调用my_lcdfb_setcolreg()函数,来设置调色板fb_info-> pseudo_palette
    135             .fb_fillrect = cfb_fillrect,//填充矩形
    136             .fb_copyarea = cfb_copyarea,//复制数据
    137             .fb_imageblit = cfb_imageblit,//绘画图形
    138 };
    139 
    140 //设置可变参数
    141 static int fb_fill_var(struct fb_info *myfb)
    142 {
    143     myfb->var.activate = FB_ACTIVATE_NOW;
    144     myfb->var.vmode = FB_VMODE_NONINTERLACED;
    145     myfb->var.bits_per_pixel = myLcdBpp;/*每个像素的位数即BPP,比如:RGB565则填入16*/
    146     myfb->var.xres_virtual = myXvSize;/*虚拟屏幕一行有多少个像素点 */
    147     myfb->var.yres_virtual = myYvSize;/*虚拟屏幕一列有多少个像素点*/
    148     myfb->var.xres = myXvSize;/*可见屏幕一行有多少个像素点*/
    149     myfb->var.yres = myYvSize;/*可见屏幕一列有多少个像素点*/
    150     myfb->var.xoffset = 0;/*虚拟到可见屏幕之间的行偏移,若可见和虚拟的分辨率一样,就直接设为0*/
    151     myfb->var.yoffset = 0;/*虚拟到可见屏幕之间的列偏移*/
    152 
    153     //保持透明度参数为0
    154     myfb->var.transp.offset = 0;
    155     myfb->var.transp.length = 0;
    156     switch(myfb->var.bits_per_pixel){
    157             case 1:
    158             case 2:
    159             case 4:
    160             case 8:
    161                 /* non palletised, A:1,R:2,G:3,B:2 mode */
    162                 myfb->var.red.offset = 5;
    163                 myfb->var.green.offset = 2;
    164                 myfb->var.blue.offset = 0;
    165                 myfb->var.red.length = 2;
    166                 myfb->var.green.length = 3;
    167                 myfb->var.blue.length = 2;
    168                 myfb->var.transp.offset = 7;
    169                 myfb->var.transp.length = 1;
    170                 break;
    171             case 19:
    172                 /* 666 with one bit alpha/transparency */
    173                 myfb->var.transp.offset = 18;
    174                 myfb->var.transp.length = 1;
    175                 /* drop through */
    176             case 18:
    177                 myfb->var.bits_per_pixel = 32;
    178                 /* 666 format */
    179                 myfb->var.red.offset = 12;
    180                 myfb->var.green.offset = 6;
    181                 myfb->var.blue.offset = 0;
    182                 myfb->var.red.length = 6;
    183                 myfb->var.green.length = 6;
    184                 myfb->var.blue.length = 6;
    185                 break;
    186             case 16:
    187                 /* 16 bpp, 565 format */
    188                 myfb->var.red.offset = 11;
    189                 myfb->var.green.offset = 5;
    190                 myfb->var.blue.offset = 0;
    191                 myfb->var.red.length = 5;
    192                 myfb->var.green.length = 6;
    193                 myfb->var.blue.length = 5;
    194                 break;
    195             case 32:
    196             case 28:
    197             case 25:
    198                 myfb->var.transp.length = myfb-> var.bits_per_pixel - 24;
    199                 myfb->var.transp.offset = 24;
    200                 /* drop through */
    201             case 24:
    202                 /* our 24bpp is unpacked, so 32bpp */
    203                 myfb->var.bits_per_pixel = 32;
    204                 myfb->var.red.offset = 16;
    205                 myfb->var.red.length = 8;
    206                 myfb->var.green.offset = 8;
    207                 myfb->var.green.length = 8;
    208                 myfb->var.blue.offset = 0;
    209                 myfb->var.blue.length = 8;
    210                 break;
    211             default:
    212                 printk("invalid bpp
    ");
    213                 return -EINVAL;
    214     }
    215     return 0;
    216 }
    217 
    218 //设置固定参数
    219 static int fb_fill_fix(struct fb_info *myfb)
    220 {
    221     unsigned int real_size,virt_size,size;
    222     dma_addr_t map_dma;
    223     strcpy(myfb->fix.id,"mylcd");
    224     myfb->fix.type = FB_TYPE_PACKED_PIXELS; //在该方式下,像素值与内存直接对应
    225     myfb->fix.accel = FB_ACCEL_NONE;
    226     myfb->fix.line_length =(myfb->var.xres_virtual * myfb->var.bits_per_pixel)/8;//一行的大小(字节数)
    227     myfb->fix.xpanstep = myfb->var.xres_virtual> myfb->var.xres?1:0;/*如果没有硬件panning就赋值为0 */
    228     myfb->fix.ypanstep = myfb->var.yres_virtual> myfb->var.yres?1:0;/*如果没有硬件panning就赋值为0 */
    229      //fix.visual画面设置,常用参数如下
    230     // FB_VISUAL_MONO01             0   单色,0:白色,1:黑色
    231     // FB_VISUAL_MONO10             1    单色,1:白色,0:黑色
    232     // FB_VISUAL_TRUECOLOR          2     真彩(TFT:真彩)
    233     // FB_VISUAL_PSEUDOCOLOR        3     伪彩
    234     // FB_VISUAL_DIRECTCOLOR        4     直彩
    235     switch(myfb->var.bits_per_pixel){
    236         case 32:
    237         case 24:
    238         case 16:
    239         case 12:
    240             myfb->fix.visual = FB_VISUAL_TRUECOLOR;
    241             break;
    242         case 8:
    243             if(myPaletteSize >= 256)
    244                 myfb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
    245             else
    246                 myfb->fix.visual = FB_VISUAL_TRUECOLOR;
    247             break;
    248         case 1:
    249             myfb->fix.visual = FB_VISUAL_MONO01;
    250             break;
    251         default:
    252             myfb->fix.visual = FB_VISUAL_TRUECOLOR;
    253             break;
    254     }
    255 
    256      /*计算整体缓冲大小*/
    257     real_size = myfb->var.xres * myfb->var.yres;
    258     virt_size = myfb->var.xres_virtual * myfb->var.yres_virtual;
    259     size =(real_size > virt_size)?real_size:virt_size;
    260     size *=(myfb->var.bits_per_pixel > 16)?32:myLcdBpp;
    261 
    262     size /= 8;
    263     myfb->fix.smem_len = size;//framebuffer长度,字节为单位
    264     size = PAGE_ALIGN(size);
    265     //显存虚拟起始地址,把地址告诉LCD控制器和fb_info
    266     //void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);  //分配DMA缓存区给显存
    267     //返回值为:申请到的DMA缓冲区的虚拟地址,若为NULL,表示分配失败,则需要使用dma_free_writecombine()释放内存,避免内存泄漏
    268     //参数如下: 
    269     //*dev:指针,这里填0,表示这个申请的缓冲区里没有内容
    270     //size:分配的地址大小(字节单位)
    271     //*handle:申请到的物理起始地址
    272     //gfp:分配出来的内存参数,标志定义在<linux/gfp.h>,常用标志如下:
    273     //GFP_ATOMIC    用来从中断处理和进程上下文之外的其他代码中分配内存. 从不睡眠.
    274     //GFP_KERNEL    内核内存的正常分配. 可能睡眠.
    275     //GFP_USER      用来为用户空间页来分配内存; 它可能睡眠. 
    276     myfb->screen_base = dma_alloc_writecombine(myfb->dev, size,&map_dma, GFP_KERNEL);
    277     if(!myfb->screen_base){
    278         return -ENOMEM;
    279     }
    280     memset(myfb->screen_base,0x0,size);
    281     myfb->fix.smem_start = map_dma;
    282     return 0;
    283 }
    284 
    285 static void myfb_Init(struct fb_info *myfb)
    286 {
    287     /*varinit*/
    288     fb_fill_var(myfb);
    289     /*fix init*/
    290     fb_fill_fix(myfb);
    291     /*ops init*/
    292     myfb->fbops =&my_fb_ops;
    293     /*ops init*/
    294     myfb->flags = FBINFO_FLAG_DEFAULT;
    295     myfb->pseudo_palette = pseudo_palette;//保存调色板数组
    296 }
    297 
    298 static void mygpio_Init(void)
    299 {
    300     gpf0con = ioremap(LCD_F0,4);
    301     gpf1con = ioremap(LCD_F1,4);
    302     gpf2con = ioremap(LCD_F2,4);
    303     gpf3con = ioremap(LCD_F3,4);
    304     writel(0x22222222,gpf0con);
    305     writel(0x22222222,gpf1con);
    306     writel(0x22222222,gpf2con);
    307     *gpf3con &=~(0xffff);
    308     writel(0x2222,gpf3con);
    309 
    310     //背光
    311     if(BLK_FLAG)//pwm方式
    312     {
    313         gpd0con = ioremap(LCD_PWM,4);
    314         writel((readl(gpd0con) & (~(0xf<<4))) | (0x2<<4) , gpd0con);
    315     }
    316     else //直接点亮方式
    317     {
    318         int val;
    319     //    unsigned int * __iomem gpd0con;
    320     //    unsigned int * __iomem gpd0dat;
    321     
    322         gpd0con = ioremap(0x114000A0,4);
    323         gpd0dat = ioremap(0x114000A4,4);
    324         
    325         val = readl(gpd0con);
    326         val &=~(0xf<<4);
    327         val |=(0x1<<4);
    328         writel(val,gpd0con);
    329         val = readl(gpd0dat);
    330         val|=(0x1<<1);
    331         writel(val,gpd0dat);
    332     }
    333 }
    334 
    335 static void myclk_Init(void)
    336 {
    337     clk_div_lcd = ioremap(0x1003c534,4);
    338     clk_src_lcd0 = ioremap(0x1003c234,4);
    339     lcdblk_cfg = ioremap(0x10010210,4);
    340     lcdblk_cfg2 = ioremap(0x10010214,4);
    341 
    342     /*时钟源选择MPLL具体参考<Exyons 4412 datasheet pg526>
    343     *CLK_DIV_LCD:
    344     *[3:0]:FIMD0_RATIO   0
    345     *SCLK_FIMD0 = MOUTFIMD0/(FIMD0_RATIO + 1)=800M/1 = 800M
    346 
    347     *<Exyons 4412 datasheet pg501>
    348     *CLK_SRC_LCD0:
    349     *[3:0]:FIMD0_SEL 0110 ===>0x6 SCLKmpll_user_t 选择时钟源为SCLKmpll_user_t
    350     */
    351     writel(readl(clk_div_lcd)&~0xf,clk_div_lcd);
    352     writel((readl(clk_src_lcd0)&~0xf)|0x6,clk_src_lcd0);
    353 
    354     /*<Exyons 4412 datasheet pg1767>
    355     *Using the display controller data, you can select one of the above data paths by
    356     *setting LCDBLK_CFG Register (0x1001_0210). For more information, refer to the "System Others" manual.
    357     *While using RGB interface, the VT_LBLKx bit fields in LCDBLKC_CFG (0x1001_0210) register should be set to
    358     *RGB Interface out (2'b00), even though you use DSI Video Mode.*/
    359 
    360     /*
    361     *<Exyons 4412 datasheet pg884>
    362     *LCDBLK_CFG:
    363     *           [1] : FIMD of LBLK0 Bypass Selection    1 : FIMD Bypass   使用FIMD接口
    364     *LCDBLK_CFG2:
    365     *            [0]:MIE0_DISPON     1 :  PWM outpupt enable 
    366     */
    367     writel((readl(lcdblk_cfg)&(~(0x3<<10)))|(1<<1),lcdblk_cfg);//set FIMD
    368   //writel(readl(lcdblk_cfg2)|(1<<0),lcdblk_cfg2); //set pwm
    369 
    370 }
    371 
    372 static void mypwm_Init(void)
    373 {
    374     tcfg0 = ioremap(LCD_PWM_TCFG0,4);
    375     tcfg1 = ioremap(LCD_PWM_TCFG1,4);
    376     tcon = ioremap(LCD_PWM_TCON,4);
    377     tcntb1 = ioremap(LCD_PWM_TCNTB1,4);
    378     tcmpb1 = ioremap(LCD_PWM_TCMPB1,4);
    379     
    380     /*占空比控制背光亮度*/
    381     writel((readl(tcfg0) &(~0xff))|0xff,tcfg0);
    382     writel((readl(tcfg1) &(~(0xf<<4)))|0x4<<4,tcfg1);
    383     writel(300,tcntb1);
    384     writel(150,tcmpb1);
    385     
    386     writel((readl(tcon)&(~(0xf<<8)))|(0x1<<9),tcon);
    387 
    388     //使能
    389     writel((readl(tcon)&(~(0x1<<9)))|(0x1<<8),tcon);
    390 
    391 }
    392 
    393 static int lcd_Init(struct fb_info *myfb)
    394 {
    395     unsigned int val;
    396     //lcd设置
    397     vidcon0 =ioremap(0x11c00000,0x4);
    398     vidcon1 =ioremap(0x11c00004,0x4);
    399     vidcon2 =ioremap(0x11c00008,0x4);
    400     vidtcon0 = ioremap(0x11c00010,0x4);
    401     vidtcon1 = ioremap(0x11c00014,0x4);
    402     vidtcon2 = ioremap(0x11c00018,0x4);
    403     win0map = ioremap(0x11C00180, 0x4);
    404     wincon0 = ioremap(0x11c00020, 0x4);
    405     vidoso0a = ioremap(0x11c00040,0x4);
    406     vidoso0b = ioremap(0x11c00044,0x4);
    407     vidoso0c = ioremap(0x11c00048,0x4);
    408     shaadowcon = ioremap(0x11c00034,0x4);
    409     winchmap2 =ioremap(0x11c0003c,0x4);
    410     vidw00add0b0 = ioremap(0x11c000a0,0x4);
    411     vidw00add1b0 = ioremap(0x11c000d0,0x4);
    412     vidw00add2 = ioremap(0x11C00104,0x4);
    413 
    414     /*HV mode fclk :44.9~63 推荐51.2Mhz 参考
    415     *vidcon0 [13-6] VCLK = FIMD*SCLK/(CLKVAL+1)
    416     *50M = 800M/(CLK_VAL+1) CLK_VAL= 15 这里为了取整,取50M
    417     *CLK_VAL为vidcon0 [13-6]这7位的十进制值,15为0001111,左移6位到[13-6],
    418     *注意并不是将13位转化为10进制,而是单独7位
    419     */
    420     //writel(15<<6, vidcon0);
    421     writel((15<<6|3), vidcon0);
    422     /*
    423     *:VSYNC,HSYNC高电平触发信号,VCLK上升沿开始传输数据
    424     *:VSD,HSD低电平触发信号,CLKV下降沿开始传输数据
    425     *
    426     * VIDCON1:
    427     * [5]:IVSYNC ===> 1 : Inverted(反转)
    428     * [6]:IHSYNC ===> 1 : Inverted(反转)
    429     * [7]:IVCLK ===> 1 : Fetches video data at VCLK rising edge (下降沿触发,反转?)
    430     * [10:9]:FIXVCLK ====> 01 : VCLK running�
    431     * */
    432     writel((1<<9)|(1<<7)|(1<<5)|(1<<6),vidcon1);
    433     //Reserved: This bit should be set to 1.
    434     writel(1<<14, vidcon2);
    435     
    436     /*参考 HV mode
    437     * thbp: 160 (DCLK)
    438     * thfp: 160 (DCLK)
    439     * thpw: 1-140 (DCLK)
    440     * tvpw: 1-20 (Th)
    441     * ttvbp: 23 (Th)
    442     * tvfp: 12 (Th)
    443     */
    444     /*
    445     *<Exyons 4412 datasheet pg1874 pg1848(时序)> <参考具体LCD屏参数(时序)>
    446     *VIDTCON0: 
    447     *         [23:16]:  VBPD + 1 <------> tvpw (1 - 20)    13
    448     *         [15:8]: VFPD + 1 <------> tvfp 22
    449     *         [7:0]: VSPW  + 1 <------> tvb - tvpw = 23 - 13 = 10
    450     **/
    451     /*VIDTCONx用来设置时序和长宽等参数,这里就主要设置VBPD(vertical back porch)、
    452      VFBD(vertical frontporch)、VSPW(vertical sync pulse width)、
    453     HBPD(horizontal backporch)、 HFPD(horizontal sync pul     se width)等参数
    454     */
    455     /*<Exyons 4412 datasheet pg1874 pg1848(时序)> <参考具体LCD屏参数(时序)>
    456      *VIDTCON1: 
    457      *       [23:16]:  HBPD + 1 <------> thpw (1 - 40)  36 
    458      *       [15:8]:   HFPD + 1 <------> thfp 210 
    459      *       [7:0]:    HSPW  + 1 <------> thb - thpw = 46 - 36 = 10
    460      */
    461 
    462 #define HSPW 31 //行同步
    463 #define HBPD 79
    464 #define HFPD 47
    465 #define VSPW 4 //帧同步
    466 #define VBPD 13
    467 #define VFPD 2
    468     writel(((VBPD <<16)|(VFPD <<8)|(VSPW <<0)),vidtcon0);
    469     writel(((HBPD <<16)|(HFPD <<8)|(HSPW <<0)),vidtcon1);
    470 
    471     /*设置大小,参考 Display Format Graphic 1024RGB*600 Dot-matrix
    472     * HOZVAL = (Horizontal display size) – 1 and LINEVAL = (Vertical display size) – 1.
    473     */
    474     writel(((1023<<0) | (599<<11)), vidtcon2);
    475 
    476     /*绑定win,这里直接使用了win0
    477     * TODO:0xd=32位,这里强行写的,具体需要参考实际情况写16,24或32
    478     */
    479     //writel((1<<6)|(0xD<<2)|1,wincon0);
    480     writel((1<<6)|(5<<2)|1,wincon0);
    481 
    482     /*LCD左上角坐标*/
    483     writel(0<<11|0, vidoso0a);
    484 
    485     /* LCD右下角坐标 参考
    486     * 24 BPP mode should have X position by 1 pixel. (For example, X = 0, 1, 2, 3….)
    487     * 16 BPP mode should have X position by 2 pixel. (For example, X = 0, 2, 4, 6….)
    488     * 8 BPP mode should have X position by 4 pixel. (For example, X = 0, 4, 8, 12….)
    489     */
    490     if(myLcdBpp == 16)
    491     {
    492         val = (((1023*2) <<11) | ((599*2) <<0));
    493     }
    494     else if((myLcdBpp == 24) || (myLcdBpp == 32))
    495     {
    496         val = (((1023) <<11) | ((599) <<0));
    497     }
    498     writel(val, vidoso0b);
    499 
    500     /*总大小*/
    501     writel(1024*600, vidoso0c);
    502 
    503     /*帧缓冲起始地址*/
    504     writel(myfb->fix.smem_start, vidw00add0b0);
    505 
    506     /*帧缓冲结束地址*/
    507     writel(myfb->fix.smem_start+myfb->fix.smem_len, vidw00add1b0);
    508 
    509     /*设置偏移和宽度*/
    510     writel((0<<13) | ((1024 * myLcdBpp / 8)<<0), vidw00add2);
    511 
    512     /*绑定通道和窗口*/
    513     writel(1, shaadowcon);
    514     writel((readl(winchmap2)&(~(0x7<<16))&(~0x7))|(1<<16)|(1<<0), winchmap2);
    515 
    516     /*Enables the video output and video control signal*/
    517     writel(readl(vidcon0)|0x3, vidcon0);
    518     return 0;
    519 }
    520 
    521 static int fs4412_lcd_init(void)
    522 {
    523     int ret = 0;
    524     /************************kernel相关*******************************/
    525     /**这部分参考s3c-fb.c**/
    526     /*申请fb_info*/
    527     my_fbInfo = framebuffer_alloc(0,NULL); //这里没有私有数据,所以是0;dev没有,平台驱动需要添加
    528 
    529     /*初始化fb_info*/
    530     myfb_Init(my_fbInfo);
    531     /************************硬件相关*******************************/
    532     /*管脚设置*/
    533     mygpio_Init();
    534     /*时钟设置*/
    535     myclk_Init();
    536     /*控制芯片设置*/
    537     mypwm_Init();
    538     lcd_Init(my_fbInfo);
    539 
    540 
    541     /*注册*/
    542     ret = register_framebuffer(my_fbInfo);
    543     if(0> ret){
    544         printk(KERN_ERR "failed to register framebuffer 
    ");
    545     //dma_free_coherent(fs_info->dev, fs_info->fix.smem_len,fs_info->screen_base, fs_info->fix.smem_start);
    546         return ret;
    547     }
    548     printk("Lcd init ok
    ");
    549     return 0;
    550 }
    551 
    552 
    553 static void fs4412_lcd_exit(void)
    554 {
    555     printk("Lcd exit
    ");
    556     unregister_framebuffer(my_fbInfo);
    557     iounmap(gpf0con);
    558     iounmap(gpf1con);
    559     iounmap(gpf2con);
    560     iounmap(gpf3con);
    561     //myfb->dev, size,&map_dma, GFP_KERNEL
    562 
    563     /*释放DMA缓存地址dma_free_writecombine()*/
    564     dma_free_writecombine(my_fbInfo->dev,my_fbInfo->screen_size,my_fbInfo->screen_base,my_fbInfo->fix.smem_start);
    565     framebuffer_release(my_fbInfo);
    566 }
    567 
    568 module_init(fs4412_lcd_init);
    569 module_exit(fs4412_lcd_exit);
      1 #include <unistd.h>
      2 #include <stdio.h>
      3 #include <fcntl.h>
      4 #include <linux/fb.h>
      5 #include <sys/mman.h>
      6 #include <errno.h>
      7 #include <stdlib.h>
      8 //#include "logo1.h"
      9 char *framebuffer_ptr;
     10 unsigned int xsize = 1024;
     11 unsigned int ysize = 600;
     12 unsigned int bpp = 16;
     13 void PutPixel(unsigned int x, unsigned int y, unsigned int color)
     14 {
     15     unsigned char red,green,blue;
     16     switch (bpp){
     17         case 16:
     18         {
     19             unsigned short *addr = (unsigned short *)framebuffer_ptr + (y * xsize + x);
     20             red   = (color >> 19) & 0x1f;
     21             green = (color >> 10) & 0x3f;
     22             blue  = (color >>  3) & 0x1f;
     23             color = (red << 11) | (green << 5) | blue; // 格式5:6:5
     24             *addr = (unsigned short) color;
     25             break;
     26         }
     27         
     28         case 8:
     29         {
     30             unsigned char *addr = (unsigned char *)framebuffer_ptr + (y * xsize + x);
     31             *addr = (unsigned char) color;
     32             break;
     33         }
     34 
     35         default:
     36             break;
     37     }
     38 }
     39 /* 
     40   * 绘制同心圆
     41   */
     42 void Mire(void)
     43 {
     44     unsigned long x,y;
     45     unsigned long color;
     46     unsigned char red,green,blue,alpha;
     47 
     48     for (y = 0; y < ysize; y++)
     49         for (x = 0; x < xsize; x++){
     50             color = ((x-xsize/2)*(x-xsize/2) + (y-ysize/2)*(y-ysize/2))/64;
     51             red   = (color/8) % 256;
     52             green = (color/4) % 256;
     53             blue  = (color/2) % 256;
     54             alpha = (color*2) % 256;
     55 
     56             color |= ((unsigned long)alpha << 24);
     57             color |= ((unsigned long)red   << 16);
     58             color |= ((unsigned long)green << 8 );
     59             color |= ((unsigned long)blue       );
     60 
     61             PutPixel(x,y,color);
     62         }
     63 }
     64 /* 
     65  * 将屏幕清成单色
     66  * 输入参数:
     67  *     color: 颜色值
     68  *         对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
     69  *     需要转换为5:6:5格式
     70  *         对于8BPP: color为调色板中的索引值,
     71  *     其颜色取决于调色板中的数值
     72  */
     73 void ClearScr(unsigned int color)
     74 {   
     75     unsigned long x,y;
     76     
     77     for (y = 0; y < ysize; y++)
     78         for (x = 0; x < xsize; x++)
     79             PutPixel(x, y, color);
     80 }
     81 int bmp2fb16_rgb565(unsigned char *bmpdata,unsigned short *fb16)
     82 {
     83     int x, y;
     84     unsigned short r, g, b;
     85     unsigned short pixel16;
     86     unsigned short * fb16_buff;
     87 
     88     fb16_buff = fb16;
     89     for(y = ysize-1; y >= 0 ; y--)
     90     {
     91         for (x = 0 ; x < xsize; x++) /*copy one line to frame buffer*/
     92         {    
     93             /*copy one pixel to frame buffer*/
     94             b = *bmpdata;
     95             bmpdata++;
     96             b >>= 3;
     97             g = *bmpdata;
     98             bmpdata++;
     99             g >>= 2;
    100             r = *bmpdata;
    101             bmpdata++;
    102             r >>= 3;
    103             pixel16 = (unsigned short)((r << 11) | (g << 5) | b);    
    104             *(fb16_buff + (y* xsize + x)) = pixel16;
    105         }
    106     }
    107     return 0;
    108 }
    109 
    110 int bmp_read_file(const char *bmpfilename,unsigned char **bmpdata)
    111 {
    112     int nread;
    113     int raw_size = 0;    
    114     *bmpdata = bmpfilename +(unsigned char)54;
    115     return 0;
    116 }
    117 
    118 void draw_bmp(char *bmpfilename, unsigned short *fb)
    119 {
    120     unsigned char * bmpdata;
    121     int ret;
    122 
    123     ret = bmp_read_file(bmpfilename, &bmpdata);
    124     if (ret)
    125     {
    126         printf("read bmpfile error.
    ");
    127     }
    128     printf("bmpread0000000!!!!
    ");
    129     bmp2fb16_rgb565(bmpdata, fb);
    130     printf("bm2fb1600000000000!!!!
    ");
    131 }
    132 //./lcd_test xxx.jpg
    133 int main(int argc,char **argv)
    134 {
    135     int fp = 0;
    136     struct fb_var_screeninfo   vinfo;
    137     struct fb_fix_screeninfo   finfo;
    138  
    139     int screensize = 0;
    140     //char *fbp = 0;
    141     //int x = 0, y = 0;
    142     //int location = 0;
    143     int bytes_per_pixel;
    144     int pic_fd;
    145     unsigned long len;
    146     unsigned char *buffer;
    147     int key;
    148     int i;
    149     
    150     /*1.打开一副图片*/
    151     pic_fd =open(argv[1],O_RDWR);
    152     printf("pic_fd=%d
    ",pic_fd);
    153 
    154     /*2.获取图片大小*/
    155     len =lseek(pic_fd, 0, SEEK_END);
    156     printf("len =%ld
    ",len);
    157 
    158     buffer =(unsigned char *)malloc(len);
    159 
    160     lseek(pic_fd, 0, SEEK_SET);
    161     /*3.读取图片数据*/
    162     read(pic_fd,buffer,len); 
    163 
    164  
    165     fp = open("/dev/fb0", O_RDWR);
    166     if(fp < 0) {
    167         printf("open failed
    ");
    168     }
    169  
    170     if(ioctl(fp, FBIOGET_FSCREENINFO, &finfo)) {
    171         perror("ioctl");
    172     }
    173  
    174     if(ioctl(fp, FBIOGET_VSCREENINFO, &vinfo)) {
    175         perror("ioctl");
    176     }
    177  
    178     bytes_per_pixel = vinfo.bits_per_pixel/8;
    179     screensize = vinfo.xres * vinfo.yres * bytes_per_pixel;
    180     printf("x = %d  y = %d   bytes_per_pixel = %d
    ",  vinfo.xres,  vinfo.yres,  bytes_per_pixel);
    181     printf("screensize = %d
    ",  screensize);
    182  
    183     framebuffer_ptr = (char*) mmap(0,  screensize,  PROT_READ |PROT_WRITE,  MAP_SHARED, fp, 0);
    184     if(framebuffer_ptr < 0) {
    185         perror("mmap");
    186     }
    187     printf("line_length = %d
    ",finfo.line_length);
    188 #if 0
    189     for(x = 100; x<200; x++) {
    190         for(y=100; y<200; y++) {
    191             location = x * bytes_per_pixel + y * finfo.line_length;
    192             *(framebuffer_ptr + location) = 0;
    193             *(framebuffer_ptr +location + 1) = 255;
    194             *(framebuffer_ptr + location + 2) = 0;
    195             *(framebuffer_ptr + location + 3) = 0;
    196         }
    197     }
    198  #endif
    199 
    200     while(1)
    201     {
    202         /*2.图像处理*/
    203         scanf("%d",&key);
    204         switch(key)
    205         {
    206             case 1:
    207                 /*2.7 显示图片*/
    208                 printf("test picture!
    ");
    209                 
    210                 printf("loadjpeg00000!!!!
    ");
    211                 draw_bmp(buffer,(unsigned short *) framebuffer_ptr);
    212                 break;
    213             case 2:
    214                 ClearScr(0x00ff0000);
    215                 break;
    216             case 3:
    217                 Mire();
    218                 break;
    219             default:
    220                 break;
    221         }    
    222     }
    223     munmap(framebuffer_ptr, screensize);
    224     close(fp);
    225     return 0;
    226 }
     1 ROOTFS_DIR = /source/rootfs
     2 
     3 MODULE_NAME = lcd_drv
     4 APP_NAME = lcd_test
     5 
     6 CROSS_COMPILE = /home/kevin/Linux_4412/toolchain/gcc-4.6.4/bin/arm-none-linux-gnueabi-
     7 CC = $(CROSS_COMPILE)gcc
     8 
     9 ifeq ($(KERNELRELEASE), )
    10 
    11 KERNEL_DIR = /home/kevin/Linux_4412/linux-3.14-fs4412
    12 CUR_DIR = $(shell pwd)
    13 
    14 all :
    15     make -C  $(KERNEL_DIR) M=$(CUR_DIR) modules
    16     $(CC) $(APP_NAME).c  -o $(APP_NAME)
    17 
    18 clean :
    19     make -C  $(KERNEL_DIR) M=$(CUR_DIR) clean
    20     rm -rf $(APP_NAME)    
    21 
    22 install:
    23     cp -raf *.ko $(APP_NAME)   $(ROOTFS_DIR)/drv_module
    24 
    25 
    26 else
    27 
    28 obj-m += $(MODULE_NAME).o
    29 
    30 
    31 endif

    gt811的编程思路:
    1, 为gt811需要一个i2c client提供从设备信息

    arch/arm/mach-s5pv210/mach-smdkv210.c
    static struct i2c_board_info smdkv210_i2c_devs2[] __initdata = {
    /* To Be Updated */
    { I2C_BOARD_INFO("gt811_i2c_ts", 0x5d), },
    };

    make zImage -j2
    更新内核:
    cp -raf arch/arm/boot/zImage /tftpboot/

    2, 构建i2c_driver, 注册到总线
    实现probe()
    |
    1, 构建一个input device
    2, 初始化 input device
    3, 注册input device
    4, 硬件初始化:
    a, 上电初始化
    1, 设置中断引脚为悬浮输入态,RESET设置成GPIO(内部上拉)
    2, RESET引脚设置成输出低(开始复位), 延时1ms, 转成输入态
    3, 延迟至少20ms,通过i2c寻址gt811 (确认复位是否成功)
    4,如果有响应,分一次或者多次初始化寄存器
    5,如果没有响应,重复2步骤



    b, 申请中断--request_irq(), 还要用中断下半部(tasklet, 工作队列(选择这个))
    |
    1,通过i2c_tranfser(会导致休眠)读取到坐标
    2, 分析坐标
    3, 上报坐标
    ------------------------------------------------------------

    linux驱动中:对于多点触摸屏, 实际需要一个多点上报协议:

    Documentation/input$ ls multi-touch-protocol.txt

    Here is what a minimal event sequence for a two-contact touch would look
    like for a type A device:

    ABS_MT_POSITION_X x[0]
    ABS_MT_POSITION_Y y[0]
    SYN_MT_REPORT //第0点上报完毕
    ABS_MT_POSITION_X x[1]
    ABS_MT_POSITION_Y y[1]
    SYN_MT_REPORT //第1点上报完毕
    SYN_REPORT //所有点上报完毕


    在代码中实现:
    input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_X, x);
    input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_Y, y);
    input_mt_sync(gt811_dev->inputdev);
    |
    input_event(dev, EV_SYN, SYN_MT_REPORT, 0);

    input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_X, x);
    input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_Y, y);
    input_mt_sync(gt811_dev->inputdev);

    input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_X, x);
    input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_Y, y);
    input_mt_sync(gt811_dev->inputdev);

    input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_X, x);
    input_event(gt811_dev->inputdev, EV_ABS, ABS_MT_POSITION_Y, y);
    input_mt_sync(gt811_dev->inputdev);

    input_sync(gt811_dev->inputdev); //所有点上报完毕

    Stay hungry, stay foolish 待续。。。
  • 相关阅读:
    centos7.6 安装与配置 MongoDB yum方式
    MongoDB 介绍
    centos 关闭selinux
    前端 HTML标签属性
    前端 HTML 标签嵌套规则
    前端 HTML 标签分类
    前端 HTML body标签相关内容 常用标签 表单标签 form里面的 input标签介绍
    前端 HTML body标签相关内容 常用标签 表单标签 form 表单控件分类
    前端 HTML form表单标签 select标签 option 下拉框
    POJ 1426
  • 原文地址:https://www.cnblogs.com/panda-w/p/10992943.html
Copyright © 2011-2022 走看看