乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      lcd驅(qū)動(dòng)解析

       lchjczw 2013-05-16

      硬件執(zhí)行流程1

      硬件執(zhí)行流程2

      這兩幅圖的差別在于mix的位置,mix的功能包括alpha blending,color-key,圖層處理等。流程1,這些工作是有軟件完成的,流程2是由硬件完成的。

      這個(gè)網(wǎng)上找個(gè)圖啊,不過(guò)lcd驅(qū)動(dòng)基本都是這樣的架構(gòu)。fbmem.c是已經(jīng)實(shí)現(xiàn)的,×××fb.c是需要我們自己實(shí)現(xiàn)的,這關(guān)系到具體的lcd屏。

      首先,lcd驅(qū)動(dòng)的初始化分為3個(gè)部分,

      1 lcd設(shè)備的注冊(cè)

      platform_add_devices(devices, ARRAY_SIZE(devices));

      2 lcd系統(tǒng)自帶驅(qū)動(dòng)的注冊(cè)(fbmem.c)

      register_chrdev(FB_MAJOR,"fb",&fb_fops);

      3 lcd自己寫的驅(qū)動(dòng)的注冊(cè)(***fb.c)

      platform_driver_register(&sep0611fb_driver);

      驅(qū)動(dòng)部分為什么一分為二,為了方便編寫吧,移植等等,驅(qū)動(dòng)開(kāi)發(fā)也只需要編寫下面的一段而已,工作量減小了。那么其他驅(qū)動(dòng)是否也是這樣安排的呢?

          關(guān)于設(shè)備部分呢,主要就是關(guān)于具體設(shè)備的參數(shù),比如說(shuō)lcd屏,就有一些參數(shù),這些參數(shù)根據(jù)屏的不同而不同,比如時(shí)序參數(shù),使用到GPIO,屏的寬度,屏的分辨率,還有屏控制器寄存器所占的物理地址,lcd用的中斷等。如果沒(méi)有l(wèi)cd,那么物理地址空間也不會(huì)看到lcd寄存器,lcd寄存器的物理地址也是需要申請(qǐng)的,還會(huì)映射為虛擬地址,便于操作。這些其實(shí)都是一個(gè)從無(wú)到有的過(guò)程。為了驅(qū)動(dòng)lcd屏而存在。在文件系統(tǒng)里面,設(shè)備也是抽象的,它只包含具體設(shè)備的信息,驅(qū)動(dòng)要操作具體的設(shè)備,就要先獲取相關(guān)的信息,找個(gè)就是它啊,好比,找到控制這個(gè)設(shè)備的寄存器,利用寄存器來(lái)控制外設(shè)。所以注冊(cè)的設(shè)備信息與設(shè)備必須一一對(duì)應(yīng),才能被驅(qū)動(dòng)所用。這也解釋了驅(qū)動(dòng)為什么能驅(qū)動(dòng)硬件的問(wèn)題。

          fbmem.c中的read,write是給用戶調(diào)用的,然后再調(diào)用***fb.c中的具體實(shí)施環(huán)節(jié)。自己寫的***fb.c通過(guò)register_framebuffer()與系統(tǒng)中的fbmem.c聯(lián)系起來(lái),共同組成驅(qū)動(dòng)部分。

      復(fù)制代碼
      register_framebuffer(struct fb_info *fb_info)
      {
      .......
      fb_info->dev = device_create(fb_class, fb_info->device,
                           MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
          //在/dev下面注冊(cè)設(shè)備,申請(qǐng)次設(shè)備號(hào)
      .......
      registered_fb[i] = fb_info;
      .......
      }
      復(fù)制代碼

      這就把fbmem.c與×××fb.c聯(lián)系起來(lái)了。當(dāng)用戶使用fbmem.c中的open("/dev/fb0"),就會(huì)獲得fb的主設(shè)備號(hào)29,和次設(shè)備號(hào)0,通過(guò)主設(shè)備號(hào)找到fbmem.c中的read,write等,通過(guò)次設(shè)備號(hào),可以決定你操作的是那個(gè)framebuffer(即那個(gè)圖層)。用戶只需要把數(shù)據(jù)寫入framebuffer,就等于寫入顯存,從硬件流程圖可知,數(shù)據(jù)從framebuffer到顯存是由DMA硬件完成的,所以在用戶看來(lái),操作framebuffer就是操作顯存,使得圖片可以立即被輸出顯示。(framebuffer是內(nèi)核空間的一段內(nèi)存,各個(gè)圖層可以共用同一個(gè)framebuffer,也可以各自擁有一個(gè)獨(dú)立的framebuffer)

      為什么不讓用戶直接操作顯存呢?

      顯存本身就是一個(gè)設(shè)備,也有對(duì)應(yīng)的物理地址,這樣看是可以直接操作的。之所以使用framebuffer,我認(rèn)識(shí)用戶寫的數(shù)據(jù),需要處理才能顯示,而如果直接寫入顯存,就直接流入lcd屏了。所以要把用戶數(shù)據(jù)緩沖下,以便處理(圖層疊加啊,yuv改變?yōu)閞gb啊,使用colorkey,alpha-bleeding等),處理完再送入顯存,直接通過(guò)hdmi等接口送給lcd屏。

      init部分主要完成的任務(wù)是:屏的初始化,顯示的初始化,最后打開(kāi)lcd,背光,等待圖片數(shù)據(jù)輸入,然后輸出。(產(chǎn)生fbinfo結(jié)構(gòu)體給fbmem.c使用)

      用戶操作的流程包括:ioctl控制圖片的顯示屬性(讀取初始化時(shí)的配置或者使用bsp操作寄存器改變顯示設(shè)置)和顯示圖片的數(shù)據(jù)源。(概括說(shuō)就是控制和數(shù)據(jù)兩條線)

      這一節(jié)主要分析init部分,就是屬于***fb.c文件的函數(shù)。

          驅(qū)動(dòng)程序綁定由內(nèi)核自動(dòng)執(zhí)行,當(dāng)內(nèi)核發(fā)現(xiàn)一個(gè)驅(qū)動(dòng)程序與一個(gè)設(shè)備匹配時(shí),將調(diào)用驅(qū)動(dòng)程序的probe函數(shù),完成對(duì)設(shè)備的探測(cè)及初始化等工作。device與driver是用名字搭配的,其實(shí)注冊(cè)并部分先后,device注冊(cè)時(shí)會(huì)去找driver,driver注冊(cè)的時(shí)候會(huì)去找device,當(dāng)配對(duì)成功后,driver就從device中獲取必要的數(shù)據(jù)(使用到資源或者一些參數(shù)),然后對(duì)設(shè)備進(jìn)行初始化。搭建必要的設(shè)備運(yùn)行環(huán)境,比如lcd需要在內(nèi)存中申請(qǐng)一段空間,用于接收用戶發(fā)送過(guò)來(lái)的數(shù)據(jù)。只有都準(zhǔn)備完畢了,才可以打開(kāi)設(shè)備,等待用戶操作。(lcd driver還產(chǎn)生了一個(gè)結(jié)構(gòu)體fbinfo,存放了用戶可能用到的所有信息,放到fbmem.c中)這樣probe函數(shù)的入口參數(shù)就可以解釋了。

      kzalloc

          用kzalloc申請(qǐng)內(nèi)存的時(shí)候, 效果等同于先是用 kmalloc() 申請(qǐng)空間 , 然后用 memset() 來(lái)初始化 ,所有申請(qǐng)的元素都被初始化為 0.

      首先為什么要使用這個(gè)函數(shù),目的是在堆空間分配一段內(nèi)存給一個(gè)指針,然后初始化為0。其實(shí)完成同樣的功能也可以這樣,先定義一個(gè)結(jié)構(gòu)體實(shí)例,并初始化為0,然后把這個(gè)對(duì)象賦值給那個(gè)指針。結(jié)果都是一個(gè)指針指向了一段大小一樣空的內(nèi)存,只不過(guò)一個(gè)在堆,一個(gè)在棧。不過(guò)在堆中更容易控制,可以自己free掉,而不需要等待系統(tǒng)去幫你free。有個(gè)不好就是把指針給別人用,別人卻不去free它,那就糟了,這一點(diǎn)還是比不上結(jié)構(gòu)體實(shí)例的。

      platform_get_resource

       

      復(fù)制代碼
      struct resource *platform_get_resource(struct platform_device *dev,
                                         unsigned int type, unsigned int num)
      {
             int i; 
             for (i = 0; i < dev->num_resources; i++) {
      //不管你想找哪一類資源,都要從第一個(gè)資源看是比對(duì),所以效率嗎貌似有點(diǎn)低,不過(guò)一般總資源數(shù)也不多。
                    struct resource *r = &dev->resource[i]; 
                    if (type == resource_type(r) && num-- == 0)
                           return r;
      //找到匹配的之后把整個(gè)結(jié)構(gòu)體返回。
             }
             return NULL;
      //沒(méi)找到就返回空。
      }
      //這里取出的資源包括中斷號(hào),io端口的寄存器物理地址等。這些資源是設(shè)備需要用的,驅(qū)動(dòng)取出后用于靜態(tài)申請(qǐng)(就是已知物理地址,中斷號(hào)的情況下去申請(qǐng)物理地址和中斷號(hào)),可以理解為,
      //告訴系統(tǒng)這段物理地址和中斷號(hào)被占用,不能再分配給其他設(shè)備了。如果沒(méi)有l(wèi)cd,這些資源就可以給別人用了。這些都是系統(tǒng)資源啊,大家共用的。
      
      復(fù)制代碼
      info->mem = request_mem_region(res->start, resource_size(res), pdev->name);
      //這就是申請(qǐng)指定的io物理地址空間,告訴系統(tǒng),這段物理地址被lcd占用。(后來(lái)使用寄存器的物理地址)
      info->io = ioremap(res->start, resource_size(res));
      //把申請(qǐng)到的物理地址空間映射到虛擬地址空間中,后來(lái)操作寄存器都是使用的虛擬地址。

      framebuffer_alloc()

      framebuffer_alloc()功能是向內(nèi)核申請(qǐng)一段大小為sizeof(struct fb_info) + size的空間,其中size的大小代表設(shè)備的私有數(shù)據(jù)空間,并用fb_info的par域指向該私有空間。為什要價(jià)size大小,因?yàn)檫@樣才是整個(gè)fbinfo的大小,私有數(shù)據(jù)空間需要與fbinfo一起free,就是說(shuō)這段數(shù)據(jù)是不可缺少的,那么為什么不用結(jié)構(gòu)體來(lái)存放,這樣與fbinfo就是一個(gè)整體了啊,一起free更有說(shuō)服力。大家注意一下par是個(gè)void型的指針,為什么要是void型的呢,因?yàn)樗约憾疾恢浪麑⒁赶虻乃接袛?shù)據(jù)類型,那你用什么結(jié)構(gòu)體來(lái)存放這莫名的私有數(shù)據(jù)呢。fbinfo這個(gè)結(jié)構(gòu)體里面的成員是定好的,他是與fbmem.c的接口,這個(gè)接口結(jié)構(gòu)體中就只有這樣一個(gè)私有數(shù)據(jù)指針是可變的,是給用戶發(fā)揮的。這就解釋了為什么par是void類型的指針。既然fbinfo是在***fb.c中申請(qǐng)的,作為數(shù)據(jù)接口給fbmem.c,那么在init結(jié)束后也是不能釋放的,所以放在堆里面很安全,在注銷驅(qū)動(dòng)的時(shí)候在remove函數(shù)內(nèi)會(huì)free掉,很方便是不是?

       關(guān)于android lcd doublebuffer問(wèn)題

      DMA從SDRAM FIFO中取數(shù)據(jù),送給顯存buffer的時(shí)候,中間需要進(jìn)行處理,比如mix alphableeding,colorkey等工作,這些時(shí)間并不長(zhǎng),但是在進(jìn)行處理時(shí),SDRAM FIFO中的數(shù)據(jù)無(wú)法更新,可以理解為是基于此FIFO進(jìn)行合成等工作的,合成完了才會(huì)送到顯存FIFO,送完后等待取出下一張要顯示的圖片,取圖片又是需要時(shí)間的,兩個(gè)時(shí)間加起來(lái)就無(wú)法忽略了,有明顯的延遲。所以使用doublebuffer,就是行為原來(lái)的兩倍,可以存兩張圖片,一個(gè)用來(lái)合成,一個(gè)用來(lái)繪制,兩個(gè)交替使用,解決延遲的問(wèn)題。(這也就是通常說(shuō)的pan_display)

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多