//driver entry function, using the platform framework for matching int __init s3c2410fb_init(void) { int ret = platform_driver_register(&s3c2410fb_driver);//在此处进行匹配,s3c2410fb_driver在下一步 if (ret == 0) ret = platform_driver_register(&s3c2412fb_driver); return ret; } //s3c2410fb_driver The device driver information is matched according to driver.name static struct platform_driver s3c2410fb_driver = { .probe = s3c2410fb_probe, .remove = __devexit_p(s3c2410fb_remove), .suspend = s3c2410fb_suspend, .resume = s3c2410fb_resume, .driver = { .name = "s3c2410-lcd", .owner = THIS_MODULE, }, }; ======================================================================= //When the match succeeds, the s3c2410fb_probe function is called static int __devinit s3c2410fb_probe(struct platform_device *pdev) { return s3c24xxfb_probe(pdev, DRV_S3C2410);//DRV_S3C2410是type类型,为了区分DRV_S3C2412 } //Check concrete s3c24xxfb_probe static int __devinit s3c24xxfb_probe(struct platform_device *pdev, enum s3c_drv_type drv_type) { //The passed parameter pdev = s3c_device_lcd, /* static struct resource s3c_lcd_resource[] = { [0] = DEFINE_RES_MEM(S3C24XX_PA_LCD, S3C24XX_SZ_LCD), [1] = DEFINE_RES_IRQ(IRQ_LCD), }; struct platform_device s3c_device_lcd = { .name = "s3c2410-lcd", .id = -1, .num_resources = ARRAY_SIZE(s3c_lcd_resource), .resource = s3c_lcd_resource, .dev = { .dma_mask = &samsung_device_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), } }; */ struct s3c2410fb_info *info; struct s3c2410fb_display *display; struct fb_info *fbinfo; struct s3c2410fb_mach_info *mach_info; struct resource *res; int ret; int irq; int i; int size; u32 lcdcon1; mach_info = pdev->dev.platform_data;//Here we take out the previous stored thing, that is, smdk2440_fb_info, this variable contains various LCD parameter information //Find which display,default_display = 0,num_displays = 1 display = mach_info->displays + mach_info->default_display; irq = platform_get_irq(pdev, 0);// Register LCD interrupt //equests a frame buffer structure containing the set of properties and operation functions of the frame buffer device fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev); platform_set_drvdata(pdev, fbinfo);//Store fbinfo in pdev.dev.driver_data, which is s3c_device_lcd info = fbinfo->par;//fbinfo->parIt creates a space for framebuffer_alloc() applications info->dev = &pdev->dev; info->drv_type = drv_type;//drv_type = DRV_S3C2410 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//Access to platform resources size = resource_size(res); info->mem = request_mem_region(res->start, size, pdev->name);//Request memory info->io = ioremap(res->start, size);//Memory mapping if (drv_type == DRV_S3C2412) info->irq_base = info->io + S3C2412_LCDINTBASE; else info->irq_base = info->io + S3C2410_LCDINTBASE;//0x4D000000 + 0x54 = 0x4D000054 strcpy(fbinfo->fix.id, driver_name);//driver_name = s3c2410fb /* Stop the video */ lcdcon1 = readl(info->io + S3C2410_LCDCON1);//Read the contents of the lcdcon1 register writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1); //S3C2410_LCDCON1_ENVID = 1,Clear the 0th digit in lcdcon1. This means to turn off the image output and lcd controller signal output 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.accel_flags = 0; fbinfo->var.vmode = FB_VMODE_NONINTERLACED; fbinfo->fbops = &s3c2410fb_ops;//The application layer uses open,read,write and other operation functions fbinfo->flags = FBINFO_FLAG_DEFAULT; fbinfo->pseudo_palette = &info->pseudo_pal; for (i = 0; i < 256; i++) info->palette_buffer[i] = PALETTE_BUFF_CLEAR;//Clear buffer ret = request_irq(irq, s3c2410fb_irq, 0, pdev->name, info);//Request lcd interrupt //Obtain the lcd clock and enable the clock info->clk = clk_get(NULL, "lcd"); clk_enable(info->clk); info->clk_rate = clk_get_rate(info->clk); /* Compute the cache, the size of an image frame */ for (i = 0; i < mach_info->num_displays; i++) { unsigned long smem_len = mach_info->displays[i].xres; smem_len *= mach_info->displays[i].yres; smem_len *= mach_info->displays[i].bpp; smem_len >>= 3;//Length*Width*bpp(16 bits) / 8 if (fbinfo->fix.smem_len < smem_len) fbinfo->fix.smem_len = smem_len; } /* Initialize video memory */ ret = s3c2410fb_map_video_memory(fbinfo); fbinfo->var.xres = display->xres; fbinfo->var.yres = display->yres; fbinfo->var.bits_per_pixel = display->bpp; //Initializes the lcd internal registers, mainly gpio, VD for data transfer [0:23] s3c2410fb_init_registers(fbinfo); //Register a frame buffer entity, which is the fb_info structure ret = register_framebuffer(fbinfo); /* create device files */ ret = device_create_file(&pdev->dev, &dev_attr_debug); if (ret) printk(KERN_ERR "failed to add debug attribute\n"); printk(KERN_INFO "fb%d: %s frame buffer device\n", fbinfo->node, fbinfo->fix.id); return 0; }