找回密码
 注册
关于网站域名变更的通知
查看: 278|回复: 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! [5 G! l# x( V
    3 o( P1 r  A# A4 c! F/ y' i
    看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数3 F9 `$ @3 Y& ]" Y
    ' |0 H( w8 V% B0 Q; i7 E9 C7 w7 F

    + e( @; W" L) o/ e- `5 s  j6 oint __init s3c2410fb_init(void)
    , ^' |1 t( @* u- z{8 Z& H. Z: @; L1 q' m
            /* 注册一个s3c2410fb_driver平台驱动 */8 u: C2 i/ ^5 T8 d  @
            int ret = platform_driver_register(&s3c2410fb_driver);
    ; G- C7 H5 U* l) u- ^2 o. {  y3 g8 i
            if (ret == 0)
    % @, p8 D4 O: W/ h2 Q5 j                ret = platform_driver_register(&s3c2412fb_driver);;" W& T# {; e, F$ Z) q' i4 h
    8 _- S4 V/ }" P3 N: S; \* U4 [
            return ret;4 }2 l8 g# _  T* _6 c# ~& k
    }
    * W1 e; }; ^! q出口函数,自然是注销s3c2410fb_driver平台驱动9 Y( v9 O$ S5 Y2 [. N8 C' J+ w7 G

    6 _4 G; R; q6 W4 ^static void __exit s3c2410fb_cleanup(void)
    5 O+ u" \% g# e9 Z1 H) T{
    ) T0 t$ Q& u5 I# J' Q. i        platform_driver_unregister(&s3c2410fb_driver);
    ; |' h& ~% h2 D& O        platform_driver_unregister(&s3c2412fb_driver);  t3 g+ p) |4 U! ~% n: n
    }5 a& a6 l" I0 ^
    我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
    : ]2 L- k3 w( l+ d' r, q( f; R! s; O* l* O) c' E
    static struct platform_driver s3c2410fb_driver = {8 }' @. N, d8 C" M5 j- j& \' k
            .probe                = s3c2410fb_probe,
    - g& x5 l. _: B7 |; P  i$ a        .remove                = s3c2410fb_remove,
    1 u( @. Y8 }3 Y        .suspend        = s3c2410fb_suspend,, q0 v$ o8 [, s: {# ?
            .resume                = s3c2410fb_resume,$ Y: n9 t! s" J2 R- ~
            .driver                = {
    # P$ W6 c# ], a2 v9 G! W                .name        = "s3c2410-lcd",
    ' v; G4 _3 t4 |$ Q9 S2 v# _                .owner        = THIS_MODULE,0 z! _+ I7 P2 Z, C
            },% f0 _! d$ f; b
    };
    1 l3 ^% g+ u5 j0 ~$ a9 V这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。
    7 o' Q. t5 D+ U" C) I% Z2 z0 T在source  insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段) {: w7 T3 W$ |) a7 ~8 s% b& D: C
    - x) h% _( t1 h: d1 J$ }9 I

    ) l' u3 B# }$ q$ B# @& Dstruct platform_device s3c_device_lcd = {
      x9 @! R! u( t5 E4 X  q        .name                  = "s3c2410-lcd",( L" t  @# b- u- v8 d$ f+ {
            .id                  = -1,) o* E. R1 M( ^" g. v
            .num_resources          = ARRAY_SIZE(s3c_lcd_resource),3 \5 e0 v, \1 C( Q, \! x" K
            .resource          = s3c_lcd_resource,7 a( `) N1 I- v: g
            .dev              = {3 O# [8 g2 m, ]2 b" [4 a- D
                    .dma_mask                = &s3c_device_lcd_dmamask,
    # i; J9 d  `+ ?. }, t                .coherent_dma_mask        = 0xffffffffUL
    $ X1 c# R" r: Y; c" x        }
    0 E, o: g8 O' S5 ~' R};
    2 t9 Q8 a2 j# l6 m
    ( J2 G" q; q0 m3 k9 eEXPORT_SYMBOL(s3c_device_lcd);
    - I' a1 \( F+ v" u0 m* i4 ?9 {; \其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource
    7 y8 K8 Z/ L! M: d' w9 ]- [; f4 l. W$ S5 e9 B. A$ J) U& i
    static struct resource s3c_lcd_resource[] = {2 A( g( u9 w; z: e
            [0] = {
    ' h* \9 b: x+ X$ t& S                .start = S3C24XX_PA_LCD,                                /* 0x4D000000 */
    - r' d+ C0 e! i: n% @1 e# }                .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,+ i8 {. |. Q, J* J! s
                    .flags = IORESOURCE_MEM," |" C- m( i9 Y& F4 x; ]
            },3 P! Z# W8 u& z. p
            [1] = {  |2 l# q! r# @7 D. T
                    .start = IRQ_LCD,                                                /* IRQ = 32 */5 C3 @& z4 }* @
                    .end   = IRQ_LCD," E/ c, w4 i: p) {
                    .flags = IORESOURCE_IRQ,2 `# B" O+ H' w
            }) g( {: r0 T% V5 t7 q- g8 S
    ' Z$ U: q- M) ~6 U% K5 a
    };0 u6 Z& s4 [, Y' ^8 n4 l
    # ~& M/ V, M& R5 o
    static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
    7 ~( f5 `: w; p0 K8 a$ m. j那么接下来当然是要分析probe函数了  ^  o* j! j- }% J( {
    ( N. f4 R& ~$ F
    static int __init s3c2410fb_probe(struct platform_device *pdev)- }; }, I* J3 P, D
    {8 B, a, {2 `& t+ v! y0 G6 ]% [, u1 D
            return s3c24xxfb_probe(pdev, DRV_S3C2410);1 C( |  r6 {# L
    }
    % w0 z, n5 c2 m7 k# T* t4 t9 h7 os3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。, a6 l# l' D3 ^- A- t% a( o
    linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。: O: e# d9 f/ c( i
    + F8 B" \- K* c0 m8 C
    帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。
    1 W( I) o9 {5 J' D! E8 o! Z" p& ^
    1 L9 G2 j7 Q: _! _7 u4 F+ Gstruct fb_info {
    8 A/ [5 v2 L% z  k& @        int node;                                                //用作次设备号索引" y# X: N8 V$ S0 X6 Z; o  h
            int flags;# u, J. e& m7 _* M, I$ K% G
            struct mutex lock;                                //用于open/release/ioctl函数的锁* c( P+ F: f7 _! ?: K( s7 S8 o
            struct fb_var_screeninfo var;        //可变参数,重点
    6 u+ n1 z% S" N6 {' q/ E' M        struct fb_fix_screeninfo fix;        //固定参数,重点, \8 Q% r2 f! J
            struct fb_monspecs monspecs;        //显示器标准8 a. H5 c/ z9 k( `  ?! ^# D: ]9 m
            struct work_struct queue;                //帧缓冲区队列
    - O! w+ s  j) M& X( H        struct fb_pixmap pixmap;                //图像硬件映射: R. i  G8 x) A; q& c
            struct fb_pixmap sprite;                //光标硬件映射
    % A3 T4 ]0 l# d) A) X7 Y        struct fb_cmap cmap;                        //当前颜色表
    ( r8 }: [$ ?1 l) i/ @7 i0 N        struct list_head modelist;      //模式链表: h/ J+ ?2 E4 k3 X+ g
            struct fb_videomode *mode;                //当前video模式
    3 }" f( p# Y) c3 u/ k, |
    1 K# d3 P/ [9 u4 [        char __iomem *screen_base;                //显存基地址1 I& }, ^" N7 N: I
            unsigned long screen_size;                //显存大小; _6 s3 R5 [' B9 v" q
            void *pseudo_palette;                        //伪16色颜色表
    9 E) e, C' y5 |# Z7 i  j  Y( F#define FBINFO_STATE_RUNNING        0
    ( \1 a$ P6 r* J8 W#define FBINFO_STATE_SUSPENDED        1
      U2 Y$ C1 N# d        u32 state;                                                //硬件状态,如挂起
    , q  m) t6 p9 |1 f0 i8 q        void *fbcon_par;                //用作私有数据区4 V9 i& e0 ?/ C
            void *par;                                                //info->par指向了额外多申请内存空间的首地址
    ; ]/ R1 ?- O0 c9 X" N- K};
    ; J; ^1 H( w% c; b0 Ps3c2410fb_info结构体,这是s3c2410抽像出来的特有信息5 Z4 r) s" w8 `+ U% j3 U( I# \2 P+ v
    ) a1 m1 Z1 Q; {
    struct s3c2410fb_info {
    : ?6 e) z2 D1 s$ d% x  p        struct device                *dev;                        //设备! u; O- Z  h: \
            struct clk                        *clk;                        //时钟
    5 ~- M$ z2 i0 X
    " U( F# \! ?6 I" U        struct resource                *mem;                        //资源; Q2 P' Q7 R4 M9 d) d: L% I
            void __iomem                *io;                        //IO地址8 X9 g- T3 G, O
            void __iomem                *irq_base;                //IRQ基数
    3 I& d; K+ W2 b' @0 H
    ; T+ M' m1 A* T. z! e  k5 E9 O6 J        enum s3c_drv_type        drv_type;                //驱动类型,S3C2410或S3C24123 i0 K3 g3 t" P6 M
            struct s3c2410fb_hw        regs;                        //s3c2410 lcd硬件寄存器
    . q/ b* r$ D( t- C+ G; H9 o: a) U, G3 q1 H. Y; U
            unsigned int                palette_ready;        //调色板是否就绪标志位
    7 E+ M+ F# B. x: K6 ]. A$ E. Q* C" m+ ^" ^. r7 Q$ \
            /* keep these registers in case we need to re-write palette */
    ! e4 e0 l: F$ X  V) Z        u32                        palette_buffer[256];        //调色板缓冲区# o/ w  t4 Y* `4 @. g1 r
            u32                        pseudo_pal[16];                        //伪颜色表
    6 n) W4 s" K: r  t};# h' D& V/ e$ j, D. V
    s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等2 n5 ?, ^+ }% {( \; X& H

    7 _( E! Q' p1 Z( h/* LCD description */
    9 x6 Y( }3 D2 L( Tstruct s3c2410fb_display {% E+ ?. y6 k! A6 X% E7 K
            /* LCD type */
    2 o3 q8 P. P( y& T% @$ p- [- A% ~5 c        unsigned type;
    - T6 y/ P' p" z0 ~* P( L6 F7 P& S* w$ r6 L" [
            /* Screen size */7 S4 }, Y1 d9 f& f" u5 m
            unsigned short width;; }* f3 @2 S6 e/ Z) S
            unsigned short height;
    6 \) ~& ~- ~2 F1 W4 C7 O' Q- l7 k% \) U( v. z8 W+ e! `
            /* Screen info */
    ! p6 _) t4 l  R  k1 R        unsigned short xres;
    , {6 s; _* \- T! U2 G: c        unsigned short yres;
    ) ~& Z0 ?, n" T! e7 @9 g        unsigned short bpp;, y/ Z0 Z$ W# S( \

    1 }( w5 [5 b% `  e0 b8 G2 I        unsigned pixclock;                         /* pixclock in picoseconds */
    + o. [5 ?2 x8 H( J9 X        unsigned setclkval;                         /* clkval */# c- z/ l1 Q* @1 p" b
            unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */& }3 T4 p3 m2 U1 W/ {
            unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */2 F8 v7 X3 U: A8 M
            unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */8 w- O9 o# }1 u+ G
            unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */
    ! h/ ^) j6 E  T5 h; [5 m        unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */
    : r  Q4 h7 k- q8 y        unsigned short vsync_len;         /* value in lines (TFT) or 0 (STN) */
    : d! }3 T1 J1 T1 V0 F2 ]. D1 i3 l4 c6 l0 v& u) w
            /* lcd configuration registers */
    2 m4 i! w( t( t7 Y/ ~: h0 t        unsigned long        lcdcon5;
    * x9 ^, F/ R# E* S};
    # G) n* ]% S1 ?% Y  s  B4 a9 w对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
    . }! K8 z! l4 ]. T! M5 d+ `1 Q& ]) t% [( j* `& q- O
    /* LCD driver info */; u7 K  s: |6 Y) {" E; o% {
    static struct s3c2410fb_display tq2440_lcd_cfg __initdata = {0 Q* `( R: h% g( t! n/ q
            .lcdcon5        = S3C2410_LCDCON5_FRM565 |+ p+ i# g* o+ g- n9 {
                              S3C2410_LCDCON5_INVVLINE |$ U" ]6 j/ U* x+ D' e- A" O- L+ H
                              S3C2410_LCDCON5_INVVFRAME |
    ( E" F6 X5 N! v. R0 K                          S3C2410_LCDCON5_PWREN |
    ) q: z  n& X# Q% u                          S3C2410_LCDCON5_HWSWP,
    6 t( ~2 B3 G  E7 U7 W# n        .type                = S3C2410_LCDCON1_TFT,
    . h/ I6 ~. W: `& {4 y        /* TQ2440的液晶是4.3寸的,分辨率是480*272 */# l. ^3 V7 i( e, q; g
    #elif defined(CONFIG_FB_S3C24X0_TFT480272)  /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */
    ! F# B3 w: X8 @$ M        .width                = 480,
    * v& h- U& q3 y) L" U1 D, c0 Y        .height                = 272,
    1 l! x8 p6 b! f3 }  v7 _. z0 K
    : U4 L  `9 G+ y* R4 y$ c        .pixclock        = 40000,    /* HCLK 100 MHz, divisor 1 */
      `1 x: O4 F/ e        .setclkval        = 0x4,
    / b1 b  c$ R) t        .xres                = 480,8 [( ^  M' R* m
            .yres                = 272,
    % T7 d# Q# R* i" o, i        .bpp                = 16,
    2 ], z& N( t* ^# e        .left_margin        = 19,        /* for HFPD*/5 L8 k0 a8 y9 j2 M, o" e
            .right_margin        = 10,        /* for HBPD*/
    - Z4 X3 u# B  p8 s  ?* b) ]  {        .hsync_len        = 30,                /* for HSPW*/! H1 _& f  s% a* i! Q( Z9 T
            .upper_margin        = 4,        /* for VFPD*/
    / ^+ K- B- Y$ L3 Z2 X# a: q        .lower_margin        = 2,        /* for VBPD*/
    4 J2 I. U# f' Z: U        .vsync_len        = 8,                /* for VSPW*/! e' G* N6 T( u. I4 d; Y
    };
    2 u! n: M+ ?6 _5 ~4 B' b) Ks3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体. X* t1 S/ M/ i! t# C5 u: n% r

      o3 U0 t6 U, {# astruct s3c2410fb_mach_info {& ~  R8 p0 U; Y
            struct s3c2410fb_display *displays;                //s3c2410fb_display结构体2 ^& z6 {. ~0 c0 C) ]# K, p
            unsigned num_displays;                                        //displays的个数
    9 A% }# v, }: p& M( d6 q- K1 b* g        unsigned default_display;                                //默认的default_display个数& W& O& z5 }- Q" E
    4 Z$ m) c- Q2 J: s
            /* GPIOs */) l% ^5 l4 [; P  k: e
            unsigned long        gpcup;                                        //GPC
    - ]$ x# g  m7 s* b  Q1 g+ G        unsigned long        gpcup_mask;
    & S# |; S5 @! H1 J' v- T        unsigned long        gpccon;3 ~8 ~2 @0 C8 J
            unsigned long        gpccon_mask;
    + l8 ^2 y, T5 Z: L        unsigned long        gpdup;                                        //GPD  C0 @7 u2 H7 e/ u
            unsigned long        gpdup_mask;
    ' L" K' O4 ]' w) M8 _, M# F& ]+ O        unsigned long        gpdcon;
    ' t% d& f6 s; b        unsigned long        gpdcon_mask;
    4 {4 }, m. r3 V* }5 J1 i1 k, _) d5 }* s6 e9 p% u; ]# U
            /* lpc3600 control register */
    # t1 V4 p5 a1 a; H" N0 ?  `* F) h        unsigned long        lpcsel;( s4 N( Q. ^1 E: m( o8 E3 v% ~) B/ p
    };
    - I  N0 b3 q; D  Q( b+ @8 W8 i5 Y4 q6 P2 {5 u# S$ m' u

    2 }& W' E$ m( v) R! D6 K. e

    该用户从未签到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-11-25 21:37 , Processed in 0.187500 second(s), 23 queries , Gzip On.

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

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

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