|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
貌似好久好久没写驱动类的博客,距上一次写驱动的博客还得回到半年前,那时天气还很冷,如今已经热的要命,但我还是想把自己学习到的知识跟大家分享。没写驱动类的博客是觉得Linux下的驱动源码真是太多太多了,半年前我也比较害怕Linux源代码,随时时间的推移,自己琢磨了不短时间了,觉得大概能读懂Linux源代码了,也就没那么害怕它了。
& P( U# X" E C, Q: v
: r' v7 g9 b! O2 K原归正传,预定以后的驱动博客我想用尽量短篇幅来记录,但是会以尽量详细的角度去分析驱动。学习驱动心得,驱动呢主要还是要抓住主干的架构,太细节的东西不必太刻意去研究,因为很多太底层的函数人家已经帮你实现了,你不必去怀疑它正确与否。/ b) [! R" c' N8 Y @
+ [ M6 G- j+ B
LCD驱动里有个很重要的概念叫帧缓冲(framebuffer),它是Linux系统为显示设备提供的一个接口,应用程序在图形模式允许对显示缓冲区进行读写操作。用户根本不用关心物理显示缓冲区的具体位置及存放方式,因为这些都由缓冲区设备驱动完成了。4 J$ Y) V: h+ J9 c" s9 F5 U; E
8 z; V7 v9 @: J; R {0 e1 _/ W启动开发板后执行ls /dev/fb* 命令可以看到,帧缓冲设备的主设备号为29,对应/dev/fbn设备文件,一般为/dev/fb0
" `1 j2 w3 G3 \: v H4 M
- P0 g) N" `$ ?; ~4 P d& A在弄清楚LCD驱动架构之前,我们先弄清楚几个重要的结构体,为了减短篇幅,有一些不是很重要的成员会用省略,具体的源代码请大家参考Linux源代码,这里我使用的源代码是天嵌公司提供的移植好的Linux-2.6.30.4。& Q4 z, M* T8 t
/ a D' z+ C$ j8 x: z8 p
1.fb_info结构体(在include/linux/fb.h文件里定义) c( G r& { g
4 d2 [& P$ Y5 D h/ Zstruct fb_info {; ?2 ]8 H( a O3 L0 |9 X
int node; /* 序号索引值,/dev/fb0,/dev/fb1 其中0,1 就是从这里获得的*/
, J) R4 Y% R* T/ [int flags;* T3 R. }% c) U& m7 ?7 Q
struct mutex lock;/* 一般在 open/release/ioctl 函数里会用到的锁 */+ s3 ?9 R: H( W1 x: j8 ~% R
struct fb_var_screeninfo var;/* 可变参数,很重要 */
1 i( ]: o! E6 t: B* r$ t) Xstruct fb_fix_screeninfo fix; /* 固定参数,很重要 */, a& l! Y( E9 [. F4 K4 _; f, I
struct fb_monspecs monspecs;/* Current Monitor specs */( t' u7 C, G/ F2 ^/ E0 V- G
struct work_struct queue; /* Framebuffer event queue */
, X8 Y$ ?$ {. E6 C/ i; o% [- X2 sstruct fb_pixmap pixmap; /* Image hardware mapper */
# p. [+ \7 [8 ^, sstruct fb_pixmap sprite; /* Cursor hardware mapper */0 g2 B) {$ {, F2 H( D
struct fb_cmap cmap; /* Current cmap */
: r, Q' W/ g5 @/ B) Ostruct list_head modelist; /* mode list */
- \& N0 ?* c) L. a( Ustruct fb_videomode *mode;/* current mode */4 c8 J' `' f# F
8 ? S' M B( m/ b% [
。。。。。。+ K( V3 k! T4 x7 P
1 ^) @$ q; S( D% {% f
struct fb_ops *fbops;/ P2 x. S" C& i9 r6 @
struct device *device;/* This is the parent */
3 k1 t9 D0 m D2 pstruct device *dev;/* This is this fb device */6 W1 X% W" j2 z- f
. ~. {; Z6 g4 ~2 U* E4 Q。。。。。。& } g; c, r5 D6 V8 u& e% R1 v, B
char __iomem *screen_base;/* "显存“的基地址 */
3 m8 c# C$ G0 p; I- M3 w5 lunsigned long screen_size; /* ”显存“的大小 */ 7 n C1 c: y. D
void *pseudo_palette; /* 16位假的调色板 */
) [& | O" P1 B' e2 u#define FBINFO_STATE_RUNNING 0
9 S+ c5 k, z5 w% ^4 ?3 C#define FBINFO_STATE_SUSPENDED 1/ q1 v: x- [8 @" S/ H ?
u32 state; /* Hardware state i.e suspend */* X+ G" I1 k, {* W- v5 C
void *fbcon_par; /* fbcon use-only private area */
4 n4 E: n! O/ o7 _% v/* From here on everything is device dependent */
* l6 Y" Z8 U( ~void *par; /* 这个用来存放私有数据 */. a3 S( |+ {% V0 I! _' L) e
};4 ^6 N6 c L0 ?6 G; z- [3 A6 H
$ p1 h' N- C8 E$ M6 z
2.fb_ops结构体(在include/linux/fb.h文件里定义)6 M% C2 A# ]: p* H' y' i" U
- a v1 h6 G8 Z0 S; q: \. Z考虑到fb_ops结构体里面的函数指针成员太多,这里仅简单列举几个比较常见的,具体的请参考源代码。
4 X6 k8 l) H: K) s: f6 l, q3 k6 R1 ~3 A
0 W: f7 q8 M0 }5 Q( B! kstruct fb_ops{
0 C3 v7 o. Q' Y1 ]& k4 {6 Q6 Estruct module *owner; /* 模块计数 */
9 g5 B' H+ Z0 o5 q& U Z/ iint (*fb_open)(struct fb_info *info, int user); /* 打开函数,第一个参数为fb_info */: p# x: L5 h7 _! B4 q
int (*fb_release)(struct fb_info *info, int user);
) T9 ?( v7 V7 T3 C5 C。。。。。。
) I, e0 \9 ?* p6 k/ _" F/* fb_check_var函数用来检查可变参数,并调整修改可变参数 */
' m" k: L3 t" d1 Z! p- gint (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
' ~5 j- C f8 [' h4 n1 D2 Q。。。。。。3 V, K5 c( y# O( |
/*fb_setcolreg函数就是用来设置fb_info里面的pseudo_palette调色板成员 */+ a$ [; A! }1 p K' y
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
8 g0 m" y9 @# w. L7 x4 o unsigned blue, unsigned transp, struct fb_info *info);$ A; u" ]* z3 ?; i6 e+ v/ E
。。。。。。
3 o5 e1 {* {' q2 y; D: e3 B5 f9 @! q& v1 s
/* 下面三个是通用的函数 */0 a& ^1 {3 {% f- D d# T( @
/* Draws a rectangle */
8 I$ F- V. c L d7 {void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
1 \2 L* {' P0 k/* Copy data from area to another */
: ]* ~/ b8 s9 O) Q( svoid (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);, ?2 \( ?# ]2 B0 P% z9 I
/* Draws a image to the display */
7 e0 t- ]; Y$ D1 `3 }( Xvoid (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);/ L+ k6 T4 b1 Z) I! U
。。。。。。
( z# D$ A# c8 K% _( h! A( M; P/* 有了fb_ioctl应用层可以通过ioctl系统调用来设置屏幕参数等 */
M+ P( e; N* tint (*fb_ioctl)(struct fb_info *info, unsigned int cmd,9 ^3 K* e- v! R* ~ V$ |) ~, ~
unsigned long arg);
7 m- G# Q [9 T& _6 q1 h- P。。。。。。; T, @% K& I3 K+ l( Z" X
/* 有了fb_mmap应用层可以通过mmap系统调用来读写帧缓冲区内存 */
8 @* d# @0 | R, s* l) Wint (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
6 L0 R- H" x# q# {! S3 ?3 c。。。% S9 U+ A7 \ C* @4 D
};7 b/ y( y% }5 [: n. q$ r; ~
$ i* d1 z; V3 i, Q
3.fb_var_screeninfo 结构体(在include/linux/fb.h文件里定义)
( S$ g7 M& t# s O# w" v c9 _( N3 a& R
fb_var_screeninfo 被fb_info结构体所包含,这个结构体主要用来设置LCD屏幕的参数,如分辨率、像素比特数等,LCD驱动程序里面硬件相关的设置很多都涉及这个结构体。8 ?* C9 C0 w q/ a
$ t5 N$ h; T, D; Y Hstruct fb_var_screeninfo {
! |+ e6 W2 o* \8 A+ N4 o2 G) \6 a2 G__u32 xres;/* visible resolution,分辨率,即一行有多少个点 */' C; B1 }7 u3 q4 K1 |! ?" P
__u32 yres;* P! l$ A Q$ u/ a, K
__u32 xres_virtual;/* virtual resolution*/
; i9 O) G+ H4 Z__u32 yres_virtual;: ^) m% o( U1 E7 D
__u32 xoffset;/* offset from virtual to visible */, x! _/ j% k7 b9 M& F$ y
__u32 yoffset;/* resolution*/1 p( @8 I8 ^: n0 [
2 o0 d7 N! ^: V$ {3 B! a; Y4 i' v! B$ E F& r" a0 M8 Q
__u32 bits_per_pixel;/* guess what,定义每个点用多少个自己表示 */
7 [1 ]3 t% E# V/ M' p__u32 grayscale;/* != 0 Graylevels instead of colors */
& Y A. E& r2 B0 p* `9 | h# U
( R: a( ?* _( M/ [- y! W& f w9 B/ X/ g3 G& a6 l$ C
struct fb_bitfield red; /* bitfield in fb mem if true color, */8 c( Q. @: B( |& }3 g
struct fb_bitfield green; /* else only length is significant */" K1 N$ F0 s7 N8 W0 G2 x4 S) t
struct fb_bitfield blue;+ e( q# w: Z! o5 w9 K- ~
struct fb_bitfield transp; /* transparency*/
4 K. h8 T& ~# m6 q9 w! M: B z8 [8 ~) y$ b
! y6 F, {. M& A: }5 h
__u32 nonstd; /* != 0 Non standard pixel format */
5 z5 S8 g5 O+ Y4 g9 t5 q/ h9 J$ q/ j K
( W9 H1 U$ N. l9 ]' ?) v__u32 activate;/* see FB_ACTIVATE_**/
" \& K( m9 g% }! t# Y9 Y, W" Q( \2 C8 e; h4 ?$ T1 q/ m
) f4 Q2 N1 k' ^" E__u32 height;/* height of picture in mm */+ i+ B, F8 T' y3 a1 {7 g& m
__u32 width;/* width of picture in mm */
) [ |; @- S O7 p* S; s1 m5 l! c' t0 A
U& N% e4 D4 T% @
__u32 accel_flags;/* (OBSOLETE) see fb_info.flags */
0 w( h, x) u1 r+ z' i# z
- a3 e5 M1 d1 p; I9 j- R2 m3 v8 L9 k" h5 M0 |' J) ?. p
/* Timing: All values in pixclocks, except pixclock (of course) */4 K! l! m& `' v* T' \) H) ~
__u32 pixclock;/* pixel clock in ps (pico seconds) */$ x8 M! ]5 U$ G; L1 `
__u32 left_margin;/* time from sync to picture*/
/ i9 B T& v& @8 q/ m__u32 right_margin;/* time from picture to sync*/* s3 z( g; V$ @$ P) r2 [6 Y
__u32 upper_margin;/* time from sync to picture*/) G8 _1 k+ \& Y4 W: S- i% s) t& Z0 [
__u32 lower_margin;
) l) ~& A" S! Z0 D0 D__u32 hsync_len;/* length of horizontal sync*/ j' n/ H. I: w( B5 Z( S
__u32 vsync_len;/* length of vertical sync*/$ G& K6 J& l' F# A' W
__u32 sync; /* see FB_SYNC_* */( ?& u, S8 u8 T$ n# L) Y
__u32 vmode; /* see FB_VMODE_* */
+ F; M2 I6 Y7 [. g8 e__u32 rotate; /* angle we rotate counter clockwise */
3 _7 Q9 i- Q% ]4 d% E* B__u32 reserved[5];/* Reserved for future compatibility */) C+ r0 P9 c: o& x J7 I; ]: {% n
};6 ?( L0 }) U0 a$ y4 V4 t" e( Z
5 _ x, X$ q/ w/ z& H: F' t- C
4.fb_fix_screeninfo 结构体(在include/linux/fb.h文件里定义)
1 q/ w1 K# y2 X) {3 `' {$ \$ E" o
( X# J6 @( A3 n1 o; Jstruct fb_fix_screeninfo {& \+ P2 g$ m( I6 s
char id[16];/* 驱动名字就保存在这里*/
. C5 C$ i& j7 t! g0 [unsigned long smem_start; /* fb缓冲区的基地址,这是一个物理地址 */# b" Q$ r% |' [9 {9 c. i
__u32 smem_len; /* fb缓冲区的长度 */) S7 q$ y, W" g& |3 g
__u32 type; /* FB_TYPE_类型*/
- b# m, I( i! L: A& w__u32 type_aux;/* Interleave for interleaved Planes */
& C/ |4 n8 ~+ X" g9 ^__u32 visual;/* FB_VISUAL_类型*/ / u: H' \4 @0 R8 m0 U
__u16 xpanstep;/* 一般设置为0 */
9 l- G8 l& G3 p" [__u16 ypanstep;/* 一般设置为0 */
) P) k2 ?1 w% }- u. J2 A0 D9 k, x2 l__u16 ywrapstep;/* 一般设置为0 */# S3 |+ ~' w6 O
__u32 line_length;/* 屏幕一行有多个字节 */6 g3 F; j6 B0 o, m/ S
unsigned long mmio_start;/* Start of Memory Mapped I/O */
; X# ?" h S+ |- n4 `/* (physical address) */
9 z; @4 b) l3 C; Q" P# y__u32 mmio_len;/* Length of Memory Mapped I/O */( k$ a! G9 }% w0 o
__u32 accel; /* Indicate to driver which */; h- C7 V1 j& y
/* specific chip/card we have*/; g. q- @! o0 y$ I
__u16 reserved[3];/* Reserved for future compatibility */5 d) v# U$ r; m$ ^
};9 S. ]% K; R6 c6 f# B3 B
N8 ]* I4 S0 L. ]
以上笼统的介绍了几个重要的结构体,大家如果没有阅读过源码的可能对这些结构体比较陌生,但是没关系,比较常用的我都用显眼的颜色标记了,大家结合以后的博客日志就会懂这些结构有什么作用了。; K7 D4 M& q3 E9 B4 _" ]
5 J2 r) A4 E' ?) F5 { n; ~2 f对于这些参数会在哪里设置?通过什么样的形式来设置?
1 U4 |- e3 ~# u& W( @ |# H
# n, c1 ^6 P: W4 N6 ?! t答:通过平台设备的方式来设置,这就是鼎鼎有名的platform_device结构体了,这个知识留到后面的LCD驱动篇来讲解。- @ o- D; G( B! T6 f; n
# b$ |% ~! h( A; S, k, k
+ v/ ?: U; d$ _2 i! H6 g3 J" A% _8 f2 E8 F# |& `+ B- T( ^+ L
|
|