找回密码
 注册
关于网站域名变更的通知
查看: 282|回复: 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" Q- I; O0 p1 J+ m. X1 f4 v  Z
    # V& s4 {( X6 [
    看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数  O8 S3 z3 Z8 P) w1 I5 s# a% I
    / s/ T2 E" L4 p

    % Q- `/ z4 J5 f1 @6 @int __init s3c2410fb_init(void)$ F& v6 @% I6 I$ ]) i- b
    {
    # l" n6 f9 p2 b6 i: i        /* 注册一个s3c2410fb_driver平台驱动 */
    8 w7 y0 z6 L/ I        int ret = platform_driver_register(&s3c2410fb_driver);
    * \+ r4 S4 v4 y4 n9 q& V# q1 j& V4 r
            if (ret == 0)
      R3 @- _1 s: A5 a% M                ret = platform_driver_register(&s3c2412fb_driver);;1 L# K; Q$ T2 v3 n4 N) P! M0 t% b8 U

    " `9 S' S: ~+ o5 g1 A        return ret;
    : q8 A$ z$ R5 `0 o}
      g" @2 Q$ Q: G) x出口函数,自然是注销s3c2410fb_driver平台驱动) a3 j# m8 ]$ `) h8 Y3 g

    2 ?3 w9 r8 e# F7 F0 v; n3 Ystatic void __exit s3c2410fb_cleanup(void)
    ) j, l$ Q" U6 I; i1 Z- U{- R) N* e- |6 V) Z
            platform_driver_unregister(&s3c2410fb_driver);1 k! ^' g7 [8 X% I4 l
            platform_driver_unregister(&s3c2412fb_driver);# \# k! ?5 P! }, @) h3 }& a
    }# h; K6 {$ b- ^/ d7 d
    我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
    / q9 R5 M+ a9 H* S
    + l& S& P! x7 K" @static struct platform_driver s3c2410fb_driver = {
    7 ^/ i) S4 }$ U& M% r5 {' m        .probe                = s3c2410fb_probe,
    " q/ o2 ?) P  j        .remove                = s3c2410fb_remove,' V# q7 i8 H) s# M
            .suspend        = s3c2410fb_suspend,
    & E2 U+ A/ n$ q& q        .resume                = s3c2410fb_resume,
    + u* }- ^! A2 C/ P! I        .driver                = {) a. i$ ]' ^4 \
                    .name        = "s3c2410-lcd"," k' u' e) I; b
                    .owner        = THIS_MODULE,4 t9 i9 _/ N3 T# Z/ F
            },; j1 {# K. {, p2 z* m7 U" e: v
    };; ~7 _; e  H% c7 s% H. c* F
    这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。
    5 O8 H0 j% P, U) G: F# m在source  insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段4 ~$ B5 x  Q; j- {0 N
    ' m" k2 A# J& [8 l% a
    / [2 J  k7 t. ]+ f- }/ f; {3 r2 S; u
    struct platform_device s3c_device_lcd = {4 y+ H0 V1 b% _  y' h* s
            .name                  = "s3c2410-lcd",
    ) U0 ^% H+ u! T4 M8 ]4 y        .id                  = -1,4 a7 f/ Y- v. ~9 B
            .num_resources          = ARRAY_SIZE(s3c_lcd_resource),% K- w- _! V8 s$ T  k! ?
            .resource          = s3c_lcd_resource,
    3 m- p( ]0 g) l' f        .dev              = {: E, V. R( K- B; a' f
                    .dma_mask                = &s3c_device_lcd_dmamask,4 b/ {5 C0 Z  \9 ~+ |6 x; _8 t
                    .coherent_dma_mask        = 0xffffffffUL: I& X7 E4 }$ T+ B& m  o1 e
            }
    ' w; a/ L% e0 b. M};
    $ N7 f$ `/ B! a% q# d# _
    : d2 k1 U4 U# T; ]8 BEXPORT_SYMBOL(s3c_device_lcd);
    ! ~7 d6 b1 Z% c" D9 w: N. M7 x1 F其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource
    5 a8 G% S5 \5 A
    + d5 J# M) M+ Y; c1 k% pstatic struct resource s3c_lcd_resource[] = {
    5 z2 i! b) L" m7 I: S        [0] = {
    ! h" L- x" \0 f7 D. a                .start = S3C24XX_PA_LCD,                                /* 0x4D000000 */
    % F( J7 Z; N: @% F7 V; _                .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
    * |, q& u8 w8 m2 @  y7 ~% H" }                .flags = IORESOURCE_MEM,4 t7 i  r  {, w
            },  f5 H- z% C6 \+ t& w
            [1] = {4 Q) x( j' q  R
                    .start = IRQ_LCD,                                                /* IRQ = 32 */
      l1 p7 w- f7 k* e5 q                .end   = IRQ_LCD,
    : u$ k5 c% c# K0 J$ H                .flags = IORESOURCE_IRQ,
    * T! N$ P, {9 {' N, P        }
    ; a  k, E' E$ G$ W* |
    0 q6 Z7 `6 X* j! v7 g/ z. D. o};9 ?, n( I( E4 I6 F
    9 D- w: s4 z' D7 R2 H
    static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
    ( m+ G( @2 U/ d& h! B那么接下来当然是要分析probe函数了! _+ F6 f- F  X9 l
    & D8 k! O! E* C) ]
    static int __init s3c2410fb_probe(struct platform_device *pdev)' |/ P& ]/ _7 K' L* E- B
    {
    0 g, T7 p3 d& T  i, P9 a7 n        return s3c24xxfb_probe(pdev, DRV_S3C2410);, E0 T& _! M; ?' [* @
    }
    ! G0 M8 C* D. g& Z* x& h' J$ ls3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。% a7 Z' D- s+ E: f, C1 O
    linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
    1 \0 ~% q  B$ z! v- u+ N1 B: Q5 n9 ]7 r; Z
    帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。. v5 T* ]6 S/ ^. c
    2 r7 n: E' O* S2 J
    struct fb_info {% y; j0 _7 Q: B3 y; ?+ i9 F* u
            int node;                                                //用作次设备号索引/ k; D8 j$ o- R) a8 i
            int flags;5 q1 ~# T. O9 X" i7 U# V
            struct mutex lock;                                //用于open/release/ioctl函数的锁5 s+ n* w8 W: a/ Y' }+ d
            struct fb_var_screeninfo var;        //可变参数,重点
      p" U5 |) @" E# S# j, ]        struct fb_fix_screeninfo fix;        //固定参数,重点
    # x6 I% [# d; D6 H0 `4 {. k        struct fb_monspecs monspecs;        //显示器标准
    * F" v. z9 {7 P  c        struct work_struct queue;                //帧缓冲区队列( Y6 k' X, `0 u* y0 P4 N$ m
            struct fb_pixmap pixmap;                //图像硬件映射
    9 _( l. q; q, Y; U( g        struct fb_pixmap sprite;                //光标硬件映射) g. |0 q% S. a: d
            struct fb_cmap cmap;                        //当前颜色表8 K* R2 d  `; @6 f! f$ j" r
            struct list_head modelist;      //模式链表9 T) ?. t, R  d
            struct fb_videomode *mode;                //当前video模式9 v$ X/ w3 v9 Y6 x% F: w% o# `* K( {

    : N! a2 S6 _& |5 E1 g) f8 [        char __iomem *screen_base;                //显存基地址* [. N$ n6 }' W: V: l' K" {7 d
            unsigned long screen_size;                //显存大小- t5 [8 r  }* t+ z+ c  n: _
            void *pseudo_palette;                        //伪16色颜色表$ X. e6 @1 @' ~' [/ \. _3 U
    #define FBINFO_STATE_RUNNING        0+ R( L) m. ]. m5 b
    #define FBINFO_STATE_SUSPENDED        1
    $ h. X1 ^* j0 N" A        u32 state;                                                //硬件状态,如挂起
    , g/ g# o9 ?& v0 F; F# B4 ~        void *fbcon_par;                //用作私有数据区
    7 U+ y9 y3 L. F! ]* d        void *par;                                                //info->par指向了额外多申请内存空间的首地址9 X5 @8 O9 S2 ^4 Q
    };
    ( C5 V  ^( m7 x; ~s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息
    & ]# _" ]7 I9 p' {" z" k5 y5 {% |$ ~1 b8 B9 G: N
    struct s3c2410fb_info {" r& v' u' ~) w. q% \; N& Y* P
            struct device                *dev;                        //设备$ {. Z1 S' s! X
            struct clk                        *clk;                        //时钟
    5 P5 u7 e( O) K) V3 g+ Q3 w3 X, R
            struct resource                *mem;                        //资源+ {! l: W0 g' l, X1 _$ P7 w$ x
            void __iomem                *io;                        //IO地址
    2 g, u! A" h8 ^6 f6 T5 {; i8 d- Z        void __iomem                *irq_base;                //IRQ基数
    : m; o7 u, h  W; j+ W+ A3 R( `- q. ~+ J0 |
            enum s3c_drv_type        drv_type;                //驱动类型,S3C2410或S3C24125 `# ?& V8 Z, p& c( C+ u
            struct s3c2410fb_hw        regs;                        //s3c2410 lcd硬件寄存器* U9 k9 ^5 T) y% z

    6 `7 w2 S& k: n$ a' _* c! s+ o        unsigned int                palette_ready;        //调色板是否就绪标志位. o( K( H% ?0 I/ p" \3 [" ^* w
    5 ^& |) ^7 W( z$ x3 z. ~) B( f
            /* keep these registers in case we need to re-write palette */
    + m) ?# s6 T. b0 G        u32                        palette_buffer[256];        //调色板缓冲区) b2 G$ A" ~$ I( g
            u32                        pseudo_pal[16];                        //伪颜色表# W5 U. V9 ]: k. J
    };) O% v) e# h3 E6 n0 @" |
    s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等$ G5 U6 z% z) i) e# S- k% R
    6 o7 V2 i  h6 {$ l9 Z# N
    /* LCD description */3 P4 n. N' f# Y7 K4 {, E+ k
    struct s3c2410fb_display {* ?0 `/ C' g6 \% B' r
            /* LCD type */
    % \2 p2 ?7 O( X: Q3 e9 \        unsigned type;
    / O( n- d9 B" `' K. b0 z9 K' [0 F# ]/ n$ @3 L' P4 p) t. t1 I
            /* Screen size */4 z" @: h# _; D  s; W
            unsigned short width;# j* T, b+ t: I, u7 _+ ]  N
            unsigned short height;
    0 ?( D) h2 Y( P3 ?! G5 m8 z; W: D2 p7 |5 }; _$ W& B
            /* Screen info */, B! A& n- m9 e9 R" w' r
            unsigned short xres;
    4 f9 c1 G1 N  F* P5 v1 d        unsigned short yres;
    4 p7 f& n5 g) A        unsigned short bpp;& }+ N) a6 K$ E& g! L

    + @( }' q; O! _        unsigned pixclock;                         /* pixclock in picoseconds */
    & G( h1 V3 i  q& R        unsigned setclkval;                         /* clkval */
    6 T5 N% w0 Q% c1 M7 R        unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
    2 s- ?" ?- R3 L8 l        unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
    + Y) }: A2 l' I8 P" a$ B        unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
    : p9 T: a: u5 `7 E) R        unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
    2 W! X4 `9 A' c+ s        unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */9 Y" n! ?6 E3 |& R% C8 B: J- s" H
            unsigned short vsync_len;         /* value in lines (TFT) or 0 (STN) */
    ; o2 C& @% _2 S" q5 v: R$ o# D; u
            /* lcd configuration registers */0 u7 v+ z) C! R" o1 l
            unsigned long        lcdcon5;
      \0 B. Y7 P' y" h& W};
    1 C6 X- r7 r7 q* F" f) s* C! C* H1 }对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置1 i* z1 y  \4 n3 K

    3 I4 i; e0 v( n* y/* LCD driver info */# V+ `7 x8 s8 E6 d
    static struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
      {% v. E4 Y. Q0 _# X+ T        .lcdcon5        = S3C2410_LCDCON5_FRM565 |! \2 R: X5 W' q6 w) m
                              S3C2410_LCDCON5_INVVLINE |
    ' z7 _% }2 T+ @# h/ k                          S3C2410_LCDCON5_INVVFRAME |! T: p# j; @1 u- p  t
                              S3C2410_LCDCON5_PWREN |
    ( f+ x& `! n# W6 h& v                          S3C2410_LCDCON5_HWSWP,
    . l# V6 W9 N# W& |8 C$ L2 J        .type                = S3C2410_LCDCON1_TFT,* w- w4 u: p! Z: f6 r
            /* TQ2440的液晶是4.3寸的,分辨率是480*272 */
    , ~6 C1 u# F2 M$ Y5 r& c% v" t+ R#elif defined(CONFIG_FB_S3C24X0_TFT480272)  /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */5 N4 J" g0 U! l/ U7 A& W7 m
            .width                = 480,
    9 K0 p) Q+ U& D8 m, \, C5 j+ l        .height                = 272,  J  ]! [2 F& ]: S, S$ p' E
    3 k2 E2 p# |, q- P
            .pixclock        = 40000,    /* HCLK 100 MHz, divisor 1 */
    & x. P6 k3 o+ @8 z: q        .setclkval        = 0x4,) A) g  A3 l/ I+ q. ~2 s
            .xres                = 480,
    1 n2 \$ P9 Z9 _# N0 `        .yres                = 272,; u2 j# T# U8 c, O) I, v9 Z
            .bpp                = 16,' ?' l4 O% \( U$ b) q) e. W, K) S. O
            .left_margin        = 19,        /* for HFPD*/
    8 Q4 Q, H; @7 N5 k6 Y' P        .right_margin        = 10,        /* for HBPD*/% m2 h. z" P9 w7 a) @+ f, j, I
            .hsync_len        = 30,                /* for HSPW*/3 g. ^; f2 J: v5 h9 C1 G; Z
            .upper_margin        = 4,        /* for VFPD*/
    5 h& I2 \1 S3 W7 V$ d& O' s3 U( `        .lower_margin        = 2,        /* for VBPD*/
    2 e" U. b( I+ z' N4 }        .vsync_len        = 8,                /* for VSPW*/
    % j) Z' f  _1 x- S7 X};
    6 A( H3 y# j$ E$ g1 C# N1 V+ is3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体
    ( E. H' V  M: q% b" ~
    $ t9 u" @0 C! m* jstruct s3c2410fb_mach_info {
    ; c" J( H4 A0 J5 C- ^' ?. o        struct s3c2410fb_display *displays;                //s3c2410fb_display结构体6 o. ]/ y: F- q/ J3 L, y8 Z4 J4 Q
            unsigned num_displays;                                        //displays的个数
    6 c  K0 r8 j! n# ^9 G# X: i5 |        unsigned default_display;                                //默认的default_display个数
    ) y* l$ q8 s7 F; M" F& S! L; K8 o2 f/ J5 e* b
            /* GPIOs */% D7 U2 }' s/ F; o5 y6 l9 i
            unsigned long        gpcup;                                        //GPC
    - y) v  p' X2 T) z        unsigned long        gpcup_mask;) Q  e" ^* P* M: l! }. o! h7 O$ [
            unsigned long        gpccon;3 j+ |3 g# A4 u. m
            unsigned long        gpccon_mask;. b( m* I5 X- m/ Y9 a! j" J
            unsigned long        gpdup;                                        //GPD
    * d$ ~6 y0 U) E3 t; y7 {$ Q; x        unsigned long        gpdup_mask;
    % D1 F5 _; F4 _+ K( m        unsigned long        gpdcon;
    8 `4 I; ~+ y; m        unsigned long        gpdcon_mask;# Y0 q/ K. k- O7 n. W
    2 {6 s$ n/ A1 z' Z- o9 k1 V
            /* lpc3600 control register */* ]9 @; X7 x0 E# z) ~
            unsigned long        lpcsel;
    & a3 g! T" |/ V5 w};6 U7 _. @- |6 I! T# W3 j
    1 g6 R6 t( w3 p' X  R

    " d. W  A; y' v* {5 b( X

    该用户从未签到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

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

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

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

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