| |
搞了好几天了,终于把SM501的驱动搞好了。
硬件资料不全,真是麻烦。
看datasheet,打印查看寄存器信息,真不容易,呵呵。
好在搞定了。
从Silicon Motion下载驱动,版本为0.05。里面既有针对2.4的也有对2.6的,我使用2.4.20的内核。
把sm501hw.h,smi2d.c,smi2d.h,voyager.c和voyager.h 放入/drivers/video目录下
在/drivers/video/fbmem.c中开头部分添加SM501部分驱动的函数声明:
extern int sm501fb_init(void);
extern int sm501fb_setup(char*);
在fb_drivers结构体中添加
#ifdef CONFIG_FB_SM501_KERNEL_2_4_X
/*
* Silicon Motion, Inc. SM501 (VOYAGER GX) frame. buffer device.
*/
{ "sm501fb", sm501fb_init, NULL },
#endif
fb_drivers的结构体是这样的:
static struct {
const char *name;
int (*init)(void);
int (*setup)(char*);
}
表示驱动名称,初始化函数,设置函数。
在/drivers/video下的Makefile中添加编译项:
obj-$(CONFIG_FB_SM501_KERNEL_2_4_X) += voyager.o
obj-$(CONFIG_FB_SM501_KERNEL_2_4_X) += smi2d.o
在Config.in设置文件中添加SM501配置选项:
bool ' Silicon Motion, Inc. SM501 graphics console' CONFIG_FB_SM501_KERNEL_2_4_X
单括号内的无所谓,当选择这个选项时,在.config中就CONFIG_FB_SM501_KERNEL_2_4_X=y
则在/drivers/video下的Makefile中就表示:
obj-y += voyager.o
voyager.o就会被编译入内核,如果时obj-m += voyager.o 则就编译为模块。
然后进行配置,进入"Character devices",选择
"Virtual Terminal"
"Support for console on virtual terminal"
这样就可以在开机时在屏幕上看到小企鹅的标志。
进入控制台驱动"Console drivers"
把帧缓存支持选择上去:
"Frame-buffer support"
然后进入"Support for frame. buffer devices (EXPERIMENTAL)"选择以下选项:
"Silicon Motion, Inc. VOYAGER graphics console"
"Virtual Frame. Buffer support"
"Select compiled-in fonts"
"VGA 8x8 font"
"Silicon Motion, Inc. VOYAGER graphics console"是我们刚才添加的。
然后进行正常的编译了,通常:
make depend
make clean
make zImage
虽然编译进去了,但并不能运行,要进行移植,修改配置。
我的板子是arm9的芯片,S3C2440,和SM501的datasheet中列举的几种芯片架构都不同,但是和Xscale架构差不多,一个是ARM9,一个是StrongARM。
回来继续补充......
现在继续补充,呵呵。
还要修改一下东西。
在voyager.h中的宏定义:
#define isPCI 1
#define isPC 0 不是使用PC下的PCI模式,所以要改为
#define isPCI 0 #define isPC 0
定义一下分辨率:
#define SCREEN_X_RES 1024
#define SCREEN_Y_RES 768
#define SCREEN_BPP 16 //色彩深度
定义有关缓存和寄存器地址:
#define isACCELENT 0 /* is Accelent platform. */
/*SM501 nGCS1 0x08000000 hall*/
#define FB_PHYSICAL_ADDR 0x08000000 //RAM //SM501接在BANK1上,所以起始地址为0x08000000
#define REG_PHYSICAL_ADDR 0x0BE00000 //REG /*last 2M is REG*/
#if isACCELENT //这个和上面的定义差不多,不是
#undef isPC
#undef isPCI
#define isPC 0
#define isPCI 0
#endif
这个文件里就改这些。
在voyager.c中:
int __init sm501fb_init(void) 用于SM501的初始化,这段很重要,在这里要设置SM501的寄存器,工作模式等。
设置缓存大小
u_long smem_size= 0x00800000; //default 8MB
在static void smi_set_timing(struct smifb_info *sfb,struct par_info *hw)加个设置SM501外界晶振大小的语句:
regWrite32(MISC_CTRL, 0x01000002);
原来驱动默认的是24M,但我们用的晶振是12M,所以在这里加一个设置。
同时把:panelSetMode(hw->width, hw->height, 0, hw->hz, sfb->fb.var.bits_per_pixel);
改为了:
//chang by hall
crtSetMode(hw->width, hw->height, 0, hw->hz, sfb->fb.var.bits_per_pixel);
一个是液晶设置模式,一个VGA设置模式,不过不改也可以工作。
void programMode(reg_table_t *register_table)这个是比较关键的函数,如果SM501工作不正常,则仔细对照这里参数设置。
这里的设置寄存器的函数都是直接对地址写值,而没有使用ioremap。
在smifb_decode_var
hw->hz的值是VGA的刷新频率吧。我改为85了。
如果工作不正常的话,先看看能不能读到SM501的ID,在sm501fb_init中加调试信息吧,如果你有仿真器的话,更好了,读寄存器地址的第0x60位。我的在Bank1上,最后2M为寄存器地址,所以应该为0xbe000000+0x60.
volatile unsigned char * bwscon;
bwscon = ioremap_nocache(0xbe00000, 0x200000);
printk("ChipID=%x\n\n",readl(bwscon+0x60));
iounmap(bwscon);
这段代码最好在寄存器设置完毕后运行,就是在sm501fb_init( )末尾加。如果读不到芯片ID,就看看那几个决定状态的GPIO接好了没有。
几个GPIO口的状态决定了它的一些工作模式。这个要好好对照一下。
驱动正常了,接上显示器,系统启动后,就会看到那可爱的小企鹅。并且/dev下有 fb/0。cat /dev/zero > /dev/fb/0 和cat /dev/null > /dev/fb/0就看到屏幕黑白变化了。
下面就是针对FB编程了。