LCD驱动笔记

4 篇文章 0 订阅

LCD驱动笔记                 

linux当中,把整个LCD驱动分为两层:LCD帧缓冲区层和LCD硬件驱动层。LCD帧缓冲区层其实就是将内核中的一部分空间当作一个字符型设备,通过操作字符型设备的接口函数就可以操作这段帧缓冲区。而LCD硬件驱动层是对LCD硬件的初始化,LCD控制器在硬件驱动层被看作一个平台设备

LCD帧缓冲区层对应的文件是fbmem.c LCD硬件驱动层对应的文件是S32440fb.c 


驱动的入口函数

1:向内核申请一段大小为sizeof(struct fb_info) + size的空间,并分配一个fb_info         

         s3c_lcd =framebuffer_alloc(0, NULL);  //     

2:设置

  /*2.1设置固定参数*/

         strcpy(s3c_lcd->fix.id,"mylcd");   //  名字     

         s3c_lcd->fix.smem_len= 240*320*16/8;  //整个屏幕占用空间的大小

         s3c_lcd->fix.type     = FB_TYPE_PACKED_PIXELS;  //充满整个空间的像素  

         s3c_lcd->fix.visual   = FB_VISUAL_TRUECOLOR; /* TFT */ // 真彩色

         s3c_lcd->fix.line_length= 240*2;   //行长度

 

         /*2.2 设置可变的参数 */

         s3c_lcd->var.xres           = 240;    //真实的分辨率

         s3c_lcd->var.yres           = 320;   

         s3c_lcd->var.xres_virtual   = 240;   //虚拟分辨率

         s3c_lcd->var.yres_virtual   = 320;

         s3c_lcd->var.bits_per_pixel= 16;     //数据位多少位

 

         /*RGB:565 */  16位三原色

s3c_lcd->var.red.offset     = 11;   //11-15是表示红色

     s3c_lcd->var.red.length     = 5;  //红色五位

    

     s3c_lcd->var.green.offset   = 5;   //5-10表示绿色

     s3c_lcd->var.green.length   = 6;  //绿色六位

 

     s3c_lcd->var.blue.offset    = 0;  //0-4表示蓝色

     s3c_lcd->var.blue.length    = 5;  //

 

     s3c_lcd->var.activate       = FB_ACTIVATE_NOW;    //立即设置值

     /* 2.4 其他的设置*/

     s3c_lcd->pseudo_palette =pseudo_palette;

     //s3c_lcd->screen_base  = ;  /*显存的虚拟地址 */

     s3c_lcd->screen_size   = 240*324*16/8;

 

     /* 3. 硬件相关的操作*/

     /* 3.1 配置GPIO用于LCD */

     gpbcon = ioremap(0x56000010, 8);     //GPB控制寄存机虚拟地址映射

     gpbdat = gpbcon+1;  //GPB数据寄存机虚拟地址映射

 

     gpccon = ioremap(0x56000020, 4);    GBC控制寄存机虚拟地址映射

     gpdcon = ioremap(0x56000030, 4);    //GPD控制寄存机虚拟地址映射

     gpgcon = ioremap(0x56000060, 4);    //GPG控制寄存机虚拟地址映射

 

    *gpccon = 0xaaaaaaaa;   /* GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND*/

     *gpdcon = 0xaaaaaaaa;   /* GPIO管脚用于VD[23:8] */

    

     *gpbcon &= ~(3);  /* GPB0设置为输出引脚*/

     *gpbcon |= 1;

     *gpbdat &= ~1;     /* 输出低电平*/

 

     *gpgcon |= (3<<8); /* GPG4用作LCD_PWREN */

 

         /*3.2 根据LCD手册设置LCD控制器, 比如VCLK的频率等 */

         lcd_regs= ioremap(0x4D000000, sizeof(struct lcd_regs));

 

         /*bit[17:8]: VCLK = HCLK / [(CLKVAL+1) x 2], LCD手册P14

          *           10MHz(100ns) = 100MHz / [(CLKVAL+1) x 2]

          *           CLKVAL = 4

          * bit[6:5]: 0b11, TFT LCD

          * bit[4:1]: 0b1100, 16 bpp for TFT

          * bit[0] : 0 = Disable the video output and the LCD control signal.

          */

         lcd_regs->lcdcon1  = (4<<8) | (3<<5) |(0x0c<<1);

 

#if 1

         /*垂直方向的时间参数

          * bit[31:24]: VBPD, VSYNC之后再过多长时间才能发出第1行数据

          *            LCD手册T0-T2-T1=4

          *            VBPD=3

          * bit[23:14]: 多少行,320, 所以LINEVAL=320-1=319

          * bit[13:6] : VFPD, 发出最后一行数据之后,再过多长时间才发出VSYNC

          *            LCD手册T2-T5=322-320=2,所以VFPD=2-1=1

          * bit[5:0] : VSPW, VSYNC信号的脉冲宽度,LCD手册T1=1, 所以VSPW=1-1=0

          */

         lcd_regs->lcdcon2  = (3<<24) | (319<<14) |(1<<6) | (0<<0);

 

 

         /*水平方向的时间参数

          * bit[25:19]: HBPD, VSYNC之后再过多长时间才能发出第1行数据

          *            LCD手册T6-T7-T8=17

          *             HBPD=16

          * bit[18:8]: 多少列,240, 所以HOZVAL=240-1=239

          * bit[7:0] : HFPD, 发出最后一行里最后一个象素数据之后,再过多长时间才发出HSYNC

          *            LCD手册T8-T11=251-240=11,所以HFPD=11-1=10

          */

         lcd_regs->lcdcon3= (16<<19) | (239<<8) | (10<<0);

 

         /*水平方向的同步信号

          * bit[7:0]         :HSPW, HSYNC信号的脉冲宽度,LCD手册T7=5, 所以HSPW=5-1=4

          */  

         lcd_regs->lcdcon4= 4;

 

#else

lcd_regs->lcdcon2 =         S3C2410_LCDCON2_VBPD(5) | \

                   S3C2410_LCDCON2_LINEVAL(319)| \

                   S3C2410_LCDCON2_VFPD(3)| \

                   S3C2410_LCDCON2_VSPW(1);

 

lcd_regs->lcdcon3 =         S3C2410_LCDCON3_HBPD(10) | \

                   S3C2410_LCDCON3_HOZVAL(239)| \

                   S3C2410_LCDCON3_HFPD(1);

 

lcd_regs->lcdcon4 =         S3C2410_LCDCON4_MVAL(13) | \

                   S3C2410_LCDCON4_HSPW(0);

 

#endif

         /*信号的极性

          * bit[11]: 1=565 format

          * bit[10]: 0 = The video data is fetched atVCLK falling edge

          * bit[9] : 1 = HSYNC信号要反转,即低电平有效

          * bit[8] : 1 = VSYNC信号要反转,即低电平有效

          * bit[6] : 0 = VDEN不用反转

          * bit[3] : 0 = PWREN输出0

          * bit[1] : 0 = BSWP

          * bit[0] : 1 = HWSWP 2440手册P413

          */

         lcd_regs->lcdcon5= (1<<11) | (0<<10) | (1<<9) | (1<<8) | (1<<0);

        

         /*3.3 分配显存(framebuffer), 并把地址告诉LCD控制器 */

         s3c_lcd->screen_base= dma_alloc_writecombine(NULL, s3c_lcd->fix.smem_len,&s3c_lcd->fix.smem_start, GFP_KERNEL);     //分配一个320*240*16/8的显存

        

         lcd_regs->lcdsaddr1  = (s3c_lcd->fix.smem_start >> 1)& ~(3<<30); //告诉LCD控制器起始地址

         lcd_regs->lcdsaddr2  = ((s3c_lcd->fix.smem_start +s3c_lcd->fix.smem_len) >> 1) & 0x1fffff;

//告诉LCD控制器结束地址

         lcd_regs->lcdsaddr3  = (240*16/16);  /* 一行的长度(单位: 2字节)*/  

        

         //s3c_lcd->fix.smem_start= xxx;  /* 显存的物理地址*/

         /*启动LCD */

         lcd_regs->lcdcon1|= (1<<0); /* 使能LCD控制器 */

         lcd_regs->lcdcon5|= (1<<3); /* 使能LCD本身 */

         *gpbdat|= 1;     /* 输出高电平, 使能背光 */               

 

         /*4. 注册 */

         register_framebuffer(s3c_lcd);

 

 

出口函数

  staticvoid lcd_exit(void)

{

         unregister_framebuffer(s3c_lcd);

         lcd_regs->lcdcon1&= ~(1<<0); /* 关闭LCD本身 */

         *gpbdat&= ~1;     /* 关闭背光 */

         dma_free_writecombine(NULL,s3c_lcd->fix.smem_len, s3c_lcd->screen_base, s3c_lcd->fix.smem_start);    //释放显存

         iounmap(lcd_regs);

         iounmap(gpbcon);

         iounmap(gpccon);

         iounmap(gpdcon);

         iounmap(gpgcon); 

         framebuffer_release(s3c_lcd);     //释放fb_info结构体

}

 

调色板

/* from pxafb.c */

static inline unsigned intchan_to_field(unsigned int chan, struct fb_bitfield *bf)

{

         chan&= 0xffff;

         chan>>= 16 - bf->length;

         returnchan << bf->offset;

}

 

 

static int s3c_lcdfb_setcolreg(unsigned intregno, unsigned int red,

                                 unsigned int green, unsigned int blue,

                                 unsigned int transp, struct fb_info *info)

{

         unsignedint val;

        

         if(regno > 16)

                   return1;

 

         /*用red,green,blue三原色构造出val */

         val  = chan_to_field(red,        &info->var.red);

         val|= chan_to_field(green, &info->var.green);

         val|= chan_to_field(blue,        &info->var.blue);

        

         //((u32*)(info->pseudo_palette))[regno] = val;

         pseudo_palette[regno]= val;

         return0;

}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值