TA的每日心情 | 怒 2019-11-20 15:22 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c
8 t7 ]" C( x" y- k
, p2 V$ h2 f- f5 K+ r- A3 c3 W2 A看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数4 G! o5 f' i- Z# w! u) S) B
5 D5 N, x* J9 _* F* t
9 O. t( F5 r( aint __init s3c2410fb_init(void)* r6 S7 [) x' l: j2 H7 N
{
8 u, `- P; ~+ q; U+ m /* 注册一个s3c2410fb_driver平台驱动 */
) V- P7 @5 M/ j9 x' j int ret = platform_driver_register(&s3c2410fb_driver);# c2 Z2 { k7 }. q g: V
: \( c3 [9 Z5 O+ {2 U) `
if (ret == 0)0 b4 l9 ~+ H5 N2 t& [/ E' _
ret = platform_driver_register(&s3c2412fb_driver);;
& V& F" t- J t) W, c3 }/ b( U! `6 W8 O7 S" i1 {
return ret;
3 D0 r7 Y4 S" u* D- e+ A0 |" F, {. W}! T. X' u0 N. c5 M3 M; W8 v
出口函数,自然是注销s3c2410fb_driver平台驱动
3 z1 q5 T: X4 B; a$ K& Y S ?0 q1 P8 p' R" `0 v8 B4 M
static void __exit s3c2410fb_cleanup(void)
1 y& E3 ~( C: r. q" q{6 V; z; T2 {: \( F$ U) E9 v2 g
platform_driver_unregister(&s3c2410fb_driver);
) |. b* U8 m1 i+ p+ t) v. E platform_driver_unregister(&s3c2412fb_driver);
$ q4 I2 U* B7 _# q& p}
6 i/ T/ o8 Y- e' x! N我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。& v+ n0 B$ S0 N$ ~* X5 F
# Z* {' ]( c+ U6 R2 ]static struct platform_driver s3c2410fb_driver = {
' Q( b. x$ c8 e* z# t .probe = s3c2410fb_probe,$ v& z L. M$ a3 C3 T7 q6 @! P
.remove = s3c2410fb_remove,3 ]+ `1 K- C8 T$ m8 V8 h, M4 u
.suspend = s3c2410fb_suspend,/ c3 I- n" Z! l h& g% W- f9 `% q2 ~
.resume = s3c2410fb_resume,
4 B" F* C$ ~* ?1 b .driver = {$ Q J2 \9 n% O
.name = "s3c2410-lcd",& A, z. ~; @( Q. u* x2 ?" B4 F
.owner = THIS_MODULE,0 Q" [" \5 s7 w. a. J
},
( i( G* A/ y/ D' f9 k};9 r4 g9 p* C" w( s" u/ S' H* w
这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。2 n2 v, @9 ?/ M& S* j; F! s
在source insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段- g" Y# f' {5 A9 }. C0 w
$ [! t$ E* l3 l, e: W) o9 I
( ~7 \! b, b, O" f3 M
struct platform_device s3c_device_lcd = {
6 v9 r" U/ C( S6 Z! X! j/ W, _ .name = "s3c2410-lcd",$ d: a* W9 P6 k% t
.id = -1,
* ^' q. N5 f/ _ .num_resources = ARRAY_SIZE(s3c_lcd_resource),
- n8 g! x! M. i$ ^+ }8 w1 T6 _9 Y9 ^ .resource = s3c_lcd_resource,5 v5 { p" r. p9 E C
.dev = {
) I8 N Q7 F& ?9 I .dma_mask = &s3c_device_lcd_dmamask,
& u% M: f* K1 a .coherent_dma_mask = 0xffffffffUL! s, P& {" ?- k8 Q/ F- R$ @
}
! L5 }1 a& E4 T& R4 Q' D* C1 N};$ q; D$ L: W' |2 |; F. M
0 f+ o5 _0 ?& ^. K! W! m3 K
EXPORT_SYMBOL(s3c_device_lcd);6 D4 Y% S+ g( n/ }5 q n3 k
其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource3 G* s0 q, P/ p) F! Y5 J! Q3 L
9 L" @* N' S) y1 w% tstatic struct resource s3c_lcd_resource[] = {
1 e+ L5 t# r* R" e- L. v [0] = {
1 Y& [0 g4 C# x .start = S3C24XX_PA_LCD, /* 0x4D000000 */: g) l- D' J E( ]" H7 u( v. r3 d
.end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
9 q. g1 E. }8 C5 a- s$ A9 @) k .flags = IORESOURCE_MEM,
* [, L# C) M* o$ n+ g; c },2 w( V1 r" b P4 S
[1] = {9 D% |7 m# d, x" K* |% u# V
.start = IRQ_LCD, /* IRQ = 32 */
& A2 F" G! F# K$ Q7 R" U: k8 R .end = IRQ_LCD,3 ~9 B* j7 d8 H; n; ~$ n
.flags = IORESOURCE_IRQ,
) J$ R6 G9 `+ [& C" [1 l }3 e D1 g3 O7 ^" a! x# r2 ?4 P
) O, H1 [/ n& K1 S7 n% q3 x1 M
};8 V. i2 A% k3 E# t0 }7 z2 T
1 ]* |) Y$ y7 c5 ?static u64 s3c_device_lcd_dmamask = 0xffffffffUL;7 b% m+ }% y, J
那么接下来当然是要分析probe函数了+ [2 \9 d% o5 m) D! A7 B
: v. q( D5 P8 ~. v0 {( m/ j2 I2 \
static int __init s3c2410fb_probe(struct platform_device *pdev)( R6 g+ F: i- R4 v$ p: o0 e! Y
{, j, X1 O; B* p- M" X P2 z$ U
return s3c24xxfb_probe(pdev, DRV_S3C2410);8 W; P" ]! }/ w9 M U2 |- y& d
}
: m# J; |' f! {s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。9 T: e' s* ~+ P% r% C8 C
linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。8 @- h: X; U, p3 V* C5 d/ u
2 C ^ m/ B, [% e
帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
' ^" j: d( u% x2 `5 Z! e9 ]* u+ N4 p7 G- a; y
struct fb_info {
$ l8 P& L5 Y, s5 T- E* H int node; //用作次设备号索引
4 U) Z# A, O; }# {, R) I int flags;
" C& t- t- `* V& T struct mutex lock; //用于open/release/ioctl函数的锁
E) W4 Y+ t2 X4 R+ o struct fb_var_screeninfo var; //可变参数,重点3 m: i1 `0 \: ~7 ^# m' u
struct fb_fix_screeninfo fix; //固定参数,重点 B( `3 j) a+ ~( g; h! w
struct fb_monspecs monspecs; //显示器标准
8 k' ~( _8 K! I, j struct work_struct queue; //帧缓冲区队列
3 e8 F/ [% }7 [2 I m Y struct fb_pixmap pixmap; //图像硬件映射
7 n% X1 m y' X+ H, z9 ` e" f8 l struct fb_pixmap sprite; //光标硬件映射
" y! S: s, z1 b7 v! k+ I3 e struct fb_cmap cmap; //当前颜色表
! M' {. |5 S' r+ \- b) e- A struct list_head modelist; //模式链表
" J& g% Q, k& R struct fb_videomode *mode; //当前video模式
2 [6 K4 t* M% N
6 c7 W8 n% w# T. [& [3 x6 M char __iomem *screen_base; //显存基地址
# M/ H: |8 y6 M3 e unsigned long screen_size; //显存大小9 W. H$ C' u7 X2 ?- W
void *pseudo_palette; //伪16色颜色表7 e5 _$ a/ f4 Y& k
#define FBINFO_STATE_RUNNING 0& z9 k9 s7 X" O3 J& @
#define FBINFO_STATE_SUSPENDED 1
/ _. ~7 h; O6 Z/ B% {7 ~ u32 state; //硬件状态,如挂起/ k. H+ s/ k2 C8 X) o
void *fbcon_par; //用作私有数据区
/ [0 m# `# N/ c9 o% r) o void *par; //info->par指向了额外多申请内存空间的首地址8 ~8 ]9 W* R W4 S* D9 A
};) o; D4 P& L; k8 t
s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息* @1 r; \3 |+ }" v3 p, \
* l3 J" i3 o# Y" y) c7 H$ v+ q# ?+ m& P
struct s3c2410fb_info {
6 c; o; D- ?& M6 A( R0 ] struct device *dev; //设备% m' s& H- }7 v$ T+ a2 b) m$ x
struct clk *clk; //时钟
5 z$ k0 d3 t1 f" H; B
; Q) p! a f# ]$ L7 D struct resource *mem; //资源
5 q1 |8 i( X. G; x+ P# j void __iomem *io; //IO地址% W" c' y6 t5 Z& O3 F1 c
void __iomem *irq_base; //IRQ基数
7 n1 r" P5 Q/ G% t1 P
h6 t: G( z; s6 @8 j6 m5 ]) K enum s3c_drv_type drv_type; //驱动类型,S3C2410或S3C2412
. T. N0 y2 Y% q0 s# Z struct s3c2410fb_hw regs; //s3c2410 lcd硬件寄存器
/ ?1 D5 E( i* x: H- X: X2 q6 q+ D4 J7 f/ p/ A
unsigned int palette_ready; //调色板是否就绪标志位
9 O3 ^1 W& H- f6 `# ^! P" [4 Z+ m' w' p3 f2 C$ v/ c5 c
/* keep these registers in case we need to re-write palette */
8 \) i- M5 N; ]2 R# {3 R u32 palette_buffer[256]; //调色板缓冲区7 j) B6 c: @2 J9 z9 p; b* h1 e" }
u32 pseudo_pal[16]; //伪颜色表9 i2 J1 U3 Q& F, l. p, H. `
};
5 S; U6 J1 @( o* Rs3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等
4 x7 N, P6 X' x( H; h: w: n1 R% C8 g
/* LCD description */3 P' m- k7 o7 Z9 c0 M8 R5 u
struct s3c2410fb_display {0 p& n; w- `: [2 ]' x" J5 d" M- E
/* LCD type */
- _+ p9 W) O' A+ y( u9 Z6 w unsigned type;. e4 o7 M; Q3 L6 T2 U$ @- k l
3 v. T4 B O+ r, Q7 T1 A8 Z
/* Screen size *// P2 o1 J7 G$ n. r; w
unsigned short width;) t/ K- I. t e T& `( Q
unsigned short height;
! }! Z6 r% k' J4 }; i4 b- k5 w) H
) V a/ c4 H: l j6 A9 R& X7 r7 d /* Screen info */ @2 w; _6 p! Z
unsigned short xres;/ F6 O! K! m& C7 k' M. M. p# B
unsigned short yres;: Q1 z$ s) `1 b
unsigned short bpp;: x$ C3 e6 A7 v( L# J% b
# {; s/ t' X U5 \1 a' t6 \, A; |
unsigned pixclock; /* pixclock in picoseconds */
8 z' p) {( _+ b( H1 s, l" a3 o, b: [ unsigned setclkval; /* clkval */
+ f/ K Q! }, M0 ]2 x unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */# S' i/ I4 Q6 [9 P* n0 y( o
unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
* Y% d' c7 \& o/ w) ~ unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
/ C1 J/ ^9 i6 s: I% y+ p" W; E unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */$ U3 \, w+ Z3 E/ p( {. P
unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
/ b. @" `# J9 _ unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */2 t: {4 \: f- G2 r) `0 p+ b; t
+ Q( ?- |, p, u8 Y$ X5 q /* lcd configuration registers */, }, c9 }6 e5 u" ?& a
unsigned long lcdcon5;. R' j) [8 H ~4 ?: S
};& ^9 T, R: Y* b c( b* n
对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置9 o1 t4 i. x1 l" I) @; S+ z$ N5 j
& I. k3 {/ z9 ^6 b* \' _- h* g/* LCD driver info */
1 a# x: T0 U% Y4 e, Kstatic struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
, w" v8 G7 |5 U4 Q5 \ .lcdcon5 = S3C2410_LCDCON5_FRM565 |5 O K$ M4 m0 n1 l
S3C2410_LCDCON5_INVVLINE |
" d% u/ |2 O2 H3 i5 x% R S3C2410_LCDCON5_INVVFRAME |2 X& g3 h0 d8 M0 w4 q" }
S3C2410_LCDCON5_PWREN |
9 _1 s3 E% p) T4 A S3C2410_LCDCON5_HWSWP,
! j" ] {# O2 y- V .type = S3C2410_LCDCON1_TFT,
+ ^, y6 f8 A' Z7 m. o6 f. E0 [5 V /* TQ2440的液晶是4.3寸的,分辨率是480*272 *// o/ }, M) b& i: K: R
#elif defined(CONFIG_FB_S3C24X0_TFT480272) /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */
" {$ y6 W$ B5 o0 d' k5 O. k .width = 480,
: d) n7 i M/ ]7 d7 h4 d8 q9 q .height = 272,
( u. i$ o7 B( P, q
, M( D$ w3 i. B .pixclock = 40000, /* HCLK 100 MHz, divisor 1 */
% } y7 E4 [; O4 h2 y .setclkval = 0x4,4 {5 ]$ t2 P0 f# m
.xres = 480,5 r6 }. o# H6 d/ s- U
.yres = 272,
7 l* W% m& g8 a2 G9 ]. I2 | .bpp = 16,
[: U1 w$ d: N# e- b' f .left_margin = 19, /* for HFPD*/! I3 ^: t6 l3 k* x8 F0 @- V: W3 @# J
.right_margin = 10, /* for HBPD*/
3 G3 P# A( u6 Q3 p& U* ?0 n; R4 _ .hsync_len = 30, /* for HSPW*/
2 _7 P7 b% p2 q6 A( A: x* _# O* z .upper_margin = 4, /* for VFPD*/" y9 G' F5 t% m7 g8 d
.lower_margin = 2, /* for VBPD*/. r1 k/ g$ ?! x8 O
.vsync_len = 8, /* for VSPW*/' I, Q b* |6 i0 L4 J
};; Q" b! X0 S+ A4 L
s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体
) {* K- Z" B6 g" ~ W* W# z
' o0 P. X: m6 J6 s8 U) n5 [struct s3c2410fb_mach_info {
5 u0 j- i: U# a* H% x& J struct s3c2410fb_display *displays; //s3c2410fb_display结构体
1 m- G, X* o6 ?5 X3 G unsigned num_displays; //displays的个数
2 F8 S$ t) ~4 m5 V- K unsigned default_display; //默认的default_display个数7 Z1 w! `$ x) p+ f% z; ^
3 \% i( g3 B4 i- @1 G /* GPIOs */
- y7 P& V' M3 n7 g' ?' S unsigned long gpcup; //GPC
( Y, G( ?2 R6 W unsigned long gpcup_mask;
! @3 |' B; K" c1 X5 J unsigned long gpccon;
& S3 o% J, n2 \ R! b0 x, b unsigned long gpccon_mask;) [2 n) o0 C0 V& y0 O) d; A
unsigned long gpdup; //GPD& d _) Y# C1 y/ a' V, ^ n% |
unsigned long gpdup_mask;; z7 K# z3 H1 G- E
unsigned long gpdcon;" V' {+ G* B, d( c2 l7 W9 Z
unsigned long gpdcon_mask;
) y A6 Y6 F% L3 Q' I) N" R' y8 u# [! Y$ `$ T" I t
/* lpc3600 control register */# }& |0 _6 l2 y& D3 Q( Y7 c
unsigned long lpcsel;
' [: ~5 m u) U/ R: H9 k};
$ J% K; A( r' k. }* g+ t) \
$ r6 |0 a+ y0 d a: |9 e% Q+ B9 d3 v- k
|
|