找回密码
 注册
关于网站域名变更的通知
查看: 263|回复: 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
    - 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

    该用户从未签到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-10-26 00:14 , Processed in 0.140625 second(s), 23 queries , Gzip On.

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

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

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