找回密码
 注册
关于网站域名变更的通知
查看: 280|回复: 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, y$ Y/ S. f6 v1 M; n  C
    6 _- K3 F# [0 i6 b7 y* K
    看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数" _6 l$ a; j/ t4 ?+ f8 U, _

    3 L2 z) T. [# A) V: D5 [# H1 Z5 h, k% Y3 g) D& ?
    int __init s3c2410fb_init(void)$ j- A. J' i7 Q& f
    {& w! w- A% h. K6 h4 M2 s% {8 s
            /* 注册一个s3c2410fb_driver平台驱动 */, l" A5 o; R( w, D9 h2 f
            int ret = platform_driver_register(&s3c2410fb_driver);
      N' ^) i( O9 \% F  {' s
    6 C% j$ ]/ R5 h% O        if (ret == 0)
    3 k  M$ }% B! k) m" d7 b                ret = platform_driver_register(&s3c2412fb_driver);;) J/ y( b9 A. T$ K8 b$ h; {

    % s! n2 C/ d& |7 I( L# a        return ret;
    ) ?+ V+ S+ _2 _( l3 x. D8 Y6 T}) D! N( y6 j: K
    出口函数,自然是注销s3c2410fb_driver平台驱动
    1 [  s! @1 d/ P2 I+ [0 W; m% X; L$ u5 g) O6 W. N
    static void __exit s3c2410fb_cleanup(void)
    ; @$ A4 B. S" }4 U{1 @1 }: H, Z; @$ t! q
            platform_driver_unregister(&s3c2410fb_driver);
    2 x+ [. X; `8 k! z! S2 ?        platform_driver_unregister(&s3c2412fb_driver);
    % _- b5 X. L* n# J" o9 j$ k! p' k5 Q}; l6 n- _( g  B9 F
    我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
    8 b4 z1 I( P+ q1 w- {6 t7 O
    , _- @3 H% e6 o0 Pstatic struct platform_driver s3c2410fb_driver = {
    4 d! D, w8 h' P7 [& V        .probe                = s3c2410fb_probe,( @9 |% z9 ]2 O2 I0 B
            .remove                = s3c2410fb_remove,
    5 t) G+ }, g* J8 I0 h3 c( W! W; _1 h        .suspend        = s3c2410fb_suspend,
    ) x( ~. \) N+ W$ [8 N% @5 K" w, r        .resume                = s3c2410fb_resume,
    9 A% W* h. _" y# y) T8 f# m, x" \: [        .driver                = {6 U5 j6 Z' f. @+ M7 u
                    .name        = "s3c2410-lcd",
    0 l- q  W9 W* ?$ p  U% v- Y2 m: S7 H                .owner        = THIS_MODULE,
    0 E& |" L2 _" e( h2 H% N        },) Z8 S# W, w, x+ H" V5 p. {, k% X- ~
    };
    9 L/ b) ?3 b2 @6 {9 M1 `5 H这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。
    7 \. n# T8 U9 Y: C! R在source  insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段
    3 |/ [5 Z2 t* @5 @3 T
    - l- W# j" \5 ]2 f7 K, K
    2 w9 _/ G" F9 W+ r. Kstruct platform_device s3c_device_lcd = {
    , d* d7 C+ I% D) x* ^6 ?        .name                  = "s3c2410-lcd",/ s' y: r1 v4 y
            .id                  = -1,* K" ]" P  i/ s( q5 b, g; @
            .num_resources          = ARRAY_SIZE(s3c_lcd_resource),
    . [  G' O* E+ s' s        .resource          = s3c_lcd_resource,0 t- @% m% I; L* o# x
            .dev              = {
    8 A7 C& w+ @- u. b7 T) g) t                .dma_mask                = &s3c_device_lcd_dmamask,* }- Q' I8 h9 \, ?
                    .coherent_dma_mask        = 0xffffffffUL
    . \* Q# ]1 d: n( V/ H! o        }0 V5 N: S! H* y. f, D- i' [( v
    };9 w5 I2 b7 v! }& z; U4 h# p

    / e2 _; D. J$ j; I6 qEXPORT_SYMBOL(s3c_device_lcd);1 }( Q" J2 P/ w, a. {( U# D2 N
    其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource: c0 C* [9 ~8 a0 o! t! c) u
    3 _: O4 {7 C) z0 l
    static struct resource s3c_lcd_resource[] = {+ r: g! _/ q% _' y+ j, q4 i
            [0] = {
    7 i' D# A) r* N6 V                .start = S3C24XX_PA_LCD,                                /* 0x4D000000 */
    3 q0 D, e  n% W. _! J                .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,( V- g0 z- U' [8 t. h
                    .flags = IORESOURCE_MEM,! ^. s3 {0 ?8 [5 V& M+ i
            },4 n8 |, c; n5 r4 h" t+ W
            [1] = {2 r, v0 h; n& V8 b8 ^
                    .start = IRQ_LCD,                                                /* IRQ = 32 */' N: q2 X  b! ~( n. N$ j: J( I
                    .end   = IRQ_LCD,
    / \$ j% C7 u8 Y9 X, |- I1 |                .flags = IORESOURCE_IRQ,
    2 r. {& C, m4 ]* Y9 [0 @( e+ p* ^9 S/ G        }$ @5 Q+ W5 @( X- A3 k" T
    . O' A: a, J3 _: ?
    };
      M* Z* y$ J+ K/ c0 P9 q- i
    , m  b+ `0 ]" W4 s2 J1 z# ]static u64 s3c_device_lcd_dmamask = 0xffffffffUL;0 \- B2 J8 U+ H" O6 g
    那么接下来当然是要分析probe函数了9 v6 K9 Q3 j. [5 E7 K  _( X9 q

    ! X/ G( ?, p7 S8 Lstatic int __init s3c2410fb_probe(struct platform_device *pdev), s3 Z1 j) {9 |  d' I1 f/ o5 G
    {
    " X4 |; o  v  d4 @        return s3c24xxfb_probe(pdev, DRV_S3C2410);
    ! O. p! Q( l. L4 o  p: p}
    + q5 o8 V' k! Ps3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。* H, U# n% N7 J# k# x0 f
    linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
    6 |* o" r4 O- e8 `0 e3 d8 V/ \
    5 o( V1 g: K7 c" i6 b' u. S) i帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
    * x4 R2 Y4 [+ J3 r
    1 {9 u6 \6 k$ y, j# y2 estruct fb_info {; s0 \5 H% W( a' T2 ~9 m
            int node;                                                //用作次设备号索引; v; G: n3 K) n3 P
            int flags;
    , k/ w, u) `4 i- B        struct mutex lock;                                //用于open/release/ioctl函数的锁9 F, n- M7 O% T. {2 N) q; d
            struct fb_var_screeninfo var;        //可变参数,重点
    / R# q: |# f* P+ Q# u1 F; I& _        struct fb_fix_screeninfo fix;        //固定参数,重点
    ' k( k$ y) p# l% D        struct fb_monspecs monspecs;        //显示器标准
    + O3 C* S: k/ I% C" t: T& x, X" U        struct work_struct queue;                //帧缓冲区队列
    5 o/ z* G& m, p        struct fb_pixmap pixmap;                //图像硬件映射
    8 S  N3 f' l; v+ E7 m        struct fb_pixmap sprite;                //光标硬件映射1 s' }) q$ `# C1 C+ w5 n& J
            struct fb_cmap cmap;                        //当前颜色表
    " J1 q* \+ {+ _! a" l7 b" G6 F        struct list_head modelist;      //模式链表3 e& l9 c$ i9 ]/ n; U' k
            struct fb_videomode *mode;                //当前video模式
    ) E4 i" m# I& n  o% d) `4 Y/ u
    ! q& }9 H! s5 f; g  T        char __iomem *screen_base;                //显存基地址' G4 c( h9 F' b* j; k
            unsigned long screen_size;                //显存大小. X3 j  f% L& g8 p! {$ ^
            void *pseudo_palette;                        //伪16色颜色表
    % p9 T3 u" Z5 b#define FBINFO_STATE_RUNNING        0- j% g* l  b; s9 Q5 g& \) r
    #define FBINFO_STATE_SUSPENDED        1
    0 m1 K* H9 l- n; g3 |* D8 e        u32 state;                                                //硬件状态,如挂起
    " M1 I5 r9 ^1 u% _* B2 \; ~1 k        void *fbcon_par;                //用作私有数据区
    ' y5 Z/ W, H+ k' T        void *par;                                                //info->par指向了额外多申请内存空间的首地址
    0 y; z. M$ Z2 R6 o% P: F& H};
    ( K2 \( K( K. E) q8 d6 E6 K% _s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息( a9 H. \$ S* K" o/ J9 c% F7 L

    6 {0 y/ m1 h6 i& ]* estruct s3c2410fb_info {
    7 D. _; \1 m5 z6 X+ n! M, t- P        struct device                *dev;                        //设备  y- N+ \. H7 P& \$ H# ~& F8 C) ^, t
            struct clk                        *clk;                        //时钟
    5 ]4 M/ O& j$ V* Q( N' I3 z/ P/ v+ i/ G$ \
            struct resource                *mem;                        //资源
    3 X2 Z, _' i- y- r/ f) {1 v" u        void __iomem                *io;                        //IO地址7 h! V" ~% V5 t3 D* W# |! l& g
            void __iomem                *irq_base;                //IRQ基数
    ; P% B. k0 M! m) R7 ?2 z/ }9 {, F% H$ }- t( d' M+ |, M; D. |
            enum s3c_drv_type        drv_type;                //驱动类型,S3C2410或S3C24126 k3 K+ r3 ?+ h! k1 y: a
            struct s3c2410fb_hw        regs;                        //s3c2410 lcd硬件寄存器
    : }- P) E4 P& G2 k3 _7 v
    ! I$ g* }& S, M        unsigned int                palette_ready;        //调色板是否就绪标志位$ m( W  W5 e" T% d8 y7 d
    ) ~" L4 W: X: G, o( E0 r
            /* keep these registers in case we need to re-write palette */
    , `* z" N/ _( a& o5 ^! w        u32                        palette_buffer[256];        //调色板缓冲区# W  L3 k2 Q; X' t+ _; K6 W
            u32                        pseudo_pal[16];                        //伪颜色表
    : V" y# y" Y. z3 S};$ F/ ^' [4 O# r8 l+ S  b2 C
    s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等  U9 _6 Z8 m4 u/ O# w% w
    ' J8 e7 D& F) g5 h) r5 e
    /* LCD description */
    5 \4 S6 t5 e; W5 T. tstruct s3c2410fb_display {
    ( y# P7 X, n- k- g  i, U& Y        /* LCD type */
    ! V7 k* Q9 c0 I        unsigned type;: E: b! @3 v5 B1 U% u  n
    ' H0 b: M6 ]$ J# m4 @$ s
            /* Screen size */, {3 i0 @1 n0 l0 h" p
            unsigned short width;3 p0 k3 \! I$ ^' M
            unsigned short height;0 Y! Q6 I; s$ o' Y9 y/ J' v$ @

    8 q! P' z$ m  e$ r* S        /* Screen info */
    1 Z  T- e5 d2 l) N- H. W        unsigned short xres;; {* K! Q. T; W( L# f3 C
            unsigned short yres;
    " _6 w7 F$ ?- x2 _: g        unsigned short bpp;
    ' a+ f7 o- g( G# }+ Z+ b  [4 x
    0 z2 y7 {' r. P% z# _: A        unsigned pixclock;                         /* pixclock in picoseconds */
    $ O9 p/ X, D# u5 t        unsigned setclkval;                         /* clkval */4 h- M4 e% ^! P+ b  w1 c9 w
            unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
    ' A; D/ d$ `7 a+ d/ J# S5 |        unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */2 B7 G9 h( Y) F: i* q4 ?
            unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */% g: O: [7 P1 M" z, G
            unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */: U5 T7 p: a# _7 @
            unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
    ( _( n+ p" Z/ b$ J  L        unsigned short vsync_len;         /* value in lines (TFT) or 0 (STN) */, ]* ]- y- m& Q2 o0 ?) E- D$ y

    2 u6 Y- G* ~7 r4 S9 H2 c        /* lcd configuration registers */
    2 b6 N8 x- r. l+ F        unsigned long        lcdcon5;
    2 q6 u8 q+ c/ `! r$ J4 m- y4 B: J7 m};- H# k% c$ X) B# d3 }- U# X
    对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
    * ], y7 U& Q/ \) t  n5 \
    5 Q- \# U4 @- |0 o- w7 S/* LCD driver info */
    9 t7 \1 o4 ~4 ystatic struct s3c2410fb_display tq2440_lcd_cfg __initdata = {
    7 E6 Y( z; I9 e( \" m        .lcdcon5        = S3C2410_LCDCON5_FRM565 |3 S- k% i; v* @- y$ e
                              S3C2410_LCDCON5_INVVLINE |( \8 J" C9 z7 w0 @  d: p8 Z1 c0 x
                              S3C2410_LCDCON5_INVVFRAME |1 j* C( ]( a7 i
                              S3C2410_LCDCON5_PWREN |! r9 c& I" B  z/ N' [) @5 j9 S
                              S3C2410_LCDCON5_HWSWP,2 }& P% `$ O9 x
            .type                = S3C2410_LCDCON1_TFT,. R, k0 c0 [# i0 B
            /* TQ2440的液晶是4.3寸的,分辨率是480*272 */- ~' E1 U' D3 n+ A( B/ C  e
    #elif defined(CONFIG_FB_S3C24X0_TFT480272)  /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */, v9 J+ f5 M# m" r$ f* W
            .width                = 480,
    / C: o1 [3 Y5 y8 ~+ h) a        .height                = 272,5 N: q% D# ~0 k) T

    ' `; c" @1 t9 I# x8 u        .pixclock        = 40000,    /* HCLK 100 MHz, divisor 1 */* m$ ?- L# P5 X, ]3 L+ D% I9 E  b6 v2 }
            .setclkval        = 0x4,
    # c! S! _9 _0 W5 v$ J        .xres                = 480,
      j* D8 w; b0 d        .yres                = 272,3 S$ W- _, g* P  |2 y7 x4 J
            .bpp                = 16,
    8 @4 R2 q' R8 o" M; z  X/ |        .left_margin        = 19,        /* for HFPD*/
    5 G3 z* e. y3 O3 I        .right_margin        = 10,        /* for HBPD*/" z, \3 _1 ~. f; _& d9 f, q
            .hsync_len        = 30,                /* for HSPW*/' q# R5 L8 F' W
            .upper_margin        = 4,        /* for VFPD*/
    * ?3 l, p2 q# u0 ~        .lower_margin        = 2,        /* for VBPD*/
    , S+ {4 m& k7 [% U3 w% e2 L4 j        .vsync_len        = 8,                /* for VSPW*/1 S) n3 ]* u% r7 A! H! c
    };
    " N1 g# a- u+ h6 C4 w$ ys3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体8 {: h# O- `3 z7 r

      Y: H" G& L+ J; B6 Hstruct s3c2410fb_mach_info {
    ( I7 X' }# P9 t' m& B3 Y8 k* O        struct s3c2410fb_display *displays;                //s3c2410fb_display结构体: s% K% [" c+ k0 h5 P9 K0 ?
            unsigned num_displays;                                        //displays的个数) w! r7 H; n! V1 C6 e1 {' p% k# r
            unsigned default_display;                                //默认的default_display个数5 A1 T/ ?* r6 p; n+ Y! }

    ! a6 L8 c6 {) L( |        /* GPIOs */- ]! c4 @2 Y# b( ]* n
            unsigned long        gpcup;                                        //GPC
    7 g( }* {' H6 x  A: K7 \+ W        unsigned long        gpcup_mask;
    % C$ p# t# R. {( c        unsigned long        gpccon;
    9 y' x, b7 f# r. u- g        unsigned long        gpccon_mask;
    5 k; O4 T) Z* |1 ?7 b        unsigned long        gpdup;                                        //GPD
    ( H& ^7 w" Y) ?+ o1 p6 F/ ~8 R5 W+ w        unsigned long        gpdup_mask;3 h' o  s2 t  q5 i$ ~  Z* t
            unsigned long        gpdcon;
    ' @4 E2 ]( T+ `$ X1 k. E& ~: z        unsigned long        gpdcon_mask;
      s: |- ~: ~. ?
    + u; H; q* w( ~. F$ K+ a3 R0 |3 J        /* lpc3600 control register */+ Y6 B" V4 g1 y* O4 @
            unsigned long        lpcsel;- h1 [0 U8 r3 ^, N
    };9 R" \1 n2 Z& q' o$ g  ~* Z
    ' [2 ^6 e- D' Z! h* a
    : a7 R8 n$ |2 }  t, J

    该用户从未签到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-11-26 01:59 , Processed in 0.156250 second(s), 23 queries , Gzip On.

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

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

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