【转】s3c6410 framebuffer分析

原文地址: http://blog.csdn.net/walkingman321/archive/2011/02/27/6211075.aspx

 

本文介绍了 s3c6410 中的 framebuffer ,参考代码为 Linux2.6.28 。网上介绍 framebuffer 的文章很多,内核代码中也有关于 framebuffer 的文档,所以本文只介绍一些其它文章较少介绍的部分。

1.      Overview

在嵌入式系统中,会有一块内核空间保存 LCD 上每一个象素需要被显示的值。系统运行时, CPU 的显示控制器会自动从这块内存读取内容,然后发送到 LCD 显示屏。这块内存就叫作 framebuffer 。对程序来说,通过修改 framebuffer 中的内容,就可以控制 LCD 的显示。

 

Linux GUI 系统都运行在用户空间,不能直接访问内核空间。所以就需要一个 framebuffer 驱动,将内核空间的 framebuffer 映射到用户空间,方便 GUI 的访问。

framebuffer 的典型操作如下所示:

l          fd = open(fb, …);

l          ioctl(fb, …);               // 设置 framebuffer ,比如象素的格式等。

l          pBuffer = mmap(fb, …);    // 映射 framebuffer 到用户空间

l          。。。                       // 像读写内存一样操作 pBuffer

 

 

framebuffer LCD 接口之间的通路有两种,分别是 DMA local bus ,一般都会将通路设置为 DMA 以提高性能。设置成 DMA 时,注意不能用 kmalloc 分配 framebuffer ,应使用 dma_alloc_writecombine 函数分配能被 DMA 访问的内存空间,对应代码在 s3cfb_map_video_memory 函数中。

 

s3c6410 支持多个层叠窗口( 5 个),显示的时候,这些窗口会被叠加显示。在这里, framebuffer 的概念变成和窗口关联,而不是和 LCD 显示屏关联。每个窗口对应一个 framebuffer ,所以, s3c6410 中可以有 5 framebuffer (不考虑硬件双缓冲的情况)。关于窗口的概念在 s3c6410 的芯片手册中有介绍。

2.      双缓冲

双缓冲是指 framebuffer 的大小两倍于 LCD 的大小,可将其称为 frame1 frame2 LCD 显示 frame1 的内容时, GUI 在后台绘制 frame2 LCD 显示 frame2 时, GUI 在后台绘制 frame1

有多种实现双缓冲的方法,比如硬件切换、 virtual screen 等。

 

硬件实现

s3c6410 的芯片手册中提到它最多支持 5 个窗口叠加。其中 win0 win1 支持硬件双缓冲。 win0 对应的寄存器为

l          VIDW00ADD0B0                               // win0 buffer0 起始地址

l          VIDW00ADD0B1                               // win0 buffer1 起始地址

l          VIDW00ADD1B0                               // win0 buffer0 结束地址

l          VIDW00ADD1B1                               // win0 buffer1 结束地址

要实现 win0 buffer0/1 之间的切换,只需要设置 WINCON0 寄存器的 BUFSEL 位即可。显示控制器会根据 VIDW00ADD0B0 VIDW00ADD0B1 的值,自动切换是使用 buffer0 还是 buffer1 作为显示内容。

win1 对应的寄存器与 win0 类似。

代码中对应的切换命令为 IOCTL S3 CFB _CHANGE_REQ

 

Virtual Screen

virtual screen 的概念在 s3c6410_rev12.pdf 的第 485 页, figure 14-10 。通过设定 framebuffer xoffset yoffset ,可以设置 framebuffer LCD 显示的 x y 坐标。因此,可以定义 frame1 的坐标为 (0,0) frame2 的坐标为 (0,<LCD’s yres>) 。通过改变 x/y 的坐标,可以在 LCD 上切换 frame1 frame2

在代码中,能改变坐标的 IOCTL 操作为   FBIOPAN_DISPLAY

 

FBIOPAN_DISPLAY 通过改变 framebuffer 的起始地址实现双缓冲,对应的函数为 s3cfb_set_fb_addr 。这种机制被 Android 采用。

3.      alpha colorkey

s3c6410 支持硬件 alpha 操作和 colorkey 操作。

alpha 操作用于实现图形渐变效果,以及半透明效果等等。

colorkey 操作可以在融合两个窗口时过滤掉其中一个窗口的某一种特定颜色。因为 GUI 在显示图象时都是通过画矩形实现,所以这个功能在显示非矩形图像(比如圆形)时很有用。假设要显示圆形图案,可以把圆形放进一个矩形,然后矩形的剩余部分填充一个背景色,并把这个背景色指定为 colorkey 。这样,显示的时候自动将 colorkey 指定的颜色过滤,屏幕上就能显示出那个圆形了。

不管是 alpha 操作还是 colorkey 操作,都有对应的软件模拟实现。网上类似的代码有很多,不再赘述。

4.       窗口平移与 virtual screen 平移

窗口平移与 virtual screen 平移是两个容易被混淆的概念,下面简单介绍一下:

窗口平移

s3c6410 硬件上支持 5 个窗口,每一个窗口都可以显示在 LCD 的不同位置。所以窗口平移就是指硬件支持的窗口在 LCD 上的移动。

窗口平移由以下寄存器控制:

S3C_VIDOSD[0-4]A

S3C_VIDOSD[0-4]B

framebuffer 的驱动中,可以通过以下 IOCTL 控制窗口平移:

S3 CFB _OSD_MOVE_LEFT

S3 CFB _OSD_MOVE_RIGHT

S3 CFB _OSD_MOVE_UP

S3 CFB _OSD_MOVE_DOWN

另外 SET_OSD_INFO 也可以用于控制平移。内核中与窗口平移对应的函数为 s3cfb_set_win_position

virtual screen 平移

virtual screen 的概念在上面介绍双缓冲的地方提到过,具体可查阅芯片手册。这里的平移指的是显示内容的平移,可以想象成通过拖动 GUI 中的滚动条造成的效果。

virtual screen 的平移由寄存器 VIDWxxADD[0-1] 实现 内核中对应函数为 s3cfb_set_fb_addr 用户程序可以通过调用 FBIOPAN_DISPLAY 控制。

 

目前 s3c6410 framebuffer 实现中,窗口平移和 virtual screen 平移都由 fb_var_screeninfo 中的 xoffset yoffset 控制,所以使用时要小心。另外 FBIOPAN_DISPLAY 的实现代码中没有考虑 x 轴平移,只有 y 轴平移。

你可能感兴趣的:(c,linux,android,video,嵌入式,buffer)