找回密码
 注册
关于网站域名变更的通知
查看: 253|回复: 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 t7 ]" C( x" y- k
    , p2 V$ h2 f- f5 K+ r- A3 c3 W2 A看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数4 G! o5 f' i- Z# w! u) S) B
    5 D5 N, x* J9 _* F* t

    9 O. t( F5 r( aint __init s3c2410fb_init(void)* r6 S7 [) x' l: j2 H7 N
    {
    8 u, `- P; ~+ q; U+ m        /* 注册一个s3c2410fb_driver平台驱动 */
    ) V- P7 @5 M/ j9 x' j        int ret = platform_driver_register(&s3c2410fb_driver);# c2 Z2 {  k7 }. q  g: V
    : \( c3 [9 Z5 O+ {2 U) `
            if (ret == 0)0 b4 l9 ~+ H5 N2 t& [/ E' _
                    ret = platform_driver_register(&s3c2412fb_driver);;
    & V& F" t- J  t) W, c3 }/ b( U! `6 W8 O7 S" i1 {
            return ret;
    3 D0 r7 Y4 S" u* D- e+ A0 |" F, {. W}! T. X' u0 N. c5 M3 M; W8 v
    出口函数,自然是注销s3c2410fb_driver平台驱动
    3 z1 q5 T: X4 B; a$ K& Y  S  ?0 q1 P8 p' R" `0 v8 B4 M
    static void __exit s3c2410fb_cleanup(void)
    1 y& E3 ~( C: r. q" q{6 V; z; T2 {: \( F$ U) E9 v2 g
            platform_driver_unregister(&s3c2410fb_driver);
    ) |. b* U8 m1 i+ p+ t) v. E        platform_driver_unregister(&s3c2412fb_driver);
    $ q4 I2 U* B7 _# q& p}
    6 i/ T/ o8 Y- e' x! N我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。& v+ n0 B$ S0 N$ ~* X5 F

    # Z* {' ]( c+ U6 R2 ]static struct platform_driver s3c2410fb_driver = {
    ' Q( b. x$ c8 e* z# t        .probe                = s3c2410fb_probe,$ v& z  L. M$ a3 C3 T7 q6 @! P
            .remove                = s3c2410fb_remove,3 ]+ `1 K- C8 T$ m8 V8 h, M4 u
            .suspend        = s3c2410fb_suspend,/ c3 I- n" Z! l  h& g% W- f9 `% q2 ~
            .resume                = s3c2410fb_resume,
    4 B" F* C$ ~* ?1 b        .driver                = {$ Q  J2 \9 n% O
                    .name        = "s3c2410-lcd",& A, z. ~; @( Q. u* x2 ?" B4 F
                    .owner        = THIS_MODULE,0 Q" [" \5 s7 w. a. J
            },
    ( i( G* A/ y/ D' f9 k};9 r4 g9 p* C" w( s" u/ S' H* w
    这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。2 n2 v, @9 ?/ M& S* j; F! s
    在source  insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段- g" Y# f' {5 A9 }. C0 w
    $ [! t$ E* l3 l, e: W) o9 I
    ( ~7 \! b, b, O" f3 M
    struct platform_device s3c_device_lcd = {
    6 v9 r" U/ C( S6 Z! X! j/ W, _        .name                  = "s3c2410-lcd",$ d: a* W9 P6 k% t
            .id                  = -1,
    * ^' q. N5 f/ _        .num_resources          = ARRAY_SIZE(s3c_lcd_resource),
    - n8 g! x! M. i$ ^+ }8 w1 T6 _9 Y9 ^        .resource          = s3c_lcd_resource,5 v5 {  p" r. p9 E  C
            .dev              = {
    ) I8 N  Q7 F& ?9 I                .dma_mask                = &s3c_device_lcd_dmamask,
    & u% M: f* K1 a                .coherent_dma_mask        = 0xffffffffUL! s, P& {" ?- k8 Q/ F- R$ @
            }
    ! L5 }1 a& E4 T& R4 Q' D* C1 N};$ q; D$ L: W' |2 |; F. M
    0 f+ o5 _0 ?& ^. K! W! m3 K
    EXPORT_SYMBOL(s3c_device_lcd);6 D4 Y% S+ g( n/ }5 q  n3 k
    其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource3 G* s0 q, P/ p) F! Y5 J! Q3 L

    9 L" @* N' S) y1 w% tstatic struct resource s3c_lcd_resource[] = {
    1 e+ L5 t# r* R" e- L. v        [0] = {
    1 Y& [0 g4 C# x                .start = S3C24XX_PA_LCD,                                /* 0x4D000000 */: g) l- D' J  E( ]" H7 u( v. r3 d
                    .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
    9 q. g1 E. }8 C5 a- s$ A9 @) k                .flags = IORESOURCE_MEM,
    * [, L# C) M* o$ n+ g; c        },2 w( V1 r" b  P4 S
            [1] = {9 D% |7 m# d, x" K* |% u# V
                    .start = IRQ_LCD,                                                /* IRQ = 32 */
    & A2 F" G! F# K$ Q7 R" U: k8 R                .end   = IRQ_LCD,3 ~9 B* j7 d8 H; n; ~$ n
                    .flags = IORESOURCE_IRQ,
    ) J$ R6 G9 `+ [& C" [1 l        }3 e  D1 g3 O7 ^" a! x# r2 ?4 P
    ) O, H1 [/ n& K1 S7 n% q3 x1 M
    };8 V. i2 A% k3 E# t0 }7 z2 T

    1 ]* |) Y$ y7 c5 ?static u64 s3c_device_lcd_dmamask = 0xffffffffUL;7 b% m+ }% y, J
    那么接下来当然是要分析probe函数了+ [2 \9 d% o5 m) D! A7 B
    : v. q( D5 P8 ~. v0 {( m/ j2 I2 \
    static int __init s3c2410fb_probe(struct platform_device *pdev)( R6 g+ F: i- R4 v$ p: o0 e! Y
    {, j, X1 O; B* p- M" X  P2 z$ U
            return s3c24xxfb_probe(pdev, DRV_S3C2410);8 W; P" ]! }/ w9 M  U2 |- y& d
    }
    : m# J; |' f! {s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。9 T: e' s* ~+ P% r% C8 C
    linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。8 @- h: X; U, p3 V* C5 d/ u
    2 C  ^  m/ B, [% e
    帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
    ' ^" j: d( u% x2 `5 Z! e9 ]* u+ N4 p7 G- a; y
    struct fb_info {
    $ l8 P& L5 Y, s5 T- E* H        int node;                                                //用作次设备号索引
    4 U) Z# A, O; }# {, R) I        int flags;
    " C& t- t- `* V& T        struct mutex lock;                                //用于open/release/ioctl函数的锁
      E) W4 Y+ t2 X4 R+ o        struct fb_var_screeninfo var;        //可变参数,重点3 m: i1 `0 \: ~7 ^# m' u
            struct fb_fix_screeninfo fix;        //固定参数,重点  B( `3 j) a+ ~( g; h! w
            struct fb_monspecs monspecs;        //显示器标准
    8 k' ~( _8 K! I, j        struct work_struct queue;                //帧缓冲区队列
    3 e8 F/ [% }7 [2 I  m  Y        struct fb_pixmap pixmap;                //图像硬件映射
    7 n% X1 m  y' X+ H, z9 `  e" f8 l        struct fb_pixmap sprite;                //光标硬件映射
    " y! S: s, z1 b7 v! k+ I3 e        struct fb_cmap cmap;                        //当前颜色表
    ! M' {. |5 S' r+ \- b) e- A        struct list_head modelist;      //模式链表
    " J& g% Q, k& R        struct fb_videomode *mode;                //当前video模式
    2 [6 K4 t* M% N
    6 c7 W8 n% w# T. [& [3 x6 M        char __iomem *screen_base;                //显存基地址
    # M/ H: |8 y6 M3 e        unsigned long screen_size;                //显存大小9 W. H$ C' u7 X2 ?- W
            void *pseudo_palette;                        //伪16色颜色表7 e5 _$ a/ f4 Y& k
    #define FBINFO_STATE_RUNNING        0& z9 k9 s7 X" O3 J& @
    #define FBINFO_STATE_SUSPENDED        1
    / _. ~7 h; O6 Z/ B% {7 ~        u32 state;                                                //硬件状态,如挂起/ k. H+ s/ k2 C8 X) o
            void *fbcon_par;                //用作私有数据区
    / [0 m# `# N/ c9 o% r) o        void *par;                                                //info->par指向了额外多申请内存空间的首地址8 ~8 ]9 W* R  W4 S* D9 A
    };) o; D4 P& L; k8 t
    s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息* @1 r; \3 |+ }" v3 p, \
    * l3 J" i3 o# Y" y) c7 H$ v+ q# ?+ m& P
    struct s3c2410fb_info {
    6 c; o; D- ?& M6 A( R0 ]        struct device                *dev;                        //设备% m' s& H- }7 v$ T+ a2 b) m$ x
            struct clk                        *clk;                        //时钟
    5 z$ k0 d3 t1 f" H; B
    ; Q) p! a  f# ]$ L7 D        struct resource                *mem;                        //资源
    5 q1 |8 i( X. G; x+ P# j        void __iomem                *io;                        //IO地址% W" c' y6 t5 Z& O3 F1 c
            void __iomem                *irq_base;                //IRQ基数
    7 n1 r" P5 Q/ G% t1 P
      h6 t: G( z; s6 @8 j6 m5 ]) K        enum s3c_drv_type        drv_type;                //驱动类型,S3C2410或S3C2412
    . T. N0 y2 Y% q0 s# Z        struct s3c2410fb_hw        regs;                        //s3c2410 lcd硬件寄存器
    / ?1 D5 E( i* x: H- X: X2 q6 q+ D4 J7 f/ p/ A
            unsigned int                palette_ready;        //调色板是否就绪标志位
    9 O3 ^1 W& H- f6 `# ^! P" [4 Z+ m' w' p3 f2 C$ v/ c5 c
            /* keep these registers in case we need to re-write palette */
    8 \) i- M5 N; ]2 R# {3 R        u32                        palette_buffer[256];        //调色板缓冲区7 j) B6 c: @2 J9 z9 p; b* h1 e" }
            u32                        pseudo_pal[16];                        //伪颜色表9 i2 J1 U3 Q& F, l. p, H. `
    };
    5 S; U6 J1 @( o* Rs3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等
    4 x7 N, P6 X' x( H; h: w: n1 R% C8 g
    /* LCD description */3 P' m- k7 o7 Z9 c0 M8 R5 u
    struct s3c2410fb_display {0 p& n; w- `: [2 ]' x" J5 d" M- E
            /* LCD type */
    - _+ p9 W) O' A+ y( u9 Z6 w        unsigned type;. e4 o7 M; Q3 L6 T2 U$ @- k  l
    3 v. T4 B  O+ r, Q7 T1 A8 Z
            /* Screen size *// P2 o1 J7 G$ n. r; w
            unsigned short width;) t/ K- I. t  e  T& `( Q
            unsigned short height;
    ! }! Z6 r% k' J4 }; i4 b- k5 w) H
    ) V  a/ c4 H: l  j6 A9 R& X7 r7 d        /* Screen info */  @2 w; _6 p! Z
            unsigned short xres;/ F6 O! K! m& C7 k' M. M. p# B
            unsigned short yres;: Q1 z$ s) `1 b
            unsigned short bpp;: x$ C3 e6 A7 v( L# J% b
    # {; s/ t' X  U5 \1 a' t6 \, A; |
            unsigned pixclock;                         /* pixclock in picoseconds */
    8 z' p) {( _+ b( H1 s, l" a3 o, b: [        unsigned setclkval;                         /* clkval */
    + f/ K  Q! }, M0 ]2 x        unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */# S' i/ I4 Q6 [9 P* n0 y( o
            unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
    * Y% d' c7 \& o/ w) ~        unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
    / C1 J/ ^9 i6 s: I% y+ p" W; E        unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */$ U3 \, w+ Z3 E/ p( {. P
            unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
    / b. @" `# J9 _        unsigned short vsync_len;         /* value in lines (TFT) or 0 (STN) */2 t: {4 \: f- G2 r) `0 p+ b; t

    + Q( ?- |, p, u8 Y$ X5 q        /* lcd configuration registers */, }, c9 }6 e5 u" ?& a
            unsigned long        lcdcon5;. R' j) [8 H  ~4 ?: S
    };& ^9 T, R: Y* b  c( b* n
    对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置9 o1 t4 i. x1 l" I) @; S+ z$ N5 j

    & I. k3 {/ z9 ^6 b* \' _- h* g/* LCD driver info */
    1 a# x: T0 U% Y4 e, Kstatic struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
    , w" v8 G7 |5 U4 Q5 \        .lcdcon5        = S3C2410_LCDCON5_FRM565 |5 O  K$ M4 m0 n1 l
                              S3C2410_LCDCON5_INVVLINE |
    " d% u/ |2 O2 H3 i5 x% R                          S3C2410_LCDCON5_INVVFRAME |2 X& g3 h0 d8 M0 w4 q" }
                              S3C2410_LCDCON5_PWREN |
    9 _1 s3 E% p) T4 A                          S3C2410_LCDCON5_HWSWP,
    ! j" ]  {# O2 y- V        .type                = S3C2410_LCDCON1_TFT,
    + ^, y6 f8 A' Z7 m. o6 f. E0 [5 V        /* TQ2440的液晶是4.3寸的,分辨率是480*272 *// o/ }, M) b& i: K: R
    #elif defined(CONFIG_FB_S3C24X0_TFT480272)  /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */
    " {$ y6 W$ B5 o0 d' k5 O. k        .width                = 480,
    : d) n7 i  M/ ]7 d7 h4 d8 q9 q        .height                = 272,
    ( u. i$ o7 B( P, q
    , M( D$ w3 i. B        .pixclock        = 40000,    /* HCLK 100 MHz, divisor 1 */
    % }  y7 E4 [; O4 h2 y        .setclkval        = 0x4,4 {5 ]$ t2 P0 f# m
            .xres                = 480,5 r6 }. o# H6 d/ s- U
            .yres                = 272,
    7 l* W% m& g8 a2 G9 ]. I2 |        .bpp                = 16,
      [: U1 w$ d: N# e- b' f        .left_margin        = 19,        /* for HFPD*/! I3 ^: t6 l3 k* x8 F0 @- V: W3 @# J
            .right_margin        = 10,        /* for HBPD*/
    3 G3 P# A( u6 Q3 p& U* ?0 n; R4 _        .hsync_len        = 30,                /* for HSPW*/
    2 _7 P7 b% p2 q6 A( A: x* _# O* z        .upper_margin        = 4,        /* for VFPD*/" y9 G' F5 t% m7 g8 d
            .lower_margin        = 2,        /* for VBPD*/. r1 k/ g$ ?! x8 O
            .vsync_len        = 8,                /* for VSPW*/' I, Q  b* |6 i0 L4 J
    };; Q" b! X0 S+ A4 L
    s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体
    ) {* K- Z" B6 g" ~  W* W# z
    ' o0 P. X: m6 J6 s8 U) n5 [struct s3c2410fb_mach_info {
    5 u0 j- i: U# a* H% x& J        struct s3c2410fb_display *displays;                //s3c2410fb_display结构体
    1 m- G, X* o6 ?5 X3 G        unsigned num_displays;                                        //displays的个数
    2 F8 S$ t) ~4 m5 V- K        unsigned default_display;                                //默认的default_display个数7 Z1 w! `$ x) p+ f% z; ^

    3 \% i( g3 B4 i- @1 G        /* GPIOs */
    - y7 P& V' M3 n7 g' ?' S        unsigned long        gpcup;                                        //GPC
    ( Y, G( ?2 R6 W        unsigned long        gpcup_mask;
    ! @3 |' B; K" c1 X5 J        unsigned long        gpccon;
    & S3 o% J, n2 \  R! b0 x, b        unsigned long        gpccon_mask;) [2 n) o0 C0 V& y0 O) d; A
            unsigned long        gpdup;                                        //GPD& d  _) Y# C1 y/ a' V, ^  n% |
            unsigned long        gpdup_mask;; z7 K# z3 H1 G- E
            unsigned long        gpdcon;" V' {+ G* B, d( c2 l7 W9 Z
            unsigned long        gpdcon_mask;
    ) y  A6 Y6 F% L3 Q' I) N" R' y8 u# [! Y$ `$ T" I  t
            /* lpc3600 control register */# }& |0 _6 l2 y& D3 Q( Y7 c
            unsigned long        lpcsel;
    ' [: ~5 m  u) U/ R: H9 k};
    $ J% K; A( r' k. }* g+ t) \
    $ r6 |0 a+ y0 d  a: |9 e% Q+ B9 d3 v- k

    该用户从未签到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-7-1 11:56 , Processed in 0.078125 second(s), 23 queries , Gzip On.

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

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

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