TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c
% R) a* G1 L5 C
# d4 r9 f) ?( ?看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数
. o7 `' ~5 z6 d4 C5 s( F1 t9 S6 r5 J9 O3 B: J
" ^5 j+ H Q' u3 V, |. j8 S
int __init s3c2410fb_init(void)
# I! T$ m7 W" t{" B/ v7 M3 {0 |
/* 注册一个s3c2410fb_driver平台驱动 */3 ?1 u1 X. B2 G* y+ w
int ret = platform_driver_register(&s3c2410fb_driver);
' ^% N$ d1 u) z% D9 q
( t8 O" ^6 v9 X% F7 Q$ n- {: ?4 n if (ret == 0)
3 ^* Y- ~: S3 h* L& _6 n. I& U: r ret = platform_driver_register(&s3c2412fb_driver);;
1 [; W0 u/ I% V- q& v: `/ I9 P. P& P/ A+ o" ^0 ?0 Z. a4 X
return ret;$ M/ N" i# l( k6 u
}
) o; f! F, T% |8 I2 F1 @出口函数,自然是注销s3c2410fb_driver平台驱动
# d( p9 h+ f Q8 ~7 [; a
) c6 L! F+ p0 |$ Mstatic void __exit s3c2410fb_cleanup(void)+ g5 q* F, M7 a4 S
{3 i! H ]) S( R$ O5 K
platform_driver_unregister(&s3c2410fb_driver);
* Z( Z* x! l( s0 i! X! @4 J platform_driver_unregister(&s3c2412fb_driver);! l! E2 F& b/ H0 w
}' I; L$ n: j' r0 p
我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
" v) \6 j/ ~' V$ v5 l3 p1 o# N$ P7 P( r w I. q" E2 q
static struct platform_driver s3c2410fb_driver = {6 A2 D# @( j! S) \; @
.probe = s3c2410fb_probe,5 i. e. Q, |+ s/ q5 ~7 i" N
.remove = s3c2410fb_remove,
* h; a/ b% D) ]1 S5 \ c. t .suspend = s3c2410fb_suspend,
3 M2 |! `' ?8 x .resume = s3c2410fb_resume,
3 ?# a3 [' W1 g! _! G P .driver = {
/ r4 b% \3 h, X( r* Z& b" o2 G .name = "s3c2410-lcd",9 r) p/ A! v$ T- O/ E% L. w
.owner = THIS_MODULE,
' ]6 @5 B# A, y. D2 q },
6 L p6 H" e6 F/ d9 e7 l% X};, P6 i! h: C# |+ ~
这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。' Z, `& P ^. @+ u( M
在source insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段
& Y2 B8 m9 h, B/ m7 w* Y& X
# b0 r4 P: v# f* R. l6 y7 x* L2 ^# E# q |. M
struct platform_device s3c_device_lcd = {$ U+ d% p* f. W6 `. K$ [) b
.name = "s3c2410-lcd", B/ ^, N& M) r" c" D' e# R
.id = -1,0 Q p& u9 d2 r( ]% g0 z% z
.num_resources = ARRAY_SIZE(s3c_lcd_resource),) [7 C6 T: ^% Z0 k4 J; |
.resource = s3c_lcd_resource,7 N2 e1 h+ y7 ~3 s' `
.dev = {
( }/ q4 x1 i2 K6 Y" V+ h .dma_mask = &s3c_device_lcd_dmamask,- I; [0 }# X4 e) D
.coherent_dma_mask = 0xffffffffUL/ W, {8 @3 z" k8 G$ { b
}
/ @1 o6 A+ }- X. L; D% R};- s2 T8 V7 [7 a, O5 @5 T3 |
3 J, X( x( g7 a) j5 yEXPORT_SYMBOL(s3c_device_lcd);& O C( j2 L. M' |; T8 n* P! o
其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource. z1 W* z4 q# c0 L+ j
6 n, [. Z# r" b) @0 V8 T
static struct resource s3c_lcd_resource[] = {/ N: T+ {5 V' `7 ~* N
[0] = {5 f; a0 m) U8 g* P! \, f' H
.start = S3C24XX_PA_LCD, /* 0x4D000000 */
! \7 v$ a) H" m( |: }' R5 m* x .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
1 `2 f$ _- P1 X% Y .flags = IORESOURCE_MEM,
5 m+ c& f( Q7 v. Q) V },) U- a* I+ Q3 S1 J; {4 v# f# L! y* i
[1] = {4 p( \! Z% Y+ g, `
.start = IRQ_LCD, /* IRQ = 32 */
! b9 g- l# ?- o* O! ?8 ` .end = IRQ_LCD,
7 B8 l1 p0 H6 p# S .flags = IORESOURCE_IRQ,
- s4 ?4 D- W& }9 p# d }
?* i; J6 s! Q* u0 \
& X% P) X. t2 y3 s; H; c5 N/ o$ K9 z};
% t6 Z- U0 J. S# P+ ~4 v& S1 J/ ^
) O, g5 z# n7 V- y$ j9 Rstatic u64 s3c_device_lcd_dmamask = 0xffffffffUL;& _6 A6 v/ J+ L8 u" ^7 x
那么接下来当然是要分析probe函数了% t9 f; S; P5 \1 F3 g- W) o3 k. r
: E$ x+ b" [: O( S2 V- m
static int __init s3c2410fb_probe(struct platform_device *pdev)
& g# v; Z7 O8 K4 ]+ l{# ~) @- @5 U5 o0 X1 i1 f
return s3c24xxfb_probe(pdev, DRV_S3C2410);( |/ `; Q4 k. a! Y7 s. I! W0 \
}5 |* l, @% t2 Z" q0 r. S8 b7 Q
s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。1 ^2 j" }2 L& \% W$ q" z, q8 x
linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
9 W1 X5 {' ^9 W% r: y8 ~0 F" Y9 G. H
帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。. ?0 ~3 ]! u3 a& l/ N' u0 r9 G e
/ U1 D; Z, r, Z5 n7 Gstruct fb_info {
7 S# N" z9 m j$ U int node; //用作次设备号索引
. W0 |; |4 |2 _ int flags;8 l7 V' a* n8 n2 M; Q& ~ z
struct mutex lock; //用于open/release/ioctl函数的锁
+ s7 C) z& }0 h struct fb_var_screeninfo var; //可变参数,重点4 g, `7 v3 i1 X: h! d9 \0 {% e
struct fb_fix_screeninfo fix; //固定参数,重点, O5 q+ z& }5 i* l( d/ z/ ?
struct fb_monspecs monspecs; //显示器标准
! \4 f# ?+ ~1 T2 P! U7 B% M struct work_struct queue; //帧缓冲区队列
) j- J7 A: h% v0 X struct fb_pixmap pixmap; //图像硬件映射
o/ G5 h$ w0 a! N; v# o struct fb_pixmap sprite; //光标硬件映射
+ b8 \9 g1 D; T5 T: l6 y, I5 T8 | struct fb_cmap cmap; //当前颜色表5 @, x* { l' Z% F7 k
struct list_head modelist; //模式链表
! A' |" H$ ~6 M% ], B% z struct fb_videomode *mode; //当前video模式
- P( J t7 B' B6 ?& r% e
" |% |* T |5 ] char __iomem *screen_base; //显存基地址" E: I! S, _' z* R/ t, \- t* _9 A4 ^
unsigned long screen_size; //显存大小9 X6 L2 e. J$ a3 c3 m& @
void *pseudo_palette; //伪16色颜色表
0 O0 g9 D$ L3 ]' W/ g% ^7 Z/ Z/ Q#define FBINFO_STATE_RUNNING 0
+ j' E8 \2 u$ g- F: G( G) R* c#define FBINFO_STATE_SUSPENDED 1
6 D2 _9 n% A. a3 y+ l3 G u32 state; //硬件状态,如挂起, R" _5 K/ k' s4 r
void *fbcon_par; //用作私有数据区
' J4 i l# Z$ x U! h$ H1 I void *par; //info->par指向了额外多申请内存空间的首地址2 b# U( G3 e5 V- |4 A l' g$ }8 F5 c
};3 d. @ j# F) s o) M' J
s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息
2 V. {0 q+ x/ u1 ]4 f5 m
+ a& N; s6 }* y+ Kstruct s3c2410fb_info {
6 l0 Q$ y' q7 Q7 |3 m$ x% m: v! y struct device *dev; //设备* l$ x+ O7 Y3 T. [# D$ I
struct clk *clk; //时钟0 s) x5 h. o7 L, P) x- U* J7 \
' J- g, L0 `+ t: f9 |/ S- Q0 ?) d: } struct resource *mem; //资源
4 P! m0 B) f: I U void __iomem *io; //IO地址3 `/ X |6 Y$ h) y" ~) W
void __iomem *irq_base; //IRQ基数
- m1 r3 Q% W0 S C8 ]7 C6 {" ~3 H+ o) ]/ W" o& H5 K
enum s3c_drv_type drv_type; //驱动类型,S3C2410或S3C2412
1 `( D; q; [; t' z" T- J% W' q struct s3c2410fb_hw regs; //s3c2410 lcd硬件寄存器
3 M# o1 x5 n) I1 K$ |1 i: v7 ^, u! b5 e# K
unsigned int palette_ready; //调色板是否就绪标志位4 W" e( `0 b+ O: D
# A6 i$ F4 k+ L- x- T: P( j- X# E6 | /* keep these registers in case we need to re-write palette */
5 G9 h2 R6 u$ U! o( O1 }* G0 T u32 palette_buffer[256]; //调色板缓冲区+ ?. @1 M- u e/ ]
u32 pseudo_pal[16]; //伪颜色表/ A! E `# M6 J9 ~" _. ~
};* T0 `' g2 D( x8 ^; ]
s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等
% n& X" D4 c! [8 B
+ W/ b3 N, S; I8 w$ G- i0 P6 h/* LCD description */
, S" s& _: N: w. N# h" M1 M estruct s3c2410fb_display {
3 q' _5 C4 R" ` /* LCD type */
6 G3 L, X) l+ M3 E6 | unsigned type;$ |) o9 j4 \1 J; g
% N- @ F o# o" U! U; C, m5 d4 `1 M /* Screen size */
3 z3 X# `: m, Y a( ]/ R7 H! n) K unsigned short width;0 R) P" Y3 @% j* Z5 V) K- l3 N
unsigned short height;
: _7 q5 f, X* c/ f& t$ t9 p
4 g. j' M0 Z* X$ X n" s" f! F /* Screen info */
( G& ?2 U& k4 y unsigned short xres;- ?+ Q' R. i2 R4 e$ i
unsigned short yres;2 m9 k3 L. y' a7 R$ l9 r
unsigned short bpp;
- ]4 ~ @- f; d- Y% Z/ w( ?' X# }" i( @" F! f7 q4 _+ `
unsigned pixclock; /* pixclock in picoseconds */0 R c+ K% d* \. C/ m
unsigned setclkval; /* clkval */
: [: s0 N& }9 j unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */
3 K) c% V$ g+ V6 F unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */& ~2 L! n7 I/ p! k- \
unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */' v8 Z- a, I! E- S' j
unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */! @+ ]. l. P4 ^8 j
unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */$ z, S R H; w( s t, {! m
unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */
: R. u6 N* h3 h" }6 W) U4 X4 B# M1 B; R3 V7 k3 Q1 \
/* lcd configuration registers */9 a# P% Y; g' P. C
unsigned long lcdcon5;4 |9 Q4 n8 R. Z
};5 m6 \9 Z5 u, g4 A0 d8 U$ ?! \0 g
对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
: \1 z( B4 x- W4 S1 l$ f3 f$ Z* h4 C u' _) j5 P: j
/* LCD driver info */; l- s% _3 e7 }9 n) V$ o5 g
static struct s3c2410fb_display tq2440_lcd_cfg __initdata = {; V! Z/ \/ ^9 D( B. A- ?
.lcdcon5 = S3C2410_LCDCON5_FRM565 |6 P' o& y# z' J4 {# b- ^& \; ~
S3C2410_LCDCON5_INVVLINE |0 B5 ^# f" z/ k; `4 k
S3C2410_LCDCON5_INVVFRAME |/ g! b6 ^( n7 Y" P9 W, w
S3C2410_LCDCON5_PWREN |
7 f, K& @( F x/ J, i( C S3C2410_LCDCON5_HWSWP,
! I- [6 W3 _! x; d .type = S3C2410_LCDCON1_TFT,
@8 S# n: m3 @ /* TQ2440的液晶是4.3寸的,分辨率是480*272 */! ~1 e# Y# F5 @+ B% y5 p) ~7 t
#elif defined(CONFIG_FB_S3C24X0_TFT480272) /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */" o5 O( m' [- x5 g% p
.width = 480,+ ^% x" ^; V; X" m
.height = 272,
, ?3 ^ f& I# Y2 A3 M' ^, x- \ I3 H) f J' u: M! [3 D [6 ]& C
.pixclock = 40000, /* HCLK 100 MHz, divisor 1 */( K; g5 Z. G( V R8 G
.setclkval = 0x4,% B; \: q6 s/ a1 Q1 U
.xres = 480,
/ A8 s& K; I! B. l .yres = 272,* |; X5 _8 @) |$ Z) }0 B
.bpp = 16,/ s. N: o1 z& o a/ X) v1 M* F
.left_margin = 19, /* for HFPD*/( z& I/ j) ]3 t( Y6 j( t+ I
.right_margin = 10, /* for HBPD*/
; M0 `3 i% E9 ~& e# ]& I# U .hsync_len = 30, /* for HSPW*/
* j8 X6 A" y' t! T" ^ .upper_margin = 4, /* for VFPD*/
7 d. e7 `, `* y% ^9 r, A .lower_margin = 2, /* for VBPD*/
: a. m8 r! p' M7 F; ? .vsync_len = 8, /* for VSPW*/+ M, k& k* ~- Q/ w; f% D( o
};, _- Q4 S# d% u/ D5 l$ K0 I
s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体- ^# z7 O# d) e& Z
E( m$ p) l w4 p/ N* u8 i# R% v
struct s3c2410fb_mach_info {8 `* z- G! d! \/ J& B( u
struct s3c2410fb_display *displays; //s3c2410fb_display结构体
# ?5 f# u2 v% `/ N" T- P0 q. K unsigned num_displays; //displays的个数
2 c: q' Q6 i2 ]4 u unsigned default_display; //默认的default_display个数
: E3 ]! [6 ^# x# J2 T8 A
' U5 M R A; z" c1 A. t( g! l /* GPIOs */
, f7 ?2 ~8 b) g5 {+ } unsigned long gpcup; //GPC
( p9 q5 T; L2 w) J: i5 a' ^ unsigned long gpcup_mask;: M3 i* |& g: M
unsigned long gpccon;- Z( j/ U* a& ~' T$ B) C! y% x
unsigned long gpccon_mask;
4 e1 q% k# F9 W4 C" B% Y unsigned long gpdup; //GPD
W% _4 E3 ]4 B* q( R7 } unsigned long gpdup_mask;( D; S b6 ]. `8 {6 N) f5 @- {
unsigned long gpdcon;# \) x5 w: Q% h% g) T7 u
unsigned long gpdcon_mask;
' z: G2 D' D/ e1 B- d
; d; i) T }( [ /* lpc3600 control register */
' i# q% Y' X3 c* l/ k7 @ unsigned long lpcsel;- c. e+ W! T. u5 M6 G) t
};
' ]4 S5 m& i) R7 b( D5 N$ L+ L0 ?: S. n; U4 |
" l$ B! o6 D* `$ I" t! [ |
|