📄 stifb.c
字号:
} if (count-c) return (count-c); return err;}static intstifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info){ struct stifb_info *fb = (struct stifb_info *) info; u32 color; if (regno >= 256) /* no. of hw registers */ return 1; red >>= 8; green >>= 8; blue >>= 8; DEBUG_OFF(); START_IMAGE_COLORMAP_ACCESS(fb); if (fb->info.var.grayscale) { /* gray = 0.30*R + 0.59*G + 0.11*B */ color = ((red * 77) + (green * 151) + (blue * 28)) >> 8; } else { color = ((red << 16) | (green << 8) | (blue)); } 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_read = stifb_read, .fb_write = stifb_write, .fb_setcolreg = stifb_setcolreg, .fb_blank = stifb_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_cursor = soft_cursor,};/* * Initialization */int __initstifb_init_fb(struct sti_struct *sti, int force_bpp){ 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 = kmalloc(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 */ memset(fb, 0, sizeof(*fb)); 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: /* look for a double buffering device like e.g. the "INTERNAL_EG_DX1024" in the RDI precisionbook laptop which won't work. The same device in non-double buffering mode returns "INTERNAL_EG_X1024". */ if (strstr(sti->outptr.dev_name, "EG_DX")) { printk(KERN_WARNING "stifb: ignoring '%s'. Disable double buffering in IPL menu.\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 = (void*) REGION_BASE(fb_info,2); * 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 = fb->sti->regions_phys[0]; else sti_rom_address = fb->sti->regions_phys[1];#ifdef __LP64__ sti_rom_address |= 0xffffffff00000000;#endif fb->deviceSpecificConfig = __raw_readl(sti_rom_address); if (IS_24_DEVICE(fb)) { if (force_bpp == 8 || force_bpp == 32) bpp = force_bpp; 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_TRUECOLOR; 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 = (void*) REGION_BASE(fb,1); info->flags = FBINFO_DEFAULT; info->currcon = -1; /* This has to been done !!! */ fb_alloc_cmap(&info->cmap, 256, 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: fb_dealloc_cmap(&info->cmap);out_err0: kfree(fb); return -ENXIO;}static int stifb_disabled __initdata;int __initstifb_setup(char *options);int __initstifb_init(void){ struct sti_struct *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; } for (i = 1; i < MAX_STI_ROMS; i++) { sti = sti_get_rom(i); if (!sti) break; if (bpp > 0) stifb_force_bpp[i] = bpp; stifb_init_fb(sti, stifb_force_bpp[i]); } 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); fb_dealloc_cmap(&info->cmap); kfree(info); } sti->info = NULL; }}int __initstifb_setup(char *options){ int i; if (!options || !*options) return 0; 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++ == ':') { stifb_force_bpp[i] = simple_strtoul(options, &options, 10); bpp = -1; } else break; } } return 0;}__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");MODULE_PARM(bpp, "i");MODULE_PARM_DESC(mem, "Bits per pixel (default: 8)");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -