找回密码
 注册
关于网站域名变更的通知
查看: 284|回复: 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
    % R) a* G1 L5 C
    # d4 r9 f) ?( ?看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数
    . o7 `' ~5 z6 d4 C5 s( F1 t9 S6 r5 J9 O3 B: J
    " ^5 j+ H  Q' u3 V, |. j8 S
    int __init s3c2410fb_init(void)
    # I! T$ m7 W" t{" B/ v7 M3 {0 |
            /* 注册一个s3c2410fb_driver平台驱动 */3 ?1 u1 X. B2 G* y+ w
            int ret = platform_driver_register(&s3c2410fb_driver);
    ' ^% N$ d1 u) z% D9 q
    ( t8 O" ^6 v9 X% F7 Q$ n- {: ?4 n        if (ret == 0)
    3 ^* Y- ~: S3 h* L& _6 n. I& U: r                ret = platform_driver_register(&s3c2412fb_driver);;
    1 [; W0 u/ I% V- q& v: `/ I9 P. P& P/ A+ o" ^0 ?0 Z. a4 X
            return ret;$ M/ N" i# l( k6 u
    }
    ) o; f! F, T% |8 I2 F1 @出口函数,自然是注销s3c2410fb_driver平台驱动
    # d( p9 h+ f  Q8 ~7 [; a
    ) c6 L! F+ p0 |$ Mstatic void __exit s3c2410fb_cleanup(void)+ g5 q* F, M7 a4 S
    {3 i! H  ]) S( R$ O5 K
            platform_driver_unregister(&s3c2410fb_driver);
    * Z( Z* x! l( s0 i! X! @4 J        platform_driver_unregister(&s3c2412fb_driver);! l! E2 F& b/ H0 w
    }' I; L$ n: j' r0 p
    我们研究的是s3c2440,只关心s3c2410fb_driver,s3c2412fb_driver不用理会。
    " v) \6 j/ ~' V$ v5 l3 p1 o# N$ P7 P( r  w  I. q" E2 q
    static struct platform_driver s3c2410fb_driver = {6 A2 D# @( j! S) \; @
            .probe                = s3c2410fb_probe,5 i. e. Q, |+ s/ q5 ~7 i" N
            .remove                = s3c2410fb_remove,
    * h; a/ b% D) ]1 S5 \  c. t        .suspend        = s3c2410fb_suspend,
    3 M2 |! `' ?8 x        .resume                = s3c2410fb_resume,
    3 ?# a3 [' W1 g! _! G  P        .driver                = {
    / r4 b% \3 h, X( r* Z& b" o2 G                .name        = "s3c2410-lcd",9 r) p/ A! v$ T- O/ E% L. w
                    .owner        = THIS_MODULE,
    ' ]6 @5 B# A, y. D2 q        },
    6 L  p6 H" e6 F/ d9 e7 l% X};, P6 i! h: C# |+ ~
    这里看到s3c2410fb_driver的name字段为s3c2410-lcd。回顾这钱前面章节说过的知识,如果linux系统中存在同名的平台设备时,就会调用平台驱动的probe函数。这里,如果存在有同名"s3c2410-lcd"的平台设备,就会调用s3c2410fb_driver的s3c2410fb_probe函数。' Z, `& P  ^. @+ u( M
    在source  insight搜索s3c2410-lcd,很快就能搜索到arch/ARM/plat-s3c24xx/devs.c中有那么一段
    & Y2 B8 m9 h, B/ m7 w* Y& X
    # b0 r4 P: v# f* R. l6 y7 x* L2 ^# E# q  |. M
    struct platform_device s3c_device_lcd = {$ U+ d% p* f. W6 `. K$ [) b
            .name                  = "s3c2410-lcd",  B/ ^, N& M) r" c" D' e# R
            .id                  = -1,0 Q  p& u9 d2 r( ]% g0 z% z
            .num_resources          = ARRAY_SIZE(s3c_lcd_resource),) [7 C6 T: ^% Z0 k4 J; |
            .resource          = s3c_lcd_resource,7 N2 e1 h+ y7 ~3 s' `
            .dev              = {
    ( }/ q4 x1 i2 K6 Y" V+ h                .dma_mask                = &s3c_device_lcd_dmamask,- I; [0 }# X4 e) D
                    .coherent_dma_mask        = 0xffffffffUL/ W, {8 @3 z" k8 G$ {  b
            }
    / @1 o6 A+ }- X. L; D% R};- s2 T8 V7 [7 a, O5 @5 T3 |

    3 J, X( x( g7 a) j5 yEXPORT_SYMBOL(s3c_device_lcd);& O  C( j2 L. M' |; T8 n* P! o
    其中平台设备中比较重要的是成员是resource,这里是s3c_lcd_resource. z1 W* z4 q# c0 L+ j
    6 n, [. Z# r" b) @0 V8 T
    static struct resource s3c_lcd_resource[] = {/ N: T+ {5 V' `7 ~* N
            [0] = {5 f; a0 m) U8 g* P! \, f' H
                    .start = S3C24XX_PA_LCD,                                /* 0x4D000000 */
    ! \7 v$ a) H" m( |: }' R5 m* x                .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
    1 `2 f$ _- P1 X% Y                .flags = IORESOURCE_MEM,
    5 m+ c& f( Q7 v. Q) V        },) U- a* I+ Q3 S1 J; {4 v# f# L! y* i
            [1] = {4 p( \! Z% Y+ g, `
                    .start = IRQ_LCD,                                                /* IRQ = 32 */
    ! b9 g- l# ?- o* O! ?8 `                .end   = IRQ_LCD,
    7 B8 l1 p0 H6 p# S                .flags = IORESOURCE_IRQ,
    - s4 ?4 D- W& }9 p# d        }
      ?* i; J6 s! Q* u0 \
    & X% P) X. t2 y3 s; H; c5 N/ o$ K9 z};
    % t6 Z- U0 J. S# P+ ~4 v& S1 J/ ^
    ) O, g5 z# n7 V- y$ j9 Rstatic u64 s3c_device_lcd_dmamask = 0xffffffffUL;& _6 A6 v/ J+ L8 u" ^7 x
    那么接下来当然是要分析probe函数了% t9 f; S; P5 \1 F3 g- W) o3 k. r
    : E$ x+ b" [: O( S2 V- m
    static int __init s3c2410fb_probe(struct platform_device *pdev)
    & g# v; Z7 O8 K4 ]+ l{# ~) @- @5 U5 o0 X1 i1 f
            return s3c24xxfb_probe(pdev, DRV_S3C2410);( |/ `; Q4 k. a! Y7 s. I! W0 \
    }5 |* l, @% t2 Z" q0 r. S8 b7 Q
    s3c2410fb_probe函数调用s3c24xxfb_probe函数,这是lcd驱动的关键函数之一,留到"linux lcd设备驱动剖析二"再分析,但是在分析这个函数前,需要来熟悉一下几个结构体。1 ^2 j" }2 L& \% W$ q" z, q8 x
    linux lcd驱动中有个关键词叫帧缓冲,它是linux为显示设备提供的一个接口,它允许应用程序在图形模式下直接对显示缓冲区进行读写操作,用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
    9 W1 X5 {' ^9 W% r: y8 ~0 F" Y9 G. H
    帧缓冲设备为标准字符设备,主设备号为29,对应/dev/fbn 设备文件,帧缓冲设备最关键的一个数据结构是fb_info结构体,它包括了关于帧缓冲设备属性和操作的完整描述。. ?0 ~3 ]! u3 a& l/ N' u0 r9 G  e

    / U1 D; Z, r, Z5 n7 Gstruct fb_info {
    7 S# N" z9 m  j$ U        int node;                                                //用作次设备号索引
    . W0 |; |4 |2 _        int flags;8 l7 V' a* n8 n2 M; Q& ~  z
            struct mutex lock;                                //用于open/release/ioctl函数的锁
    + s7 C) z& }0 h        struct fb_var_screeninfo var;        //可变参数,重点4 g, `7 v3 i1 X: h! d9 \0 {% e
            struct fb_fix_screeninfo fix;        //固定参数,重点, O5 q+ z& }5 i* l( d/ z/ ?
            struct fb_monspecs monspecs;        //显示器标准
    ! \4 f# ?+ ~1 T2 P! U7 B% M        struct work_struct queue;                //帧缓冲区队列
    ) j- J7 A: h% v0 X        struct fb_pixmap pixmap;                //图像硬件映射
      o/ G5 h$ w0 a! N; v# o        struct fb_pixmap sprite;                //光标硬件映射
    + b8 \9 g1 D; T5 T: l6 y, I5 T8 |        struct fb_cmap cmap;                        //当前颜色表5 @, x* {  l' Z% F7 k
            struct list_head modelist;      //模式链表
    ! A' |" H$ ~6 M% ], B% z        struct fb_videomode *mode;                //当前video模式
    - P( J  t7 B' B6 ?& r% e
    " |% |* T  |5 ]        char __iomem *screen_base;                //显存基地址" E: I! S, _' z* R/ t, \- t* _9 A4 ^
            unsigned long screen_size;                //显存大小9 X6 L2 e. J$ a3 c3 m& @
            void *pseudo_palette;                        //伪16色颜色表
    0 O0 g9 D$ L3 ]' W/ g% ^7 Z/ Z/ Q#define FBINFO_STATE_RUNNING        0
    + j' E8 \2 u$ g- F: G( G) R* c#define FBINFO_STATE_SUSPENDED        1
    6 D2 _9 n% A. a3 y+ l3 G        u32 state;                                                //硬件状态,如挂起, R" _5 K/ k' s4 r
            void *fbcon_par;                //用作私有数据区
    ' J4 i  l# Z$ x  U! h$ H1 I        void *par;                                                //info->par指向了额外多申请内存空间的首地址2 b# U( G3 e5 V- |4 A  l' g$ }8 F5 c
    };3 d. @  j# F) s  o) M' J
    s3c2410fb_info结构体,这是s3c2410抽像出来的特有信息
    2 V. {0 q+ x/ u1 ]4 f5 m
    + a& N; s6 }* y+ Kstruct s3c2410fb_info {
    6 l0 Q$ y' q7 Q7 |3 m$ x% m: v! y        struct device                *dev;                        //设备* l$ x+ O7 Y3 T. [# D$ I
            struct clk                        *clk;                        //时钟0 s) x5 h. o7 L, P) x- U* J7 \

    ' J- g, L0 `+ t: f9 |/ S- Q0 ?) d: }        struct resource                *mem;                        //资源
    4 P! m0 B) f: I  U        void __iomem                *io;                        //IO地址3 `/ X  |6 Y$ h) y" ~) W
            void __iomem                *irq_base;                //IRQ基数
    - m1 r3 Q% W0 S  C8 ]7 C6 {" ~3 H+ o) ]/ W" o& H5 K
            enum s3c_drv_type        drv_type;                //驱动类型,S3C2410或S3C2412
    1 `( D; q; [; t' z" T- J% W' q        struct s3c2410fb_hw        regs;                        //s3c2410 lcd硬件寄存器
    3 M# o1 x5 n) I1 K$ |1 i: v7 ^, u! b5 e# K
            unsigned int                palette_ready;        //调色板是否就绪标志位4 W" e( `0 b+ O: D

    # A6 i$ F4 k+ L- x- T: P( j- X# E6 |        /* keep these registers in case we need to re-write palette */
    5 G9 h2 R6 u$ U! o( O1 }* G0 T        u32                        palette_buffer[256];        //调色板缓冲区+ ?. @1 M- u  e/ ]
            u32                        pseudo_pal[16];                        //伪颜色表/ A! E  `# M6 J9 ~" _. ~
    };* T0 `' g2 D( x8 ^; ]
    s3c2410fb_display结构体,关于LCD参数的描述,如分辨率,LCD类型,BPP等等
    % n& X" D4 c! [8 B
    + W/ b3 N, S; I8 w$ G- i0 P6 h/* LCD description */
    , S" s& _: N: w. N# h" M1 M  estruct s3c2410fb_display {
    3 q' _5 C4 R" `        /* LCD type */
    6 G3 L, X) l+ M3 E6 |        unsigned type;$ |) o9 j4 \1 J; g

    % N- @  F  o# o" U! U; C, m5 d4 `1 M        /* Screen size */
    3 z3 X# `: m, Y  a( ]/ R7 H! n) K        unsigned short width;0 R) P" Y3 @% j* Z5 V) K- l3 N
            unsigned short height;
    : _7 q5 f, X* c/ f& t$ t9 p
    4 g. j' M0 Z* X$ X  n" s" f! F        /* Screen info */
    ( G& ?2 U& k4 y        unsigned short xres;- ?+ Q' R. i2 R4 e$ i
            unsigned short yres;2 m9 k3 L. y' a7 R$ l9 r
            unsigned short bpp;
    - ]4 ~  @- f; d- Y% Z/ w( ?' X# }" i( @" F! f7 q4 _+ `
            unsigned pixclock;                         /* pixclock in picoseconds */0 R  c+ K% d* \. C/ m
            unsigned setclkval;                         /* clkval */
    : [: s0 N& }9 j        unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
    3 K) c% V$ g+ V6 F        unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */& ~2 L! n7 I/ p! k- \
            unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */' v8 Z- a, I! E- S' j
            unsigned short upper_margin; /* value in lines (TFT) or 0 (STN) */! @+ ]. l. P4 ^8 j
            unsigned short lower_margin; /* value in lines (TFT) or 0 (STN) */$ z, S  R  H; w( s  t, {! m
            unsigned short vsync_len;         /* value in lines (TFT) or 0 (STN) */
    : R. u6 N* h3 h" }6 W) U4 X4 B# M1 B; R3 V7 k3 Q1 \
            /* lcd configuration registers */9 a# P% Y; g' P. C
            unsigned long        lcdcon5;4 |9 Q4 n8 R. Z
    };5 m6 \9 Z5 u, g4 A0 d8 U$ ?! \0 g
    对于TQ2440的液晶屏实例为tq2440_lcd_cfg,为方便查阅这里省略了其他分辨率的参数设置
    : \1 z( B4 x- W4 S1 l$ f3 f$ Z* h4 C  u' _) j5 P: j
    /* LCD driver info */; l- s% _3 e7 }9 n) V$ o5 g
    static struct s3c2410fb_display tq2440_lcd_cfg __initdata = {; V! Z/ \/ ^9 D( B. A- ?
            .lcdcon5        = S3C2410_LCDCON5_FRM565 |6 P' o& y# z' J4 {# b- ^& \; ~
                              S3C2410_LCDCON5_INVVLINE |0 B5 ^# f" z/ k; `4 k
                              S3C2410_LCDCON5_INVVFRAME |/ g! b6 ^( n7 Y" P9 W, w
                              S3C2410_LCDCON5_PWREN |
    7 f, K& @( F  x/ J, i( C                          S3C2410_LCDCON5_HWSWP,
    ! I- [6 W3 _! x; d        .type                = S3C2410_LCDCON1_TFT,
      @8 S# n: m3 @        /* TQ2440的液晶是4.3寸的,分辨率是480*272 */! ~1 e# Y# F5 @+ B% y5 p) ~7 t
    #elif defined(CONFIG_FB_S3C24X0_TFT480272)  /* config_EmbedSky_W43:CONFIG_FB_S3C24X0_TFT480272=y */" o5 O( m' [- x5 g% p
            .width                = 480,+ ^% x" ^; V; X" m
            .height                = 272,
    , ?3 ^  f& I# Y2 A3 M' ^, x- \  I3 H) f  J' u: M! [3 D  [6 ]& C
            .pixclock        = 40000,    /* HCLK 100 MHz, divisor 1 */( K; g5 Z. G( V  R8 G
            .setclkval        = 0x4,% B; \: q6 s/ a1 Q1 U
            .xres                = 480,
    / A8 s& K; I! B. l        .yres                = 272,* |; X5 _8 @) |$ Z) }0 B
            .bpp                = 16,/ s. N: o1 z& o  a/ X) v1 M* F
            .left_margin        = 19,        /* for HFPD*/( z& I/ j) ]3 t( Y6 j( t+ I
            .right_margin        = 10,        /* for HBPD*/
    ; M0 `3 i% E9 ~& e# ]& I# U        .hsync_len        = 30,                /* for HSPW*/
    * j8 X6 A" y' t! T" ^        .upper_margin        = 4,        /* for VFPD*/
    7 d. e7 `, `* y% ^9 r, A        .lower_margin        = 2,        /* for VBPD*/
    : a. m8 r! p' M7 F; ?        .vsync_len        = 8,                /* for VSPW*/+ M, k& k* ~- Q/ w; f% D( o
    };, _- Q4 S# d% u/ D5 l$ K0 I
    s3c2410fb_mach_info结构体,它包括了s3c2410fb_display结构体- ^# z7 O# d) e& Z
      E( m$ p) l  w4 p/ N* u8 i# R% v
    struct s3c2410fb_mach_info {8 `* z- G! d! \/ J& B( u
            struct s3c2410fb_display *displays;                //s3c2410fb_display结构体
    # ?5 f# u2 v% `/ N" T- P0 q. K        unsigned num_displays;                                        //displays的个数
    2 c: q' Q6 i2 ]4 u        unsigned default_display;                                //默认的default_display个数
    : E3 ]! [6 ^# x# J2 T8 A
    ' U5 M  R  A; z" c1 A. t( g! l        /* GPIOs */
    , f7 ?2 ~8 b) g5 {+ }        unsigned long        gpcup;                                        //GPC
    ( p9 q5 T; L2 w) J: i5 a' ^        unsigned long        gpcup_mask;: M3 i* |& g: M
            unsigned long        gpccon;- Z( j/ U* a& ~' T$ B) C! y% x
            unsigned long        gpccon_mask;
    4 e1 q% k# F9 W4 C" B% Y        unsigned long        gpdup;                                        //GPD
      W% _4 E3 ]4 B* q( R7 }        unsigned long        gpdup_mask;( D; S  b6 ]. `8 {6 N) f5 @- {
            unsigned long        gpdcon;# \) x5 w: Q% h% g) T7 u
            unsigned long        gpdcon_mask;
    ' z: G2 D' D/ e1 B- d
    ; d; i) T  }( [        /* lpc3600 control register */
    ' i# q% Y' X3 c* l/ k7 @        unsigned long        lpcsel;- c. e+ W! T. u5 M6 G) t
    };
    ' ]4 S5 m& i) R7 b( D5 N$ L+ L0 ?: S. n; U4 |

    " l$ B! o6 D* `$ I" t! [

    该用户从未签到

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

    本版积分规则

    关闭

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

    EDA365公众号

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

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

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

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

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