TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c
8 M. ^( G0 V9 j; I: @% y E& z
* v& Y7 G+ y N) N看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数
) \" Q: D" b4 L# r0 `# g* n. {
1 _; b, w/ F. P! a4 Q
. ]1 z- }1 _4 c( q O+ E- A5 \% }int __init s3c2410fb_init(void)
, G7 Z7 i# g8 K& e% u! {{* Z) G5 B# b1 H4 Y0 ?6 B
/* 注册一个s3c2410fb_driver平台驱动 */- Q' H* X( x3 x1 u7 M( i. j( V
int ret = platform_driver_register(&s3c2410fb_driver);
4 i) {9 Z0 Z2 y8 n2 `
5 K5 H0 d: S( S9 g: n if (ret == 0)# w$ M. g( v5 b
ret = platform_driver_register(&s3c2412fb_driver);;
: _- k) y2 W+ g, b7 [' Y2 Y) {: i' C4 v
return ret;+ z. M# W9 `4 a' B! j( I' I; j
}
4 K" H' `+ C' j, x8 ]( W出口函数,自然是注销s3c2410fb_driver平台驱动+ v# i2 l' {3 A. [
3 G9 C7 u) q% a% V
static void __exit s3c2410fb_cleanup(void)
- R' E( O0 {/ Z' P5 K{8 \5 ]5 k7 X( G5 c+ l3 ^3 f
platform_driver_unregister(&s3c2410fb_driver);& }' x: c6 G6 T& f, Z
platform_driver_unregister(&s3c2412fb_driver);
& s+ w, } j0 c}
; n8 f! T4 D# Q0 J5 C) V( u) @我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
, u! i% \: Z$ V/ x8 O4 q5 f6 ~5 r3 O0 }0 V# k# C; o$ e
static struct platform_driver s3c2410fb_driver = {
7 d0 {& N; O- r& y7 U: A .probe = s3c2410fb_probe,
5 V1 I8 D0 ]6 i. _! s& w0 Q .remove = s3c2410fb_remove,3 j1 @) Z5 _8 [: @
.suspend = s3c2410fb_suspend,3 X/ w& N0 C4 j% `" k r* c
.resume = s3c2410fb_resume,
6 g) A; k* l- d7 N6 X9 s9 ^ .driver = {
0 n" S$ U# Q6 _5 N: w( i$ G; N' \ .name = "s3c2410-lcd",
: F+ i2 f& X' C/ l .owner = THIS_MODULE,+ i- R; p+ j, }0 d; c. c5 v
},
4 @' Y3 s# R- V; \/ A0 {};- C; a6 S, {- j* U1 v- p& B( V
这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。: } E7 e! q" z# O1 z: l
在source insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段
3 ?( x: f. F \7 L- r* I
4 k( s7 l% b" e$ y& p% h- A" f; G1 r. ]' P9 w+ L; E; _
struct platform_device s3c_device_lcd = {, g0 p. c$ z S, b1 M# m
.name = "s3c2410-lcd",
- A W3 [* [& t* T .id = -1,; {9 ]# W/ s; @8 ?8 u" ~0 |
.num_resources = ARRAY_SIZE(s3c_lcd_resource),
! ~1 F. }" D/ l' k0 a .resource = s3c_lcd_resource,
% A) X( }- M1 \! M; r .dev = {1 s+ R; w( Z: Q3 b
.dma_mask = &s3c_device_lcd_dmamask,
4 \( ?2 Y+ Q( h! t .coherent_dma_mask = 0xffffffffUL& u6 h j* q: Q& B9 I' o
}
6 L0 v7 i) _( |" A i! Z};
& R* B: b$ ^+ z/ t/ `0 ?4 T) H) G7 M& Z% n- W6 ]
EXPORT_SYMBOL(s3c_device_lcd);) N+ J2 p# i8 I" w# Q
其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource
n' M5 t: v! i# Y
' R5 G* C( i% G' zstatic struct resource s3c_lcd_resource[] = {
0 o1 T: @/ |8 S- O [0] = {
9 d% G; D7 M. [( \' z. |" ?6 O .start = S3C24XX_PA_LCD, /* 0x4D000000 */
- f% r1 ?3 I/ ^- ^. n& e .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
& Z3 p* W( T* G5 `7 z- u6 c .flags = IORESOURCE_MEM,9 g% I9 R1 ^3 F5 u8 }( h
},! Z, J7 B9 _- q- n6 _) k
[1] = {
6 `+ G6 E6 B5 s$ v% D .start = IRQ_LCD, /* IRQ = 32 */2 ~ J6 x, M2 F& M
.end = IRQ_LCD,
# k5 |$ K$ o2 s @1 \: f) ], Q .flags = IORESOURCE_IRQ,# D% a, |3 E" |2 U
}
k7 P) t5 Q) v+ G/ q) y$ N6 B0 B, [% {: a6 q
};
; B* H/ L& Y% N# s' J& Z# ]" C- U( \5 |& h6 W$ J
static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
2 W; c/ L, o% Y0 o5 k5 L/ x* u# I那么接下来当然是要分析probe函数了0 D5 _) H9 W- F# w" x6 ?
0 W- @7 U: ~3 Z6 P' H5 S N
static int __init s3c2410fb_probe(struct platform_device *pdev)/ e7 [2 O2 B- a/ t
{1 w* h3 y' K% [
return s3c24xxfb_probe(pdev, DRV_S3C2410);: l, W8 ^; r3 A- D; E
}; J. G5 S2 ]: x- q- W! N& h
s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。
2 s& C' N. L, B1 X3 b: {3 Q/ nlinux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。7 C# h$ H9 J; ?
7 u# d) l! ^0 W8 ^+ L4 k, r
帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
- ]4 C, k# h# L& y* i, G7 M! I- U D! I: d
struct fb_info {3 H( g) b8 V( n: f
int node; //用作次设备号索引
3 ]2 Z, q8 {0 s2 o int flags;0 r/ N7 e7 t& ?* k6 B/ r
struct mutex lock; //用于open/release/ioctl函数的锁
3 E: s1 Y0 ]9 O Y' ?; U! ^/ | struct fb_var_screeninfo var; //可变参数,重点! I) `5 z, N& I" z4 M2 C; {
struct fb_fix_screeninfo fix; //固定参数,重点
# ?! S3 G8 d* r$ ~7 _3 j J' u struct fb_monspecs monspecs; //显示器标准
. y6 F; H) k" A2 W struct work_struct queue; //帧缓冲区队列
! M+ M$ _8 c! n% T7 g struct fb_pixmap pixmap; //图像硬件映射
( ^9 f3 z* b; _3 [/ n struct fb_pixmap sprite; //光标硬件映射
6 Q1 D3 k9 D3 I8 Z* s/ Y3 \ struct fb_cmap cmap; //当前颜色表+ e* k+ t3 b" Q6 l# h4 g) E
struct list_head modelist; //模式链表" |4 }1 K7 }# B' U8 s8 d3 p
struct fb_videomode *mode; //当前video模式
+ M) A. ~4 P" r+ Y/ }5 ~: e
) s7 p7 j& A( ^9 r# {5 L w char __iomem *screen_base; //显存基地址
" ^- G p4 u/ K% H unsigned long screen_size; //显存大小
, b0 K" |+ C$ N9 }: A7 o void *pseudo_palette; //伪16色颜色表. p+ S# B6 U3 L0 s0 q5 m& q
#define FBINFO_STATE_RUNNING 0
, m! ~9 t' I- l# Y$ M6 e! T#define FBINFO_STATE_SUSPENDED 1
2 s( Z$ U4 G* R+ H/ I% f c u32 state; //硬件状态,如挂起
& Q- t* `% j5 X1 ?) e2 B0 n void *fbcon_par; //用作私有数据区
( J; L3 O/ O! {% J( ^ void *par; //info->par指向了额外多申请内存空间的首地址
- ?" X6 L- d C6 x+ A}; O f8 M: u) e7 S1 F! V/ H6 x- Q
s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息" T7 z: P4 w- g: |# a( g6 u
2 T. |0 G4 p h c( L- H. z1 Nstruct s3c2410fb_info {
2 d/ Y( E0 E* \$ r struct device *dev; //设备/ k- P& I7 {3 G6 R( r
struct clk *clk; //时钟! j8 c9 V$ S- V4 e! V
4 ]* q$ [* T; u+ N5 W struct resource *mem; //资源$ ~1 o1 s0 n5 _% X6 y
void __iomem *io; //IO地址
+ o. H+ a" H9 v void __iomem *irq_base; //IRQ基数. z, Q5 [7 |; ^0 R4 O3 L1 p4 f
9 u7 K6 P# B L. n' y: ^ enum s3c_drv_type drv_type; //驱动类型,S3C2410或S3C2412
& n! x0 W: y9 z# U* g) Y struct s3c2410fb_hw regs; //s3c2410 lcd硬件寄存器
0 q- B. t; R/ h& _# T
$ e# R. h7 S, C: S: U- \ unsigned int palette_ready; //调色板是否就绪标志位2 c% V4 L. F4 l* H6 T! I: K
4 x7 X0 Q- A# ?+ e! h8 i$ h6 K /* keep these registers in case we need to re-write palette */
: F) [; d- v! {+ s5 ]$ B* w u32 palette_buffer[256]; //调色板缓冲区
& ~* @) u( D1 `" M! M0 T' ` u32 pseudo_pal[16]; //伪颜色表
$ t9 y; N5 c% Q+ h. J9 v5 N};
" V; }) n& |" i; ns3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等
1 L0 G! ~2 k& z) F& I5 |+ f0 Y- l7 f/ ~$ T& j) E V. {
/* LCD description */
+ J- S4 D6 D3 Q& S& Bstruct s3c2410fb_display {
, W1 J& Q, g5 _# L( i /* LCD type */) a' Q* y6 e$ l# u- |4 |' z2 i
unsigned type;) v- y: k$ e @" N6 Q4 c
4 u- x. l3 `$ n. V# Q /* Screen size */! s8 r) I" V) N/ K
unsigned short width;
1 d% Y% @: m1 P# z7 V2 G unsigned short height;0 g3 y2 b- T& N; G
. h2 x& a$ q$ M/ `' E3 h9 j7 `) Q4 J /* Screen info */
$ J( `0 C! f. I1 @/ A8 } unsigned short xres;
* `, x) Y" [' E8 Z3 t unsigned short yres;
i! M6 G( O; q1 v unsigned short bpp;
1 F, f5 K! B9 b# q' w2 U* _. v8 e3 v, f3 b& w+ i9 L9 ]$ X
unsigned pixclock; /* pixclock in picoseconds */. N. Y- e j' V7 v2 @" T' y2 ^
unsigned setclkval; /* clkval */ |, }6 }" e6 k; C
unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
$ n [: B5 [1 c unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
8 w# _1 H3 n8 S7 C) a1 l unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
) k+ n9 o4 a/ U3 V+ N/ g unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
6 {5 i/ L6 b# G" L6 g+ x, i8 O unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */9 a _# }: }) o8 `! d# W
unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */3 }+ j" G2 t; c
% w7 S J* {& Y. M8 C; \. X /* lcd configuration registers */
2 y" ?: \1 b# t3 U0 w3 H) D4 c unsigned long lcdcon5;" I, l! f9 y: F l0 H
};
3 R# i0 N. O, p对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
1 W) N. M' W! T8 y& h; u2 @, N: k0 Z) N
/* LCD driver info */
3 \2 R' G" R# H3 b2 _+ }% Qstatic struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
( _8 D2 i5 K! i# c. S .lcdcon5 = S3C2410_LCDCON5_FRM565 |( d: n3 n! {( O
S3C2410_LCDCON5_INVVLINE |
! D' n% a: Y$ {5 G$ ? S3C2410_LCDCON5_INVVFRAME |
* ]+ X" L1 K I2 B6 P S3C2410_LCDCON5_PWREN |7 b5 h% l7 L x% S5 T o; l' B1 {
S3C2410_LCDCON5_HWSWP,/ e2 @, s0 H7 H! j' N, f+ y
.type = S3C2410_LCDCON1_TFT,
: [5 }0 q2 |; c( U, A' l /* TQ2440的液晶是4.3寸的,分辨率是480*272 */1 }6 P' t* U& ?* e+ A
#elif defined(CONFIG_FB_S3C24X0_TFT480272) /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */
% P% P; q X T/ N4 {# w% v .width = 480,' m' }; ?5 g; g2 f" M6 P
.height = 272,
3 P3 L) R) X# [# C& P9 ^% Y# e
8 i0 @' D; M$ N% q: F2 x. s .pixclock = 40000, /* HCLK 100 MHz, divisor 1 */
4 x# K2 h& z3 L6 T& ~ .setclkval = 0x4,: G2 O( i U& m1 t
.xres = 480,
* h8 `; } D/ n" T) l4 l .yres = 272,, \8 b! F5 Y' Q/ I( W$ K
.bpp = 16,
& J" Q1 L/ s0 o* F/ y: w' [ .left_margin = 19, /* for HFPD*/! F0 ]% G: K+ ], s+ X
.right_margin = 10, /* for HBPD*/
- [5 o2 X: u6 @7 C' O2 y" } .hsync_len = 30, /* for HSPW*/
3 `; y- k0 f; V: u) A" g2 u4 S .upper_margin = 4, /* for VFPD*/8 c5 f, F6 e: @4 z. Z6 n
.lower_margin = 2, /* for VBPD*/
! l0 M5 m. e! e; n. I .vsync_len = 8, /* for VSPW*/; b9 C. c4 o8 k5 b; {2 ?) N: [7 t
};9 c- q/ t. |7 ^! m& G
s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体4 N+ X# S8 B7 Y$ s% {) Z" S: U
# {$ I2 x) @2 \
struct s3c2410fb_mach_info {
$ U5 k* Z- T9 m# j struct s3c2410fb_display *displays; //s3c2410fb_display结构体
. s8 z6 ?2 k$ z. S1 N0 k unsigned num_displays; //displays的个数
- `7 |6 `: H; x9 x; l unsigned default_display; //默认的default_display个数
: C9 H# H* R4 D m, \, T i0 A# L9 Z# Z+ Z4 u; t. r9 i2 }
/* GPIOs */0 h; M; R; s# x Z
unsigned long gpcup; //GPC
! Q; E5 t# {7 [; C. [# a) B unsigned long gpcup_mask;( m4 [) q: y' T8 M- E' n' k* ]
unsigned long gpccon;
) W1 u( I8 E. z6 B, k' D unsigned long gpccon_mask;
+ h, a4 \/ z6 j$ J G" n unsigned long gpdup; //GPD; u; e( c1 m" c% A# k
unsigned long gpdup_mask;
/ u+ s: l/ Q, R7 Y- g$ | unsigned long gpdcon;
0 n1 c7 B4 ^8 b b2 h unsigned long gpdcon_mask;& Q: Q2 c& D; _' d$ W
9 Z& o A o- A( l5 Y
/* lpc3600 control register */
7 w+ a6 Z1 b- N/ {) R+ S unsigned long lpcsel;
. [# L0 p, t) t- u! b};
! B& V a3 d# ^* L
/ h0 b' S! y+ j! O5 Q+ j; I2 b d4 a' n7 p, B
|
|