TA的每日心情 | 怒 2019-11-20 15:22 |
|---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c
- N3 c( y1 }) M6 U5 M
# S0 b# m9 x9 U1 l$ l$ |# o' @" C看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数8 ^5 x6 l! P0 Q. W; ?& r
9 B2 J* c% o. t% {8 Q; K
l5 A2 t4 k$ R) L6 oint __init s3c2410fb_init(void)
/ _& X% T5 K! S+ F{
, j6 `1 J, A; x* E /* 注册一个s3c2410fb_driver平台驱动 */0 E/ p2 k* S3 o/ P$ @$ l
int ret = platform_driver_register(&s3c2410fb_driver);+ B! C" \0 M6 S, u$ P K* ~
- [6 [1 R$ i. Y6 H/ e1 `1 M N
if (ret == 0)
: Y# z& i/ P! y' C. Z1 }% {( x ret = platform_driver_register(&s3c2412fb_driver);; I& S! S" ~6 ?5 e
/ x" `: I/ f- {: b return ret;
9 h8 f. O- K% X- V6 p+ f! Y4 j6 ~7 L4 y}' [ t9 {3 g- S! X
出口函数,自然是注销s3c2410fb_driver平台驱动. x9 l0 b- n B; |- v
% K/ M, q1 b5 q+ A" cstatic void __exit s3c2410fb_cleanup(void)
; T; u- a; M1 d{: ^! j8 R9 d( H* w; ]) \
platform_driver_unregister(&s3c2410fb_driver);; o# h7 J* ^' Z$ {
platform_driver_unregister(&s3c2412fb_driver);
. A6 t. h+ q! Z% x6 O$ Z2 l}
3 w/ c/ H6 K# j1 g& {. ~3 h我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。) L" z( o, K! e3 i/ X" H
, H7 L: @ T' s3 F; h0 ~3 k
static struct platform_driver s3c2410fb_driver = {
L% B! _: \) X C# o: \ .probe = s3c2410fb_probe,, y1 v1 A5 N. }, [6 f
.remove = s3c2410fb_remove,
, m8 n& X: |7 g k" h. ?* z8 S .suspend = s3c2410fb_suspend,$ `8 m Y+ ?+ I/ ~, t) j2 c
.resume = s3c2410fb_resume,
7 ~' c) \8 K: X* G5 i h1 F6 \ .driver = {
3 ]. a- ]. Z0 Y5 H2 [, d' g .name = "s3c2410-lcd",
7 z% f0 F+ P- y0 d0 v- q* _# t6 V .owner = THIS_MODULE,( J/ x. W2 ?5 O6 s/ c5 _
}," U/ m% a; E4 b0 B
};
; H0 x, f+ a! C3 l0 B这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。7 Z! S* ^8 r+ r- o# s: s
在source insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段
7 f( c+ u7 c0 S' X) j$ T @% u) c8 ?0 W9 \1 ]0 P& I& x
# p; z& @$ V$ L2 [# S- gstruct platform_device s3c_device_lcd = {3 `3 j, }6 H1 i7 g
.name = "s3c2410-lcd",
, ^: P% }$ M0 `# Y" r .id = -1,9 S4 F& l- A9 B6 |# y1 k+ \9 H4 `
.num_resources = ARRAY_SIZE(s3c_lcd_resource),3 o+ }3 a7 C$ y0 V, O8 ?5 u
.resource = s3c_lcd_resource,! \9 g) I% D' `' s) N7 G
.dev = {2 ?9 A/ F0 b7 Q) s. R$ V
.dma_mask = &s3c_device_lcd_dmamask,' [) L1 N& n) D/ u1 K
.coherent_dma_mask = 0xffffffffUL
. S& X' y! Y/ H3 C }
/ B I. a6 d$ u }$ @$ @2 l+ D};
* [' P! y u6 ~/ A; w; e: c; |/ t; ?, L( [ w
EXPORT_SYMBOL(s3c_device_lcd);0 h9 S1 N- `9 H. {* f! C
其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource
2 d: E. X% P3 ^" Q6 ^1 O+ a
; [1 Q" m0 g# n( Q, J0 p. ~static struct resource s3c_lcd_resource[] = {$ |) B3 D, J/ M# A6 [" Q
[0] = {4 m9 Y3 M# q: ?* G
.start = S3C24XX_PA_LCD, /* 0x4D000000 */
/ T F A& ~( k3 E2 ? `% x .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,- j7 L7 o* ?+ O5 a. U
.flags = IORESOURCE_MEM,. Q' s( i1 l$ c
},
, w1 a+ m I: F3 s, f' O. ]9 o [1] = {
2 g$ L( s9 M& a .start = IRQ_LCD, /* IRQ = 32 */
( {! W4 {5 _ W, F- R .end = IRQ_LCD,, D7 d3 e& s" r7 y. E
.flags = IORESOURCE_IRQ,. N! r; s A9 {) X# R+ D) p
}' R2 J& b% N" }5 l
; Q3 ]* w5 W! @};
5 k T9 k$ R6 I7 ]; t; g3 S3 I/ K5 L5 m& K& z* P; q& G7 \1 ^
static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
. s+ e( q p) A* q U; w那么接下来当然是要分析probe函数了3 n& I* \5 b/ W4 c1 h$ b( h+ T. u1 F
! O1 ?) T* d; F, Q' hstatic int __init s3c2410fb_probe(struct platform_device *pdev)6 H D! c* l# }% j$ G
{, H/ p- |" q( L$ _# p. O/ c
return s3c24xxfb_probe(pdev, DRV_S3C2410);
3 Z8 v: I- @, N$ G8 z}8 u/ c2 p* y8 Q' ]$ O4 Y* X$ |6 z1 ?
s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。& E7 j3 E" }" X- L9 b# S3 g
linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
& u% d ^" G/ y' D
0 A) d9 b* l, X4 t" w8 J帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。3 e1 C8 O/ e1 }7 q; o- |9 C! G- Y
2 k3 \. ?! c% ]& }2 O( j9 lstruct fb_info {
9 V) \% V! H1 Y/ ?6 S( O int node; //用作次设备号索引
* S$ C9 e, {0 p2 Y int flags;+ g I3 B0 H$ v! w+ d
struct mutex lock; //用于open/release/ioctl函数的锁$ W7 H. C' u. T& a' U
struct fb_var_screeninfo var; //可变参数,重点
; [: ?( u- D7 Z( k+ E' P/ R struct fb_fix_screeninfo fix; //固定参数,重点7 @, `8 R* @! O' J
struct fb_monspecs monspecs; //显示器标准0 P9 |: r m! z! `$ }9 S
struct work_struct queue; //帧缓冲区队列
: G3 R# V: R$ `( F: V. a+ J6 l struct fb_pixmap pixmap; //图像硬件映射7 ^5 M' X' s) `* P4 j2 W
struct fb_pixmap sprite; //光标硬件映射% a8 u5 P. H2 D0 K' S2 x
struct fb_cmap cmap; //当前颜色表
" x' c" o& z0 a2 r struct list_head modelist; //模式链表* k; G7 A- }* K0 x& H# N. M; ]
struct fb_videomode *mode; //当前video模式
" o& U$ A; G+ u: {" f9 G1 R1 y1 w/ r% n
char __iomem *screen_base; //显存基地址
5 e) n. D1 h4 h0 ^ unsigned long screen_size; //显存大小' h* a% u% \* N7 B& A
void *pseudo_palette; //伪16色颜色表2 x4 h# P+ [# F' }" e9 r8 u5 s9 i
#define FBINFO_STATE_RUNNING 0: `+ r/ k6 x8 A% }! B; C
#define FBINFO_STATE_SUSPENDED 1+ X, f- K9 n7 ~# |" }" ]+ V( j) h
u32 state; //硬件状态,如挂起3 ]8 w7 V W: O- K- ]" f( p' s: R5 _
void *fbcon_par; //用作私有数据区9 V: V3 B# Y$ G2 Z' \& B
void *par; //info->par指向了额外多申请内存空间的首地址4 a# k5 h3 \& M9 W1 W. J& a% h, U( K+ w
};
Y% | S* t# O! j8 m( qs3c2410fb_info结构体,这是s3c2410抽像出来的特有信息- A6 O8 e% O" R9 O1 {, g; I
6 \! i9 [0 t' s0 j5 z: b D
struct s3c2410fb_info {
- E9 H* o ^! x* N/ _" y struct device *dev; //设备
# s3 y" x4 B1 m# h t- {6 ]. r struct clk *clk; //时钟9 `" X; E7 S1 O" ?# R2 O+ H
; U+ f0 [) _, b" i+ T2 b struct resource *mem; //资源
+ o8 S+ t9 V6 Z, Z8 S8 } void __iomem *io; //IO地址
: _/ A) z5 _+ S+ C% l void __iomem *irq_base; //IRQ基数! L, G# Y* ]( q. p" j' t4 J6 [, ^
R: q0 P( ^+ D& ~1 x& O/ |, Y
enum s3c_drv_type drv_type; //驱动类型,S3C2410或S3C24123 E: k. L+ q& u" Z. h
struct s3c2410fb_hw regs; //s3c2410 lcd硬件寄存器 s6 Q/ B0 N$ ?7 [
) B: C, Q! E+ Y& V; t unsigned int palette_ready; //调色板是否就绪标志位
, u" m0 t9 o9 G0 _0 s7 s' R I
: r. n( L ]2 H /* keep these registers in case we need to re-write palette */9 t5 Z/ h* j8 R+ x# b
u32 palette_buffer[256]; //调色板缓冲区
5 ^$ J& Q+ }( @$ k u32 pseudo_pal[16]; //伪颜色表
( {7 L) h. i) H" P: Z" }};1 y! m8 |1 m' d* }; h
s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等# \& M8 R. S) f+ f" z( y3 g
: ~% U9 m1 b+ u0 ^2 b/* LCD description */* t. t7 c( q$ ?1 t3 D3 u
struct s3c2410fb_display {7 M4 P# s! P) Y2 d* \, J0 U2 Q
/* LCD type */
6 ]3 d$ m' ?- w, G% q3 ] unsigned type;
+ c5 {7 M5 _) m. R/ q, T- }8 k w G
: _0 F# Q1 e% |8 a2 G: s /* Screen size */
# V! C) j$ l: l4 P2 k3 N unsigned short width;: Z5 K1 z5 {& j$ e4 I9 |
unsigned short height;
9 [/ P2 Z6 O+ C; Z- m) g' u6 s, \3 b7 M# O- e, E' Y \
/* Screen info */$ p6 ~: j0 |/ k+ ] k! {, p
unsigned short xres;" ]8 \: z6 L P( |
unsigned short yres;6 S3 W- }9 {$ h. G" s
unsigned short bpp;
* h- ~! {2 U' Q9 a; [8 e
9 y% z7 H2 d) m9 M6 ]& _3 Y1 t+ Y unsigned pixclock; /* pixclock in picoseconds */
8 J8 f! c$ }& B4 P' P% {2 R unsigned setclkval; /* clkval */
: o D U2 }* v$ b2 L9 g! T# x7 v unsigned short left_margin; /* value in pixels (TFT) or HCLKs (STN) */- `( m4 }6 {& Q3 [" ~& B9 o& t0 l" F* q
unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
7 e7 G* M0 V5 [3 R- J& r2 [& x unsigned short hsync_len; /* value in pixels (TFT) or HCLKs (STN) */
& o; Y) g# D+ i2 z) ?2 b unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */+ l. u- z D, ] C1 }" k# k8 s
unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */5 @5 }3 E8 ` Y% ~2 E: y) i7 t
unsigned short vsync_len; /* value in lines (TFT) or 0 (STN) */) y/ W# M( e& F# |* S
/ d' c9 z7 {' h2 T3 I
/* lcd configuration registers */
9 w6 S6 T) `& P unsigned long lcdcon5;2 K* }! J, P9 O& [. B" D" g: |( b
};4 W, d( l% L; E: r0 ?5 K
对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置0 B" [ Y9 ]6 Y7 I0 r6 m
1 H7 P7 W; G9 e' w$ N
/* LCD driver info */
7 A- ~+ ]2 [3 `5 ?" s3 t5 o \static struct s3c2410fb_display tq2440_lcd_cfg __initdata = {% ]. m( Y" U: i! O- b
.lcdcon5 = S3C2410_LCDCON5_FRM565 |# v* Z4 V* c+ A$ W T
S3C2410_LCDCON5_INVVLINE |$ t- H- P+ m* p/ J, C
S3C2410_LCDCON5_INVVFRAME |
( v1 c; r- E' f; ?8 t1 M S3C2410_LCDCON5_PWREN |0 B9 S2 L* e7 Z( R5 C
S3C2410_LCDCON5_HWSWP,
4 l* \% {/ b7 P; ~1 e& g' C; A) f8 g .type = S3C2410_LCDCON1_TFT,, Q. D) F( O! H: G
/* TQ2440的液晶是4.3寸的,分辨率是480*272 */
% P. S/ D: [! v- X& c#elif defined(CONFIG_FB_S3C24X0_TFT480272) /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */
& ^! L6 X/ I2 x6 U. ^ .width = 480,/ s" a) I% G0 y& a7 s0 a, T. v# Y
.height = 272,, ]" h6 g/ O3 L
1 B9 @9 [: I, C: n; ^
.pixclock = 40000, /* HCLK 100 MHz, divisor 1 */
2 Y+ r* l, C: [ .setclkval = 0x4,
/ d8 \$ z, p2 R) q" O/ Q; \4 P .xres = 480,
# I$ J# P9 Z2 R J .yres = 272,& _6 ~8 U2 B. S& v& R% f; \
.bpp = 16,
. m0 J' s/ `- R/ f' ?/ K0 B8 }1 x ` .left_margin = 19, /* for HFPD*/3 v; C- T2 u5 z8 b* d
.right_margin = 10, /* for HBPD*/' o$ o! B f+ t( v0 i
.hsync_len = 30, /* for HSPW*// X( o) Q U/ o# H( \2 B
.upper_margin = 4, /* for VFPD*/
0 @3 ?" u# [0 z/ x& i+ R5 n4 O .lower_margin = 2, /* for VBPD*/
9 }8 f! N) G' c5 g .vsync_len = 8, /* for VSPW*/
" o; ~( e$ v* [$ ?5 s/ I& u};2 d& T0 H k& z! n
s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体; y6 N7 t3 Y6 d0 ]1 o# T6 o6 `4 F
9 L' P5 H. y) K6 M3 B) _4 lstruct s3c2410fb_mach_info {: E' k5 S6 L% Q! c7 I
struct s3c2410fb_display *displays; //s3c2410fb_display结构体
+ l1 f; |! z p- q unsigned num_displays; //displays的个数+ Q1 j; f/ p( A' h" ?" f# ?9 r; K
unsigned default_display; //默认的default_display个数 R) Q1 L- e" H: Q8 d
1 y9 ~1 b0 V, m4 ~- \) \ /* GPIOs */
0 j" x7 p. G7 p7 ^& M unsigned long gpcup; //GPC9 \" e8 e5 r/ v
unsigned long gpcup_mask;) @& B4 _( I# S
unsigned long gpccon;: K' E. W" W" v. g6 S
unsigned long gpccon_mask;4 }* M- @% T+ @3 O4 I
unsigned long gpdup; //GPD
$ c# S& N, n, r/ Y# B0 B* d1 |# V unsigned long gpdup_mask;
% J3 O2 J/ O$ b, O* O unsigned long gpdcon;
( m5 N$ Z9 L2 u O. D/ ^3 P unsigned long gpdcon_mask;
0 m, y* n% c- @. z8 f( l- O
2 L- z+ x2 {4 M' ?8 q/ X /* lpc3600 control register */# I; ~: ^) n6 [$ g- p% D ^
unsigned long lpcsel;
( M0 w6 F/ A: x! n7 m};
- h) _! }$ e& r3 n
; J2 r$ D: w q$ U- N- I& L8 O: v! J
|
|