找回密码
 注册
关于网站域名变更的通知
查看: 283|回复: 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
    8 M. ^( G0 V9 j; I: @% y  E& z
    * v& Y7 G+ y  N) N看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数
    ) \" Q: D" b4 L# r0 `# g* n. {
    1 _; b, w/ F. P! a4 Q
    . ]1 z- }1 _4 c( q  O+ E- A5 \% }int __init s3c2410fb_init(void)
    , G7 Z7 i# g8 K& e% u! {{* Z) G5 B# b1 H4 Y0 ?6 B
            /* 注册一个s3c2410fb_driver平台驱动 */- Q' H* X( x3 x1 u7 M( i. j( V
            int ret = platform_driver_register(&s3c2410fb_driver);
    4 i) {9 Z0 Z2 y8 n2 `
    5 K5 H0 d: S( S9 g: n        if (ret == 0)# w$ M. g( v5 b
                    ret = platform_driver_register(&s3c2412fb_driver);;
    : _- k) y2 W+ g, b7 [' Y2 Y) {: i' C4 v
            return ret;+ z. M# W9 `4 a' B! j( I' I; j
    }
    4 K" H' `+ C' j, x8 ]( W出口函数,自然是注销s3c2410fb_driver平台驱动+ v# i2 l' {3 A. [
    3 G9 C7 u) q% a% V
    static void __exit s3c2410fb_cleanup(void)
    - R' E( O0 {/ Z' P5 K{8 \5 ]5 k7 X( G5 c+ l3 ^3 f
            platform_driver_unregister(&s3c2410fb_driver);& }' x: c6 G6 T& f, Z
            platform_driver_unregister(&s3c2412fb_driver);
    & s+ w, }  j0 c}
    ; n8 f! T4 D# Q0 J5 C) V( u) @我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
    , u! i% \: Z$ V/ x8 O4 q5 f6 ~5 r3 O0 }0 V# k# C; o$ e
    static struct platform_driver s3c2410fb_driver = {
    7 d0 {& N; O- r& y7 U: A        .probe                = s3c2410fb_probe,
    5 V1 I8 D0 ]6 i. _! s& w0 Q        .remove                = s3c2410fb_remove,3 j1 @) Z5 _8 [: @
            .suspend        = s3c2410fb_suspend,3 X/ w& N0 C4 j% `" k  r* c
            .resume                = s3c2410fb_resume,
    6 g) A; k* l- d7 N6 X9 s9 ^        .driver                = {
    0 n" S$ U# Q6 _5 N: w( i$ G; N' \                .name        = "s3c2410-lcd",
    : F+ i2 f& X' C/ l                .owner        = THIS_MODULE,+ i- R; p+ j, }0 d; c. c5 v
            },
    4 @' Y3 s# R- V; \/ A0 {};- C; a6 S, {- j* U1 v- p& B( V
    这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。: }  E7 e! q" z# O1 z: l
    在source  insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段
    3 ?( x: f. F  \7 L- r* I
    4 k( s7 l% b" e$ y& p% h- A" f; G1 r. ]' P9 w+ L; E; _
    struct platform_device s3c_device_lcd = {, g0 p. c$ z  S, b1 M# m
            .name                  = "s3c2410-lcd",
    - A  W3 [* [& t* T        .id                  = -1,; {9 ]# W/ s; @8 ?8 u" ~0 |
            .num_resources          = ARRAY_SIZE(s3c_lcd_resource),
    ! ~1 F. }" D/ l' k0 a        .resource          = s3c_lcd_resource,
    % A) X( }- M1 \! M; r        .dev              = {1 s+ R; w( Z: Q3 b
                    .dma_mask                = &s3c_device_lcd_dmamask,
    4 \( ?2 Y+ Q( h! t                .coherent_dma_mask        = 0xffffffffUL& u6 h  j* q: Q& B9 I' o
            }
    6 L0 v7 i) _( |" A  i! Z};
    & R* B: b$ ^+ z/ t/ `0 ?4 T) H) G7 M& Z% n- W6 ]
    EXPORT_SYMBOL(s3c_device_lcd);) N+ J2 p# i8 I" w# Q
    其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource
      n' M5 t: v! i# Y
    ' R5 G* C( i% G' zstatic struct resource s3c_lcd_resource[] = {
    0 o1 T: @/ |8 S- O        [0] = {
    9 d% G; D7 M. [( \' z. |" ?6 O                .start = S3C24XX_PA_LCD,                                /* 0x4D000000 */
    - f% r1 ?3 I/ ^- ^. n& e                .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
    & Z3 p* W( T* G5 `7 z- u6 c                .flags = IORESOURCE_MEM,9 g% I9 R1 ^3 F5 u8 }( h
            },! Z, J7 B9 _- q- n6 _) k
            [1] = {
    6 `+ G6 E6 B5 s$ v% D                .start = IRQ_LCD,                                                /* IRQ = 32 */2 ~  J6 x, M2 F& M
                    .end   = IRQ_LCD,
    # k5 |$ K$ o2 s  @1 \: f) ], Q                .flags = IORESOURCE_IRQ,# D% a, |3 E" |2 U
            }
      k7 P) t5 Q) v+ G/ q) y$ N6 B0 B, [% {: a6 q
    };
    ; B* H/ L& Y% N# s' J& Z# ]" C- U( \5 |& h6 W$ J
    static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
    2 W; c/ L, o% Y0 o5 k5 L/ x* u# I那么接下来当然是要分析probe函数了0 D5 _) H9 W- F# w" x6 ?
    0 W- @7 U: ~3 Z6 P' H5 S  N
    static int __init s3c2410fb_probe(struct platform_device *pdev)/ e7 [2 O2 B- a/ t
    {1 w* h3 y' K% [
            return s3c24xxfb_probe(pdev, DRV_S3C2410);: l, W8 ^; r3 A- D; E
    }; J. G5 S2 ]: x- q- W! N& h
    s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。
    2 s& C' N. L, B1 X3 b: {3 Q/ nlinux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。7 C# h$ H9 J; ?
    7 u# d) l! ^0 W8 ^+ L4 k, r
    帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
    - ]4 C, k# h# L& y* i, G7 M! I- U  D! I: d
    struct fb_info {3 H( g) b8 V( n: f
            int node;                                                //用作次设备号索引
    3 ]2 Z, q8 {0 s2 o        int flags;0 r/ N7 e7 t& ?* k6 B/ r
            struct mutex lock;                                //用于open/release/ioctl函数的锁
    3 E: s1 Y0 ]9 O  Y' ?; U! ^/ |        struct fb_var_screeninfo var;        //可变参数,重点! I) `5 z, N& I" z4 M2 C; {
            struct fb_fix_screeninfo fix;        //固定参数,重点
    # ?! S3 G8 d* r$ ~7 _3 j  J' u        struct fb_monspecs monspecs;        //显示器标准
    . y6 F; H) k" A2 W        struct work_struct queue;                //帧缓冲区队列
    ! M+ M$ _8 c! n% T7 g        struct fb_pixmap pixmap;                //图像硬件映射
    ( ^9 f3 z* b; _3 [/ n        struct fb_pixmap sprite;                //光标硬件映射
    6 Q1 D3 k9 D3 I8 Z* s/ Y3 \        struct fb_cmap cmap;                        //当前颜色表+ e* k+ t3 b" Q6 l# h4 g) E
            struct list_head modelist;      //模式链表" |4 }1 K7 }# B' U8 s8 d3 p
            struct fb_videomode *mode;                //当前video模式
    + M) A. ~4 P" r+ Y/ }5 ~: e
    ) s7 p7 j& A( ^9 r# {5 L  w        char __iomem *screen_base;                //显存基地址
    " ^- G  p4 u/ K% H        unsigned long screen_size;                //显存大小
    , b0 K" |+ C$ N9 }: A7 o        void *pseudo_palette;                        //伪16色颜色表. p+ S# B6 U3 L0 s0 q5 m& q
    #define FBINFO_STATE_RUNNING        0
    , m! ~9 t' I- l# Y$ M6 e! T#define FBINFO_STATE_SUSPENDED        1
    2 s( Z$ U4 G* R+ H/ I% f  c        u32 state;                                                //硬件状态,如挂起
    & Q- t* `% j5 X1 ?) e2 B0 n        void *fbcon_par;                //用作私有数据区
    ( J; L3 O/ O! {% J( ^        void *par;                                                //info->par指向了额外多申请内存空间的首地址
    - ?" X6 L- d  C6 x+ A};  O  f8 M: u) e7 S1 F! V/ H6 x- Q
    s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息" T7 z: P4 w- g: |# a( g6 u

    2 T. |0 G4 p  h  c( L- H. z1 Nstruct s3c2410fb_info {
    2 d/ Y( E0 E* \$ r        struct device                *dev;                        //设备/ k- P& I7 {3 G6 R( r
            struct clk                        *clk;                        //时钟! j8 c9 V$ S- V4 e! V

    4 ]* q$ [* T; u+ N5 W        struct resource                *mem;                        //资源$ ~1 o1 s0 n5 _% X6 y
            void __iomem                *io;                        //IO地址
    + o. H+ a" H9 v        void __iomem                *irq_base;                //IRQ基数. z, Q5 [7 |; ^0 R4 O3 L1 p4 f

    9 u7 K6 P# B  L. n' y: ^        enum s3c_drv_type        drv_type;                //驱动类型,S3C2410或S3C2412
    & n! x0 W: y9 z# U* g) Y        struct s3c2410fb_hw        regs;                        //s3c2410 lcd硬件寄存器
    0 q- B. t; R/ h& _# T
    $ e# R. h7 S, C: S: U- \        unsigned int                palette_ready;        //调色板是否就绪标志位2 c% V4 L. F4 l* H6 T! I: K

    4 x7 X0 Q- A# ?+ e! h8 i$ h6 K        /* keep these registers in case we need to re-write palette */
    : F) [; d- v! {+ s5 ]$ B* w        u32                        palette_buffer[256];        //调色板缓冲区
    & ~* @) u( D1 `" M! M0 T' `        u32                        pseudo_pal[16];                        //伪颜色表
    $ t9 y; N5 c% Q+ h. J9 v5 N};
    " V; }) n& |" i; ns3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等
    1 L0 G! ~2 k& z) F& I5 |+ f0 Y- l7 f/ ~$ T& j) E  V. {
    /* LCD description */
    + J- S4 D6 D3 Q& S& Bstruct s3c2410fb_display {
    , W1 J& Q, g5 _# L( i        /* LCD type */) a' Q* y6 e$ l# u- |4 |' z2 i
            unsigned type;) v- y: k$ e  @" N6 Q4 c

    4 u- x. l3 `$ n. V# Q        /* Screen size */! s8 r) I" V) N/ K
            unsigned short width;
    1 d% Y% @: m1 P# z7 V2 G        unsigned short height;0 g3 y2 b- T& N; G

    . h2 x& a$ q$ M/ `' E3 h9 j7 `) Q4 J        /* Screen info */
    $ J( `0 C! f. I1 @/ A8 }        unsigned short xres;
    * `, x) Y" [' E8 Z3 t        unsigned short yres;
      i! M6 G( O; q1 v        unsigned short bpp;
    1 F, f5 K! B9 b# q' w2 U* _. v8 e3 v, f3 b& w+ i9 L9 ]$ X
            unsigned pixclock;                         /* pixclock in picoseconds */. N. Y- e  j' V7 v2 @" T' y2 ^
            unsigned setclkval;                         /* clkval */  |, }6 }" e6 k; C
            unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
    $ n  [: B5 [1 c        unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
    8 w# _1 H3 n8 S7 C) a1 l        unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
    ) k+ n9 o4 a/ U3 V+ N/ g        unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
    6 {5 i/ L6 b# G" L6 g+ x, i8 O        unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */9 a  _# }: }) o8 `! d# W
            unsigned short vsync_len;         /* value in lines (TFT) or 0 (STN) */3 }+ j" G2 t; c

    % w7 S  J* {& Y. M8 C; \. X        /* lcd configuration registers */
    2 y" ?: \1 b# t3 U0 w3 H) D4 c        unsigned long        lcdcon5;" I, l! f9 y: F  l0 H
    };
    3 R# i0 N. O, p对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
    1 W) N. M' W! T8 y& h; u2 @, N: k0 Z) N
    /* LCD driver info */
    3 \2 R' G" R# H3 b2 _+ }% Qstatic struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
    ( _8 D2 i5 K! i# c. S        .lcdcon5        = S3C2410_LCDCON5_FRM565 |( d: n3 n! {( O
                              S3C2410_LCDCON5_INVVLINE |
    ! D' n% a: Y$ {5 G$ ?                          S3C2410_LCDCON5_INVVFRAME |
    * ]+ X" L1 K  I2 B6 P                          S3C2410_LCDCON5_PWREN |7 b5 h% l7 L  x% S5 T  o; l' B1 {
                              S3C2410_LCDCON5_HWSWP,/ e2 @, s0 H7 H! j' N, f+ y
            .type                = S3C2410_LCDCON1_TFT,
    : [5 }0 q2 |; c( U, A' l        /* TQ2440的液晶是4.3寸的,分辨率是480*272 */1 }6 P' t* U& ?* e+ A
    #elif defined(CONFIG_FB_S3C24X0_TFT480272)  /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */
    % P% P; q  X  T/ N4 {# w% v        .width                = 480,' m' }; ?5 g; g2 f" M6 P
            .height                = 272,
    3 P3 L) R) X# [# C& P9 ^% Y# e
    8 i0 @' D; M$ N% q: F2 x. s        .pixclock        = 40000,    /* HCLK 100 MHz, divisor 1 */
    4 x# K2 h& z3 L6 T& ~        .setclkval        = 0x4,: G2 O( i  U& m1 t
            .xres                = 480,
    * h8 `; }  D/ n" T) l4 l        .yres                = 272,, \8 b! F5 Y' Q/ I( W$ K
            .bpp                = 16,
    & J" Q1 L/ s0 o* F/ y: w' [        .left_margin        = 19,        /* for HFPD*/! F0 ]% G: K+ ], s+ X
            .right_margin        = 10,        /* for HBPD*/
    - [5 o2 X: u6 @7 C' O2 y" }        .hsync_len        = 30,                /* for HSPW*/
    3 `; y- k0 f; V: u) A" g2 u4 S        .upper_margin        = 4,        /* for VFPD*/8 c5 f, F6 e: @4 z. Z6 n
            .lower_margin        = 2,        /* for VBPD*/
    ! l0 M5 m. e! e; n. I        .vsync_len        = 8,                /* for VSPW*/; b9 C. c4 o8 k5 b; {2 ?) N: [7 t
    };9 c- q/ t. |7 ^! m& G
    s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体4 N+ X# S8 B7 Y$ s% {) Z" S: U
    # {$ I2 x) @2 \
    struct s3c2410fb_mach_info {
    $ U5 k* Z- T9 m# j        struct s3c2410fb_display *displays;                //s3c2410fb_display结构体
    . s8 z6 ?2 k$ z. S1 N0 k        unsigned num_displays;                                        //displays的个数
    - `7 |6 `: H; x9 x; l        unsigned default_display;                                //默认的default_display个数
    : C9 H# H* R4 D  m, \, T  i0 A# L9 Z# Z+ Z4 u; t. r9 i2 }
            /* GPIOs */0 h; M; R; s# x  Z
            unsigned long        gpcup;                                        //GPC
    ! Q; E5 t# {7 [; C. [# a) B        unsigned long        gpcup_mask;( m4 [) q: y' T8 M- E' n' k* ]
            unsigned long        gpccon;
    ) W1 u( I8 E. z6 B, k' D        unsigned long        gpccon_mask;
    + h, a4 \/ z6 j$ J  G" n        unsigned long        gpdup;                                        //GPD; u; e( c1 m" c% A# k
            unsigned long        gpdup_mask;
    / u+ s: l/ Q, R7 Y- g$ |        unsigned long        gpdcon;
    0 n1 c7 B4 ^8 b  b2 h        unsigned long        gpdcon_mask;& Q: Q2 c& D; _' d$ W
    9 Z& o  A  o- A( l5 Y
            /* lpc3600 control register */
    7 w+ a6 Z1 b- N/ {) R+ S        unsigned long        lpcsel;
    . [# L0 p, t) t- u! b};
    ! B& V  a3 d# ^* L
    / h0 b' S! y+ j! O5 Q+ j; I2 b  d4 a' n7 p, B

    该用户从未签到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

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

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

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

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