📄 pvr2fb.c
字号:
* in for flexibility anyways. Who knows, maybe someone has tv-out on a * PCI-based version of these things ;-) */static int __devinit pvr2fb_common_init(void){ struct pvr2fb_par *par = currentpar; unsigned long modememused, rev; fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start, pvr2_fix.smem_len); if (!fb_info->screen_base) { printk(KERN_ERR "pvr2fb: Failed to remap smem space\n"); goto out_err; } par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start, pvr2_fix.mmio_len); if (!par->mmio_base) { printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n"); goto out_err; } fb_memset(fb_info->screen_base, 0, pvr2_fix.smem_len); pvr2_fix.ypanstep = nopan ? 0 : 1; pvr2_fix.ywrapstep = nowrap ? 0 : 1; fb_info->fbops = &pvr2fb_ops; fb_info->fix = pvr2_fix; fb_info->par = currentpar; fb_info->pseudo_palette = currentpar->palette; fb_info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; if (video_output == VO_VGA) defmode = DEFMODE_VGA; if (!mode_option) mode_option = "640x480@60"; if (!fb_find_mode(&fb_info->var, fb_info, mode_option, pvr2_modedb, NUM_TOTAL_MODES, &pvr2_modedb[defmode], 16)) fb_info->var = pvr2_var; fb_alloc_cmap(&fb_info->cmap, 256, 0); if (register_framebuffer(fb_info) < 0) goto out_err; /*Must write PIXDEPTH to register before anything is displayed - so force init */ pvr2_init_display(fb_info); modememused = get_line_length(fb_info->var.xres_virtual, fb_info->var.bits_per_pixel); modememused *= fb_info->var.yres_virtual; rev = fb_readl(par->mmio_base + 0x04); printk("fb%d: %s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n", fb_info->node, fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f, modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10)); printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", fb_info->node, fb_info->var.xres, fb_info->var.yres, fb_info->var.bits_per_pixel, get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), (char *)pvr2_get_param(cables, NULL, cable_type, 3), (char *)pvr2_get_param(outputs, NULL, video_output, 3));#ifdef CONFIG_SH_STORE_QUEUES printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node); pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len, fb_info->fix.id, pgprot_val(PAGE_SHARED)); printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n", fb_info->node, pvr2fb_map);#endif return 0;out_err: if (fb_info->screen_base) iounmap(fb_info->screen_base); if (par->mmio_base) iounmap((void *)par->mmio_base); return -ENXIO;}#ifdef CONFIG_SH_DREAMCASTstatic int __init pvr2fb_dc_init(void){ if (!mach_is_dreamcast()) return -ENXIO; /* Make a guess at the monitor based on the attached cable */ if (pvr2_init_cable() == CT_VGA) { fb_info->monspecs.hfmin = 30000; fb_info->monspecs.hfmax = 70000; fb_info->monspecs.vfmin = 60; fb_info->monspecs.vfmax = 60; } else { /* Not VGA, using a TV (taken from acornfb) */ fb_info->monspecs.hfmin = 15469; fb_info->monspecs.hfmax = 15781; fb_info->monspecs.vfmin = 49; fb_info->monspecs.vfmax = 51; } /* * XXX: This needs to pull default video output via BIOS or other means */ if (video_output < 0) { if (cable_type == CT_VGA) { video_output = VO_VGA; } else { video_output = VO_NTSC; } } /* * Nothing exciting about the DC PVR2 .. only a measly 8MiB. */ pvr2_fix.smem_start = 0xa5000000; /* RAM starts here */ pvr2_fix.smem_len = 8 << 20; pvr2_fix.mmio_start = 0xa05f8000; /* registers start here */ pvr2_fix.mmio_len = 0x2000; if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, IRQF_SHARED, "pvr2 VBL handler", fb_info)) { return -EBUSY; }#ifdef CONFIG_SH_DMA if (request_dma(pvr2dma, "pvr2") != 0) { free_irq(HW_EVENT_VSYNC, 0); return -EBUSY; }#endif return pvr2fb_common_init();}static void __exit pvr2fb_dc_exit(void){ if (fb_info->screen_base) { iounmap(fb_info->screen_base); fb_info->screen_base = NULL; } if (currentpar->mmio_base) { iounmap((void *)currentpar->mmio_base); currentpar->mmio_base = 0; } free_irq(HW_EVENT_VSYNC, 0);#ifdef CONFIG_SH_DMA free_dma(pvr2dma);#endif}#endif /* CONFIG_SH_DREAMCAST */#ifdef CONFIG_PCIstatic int __devinit pvr2fb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ int ret; ret = pci_enable_device(pdev); if (ret) { printk(KERN_ERR "pvr2fb: PCI enable failed\n"); return ret; } ret = pci_request_regions(pdev, "pvr2fb"); if (ret) { printk(KERN_ERR "pvr2fb: PCI request regions failed\n"); return ret; } /* * Slightly more exciting than the DC PVR2 .. 16MiB! */ pvr2_fix.smem_start = pci_resource_start(pdev, 0); pvr2_fix.smem_len = pci_resource_len(pdev, 0); pvr2_fix.mmio_start = pci_resource_start(pdev, 1); pvr2_fix.mmio_len = pci_resource_len(pdev, 1); fb_info->device = &pdev->dev; return pvr2fb_common_init();}static void __devexit pvr2fb_pci_remove(struct pci_dev *pdev){ if (fb_info->screen_base) { iounmap(fb_info->screen_base); fb_info->screen_base = NULL; } if (currentpar->mmio_base) { iounmap((void *)currentpar->mmio_base); currentpar->mmio_base = 0; } pci_release_regions(pdev);}static struct pci_device_id pvr2fb_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NEON250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, },};MODULE_DEVICE_TABLE(pci, pvr2fb_pci_tbl);static struct pci_driver pvr2fb_pci_driver = { .name = "pvr2fb", .id_table = pvr2fb_pci_tbl, .probe = pvr2fb_pci_probe, .remove = __devexit_p(pvr2fb_pci_remove),};static int __init pvr2fb_pci_init(void){ return pci_register_driver(&pvr2fb_pci_driver);}static void __exit pvr2fb_pci_exit(void){ pci_unregister_driver(&pvr2fb_pci_driver);}#endif /* CONFIG_PCI */static int __devinit pvr2_get_param(const struct pvr2_params *p, const char *s, int val, int size){ int i; for (i = 0 ; i < size ; i++ ) { if (s != NULL) { if (!strnicmp(p[i].name, s, strlen(s))) return p[i].val; } else { if (p[i].val == val) return (int)p[i].name; } } return -1;}/* * Parse command arguments. Supported arguments are: * inverse Use inverse color maps * cable:composite|rgb|vga Override the video cable type * output:NTSC|PAL|VGA Override the video output format * * <xres>x<yres>[-<bpp>][@<refresh>] or, * <name>[-<bpp>][@<refresh>] Startup using this video mode */#ifndef MODULEstatic int __init pvr2fb_setup(char *options){ char *this_opt; char cable_arg[80]; char output_arg[80]; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ","))) { if (!*this_opt) continue; if (!strcmp(this_opt, "inverse")) { fb_invert_cmaps(); } else if (!strncmp(this_opt, "cable:", 6)) { strcpy(cable_arg, this_opt + 6); } else if (!strncmp(this_opt, "output:", 7)) { strcpy(output_arg, this_opt + 7); } else if (!strncmp(this_opt, "nopan", 5)) { nopan = 1; } else if (!strncmp(this_opt, "nowrap", 6)) { nowrap = 1; } else { mode_option = this_opt; } } if (*cable_arg) cable_type = pvr2_get_param(cables, cable_arg, 0, 3); if (*output_arg) video_output = pvr2_get_param(outputs, output_arg, 0, 3); return 0;}#endifstatic struct pvr2_board { int (*init)(void); void (*exit)(void); char name[16];} board_driver[] = {#ifdef CONFIG_SH_DREAMCAST { pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" },#endif#ifdef CONFIG_PCI { pvr2fb_pci_init, pvr2fb_pci_exit, "PCI PVR2" },#endif { 0, },};static int __init pvr2fb_init(void){ int i, ret = -ENODEV; int size;#ifndef MODULE char *option = NULL; if (fb_get_options("pvr2fb", &option)) return -ENODEV; pvr2fb_setup(option);#endif size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32); fb_info = framebuffer_alloc(sizeof(struct pvr2fb_par), NULL); if (!fb_info) { printk(KERN_ERR "Failed to allocate memory for fb_info\n"); return -ENOMEM; } currentpar = fb_info->par; for (i = 0; i < ARRAY_SIZE(board_driver); i++) { struct pvr2_board *pvr_board = board_driver + i; if (!pvr_board->init) continue; ret = pvr_board->init(); if (ret != 0) { printk(KERN_ERR "pvr2fb: Failed init of %s device\n", pvr_board->name); framebuffer_release(fb_info); break; } } return ret;}static void __exit pvr2fb_exit(void){ int i; for (i = 0; i < ARRAY_SIZE(board_driver); i++) { struct pvr2_board *pvr_board = board_driver + i; if (pvr_board->exit) pvr_board->exit(); }#ifdef CONFIG_SH_STORE_QUEUES sq_unmap(pvr2fb_map);#endif unregister_framebuffer(fb_info); framebuffer_release(fb_info);}module_init(pvr2fb_init);module_exit(pvr2fb_exit);MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -