LCD驱动 15-3

测试:
1:make menuconfig去掉原来的驱动程序
    Device Drivers  --->    
        Graphics support  ---> 
           <M> S3C2410 LCD framebuffer support                 
2: make uImage
  make modules
  cp arch/arm/boot/uImage  /work/nfs_root/uImage_nolcd

3.使用新的uImage启动开发板:

insmod cfbcopyarea.ko
insmod cfbfillrect.ko 
insmod cfbimgblt.ko

insmod lcd.ko

4.

ech0 hello > /dev/tty1         //可以看到LCD上有hello

cat lcd.ko > /dev/fb0        //有花屏

 

5.修改/etc/inittab
  tty1::askfirst:-/bin/sh

insmod cfbcopyarea.ko

insmod cfbfillrect.ko 

insmod cfbimgblt.ko

insmod lcd.ko

insmod buttons.ko

 

通过按键控制另一个sh控制台

 

 

  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 
 17 #include <asm/io.h>
 18 #include <asm/uaccess.h>
 19 #include <asm/div64.h>
 20 
 21 #include <asm/mach/map.h>
 22 #include <asm/arch/regs-lcd.h>
 23 #include <asm/arch/regs-gpio.h>
 24 #include <asm/arch/fb.h>
 25 
 26 struct lcd_regs{
 27     unsigned long    lcdcon1;    
 28     unsigned long    lcdcon2;    
 29     unsigned long    lcdcon3;
 30     unsigned long    lcdcon4;
 31     unsigned long    lcdcon5;
 32     unsigned long    lcdsaddr1;
 33     unsigned long    lcdsaddr2;
 34     unsigned long    lcdsaddr3;
 35     unsigned long    redlut;   
 36     unsigned long    greenlut; 
 37     unsigned long    bluelut;  
 38     unsigned long    reserved[9];
 39     unsigned long    dithmode;   
 40     unsigned long    tpal;   
 41     unsigned long    lcdintpnd;
 42     unsigned long    lcdsrcpnd;
 43     unsigned long    lcdintmsk;  
 44     unsigned long    lpcsel;
 45 
 46 };
 47 
 48 static struct fb_info *s3c_lcd;
 49 /* gpbon,gpbdat,c,d,g, */
 50 volatile unsigned long *gpbcon;
 51 volatile unsigned long *gpbdat;
 52 volatile unsigned long *gpccon;
 53 volatile unsigned long *gpdcon;
 54 volatile unsigned long *gpgcon;
 55 static volatile  struct lcd_regs* lcd_regs;
 56 static u32    pseudo_palette[16];
 57 
 58 static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
 59 {
 60     chan &= 0xffff;
 61     chan >>= 16 - bf->length;
 62     return chan << bf->offset;
 63 }
 64 
 65 static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,
 66                  unsigned int green, unsigned int blue,
 67                  unsigned int transp, struct fb_info *info)
 68 {
 69     unsigned int val;
 70     
 71     if (regno > 16)
 72         return 1;
 73 
 74     /* 用red,green,blue三原色构造出val */
 75     val  = chan_to_field(red,    &info->var.red);
 76     val |= chan_to_field(green, &info->var.green);
 77     val |= chan_to_field(blue,    &info->var.blue);
 78     
 79     //((u32 *)(info->pseudo_palette))[regno] = val;
 80     pseudo_palette[regno] = val;
 81     return 0;
 82 }
 83 
 84 static struct fb_ops s3c_lcdfb_ops = {
 85     .owner        = THIS_MODULE,
 86     .fb_setcolreg    = s3c_lcdfb_setcolreg,
 87     .fb_fillrect    = cfb_fillrect,
 88     .fb_copyarea    = cfb_copyarea,
 89     .fb_imageblit    = cfb_imageblit,
 90 };
 91 
 92 
 93 static int lcd_init(void)
 94 {
 95 
 96     /* 1. 分配一个fb_info */
 97     s3c_lcd = framebuffer_alloc(0, NULL);
 98     
 99     /* 2. 设置 */
100     /* 2.1 设置固定的参数 */
101     strcpy(s3c_lcd->fix.id, "mylcd");
102     s3c_lcd->fix.smem_len = 480 * 272 * 16 / 8;
103     s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS;
104     s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR;  /*TFT*/
105     s3c_lcd->fix.line_length = 480 * 2;
106     
107     /* 2.2 设置可变的参数 */
108     s3c_lcd->var.xres           = 480;
109     s3c_lcd->var.yres           = 272;
110     s3c_lcd->var.xres_virtual   = 480;
111     s3c_lcd->var.yres_virtual   = 272;
112     s3c_lcd->var.bits_per_pixel = 16;
113 
114     /* RGB:565 */
115     s3c_lcd->var.red.offset     = 11;
116     s3c_lcd->var.red.length     = 5;
117 
118     s3c_lcd->var.green.offset   = 5;
119     s3c_lcd->var.green.length   = 6;
120 
121     s3c_lcd->var.blue.offset    = 0;
122     s3c_lcd->var.blue.length    = 5;
123     
124     s3c_lcd->var.activate       = FB_ACTIVATE_NOW;
125     
126     /* 2.3 设置操作函数 */
127     s3c_lcd->fbops = &s3c_lcdfb_ops;
128     
129     /* 2.4 其他设置 */
130     s3c_lcd->pseudo_palette = pseudo_palette;    //假的调色板    
131 
132     s3c_lcd->screen_size = 480 * 272 * 16 / 8;
133     
134     /* 3. 硬件相关的设置 */
135     /* 3.1 配置GPIO用于LCD */
136     //0x56000010 ,8
137     gpbcon = ioremap(0x56000010, 8);
138     gpbdat = gpbcon + 1;
139     gpccon = ioremap(0x56000020, 4);
140     gpdcon = ioremap(0x56000030, 4);
141     gpgcon = ioremap(0x56000060, 4);
142     //映射是一页一页映射,不用担心不足  
143     *gpccon  = 0xaaaaaaaa;   // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND 
144     *gpdcon  = 0xaaaaaaaa;   // GPIO管脚用于VD[23:8]
145     *gpbcon &= ~(3);  // Power enable pin
146     *gpbcon |= (0x01);
147     *gpbdat &= ~(1<<0);            // Power off
148     *gpgcon |=  (3<<8);   // GPG4用作LCD_PWREN
149     
150     /* 3.2 根据LCD手册设置LCD控制器,比如VCLK的频率等 */
151     lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));
152 
153         /* 
154          * 设置LCD控制器的控制寄存器LCDCON1~5
155          * 1. LCDCON1:
156          *    设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
157          *    选择LCD类型: TFT LCD   
158          *    设置显示模式: 16BPP
159          *    先禁止LCD信号输出
160          * 2. LCDCON2/3/4:
161          *    设置控制信号的时间参数
162          *    设置分辨率,即行数及列数
163          * 现在,可以根据公式计算出显示器的频率:
164          * 当HCLK=100MHz时,
165          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
166          *              {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
167          *              {2x(CLKVAL+1)/(HCLK)}]
168          *            = 60Hz
169          * 3. LCDCON5:
170          *    设置显示模式为16BPP时的数据格式: 5:6:5
171          *    设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
172          *    半字(2字节)交换使能
173          */
174          
175     lcd_regs->lcdcon1 = (4<<8) | (0x3<<5) | \
176                   (0xC<<1) | (0<<0);
177     lcd_regs->lcdcon2 = (1<<24) | (271<<14) | \
178                   (1<<6) | (10-1);
179     lcd_regs->lcdcon3 = (1<<19) | (479<<8) | (1);
180     lcd_regs->lcdcon4 = 40;
181     lcd_regs->lcdcon5 = (1<<11) | (1<<9) | (1<<8) | \
182                   (1<<1);
183     /* 3.3 分配显存(framebuffer),并把地址告诉LCD控制器 */
184     s3c_lcd->screen_base = dma_alloc_writecombine(NULL,        \
185                 s3c_lcd->fix.smem_len, &s3c_lcd->fix.smem_start, GFP_KERNEL);
186     lcd_regs->lcdsaddr1 = (s3c_lcd->fix.smem_start>>1) & ~(3 << 30);
187     lcd_regs->lcdsaddr2 = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1)    \
188                 & ( 0X1fffff );
189     lcd_regs->lcdsaddr3 = (0<<11) | (480 *16/16);
190     
191     /* 启动LCD */
192     lcd_regs->lcdcon1 |= (1 << 0);        //使能LCD本身
193     lcd_regs->lcdcon5 |=  (1<<3);     // 设置是否输出LCD_PWREN
194     *gpbdat |= (1<<0);            // Power on
195     
196     /* 4. 注册 */
197     
198     register_framebuffer(s3c_lcd);
199     
200     return 0;
201 }
202 
203 static int lcd_exit(void)
204 {
205     unregister_framebuffer(s3c_lcd);
206     lcd_regs->lcdcon1 &= ~(1 << 0);        //关闭LCD本身
207     *gpbdat &= ~(1<<0);            // Power off
208     dma_free_writecombine(NULL, s3c_lcd->fix.smem_len, \
209     s3c_lcd->screen_base, s3c_lcd->fix.smem_start);
210 
211     iounmap(gpbcon);
212     iounmap(gpccon);
213     iounmap(gpdcon);
214     iounmap(gpgcon);
215 
216     framebuffer_release(&s3c_lcd);
217     return 0;
218 }
219 
220 module_init(lcd_init);
221 module_exit(lcd_exit);
222 
223 MODULE_LICENSE("GPL");

 

 

posted @ 2016-01-29 23:41  CAM&  阅读(324)  评论(0编辑  收藏  举报