char __init *cgthreefb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; 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; int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL; #ifndef FBCON_HAS_CFB8 return NULL; #endif if (!fb->s.cg3.regs) { fb->s.cg3.regs = (struct cg3_regs *) sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET, sizeof(struct cg3_regs), "cg3 regs"); if (cgRDI) { char buffer[40]; char *p; int ww, hh; *buffer = 0; prom_getstring (fb->prom_node, "params", buffer, sizeof(buffer)); if (*buffer) { ww = simple_strtoul (buffer, &p, 10); if (ww && *p == 'x') { hh = simple_strtoul (p + 1, &p, 10); if (hh && *p == '-') { if (type->fb_width != ww || type->fb_height != hh) { type->fb_width = ww; type->fb_height = hh; return SBUSFBINIT_SIZECHANGE; } } } } } } strcpy(fb->info.modename, "CGthree"); strcpy(fix->id, "CGthree"); fix->line_length = fb->var.xres_virtual; fix->accel = FB_ACCEL_SUN_CGTHREE; disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) { disp->screen_base = (char *) sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET, type->fb_size, "cg3 ram"); } disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; fb->dispsw = fbcon_cfb8; fb->margins = cg3_margins; fb->loadcmap = cg3_loadcmap; fb->blank = cg3_blank; fb->unblank = cg3_unblank; fb->physbase = phys; fb->mmap_map = cg3_mmap_map; #ifdef __sparc_v9__ sprintf(idstring, "%s at %016lx", cgRDI ? "cgRDI" : "cgthree", phys); #else sprintf(idstring, "%s at %x.%08lx", cgRDI ? "cgRDI" : "cgthree", fb->iospace, phys); #endif if (!prom_getbool(fb->prom_node, "width")) { /* Ugh, broken PROM didn't initialize us. * Let's deal with this ourselves. */ enum cg3_type type; u8 *p; if (cgRDI) type = CG3_RDI; else { u8 status = sbus_readb(&fb->s.cg3.regs->status), mon; if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) { mon = status & CG3_SR_RES_MASK; if (mon == CG3_SR_1152_900_76_A || mon == CG3_SR_1152_900_76_B) type = CG3_AT_76HZ; else type = CG3_AT_66HZ; } else { prom_printf("cgthree: can't handle SR %02x\n", status); prom_halt(); return NULL; /* fool gcc. */ } } for (p = cg3_regvals[type]; *p; p += 2) { u8 *regp = &((u8 *)fb->s.cg3.regs)[p[0]]; sbus_writeb(p[1], regp); } for (p = cg3_dacvals; *p; p += 2) { volatile u8 *regp; regp = (volatile u8 *)&fb->s.cg3.regs->cmap.addr; sbus_writeb(p[0], regp); regp = (volatile u8 *)&fb->s.cg3.regs->cmap.control; sbus_writeb(p[1], regp); } } return idstring; }
__initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb)) { struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; int lowdepth, i, j; #ifndef FBCON_HAS_CFB8 return NULL; #endif lowdepth = prom_getbool (fb->prom_node, "tcx-8-bit"); if (lowdepth) { strcpy(fb->info.modename, "TCX8"); strcpy(fix->id, "TCX8"); } else { strcpy(fb->info.modename, "TCX24"); strcpy(fix->id, "TCX24"); } fix->line_length = fb->var.xres_virtual; disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) disp->screen_base = (char *)sparc_alloc_io(phys, 0, type->fb_size, "tcx_ram", fb->iospace, 0); disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; fb->s.tcx.tec = (struct tcx_tec *)sparc_alloc_io(fb->sbdp->reg_addrs[7].phys_addr, 0, sizeof(struct tcx_tec), "tcx_tec", fb->iospace, 0); fb->s.tcx.thc = (struct tcx_thc *)sparc_alloc_io(fb->sbdp->reg_addrs[9].phys_addr, 0, sizeof(struct tcx_thc), "tcx_thc", fb->iospace, 0); fb->s.tcx.bt = (struct bt_regs *)sparc_alloc_io(fb->sbdp->reg_addrs[8].phys_addr, 0, sizeof(struct bt_regs), "tcx_dac", fb->iospace, 0); if (!lowdepth) { fb->s.tcx.cplane = (u32 *)sparc_alloc_io(fb->sbdp->reg_addrs[4].phys_addr, 0, type->fb_size*4, "tcx_cplane", fb->iospace, 0); type->fb_depth = 24; fb->switch_from_graph = tcx_switch_from_graph; } else { /* As there can be one tcx in a machine only, we can write directly into tcx_mmap_map */ tcx_mmap_map[1].size = SBUS_MMAP_EMPTY; tcx_mmap_map[4].size = SBUS_MMAP_EMPTY; tcx_mmap_map[5].size = SBUS_MMAP_EMPTY; tcx_mmap_map[6].size = SBUS_MMAP_EMPTY; } fb->dispsw = fbcon_cfb8; fb->margins = tcx_margins; fb->loadcmap = tcx_loadcmap; if (prom_getbool (fb->prom_node, "hw-cursor")) { fb->setcursor = tcx_setcursor; fb->setcursormap = tcx_setcursormap; fb->setcurshape = tcx_setcurshape; } fb->restore_palette = tcx_restore_palette; fb->blank = tcx_blank; fb->unblank = tcx_unblank; fb->reset = tcx_reset; fb->physbase = 0; for (i = 0; i < 13; i++) { /* tcx_mmap_map has to be sorted by voff, while order of phys registers from PROM differs a little bit. Here is the correction */ switch (i) { case 10: j = 12; break; case 11: case 12: j = i - 1; break; default: j = i; break; } tcx_mmap_map[i].poff = fb->sbdp->reg_addrs[j].phys_addr; } fb->mmap_map = tcx_mmap_map; /* Initialize Brooktree DAC */ fb->s.tcx.bt->addr = 0x04 << 24; /* color planes */ fb->s.tcx.bt->control = 0xff << 24; fb->s.tcx.bt->addr = 0x05 << 24; fb->s.tcx.bt->control = 0x00 << 24; fb->s.tcx.bt->addr = 0x06 << 24; /* overlay plane */ fb->s.tcx.bt->control = 0x73 << 24; fb->s.tcx.bt->addr = 0x07 << 24; fb->s.tcx.bt->control = 0x00 << 24; sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s", fb->iospace, phys, (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_REV_SHIFT) & TCX_THC_REV_REV_MASK, (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_MINREV_SHIFT) & TCX_THC_REV_MINREV_MASK, lowdepth ? "8-bit only" : "24-bit depth"); tcx_reset(fb); return idstring; }