这里最好牵涉到几个文件S3cfb.c、S3cfb_fimd6x.c setuo-fb.c fb_mem.c
在这里之前最好知道pci,和memio一些术语的意思
S3cfb.c中的s3cfb_probe设备探测,是驱动注册的主要函数
- /*定义一个结构体用来维护驱动程序中各函数中用到的变量
- 先别看结构体要定义这些成员,到各函数使用的地方就明白了*/
- static int __devinit s3cfb_probe(struct platform_device *pdev)
- {
- struct s3c_platform_fb *pdata;/*LCD屏配置信息结构体*/
- struct s3cfb_global *fbdev;/*驱动程序全局变量结构体*/
- struct resource *res; /*用来保存从LCD平台设备中获取的LCD资源*/
- int i, j, ret = 0;
- printk("%s\n",__func__);
- fbdev = kzalloc(sizeof(struct s3cfb_global), GFP_KERNEL);
- if (!fbdev) {
- dev_err(&pdev->dev, "failed to allocate for "
- "global fb structure\n");
- ret = -ENOMEM;
- goto err_global;
- }
- fbdev->dev = &pdev->dev;
- fbdev->regulator = regulator_get(&pdev->dev, "pd");
- if (!fbdev->regulator) {
- dev_err(fbdev->dev, "failed to get regulator\n");
- ret = -EINVAL;
- goto err_regulator;
- }
- ret = regulator_enable(fbdev->regulator);
- if (ret < 0) {
- dev_err(fbdev->dev, "failed to enable regulator\n");
- ret = -EINVAL;
- goto err_regulator;
- }
- /*获取LCD参数信息*/
- pdata = to_fb_plat(&pdev->dev);
- if (!pdata) {
- dev_err(fbdev->dev, "failed to get platform data\n");
- ret = -EINVAL;
- goto err_pdata;
- }
- fbdev->lcd = (struct s3cfb_lcd *)pdata->lcd;
- /*配置GPIO端口*/
- if (pdata->cfg_gpio)
- pdata->cfg_gpio(pdev);
- /*设置时钟参数*/
- if (pdata->clk_on)
- pdata->clk_on(pdev, &fbdev->clock);
- /*获取LCD平台设备所使用的IO端口资源,注意这个IORESOURCE_MEM标志和LCD平台设备定义中的一致*/
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(fbdev->dev, "failed to get io memory region\n");
- ret = -EINVAL;
- goto err_io;
- }
- /*申请LCD IO端口所占用的IO空间(注意理解IO空间和内存空间的区别),request_mem_region定义在ioport.h中*/
- res = request_mem_region(res->start,
- res->end - res->start + 1, pdev->name);
- if (!res) {
- dev_err(fbdev->dev, "failed to request io memory region\n");
- ret = -EINVAL;
- goto err_io;
- }
- /*将LCD的IO端口占用的这段IO空间映射到内存的虚拟地址,ioremap定义在io.h中
- 注意:IO空间要映射后才能使用,以后对虚拟地址的操作就是对IO空间的操作*/
- fbdev->regs = ioremap(res->start, res->end - res->start + 1);
- if (!fbdev->regs) {
- dev_err(fbdev->dev, "failed to remap io region\n");
- ret = -EINVAL;
- goto err_mem;
- }
- #ifdef CONFIG_FB_S3C_LTE480WV
- /*设置寄存器初始状态*/
- s3cfb_pre_init_para(fbdev);
- #endif
- /*设置gamma 值*/
- s3cfb_set_gamma(fbdev);
- /*设置VSYNC中断*/
- s3cfb_set_vsync_interrupt(fbdev, 1);
- /*设置全局中断*/
- s3cfb_set_global_interrupt(fbdev, 1);
- /*fb设备参数信息初始化*/
- s3cfb_init_global(fbdev);
- /*为framebuffer分配空间,进行内存映射,填充fb_info*/
- if (s3cfb_alloc_framebuffer(fbdev)) {
- ret = -ENOMEM;
- goto err_alloc;
- }
- /*注册fb设备到系统中*/
- if (s3cfb_register_framebuffer(fbdev)) {
- ret = -EINVAL;
- goto err_register;
- }
- s3cfb_set_clock(fbdev);
- s3cfb_set_window(fbdev, pdata->default_win, 1);
- s3cfb_display_on(fbdev);
- fbdev->irq = platform_get_irq(pdev, 0);
- if (request_irq(fbdev->irq, s3cfb_irq_frame, IRQF_SHARED,
- pdev->name, fbdev)) {
- dev_err(fbdev->dev, "request_irq failed\n");
- ret = -EINVAL;
- goto err_irq;
- }
- #ifdef CONFIG_FB_S3C_LCD_INIT
- if (pdata->backlight_on)
- pdata->backlight_on(pdev);
- if (!bootloaderfb && pdata->reset_lcd)
- pdata->reset_lcd(pdev);
- if (pdata->lcd_on)
- pdata->lcd_on(pdev);
- #endif
- #ifdef CONFIG_HAS_EARLYSUSPEND
- fbdev->early_suspend.suspend = s3cfb_early_suspend;
- fbdev->early_suspend.resume = s3cfb_late_resume;
- fbdev->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
- register_early_suspend(&fbdev->early_suspend);
- #endif
- /*对设备文件系统的支持,创建fb设备文件*/
- ret = device_create_file(&(pdev->dev), &dev_attr_win_power);
- if (ret < 0)
- dev_err(fbdev->dev, "failed to add sysfs entries\n");
- dev_info(fbdev->dev, "registered successfully\n");
- /*显示开机logo*/
- #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
- if (fb_prepare_logo( fbdev->fb[pdata->default_win], FB_ROTATE_UR)) {
- printk("Start display and show logo\n");
- /* Start display and show logo on boot */
- fb_set_cmap(&fbdev->fb[pdata->default_win]->cmap, fbdev->fb[pdata->default_win]);
- fb_show_logo(fbdev->fb[pdata->default_win], FB_ROTATE_UR);
- }
- #endif
- return 0;
- }
阅读(445) | 评论(0) | 转发(0) |