微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > S3C2440上LCD驱动(FrameBuffer)实例开发讲解(二)

S3C2440上LCD驱动(FrameBuffer)实例开发讲解(二)

时间:08-15 来源:互联网 点击:

ate = FB_ACTIVATE_NOW;

fbinfo->var.accel_flags = 0;

fbinfo->var.vmode = FB_VMODE_NONINTERLACED;

fbinfo->var.xres = display->xres;

fbinfo->var.yres = display->yres;

fbinfo->var.bits_per_pixel = display->bpp;

/*指定对底层硬件操作的函数指针, 因内容较多故其定义在第③步中再讲*/

fbinfo->fbops = &my2440fb_ops;

fbinfo->flags = FBINFO_FLAG_DEFAULT;

fbinfo->pseudo_palette = &fbvar->pseudo_pal;

fbinfo->flags = FBINFO_FLAG_DEFAULT;

fbinfo->pseudo_palette = &fbvar->pseudo_pal;

/*初始化色调色板(颜色表)为空*/

for(i = 0; i < 256; i++)

{

fbvar->palette_buffer[i] = PALETTE_BUFF_CLEAR;

}

for (i = 0; i < mach_info->num_displays; i++) /*fb缓存的长度*/

{

/*计算FrameBuffer缓存的最大大小,这里右移3位(即除以8)是因为色位模式BPP是以位为单位*/

unsigned long smem_len = (mach_info->displays[i].xres * mach_info->displays[i].yres * mach_info->displays[i].bpp) >> 3;

if(fbinfo->fix.smem_len < smem_len)

{

fbinfo->fix.smem_len = smem_len;

}

}

/*初始化LCD控制器之前要延迟一段时间*/

msleep(1);

/*初始化完fb_info后,开始对LCD各寄存器进行初始化,其定义在后面讲到*/

my2440fb_init_registers(fbinfo);

/*初始化完寄存器后,开始检查fb_info中的可变参数,其定义在后面讲到*/

my2440fb_check_var(fbinfo);

/*申请帧缓冲设备fb_info的显示缓冲区空间,其定义在后面讲到*/

ret = my2440fb_map_video_memory(fbinfo);

if (ret)

{

dev_err(&pdev->dev, "failed to allocate video RAM: %d\n", ret);

ret = -ENOMEM;

goto err_nofb;

}

/*最后,注册这个帧缓冲设备fb_info到系统中, register_framebuffer定义在fb.h中在fbmem.c中实现*/

ret = register_framebuffer(fbinfo);

if (ret < 0)

{

dev_err(&pdev->dev, "failed to register framebuffer device: %d\n", ret);

goto err_video_nomem;

}

/*对设备文件系统的支持(对设备文件系统的理解请参阅:嵌入式Linux之我行——设备文件系统剖析与使用)

创建frambuffer设备文件,device_create_file定义在linux/device.h中*/

ret = device_create_file(&pdev->dev, &dev_attr_debug);

if (ret)

{

dev_err(&pdev->dev, "failed to add debug attribute\n");

}

return 0;

/*以下是上面错误处理的跳转点*/

err_nomem:

release_resource(fbvar->lcd_mem);

kfree(fbvar->lcd_mem);

err_nomap:

iounmap(fbvar->lcd_base);

err_noclk:

clk_disable(fbvar->lcd_clock);

clk_put(fbvar->lcd_clock);

err_noirq:

free_irq(fbvar->lcd_irq_no, fbvar);

err_nofb:

platform_set_drvdata(pdev, NULL);

framebuffer_release(fbinfo);

err_video_nomem:

my2440fb_unmap_video_memory(fbinfo);

return ret;

}

/*LCD中断服务程序*/

static irqreturn_t lcd_fb_irq(int irq, void *dev_id)

{

struct my2440fb_var *fbvar = dev_id;

void __iomem *lcd_irq_base;

unsigned long lcdirq;

/*LCD中断挂起寄存器基地址*/

lcd_irq_base = fbvar->lcd_base + S3C2410_LCDINTBASE;

/*读取LCD中断挂起寄存器的值*/

lcdirq = readl(lcd_irq_base + S3C24XX_LCDINTPND);

/*判断是否为中断挂起状态*/

if(lcdirq & S3C2410_LCDINT_FRSYNC)

{

/*填充调色板*/

if (fbvar->palette_ready)

{

my2440fb_write_palette(fbvar);

}

/*设置帧已插入中断请求*/

writel(S3C2410_LCDINT_FRSYNC, lcd_irq_base + S3C24XX_LCDINTPND);

writel(S3C2410_LCDINT_FRSYNC, lcd_irq_base + S3C24XX_LCDSRCPND);

}

return IRQ_HANDLED;

}

/*填充调色板*/

static void my2440fb_write_palette(struct my2440fb_var *fbvar)

{

unsigned int i;

void __iomem *regs = fbvar->lcd_base;

fbvar->palette_ready = 0;

for (i = 0; i < 256; i++)

{

unsigned long ent = fbvar->palette_buffer[i];

if (ent == PALETTE_BUFF_CLEAR)

{

continue;

}

writel(ent, regs + S3C2410_TFTPAL(i));

if (readw(regs + S3C2410_TFTPAL(i)) == ent)

{

fbvar->palette_buffer[i] = PALETTE_BUFF_CLEAR;

}

else

{

fbvar->palette_ready

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top