📄 em8xxx_fb.c
字号:
} /* * Pan or Wrap the Display * * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */static int em8xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ printk("mambolfb in pandisplay\n"); if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual || var->xoffset) return -EINVAL; } else { if (var->xoffset + var->xres > info->var.xres_virtual || var->yoffset + var->yres > info->var.yres_virtual) return -EINVAL; } info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) info->var.vmode |= FB_VMODE_YWRAP; else info->var.vmode &= ~FB_VMODE_YWRAP; return 0;} /* * Most drivers don't need their own mmap function *//* Some RedHat systems have CONFIG_HIGHPTE, so pte_offset is renamed */#ifndef pte_offset#define pte_offset pte_offset_kernel#endif/* This is used to get the physical address or cookie associated to an iomapped area * See http://www.xml.com/ldd/chapter/book/ch13.html */#if EM86XX_CHIP==EM86XX_CHIPID_TANGO2 && EM86XX_MODE==EM86XX_MODEID_STANDALONE#define io_virt_to_phys(v) kc_virt_to_phys(v)#else#define io_virt_to_phys(v) (pte_val(*(pte_t *)pte_offset(pmd_offset(pgd_offset_k((v)), (v)), (v))) & PAGE_MASK) + ((v) & ~PAGE_MASK)#endifstatic int em8xxxfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma){ // printk("mambolfb in mmap\n");#ifndef __arm__ unsigned long phys = io_virt_to_phys(videomemory); printk("mambolfb_mmap: OSD videomemory asked:0x%08lx\n",videomemory);#if (RMPLATFORM==RMPLATFORMID_AOE6_SH4) /* * This code is highly SH processor dependent. * * Suggested by ronen.bidany@flextronicssemi.com * */ if (kc_remap_page_range((struct kc_vm_area_struct *) vma, vma->vm_start, videomemory, vma->vm_end-vma->vm_start, (struct kc_pgprot_t *) &vma->vm_page_prot)) return -EAGAIN;#else /* default platforms */ /* This should really be kc_io_remap_range, but as long as we don't * port on alpha or sparc, it's enough */ if (kc_remap_page_range((struct kc_vm_area_struct *) vma, vma->vm_start, phys, vma->vm_end-vma->vm_start, (struct kc_pgprot_t *) &vma->vm_page_prot)) return -EAGAIN;#endif printk("mambolfb_mmap remapped %ld bytes in userland of process %d at address vma_start0x%08lx to phys=0x%08lx\n", vma->vm_end-vma->vm_start,current->pid,vma->vm_start, phys); #else /* __arm__ */#if (RMPLATFORM==RMPLATFORMID_IXDP425) /* In the IXP425 architecture, the 'videomemory' is located on PCI MEM * and not mapped to virtual address, so treat 'videomemory' as physical memory. */ if (kc_remap_page_range((struct kc_vm_area_struct *) vma, vma->vm_start, videomemory, vma->vm_end-vma->vm_start, (struct kc_pgprot_t *) &vma->vm_page_prot)) return -EAGAIN; printk("mambolfb_mmap remapped %ld bytes in userland of process %d at address vma_start0x%08lx to phys=0x%08lx\n", vma->vm_end-vma->vm_start,current->pid,vma->vm_start, videomemory);#endif #endif /* __arm__ */ return 0;}static int em8xxxfb_blank(int blank, struct fb_info *info) { printk("mambolfb in blank\n"); return 0;} /* * Initialisation */static void em8xxxfb_platform_release(struct device *device){ // This is called when the reference count goes to zero.}static int __init em8xxxfb_probe(struct platform_device *device){ struct fb_info *info; int retval = -ENOMEM; info = framebuffer_alloc(sizeof(u32) * 256, &device->dev); if (!info) return -1; info->screen_base = (char __iomem *)videomemory; info->fbops = &em8xxxfb_ops; info->var = em8xxxfb_default; info->fix = em8xxxfb_fix; //--- set some other necessary parameters... info->fix.smem_start = videomemory; info->fix.smem_len = videomemorysize; info->fix.line_length = get_line_length( info->var.xres_virtual, info->var.bits_per_pixel ); info->pseudo_palette = info->par; info->par = NULL; info->flags = FBINFO_FLAG_DEFAULT; retval = fb_alloc_cmap(&info->cmap, 256, 0); if (retval < 0) goto err1; retval = register_framebuffer(info); if (retval < 0) goto err2; platform_set_drvdata(device, info); printk(KERN_INFO "fb%d: em8xxxfb frame buffer device, using %ldK of video memory\n", info->node, videomemorysize >> 10); return 0;err2: fb_dealloc_cmap(&info->cmap);err1: framebuffer_release(info); return retval;}static int em8xxxfb_remove(struct platform_device *device){ struct fb_info *info = platform_get_drvdata(device); if (info) { unregister_framebuffer(info); framebuffer_release(info); } return 0;}static struct platform_driver em8xxxfb_driver = { .probe = em8xxxfb_probe, .remove = em8xxxfb_remove, .driver = { .name = "em8xxxfb", },};static struct platform_device em8xxxfb_device = { .name = "em8xxxfb", .id = 0, .dev = { .release = em8xxxfb_platform_release, }};static int __init parse(char *video_mode){ char *token; token = strsep(&video_mode, ":"); if (!token || !video_mode) return 0; em8xxxfb_default.xres = simple_strtoul(token,&token,0); em8xxxfb_default.xres_virtual = em8xxxfb_default.xres; token = strsep(&video_mode, ":"); if (!token || !video_mode) return 0; em8xxxfb_default.yres = simple_strtoul(token,&token,0); em8xxxfb_default.yres_virtual = em8xxxfb_default.yres; em8xxxfb_default.bits_per_pixel = simple_strtoul(video_mode,&video_mode,0); return 1;}static int __init em8xxxfb_init(void){ int ret = 0; RMstatus status; printk(KERN_INFO "Opening em8xxxfb on 0x%08lX (%lu bytes).\n", videomemory, videomemorysize); if (!videomemory || !videomemorysize || !palette) return -EINVAL; if (mode){ if (parse(mode) == 0){ return -EINVAL; } } /* to do: multiple instances */ p_llad = llad_open("0"); if (p_llad == NULL){ printk(KERN_ERR "em8xxxfb: error, cannot open llad 0\n"); return -EINVAL; } p_gbus = gbus_open(p_llad); if (p_gbus == NULL){ llad_close(p_llad); printk(KERN_ERR "em8xxxfb: error, cannot open gbus 0\n"); return -EINVAL; } /* lock the regions we need */ status = gbus_lock_area(p_gbus, &osd.region_index, videomemory, videomemorysize, &osd.region_count, &osd.offset); if (RMFAILED(status)){ printk(KERN_ERR "em8xxxfb: error locking PCI chunks\n"); return -EINVAL; } printk(KERN_INFO "em8xxxfb: locked %ld regions, starting from region %ld at offset 0x%08lx\n", osd.region_count, osd.region_index, osd.offset); /* Update video address to the mapped OSD buffer */ videomemory = (u_long) gbus_map_region(p_gbus, osd.region_index, osd.region_count); if (videomemory == (u_long) NULL){ printk(KERN_ERR "em8xxxfb: error mapping OSD buffer in kernel space\n"); status = gbus_unlock_region(p_gbus, osd.region_index); if (RMFAILED(status)) printk(KERN_ERR "em8xxxfb: error unlocking regions\n"); return -EINVAL; } videomemory += osd.offset; printk(KERN_INFO "OSD videomemory = 0x%lX (%lu bytes)\n",videomemory,videomemorysize); ret = platform_driver_register(&em8xxxfb_driver); if (!ret) { ret = platform_device_register(&em8xxxfb_device); if (ret) platform_driver_unregister(&em8xxxfb_driver); } return ret;}module_init(em8xxxfb_init);static void __exit em8xxxfb_exit(void){ RMstatus status; int i; for (i = 0; i < osd.region_count; i++) { status = gbus_unlock_region(p_gbus, osd.region_index + i); if (RMFAILED(status)) printk(KERN_ERR "em8xxxfb: error unlocking regions.\n"); } gbus_close(p_gbus); llad_close(p_llad); platform_device_unregister(&em8xxxfb_device); platform_driver_unregister(&em8xxxfb_driver);}module_exit(em8xxxfb_exit);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -