您的位置:首页 > 运维架构 > Linux

嵌入式2D加速显卡SM501驱动的移植[linux.2.6.18]

2010-04-15 11:11 405 查看
本文从三个方面说明一下SM501显卡驱动在2440+2.6.18环境下的移植:

1 硬件情况。

2 移植过程

3 驱动测试

一、硬件情况:

第一次接触到显卡编程,有点不太适应。SM501的Datasheet写的太简略,个人觉得有用的基本上就是两个方面:

1 内存映射模式。

2440与
SM501连接模式为2440作为HOST有独立的SDRAM,SM501除了可以访问HOSTSDRAM外,还拥有8MB的本地内存作为
FrameBuffer。SM501的帧缓存与IO寄存器占有64M地址空间。其中0~62M属于Framebuffer,高2M地址空间属于SM501
的IO寄存器端口地址MMIO_BASE。这2M
IO端口空间中每64KB属于一组接口寄存器。 在我的板子上,SM501的64M地址空间映射在2440的
0x800_0000~0x1000_1000范围内。即FrameBuffer的起始物理地址为0x800_0000,SM501 MMIO_BASE
地址0xBE0_0000。 这些对于移植驱动来说应该已经足够。

2 基本配置。由于两个原因:1是对于图形显示芯片的基本知识欠缺,2是SM501的Datasheet实在不怎么样,太简略。应该是具体的配置还不太清晰。 主要方面如下:

1)系统设置 :系统配置,DRAM配置时序等,GPIO功能配置。

2)2D加速操作。设置寄存器的值和命令,启动图形加速操作。

3)LCD接口设置

4)CRT
接口设置

二、SM501驱动在2.6.18内核下的移植过程:



下载SM501驱动,版本0.05,按照其readme.txt的说法,支持2.6.4内核和2.4.20。

开发板环境s3c2440 + linux2.6.18。

1)按照驱动目录下的readme.txt,先将4个驱动源文件voyage.c(.h),smi2d.c(.h)拷贝到driver/vedio/下面。

2)在该目录下修改与编译相关的Kconfig和Makefile:

首先修改Kconfig文件,在menu "Graphics support" 菜单,config FB选项下边 添加选项

# added by beelike ,for sm501 support !!

config FB_SM501_KERNEL_2_6_X

bool "Silicon Motion, Inc. SM501 support"

depends on FB

choice

在Makefile中 添加 编译规则 :

obj-$(CONFIG_FB_SM501_KERNEL_2_6_X) += voyager.o smi2d.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o

3)在make menuconfig 中,选中Frame buffer 支持,LOGO,SM501支持。

下面是源代码的修改。

使驱动默认支持支持1024*768*32 CRT显示。

4)在voyager.h中,相关修改

#define isPC 0

//非PC系统

#define isPCI 0

//非PCI总线

#define SCREEN_X_RES

1024

//水平分辨率

#define SCREEN_Y_RES

768

//480

#define SCREEN_BPP

32

// BPP

#define isACCELENT

0 /* 2440 非 Accelent 平台*/

#define FB_PHYSICAL_ADDR 0x08000000 //nGCS1

#define REG_PHYSICAL_ADDR 0x0BE00000 //0x08000000+62M的地址为MMIO_BASE

voyager.h修改结束。

5)接下来的移植过程与readme.txt中的大不相同。我想是因为2.6.4与2..6.18版本的不一样。

Readme.txt中
说到将voyager.c中sm501fb_init函数添加到fbmem.c中的fb_drivers数组中去,然而,2.6.18的内核已经没有这个
数组了。添加到这个数组中无非就是为了使得在启动的时候sm501fb_init得到执行而已。我想到的办法是使用
module_init(sm501fb_init)。事实证明,这样做是正确的。

6)在sm501fb_init函数中添加外部晶振频率设定。驱动源码中默认使用24M,但是我的板子上使用的是12M。

在sm501fb_init中添加:

//beelike add , here set extern cystal clock =12M .

crystal=regRead32(MISC_CTRL);

crystal=FIELD_SET(crystal,MISC_CTRL,CRYSTAL,12);

regWrite32(MISC_CTRL, crystal);

//end add

添加的位置必须在对SM501的64M缓存进行ioremap之后,否则会出现Oops。

如果显存不为8M,可以在sm501fb_init函数中设置。驱动默认设置的是8M。

7)设置CRT模式,修改smi_set_timing函数中的panelSetMode为crtSetMode。

static void smi_set_timing(struct smifb_info *sfb,struct par_info *hw)

{

//panelSetMode(hw->width, hw->height, 0, hw->hz, sfb->fb.var.bits_per_pixel);

crtSetMode(hw->width, hw->height, 0, hw->hz, sfb->fb.var.bits_per_pixel);

// Turn on CRT DAC. for simultanous display

regWrite32(MISC_CTRL, FIELD_SET(regRead32(MISC_CTRL), MISC_CTRL, DAC_POWER, NABLE));

}

8)

其它改动:主要是添加了module_exit清理函数。

在voyager.c头文件包含下面定义全局指针:

//added by beelike

struct smifb_info *gpinfo=NULL;/*驱动数据结构的全局变量,清理函数引用它来注销和释放资源。*/

在sm501fb_init()中修改:

gpinfo=sfb = smi_alloc_fb_info(pdev, name);

在voyager.c末尾添加:

/*

* beelike add

*/

void sm501fb_exit(void)

{

if(!gpinfo) return;

smi_unmap_smem(gpinfo);

smi_unmap_mmio(gpinfo);

unregister_framebuffer(&(gpinfo->fb));

smi_free_fb_info(gpinfo);

}

module_init(sm501fb_init);

module_exit(sm501fb_exit);

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("SM501 Framebuffer driver .");

/**end add **/

9)其它被证明为没有必要的修改:

添加头文件:

#include

/*beelike add 这里添加对bank1的DRAM控制寄存器设置*/

#define S3C2410_BWSCON_DW1 (3<<4)

void

sm501_hwinit(void)

{

volatile unsigned int * p;

p= S3C2410_BWSCON;

*p = (*p & (~(S3C2410_BWSCON_ST1| S3C2410_BWSCON_WS1|S3C2410_BWSCON_DW1)));

*p = (*p)|(S3C2410_BWSCON_ST1| S3C2410_BWSCON_WS1 |S3C2410_BWSCON_DW1_32);

p=S3C2410_BANKCON1;

*p= S3C2410_BANKCON_Tacs0|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh1 | S3C2410_BANKCON_Tcah4 | S3C2410_BANKCON_Tacp6 | S3C2410_BANKCON_PMCnorm;

}

/* 虽然被证明没有必要,那因为内核或者u-boot已经对这两个寄存器做过正确设置,如果移植失败,则的确应该考虑内存控制器的设置问题 end add */

整体来说,移植SM501驱动还是比较顺利的。系统启动后在屏幕左上角安静显示了小企鹅。

三、驱动测试:(Framebuffer 编程)

所有的fb驱动拥有同一个FB_MAJOR(29)。SM501显卡驱动在我的板上占用的minor=0。先生成节点:

mknod /dev/fb0 c 29 0

然后使用程序fbtest.c测试,源码如下:(此源码来自网络,略加修改)

#include

#include

#include

#include

#include

int main()

{

int fbfd = 0;

struct fb_var_screeninfo vinfo;

struct fb_fix_screeninfo finfo;

long int screensize = 0;

int * fbp = 0;

int i;

fbfd = open("/dev/fb0", O_RDWR);

if (!fbfd) {

printf("Error: cannot open framebuffer device./n");

exit(1);

}

if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {

printf("Error reading fixed information./n");

exit(2);

}

if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {

printf("Error reading variable information./n");

exit(3);

}

screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

fbp = (int *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,fbfd, 0);

if ((int)fbp == -1) {

printf("Error: failed to map framebuffer device to memory./n");

exit(4);

}

printf("/dev/fb0:/n xres=%d,yres=%d,bpp=%d/n",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);

for(i=0;i

*(fbp+i) = 255<<8 ;

munmap(fbp, screensize);

close(fbfd);

return 0;

}

交叉编译,下载执行,CRT屏幕显示整屏绿色。测试成功。

在移植过程中主要参考readme.txt和网络上两篇好文章:
http://www.eetop.cn/blog/html/38/12938-11581.html http://blog.csdn.net/listream1/archive/2006/11/06/1369361.aspx
这两篇文章是基于2.4版内核的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: