Ejemplo n.º 1
0
void
tcx_prom(void *v)
{
	struct tcx_softc *sc = v;
	extern struct consdev consdev_prom;

	if (sc->sc_sunfb.sf_depth != 8) {
		/*
	 	 * Select 8-bit mode.
	 	 */
		tcx_reset(sc, 8);

		/*
	 	 * Go back to prom output for the last few messages, so they
	 	 * will be displayed correctly.
	 	 */
		cn_tab = &consdev_prom;
	}
}
Ejemplo n.º 2
0
Archivo: tcx.c Proyecto: 020gzh/linux
static int tcx_probe(struct platform_device *op)
{
	struct device_node *dp = op->dev.of_node;
	struct fb_info *info;
	struct tcx_par *par;
	int linebytes, i, err;

	info = framebuffer_alloc(sizeof(struct tcx_par), &op->dev);

	err = -ENOMEM;
	if (!info)
		goto out_err;
	par = info->par;

	spin_lock_init(&par->lock);

	par->lowdepth =
		(of_find_property(dp, "tcx-8-bit", NULL) != NULL);

	sbusfb_fill_var(&info->var, dp, 8);
	info->var.red.length = 8;
	info->var.green.length = 8;
	info->var.blue.length = 8;

	linebytes = of_getintprop_default(dp, "linebytes",
					  info->var.xres);
	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);

	par->tec = of_ioremap(&op->resource[7], 0,
				  sizeof(struct tcx_tec), "tcx tec");
	par->thc = of_ioremap(&op->resource[9], 0,
				  sizeof(struct tcx_thc), "tcx thc");
	par->bt = of_ioremap(&op->resource[8], 0,
				 sizeof(struct bt_regs), "tcx dac");
	info->screen_base = of_ioremap(&op->resource[0], 0,
					   info->fix.smem_len, "tcx ram");
	if (!par->tec || !par->thc ||
	    !par->bt || !info->screen_base)
		goto out_unmap_regs;

	memcpy(&par->mmap_map, &__tcx_mmap_map, sizeof(par->mmap_map));
	if (!par->lowdepth) {
		par->cplane = of_ioremap(&op->resource[4], 0,
					     info->fix.smem_len * sizeof(u32),
					     "tcx cplane");
		if (!par->cplane)
			goto out_unmap_regs;
	} else {
		par->mmap_map[1].size = SBUS_MMAP_EMPTY;
		par->mmap_map[4].size = SBUS_MMAP_EMPTY;
		par->mmap_map[5].size = SBUS_MMAP_EMPTY;
		par->mmap_map[6].size = SBUS_MMAP_EMPTY;
	}

	info->fix.smem_start = op->resource[0].start;
	par->which_io = op->resource[0].flags & IORESOURCE_BITS;

	for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
		int j;

		switch (i) {
		case 10:
			j = 12;
			break;

		case 11: case 12:
			j = i - 1;
			break;

		default:
			j = i;
			break;
		}
		par->mmap_map[i].poff = op->resource[j].start;
	}

	info->flags = FBINFO_DEFAULT;
	info->fbops = &tcx_ops;

	/* Initialize brooktree DAC. */
	sbus_writel(0x04 << 24, &par->bt->addr);         /* color planes */
	sbus_writel(0xff << 24, &par->bt->control);
	sbus_writel(0x05 << 24, &par->bt->addr);
	sbus_writel(0x00 << 24, &par->bt->control);
	sbus_writel(0x06 << 24, &par->bt->addr);         /* overlay plane */
	sbus_writel(0x73 << 24, &par->bt->control);
	sbus_writel(0x07 << 24, &par->bt->addr);
	sbus_writel(0x00 << 24, &par->bt->control);

	tcx_reset(info);

	tcx_blank(FB_BLANK_UNBLANK, info);

	if (fb_alloc_cmap(&info->cmap, 256, 0))
		goto out_unmap_regs;

	fb_set_cmap(&info->cmap, info);
	tcx_init_fix(info, linebytes);

	err = register_framebuffer(info);
	if (err < 0)
		goto out_dealloc_cmap;

	dev_set_drvdata(&op->dev, info);

	printk(KERN_INFO "%s: TCX at %lx:%lx, %s\n",
	       dp->full_name,
	       par->which_io,
	       info->fix.smem_start,
	       par->lowdepth ? "8-bit only" : "24-bit depth");

	return 0;

out_dealloc_cmap:
	fb_dealloc_cmap(&info->cmap);

out_unmap_regs:
	tcx_unmap_regs(op, info, par);
	framebuffer_release(info);

out_err:
	return err;
}
Ejemplo n.º 3
0
Archivo: tcx.c Proyecto: 020gzh/linux
static int tcx_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
	tcx_reset(info);
	return 0;
}
Ejemplo n.º 4
0
int
tcx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
	struct tcx_softc *sc = dev;
	struct wsdisplay_cmap *cm;
	struct wsdisplay_fbinfo *wdf;
	int error;

	/*
	 * Note that, although the emulation (text) mode is running in 8-bit
	 * mode, if the frame buffer is able to run in 24-bit mode, it will
	 * be advertized as such.
	 */
	switch (cmd) {
	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_SUNTCX;
		break;
	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->height = sc->sc_sunfb.sf_height;
		wdf->width = sc->sc_sunfb.sf_width;
		wdf->depth = sc->sc_sunfb.sf_depth;
		wdf->cmsize = sc->sc_cplane == 0 ? 256 : 0;
		break;
	case WSDISPLAYIO_GETSUPPORTEDDEPTH:
		if (sc->sc_cplane != 0)
			*(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
		else
			return (-1);
		break;
	case WSDISPLAYIO_LINEBYTES:
		if (sc->sc_cplane == 0)
			*(u_int *)data = sc->sc_sunfb.sf_linebytes;
		else
			*(u_int *)data = sc->sc_sunfb.sf_linebytes * 4;
		break;

	case WSDISPLAYIO_GETCMAP:
		if (sc->sc_cplane == 0) {
			cm = (struct wsdisplay_cmap *)data;
			error = bt_getcmap(&sc->sc_cmap, cm);
			if (error)
				return (error);
		}
		break;
	case WSDISPLAYIO_PUTCMAP:
		if (sc->sc_cplane == 0) {
			cm = (struct wsdisplay_cmap *)data;
			error = bt_putcmap(&sc->sc_cmap, cm);
			if (error)
				return (error);
			tcx_loadcmap_deferred(sc, cm->index, cm->count);
		}
		break;

	case WSDISPLAYIO_SMODE:
		if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
			/* Back from X11 to text mode */
			tcx_reset(sc, 8);
		} else {
			/* Starting X11, try to switch to 24 bit mode */
			if (sc->sc_cplane != 0)
				tcx_reset(sc, 32);
		}
		break;

	case WSDISPLAYIO_SVIDEO:
	case WSDISPLAYIO_GVIDEO:
		break;

	default:
		return (-1);	/* not supported yet */
	}

	return (0);
}
Ejemplo n.º 5
0
void
tcxattach(struct device *parent, struct device *self, void *args)
{
	struct tcx_softc *sc = (struct tcx_softc *)self;
	struct confargs *ca = args;
	int node, pri;
	int isconsole = 0;
	char *nam = NULL;
	vaddr_t thc_offset;

	pri = ca->ca_ra.ra_intr[0].int_pri;
	printf(" pri %d: ", pri);

	node = ca->ca_ra.ra_node;
	isconsole = node == fbnode;

	if (ca->ca_ra.ra_nreg < TCX_NREG) {
		printf("expected %d registers, got %d\n",
		    TCX_NREG, ca->ca_ra.ra_nreg);
		return;
	}

	nam = getpropstring(node, "model");
	if (*nam != '\0')
		printf("%s, ", nam);

	/*
	 * Copy the register address spaces needed for mmap operation.
	 */
	sc->sc_phys[0] = ca->ca_ra.ra_reg[TCX_REG_DFB8];
	sc->sc_phys[1] = ca->ca_ra.ra_reg[TCX_REG_DFB24];

	/*
	 * Can't trust the PROM range len here, it is only 4 bytes on the
	 * 8-bit model. Not that it matters much anyway since we map in
	 * pages.
	 */
	sc->sc_bt = (volatile struct bt_regs *)
	    mapiodev(&ca->ca_ra.ra_reg[TCX_REG_CMAP], 0, sizeof *sc->sc_bt);

	/*
	 * For some reason S24 PROM sets up TEC and THC ranges at the
	 * right addresses (701000 and 301000), while 8 bit TCX doesn't
	 * (and uses 70000 and 30000) - be sure to only compensate on 8 bit
	 * models.
	 */
	if (((vaddr_t)ca->ca_ra.ra_reg[TCX_REG_THC].rr_paddr & 0x1000) != 0)
		thc_offset = 0;
	else
		thc_offset = 0x1000;
	sc->sc_thc = (volatile struct tcx_thc *)
	    mapiodev(&ca->ca_ra.ra_reg[TCX_REG_THC],
	        thc_offset, sizeof *sc->sc_thc);

	/*
	 * Find out frame buffer geometry, so that we know how much
	 * memory to map.
	 */
	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);

	sc->sc_dfb8 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB8], 0,
	    round_page(sc->sc_sunfb.sf_fbsize));

	/*
	 * If the frame buffer advertizes itself as the 8 bit model, or
	 * if the PROM ranges are too small, limit ourselves to 8 bit
	 * operations.
	 *
	 * Further code needing to know which capabilities the frame buffer
	 * has will rely on sc_cplane being non-zero if 24 bit operation
	 * is possible.
	 */
	if (!node_has_property(node, "tcx-8-bit") &&
	    ca->ca_ra.ra_reg[TCX_REG_RDFB32].rr_len >=
	      sc->sc_sunfb.sf_fbsize * 4) {
		sc->sc_cplane =
		    (paddr_t)ca->ca_ra.ra_reg[TCX_REG_RDFB32].rr_paddr;
	}

	printf("%dx%dx%d\n",
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
	    sc->sc_cplane == 0 ? 8 : 24);

	/*
	 * Set up mappings for the acceleration code. This may fail.
	 */
	tcx_accel_init(sc, ca);

	/* reset cursor & frame buffer controls */
	tcx_reset(sc, 8);

	/* enable video */
	tcx_burner(sc, 1, 0);

	sc->sc_sunfb.sf_ro.ri_hw = sc;
	sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_dfb8;

	fbwscons_init(&sc->sc_sunfb, isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, tcx_setcolor);

	/*
	 * Now plug accelerated console routines, if possible.
	 */
	tcx_accel_plug(sc, ca);

	sc->sc_ih.ih_fun = tcx_intr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname);

	if (isconsole) {
		fbwscons_console_init(&sc->sc_sunfb, -1);
		shutdownhook_establish(tcx_prom, sc);
	}

	fbwscons_attach(&sc->sc_sunfb, &tcx_accessops, isconsole);
}
Ejemplo n.º 6
0
void tcx_init(target_phys_addr_t addr, int vram_size, int width, int height,
              int depth)
{
    TCXState *s;
    int io_memory, dummy_memory;
    ram_addr_t vram_offset;
    int size;
    uint8_t *vram_base;

    vram_offset = qemu_ram_alloc(vram_size * (1 + 4 + 4));
    vram_base = qemu_get_ram_ptr(vram_offset);

    s = qemu_mallocz(sizeof(TCXState));
    s->addr = addr;
    s->vram_offset = vram_offset;
    s->width = width;
    s->height = height;
    s->depth = depth;

    // 8-bit plane
    s->vram = vram_base;
    size = vram_size;
    cpu_register_physical_memory(addr + 0x00800000ULL, size, vram_offset);
    vram_offset += size;
    vram_base += size;

    io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);
    cpu_register_physical_memory(addr + 0x00200000ULL, TCX_DAC_NREGS,
                                 io_memory);

    dummy_memory = cpu_register_io_memory(0, tcx_dummy_read, tcx_dummy_write,
                                          s);
    cpu_register_physical_memory(addr + 0x00700000ULL, TCX_TEC_NREGS,
                                 dummy_memory);
    if (depth == 24) {
        // 24-bit plane
        size = vram_size * 4;
        s->vram24 = (uint32_t *)vram_base;
        s->vram24_offset = vram_offset;
        cpu_register_physical_memory(addr + 0x02000000ULL, size, vram_offset);
        vram_offset += size;
        vram_base += size;

        // Control plane
        size = vram_size * 4;
        s->cplane = (uint32_t *)vram_base;
        s->cplane_offset = vram_offset;
        cpu_register_physical_memory(addr + 0x0a000000ULL, size, vram_offset);
        s->ds = graphic_console_init(tcx24_update_display,
                                     tcx24_invalidate_display,
                                     tcx24_screen_dump, NULL, s);
    } else {
        cpu_register_physical_memory(addr + 0x00300000ULL, TCX_THC_NREGS_8,
                                     dummy_memory);
        s->ds = graphic_console_init(tcx_update_display,
                                     tcx_invalidate_display,
                                     tcx_screen_dump, NULL, s);
    }
    // NetBSD writes here even with 8-bit display
    cpu_register_physical_memory(addr + 0x00301000ULL, TCX_THC_NREGS_24,
                                 dummy_memory);

    register_savevm("tcx", addr, 4, tcx_save, tcx_load, s);
    qemu_register_reset(tcx_reset, s);
    tcx_reset(s);
    qemu_console_resize(s->ds, width, height);
}
Ejemplo n.º 7
0
static int __devinit tcx_init_one(struct of_device *op)
{
	struct device_node *dp = op->node;
	struct all_info *all;
	int linebytes, i, err;

	all = kzalloc(sizeof(*all), GFP_KERNEL);
	if (!all)
		return -ENOMEM;

	spin_lock_init(&all->par.lock);

	all->par.lowdepth =
		(of_find_property(dp, "tcx-8-bit", NULL) != NULL);

	sbusfb_fill_var(&all->info.var, dp->node, 8);
	all->info.var.red.length = 8;
	all->info.var.green.length = 8;
	all->info.var.blue.length = 8;

	linebytes = of_getintprop_default(dp, "linebytes",
					  all->info.var.xres);
	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);

	all->par.tec = of_ioremap(&op->resource[7], 0,
				  sizeof(struct tcx_tec), "tcx tec");
	all->par.thc = of_ioremap(&op->resource[9], 0,
				  sizeof(struct tcx_thc), "tcx thc");
	all->par.bt = of_ioremap(&op->resource[8], 0,
				 sizeof(struct bt_regs), "tcx dac");
	all->info.screen_base = of_ioremap(&op->resource[0], 0,
					   all->par.fbsize, "tcx ram");
	if (!all->par.tec || !all->par.thc ||
	    !all->par.bt || !all->info.screen_base) {
		tcx_unmap_regs(all);
		kfree(all);
		return -ENOMEM;
	}

	memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map));
	if (!all->par.lowdepth) {
		all->par.cplane = of_ioremap(&op->resource[4], 0,
					     all->par.fbsize * sizeof(u32),
					     "tcx cplane");
		if (!all->par.cplane) {
			tcx_unmap_regs(all);
			kfree(all);
			return -ENOMEM;
		}
	} else {
		all->par.mmap_map[1].size = SBUS_MMAP_EMPTY;
		all->par.mmap_map[4].size = SBUS_MMAP_EMPTY;
		all->par.mmap_map[5].size = SBUS_MMAP_EMPTY;
		all->par.mmap_map[6].size = SBUS_MMAP_EMPTY;
	}

	all->par.physbase = 0;
	all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;

	for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
		int j;

		switch (i) {
		case 10:
			j = 12;
			break;

		case 11: case 12:
			j = i - 1;
			break;

		default:
			j = i;
			break;
		};
		all->par.mmap_map[i].poff = op->resource[j].start;
	}

	all->info.flags = FBINFO_DEFAULT;
	all->info.fbops = &tcx_ops;
	all->info.par = &all->par;

	/* Initialize brooktree DAC. */
	sbus_writel(0x04 << 24, &all->par.bt->addr);         /* color planes */
	sbus_writel(0xff << 24, &all->par.bt->control);
	sbus_writel(0x05 << 24, &all->par.bt->addr);
	sbus_writel(0x00 << 24, &all->par.bt->control);
	sbus_writel(0x06 << 24, &all->par.bt->addr);         /* overlay plane */
	sbus_writel(0x73 << 24, &all->par.bt->control);
	sbus_writel(0x07 << 24, &all->par.bt->addr);
	sbus_writel(0x00 << 24, &all->par.bt->control);

	tcx_reset(&all->info);

	tcx_blank(FB_BLANK_UNBLANK, &all->info);

	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
		tcx_unmap_regs(all);
		kfree(all);
		return -ENOMEM;
	}

	fb_set_cmap(&all->info.cmap, &all->info);
	tcx_init_fix(&all->info, linebytes);

	err = register_framebuffer(&all->info);
	if (err < 0) {
		fb_dealloc_cmap(&all->info.cmap);
		tcx_unmap_regs(all);
		kfree(all);
		return err;
	}

	dev_set_drvdata(&op->dev, all);

	printk("%s: TCX at %lx:%lx, %s\n",
	       dp->full_name,
	       all->par.which_io,
	       op->resource[0].start,
	       all->par.lowdepth ? "8-bit only" : "24-bit depth");

	return 0;
}
Ejemplo n.º 8
0
__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;
}