找回密码
 注册
关于网站域名变更的通知
查看: 246|回复: 2
打印 上一主题 下一主题

详细分析一下Linux下LCD驱动

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-4-22 10:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
    貌似好久好久没写驱动类的博客,距上一次写驱动的博客还得回到半年前,那时天气还很冷,如今已经热的要命,但我还是想把自己学习到的知识跟大家分享。没写驱动类的博客是觉得Linux下的驱动源码真是太多太多了,半年前我也比较害怕Linux源代码,随时时间的推移,自己琢磨了不短时间了,觉得大概能读懂Linux源代码了,也就没那么害怕它了。
: H" Q" l( M5 E: G5 q6 \: {+ r+ N5 t0 ~
原归正传,预定以后的驱动博客我想用尽量短篇幅来记录,但是会以尽量详细的角度去分析驱动。学习驱动心得,驱动呢主要还是要抓住主干的架构,太细节的东西不必太刻意去研究,因为很多太底层的函数人家已经帮你实现了,你不必去怀疑它正确与否。
( `* p; y' Z& E7 I) E/ v: |2 M+ U  Y2 |& m. A: ~
LCD驱动里有个很重要的概念叫帧缓冲(framebuffer),它是Linux系统为显示设备提供的一个接口,应用程序在图形模式允许对显示缓冲区进行读写操作。用户根本不用关心物理显示缓冲区的具体位置及存放方式,因为这些都由缓冲区设备驱动完成了。- d9 |  Z5 b* q
' a. S$ l. W. W7 Q: D) R* Y5 L4 j
启动开发板后执行ls  /dev/fb*  命令可以看到,帧缓冲设备的主设备号为29,对应/dev/fbn设备文件,一般为/dev/fb0
: l! c6 C. K$ r% g" g0 k4 ^' W8 U( u# {2 i
在弄清楚LCD驱动架构之前,我们先弄清楚几个重要的结构体,为了减短篇幅,有一些不是很重要的成员会用省略,具体的源代码请大家参考Linux源代码,这里我使用的源代码是天嵌公司提供的移植好的Linux-2.6.30.4。8 }& y& Z& W  R
# l. p5 |( u: F9 R. W; i
1.fb_info结构体(在include/linux/fb.h文件里定义)7 c& f! z1 Y7 R1 U3 r' D

, `- u4 }7 j/ p4 @' n# bstruct  fb_info {
/ h& r) W- {: V+ ^% G9 x& z* Iint node; /*  序号索引值,/dev/fb0,/dev/fb1  其中0,1 就是从这里获得的*/; w: I8 a6 `0 C' z
int flags;
& c& B9 L) g& C& a* c3 ]+ sstruct mutex lock;/* 一般在 open/release/ioctl 函数里会用到的锁 */8 ]- g& q1 a2 h7 ^3 M
struct fb_var_screeninfo var;/* 可变参数,很重要 */
9 y5 a6 S+ P$ X* A; }struct fb_fix_screeninfo fix;       /* 固定参数,很重要 */7 J3 ~  d7 Y7 _7 j
struct fb_monspecs monspecs;/* Current Monitor specs */
. X+ b! ]( O4 Jstruct work_struct queue;       /* Framebuffer event queue */
" w; s2 ?, H3 X$ vstruct fb_pixmap pixmap;       /* Image hardware mapper */  C+ P4 Q! S; m. ^$ F
struct fb_pixmap sprite;       /* Cursor hardware mapper */( V& y0 F0 C7 C
struct fb_cmap cmap;       /* Current cmap */) l0 A$ `3 a; ]% T# \! Q* j
struct list_head modelist;              /* mode list */9 d7 e$ D  V/ R1 R9 `$ o
struct fb_videomode *mode;/* current mode */
! @# [0 t. D$ s1 `9 M; z& x' e: Z: v8 n$ k* G, l1 j
。。。。。。
, J) C6 V; M5 @+ [' w7 H& o# }: v
6 m' C; ~: {7 _, B$ ^: hstruct fb_ops *fbops;# I- J- u: l, E: H! e
struct device *device;/* This is the parent */, k# ]  }9 y) e5 k6 F% N
struct device *dev;/* This is this fb device */9 T/ H6 B# T, x* N2 ^
: J/ U6 b; y: Q% k
。。。。。。
; ]; i" G7 m- @; Z; S& b4 b# T7 cchar __iomem *screen_base;/* "显存“的基地址 */
9 u! Q; V: x" j9 e( p2 k' Vunsigned long screen_size;       /* ”显存“的大小 */ 9 ^8 N- {: U9 g
void *pseudo_palette;      /* 16位假的调色板 */ 9 M! ]. o' Y" F& ]- D/ t$ W% J
#define FBINFO_STATE_RUNNING 04 a, Z2 U5 x! g4 j) M
#define FBINFO_STATE_SUSPENDED 1( q9 {* _( _7 Q6 f4 ]& a
u32 state; /* Hardware state i.e suspend */
  q( M8 f2 U; T" ivoid *fbcon_par;                /* fbcon use-only private area */  @: Y' A1 U( h4 g' z8 }
/* From here on everything is device dependent */
* F5 x% e, b7 Z& ?! k/ V, i/ Ivoid *par;   /* 这个用来存放私有数据 */
! n) j; t' ^) `+ q};
7 ?2 w- ]8 L( h( G/ U: h: R5 v4 Z+ u& i
2.fb_ops结构体(在include/linux/fb.h文件里定义)
  A5 M3 a3 n+ n. z# R, [/ j' p! O" a
考虑到fb_ops结构体里面的函数指针成员太多,这里仅简单列举几个比较常见的,具体的请参考源代码。4 U8 T  j. ~( z+ ~3 |8 J" N
# ]  L, a9 H) t3 G0 x, ~. ]
struct fb_ops{; m: f' M2 I, {8 T5 X
struct module *owner;  /* 模块计数 */
- J( i5 t1 E/ B; T7 P- _int (*fb_open)(struct fb_info *info, int user);           /* 打开函数,第一个参数为fb_info */
0 t, T( H1 p3 T/ Y* F) Xint (*fb_release)(struct fb_info *info, int user);
6 }0 d: N$ A5 a2 r. N; b。。。。。。( V2 {# p1 V( w- I5 B- \! ~* j8 W) N
/* fb_check_var函数用来检查可变参数,并调整修改可变参数  */1 k1 {$ v. H+ y( D2 P) h
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);8 y; r# s! I$ V3 Y
。。。。。。
  H  ^6 k( O* {4 U' T2 ~/*fb_setcolreg函数就是用来设置fb_info里面的pseudo_palette调色板成员 */  X! h# X+ N. X) p3 z6 |8 `' Z% }
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,# M+ k+ {, I6 F% O6 y
   unsigned blue, unsigned transp, struct fb_info *info);
, k! M' ^. `) g。。。。。。' g7 @  B. |1 q6 n' t' s9 h6 V

; h# N/ r6 W* m  Y& g" L7 r3 C/* 下面三个是通用的函数 */
  j0 N& o  W1 x( u/ J) S4 k/* Draws a rectangle */
. g# ^0 T" g" ~; p& u5 a4 O6 Evoid (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);& {! K# T7 k. m+ ?  v- g, J
/* Copy data from area to another */
7 r0 B' t' B* q! n% f3 |3 Qvoid (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
. u7 r9 ~; y* {1 ~/* Draws a image to the display */0 Q4 ]  P6 ?2 v: ~; y0 w2 ^1 D
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);: w# ^2 d! T2 K6 q4 R  r
。。。。。。6 p0 M; ]- m. N9 K# k
/* 有了fb_ioctl应用层可以通过ioctl系统调用来设置屏幕参数等 */
" M& f& n5 L6 t2 X0 a5 n) \( ~int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,* v2 R. y: N2 I  o: f7 J6 s
unsigned long arg);
6 ^1 m1 W( v6 o1 Q) E$ B。。。。。。1 [: V- s* j# D  J  y- h5 Q
/* 有了fb_mmap应用层可以通过mmap系统调用来读写帧缓冲区内存 */
! X6 D; ?) i. cint (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);# z5 @0 v8 _  C% v0 u, L" ^4 e% r
。。。- Z& Z% _' ?5 Q& o3 R% C9 o
};
5 ?; B/ K- @5 T4 R/ w% ]
* J! E% E5 g9 f" s; b3.fb_var_screeninfo 结构体(在include/linux/fb.h文件里定义)$ ~" J4 G' U" J( O9 m* L

+ J1 c" H' p0 v6 g7 h/ \; E: T* n2 U+ {fb_var_screeninfo 被fb_info结构体所包含,这个结构体主要用来设置LCD屏幕的参数,如分辨率、像素比特数等,LCD驱动程序里面硬件相关的设置很多都涉及这个结构体。
* |1 S; x( u' D/ q3 q, N, G) y) M$ Q+ z" O
7 e# d: Q! R4 Y- F# ~6 Astruct fb_var_screeninfo {& c  ]" ?1 M: x* q- r3 P! c8 i
__u32 xres;/* visible resolution,分辨率,即一行有多少个点 */
! ^" P0 ]. `! m9 _+ A6 H. e$ T! R; z__u32 yres;
. B0 |+ B1 v' B% R" y2 r7 `__u32 xres_virtual;/* virtual resolution*/
' l! C+ K3 c% U9 }: {__u32 yres_virtual;
7 @$ Z) r6 ^* ~7 a1 e' p__u32 xoffset;/* offset from virtual to visible */
* ]$ f+ I/ Z' O+ C) a! S, Y1 E- {__u32 yoffset;/* resolution*/" s& w1 k  {- g. M

/ ^6 ~- ^' E5 n. Q( M
+ J3 ~/ D& p9 j* E. w: F__u32 bits_per_pixel;/* guess what,定义每个点用多少个自己表示 */
+ Z: m* d- B* e7 A2 X6 f, T, f__u32 grayscale;/* != 0 Graylevels instead of colors */
  g% M* Z) i. j, }6 u# Y; h" Q5 H) I( [* j2 \$ l7 S
4 Q: d. X( F0 V2 ^. W0 p
struct fb_bitfield red; /* bitfield in fb mem if true color, */
! }! C: r9 c; E  ?( sstruct fb_bitfield green; /* else only length is significant */
) D9 V3 Z: \! o( Z( ]& Y+ fstruct fb_bitfield blue;! B2 Q. T+ L+ B) r  }1 W
struct fb_bitfield transp; /* transparency*/
% n2 Q& v1 Y3 T# }/ M! o
* [1 k- h6 h! t9 z8 G6 {& M8 P9 e8 t
__u32 nonstd; /* != 0 Non standard pixel format */( f* A. C: k" w  p
) e: [6 j9 a  T& w
# C( A2 h2 D/ G& k% ^: f
__u32 activate;/* see FB_ACTIVATE_**/
+ X2 [+ W5 f& o) k( R
* F0 y! N% @- d# `+ T8 s5 y" W$ t( a8 N: q0 h" l
__u32 height;/* height of picture in mm    */8 e0 w* O3 C: o; ]
__u32 width;/* width of picture in mm     */
( k0 C; A0 n, g  _' ~
# ~" q5 X* G- Z& @9 k
  D* v0 h6 m* z, b( n% B__u32 accel_flags;/* (OBSOLETE) see fb_info.flags */8 h% S$ _3 T4 L9 }

6 H  S* r% v: p) \% Y/ k/ C/ x$ y# r0 L
/* Timing: All values in pixclocks, except pixclock (of course) */
/ P' f) w+ G* p1 Q" T' z7 |__u32 pixclock;/* pixel clock in ps (pico seconds) */
7 f' f4 F' h5 I9 M__u32 left_margin;/* time from sync to picture*/7 R0 N) ~$ R* K
__u32 right_margin;/* time from picture to sync*/
0 B$ `9 ]5 D! q__u32 upper_margin;/* time from sync to picture*/
* ]- U# P2 A: L5 ~3 g; L__u32 lower_margin;) O8 H. L% \! S' u3 \0 s
__u32 hsync_len;/* length of horizontal sync*/# b. b2 l1 \& q+ P6 S* ^9 F% y
__u32 vsync_len;/* length of vertical sync*/5 O6 |% S4 \" J" V( _0 `# K- `3 K$ R
__u32 sync; /* see FB_SYNC_* */
6 U% n; B0 W" r# g/ r) W( Z4 G__u32 vmode; /* see FB_VMODE_* */. U) m2 K! x! {& T& I/ {% d( S
__u32 rotate; /* angle we rotate counter clockwise */
9 n, X+ U6 K0 a- G( Z0 L9 W__u32 reserved[5];/* Reserved for future compatibility */
" o# V. G/ T/ _! Q- m; S7 N* K/ v2 t};
3 [9 R: @7 `) {! T( K, `' Q4 A! S; a  J7 G3 E4 w. _' x
4.fb_fix_screeninfo 结构体(在include/linux/fb.h文件里定义)
5 N! T. O2 I% j) Q0 [) q- Q( v" [% T" x8 {% L1 P$ K0 c
struct fb_fix_screeninfo {
# O/ U" @6 Y3 r% @0 d$ U5 dchar id[16];/* 驱动名字就保存在这里*/
4 O- g6 t" A4 i) O: Junsigned long smem_start;       /* fb缓冲区的基地址,这是一个物理地址 */" A5 Q: x* x" W. Y3 l8 k1 |- |7 G' C
__u32 smem_len;       /* fb缓冲区的长度 */
8 W+ c6 H" \: k! W' ^__u32 type;              /* FB_TYPE_类型*/
: c6 D4 h5 p/ w' \5 r__u32 type_aux;/* Interleave for interleaved Planes */
4 i! o& {0 `' N/ t. x* z: E3 u5 q2 M+ }__u32 visual;/* FB_VISUAL_类型*/
( w1 A3 u8 ?: S( Y+ @6 P/ z  m- ?__u16 xpanstep;/* 一般设置为0  */
/ k- e1 Z/ ^6 d& s$ O__u16 ypanstep;/* 一般设置为0  */* p; p  Z2 j. c# H  C( I% K
__u16 ywrapstep;/* 一般设置为0  */$ L, {. i, y/ c; `" O
__u32 line_length;/* 屏幕一行有多个字节    */
  T. |6 j" v# Z& d3 u1 C3 _unsigned long mmio_start;/* Start of Memory Mapped I/O   */$ J" ]) O7 w7 n- E. l3 p3 d
/* (physical address) */% K& W3 J2 {5 }# |- B/ l
__u32 mmio_len;/* Length of Memory Mapped I/O  */3 B- A" O" X6 o# Z5 S
__u32 accel; /* Indicate to driver which */
. s0 u6 E' j  i- F/*  specific chip/card we have*/
' f/ ~4 L7 D; p8 T7 w__u16 reserved[3];/* Reserved for future compatibility */9 I" R: i/ E# j5 f" ~9 Q
};' _6 z, S$ x9 [

& q4 U$ y' H! z以上笼统的介绍了几个重要的结构体,大家如果没有阅读过源码的可能对这些结构体比较陌生,但是没关系,比较常用的我都用显眼的颜色标记了,大家结合以后的博客日志就会懂这些结构有什么作用了。! |$ ~8 X6 W! I

1 |. M1 n9 X5 x7 g5 c' C, R对于这些参数会在哪里设置?通过什么样的形式来设置?
' l7 \5 R! |7 P. p! }$ L+ i/ w! C* r8 N
答:通过平台设备的方式来设置,这就是鼎鼎有名的platform_device结构体了,这个知识留到后面的LCD驱动篇来讲解。4 c2 O3 v& p# o# l- L$ G7 r

2 n, y( B) I* {  Z/ j  ^& X3 ]' M9 k6 {

. u8 w4 r4 s, a) \

该用户从未签到

2#
发表于 2020-4-22 13:29 | 只看该作者
Linux下LCD驱动

该用户从未签到

3#
发表于 2020-4-23 13:38 | 只看该作者
Linux下LCD驱动
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-4 17:27 , Processed in 0.125000 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表