找回密码
 注册
关于网站域名变更的通知
查看: 279|回复: 1
打印 上一主题 下一主题

linux lcd设备驱动剖析一

[复制链接]
  • TA的每日心情

    2019-11-20 15:22
  • 签到天数: 2 天

    [LV.1]初来乍到

    跳转到指定楼层
    1#
    发表于 2020-4-20 10:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

    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

    该用户从未签到

    2#
    发表于 2020-4-20 13:24 | 只看该作者
    linux lcd设备驱动剖析一
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-26 00:29 , Processed in 0.171875 second(s), 23 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表