TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c
o) O; B' N$ q6 O4 g3 T2 ^ G2 a( U. _. |- q
看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数. P8 U; f! d+ f5 p
% k3 p- a, {1 V4 c/ S
2 e# f# T# d. ]2 s( Qint __init s3c2410fb_init(void)
3 [5 y( ~. F: y' b1 \0 x& @{
5 L' l3 n R* Q4 G0 }2 L8 I" C6 y: Z /* 注册一个s3c2410fb_driver平台驱动 */
' P- {0 }# U0 k4 r; ` int ret = platform_driver_register(&s3c2410fb_driver);3 U: p; `( e+ @
: z. P( X' h) [' @8 s' X if (ret == 0)' g: C! j3 u# j! l7 w
ret = platform_driver_register(&s3c2412fb_driver);;
7 W0 P9 \( t; o0 T+ S9 g& u b
0 h' t$ }4 B, R) E1 B* g return ret;
( V8 A& K2 V7 x: N}
6 F" q2 Z5 r6 J/ c j! `出口函数,自然是注销s3c2410fb_driver平台驱动0 X4 T4 c0 W. z# t3 c8 R- f
* ~2 ?& h! w6 ~8 {7 P3 L9 S1 kstatic void __exit s3c2410fb_cleanup(void)
0 {6 W6 i. S% k: k% f# \{
% l: V' N& c- R1 h platform_driver_unregister(&s3c2410fb_driver);, ?) |2 F5 @! X# p6 s/ r
platform_driver_unregister(&s3c2412fb_driver);* m+ L8 h* K. U; x8 B
}6 s) x& w I* {& F3 n. S1 C7 J
我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。 K, r: P. Z# I* E
& m0 Z4 n2 \3 l5 B" }9 q# J0 n
static struct platform_driver s3c2410fb_driver = {3 l& k! A$ c$ L# ?: v/ Y* Q! i) s
.probe = s3c2410fb_probe,
6 @2 q O6 ~: x Z9 b4 M0 a .remove = s3c2410fb_remove,% U7 \4 Y* X7 W, V" s" \
.suspend = s3c2410fb_suspend,: j, o) r& o/ ~' o& @
.resume = s3c2410fb_resume,1 T, w* V1 x: J4 d3 h
.driver = {3 p- v, Q. I# B7 e+ h
.name = "s3c2410-lcd",
0 b& p) }9 r, a' ~) L- `$ j; _ .owner = THIS_MODULE,1 C8 e' t, a# T$ o( e6 X
},& F, l$ U* n5 A6 S5 W- k- o
};
8 |8 j+ p/ N. |- M h v$ r1 e这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。
9 c6 I$ M+ _& X# S/ p8 W8 s1 i在source insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段6 C8 b) a4 m" M- ?6 x+ P0 ?9 Y
p: B! E P% ?1 c
2 I' `6 j v6 M8 ostruct platform_device s3c_device_lcd = {( v3 ` a$ R6 U0 g' j
.name = "s3c2410-lcd",
% B" j- Q. x) q, S8 F4 [ .id = -1,
" Z7 x# ?% o& H, W+ O .num_resources = ARRAY_SIZE(s3c_lcd_resource),
; a/ I7 L& c& G. n; K7 | .resource = s3c_lcd_resource,
; n$ M' N9 k* _ .dev = {7 r& E$ o: e4 q$ M4 d
.dma_mask = &s3c_device_lcd_dmamask,
, N7 e2 F- h' n; d .coherent_dma_mask = 0xffffffffUL3 P5 j9 M" E$ @4 @
}
& b ?, v% z V4 |3 `5 F& T! I% X};$ [5 W+ r3 T1 _5 H
/ N P: F2 G# ~4 cEXPORT_SYMBOL(s3c_device_lcd);
( x. ^, v, o) |- j其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource
7 h% H8 I) F; Z6 N
0 V* p1 c0 r0 W, Sstatic struct resource s3c_lcd_resource[] = {
: y) u. a) M/ D1 s3 \$ i9 u1 i3 N [0] = {
7 l. t# K, T' B1 |8 J7 q .start = S3C24XX_PA_LCD, /* 0x4D000000 */* N7 \* N! v' Q& ~3 d3 i7 e. s4 m. s8 h
.end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,) t0 z7 s0 n) Q: l
.flags = IORESOURCE_MEM,
! G4 S# X3 C i' ~! Q },9 N7 K/ s8 o0 }3 F8 B; i
[1] = {1 Z$ n0 ]9 N/ O6 I3 v. O
.start = IRQ_LCD, /* IRQ = 32 */
! x4 [3 L; U2 j7 t9 E4 B# K .end = IRQ_LCD,+ }& f. h0 q& Z5 R. z
.flags = IORESOURCE_IRQ,
; U* \& g/ o2 I) b7 P8 ^. G }
# N' }3 Z r- T- w g% @% p# T; `* T7 s
};/ M8 _0 u2 p3 j( h5 l6 L
% p1 t0 M) Z8 ]& M/ e$ Gstatic u64 s3c_device_lcd_dmamask = 0xffffffffUL;( [* Z& Q ]0 B6 N: ~$ F. }" U2 n9 Q
那么接下来当然是要分析probe函数了
& I6 x) x' s7 q D4 g) S( {5 S" X; m: }7 l9 t6 W! ]3 E' _( x F: H
static int __init s3c2410fb_probe(struct platform_device *pdev)/ R* z( n1 Q5 U0 E7 S( @
{
5 P, B0 D. O( V' A% g return s3c24xxfb_probe(pdev, DRV_S3C2410); I6 l& s+ }7 {1 A8 u |. l( `
}+ j- t( r" q1 j4 M
s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。
6 l x+ }- i0 v" I% o9 Ulinux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。! w4 L" g. I3 _, ], ?
( i9 |& b0 e. h5 d
帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
( k3 C, G% V, G4 G& t; j$ @- B
& R( E/ @$ ^* I8 F$ gstruct fb_info {0 q* P A( }" @& W* c& w0 Z7 |
int node; //用作次设备号索引2 P! O+ i' _( E2 E& I6 a
int flags;
1 y0 J) D) S: B/ i8 J- ^ struct mutex lock; //用于open/release/ioctl函数的锁
* Z [/ p; m- x; g' Q' }1 ^8 Q struct fb_var_screeninfo var; //可变参数,重点! U4 ?9 m: H% s0 B, S2 m& d
struct fb_fix_screeninfo fix; //固定参数,重点* J5 I. G: T* y1 Q9 j# E
struct fb_monspecs monspecs; //显示器标准
) e& t. \/ }& F0 J# C U2 m8 ~ struct work_struct queue; //帧缓冲区队列
' B: ?2 D5 ^4 A8 w$ L2 u1 t struct fb_pixmap pixmap; //图像硬件映射- ?; h! {+ P2 g8 F/ p
struct fb_pixmap sprite; //光标硬件映射
- `: \& z- f4 L5 E2 t7 X$ L! |2 V struct fb_cmap cmap; //当前颜色表2 Y8 a. T( y$ C6 h
struct list_head modelist; //模式链表! J8 n1 \, }4 K8 l f1 X
struct fb_videomode *mode; //当前video模式' l% q7 ?4 m/ E. q8 K8 u6 e$ M
/ H l* s: u# B
char __iomem *screen_base; //显存基地址
Q" c8 @- ]2 V( s, X3 {1 y unsigned long screen_size; //显存大小# `) b; @- j- Z
void *pseudo_palette; //伪16色颜色表, p* U- E2 e$ E" e7 R; D
#define FBINFO_STATE_RUNNING 0! c$ R. a; @) U0 y
#define FBINFO_STATE_SUSPENDED 1
7 [$ v u7 j7 R+ A6 I* p& \ u32 state; //硬件状态,如挂起
8 H3 q2 K! G U! ~ void *fbcon_par; //用作私有数据区" O. J1 ]- v' c6 S* N! \
void *par; //info->par指向了额外多申请内存空间的首地址2 l# A( N# M7 \ K# I
};: A0 }% C9 ~, G. n
s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息
; l' Y$ B; F$ D/ H" {/ t4 C0 `3 @, g, c: Z0 L. m
struct s3c2410fb_info {
. y" R* f% l4 E6 v9 B struct device *dev; //设备
! y9 j" ~' z$ B) g! F( V, S struct clk *clk; //时钟
2 o& q8 Q" V- Z1 Y% S7 E0 g5 i4 }4 n$ g; e# L$ i0 V7 W( h$ y& a: v
struct resource *mem; //资源- s. w7 I( U3 X' i4 ^7 c& f6 p
void __iomem *io; //IO地址' |' _3 p5 _- o( [% _! F
void __iomem *irq_base; //IRQ基数
6 d$ r: ]8 ]* ^" G- {
# ^+ C7 b5 E+ T* {! |8 i enum s3c_drv_type drv_type; //驱动类型,S3C2410或S3C2412
; t. R6 C* |& T6 x: Y. { struct s3c2410fb_hw regs; //s3c2410 lcd硬件寄存器1 R9 c5 `4 A: q
5 @) |& K) a( G unsigned int palette_ready; //调色板是否就绪标志位2 W8 K: h8 @) ?% T% K* N! V& E0 B
+ v. }3 q2 A1 \# B; _ /* keep these registers in case we need to re-write palette */# w! Z/ c. I* X1 Z# j# |; S
u32 palette_buffer[256]; //调色板缓冲区
8 @) P j) n& j2 N u32 pseudo_pal[16]; //伪颜色表) d* l3 {6 P6 ?
};: i. T" y$ z, a m
s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等! d% Q! D" I) j7 B# w9 b/ s) H
' P; t- ~- q+ [/* LCD description *// \5 o- ~: S/ Z8 E6 |- f. S: G
struct s3c2410fb_display {
+ Q1 W( _# P; H8 K" G /* LCD type */: F6 p0 E& D4 W! k4 y- |$ T
unsigned type;
7 G, r8 V8 k6 M- D1 v
! \9 g) G1 L6 y. I- P8 f /* Screen size */
5 K4 S j; W+ l& X$ z. z! r unsigned short width;: J% N5 @9 w2 s$ `% r4 b; B
unsigned short height;/ K u2 u% O ?6 C0 N) V
: e/ S! F3 {: t6 P7 r8 ]5 k /* Screen info */( H6 [* {6 c( P, F: j5 t1 ?
unsigned short xres;
" B+ I7 f1 u" ^ unsigned short yres;2 g- e+ f! }! Z2 g6 Y
unsigned short bpp;1 }; m# T2 J% a A
. O& W0 q5 `* x8 X' i
unsigned pixclock; /* pixclock in picoseconds */
+ j1 W2 N/ Y& d' O" @, t* W& k unsigned setclkval; /* clkval */7 ^. ]$ C! q8 R' [' O
unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
( m- q8 c& E. ~ unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) *// m# }$ [* e; l
unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
: }1 r: ^" o- b6 @+ t0 k$ { unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */0 ]3 X0 C4 F# G6 }9 L5 N- T+ }
unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */* a7 z( u$ K3 K
unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */
u7 e* c3 o; t2 X% ^! s4 X% d0 [: ~2 X; ]/ d
/* lcd configuration registers */
8 x) J' ~& {. `9 G unsigned long lcdcon5;
. f9 i" K2 R L1 ^$ j};
# v( W4 L9 |# r对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
) L# v5 o) F4 }' E% H7 k* g: f" v
7 x7 Z4 P2 q. D: Y/* LCD driver info */
, @# w. K7 n3 ?* [) Rstatic struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
3 T( m! o. U' d$ O6 f7 m9 g .lcdcon5 = S3C2410_LCDCON5_FRM565 |
& o3 e3 g; p( C7 u: s$ X B# k S3C2410_LCDCON5_INVVLINE |
6 @5 ?; G. N9 H+ k/ x" ~. V& T% T S3C2410_LCDCON5_INVVFRAME |, G3 S; d$ m' f* z' ^
S3C2410_LCDCON5_PWREN |5 ?* {% \* Y& L+ K' g
S3C2410_LCDCON5_HWSWP,0 L7 m& G3 w6 n4 ^ @3 K' p# z/ k
.type = S3C2410_LCDCON1_TFT,8 p. Y/ j9 c# m' d6 {
/* TQ2440的液晶是4.3寸的,分辨率是480*272 */- ^6 ?; z' m& z# i1 Q
#elif defined(CONFIG_FB_S3C24X0_TFT480272) /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */, t9 Z/ P/ O- l* N: D0 Z
.width = 480,9 n3 d, n2 U, o1 J
.height = 272,
3 q6 g4 J% x) r" g( g* W
1 j2 L# ]3 y5 \/ r% z2 _. @9 j .pixclock = 40000, /* HCLK 100 MHz, divisor 1 */
& b/ \: ]4 R) M# s .setclkval = 0x4,
( N I7 E- l5 b% A) Q5 j5 t& r .xres = 480,6 i# N. `# `3 {( n: j
.yres = 272,' E- o& d0 ]7 J/ G( A
.bpp = 16,
$ r# \( m5 V: W. P( }7 |7 Q3 n5 P. a .left_margin = 19, /* for HFPD*/) G0 g/ b/ r- d6 g9 a
.right_margin = 10, /* for HBPD*/) H! O( O) O$ D- U& E
.hsync_len = 30, /* for HSPW*/
1 p! z9 O/ |. [0 z .upper_margin = 4, /* for VFPD*/! j# @ A/ d, e% o) k, a
.lower_margin = 2, /* for VBPD*/
$ p2 c/ [% m$ [/ \+ K9 p .vsync_len = 8, /* for VSPW*/
9 s$ t* ]2 U ^7 P- T};! D3 C. b& Y0 E3 |7 j# a4 K
s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体1 D* I5 U8 }2 f( G3 z7 V1 A
! e( T2 W% @9 k) G0 v- s
struct s3c2410fb_mach_info {1 z7 A6 l! M( v
struct s3c2410fb_display *displays; //s3c2410fb_display结构体& A# Z, \# {: @' c2 M) _* D
unsigned num_displays; //displays的个数
! P; O# p; I2 b6 Y1 n unsigned default_display; //默认的default_display个数
$ T+ Q F& }+ Z) ]% K& Y: C
2 y: R! y8 _: B /* GPIOs */( U7 u: t7 z- ~1 m2 q1 B% x
unsigned long gpcup; //GPC
! [# Z2 D8 e5 R# H. ?2 _ unsigned long gpcup_mask;3 C/ _2 r; A. m" h% r% u
unsigned long gpccon;$ f7 H3 Q I+ M' @9 p
unsigned long gpccon_mask; T" o4 A4 }. [8 n6 c
unsigned long gpdup; //GPD
; k+ ]1 m' B8 [0 a' ] d unsigned long gpdup_mask;
, S7 x& N# {5 o4 r# N. D. O Q unsigned long gpdcon;/ L( Z b; i8 K, ]
unsigned long gpdcon_mask;% B } l, G( J$ B
! U. d4 h# o1 G/ M' e" f' @- s /* lpc3600 control register */
* A _, _& _. V1 h; Q unsigned long lpcsel;5 o5 r4 y! y. O% ]7 v
};
: g" t0 `& B& L9 c
' C9 h% k n2 L$ b1 x; a6 C; h0 f
|
|