📄 stifb.c
字号:
struct fb_var_screeninfo *var = &fb->info.var; if (regno < 16) ((u32 *)fb->info.pseudo_palette)[regno] = regno << var->red.offset | regno << var->green.offset | regno << var->blue.offset; } WRITE_IMAGE_COLOR(fb, regno, color); if (fb->id == S9000_ID_HCRX) { NgleLutBltCtl lutBltCtl; lutBltCtl = setHyperLutBltCtl(fb, 0, /* Offset w/i LUT */ 256); /* Load entire LUT */ NGLE_BINC_SET_SRCADDR(fb, NGLE_LONG_FB_ADDRESS(0, 0x100, 0)); /* 0x100 is same as used in WRITE_IMAGE_COLOR() */ START_COLORMAPLOAD(fb, lutBltCtl.all); SETUP_FB(fb); } else { /* cleanup colormap hardware */ FINISH_IMAGE_COLORMAP_ACCESS(fb); } DEBUG_ON(); return 0;}static intstifb_blank(int blank_mode, struct fb_info *info){ struct stifb_info *fb = (struct stifb_info *) info; int enable = (blank_mode == 0) ? ENABLE : DISABLE; switch (fb->id) { case S9000_ID_A1439A: CRX24_ENABLE_DISABLE_DISPLAY(fb, enable); break; case CRT_ID_VISUALIZE_EG: case S9000_ID_ARTIST: ARTIST_ENABLE_DISABLE_DISPLAY(fb, enable); break; case S9000_ID_HCRX: HYPER_ENABLE_DISABLE_DISPLAY(fb, enable); break; case S9000_ID_A1659A: /* fall through */ case S9000_ID_TIMBER: case CRX24_OVERLAY_PLANES: default: ENABLE_DISABLE_DISPLAY(fb, enable); break; } SETUP_FB(fb); return 0;}static void __initstifb_init_display(struct stifb_info *fb){ int id = fb->id; SETUP_FB(fb); /* HCRX specific initialization */ SETUP_HCRX(fb); /* if (id == S9000_ID_HCRX) hyperInitSprite(fb); else ngleInitSprite(fb); */ /* Initialize the image planes. */ switch (id) { case S9000_ID_HCRX: hyperResetPlanes(fb, ENABLE); break; case S9000_ID_A1439A: rattlerSetupPlanes(fb); break; case S9000_ID_A1659A: case S9000_ID_ARTIST: case CRT_ID_VISUALIZE_EG: elkSetupPlanes(fb); break; } /* Clear attribute planes on non HCRX devices. */ switch (id) { case S9000_ID_A1659A: case S9000_ID_A1439A: if (fb->info.var.bits_per_pixel == 32) ngleSetupAttrPlanes(fb, BUFF1_CMAP3); else { ngleSetupAttrPlanes(fb, BUFF1_CMAP0); } if (id == S9000_ID_A1439A) ngleClearOverlayPlanes(fb, 0xff, 0); break; case S9000_ID_ARTIST: case CRT_ID_VISUALIZE_EG: if (fb->info.var.bits_per_pixel == 32) ngleSetupAttrPlanes(fb, BUFF1_CMAP3); else { ngleSetupAttrPlanes(fb, ARTIST_CMAP0); } break; } stifb_blank(0, (struct fb_info *)fb); /* 0=enable screen */ SETUP_FB(fb);}/* ------------ Interfaces to hardware functions ------------ */static struct fb_ops stifb_ops = { .owner = THIS_MODULE, .fb_setcolreg = stifb_setcolreg, .fb_blank = stifb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit,};/* * Initialization */static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref){ struct fb_fix_screeninfo *fix; struct fb_var_screeninfo *var; struct stifb_info *fb; struct fb_info *info; unsigned long sti_rom_address; char *dev_name; int bpp, xres, yres; fb = kzalloc(sizeof(*fb), GFP_ATOMIC); if (!fb) { printk(KERN_ERR "stifb: Could not allocate stifb structure\n"); return -ENODEV; } info = &fb->info; /* set struct to a known state */ fix = &info->fix; var = &info->var; fb->sti = sti; /* store upper 32bits of the graphics id */ fb->id = fb->sti->graphics_id[0]; /* only supported cards are allowed */ switch (fb->id) { case CRT_ID_VISUALIZE_EG: /* Visualize cards can run either in "double buffer" or "standard" mode. Depending on the mode, the card reports a different device name, e.g. "INTERNAL_EG_DX1024" in double buffer mode and "INTERNAL_EG_X1024" in standard mode. Since this driver only supports standard mode, we check if the device name contains the string "DX" and tell the user how to reconfigure the card. */ if (strstr(sti->outptr.dev_name, "DX")) { printk(KERN_WARNING "WARNING: stifb framebuffer driver does not " "support '%s' in double-buffer mode.\n" KERN_WARNING "WARNING: Please disable the double-buffer mode " "in IPL menu (the PARISC-BIOS).\n", sti->outptr.dev_name); goto out_err0; } /* fall though */ case S9000_ID_ARTIST: case S9000_ID_HCRX: case S9000_ID_TIMBER: case S9000_ID_A1659A: case S9000_ID_A1439A: break; default: printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n", sti->outptr.dev_name, fb->id); goto out_err0; } /* default to 8 bpp on most graphic chips */ bpp = 8; xres = sti_onscreen_x(fb->sti); yres = sti_onscreen_y(fb->sti); ngleGetDeviceRomData(fb); /* get (virtual) io region base addr */ fix->mmio_start = REGION_BASE(fb,2); fix->mmio_len = 0x400000; /* Reject any device not in the NGLE family */ switch (fb->id) { case S9000_ID_A1659A: /* CRX/A1659A */ break; case S9000_ID_ELM: /* GRX, grayscale but else same as A1659A */ var->grayscale = 1; fb->id = S9000_ID_A1659A; break; case S9000_ID_TIMBER: /* HP9000/710 Any (may be a grayscale device) */ dev_name = fb->sti->outptr.dev_name; if (strstr(dev_name, "GRAYSCALE") || strstr(dev_name, "Grayscale") || strstr(dev_name, "grayscale")) var->grayscale = 1; break; case S9000_ID_TOMCAT: /* Dual CRX, behaves else like a CRX */ /* FIXME: TomCat supports two heads: * fb.iobase = REGION_BASE(fb_info,3); * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx); * for now we only support the left one ! */ xres = fb->ngle_rom.x_size_visible; yres = fb->ngle_rom.y_size_visible; fb->id = S9000_ID_A1659A; break; case S9000_ID_A1439A: /* CRX24/A1439A */ bpp = 32; break; case S9000_ID_HCRX: /* Hyperdrive/HCRX */ memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom)); if ((fb->sti->regions_phys[0] & 0xfc000000) == (fb->sti->regions_phys[2] & 0xfc000000)) sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]); else sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]); fb->deviceSpecificConfig = gsc_readl(sti_rom_address); if (IS_24_DEVICE(fb)) { if (bpp_pref == 8 || bpp_pref == 32) bpp = bpp_pref; else bpp = 32; } else bpp = 8; READ_WORD(fb, REG_15); SETUP_HW(fb); break; case CRT_ID_VISUALIZE_EG: case S9000_ID_ARTIST: /* Artist */ break; default: #ifdef FALLBACK_TO_1BPP printk(KERN_WARNING "stifb: Unsupported graphics card (id=0x%08x) " "- now trying 1bpp mode instead\n", fb->id); bpp = 1; /* default to 1 bpp */ break;#else printk(KERN_WARNING "stifb: Unsupported graphics card (id=0x%08x) " "- skipping.\n", fb->id); goto out_err0;#endif } /* get framebuffer physical and virtual base addr & len (64bit ready) */ fix->smem_start = F_EXTEND(fb->sti->regions_phys[1]); fix->smem_len = fb->sti->regions[1].region_desc.length * 4096; fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8; if (!fix->line_length) fix->line_length = 2048; /* default */ /* limit fbsize to max visible screen size */ if (fix->smem_len > yres*fix->line_length) fix->smem_len = yres*fix->line_length; fix->accel = FB_ACCEL_NONE; switch (bpp) { case 1: fix->type = FB_TYPE_PLANES; /* well, sort of */ fix->visual = FB_VISUAL_MONO10; var->red.length = var->green.length = var->blue.length = 1; break; case 8: fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = FB_VISUAL_PSEUDOCOLOR; var->red.length = var->green.length = var->blue.length = 8; break; case 32: fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = FB_VISUAL_DIRECTCOLOR; var->red.length = var->green.length = var->blue.length = var->transp.length = 8; var->blue.offset = 0; var->green.offset = 8; var->red.offset = 16; var->transp.offset = 24; break; default: break; } var->xres = var->xres_virtual = xres; var->yres = var->yres_virtual = yres; var->bits_per_pixel = bpp; strcpy(fix->id, "stifb"); info->fbops = &stifb_ops; info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); info->screen_size = fix->smem_len; info->flags = FBINFO_DEFAULT; info->pseudo_palette = &fb->pseudo_palette; /* This has to been done !!! */ fb_alloc_cmap(&info->cmap, NR_PALETTE, 0); stifb_init_display(fb); if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) { printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n", fix->smem_start, fix->smem_start+fix->smem_len); goto out_err1; } if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) { printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n", fix->mmio_start, fix->mmio_start+fix->mmio_len); goto out_err2; } if (register_framebuffer(&fb->info) < 0) goto out_err3; sti->info = info; /* save for unregister_framebuffer() */ printk(KERN_INFO "fb%d: %s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n", fb->info.node, fix->id, var->xres, var->yres, var->bits_per_pixel, sti->outptr.dev_name, fb->id, fix->mmio_start); return 0;out_err3: release_mem_region(fix->mmio_start, fix->mmio_len);out_err2: release_mem_region(fix->smem_start, fix->smem_len);out_err1: iounmap(info->screen_base); fb_dealloc_cmap(&info->cmap);out_err0: kfree(fb); return -ENXIO;}static int stifb_disabled __initdata;int __initstifb_setup(char *options);static int __init stifb_init(void){ struct sti_struct *sti; struct sti_struct *def_sti; int i; #ifndef MODULE char *option = NULL; if (fb_get_options("stifb", &option)) return -ENODEV; stifb_setup(option);#endif if (stifb_disabled) { printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n"); return -ENXIO; } def_sti = sti_get_rom(0); if (def_sti) { for (i = 1; i <= MAX_STI_ROMS; i++) { sti = sti_get_rom(i); if (!sti) break; if (sti == def_sti) { stifb_init_fb(sti, stifb_bpp_pref[i - 1]); break; } } } for (i = 1; i <= MAX_STI_ROMS; i++) { sti = sti_get_rom(i); if (!sti) break; if (sti == def_sti) continue; stifb_init_fb(sti, stifb_bpp_pref[i - 1]); } return 0;}/* * Cleanup */static void __exitstifb_cleanup(void){ struct sti_struct *sti; int i; for (i = 1; i <= MAX_STI_ROMS; i++) { sti = sti_get_rom(i); if (!sti) break; if (sti->info) { struct fb_info *info = sti->info; unregister_framebuffer(sti->info); release_mem_region(info->fix.mmio_start, info->fix.mmio_len); release_mem_region(info->fix.smem_start, info->fix.smem_len); if (info->screen_base) iounmap(info->screen_base); fb_dealloc_cmap(&info->cmap); kfree(info); } sti->info = NULL; }}int __initstifb_setup(char *options){ int i; if (!options || !*options) return 1; if (strncmp(options, "off", 3) == 0) { stifb_disabled = 1; options += 3; } if (strncmp(options, "bpp", 3) == 0) { options += 3; for (i = 0; i < MAX_STI_ROMS; i++) { if (*options++ != ':') break; stifb_bpp_pref[i] = simple_strtoul(options, &options, 10); } } return 1;}__setup("stifb=", stifb_setup);module_init(stifb_init);module_exit(stifb_cleanup);MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");MODULE_LICENSE("GPL v2");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -