Chinaunix首页 | 论坛 | 博客
  • 博客访问: 855655
  • 博文数量: 290
  • 博客积分: 511
  • 博客等级: 下士
  • 技术积分: 1590
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-29 13:14
文章分类

全部博文(290)

文章存档

2018年(28)

2017年(19)

2016年(8)

2015年(1)

2014年(14)

2013年(12)

2012年(22)

2011年(186)

分类: LINUX

2017-06-19 13:36:19

原文地址:Linux 下LCD12864液晶驱动 作者:schspa


  • 内容介绍:之前有一个项目想要使用Linux系统但是为了省电及节约成本就使用一个黑白液晶屏,现在把驱动调试设计过程记录一下.

Linux内核:          linux-2.6.35.3
        Board:                 ZLG iMX287开发板
        液晶屏:                ZLE12864A-FFSSWE-NAA是一个ZigBee开发板的液晶模块.

首先最主要的工作就是液晶驱动的设计,对于这种液晶,没办法使用iMX287芯片的LCD Interface,所以只能使用GPIO口来模拟时序了.如果写一个通用的字符设备驱动也可以,但是这毕竟不是很好的办法.所以还是要使用FrameBuffer的驱动.

首先找到我们的参考驱动drivers/auxdisplay
其说明文档在Documentation/auxdisplay/中

首先这个驱动是给x86电脑使用的,通过并口来连接.这里用我们的ARM操作就需要使用GPIO来操作.

修改之后的接口连接(使用串行接口模式)
CS   ->    P2.12
SCL ->    P2.14
SI     ->    P2.15
RST ->    P2.4
A0    ->    P2.13
下面写出12864操作函数接口模块,这里实现了接口,模块很简单,没什么好说的.

点击(此处)折叠或打开

  1. /*
  2.  *    2015-01-21 20:53:59
  3.  *    LCD接口函数实现
  4.  *    
  5.  *
  6.  **/
  7. #include<linux/module.h> /* module */
  8. #include<linux/fs.h> /* file operation */
  9. #include<asm/uaccess.h> /* get_user() */
  10. #include<asm/io.h> /* ioctl */
  11. #include "mach/regs-pinctrl.h"/*GPIO REG Address*/
  12. #include "lcd12864.h"
  13. typedef unsigned char uchar;
  14. typedef unsigned char uint8;
  15. typedef unsigned int uint16;

  16. void __iomem *pinctrl_base = NULL;

  17. #define L_CS(a) do{    writel(1<<12, pinctrl_base + HW_PINCTRL_DOUT2_CLR-(a<<2));    }while(0)    
  18. //CS                P2.12
  19. #define L_LD(a) do{    writel(1<<13, pinctrl_base + HW_PINCTRL_DOUT2_CLR-(a<<2));    }while(0)
  20. //A0=H data A0=L command    P2.13
  21. #define L_CK(a) do{    writel(1<<14, pinctrl_base + HW_PINCTRL_DOUT2_CLR-(a<<2));    }while(0)
  22.     //CLK                P2.14
  23. #define L_DA(a) do{    writel(1<<15, pinctrl_base + HW_PINCTRL_DOUT2_CLR-(a<<2));    }while(0)
  24. //SI                P2.15
  25. #define L_BK(a) do{;}while(0)    //backlight
  26. #define L_RST(a) do{    writel(1<<4, pinctrl_base + HW_PINCTRL_DOUT2_CLR-(a<<2));    }while(0)
  27. //RST                P2.4


  28. void lcd12864_writecmd(unsigned char Command)
  29. {
  30.     unsigned char j, bit7;

  31.     L_CK(1); // = 1;
  32.     L_LD(0); // = 0;
  33.     L_CS(0); // = 0;
  34.     for (j = 0; j < 8; j++)
  35.     {
  36.         bit7 = Command & 0x80;
  37.         if (bit7 == 0)
  38.         {
  39.             L_DA(0); // = 0;
  40.         }
  41.         else
  42.         {
  43.             L_DA(1); // = 1;
  44.         }
  45.         L_CK(0);    // = 0;
  46. //        delay_us(10);
  47.         L_CK(1);    // = 1;
  48.         Command = Command << 1;
  49.     }
  50.     L_CS(1);    // = 1;
  51. }

  52. void lcd12864_writedata(unsigned char DDate)
  53. {
  54.     unsigned char j, bit7;
  55.     L_CK(1);    // = 1;
  56.     L_LD(1);    // = 1;
  57.     L_CS(0);    // = 0;
  58.     for (j = 0; j < 8; j++)
  59.     {
  60.         bit7 = DDate & 0x80;
  61.         if (bit7 == 0)
  62.         {
  63.             L_DA(0);    // = 0;
  64.         }
  65.         else
  66.         {
  67.             L_DA(1);    // = 1;
  68.         }
  69.         L_CK(0);    // = 0;
  70. //        delay_us(10);
  71.         L_CK(1);    // = 1;
  72.         DDate = DDate << 1;
  73.     }
  74.     L_CS(1);    // = 1;
  75. }

  76. void initLCDM(void)
  77. {
  78.     uchar ContrastLevel;//定义对比度
  79.     ContrastLevel = 0xa0;//对比度,根据不同的 LCD 调节,否则无法显示。
  80.     lcd12864_writecmd(0xaf);//开显示
  81.     lcd12864_writecmd(0x40);//显示起始行为 0
  82.     lcd12864_writecmd(0xa0);//RAM 列地址与列驱动同顺序
  83.     lcd12864_writecmd(0xa6);//正向显示
  84.     lcd12864_writecmd(0xa4);//显示全亮功能关闭
  85.     lcd12864_writecmd(0xa2);//LCD 偏压比 1/9
  86.     lcd12864_writecmd(0xc8);//行驱动方向为反向
  87.     lcd12864_writecmd(0x2f);//启用内部 LCD 驱动电源
  88.     lcd12864_writecmd(0xf8);//升压电路设置指令代码
  89.     lcd12864_writecmd(0x00);//倍压设置为 4X
  90.     lcd12864_writecmd(ContrastLevel); //设置对比度
  91.     lcd12864_writecmd(0xaf);//开显示
  92. }



  93. void ResetLCD(void)
  94. {
  95.         L_RST(1);
  96.     L_RST(0);
  97. //    delay_ms(10);
  98.     L_RST(1);

  99.     
  100. }

  101. void ClearRAM(void)
  102. {
  103.     uint8 i,j;
  104.     for (i = 0; i < 8; i++)
  105.     {
  106.         lcd12864_writecmd(i|0xb0);
  107.         lcd12864_writecmd(0x10);
  108.         lcd12864_writecmd(0x00);
  109.         for (j = 0; j < 132; j++)
  110.         {
  111.             lcd12864_writedata(0xAA);
  112.         }
  113.     }
  114. }

  115. static unsigned int is_lcd12864_inited = 0;

  116. unsigned int lcd12864_isinited(void){
  117.     return is_lcd12864_inited;
  118. }

  119. EXPORT_SYMBOL_GPL(lcd12864_writedata);
  120. EXPORT_SYMBOL_GPL(lcd12864_writecmd);
  121. EXPORT_SYMBOL_GPL(lcd12864_isinited);


  122. /*********************************************************************************************************
  123. Module Functions
  124. *********************************************************************************************************/
  125. static int __init lcdModule_init (void)
  126. {
  127.         int iRet=0;
  128.         printk("\nlcd12864 module init!\n");
  129.     //printk("you should see a few line on LCDi\n");
  130.     pinctrl_base = ioremap(0x80018000, 0x1B80);
  131.     writel(0xFF<<24 | 0x300, pinctrl_base+HW_PINCTRL_MUXSEL4_SET);
  132.     //set io port mode for 2.12,2.13,2.14,2.15 to GPIO
  133.     writel(0xF<<12|0x1<<4, pinctrl_base+HW_PINCTRL_DOE2_SET); //set to output mode
  134.     ResetLCD();
  135.     initLCDM();
  136.     ClearRAM(); //请液晶缓存
  137.     //lcd12864_writecmd(0xA7);
  138.     is_lcd12864_inited = 1;
  139.     return iRet;
  140. }
  141. static void __exit lcdModule_exit (void) /* warning:return void */
  142. {
  143.     printk("\nlcd module exit!\n");
  144.     iounmap(pinctrl_base);
  145.     is_lcd12864_inited = 0;
  146. }

  147. /*********************************************************************************************************
  148. Driver Definitions
  149. *********************************************************************************************************/
  150. module_init(lcdModule_init);
  151. module_exit(lcdModule_exit);

  152. MODULE_LICENSE("Dual BSD/GPL");
  153. MODULE_AUTHOR("schspa@gmail.com");
  154. MODULE_DESCRIPTION("iMX287 lcd12864 driver By Schspa");

下面是重要的内容,我们的FrameBuffer接口
        注意我们的在mmap函数中的vma->vm_pgoff之前老是映射的不对,加上之后就对了

点击(此处)折叠或打开

  1. /*
  2.  * Filename: cfag12864bfb.c
  3.  * Version: 0.1.0
  4.  * Description: cfag12864b LCD framebuffer driver
  5.  * License: GPLv2
  6.  * Depends: cfag12864b
  7.  *
  8.  * Author: Copyright (C) Miguel Ojeda Sandonis
  9.  * Date: 2006-10-31
  10.  *
  11.  * Modified: schspa
  12.  * Data: 2015-01-21
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License version 2 as
  15.  * published by the Free Software Foundation.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  25.  *
  26.  */

  27. #include <linux/init.h>
  28. #include <linux/module.h>
  29. #include <linux/kernel.h>
  30. #include <linux/delay.h>
  31. #include <linux/errno.h>
  32. #include <linux/fb.h>
  33. #include <linux/mm.h>
  34. #include <linux/platform_device.h>
  35. #include <linux/string.h>
  36. #include <linux/uaccess.h>
  37. #include <linux/cfag12864b.h>
  38. #include <asm/cacheflush.h>
  39. void cfag12864b_sync(void);
  40. extern unsigned char *cfag12864b_buffer_nocache;
  41. #define CFAG12864BFB_NAME "cfag12864bfb"

  42. static struct fb_fix_screeninfo cfag12864bfb_fix __devinitdata = {
  43.     .id = "cfag12864b",
  44.     .type = FB_TYPE_PACKED_PIXELS,
  45.     .visual = FB_VISUAL_MONO10,
  46.     .xpanstep = 0,
  47.     .ypanstep = 0,
  48.     .ywrapstep = 0,
  49.     .line_length = CFAG12864B_WIDTH / 8,
  50.     .accel = FB_ACCEL_NONE,
  51. };

  52. static struct fb_var_screeninfo cfag12864bfb_var __devinitdata = {
  53.     .xres = CFAG12864B_WIDTH,
  54.     .yres = CFAG12864B_HEIGHT,
  55.     .xres_virtual = CFAG12864B_WIDTH,
  56.     .yres_virtual = CFAG12864B_HEIGHT,
  57.     .bits_per_pixel = 1,
  58.     .red = { 0, 1, 0 },
  59.           .green = { 0, 1, 0 },
  60.           .blue = { 0, 1, 0 },
  61.     .left_margin = 0,
  62.     .right_margin = 0,
  63.     .upper_margin = 0,
  64.     .lower_margin = 0,
  65.     .vmode = FB_VMODE_NONINTERLACED,
  66. };

  67. static int cfag12864bfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
  68. {
  69.     printk("cfag12864bfb_mmap\r\n");
  70.     unsigned long page;
  71.      unsigned char i;
  72.      unsigned long start = (unsigned long)vma->vm_start;
  73.      //unsigned long end = (unsigned long)vma->vm_end;
  74.      unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
  75.      //if(size > CFAG12864B_SIZE){
  76.             printk("size %d \n", size);
  77.         //    return -ENOMEM;
  78.         //}
  79.         vma->vm_flags |= VM_IO | VM_SHARED;
  80.          vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  81.      //得到物理地址 注意这里边的vma->vm_pgoff  负责可能出现不正常的情况.
  82.      page = virt_to_phys(cfag12864b_buffer+vma->vm_pgoff);
  83.      //将用户空间的一个vma虚拟内存区映射到以page开始的一段连续物理页面上
  84.      if(remap_pfn_range(vma,start,page>>PAGE_SHIFT,size,PAGE_SHARED)){//第三个参数是页帧号,由物理地址右移PAGE_SHIFT得到
  85.         printk("remap_pfn_range failed\r\n");
  86.      return -1;
  87.      }
  88.      return 0;
  89. //    return vm_insert_page(vma, vma->vm_start,
  90. //        virt_to_page(cfag12864b_buffer));
  91. }

  92. static int cfag12864bfb_sync(struct fb_info *info)
  93. {
  94.     printk("fb_sync\r\n");
  95.     cfag12864b_sync();
  96.     return 0;//vm_insert_page(vma, vma->vm_start,
  97.         //virt_to_page(cfag12864b_buffer));
  98. }
  99. static int cfag12864bfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg){
  100.     

  101.     int i = 0;
  102.     printk("fb ioctl %d\r\n", cmd);
  103.     cfag12864b_sync();
  104.     return 0;
  105. }
  106. static struct fb_ops cfag12864bfb_ops = {
  107.     .owner = THIS_MODULE,
  108. //    .fb_read = fb_sys_read,
  109. //    .fb_write = fb_sys_write,
  110. //    .fb_fillrect = sys_fillrect,
  111. //    .fb_copyarea = sys_copyarea,
  112. //    .fb_imageblit = sys_imageblit,
  113.     .fb_ioctl    =    cfag12864bfb_ioctl,
  114.     .fb_mmap = cfag12864bfb_mmap,
  115.     .fb_sync = cfag12864bfb_sync,
  116. };

  117. static int __devinit cfag12864bfb_probe(struct platform_device *device)
  118. {
  119.     int i = 0;
  120.     int ret = -EINVAL;
  121.      struct fb_info *info = framebuffer_alloc(0, &device->dev);

  122.     if (!info)
  123.         goto none;

  124.     info->screen_base = (char __iomem *) cfag12864b_buffer;
  125.     info->screen_size = CFAG12864B_SIZE;
  126.     info->fbops = &cfag12864bfb_ops;
  127.     info->fix = cfag12864bfb_fix;
  128.     info->var = cfag12864bfb_var;
  129.     info->pseudo_palette = NULL;
  130.     info->par = NULL;
  131.     info->flags = FBINFO_FLAG_DEFAULT;

  132.     if (register_framebuffer(info) < 0)
  133.         goto fballoced;

  134.     platform_set_drvdata(device, info);

  135.     printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
  136.         info->fix.id);
  137.     for(i = 0; i<1024; i++){
  138.         info->screen_base[i] = 0x0F;
  139.     }
  140.     return 0;

  141. fballoced:
  142.     framebuffer_release(info);

  143. none:
  144.     return ret;
  145. }

  146. static int __devexit cfag12864bfb_remove(struct platform_device *device)
  147. {
  148.     struct fb_info *info = platform_get_drvdata(device);

  149.     if (info) {
  150.         unregister_framebuffer(info);
  151.         framebuffer_release(info);
  152.     }

  153.     return 0;
  154. }

  155. static struct platform_driver cfag12864bfb_driver = {
  156.     .probe    = cfag12864bfb_probe,
  157.     .remove = __devexit_p(cfag12864bfb_remove),
  158.     .driver = {
  159.         .name    = CFAG12864BFB_NAME,
  160.     },
  161. };

  162. static struct platform_device *cfag12864bfb_device;

  163. static int __init cfag12864bfb_init(void)
  164. {
  165.     int ret = -EINVAL;
  166.     //printk("PAGE_SIZE:%d\r\n",PAGE_SIZE);
  167.     /* cfag12864b_init() must be called first */
  168.     if (!cfag12864b_isinited()) {
  169.         printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: "
  170.             "cfag12864b is not initialized\n");
  171.         goto none;
  172.     }

  173.     if (cfag12864b_enable()) {
  174.         printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: "
  175.             "can't enable cfag12864b refreshing (being used)\n");
  176.         return -ENODEV;
  177.     }

  178.     ret = platform_driver_register(&cfag12864bfb_driver);

  179.     if (!ret) {
  180.         cfag12864bfb_device =
  181.             platform_device_alloc(CFAG12864BFB_NAME, 0);

  182.         if (cfag12864bfb_device)
  183.             ret = platform_device_add(cfag12864bfb_device);
  184.         else
  185.             ret = -ENOMEM;

  186.         if (ret) {
  187.             platform_device_put(cfag12864bfb_device);
  188.             platform_driver_unregister(&cfag12864bfb_driver);
  189.         }
  190.     }

  191. none:
  192.     return ret;
  193. }

  194. static void __exit cfag12864bfb_exit(void)
  195. {
  196.     platform_device_unregister(cfag12864bfb_device);
  197.     platform_driver_unregister(&cfag12864bfb_driver);
  198.     cfag12864b_disable();
  199. }

  200. module_init(cfag12864bfb_init);
  201. module_exit(cfag12864bfb_exit);

  202. MODULE_LICENSE("GPL v2");
  203. MODULE_AUTHOR("Miguel Ojeda Sandonis ");
  204. MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver");

阅读(2493) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~