📄 cgsixfb.c
字号:
u32 val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8); sbus_writel(val, &fbc->font); } } else { for (i = 0; i < fontheight(p); i++) { u32 val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p)); sbus_writel(val, &fbc->font); } } } } else { while (count >= 2) { count -= 2; sbus_writel(0, &fbc->incx); sbus_writel(1, &fbc->incy); sbus_writel(x, &fbc->x0); sbus_writel((x += 2 * fontwidth(p)) - 1, &fbc->x1); sbus_writel(y, &fbc->y0); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); } else { fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++) { u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); sbus_writel(val, &fbc->font); fd1 += 2; fd2 += 2; } } } while (count) { count--; sbus_writel(0, &fbc->incx); sbus_writel(1, &fbc->incy); sbus_writel(x, &fbc->x0); sbus_writel((x += fontwidth(p)) - 1, &fbc->x1); sbus_writel(y, &fbc->y0); if (fontheightlog(p)) i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; for (i = 0; i < fontheight(p); i++) { u32 val = *fd1++ << 24; sbus_writel(val, &fbc->font); } } else { fd1 = p->fontdata + (i << 1); for (i = 0; i < fontheight(p); i++) { u32 val = *(u16 *)fd1 << 16; sbus_writel(val, &fbc->font); fd1 += 2; } } } spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_revc(struct display *p, int xx, int yy){ /* Not used if hw cursor */}static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count){ struct bt_regs *bt = fb->s.cg6.bt; unsigned long flags; int i; spin_lock_irqsave(&fb->lock, flags); sbus_writel(index << 24, &bt->addr); for (i = index; count--; i++){ sbus_writel(fb->color_map CM(i,0) << 24, &bt->color_map); sbus_writel(fb->color_map CM(i,1) << 24, &bt->color_map); sbus_writel(fb->color_map CM(i,2) << 24, &bt->color_map); } spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_restore_palette (struct fb_info_sbusfb *fb){ struct bt_regs *bt = fb->s.cg6.bt; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); sbus_writel(0, &bt->addr); sbus_writel(0xffffffff, &bt->color_map); sbus_writel(0xffffffff, &bt->color_map); sbus_writel(0xffffffff, &bt->color_map); spin_unlock_irqrestore(&fb->lock, flags);}static struct display_switch cg6_dispsw __initdata = { setup: cg6_setup, bmove: fbcon_redraw_bmove, clear: cg6_clear, putc: cg6_putc, putcs: cg6_putcs, revc: cg6_revc, fontwidthmask: FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */};static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue){ struct bt_regs *bt = fb->s.cg6.bt; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); sbus_writel(1 << 24, &bt->addr); sbus_writel(red[0] << 24, &bt->cursor); sbus_writel(green[0] << 24, &bt->cursor); sbus_writel(blue[0] << 24, &bt->cursor); sbus_writel(3 << 24, &bt->addr); sbus_writel(red[1] << 24, &bt->cursor); sbus_writel(green[1] << 24, &bt->cursor); sbus_writel(blue[1] << 24, &bt->cursor); spin_unlock_irqrestore(&fb->lock, flags);}/* Set cursor shape */static void cg6_setcurshape (struct fb_info_sbusfb *fb){ struct cg6_thc *thc = fb->s.cg6.thc; unsigned long flags; int i; spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++) { sbus_writel(fb->cursor.bits[0][i], &thc->thc_cursmask [i]); sbus_writel(fb->cursor.bits[1][i], &thc->thc_cursbits [i]); } spin_unlock_irqrestore(&fb->lock, flags);}/* Load cursor information */static void cg6_setcursor (struct fb_info_sbusfb *fb){ unsigned int v; unsigned long flags; struct cg_cursor *c = &fb->cursor; spin_lock_irqsave(&fb->lock, flags); if (c->enable) v = ((c->cpos.fbx - c->chot.fbx) << 16) |((c->cpos.fby - c->chot.fby) & 0xffff); else /* Magic constant to turn off the cursor */ v = ((65536-32) << 16) | (65536-32); sbus_writel(v, &fb->s.cg6.thc->thc_cursxy); spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_blank (struct fb_info_sbusfb *fb){ unsigned long flags; u32 tmp; spin_lock_irqsave(&fb->lock, flags); tmp = sbus_readl(&fb->s.cg6.thc->thc_misc); tmp &= ~CG6_THC_MISC_VIDEO; sbus_writel(tmp, &fb->s.cg6.thc->thc_misc); spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_unblank (struct fb_info_sbusfb *fb){ unsigned long flags; u32 tmp; spin_lock_irqsave(&fb->lock, flags); tmp = sbus_readl(&fb->s.cg6.thc->thc_misc); tmp |= CG6_THC_MISC_VIDEO; sbus_writel(tmp, &fb->s.cg6.thc->thc_misc); spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_reset (struct fb_info_sbusfb *fb){ unsigned int rev, conf; struct cg6_tec *tec = fb->s.cg6.tec; struct cg6_fbc *fbc = fb->s.cg6.fbc; unsigned long flags; u32 mode, tmp; int i; spin_lock_irqsave(&fb->lock, flags); /* Turn off stuff in the Transform Engine. */ sbus_writel(0, &tec->tec_matrix); sbus_writel(0, &tec->tec_clip); sbus_writel(0, &tec->tec_vdc); /* Take care of bugs in old revisions. */ rev = (sbus_readl(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK; if (rev < 5) { conf = (sbus_readl(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) | CG6_FHC_CPU_68020 | CG6_FHC_TEST | (11 << CG6_FHC_TEST_X_SHIFT) | (11 << CG6_FHC_TEST_Y_SHIFT); if (rev < 2) conf |= CG6_FHC_DST_DISABLE; sbus_writel(conf, fb->s.cg6.fhc); } /* Set things in the FBC. Bad things appear to happen if we do * back to back store/loads on the mode register, so copy it * out instead. */ mode = sbus_readl(&fbc->mode); do { i = sbus_readl(&fbc->s); } while (i & 0x10000000); mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK | CG6_FBC_BDISP_MASK); mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 | CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE | CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 | CG6_FBC_BDISP_0); sbus_writel(mode, &fbc->mode); sbus_writel(0, &fbc->clip); sbus_writel(0, &fbc->offx); sbus_writel(0, &fbc->offy); sbus_writel(0, &fbc->clipminx); sbus_writel(0, &fbc->clipminy); sbus_writel(fb->type.fb_width - 1, &fbc->clipmaxx); sbus_writel(fb->type.fb_height - 1, &fbc->clipmaxy); /* Enable cursor in Brooktree DAC. */ sbus_writel(0x06 << 24, &fb->s.cg6.bt->addr); tmp = sbus_readl(&fb->s.cg6.bt->control); tmp |= 0x03 << 24; sbus_writel(tmp, &fb->s.cg6.bt->control); spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin){ p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin);}static int __init cg6_rasterimg (struct fb_info *info, int start){ struct fb_info_sbusfb *fb = sbusfbinfo(info); register struct cg6_fbc *fbc = fb->s.cg6.fbc; int i; do { i = sbus_readl(&fbc->s); } while (i & 0x10000000); return 0;}static char idstring[70] __initdata = { 0 };char __init *cgsixfb_init(struct fb_info_sbusfb *fb){ struct fb_fix_screeninfo *fix = &fb->fix; struct fb_var_screeninfo *var = &fb->var; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; struct sbus_dev *sdev = fb->sbdp; unsigned long phys = sdev->reg_addrs[0].phys_addr; u32 conf; char *p; char *cardtype; struct bt_regs *bt; struct fb_ops *fbops; fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); if (fbops == NULL) return NULL; *fbops = *fb->info.fbops; fbops->fb_rasterimg = cg6_rasterimg; fb->info.fbops = fbops; if (prom_getbool (fb->prom_node, "dblbuf")) { type->fb_size *= 4; fix->smem_len *= 4; } fix->line_length = fb->var.xres_virtual; fix->accel = FB_ACCEL_SUN_CGSIX; var->accel_flags = FB_ACCELF_TEXT; disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) { disp->screen_base = (char *) sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET, type->fb_size, "cgsix ram"); } disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; fb->s.cg6.fbc = (struct cg6_fbc *) sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET, 4096, "cgsix fbc"); fb->s.cg6.tec = (struct cg6_tec *) sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET, sizeof(struct cg6_tec), "cgsix tec"); fb->s.cg6.thc = (struct cg6_thc *) sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET, sizeof(struct cg6_thc), "cgsix thc"); fb->s.cg6.bt = bt = (struct bt_regs *) sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET, sizeof(struct bt_regs), "cgsix dac"); fb->s.cg6.fhc = (u32 *) sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET, sizeof(u32), "cgsix fhc");#if 0 prom_printf("CG6: RES[%016lx:%016lx:%016lx]\n", sdev->resource[0].start, sdev->resource[0].end, sdev->resource[0].flags); prom_printf("CG6: fbc(%p) tec(%p) thc(%p) bt(%p) fhc(%p)\n", fb->s.cg6.fbc, fb->s.cg6.tec, fb->s.cg6.thc, fb->s.cg6.bt, fb->s.cg6.fhc); prom_halt();#endif fb->dispsw = cg6_dispsw; fb->margins = cg6_margins; fb->loadcmap = cg6_loadcmap; fb->setcursor = cg6_setcursor; fb->setcursormap = cg6_setcursormap; fb->setcurshape = cg6_setcurshape; fb->restore_palette = cg6_restore_palette; fb->fill = cg6_fill; fb->blank = cg6_blank; fb->unblank = cg6_unblank; fb->reset = cg6_reset; fb->physbase = phys; fb->mmap_map = cg6_mmap_map; /* Initialize Brooktree DAC */ sbus_writel(0x04 << 24, &bt->addr); /* color planes */ sbus_writel(0xff << 24, &bt->control); sbus_writel(0x05 << 24, &bt->addr); sbus_writel(0x00 << 24, &bt->control); sbus_writel(0x06 << 24, &bt->addr); /* overlay plane */ sbus_writel(0x73 << 24, &bt->control); sbus_writel(0x07 << 24, &bt->addr); sbus_writel(0x00 << 24, &bt->control); conf = sbus_readl(fb->s.cg6.fhc); switch(conf & CG6_FHC_CPU_MASK) { case CG6_FHC_CPU_SPARC: p = "sparc"; break; case CG6_FHC_CPU_68020: p = "68020"; break; default: p = "i386"; break; } if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) { if (fix->smem_len <= 0x100000) { cardtype = "TGX"; } else { cardtype = "TGX+"; } } else { if (fix->smem_len <= 0x100000) { cardtype = "GX"; } else { cardtype = "GX+"; } } sprintf(idstring, #ifdef __sparc_v9__ "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys,#else "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", fb->iospace, phys, #endif ((sbus_readl(&fb->s.cg6.thc->thc_misc) >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK), p, (conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK, cardtype); sprintf(fb->info.modename, "CGsix [%s]", cardtype); sprintf(fix->id, "CGsix [%s]", cardtype); cg6_reset(fb); return idstring;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -