/*
 * Probe for a pfour framebuffer.  Return values:
 *
 *	PFOUR_NOTPFOUR: framebuffer is not a pfour framebuffer
 *	otherwise returns pfour ID
 */
int
fb_pfour_id(volatile void *va)
{
#if defined(SUN4)
	volatile u_int32_t val, save, *pfour = va;

	/* Read the pfour register. */
	save = *pfour;

	/*
	 * Try to modify the type code.  If it changes, put the
	 * original value back, and notify the caller that it's
	 * not a pfour framebuffer.
	 */
	val = save & ~PFOUR_REG_RESET;
	*pfour = (val ^ PFOUR_FBTYPE_MASK);
	if ((*pfour ^ val) & PFOUR_FBTYPE_MASK) {
		*pfour = save;
		return (PFOUR_NOTPFOUR);
	}

	return (PFOUR_ID(val));
#else
	return (PFOUR_NOTPFOUR);
#endif /* SUN4 */
}
Example #2
0
void
fb_setsize(struct sunfb *sf, int def_depth, int def_width, int def_height,
    int node, int bustype)
{
	int def_linebytes;

	switch (bustype) {
	case BUS_VME16:
	case BUS_VME32:
	case BUS_OBIO:
#if defined(SUN4M)
		/* 4m may have SBus-like framebuffer on obio */
		if (CPU_ISSUN4M) {
			goto obpsize;
		}
#endif
		/* Set up some defaults. */
		sf->sf_width = def_width;
		sf->sf_height = def_height;
		sf->sf_depth = def_depth;

#if defined(SUN4)
		/*
		 * This is not particularly useful on Sun 4 VME framebuffers.
		 * The EEPROM only contains info about the built-in.
		 */
		if (CPU_ISSUN4 && bustype == BUS_OBIO) {
			struct eeprom *eep = (struct eeprom *)eeprom_va;

			if (ISSET(sf->sf_flags, FB_PFOUR)) {
				volatile u_int32_t pfour;
				u_int size;

				pfour = *sf->sf_pfour;

				/*
				 * Use the pfour register to determine
				 * the size.  Note that the cgsix and
				 * cgeight don't use this size encoding.
				 * In this case, we have to settle
				 * for the defaults we were provided
				 * with.
				 */
				if ((PFOUR_ID(pfour) == PFOUR_ID_COLOR24) ||
				    (PFOUR_ID(pfour) == PFOUR_ID_FASTCOLOR))
					size = 0x00; /* invalid */
				else
					size = PFOUR_SIZE(pfour);

				switch (size) {
				case PFOUR_SIZE_1152X900:
					sf->sf_width = 1152;
					sf->sf_height = 900;
					break;
				case PFOUR_SIZE_1024X1024:
					sf->sf_width = 1024;
					sf->sf_height = 1024;
					break;
				case PFOUR_SIZE_1280X1024:
					sf->sf_width = 1280;
					sf->sf_height = 1024;
					break;
				case PFOUR_SIZE_1600X1280:
					sf->sf_width = 1600;
					sf->sf_height = 1280;
					break;
				case PFOUR_SIZE_1440X1440:
					sf->sf_width = 1440;
					sf->sf_height = 1440;
					break;
				case PFOUR_SIZE_640X480:
					sf->sf_width = 640;
					sf->sf_height = 480;
					break;
				}
			} else if (eep != NULL) {
				switch (eep->eeScreenSize) {
				case EE_SCR_1152X900:
					sf->sf_width = 1152;
					sf->sf_height = 900;
					break;
				case EE_SCR_1024X1024:
					sf->sf_width = 1024;
					sf->sf_height = 1024;
					break;
				case EE_SCR_1600X1280:
					sf->sf_width = 1600;
					sf->sf_height = 1280;
					break;
				case EE_SCR_1440X1440:
					sf->sf_width = 1440;
					sf->sf_height = 1440;
					break;
				}
			}
		}
#endif /* SUN4 */
#if defined(SUN4M)
		if (CPU_ISSUN4M) {
			/* XXX: need code to find 4/600 vme screen size */
		}
#endif /* SUN4M */

		sf->sf_linebytes = (sf->sf_width * sf->sf_depth) / 8;
		break;

	case BUS_SBUS:
#if defined(SUN4M)
obpsize:
#endif
		sf->sf_depth = getpropint(node, "depth", def_depth);
		sf->sf_width = getpropint(node, "width", def_width);
		sf->sf_height = getpropint(node, "height", def_height);

		def_linebytes =
		    roundup(sf->sf_width, sf->sf_depth) * sf->sf_depth / 8;
		sf->sf_linebytes = getpropint(node, "linebytes", def_linebytes);

		/*
		 * XXX If we are configuring a board in a wider depth level
		 * than the mode it is currently operating in, the PROM will
		 * return a linebytes property tied to the current depth value,
		 * which is NOT what we are relying upon!
		 */
		if (sf->sf_linebytes < (sf->sf_width * sf->sf_depth) / 8)
			sf->sf_linebytes = def_linebytes;

		break;
	}

	sf->sf_fbsize = sf->sf_height * sf->sf_linebytes;
}
Example #3
0
static void
bwtwoattach_obio(device_t parent, device_t self, void *aux)
{
	struct bwtwo_softc *sc = device_private(self);
	union obio_attach_args *uoba = aux;
	struct obio4_attach_args *oba;
	struct fbdevice *fb = &sc->sc_fb;
	struct eeprom *eep = (struct eeprom *)eeprom_va;
	bus_space_handle_t bh;
	int constype, isconsole;
	const char *name;

	sc->sc_dev = self;
	oba = &uoba->uoba_oba4;

	/* Remember cookies for bwtwo_mmap() */
	sc->sc_bustag = oba->oba_bustag;
	sc->sc_paddr = (bus_addr_t)oba->oba_paddr;

	fb->fb_flags = device_cfdata(self)->cf_flags;
	fb->fb_type.fb_depth = 1;
	fb_setsize_eeprom(fb, fb->fb_type.fb_depth, 1152, 900);

	constype = (fb->fb_flags & FB_PFOUR) ? EE_CONS_P4OPT : EE_CONS_BW;
	if (eep == NULL || eep->eeConsole == constype)
		isconsole = fb_is_console(0);
	else
		isconsole = 0;

	if (fb->fb_flags & FB_PFOUR) {
		/*
		 * Map the pfour control register.
		 * Set pixel offset to appropriate overlay plane.
		 */
		name = "bwtwo/p4";

		if (bus_space_map(oba->oba_bustag,
				  oba->oba_paddr,
				  sizeof(uint32_t),
				  BUS_SPACE_MAP_LINEAR,
				  &bh) != 0) {
			printf("%s: cannot map pfour register\n",
			    device_xname(self));
			return;
		}
		fb->fb_pfour = (uint32_t *)bh;
		sc->sc_reg = NULL;

		/*
		 * Notice if this is an overlay plane on a color
		 * framebuffer.  Note that PFOUR_COLOR_OFF_OVERLAY
		 * is the same as PFOUR_BW_OFF, but we use the
		 * different names anyway.
		 */
		switch (PFOUR_ID(*fb->fb_pfour)) {
		case PFOUR_ID_COLOR8P1:
			sc->sc_ovtype = BWO_CGFOUR;
			sc->sc_pixeloffset = PFOUR_COLOR_OFF_OVERLAY;
			break;

		case PFOUR_ID_COLOR24:
			sc->sc_ovtype = BWO_CGEIGHT;
			sc->sc_pixeloffset = PFOUR_COLOR_OFF_OVERLAY;
			break;

		default:
			sc->sc_ovtype = BWO_NONE;
			sc->sc_pixeloffset = PFOUR_BW_OFF;
			break;
		}

	} else {
		/* A plain bwtwo */
		if (bus_space_map(oba->oba_bustag,
				  oba->oba_paddr + BWREG_REG,
				  sizeof(struct fbcontrol),
				  BUS_SPACE_MAP_LINEAR,
				  &bh) != 0) {
			printf("%s: cannot map control registers\n",
			    device_xname(self));
			return;
		}
		sc->sc_reg = (struct fbcontrol *)bh;
		fb->fb_pfour = NULL;

		name = "bwtwo";
		sc->sc_pixeloffset = BWREG_MEM;
	}
	sc->sc_get_video = bwtwo_get_video_sun4;
	sc->sc_set_video = bwtwo_set_video_sun4;

	if (isconsole) {
		int ramsize = fb->fb_type.fb_height * fb->fb_linebytes;
		if (bus_space_map(oba->oba_bustag,
				  oba->oba_paddr + sc->sc_pixeloffset,
				  ramsize,
				  BUS_SPACE_MAP_LINEAR,
				  &bh) != 0) {
			printf("%s: cannot map pixels\n", device_xname(self));
			return;
		}
		sc->sc_fb.fb_pixels = (char *)bh;
	}

	bwtwoattach(sc, name, isconsole);
}
void
fb_setsize_pfour(struct fbdevice *fb)
{
#if defined(SUN4)
	volatile u_int32_t pfour;
	int width, height;

	/*
	 * Some pfour framebuffers, e.g. the
	 * cgsix, don't encode resolution the
	 * same, so the driver handles that.
	 * The driver can let us know that it
	 * needs to do this by not mapping in
	 * the pfour register by the time this
	 * routine is called.
	 */
	if (fb->fb_pfour == NULL)
		return;

	pfour = *fb->fb_pfour;

	/*
	 * Use the pfour register to determine
	 * the size.  Note that the cgsix and
	 * cgeight don't use this size encoding.
	 * In this case, we have to settle
	 * for the defaults we were provided
	 * with.
	 */
	if ((PFOUR_ID(pfour) == PFOUR_ID_COLOR24) ||
	    (PFOUR_ID(pfour) == PFOUR_ID_FASTCOLOR))
		return;

	switch (PFOUR_SIZE(pfour)) {
	case PFOUR_SIZE_1152X900:
		width = 1152;
		height = 900;
		break;

	case PFOUR_SIZE_1024X1024:
		width = 1024;
		height = 1024;
		break;

	case PFOUR_SIZE_1280X1024:
		width = 1280;
		height = 1024;
		break;

	case PFOUR_SIZE_1600X1280:
		width = 1600;
		height = 1280;
		break;

	case PFOUR_SIZE_1440X1440:
		width = 1440;
		height = 1440;
		break;

	case PFOUR_SIZE_640X480:
		width = 640;
		height = 480;
		break;

	default:

		/*
		 * Use the defaults already filled in by the generic fb code.
		 */

		return;
	}

	fb->fb_type.fb_width = width;
	fb->fb_type.fb_height = height;
#endif /* SUN4 */
}