(http://hi.baidu.com/zengzhaonong/blog/item/00dc0f385a0785f4b211c7af.html)
Linux-2.6.22
module_init() -->
s3c2410fb_init() -->
platform_driver_register() -->
s3c2410fb_probe()
(10) 为该设备创建一个在sysfs中的属性
static int __init s3c2410fb_probe(struct
platform_device *pdev)
{
struct
s3c2410fb_info *info;
struct
fb_info *fbinfo;
struct s3c2410fb_hw *mregs; //s3c2410fb_hw为描述LCD的硬件控制寄存器内容的结构体
int ret;
int irq;
int i;
u32 lcdcon1;
mach_info = pdev->dev.platform_data;
if (mach_info == NULL) {
dev_err(&pdev->dev,"no platform data for lcd, cannot attach\n");
return -EINVAL;
}
mregs = &mach_info->regs;
irq =
platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq for device\n");
return -ENOENT;
}
fbinfo =
framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);
if (!fbinfo) {
return -ENOMEM;
}
info = fbinfo->par;
info->fb = fbinfo;
info->dev = &pdev->dev;
platform_set_drvdata(pdev, fbinfo);
dprintk("devinit\n");
strcpy(fbinfo->fix.id, driver_name);
memcpy(&info->regs, &mach_info->regs, sizeof(info->regs));
/* Stop the video and unset ENVID if set */
info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
lcdcon1 = readl(S3C2410_LCDCON1);
writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
info->mach_info = pdev->dev.platform_data;
fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
fbinfo->fix.type_aux = 0;
fbinfo->fix.xpanstep = 0;
fbinfo->fix.ypanstep = 0;
fbinfo->fix.ywrapstep = 0;
fbinfo->fix.accel = FB_ACCEL_NONE;
fbinfo->var.nonstd = 0;
fbinfo->var.activate = FB_ACTIVATE_NOW;
fbinfo->var.height = mach_info->height;
fbinfo->var.width = mach_info->width;
fbinfo->var.accel_flags = 0;
fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
fbinfo->fbops = &s3c2410fb_ops;
fbinfo->flags = FBINFO_FLAG_DEFAULT;
fbinfo->pseudo_palette = &info->pseudo_pal;
fbinfo->var.xres = mach_info->xres.defval;
fbinfo->var.xres_virtual = mach_info->xres.defval;
fbinfo->var.yres = mach_info->yres.defval;
fbinfo->var.yres_virtual = mach_info->yres.defval;
fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
fbinfo->var.upper_margin = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) + 1;
fbinfo->var.lower_margin = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) + 1;
fbinfo->var.vsync_len = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;
fbinfo->var.left_margin = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
fbinfo->var.right_margin = S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;
fbinfo->var.hsync_len = S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;
fbinfo->var.red.offset = 11;
fbinfo->var.green.offset = 5;
fbinfo->var.blue.offset = 0;
fbinfo->var.transp.offset = 0;
fbinfo->var.red.length = 5;
fbinfo->var.green.length = 6;
fbinfo->var.blue.length = 5;
fbinfo->var.transp.length = 0;
fbinfo->fix.smem_len = mach_info->xres.max *
mach_info->yres.max *
mach_info->bpp.max / 8;
for (i = 0; i < 256; i++) //初始化调色板缓冲区
info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
if (!
request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd")) {
ret = -EBUSY;
goto dealloc_fb;
}
dprintk("got LCD region\n");
ret =
request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info);
if (ret) {
dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
ret = -EBUSY;
goto release_mem;
}
info->clk =
clk_get(NULL, "lcd");
if (!info->clk || IS_ERR(info->clk)) {
printk(KERN_ERR "failed to get lcd clock source\n");
ret = -ENOENT;
goto release_irq;
}
clk_enable(info->clk);
dprintk("got and enabled clock\n");
msleep(1);
/* Initialize video memory */
ret =
s3c2410fb_map_video_memory(info);
if (ret) {
printk( KERN_ERR "Failed to allocate video RAM: %d\n", ret);
ret = -ENOMEM;
goto release_clock;
}
dprintk("got video memory\n");
ret =
s3c2410fb_init_registers(info);
ret = s3c2410fb_check_var(&fbinfo->var, fbinfo);
ret = register_framebuffer(fbinfo);
if (ret < 0) {
printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);
goto free_video_memory;
}
/* create device files */
device_create_file(&pdev->dev, &dev_attr_debug);
printk(KERN_INFO "fb%d: %s frame buffer device\n",
fbinfo->node, fbinfo->fix.id);
return 0;
free_video_memory:
s3c2410fb_unmap_video_memory(info);
release_clock:
clk_disable(info->clk);
clk_put(info->clk);
release_irq:
free_irq(irq,info);
release_mem:
release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
dealloc_fb:
framebuffer_release(fbinfo);
return ret;
}