日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android lcd驱动框架,LCD驱动及Framebuffer相关(转载)

發布時間:2023/12/19 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android lcd驱动框架,LCD驱动及Framebuffer相关(转载) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LCD驅動及Framebuffer相關 (2012-11-20 17:04)

標簽:&nBSP;?lcd驅動??framebuffer??io內存??分類: Android驅動模塊相關

內容提要:

1. android display相關的名詞

2. 調試LCD驅動需要注意的步驟

3. 關于幀緩沖區及I/O內存

------------------------------------------------------------------------------------------

1.名詞解釋

GPU:Graphic Processing Unit (圖形處理器)

OpenGL:Open Graphic Library 定義了一個跨編程語言、跨平臺的編程接口的規格,不同廠商會有不同的實現方法,它主要用于三維圖象(二維的亦可)繪制。

SurfaceFlinger:Android中負責Surface之間疊加、混合操作的動態庫

Skia:Android中的2D圖形庫

libagl:Android中通過軟件方法實現的一套OpenGL動態庫

libhgl:為區別libagl,自定義的一種叫法。特指GPU廠商提供的硬件實現的OpenGL

composition:特指SurfaceFlinger對各個Surface之間的疊加、混合操作

render:特指使用OpenGL動態庫進行3D渲染

copybit:Android使用2D引擎來加速圖形操作(主要是Surface之間的composition操作)的一種技術,對應著一個或幾個動態庫。

pmem:Android特有驅動,從linux內核中reserve物理連續內存,可以為2d、3d引擎、vpu等設備分配物理連續內存。

Android在啟動后,會在運行時根據配置文件加載OpenGL(libagl & libhgl)的實現,如果有libhgl實現,默認使用libhgl實現,否則使用libagl實現。

OpenGL在Android中兩個作用:

1. 用于Surface的composition操作。

SurfaceFlinger會調用到OpenGL中,通過libagl或者libhgl做Surface的組合、疊加操作。

2. 用于圖形圖像的渲染

Android Framework會對OpenGL實現進行Java層次的簡單封裝,在java應用程序中對OpenGL的調用最終會調用到libagl或者libhgl中去。

很多第三方游戲、3D圖庫、某些Launcher會使用OpenGL實現比較炫麗UI的特效。

Copybit在Android中的作用

Copybit在Android中主要用于Surface的composition操作。

Skia在Android中的作用

Skia是Android的2D圖形庫,用于繪制文字、幾何圖形、圖像等。

Skia的設備后端:Raster、OpenGL、PDF

(以上這段是網上摘的)

------------------------------------------------------------------------------------------

LCD調光方式有:

一線脈沖計數調光

PWM調光

調試LCD需要注意的:

SCLK

SDA

CS

RESET

上面這幾路線是發命令和參數用的,所以首先要調通,這幾路OK后屏應該亮或花屏

PCLK

HSYNC

VSYNC

DE

這幾路是刷數據用的,屏亮后顯示不正常就調這幾路的參數

320x480的,參數為:

PCLK? ? 10MHz

HSYNC? ? 30KHz(行刷新)

VSYNC? ? 60Hz(列刷新,即一屏)

SCLK? ? 70KHz

DE? ? 30KHz(Data enable RGB寫數據時用到)

CS? ? spi寫命令或參數時用,往屏上刷數據時用不到

常見的問題:

---

lk亮屏了,但是白屏,查下極性,看是不是反了

極性: lcdc側的Pclk,Hsync,Vsync,DE是高有效,那么panel driver的

這些信號也應該是高有效,在往寄存器寫參數時要核對下

---

要注意這些東西,HFP,HBP,VFP,VBP 即通常所講的前沿,后沿

屏幕圖像左右抖動,不用說,肯定是HFP/HBP不對

前沿后沿就是給hsync,vsync往屏幕刷數據提供時間,可以看你的LCD IC SPEC了解

調試步驟(這段是網上摘的):

1)調試lcd背光,背光主要分為PMIC自帶的和單獨的DCDC,如果為PMIC自帶的背光,一般平臺廠商已經做好,

直接調用接口即可,如果為單獨的DCDC驅動,則需要用GPIO控制DCDC的EN端

2)確認lcd的模擬電,io電是否正常

3)根據lcd的分辨率,RGB/CPU/mipi等不同的接口,配置控制寄存器接口

4)根據lcd spec配置PCLK的頻率,配置PCLK,VSYNC,HSYNC,DE等控制線的極性

5)使用示波器測試所有clk的波形,確認頻率,極性是否符合要求

6)使用示波器測試data線,看是否有數據輸出,bpp的設置是否正確

7)如果lcd需要初始化,配置spi的接口,一般分為cpu自帶的spi控制器,和gpio模擬的spi。

8)根據lcd spec中的初始化代碼進行lcd的初始化

9)用示波器測量lcd的spi clk及數據線,確認是否正常輸出

10)正常情況下,此時lcd應該可以點亮。如果沒有點亮,按照上述步驟1到9,逐項進行檢查測試,重點檢查第

5項,clk的極性

11)如果lcd點亮,但是花屏。則需要先確認數據格式是否正確,然后確認fb里的數據是否正常,有以下幾種方

法確認fb里的數據

i)cat /dev/graphics/fb0 > /sdcard/fb0,然后將/sdcard/fb0 >到另一臺相同分辨率及相同格式的手機上,看圖片顯示是否正常

ii)使用irfanview軟件顯示cat /dev/graphics/fb0出來的raw數據,注意要正確設置分辨率及格式,否則顯示花屏

iii)如果adb連接正常,可以使用豌豆莢等軟件,查看fb中的數據是否正常

通過以上三種途徑,如果確認fb中的數據正常顯示,則很可能為lcd初始化代碼的問題,或者clk極性的問題,

如果fb數據不正常,則可能為lcd控制寄存器配置不正常導致。

LCD屏的調試注意事項

1. Pix clock是否在規定的范圍內。

2. Pclk是否極性正確。上升沿還是下降沿。

3. 變頻引起的閃屏問題。可以通過鎖定頻率來試驗是否是變頻引起。

要確保每一步都正確,那肯定可以顯示出圖像來

------------------------------------------------------------------------------------------

framebuffer

我們現在用的是Adreno系列,Adreno是什么?就相當于PC機上的顯卡.顯卡,也叫GPU,

它的好壞會對手機的多媒體播放和3D游戲性能有著直接的影響.

framebuffer即幀緩沖區,這個幀緩沖區就位于顯卡的內部,幀緩沖區是顯卡上固化的存儲器,其中存放的是當前屏幕的內容.你要做高通平臺,那么還會遇到MDP,MDP(Mobile Display Processor), MDP是什么? 比方說你用的data format是RGB666,那么這里的data format輸出是多少位是由MDP決定的,MDP1.1/MDP1.2只能輸出16或18bpp,而MDP1.3可以輸出24bpp.還有圖形的旋轉等效果,上面說的Copybit進行composition的動作我想底層就是由MDP支持的.我們也可以選擇是GPU來composition還是MDP來composition. 那么GPU和MDP是什么關系?GPU是顯卡,MDP是圖形處理器,后者是錦上添花,去掉無妨,前者去掉那就瞎了.后面分析代碼會看到,我們把數據寫到MDP就不管了,它內部應該是把數據再調整,然后再寫到各個接口(MIPI/LCDC)連接的panel上.這些東西都是SOC,所以你在板子上是看不到的.

顯卡對CPU來說是外設,外設會通過I/O接口連接到I/O總線上,I/O總線再連接到CPU. I/O接口包含多個I/O端口.每個連接到I/O總線上的設備都有自己的I/O地址集,通常稱為I/O端口(LKD part13 原話).為I/O編程提供統一的方法,但又不犧牲性能,所以設計者們把一組I/O端口(即一地址集)組織成一組專用的寄存器. 這也就是我們通常所說的I/O端口即寄存器的由來. 所以每個外設都是通過讀寫其寄存器來控制的.

I/O接口是處于一組I/O端口和對應的設備控制器之間的一種硬件電路.它起翻譯器的作用,即把I/O端口中的值轉換成設備所需要的命令和數據.還可以通過一條IRQ線把這種電路連接到可編程中斷控制器上,以使它代表相應的設備發出中斷請求.

硬件組織上了解后我們看軟件上怎么處理.我們要做的工作是,檢測哪些I/O端口已經分配給I/O設備. 通常來講,I/O設備驅動程序為了探測硬件設備,需要盲目地向某一I/O端口寫入數據,但是,如果其他硬件設備已經使用了這個端口,那么系統就會崩潰.所以,linux的設計者們便想出用"資源"來記錄分配給每個硬件設備的I/O端口.

資源(resource)被互斥地分配給設備驅動程序,一個資源表示I/O端口地址的一個范圍.

我為什么會說I/O呢,因為幀緩沖區就是I/O內存,和I/O有關,拋磚引玉. 關于I/O端口和I/O內存的區別可是有學問的,你知道嗎?不知道是哪位大俠創作或整理的文章,粉好,你要是知道這兩者的區別,那就不用看了,你要是不知道,那不妨看一看吧.

http://blog.csdn.net/insoonior/article/details/8011192#t0

說到這里我們需要看代碼了:

static struct resource msm_fb_resources[] = {

{

.flags??= IORESOURCE_DMA,

}

};

static struct platform_device msm_fb_device = {

.name? ?= "msm_fb",

.id? ???= 0,

.num_resources??= ARRAY_SIZE(msm_fb_resources),

.resource? ?? ? = msm_fb_resources,

.dev? ? = {

.platform_data = &msm_fb_pdata,

}

};

void __init msm_MSM7627a_allocate_memory_regions(void)

{

addr = alloc_bootmem_align(fb_size, 0x1000);? ? //這就是framebuffer的物理地址,在framebuffer的驅動中會用到

msm_fb_resources[0].start = __pa(addr);

msm_fb_resources[0].end = msm_fb_resources[0].start + fb_size - 1;

}

系統啟動并初始化時會通過以下調用,把device 的 resource 加入到resource樹中:

# TO tag? ?? ?? ?FROM line??in file/text

1??1 platform_add_devices??1455??arch/arm/mach-msm/board-qrd7627a.c

2??1 platform_device_register? ?114??drivers/base/platform.c

3??1 platform_device_add? ?337??drivers/base/platform.c

4??1 insert_resource? ?275??drivers/base/platform.c

5??1 insert_resource_conflict? ?667??conflict = insert_resource_conflict(parent, new);

6??1 __insert_resource? ?651??conflict = __insert_resource(parent, new);

有了以上的資源后就清楚了:

static int msm_fb_probe(struct platform_device *pdev)

{

fbram_size =

pdev->resource[0].end - pdev->resource[0].start + 1;

fbram_phys = (char *)pdev->resource[0].start;

fbram = __va(fbram_phys);

}

static int msm_fb_register(struct msm_fb_data_type *mfd)

{

struct fb_fix_screeninfo *fix;

struct fb_var_screeninfo *var;? ? //主要是根據panel的信息初始化這兩個數據結構

fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;

fbram += fbram_offset;

fbram_phys += fbram_offset;

fbram_size -= fbram_offset;

fbi->screen_base = fbram;

fbi->fix.smem_start = (unsigned long)fbram_phys;

}

smem_start在后面分析mdp_lcdc_update時會用到.

------------------------------------------------------------------------------------------

我們看下數據到framebuffer后是怎么顯示到屏幕上的.先從HAL層分析數據的走向,再往上的邏輯待定.

android/hardware/msm7k/libgralloc-qsd8k/ 這是display subsys的HAL層

ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info)

上層調用這句ioctl把數據推給driver,放到framebuffer里

ioctl(fd, FBIOGET_VSCREENINFO, &info)

上層通過這句可以獲知屏幕的大小

ioctl一路調用下來會到

drivers/video/fbmem.c

static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,

unsigned long arg)

case FBIOPUT_VSCREENINFO:

if (copy_from_user(&var, argp, sizeof(var)))

return -EFAULT;

if (!lock_fb_info(info))

return -ENODEV;

console_lock();

info->flags |= FBINFO_MISC_USEREVENT;

ret = fb_set_var(info, &var);? ? //struct fb_info info, struct fb_var_screeninfo var

info->flags &= ~FBINFO_MISC_USEREVENT;

console_unlock();

unlock_fb_info(info);

if (!ret && copy_to_user(argp, &var, sizeof(var)))

ret = -EFAULT;

break;

int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)

fb_pan_display(info, &info->var);

int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)

if ((err = info->fbops->fb_pan_display(var, info)))

return err;

drivers/video/msm/msm_fb.c

static int msm_fb_pan_display(struct fb_var_screeninfo *var,

struct fb_info *info)

if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */? ? /* 如果未上電,給panel上電 */

mdp_set_dma_pan_info(info, null, TRUE);

if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {

pr_err("%s: can't turn on display!\n", __func__);

return -EINVAL;

}

}

mdp_dma_pan_update(info);? ? /* 這句是把數據通過MDP更新到panel */

drivers/video/msm/mdp_dma.c

void mdp_dma_pan_update(struct fb_info *info)

struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;

mfd->dma_fnc(mfd);

drivers/video/msm/mdp.c

static int mdp_probe(struct platform_device *pdev)

case LCDC_PANEL:

mfd->dma_fnc = mdp_lcdc_update;

drivers/video/msm/mdp_dma_lcdc.c

void mdp_lcdc_update(struct msm_fb_data_type *mfd)

struct fb_info *fbi = mfd->fbi;

uint8 *buf;

int bpp;

bpp = fbi->var.bits_per_pixel / 8;

buf = (uint8 *) fbi->fix.smem_start;

buf += calc_fb_offset(mfd, fbi, bpp);

MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);? ? /* 最終會調到這句,上層拋過來的一堆數據存在buf指針指向的區域,然后

把這個地址寫到MDP BASE,然后MDP再寫到panel上 */

drivers/video/msm/mdp.h

#define MDP_OUTP(addr, data) outpdw((addr), (data))

drivers/video/msm/msm_fb_def.h

#define outpdw(port, val)? ?? ?writel(val, port)

------------------------------------------------------------------------------------------

framebuffer還有好多方方面面沒提到的,網上一搜一大把,就不提了.我只寫些自己認為需要整理的東西,算是做個整理吧.

遺留問題:

addr = alloc_bootmem_align(fb_size, 0x1000)分配的內存怎么與幀緩沖區這個IO內存對應上的?

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的android lcd驱动框架,LCD驱动及Framebuffer相关(转载)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。