LCD驅動詳解

參考文檔:《液晶屏.pdf》《S3C2440用戶手冊》《JZ2440-V3原理圖》 linux

 

frame buffer: 顯存,用於存放LCD顯示數據;frame buffer經過LCD控制器和LCD Panel創建一一映射關係; app

LCD控制器: 參考LCD用戶手冊,配置LCD控制器,用於發出LCD控制信號,驅動LCD顯示; ide

掃描方向: 如圖①所示,由start到end的掃描方向是:從左到右,從上到下(掃描方向的一種); 函數

HSYNC: 行同步信號,用於行切換,一行掃描結束,須要掃描新行時,須要先發送行同步信號; this

VSYNC: 列同步信號,用於列切換,一幀掃描結束,須要掃描新的一幀時,須要先發送列同步信號; spa

時鐘信號: 每來一個時鐘,掃描的點移位一; 3d

   

原理圖——管腳說明 調試

 

   

 

 

硬件操做配置 orm

①配置LCD控制引腳; blog

②根據LCD手冊,配置LCD控制器;

③分配Frame buffer,並映射到LCD Panel;

   

《液晶屏.pdf》

Block Diagram

   

   

Interface Timing

   

Driver Timing

   

   

Timing Chart

a、

   

b、

 

《S3C2440用戶手冊》

LCD CONTROLLER SPECIAL REGISTERS

   

   

   

   

   

   

   

   

   

   

   

   

   

   

   

   

   

 

 

MEMORY DATA FORMAT (TFT)

 

 

驅動程序

1 /*
2 * 參考內核自帶的lcd驅動程序:
3 * C:\Users\liang\Desktop\linux-2.6.22.6\drivers\video\s3c2410fb.c
4 * 《液晶屏.pdf》、《s3c2440 用戶手冊》
5 */
6 #include <linux/module.h>
7 #include <linux/kernel.h>
8 #include <linux/errno.h>
9 #include <linux/string.h>
10 #include <linux/mm.h>
11 #include <linux/slab.h>
12 #include <linux/delay.h>
13 #include <linux/fb.h>
14 #include <linux/init.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/interrupt.h>
17 #include <linux/workqueue.h>
18 #include <linux/wait.h>
19 #include <linux/platform_device.h>
20 #include <linux/clk.h>
21         
22 #include <asm/io.h>
23 #include <asm/uaccess.h>
24 #include <asm/div64.h>
25         
26 #include <asm/mach/map.h>
27 #include <asm/arch/regs-lcd.h>
28 #include <asm/arch/regs-gpio.h>
29 #include <asm/arch/fb.h>
30
31 struct lcd_regs {
32         unsigned long        lcdcon1;
33         unsigned long        lcdcon2;
34         unsigned long        lcdcon3;
35         unsigned long        lcdcon4;
36         unsigned long        lcdcon5;
37 unsigned long        lcdsaddr1;
38 unsigned long        lcdsaddr2;
39 unsigned long        lcdsaddr3;
40 unsigned long        redlut;
41 unsigned long        greenlut;
42 unsigned long        bluelut;
43 unsigned long        reserved[9];
44 unsigned long        dithmode;
45 unsigned long        tpal;
46 unsigned long        lcdintpnd;
47 unsigned long        lcdsrcpnd;
48 unsigned long        lcdintmsk;
49 unsigned long        lpcsel;
50 };
51
52
53 static volatile unsigned long *gpb_con;
54 static volatile unsigned long *gpb_dat;
55
56 static volatile unsigned long *gpc_con;
57 static volatile unsigned long *gpd_con;
58 static volatile unsigned long *gpg_con;
59
60 static volatile struct lcd_regs* lcd_regs;
61
62 static u32 pseudo_palette[16];//假的調色板
63
64 static struct fb_info *lcd_info;
65
66 static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
67 {
68         chan &= 0xffff;
69         chan >>= 16 - bf->length;
70         return chan << bf->offset;
71 }
72
73 static int lcdfb_setcolreg(unsigned int regno, unsigned int red,
74                          unsigned int green, unsigned int blue,
75                          unsigned int transp, struct fb_info *info)
76 {
77         unsigned int val;
78
79         if (regno > 16)
80         {
81                 return -1;
82         }
83
84         //用三原色構造出val
85         val = chan_to_field(red, &info->var.red);
86         val |= chan_to_field(green, &info->var.green);
87         val |= chan_to_field(blue, &info->var.blue);
88
89         pseudo_palette[regno] = val;        //調好顏色,放回調色板
90
91         return 0;
92 }
93
94
95 static struct fb_ops lcd_fbops = {
96         .owner                = THIS_MODULE,
97         .fb_setcolreg        = lcdfb_setcolreg,//假的調色板的調色函數
98         .fb_fillrect        = cfb_fillrect,                //
99         .fb_copyarea        = cfb_copyarea,
100         .fb_imageblit        = cfb_imageblit,
101 };
102
103 /* 一、出入口函數 */
104 static int lcd_init(void)
105 {
106         /* 二、分配一個fb_info結構體 */
107         lcd_info = framebuffer_alloc(0, NULL);
108         /******** 2 end ********/
109
110         /* 三、設置 */
111         /* 設置固定的參數:lcd_info->fix */
112         strcpy(lcd_info->fix.id, "mylcd");                                        //名字
113         lcd_info->fix.smem_len                 = 240*320*16/8;                        //framebuffer長度(240*320 dots,lrgb565: 16bit/dots)
114         lcd_info->fix.type                         = FB_TYPE_PACKED_PIXELS;
115         lcd_info->fix.visual                = FB_VISUAL_TRUECOLOR;        //顏色深度(tft-lcd設置爲真彩)
116         lcd_info->fix.line_length        = 240*16/8;                                //framebuffer中每一行(line)佔據的字節數;240*2(2:16bit/8)                
117
118         /* 設置可變的參數 */
119         lcd_info->var.xres                         = 240;        //x方向的分辨率
120         lcd_info->var.yres                         = 320;        //y方向的分辨率
121         lcd_info->var.xres_virtual         = 240;        //x方向的虛擬分辨率
122         lcd_info->var.yres_virtual         = 320;        //y方向的虛擬分辨率
123         lcd_info->var.bits_per_pixel= 16;        //每一個像素點16位(rgb565)
124         lcd_info->var.activate                = FB_ACTIVATE_NOW;
125
126         // 顏色數據的位分配 rgb:565
127         lcd_info->var.red.offset        = 11;        //(5)bit11 - bit15
128         lcd_info->var.red.length        = 5;        
129         lcd_info->var.green.offset        = 5;        //(6)bit5 - bit10
130         lcd_info->var.green.length        = 6;
131         lcd_info->var.blue.offset        = 0;        //(5)bit0 - bit4
132         lcd_info->var.blue.length        = 5;
133         
134         /* 設置操做函數 */
135         lcd_info->fbops = &lcd_fbops;
136
137         /* 其餘設置 */
138         lcd_info->pseudo_palette = pseudo_palette;        //假的調色板
139         lcd_info->screen_size = 240*320*16/8;                //
140         /******** 3 end ********/
141
142         /* 四、硬件相關設置 */
143         /* 配置gpio用於lcd */
144         gpc_con = ioremap(0x56000020, 4);
145         gpd_con = ioremap(0x56000030, 4);
146         gpg_con = ioremap(0x56000060, 4);
147         gpb_con = ioremap(0x56000010, 8);
148         gpb_dat = gpb_con + 1;
149
150         //GPIO管腳用於VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
151         *gpc_con = 0xaaaaaaaa;
152
153         //GPIO管腳用於VD[23:8]
154         *gpd_con = 0xaaaaaaaa;
155
156         //GPB0設置爲輸出引腳
157         *gpb_con &= ~(3);
158         *gpb_con |= 1;
159         *gpb_dat &= ~1;                //輸出低電平
160
161         //GPG4用做LCD_PWREN
162         *gpg_con |= (3<<8);
163         
164         /* 根據lcd手冊設置lcd控制器 */
165         lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));
166         lcd_regs->lcdcon1 = (4<<8) | (3<<5) | (0x0c<<1);
167         lcd_regs->lcdcon2 = (3<<24) | (319<<14) | (1<<6) | (0<<0);
168         lcd_regs->lcdcon3 = (16<<19) | (239<<8) | (10<<0);
169         lcd_regs->lcdcon4 = 4;
170         lcd_regs->lcdcon5 = (1<<11) | (0<<10) | (1<<9) | (1<<8) | (1<<0);
171         
172         /* 分配顯存(framebuffer),並把地址告訴lcd控制器 */
173         // 虛擬地址 大小 物理地址
174         lcd_info->screen_base = dma_alloc_writecombine(NULL, lcd_info->fix.smem_len, &lcd_info->fix.smem_start, GFP_KERNEL);
175         
176         lcd_regs->lcdsaddr1 = (lcd_info->fix.smem_start >> 1) & ~(3<<30);
177         lcd_regs->lcdsaddr2 = ((lcd_info->fix.smem_start + lcd_info->fix.smem_len) >> 1) & 0x1fffff;
178         lcd_regs->lcdsaddr3 = (240*16/16); /* 一行的長度(單位: 2字節) */        
179         
180         /* 啓動LCD */
181         lcd_regs->lcdcon1 |= (1<<0);         //使能LCD自己
182         lcd_regs->lcdcon5 |= (1<<3);        
183         *gpb_dat |= 1;                         //輸出高電平, 使能背光
184         /******** 4 end ********/
185         
186         /* 五、註冊 */
187         register_framebuffer(lcd_info);
188         /******** 5 end ********/
189
190         return 0;
191 }
192
193 static void lcd_exit(void)
194 {
195         dma_free_writecombine(NULL, lcd_info->fix.smem_len, lcd_info->screen_base, lcd_info->fix.smem_start);
196         unregister_framebuffer(lcd_info);
197         /* 關閉LCD */
198         lcd_regs->lcdcon1 &= ~(1<<0);
199         lcd_regs->lcdcon5 &= ~(1<<3);
200         *gpb_dat &= ~(1<<0);
201
202         iounmap(lcd_regs);
203         iounmap(gpc_con);
204         iounmap(gpd_con);
205         iounmap(gpg_con);
206         iounmap(gpb_con);
207
208         framebuffer_release(lcd_info);
209         return;
210 }
211
212 module_init(lcd_init);
213 module_exit(lcd_exit);
214 MODULE_LICENSE("GPL");
215 /******** 1 end ********/

   

附:

1 /**
2 * framebuffer_alloc - creates a new frame buffer info structure
3 *
4 * @size: size of driver private data, can be zero
5 * @dev: pointer to the device for this fb, this can be NULL
6 *
7 * Creates a new frame buffer info structure. Also reserves @size bytes
8 * for driver private data (info->par). info->par (if any) will be
9 * aligned to sizeof(long).
10 *
11 * Returns the new structure, or NULL if an error occured.
12 *
13 */
14 struct fb_info *framebuffer_alloc(size_t size, struct device *dev);

 

調試

pc-linux:

cd /work/system/linux-2.6.22.6/

make menuconfig

(lcd驅動以模塊方式編譯)

make uImage

make modules

cp /work/system/linux-2.6.22.6/drivers/video/cfbcopyarea.ko /work/nfs_root

cp /work/system/linux-2.6.22.6/drivers/video/cfbfillrect.ko /work/nfs_root

cp /work/system/linux-2.6.22.6/drivers/video/cfbimgblt.ko /work/nfs_root

cp /work/system/linux-2.6.22.6/arch/arm/boot/uImage /work/nfs_root/uImage_nolcd

   

board-u-boot:

nfs 30000000 192.168.0.103:/work/nfs_root/uImage_nolcd

bootm 30000000

   

board-linux:

mount -t nfs -o nolock,vers=2 192.168.0.103:/work/nfs_root /mnt

cd /mnt

insmod cfbcopyarea.ko

insmod cfbfillrect.ko

insmod cfbimgblt.ko

insmod lcd.ko

echo hello world! 2019/10/18 > /dev/tty1

   

cat test.bmp > /dev/fb0

   

vi /etc/inittab

#+++

tty1::askfirst:-/bin/sh

   

reboot

insmod buttons.ko

insmod cfbcopyarea.ko

insmod cfbfillrect.ko

insmod cfbimgblt.ko

insmod lcd.ko

   

<input way:key>

KEY_L KEY_S KEY_ENTER(ls'\n')

相關文章
相關標籤/搜索