TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c, y$ Y/ S. f6 v1 M; n C
6 _- K3 F# [0 i6 b7 y* K
看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数" _6 l$ a; j/ t4 ?+ f8 U, _
3 L2 z) T. [# A) V: D5 [# H1 Z5 h, k% Y3 g) D& ?
int __init s3c2410fb_init(void)$ j- A. J' i7 Q& f
{& w! w- A% h. K6 h4 M2 s% {8 s
/* 注册一个s3c2410fb_driver平台驱动 */, l" A5 o; R( w, D9 h2 f
int ret = platform_driver_register(&s3c2410fb_driver);
N' ^) i( O9 \% F {' s
6 C% j$ ]/ R5 h% O if (ret == 0)
3 k M$ }% B! k) m" d7 b ret = platform_driver_register(&s3c2412fb_driver);;) J/ y( b9 A. T$ K8 b$ h; {
% s! n2 C/ d& |7 I( L# a return ret;
) ?+ V+ S+ _2 _( l3 x. D8 Y6 T}) D! N( y6 j: K
出口函数,自然是注销s3c2410fb_driver平台驱动
1 [ s! @1 d/ P2 I+ [0 W; m% X; L$ u5 g) O6 W. N
static void __exit s3c2410fb_cleanup(void)
; @$ A4 B. S" }4 U{1 @1 }: H, Z; @$ t! q
platform_driver_unregister(&s3c2410fb_driver);
2 x+ [. X; `8 k! z! S2 ? platform_driver_unregister(&s3c2412fb_driver);
% _- b5 X. L* n# J" o9 j$ k! p' k5 Q}; l6 n- _( g B9 F
我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
8 b4 z1 I( P+ q1 w- {6 t7 O
, _- @3 H% e6 o0 Pstatic struct platform_driver s3c2410fb_driver = {
4 d! D, w8 h' P7 [& V .probe = s3c2410fb_probe,( @9 |% z9 ]2 O2 I0 B
.remove = s3c2410fb_remove,
5 t) G+ }, g* J8 I0 h3 c( W! W; _1 h .suspend = s3c2410fb_suspend,
) x( ~. \) N+ W$ [8 N% @5 K" w, r .resume = s3c2410fb_resume,
9 A% W* h. _" y# y) T8 f# m, x" \: [ .driver = {6 U5 j6 Z' f. @+ M7 u
.name = "s3c2410-lcd",
0 l- q W9 W* ?$ p U% v- Y2 m: S7 H .owner = THIS_MODULE,
0 E& |" L2 _" e( h2 H% N },) Z8 S# W, w, x+ H" V5 p. {, k% X- ~
};
9 L/ b) ?3 b2 @6 {9 M1 `5 H这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。
7 \. n# T8 U9 Y: C! R在source insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段
3 |/ [5 Z2 t* @5 @3 T
- l- W# j" \5 ]2 f7 K, K
2 w9 _/ G" F9 W+ r. Kstruct platform_device s3c_device_lcd = {
, d* d7 C+ I% D) x* ^6 ? .name = "s3c2410-lcd",/ s' y: r1 v4 y
.id = -1,* K" ]" P i/ s( q5 b, g; @
.num_resources = ARRAY_SIZE(s3c_lcd_resource),
. [ G' O* E+ s' s .resource = s3c_lcd_resource,0 t- @% m% I; L* o# x
.dev = {
8 A7 C& w+ @- u. b7 T) g) t .dma_mask = &s3c_device_lcd_dmamask,* }- Q' I8 h9 \, ?
.coherent_dma_mask = 0xffffffffUL
. \* Q# ]1 d: n( V/ H! o }0 V5 N: S! H* y. f, D- i' [( v
};9 w5 I2 b7 v! }& z; U4 h# p
/ e2 _; D. J$ j; I6 qEXPORT_SYMBOL(s3c_device_lcd);1 }( Q" J2 P/ w, a. {( U# D2 N
其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource: c0 C* [9 ~8 a0 o! t! c) u
3 _: O4 {7 C) z0 l
static struct resource s3c_lcd_resource[] = {+ r: g! _/ q% _' y+ j, q4 i
[0] = {
7 i' D# A) r* N6 V .start = S3C24XX_PA_LCD, /* 0x4D000000 */
3 q0 D, e n% W. _! J .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,( V- g0 z- U' [8 t. h
.flags = IORESOURCE_MEM,! ^. s3 {0 ?8 [5 V& M+ i
},4 n8 |, c; n5 r4 h" t+ W
[1] = {2 r, v0 h; n& V8 b8 ^
.start = IRQ_LCD, /* IRQ = 32 */' N: q2 X b! ~( n. N$ j: J( I
.end = IRQ_LCD,
/ \$ j% C7 u8 Y9 X, |- I1 | .flags = IORESOURCE_IRQ,
2 r. {& C, m4 ]* Y9 [0 @( e+ p* ^9 S/ G }$ @5 Q+ W5 @( X- A3 k" T
. O' A: a, J3 _: ?
};
M* Z* y$ J+ K/ c0 P9 q- i
, m b+ `0 ]" W4 s2 J1 z# ]static u64 s3c_device_lcd_dmamask = 0xffffffffUL;0 \- B2 J8 U+ H" O6 g
那么接下来当然是要分析probe函数了9 v6 K9 Q3 j. [5 E7 K _( X9 q
! X/ G( ?, p7 S8 Lstatic int __init s3c2410fb_probe(struct platform_device *pdev), s3 Z1 j) {9 | d' I1 f/ o5 G
{
" X4 |; o v d4 @ return s3c24xxfb_probe(pdev, DRV_S3C2410);
! O. p! Q( l. L4 o p: p}
+ q5 o8 V' k! Ps3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。* H, U# n% N7 J# k# x0 f
linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
6 |* o" r4 O- e8 `0 e3 d8 V/ \
5 o( V1 g: K7 c" i6 b' u. S) i帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
* x4 R2 Y4 [+ J3 r
1 {9 u6 \6 k$ y, j# y2 estruct fb_info {; s0 \5 H% W( a' T2 ~9 m
int node; //用作次设备号索引; v; G: n3 K) n3 P
int flags;
, k/ w, u) `4 i- B struct mutex lock; //用于open/release/ioctl函数的锁9 F, n- M7 O% T. {2 N) q; d
struct fb_var_screeninfo var; //可变参数,重点
/ R# q: |# f* P+ Q# u1 F; I& _ struct fb_fix_screeninfo fix; //固定参数,重点
' k( k$ y) p# l% D struct fb_monspecs monspecs; //显示器标准
+ O3 C* S: k/ I% C" t: T& x, X" U struct work_struct queue; //帧缓冲区队列
5 o/ z* G& m, p struct fb_pixmap pixmap; //图像硬件映射
8 S N3 f' l; v+ E7 m struct fb_pixmap sprite; //光标硬件映射1 s' }) q$ `# C1 C+ w5 n& J
struct fb_cmap cmap; //当前颜色表
" J1 q* \+ {+ _! a" l7 b" G6 F struct list_head modelist; //模式链表3 e& l9 c$ i9 ]/ n; U' k
struct fb_videomode *mode; //当前video模式
) E4 i" m# I& n o% d) `4 Y/ u
! q& }9 H! s5 f; g T char __iomem *screen_base; //显存基地址' G4 c( h9 F' b* j; k
unsigned long screen_size; //显存大小. X3 j f% L& g8 p! {$ ^
void *pseudo_palette; //伪16色颜色表
% p9 T3 u" Z5 b#define FBINFO_STATE_RUNNING 0- j% g* l b; s9 Q5 g& \) r
#define FBINFO_STATE_SUSPENDED 1
0 m1 K* H9 l- n; g3 |* D8 e u32 state; //硬件状态,如挂起
" M1 I5 r9 ^1 u% _* B2 \; ~1 k void *fbcon_par; //用作私有数据区
' y5 Z/ W, H+ k' T void *par; //info->par指向了额外多申请内存空间的首地址
0 y; z. M$ Z2 R6 o% P: F& H};
( K2 \( K( K. E) q8 d6 E6 K% _s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息( a9 H. \$ S* K" o/ J9 c% F7 L
6 {0 y/ m1 h6 i& ]* estruct s3c2410fb_info {
7 D. _; \1 m5 z6 X+ n! M, t- P struct device *dev; //设备 y- N+ \. H7 P& \$ H# ~& F8 C) ^, t
struct clk *clk; //时钟
5 ]4 M/ O& j$ V* Q( N' I3 z/ P/ v+ i/ G$ \
struct resource *mem; //资源
3 X2 Z, _' i- y- r/ f) {1 v" u void __iomem *io; //IO地址7 h! V" ~% V5 t3 D* W# |! l& g
void __iomem *irq_base; //IRQ基数
; P% B. k0 M! m) R7 ?2 z/ }9 {, F% H$ }- t( d' M+ |, M; D. |
enum s3c_drv_type drv_type; //驱动类型,S3C2410或S3C24126 k3 K+ r3 ?+ h! k1 y: a
struct s3c2410fb_hw regs; //s3c2410 lcd硬件寄存器
: }- P) E4 P& G2 k3 _7 v
! I$ g* }& S, M unsigned int palette_ready; //调色板是否就绪标志位$ m( W W5 e" T% d8 y7 d
) ~" L4 W: X: G, o( E0 r
/* keep these registers in case we need to re-write palette */
, `* z" N/ _( a& o5 ^! w u32 palette_buffer[256]; //调色板缓冲区# W L3 k2 Q; X' t+ _; K6 W
u32 pseudo_pal[16]; //伪颜色表
: V" y# y" Y. z3 S};$ F/ ^' [4 O# r8 l+ S b2 C
s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等 U9 _6 Z8 m4 u/ O# w% w
' J8 e7 D& F) g5 h) r5 e
/* LCD description */
5 \4 S6 t5 e; W5 T. tstruct s3c2410fb_display {
( y# P7 X, n- k- g i, U& Y /* LCD type */
! V7 k* Q9 c0 I unsigned type;: E: b! @3 v5 B1 U% u n
' H0 b: M6 ]$ J# m4 @$ s
/* Screen size */, {3 i0 @1 n0 l0 h" p
unsigned short width;3 p0 k3 \! I$ ^' M
unsigned short height;0 Y! Q6 I; s$ o' Y9 y/ J' v$ @
8 q! P' z$ m e$ r* S /* Screen info */
1 Z T- e5 d2 l) N- H. W unsigned short xres;; {* K! Q. T; W( L# f3 C
unsigned short yres;
" _6 w7 F$ ?- x2 _: g unsigned short bpp;
' a+ f7 o- g( G# }+ Z+ b [4 x
0 z2 y7 {' r. P% z# _: A unsigned pixclock; /* pixclock in picoseconds */
$ O9 p/ X, D# u5 t unsigned setclkval; /* clkval */4 h- M4 e% ^! P+ b w1 c9 w
unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
' A; D/ d$ `7 a+ d/ J# S5 | unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */2 B7 G9 h( Y) F: i* q4 ?
unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */% g: O: [7 P1 M" z, G
unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */: U5 T7 p: a# _7 @
unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
( _( n+ p" Z/ b$ J L unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */, ]* ]- y- m& Q2 o0 ?) E- D$ y
2 u6 Y- G* ~7 r4 S9 H2 c /* lcd configuration registers */
2 b6 N8 x- r. l+ F unsigned long lcdcon5;
2 q6 u8 q+ c/ `! r$ J4 m- y4 B: J7 m};- H# k% c$ X) B# d3 }- U# X
对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
* ], y7 U& Q/ \) t n5 \
5 Q- \# U4 @- |0 o- w7 S/* LCD driver info */
9 t7 \1 o4 ~4 ystatic struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
7 E6 Y( z; I9 e( \" m .lcdcon5 = S3C2410_LCDCON5_FRM565 |3 S- k% i; v* @- y$ e
S3C2410_LCDCON5_INVVLINE |( \8 J" C9 z7 w0 @ d: p8 Z1 c0 x
S3C2410_LCDCON5_INVVFRAME |1 j* C( ]( a7 i
S3C2410_LCDCON5_PWREN |! r9 c& I" B z/ N' [) @5 j9 S
S3C2410_LCDCON5_HWSWP,2 }& P% `$ O9 x
.type = S3C2410_LCDCON1_TFT,. R, k0 c0 [# i0 B
/* TQ2440的液晶是4.3寸的,分辨率是480*272 */- ~' E1 U' D3 n+ A( B/ C e
#elif defined(CONFIG_FB_S3C24X0_TFT480272) /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */, v9 J+ f5 M# m" r$ f* W
.width = 480,
/ C: o1 [3 Y5 y8 ~+ h) a .height = 272,5 N: q% D# ~0 k) T
' `; c" @1 t9 I# x8 u .pixclock = 40000, /* HCLK 100 MHz, divisor 1 */* m$ ?- L# P5 X, ]3 L+ D% I9 E b6 v2 }
.setclkval = 0x4,
# c! S! _9 _0 W5 v$ J .xres = 480,
j* D8 w; b0 d .yres = 272,3 S$ W- _, g* P |2 y7 x4 J
.bpp = 16,
8 @4 R2 q' R8 o" M; z X/ | .left_margin = 19, /* for HFPD*/
5 G3 z* e. y3 O3 I .right_margin = 10, /* for HBPD*/" z, \3 _1 ~. f; _& d9 f, q
.hsync_len = 30, /* for HSPW*/' q# R5 L8 F' W
.upper_margin = 4, /* for VFPD*/
* ?3 l, p2 q# u0 ~ .lower_margin = 2, /* for VBPD*/
, S+ {4 m& k7 [% U3 w% e2 L4 j .vsync_len = 8, /* for VSPW*/1 S) n3 ]* u% r7 A! H! c
};
" N1 g# a- u+ h6 C4 w$ ys3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体8 {: h# O- `3 z7 r
Y: H" G& L+ J; B6 Hstruct s3c2410fb_mach_info {
( I7 X' }# P9 t' m& B3 Y8 k* O struct s3c2410fb_display *displays; //s3c2410fb_display结构体: s% K% [" c+ k0 h5 P9 K0 ?
unsigned num_displays; //displays的个数) w! r7 H; n! V1 C6 e1 {' p% k# r
unsigned default_display; //默认的default_display个数5 A1 T/ ?* r6 p; n+ Y! }
! a6 L8 c6 {) L( | /* GPIOs */- ]! c4 @2 Y# b( ]* n
unsigned long gpcup; //GPC
7 g( }* {' H6 x A: K7 \+ W unsigned long gpcup_mask;
% C$ p# t# R. {( c unsigned long gpccon;
9 y' x, b7 f# r. u- g unsigned long gpccon_mask;
5 k; O4 T) Z* |1 ?7 b unsigned long gpdup; //GPD
( H& ^7 w" Y) ?+ o1 p6 F/ ~8 R5 W+ w unsigned long gpdup_mask;3 h' o s2 t q5 i$ ~ Z* t
unsigned long gpdcon;
' @4 E2 ]( T+ `$ X1 k. E& ~: z unsigned long gpdcon_mask;
s: |- ~: ~. ?
+ u; H; q* w( ~. F$ K+ a3 R0 |3 J /* lpc3600 control register */+ Y6 B" V4 g1 y* O4 @
unsigned long lpcsel;- h1 [0 U8 r3 ^, N
};9 R" \1 n2 Z& q' o$ g ~* Z
' [2 ^6 e- D' Z! h* a
: a7 R8 n$ |2 } t, J
|
|