- 论坛徽章:
- 0
|
1.硬件平台:AT91SAM9263,操作系统:Linux2.6.27,TFT LCD 480*272(触摸屏)
2.问题描述:由于项目的特点,需要编写一个驱动程序,根据应用层传下来的数据,进行描点动作,(就是根据数据,在LCD上显示对应的像素)。
为了实现这个功能,我的做法是,编写一个字符设备驱动,在模块初始化时,获取内核映射好的分配给LCD的内存空间(framebuffer的内存空间)。然后根据应用层传下来的数据进行描点,描点的方法就是往这段内存空间添数据。。
现在遇到很困惑的问题是:这个驱动程序都很正确描点,但是在一个屏幕上的图形只要多一些,就会明显感觉到一个屏幕的显示会很慢,会明显感觉到CPU在画线。。
但是,在uboot下,显示一个彩色图片,都感觉比较快。。。
这是为什么啊???有做过这方面工作的大侠指点一下。。有什么方法可以使得刷屏的速度快一些??
部分代码如下:
static struct file_operations Fops_lcd =
{
.owner = THIS_MODULE,
.open = lcd_device_open,
.release= lcd_device_release,
.read = lcd_device_read,
.write = lcd_device_write,
.ioctl = NULL,
};
static struct fb_fix_screeninfo fix;
static struct fb_var_screeninfo var;
static int bytes_per_pixel;
static struct fb_info *atmel_fb=NULL; /*所要操作的LCD控制器对应的FB设备结构体*/
static unsigned char *line_addr;
static void lcdport_write(unsigned int addr, char data)
{
unsigned int x,y;
int kk,bits;
bits = data;
#if LINE_SCAN_MODE == 1
for(kk=0;kk<8;kk++,bits <<=1)
{
if(bits & 0x80)
pixel(x+kk,y,COLOR_INDEX);
}
#elif LINE_SCAN_MODE == 2
for(kk=0;kk<8;kk++,bits <<=1)
{
if(bits & 0x80)
pixel(x+8-kk,y,COLOR_INDEX);
}
#elif LINE_SCAN_MODE == 3
for(kk=0;kk<8;kk++,bits <<=1)
{
if(bits & 0x80)
pixel(x,y+kk,COLOR_INDEX);
}
#elif LINE_SCAN_MODE == 4
for(kk=0;kk<8;kk++,bits <<=1)
{
if(bits & 0x80)
pixel(x,y+8-kk,COLOR_INDEX);
}
#endif
}
static inline void __setpixel (union multiptr loc, unsigned xormode, unsigned color)
{
switch(bytes_per_pixel) {
case 1:
default:
if (xormode) //transparent
*loc.p8 ^= color;
else
*loc.p8 = color;
break;
case 2:
if (xormode)
*loc.p16 ^= color;
else
*loc.p16 = color;
break;
case 3:
if (xormode)
*loc.p32 ^= color;
else
*loc.p32 = color;
break;
case 4:
if (xormode)
*loc.p32 ^= color;
else
*loc.p32 = color;
break;
}
}
static void pixel (int x, int y, unsigned colidx)
{
unsigned xormode;
union multiptr loc;
if ((x < 0) || ((__u32)x >= var.xres_virtual) ||
(y < 0) || ((__u32)y >= var.yres_virtual))
return;
xormode = colidx & XORMODE;
colidx &= ~XORMODE;
loc.p8 = line_addr + y*fix.line_length + x * bytes_per_pixel;
//__setpixel (loc, xormode, colormap [colidx]);
__setpixel (loc, xormode, 255);
}
static int __init lcd_device_init (void)
{
int ret;
int i;
char *fbp;
/* Register the character device */
if ((ret = register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &Fops_lcd)) < 0)
{
printk ("LCD Device failed with %d\n", ret);
return (ret);
}
/*PRINT_TRACE(Debug)("%s the major is %d.\n",lcd_device_driver_ver,DEVICE_MAJOR);*/
for(i = 0;i < num_registered_fb; i++)
{
/*printk("*******%s******\n",registered_fb->monspecs.manufacturer);*/
if(memcmp(registered_fb->monspecs.manufacturer,"HIT",4)==0)
{
atmel_fb = registered_fb;
break;
}
}
if(atmel_fb==NULL)
goto no_lcd;
fix = atmel_fb->fix;
var = atmel_fb->var;
bytes_per_pixel = var.bits_per_pixel / 8;
line_addr = atmel_fb->screen_base;
printk("LCD Paramres=%d,yres=%d,bytes_per_pixel=%d\n",var.xres,var.yres,bytes_per_pixel);
printk("******screen_base:0x%X\n",atmel_fb->screen_base);
printk("******screen_size:0x%X\n",atmel_fb->screen_size);
printk("******smem_start:0x%X\n",fix.smem_start);
printk("******smem_len:0x%X\n",fix.smem_len);
/*printk("*******%s******\n",atmel_fb->monspecs.manufacturer);*/
printk("LCD driver:Find specified LCD device!\n"
return 0;
no_lcd:
printk("LCD driver:Not find specified LCD device!\n"
return (0);
}
module_init (lcd_device_init);
|
|
|