NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-macppc/48600



The following reply was made to PR port-macppc/48600; it has been noted by GNATS.

From: scole_mail <scole_mail%gmx.com@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: 
Subject: Re: port-macppc/48600
Date: Wed, 29 Oct 2014 16:28:58 -0400

 Here is what I've done so far to get the platinum console working.  8
 bit seems fine, but 16 & 32 bit still have colormap issues.  Files are
 appended below.
 
 Some things I wasn't sure about:
 
 1) What is the framebuffer pixel format?  The 32 & 16 bit depth colors
 sometimes worked, but I was overriding ri_devcmap with CMY. I used
 options RASOPS_SMALL 
 in the kernel to eliminate issues with RI_BSWAP which may not
 correctly tied in for all the rasops*.c files.  I think stamp[] still
 needs to be byteswapped in some places.  Also, what if anything should
 be written to the cmap registers in 16 & 32 bit modes...
 
 2) Is mapiodev() required?  I didn't see it used for any other
 framebuffer drivers so wasn't sure.  Also, I had to use out8/in8/*
 from pio.h when writing hardware registers.
 
 3) Other things I wasn't sure about are marked with XXX
 
 The reason I was attempting to get 16 & 32 bit consoles modes working
 is because I thought it would be easier to do that first, before
 trying for X.
 
 I was still planning to try and see how far I can get with X (at least
 8 bpp), but I'm not really sure what's involved other than what is
 mentioned in wsdisplay(9).  As usual, I'll be glad to test any changes
 and am open to any suggestions.
 
 Feel free to change this code in any way...
 
 Changed files:
  sys/arch/powerpc/oea/ofw_autoconf.c
  sys/arch/macppc/conf/files.macppc
  sys/arch/macppc/conf/GENERIC_601
  sys/dev/wscons/wsconsio.h
  src/sys/dev/rasops/rasops24.c
 New files:
  sys/arch/macppc/dev/platinumfb.c
  sys/arch/macppc/dev/platinumfbreg.h
 
 Index: sys/arch/powerpc/oea/ofw_autoconf.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/powerpc/oea/ofw_autoconf.c,v
 retrieving revision 1.20
 diff -b -u -r1.20 ofw_autoconf.c
 --- sys/arch/powerpc/oea/ofw_autoconf.c	18 Feb 2014 12:27:15 -0000	1.20
 +++ sys/arch/powerpc/oea/ofw_autoconf.c	29 Oct 2014 20:23:36 -0000
 @@ -230,6 +230,14 @@
  		copy_disp_props(dev, ca->ca_node, dict);
  	}
  
 +	/*
 +	 * XXX can't read video properties from openfirmware
 +	 * for platinum.  Will parse some info later in attach function
 +	 */
 +	if (device_is_a(dev, "platinumfb")) {
 +                return;
 +	}
 +
  #if NGTPCI > 0
  	if (device_is_a(dev, "gtpci")) {
  		extern struct gtpci_prot gtpci0_prot, gtpci1_prot;
 Index: sys/arch/macppc/conf/files.macppc
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/macppc/conf/files.macppc,v
 retrieving revision 1.101
 diff -b -u -r1.101 files.macppc
 --- sys/arch/macppc/conf/files.macppc	11 Oct 2014 07:03:09 -0000	1.101
 +++ sys/arch/macppc/conf/files.macppc	29 Oct 2014 20:23:38 -0000
 @@ -307,3 +307,7 @@
  attach valkyriefb at mainbus
  file arch/macppc/dev/valkyriefb.c			valkyriefb
  defflag opt_valkyriefb.h VALKYRIEFB_DEBUG
 +
 +device platinumfb: wsemuldisplaydev, rasops8, rasops15, rasops32, vcons, videomode
 +attach platinumfb at mainbus
 +file arch/macppc/dev/platinumfb.c			platinumfb
 Index: sys/arch/macppc/conf/GENERIC_601
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/macppc/conf/GENERIC_601,v
 retrieving revision 1.7
 diff -b -u -r1.7 GENERIC_601
 --- sys/arch/macppc/conf/GENERIC_601	21 Oct 2014 08:49:55 -0000	1.7
 +++ sys/arch/macppc/conf/GENERIC_601	29 Oct 2014 20:23:40 -0000
 @@ -169,6 +169,7 @@
  options 	WS_DEFAULT_BG=WSCOL_LIGHT_WHITE
  options 	WS_KERNEL_FG=WSCOL_GREEN
  options 	WS_KERNEL_BG=WSCOL_LIGHT_WHITE
 +options         WSDISPLAY_SCROLLSUPPORT
  
  #options 	WSDISPLAY_COMPAT_RAWKBD		# can get raw scancodes
  options 	FONT_GALLANT12x22
 @@ -222,6 +223,12 @@
  # official Macintosh firmware from 3Dfx. The others should work but are
  # untested with OF 1.0.5
  
 +platinumfb* at mainbus?			# platinum built in video
 +
 +# XXX text looks byteswapped in 16/32 depths without this,
 +# think rasops15.c/rasops32.c stamp[] needs some bswapping
 +options RASOPS_SMALL 
 +
  #gffb*		at pci?	function ?	# NVIDIA GeForce2 MX
  #machfb*		at pci? function ?	# ATI Mach 64, Rage, Rage Pro
  #r128fb*		at pci? function ?	# ATI Rage 128
 Index: sys/dev/wscons/wsconsio.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/wscons/wsconsio.h,v
 retrieving revision 1.108
 diff -b -u -r1.108 wsconsio.h
 --- sys/dev/wscons/wsconsio.h	29 Apr 2013 13:39:47 -0000	1.108
 +++ sys/dev/wscons/wsconsio.h	29 Oct 2014 20:23:42 -0000
 @@ -334,6 +334,7 @@
  #define WSDISPLAY_TYPE_OMAP3	57	/* OMAP 3530 */
  #define WSDISPLAY_TYPE_WINDERMERE 58	/* SoC for EPOC32 Series 5mx */
  #define WSDISPLAY_TYPE_CLPS711X	59	/* CL PS-711x  */
 +#define WSDISPLAY_TYPE_PLATINUM	60	/* Apple onboard video 'platinum' */
  
  /* Basic display information.  Not applicable to all display types. */
  struct wsdisplay_fbinfo {
 Index: sys/dev/rasops/rasops24.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/rasops/rasops24.c,v
 retrieving revision 1.29
 diff -b -u -r1.29 rasops24.c
 --- sys/dev/rasops/rasops24.c	25 Jul 2011 18:02:47 -0000	1.29
 +++ sys/dev/rasops/rasops24.c	29 Oct 2014 20:23:44 -0000
 @@ -141,7 +141,7 @@
  	clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf];
  
  	if (uc == ' ') {
 -		u_char c = clr[0];
 +	    u_char c = clr[0]; /* XXX this doesn't look right */
  		while (height--) {
  			dp = rp;
  			rp += ri->ri_stride;
 ===================================================================
 ==== new file
 sys/arch/macppc/dev/platinumfb.c
 ===================================================================
 /*
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 /* A console driver for Apple's Platinum onboard video controller,
  * found in (all?) Catalyst logic boards including the Powermac 7200.
  *
  * Used valkyriefb.c from NetBSD, and platinumfb.c/platinumfb.h from
  * Linux sources as templates.
  *
  * Platinum is broken regarding openfirmware video variables.  In OF,
  * for a powermac 7200, doing "dev /platinum .properties" results in:
  *
  *	name                    platinum
  *	device_type             display
  *	model                   AAPL,343S1184
  *	AAPL,connector          monitor
  *	reg                     F8000000  00000800
  *	                        F1000000  01000000
  *	AAPL,interrupts         0000001E
  *
  * The first reg is the register set, and the second is for the
  * framebuffer.  There is also a set of colormap registers hardcoded
  * in platinumfbreg.h that (I think) aren't in openfirmware.
  *
  * powermac 7200 VRAM min and max limits are 1 and 4 Mb respectively.
  * OF claims 16M so we don't use that value.  If other machines can
  * can have more or less VRAM this code will need to be modified
  */
 
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: platinumfb.c,v 1.1 2014/10/31 12:00:00 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/device.h>
 
 #include <dev/ofw/openfirm.h>
 
 #include <machine/autoconf.h>
 #include <machine/pio.h>
 
 #include <dev/wscons/wsdisplayvar.h>
 #include <dev/wscons/wsconsio.h>
 #include <dev/wsfont/wsfont.h>
 #include <dev/rasops/rasops.h>
 #include <dev/wscons/wsdisplay_vconsvar.h>
 
 #include <dev/videomode/videomode.h>
 
 #include <arch/macppc/dev/platinumfbreg.h>
 
 #include "opt_wsemul.h"
 
 struct platinumfb_setting {
         char vmode_name[24];
 	int32_t width;
 	int32_t height;
     	uint8_t freq;
 	uint8_t macmode;
 
 	int32_t	fb_offset;
 	int32_t	pitch[3];
 	uint32_t regs[26];
 	uint8_t offset[3];
 	uint8_t mode[3];
 	uint8_t dacula_ctrl[3];
 	uint8_t clock_params[2][2];
 };
 
 struct platinumfb_softc {
 	device_t sc_dev;
 	int sc_node;
 
         uint8_t *sc_reg;
 	uint32_t sc_reg_size;
 
     	uint8_t *sc_cmap;
 	uint32_t sc_cmap_size;
 
 	uint8_t *sc_fb;
 	uint32_t sc_fb_size;
 
 	int sc_depth;
 	int sc_width, sc_height, sc_linebytes;
 	const struct videomode *sc_videomode;
 	uint8_t sc_modereg;
 
         int sc_mode;   /* XXX needed ? */
         /* uint32_t sc_bg; */ /* XXX needed ? */
 		
 	u_char sc_cmap_red[256];
 	u_char sc_cmap_green[256];
 	u_char sc_cmap_blue[256];	
 
 	struct vcons_data vd;
 
         uint8_t sc_cmode;
         uint8_t sc_dac_type;
         uint32_t sc_vram;
         struct platinumfb_setting *sc_pfs;
 };
 
 #define DIV2	0x20
 #define DIV4	0x40
 #define DIV8	0x60
 #define DIV16	0x80
 
 static struct platinumfb_setting platinum_5 = {
     "640x480x60",
     640, 480, 60, 5,
     0x1010,
     { 672, 1312, 2592 },
     { 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
       0, 0x15e, 0xc8, 0x18, 0x18f, 0x2f, 0x35, 0x3e,
       0x42, 0x182, 0x18e, 0x41a, 0x418, 2, 7, 0x44,
       0x404, 0x408 }, { 0x34, 0x3c, 0x41 },
     { 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
     {{ 26, 0 + DIV8 }, { 14, 2 + DIV4 }}
 };
 
 static struct platinumfb_setting platinum_12 = {
     "800x600x75",
     800, 600, 75, 12,
     0x1010,
     { 832, 1632, 3232 },
     { 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
       0, 0x1ce, 0x108, 0x14, 0x20f, 0x27, 0x30, 0x39,
       0x72, 0x202, 0x20e, 0x4e2, 0x4e0, 4, 9, 0x2e,
       0x4de, 0x4df }, { 0x64, 0x6c, 0x71 },
     { 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
     {{ 122, 7 + DIV4 }, { 62, 9 + DIV2 }}
 };
 
 static struct platinumfb_setting platinum_14 = {
     "1024x768x60",
     1024, 768, 60, 14,
     0x10b0,
     { 1056, 2080, 4128 },
     { 0xff0, 4, 0, 0, 0, 0, 0x320, 0,
       0, 0x25a, 0x14f, 0x22, 0x29f, 0x43, 0x49, 0x5b,
       0x8e, 0x28e, 0x29e, 0x64c, 0x64a, 0xa, 0xf, 0x44,
       0x644, 0x646 }, { 0x80, 0x88, 0x8d },
     { 2, 0, 0xff }, { 0x11, 0x15, 0x19 },
     {{ 71, 6 + DIV2 }, { 118, 13 + DIV2 }}
 };
 
 static struct platinumfb_setting platinum_20 = {
     "1280x1024x75",
     1280, 1024, 75, 20,
     0x5c00,
     { 1312, 2592, 2592 },
     { 0xffc, 4, 0, 0, 0, 0, 0x428, 0,
       0, 0xb3, 0xd3, 0x12, 0x1a5, 0x23, 0x28, 0x2d,
       0x5e, 0x19e, 0x1a4, 0x854, 0x852, 4, 9, 0x50,
       0x850, 0x851 }, { 0x58, 0x5d, 0x5d },
     { 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 },
     {{ 45, 3 }, { 66, 7 }}
 };
 
 static struct platinumfb_setting *pfb_setting[] = {
     &platinum_5,
     &platinum_12,
     &platinum_14,
     &platinum_20
 };
 
 static struct vcons_screen platinumfb_console_screen;
 
 static int	platinumfb_match(device_t, cfdata_t, void *);
 static void	platinumfb_attach(device_t, device_t, void *);
 static int	platinumfb_init(device_t);
 static int 	platinumfb_set_mode(struct platinumfb_softc *,
 		    const struct videomode *, int);
 
 CFATTACH_DECL_NEW(platinumfb, sizeof(struct platinumfb_softc),
     platinumfb_match, platinumfb_attach, NULL, NULL);
 
 struct wsscreen_descr platinumfb_defaultscreen = {
 	"default",
 	0, 0,
 	NULL,
 	8, 16,
 	WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
 	NULL,
 };
 
 const struct wsscreen_descr *_platinumfb_scrlist[] = {
 	&platinumfb_defaultscreen,
 	/* XXX other formats, graphics screen? */
 };
 
 struct wsscreen_list platinumfb_screenlist = {
 	sizeof(_platinumfb_scrlist) / sizeof(struct wsscreen_descr *),
 	_platinumfb_scrlist
 };
 
 static int	platinumfb_ioctl(void *, void *, u_long, void *, int,
 		    struct lwp *);
 static paddr_t	platinumfb_mmap(void *, void *, off_t, int);
 static void	platinumfb_init_screen(void *, struct vcons_screen *, int,
 			    long *);
 struct wsdisplay_accessops platinumfb_accessops = {
 	platinumfb_ioctl,
 	platinumfb_mmap,
 	NULL,
 	NULL,
 	NULL,
 	NULL,	/* load_font */
 	NULL,	/* polls */
 	NULL,	/* scroll */
 };
 
 static inline void
 platinumfb_write_reg(struct platinumfb_softc *sc, int reg, uint32_t val)
 {
     out32(sc->sc_reg + PLATINUM_REG_OFFSET_ADDR(reg), val);
 }
 
 static inline uint32_t
 platinumfb_read_reg(struct platinumfb_softc *sc, int reg)
 {
     return in32(sc->sc_reg + PLATINUM_REG_OFFSET_ADDR(reg));
 }
 
 static inline void
 platinumfb_write_cmap_reg(struct platinumfb_softc *sc, 
 			  int reg_offset, uint8_t val)
 {
     out8(sc->sc_cmap + reg_offset, val);
 }
 
 static inline uint8_t
 platinumfb_read_cmap_reg(struct platinumfb_softc *sc, int reg_offset)
 {
     return in8(sc->sc_cmap + reg_offset);
 }
 
 static inline void
 platinumfb_store_d2(struct platinumfb_softc *sc, 
 			  uint8_t a, uint8_t d)
 {
     platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_ADDR_OFFSET, a + 32);
     platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_D2_OFFSET, d);
 }
 
 static void
 platinumfb_write_cmap(struct platinumfb_softc *sc,
     int reg, uint8_t r, uint8_t g, uint8_t b)
 {
     platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_ADDR_OFFSET, reg);
     platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_LUT_OFFSET, r);
     platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_LUT_OFFSET, g);
     platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_LUT_OFFSET, b);
 }
 
 static uint32_t
 platinumfb_fb_offset_tweak(struct platinumfb_softc *sc)
 {
     char* vmode = sc->sc_pfs->vmode_name;
     uint32_t offset = 0x20;
 
     if ((strcmp(vmode, "832x624x75") == 0) && (sc->sc_cmode > 0))
 	offset = 0x10;
 
     return offset;
 }
 
 /* 2 versions of platinum clock, older one uses clock[1] and
  *     freq = 14.3Mhz * c0 / (c1 & 0x1f) / (1 << (c1 >> 5))
  * newer one uses clock[0] and
  *     freq = 15Mhz * c0 / ((c1 & 0x1f) + 2) / (1 << (c1 >> 5))
  */
 static void
 platinumfb_set_clock(struct platinumfb_softc *sc)
 {
     uint8_t clk_idx = sc->sc_dac_type == PLATINUM_DAC_1 ? 1 : 0;
     uint8_t d2;
  
     platinumfb_store_d2(sc, 6, 0xc6);
  
     platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_ADDR_OFFSET, 3+32);
     d2 = platinumfb_read_cmap_reg(sc, PLATINUM_CMAP_D2_OFFSET);
 
     if (d2 == 2) {
 	platinumfb_store_d2(sc, 7, sc->sc_pfs->clock_params[clk_idx][0]);
 	platinumfb_store_d2(sc, 8, sc->sc_pfs->clock_params[clk_idx][1]);
 	platinumfb_store_d2(sc, 3, 3);
     } else {
 	platinumfb_store_d2(sc, 4, sc->sc_pfs->clock_params[clk_idx][0]);
 	platinumfb_store_d2(sc, 5, sc->sc_pfs->clock_params[clk_idx][1]);
 	platinumfb_store_d2(sc, 3, 2);
     }
 
     delay(5000);
     platinumfb_store_d2(sc, 9, 0xa6);
 }
 
 static void
 platinumfb_dac_type(struct platinumfb_softc *sc)
 {
     uint8_t dtype = 0;
     
     platinumfb_write_cmap_reg(sc, PLATINUM_CMAP_ADDR_OFFSET, 0x40);
     dtype = platinumfb_read_cmap_reg(sc, PLATINUM_CMAP_D2_OFFSET);
 
     switch (dtype) {
     case PLATINUM_DAC_0:
     case PLATINUM_DAC_1:
 	/* do nothing */
 	break;
     default:
 	aprint_error_dev(sc->sc_dev, "unknown dac 0x%x, using 0x%x\n",
 			 dtype, PLATINUM_DAC_0);
 	dtype = PLATINUM_DAC_0;
 	break;
     }
 
     /* save type */
     sc->sc_dac_type = dtype;
 }
 
 static void
 platinumfb_memory_size(struct platinumfb_softc *sc)
 {
     int i;
     uint32_t addr = PLATINUM_FB_BANK_SIZE;
     uint32_t total_vram = PLATINUM_FB_MIN_SIZE;
 
     uint8_t test_val[] = {0x34, 0x56, 0x78};
     uint8_t bank[] = {0, 0, 0};
     uint8_t num_elems = sizeof(test_val)/sizeof(test_val[0]);
 
     /* XXX mapiodev needed ? */
     volatile uint8_t *fbuffer = mapiodev((paddr_t)sc->sc_fb, sc->sc_fb_size, false);
 
     if (fbuffer == NULL)
 	panic("could not mapiodev platinum fb");
 
     /* turn on all banks of RAM */
     platinumfb_write_reg(sc, 16, (paddr_t)sc->sc_fb);
     platinumfb_write_reg(sc, 20, 0x1011);
     platinumfb_write_reg(sc, 24, 0);
 
     /*
      * write "unique" value to each bank of memory and read value
      * back. if match assumes VRAM bank exists.  On the powermac 7200,
      * bank0 is always there and soldered to motherboard, don't know
      * if that is the case for others
      */
     for (i = 0 ; i < num_elems; i++) {
 	out8(fbuffer + addr, test_val[i]);
 	out8(fbuffer + addr + 0x8, 0x0);
 
 	__asm volatile ("eieio; dcbf 0,%0"::"r"(&fbuffer[addr]):"memory"); /* XXX ok? */
 
 	bank[i] = fbuffer[addr] == test_val[i];
 	total_vram += bank[i] * PLATINUM_FB_BANK_SIZE;
 	addr += PLATINUM_FB_BANK_SIZE;
     }
 
     if (total_vram >= PLATINUM_FB_MIN_SIZE && total_vram <= PLATINUM_FB_MAX_SIZE) {
 	/* save total vram */
 	sc->sc_vram = total_vram;
     } else {
 	aprint_error_dev(sc->sc_dev,
 			 "invalid VRAM size 0x%x, using min 0x%x\n",
 			 total_vram, PLATINUM_FB_MIN_SIZE);
 	sc->sc_vram = PLATINUM_FB_MIN_SIZE;
     }
 
     unmapiodev((paddr_t)fbuffer, sc->sc_fb_size);
 }
 
 static int
 platinumfb_match(device_t parent, cfdata_t cf, void *aux)
 {
 	struct confargs *ca = aux;
 
 	return (strcmp(ca->ca_name, "platinum") == 0);
 }
 
 static void
 platinumfb_attach(device_t parent, device_t self, void *aux)
 {
 	struct platinumfb_softc *sc = device_private(self);
 	struct confargs *ca = aux;
 	u_int *reg = ca->ca_reg;
 
 	sc->sc_dev = self;
 	sc->sc_node = ca->ca_node;
 
 	sc->sc_reg = (uint8_t *)reg[0];
 	sc->sc_reg_size = reg[1];
 
 	sc->sc_fb = (uint8_t *)reg[2];
 	sc->sc_fb_size = PLATINUM_FB_MAX_SIZE;
 
 	sc->sc_cmap = (uint8_t *)PLATINUM_CMAP_BASE_ADDR;
 	sc->sc_cmap_size = PLATINUM_CMAP_SIZE;
 
 	aprint_normal(" reg-addr 0x%08lx fb-addr 0x%08lx cmap-addr 0x%08lx\n",
 		      (paddr_t)sc->sc_reg, 
 		      (paddr_t)sc->sc_fb,
 		      (paddr_t)sc->sc_cmap);
 
 	config_finalize_register(sc->sc_dev, platinumfb_init);
 }
 
 static void
 platinumfb_set_cmap(struct platinumfb_softc *sc)
 {
     int i;
     uint8_t tmp;
 
     switch (sc->sc_cmode) {
     case PLATINUM_CMODE_8:
     default:
 	for (i = 0; i < 256; i++) {
 	    tmp = i & 0xe0;
 	    /*
 	     * replicate bits so 0xe0 maps to a red value of 0xff
 	     * in order to make white look actually white
 	     */
 	    tmp |= (tmp >> 3) | (tmp >> 6);
 	    sc->sc_cmap_red[i] = tmp;
 
 	    tmp = (i & 0x1c) << 3;
 	    tmp |= (tmp >> 3) | (tmp >> 6);
 	    sc->sc_cmap_green[i] = tmp;
 
 	    tmp = (i & 0x03) << 6;
 	    tmp |= tmp >> 2;
 	    tmp |= tmp >> 4;
 	    sc->sc_cmap_blue[i] = tmp;
 
 	    platinumfb_write_cmap(sc, i, sc->sc_cmap_red[i],
 				  sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
 	}
 	break;
     case PLATINUM_CMODE_16: 
     case PLATINUM_CMODE_32:
 	/* XXX what to do for this, need to write cmap registers ? */
 	for (i = 0; i < 256; i++) {
 	    sc->sc_cmap_red[i] = i;
 	    sc->sc_cmap_green[i] = i;
 	    sc->sc_cmap_blue[i] = i;
 	}
 	break;
     }
 }
 
 static int
 platinumfb_init(device_t self)
 {
 	struct platinumfb_softc *sc = device_private(self);
 	const struct videomode *mode;
 	struct rasops_info *ri;
 
 	struct wsemuldisplaydev_attach_args aa;
 	bool console = FALSE;
 	long defattr;
 	int i;
 
 	/*
 	 * become console if OF variable "output-device" is "screen" or
 	 * contains "platinum", since normal OF video variables are unavailable
 	 */
 	int options;
 	char output_device[128];
 	options = OF_finddevice("/options");
 	if (options == 0 || 
 	    options == -1 ||
 	    OF_getprop(options, "output-device", output_device, sizeof(output_device)) == 0 ) {
 	    aprint_error_dev(sc->sc_dev, "could not get output-device prop, assuming not console\n");
 	}
 	else {
 	    if (strstr(output_device,"platinum") ||
 		strcmp(output_device,"screen") == 0 ) {
 		console = TRUE;
 	    }
 	}	
 
 	sc->sc_pfs = NULL;
 
 	/* determine vram memory and dac clock type */
 	platinumfb_memory_size(sc);
 	platinumfb_dac_type(sc);
 
 	aprint_normal_dev(sc->sc_dev,"console %d dac 0x%x vram 0x%x\n",
 			  console, sc->sc_dac_type, sc->sc_vram);
 	
 	/* XXX */
 	/* mode = pick_mode_by_ref(640, 480, 60); */
 	mode = pick_mode_by_ref(800, 600, 75);
 	/* mode = pick_mode_by_ref(1024, 768, 60); */
 	/* mode = pick_mode_by_ref(1280, 1024, 75); */
 	if (mode == NULL) {
 	    aprint_error_dev(sc->sc_dev, "pick_mode_by_ref failed\n");
 	    return 0;
 	}
 
 	if (
 	    /* XXX */
 	    /* platinumfb_set_mode(sc, mode, 32) != 0 */
 	    /* platinumfb_set_mode(sc, mode, 16) != 0 */
 	    platinumfb_set_mode(sc, mode, 8) != 0
 	    )	
 	{
 	    aprint_error_dev(sc->sc_dev, "platinumfb_set_mode failed\n");
 	    return 0;
 	}
 
 	vcons_init(&sc->vd, sc, &platinumfb_defaultscreen,
 		   &platinumfb_accessops);
 	sc->vd.init_screen = platinumfb_init_screen;
 
 	ri = &platinumfb_console_screen.scr_ri;
 	vcons_init_screen(&sc->vd, &platinumfb_console_screen, 1, &defattr);
 
 	switch(sc->sc_cmode) {
 	case PLATINUM_CMODE_8:
 	default:
 	    memset(sc->sc_fb,
 		   (uint8_t)(ri->ri_devcmap[(defattr >> 16) & 0xf] & 0xff),
 		   sc->sc_width * sc->sc_linebytes);
 	    break;
 	case PLATINUM_CMODE_16:
 	    for (i = 0 ; i < sc->sc_vram ; i+=2)
 		*(uint16_t *)(sc->sc_fb + i) = 
 		    (uint16_t)(ri->ri_devcmap[(defattr >> 16) & 0xf] & 0xffff);
 	    break;
 	case PLATINUM_CMODE_32:
 	    for (i = 0 ; i < sc->sc_vram ; i+=4)
 		*(uint32_t *)(sc->sc_fb + i) = 
 		    (uint32_t)(ri->ri_devcmap[(defattr >> 16) & 0xf]);
 	    break;
 	}
 
 	platinumfb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
 
 	platinumfb_defaultscreen.textops = &ri->ri_ops;
 	platinumfb_defaultscreen.capabilities = ri->ri_caps;
 	platinumfb_defaultscreen.nrows = ri->ri_rows;
 	platinumfb_defaultscreen.ncols = ri->ri_cols;
 
 	if (console) {
 		wsdisplay_cnattach(&platinumfb_defaultscreen, ri, 0, 0,
 		    defattr);
 		vcons_replay_msgbuf(&platinumfb_console_screen);
 	}
 
 	aa.console = console;
 	aa.scrdata = &platinumfb_screenlist;
 	aa.accessops = &platinumfb_accessops;
 	aa.accesscookie = &sc->vd;
 
 	config_found(self, &aa, wsemuldisplaydevprint);
 
 	return 0;
 }
 
 static int
 platinumfb_set_mode(struct platinumfb_softc *sc,
     const struct videomode *mode, int depth)
 {
         int i;
 	bool one_bank;
 
 	/* determine depth settings */
 	switch (depth) {
 	case 8:
 	    sc->sc_cmode = PLATINUM_CMODE_8;
 	    sc->sc_depth = 8;
 	    break;
 	case 15:
 	case 16:
 	    sc->sc_cmode = PLATINUM_CMODE_16;
 	    sc->sc_depth = 15; /* XXX or 16 ? */
 	    break;
 	case 24:
 	case 32:
 	    sc->sc_cmode = PLATINUM_CMODE_32;
 	    sc->sc_depth = 32; /* XXX or 24? */
 	    break;
 	default:
 	    aprint_error_dev(sc->sc_dev, "unknown depth [%d] using 8\n", depth);
 	    sc->sc_cmode = PLATINUM_CMODE_8;
 	    sc->sc_depth = 8;
 	    break;
 	}
 
 	/* first find the parameter for the mode register */
 	i = 0;
 	while((i < __arraycount(pfb_setting)) &&
 	      (strcmp(mode->name, pfb_setting[i]->vmode_name) != 0))
 	    i++;
 
 	if (i >= __arraycount(pfb_setting)) {
 		aprint_error_dev(sc->sc_dev,
 		    "Can't find a mode register value for %s\n", 
 				 mode->name);
 		return EINVAL;
 	} 
 
 	/* check if we have enough video memory */
 	if ((mode->hdisplay * mode->vdisplay * (depth >> 3) + pfb_setting[i]->fb_offset) > 
 	    sc->sc_vram) {
 	    aprint_error_dev(sc->sc_dev, "Not enough video RAM for %s\n",
 			     mode->name);
 	    return EINVAL;
 	}
 
 	/* found a mode */
 	sc->sc_pfs = pfb_setting[i];
 
 	platinumfb_set_cmap(sc);
 
 	one_bank = sc->sc_vram == PLATINUM_FB_BANK_SIZE;
 
 	/* now start programming the chip */
 	platinumfb_write_reg(sc, 24, 7);    /* turn off display */
 
 	for (i = 0; i < 26; ++i)
 	    platinumfb_write_reg(sc, i+32, sc->sc_pfs->regs[i]);
 
 	platinumfb_write_reg(sc, 26+32, one_bank ? sc->sc_pfs->offset[sc->sc_cmode] + 4 - sc->sc_cmode :
 			                           sc->sc_pfs->offset[sc->sc_cmode]);
 
 	platinumfb_write_reg(sc, 16, (uint32_t)sc->sc_fb + sc->sc_pfs->fb_offset + 0x10);
 	platinumfb_write_reg(sc, 18, sc->sc_pfs->pitch[sc->sc_cmode]);
 	platinumfb_write_reg(sc, 19, one_bank ? sc->sc_pfs->mode[sc->sc_cmode+1] :
 			                        sc->sc_pfs->mode[sc->sc_cmode]);
 
 	platinumfb_write_reg(sc, 20, one_bank ? 0x11 : 0x1011);
 	platinumfb_write_reg(sc, 21, 0x100);
 	platinumfb_write_reg(sc, 22, 1);
 	platinumfb_write_reg(sc, 23, 1);
 	platinumfb_write_reg(sc, 26, 0xc00);
 	platinumfb_write_reg(sc, 27, 0x235);
 	/* platinumfb_write_reg(sc, 27, 0x2aa); */
 
 	platinumfb_store_d2(sc, 0, one_bank ? sc->sc_pfs->dacula_ctrl[sc->sc_cmode] & 0xf :
 			                      sc->sc_pfs->dacula_ctrl[sc->sc_cmode]);
 	platinumfb_store_d2(sc, 1, 4);
 	platinumfb_store_d2(sc, 2, 0);
 
 	platinumfb_set_clock(sc);
 
 	platinumfb_write_reg(sc, 24, 0);  /* turn display on */
 
 	sc->sc_modereg = sc->sc_pfs->macmode;
 	sc->sc_videomode = mode;
 	sc->sc_width = mode->hdisplay;
 	sc->sc_height = mode->vdisplay;
 	sc->sc_linebytes = mode->hdisplay * (1 << sc->sc_cmode) + platinumfb_fb_offset_tweak(sc);
 
 	aprint_normal_dev(sc->sc_dev, "switched to %s in %d bit color\n",
 			  sc->sc_pfs->vmode_name, sc->sc_depth);
 	return 0;
 }
 
 static int
 platinumfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
 	struct lwp *l)
 {
 	struct vcons_data *vd = v;
 	struct platinumfb_softc *sc = vd->cookie;
 	struct wsdisplay_fbinfo *wdf;
 	struct vcons_screen *ms = vd->active;
 
 	switch (cmd) {
 	case WSDISPLAYIO_GTYPE:
 		*(u_int *)data = WSDISPLAY_TYPE_PLATINUM;
 		return 0;
 
 	case WSDISPLAYIO_GINFO:
 		wdf = (void *)data;
 		wdf->height = ms->scr_ri.ri_height;
 		wdf->width = ms->scr_ri.ri_width;
 		wdf->depth = ms->scr_ri.ri_depth;
 		wdf->cmsize = 256;
 		return 0;
 
 	case WSDISPLAYIO_GET_FBINFO: {
 	    struct wsdisplayio_fbinfo *fbi = data;
 	    return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
 	}
 
 	case WSDISPLAYIO_LINEBYTES:
 	        *(u_int *)data = sc->sc_linebytes;
 		return 0;
 
 	case WSDISPLAYIO_SMODE: {
 		int new_mode = *(int*)data;
 		if (new_mode != sc->sc_mode) {
 			sc->sc_mode = new_mode;
 			if (new_mode == WSDISPLAYIO_MODE_EMUL) {
 				vcons_redraw_screen(ms);
 			}
 		}
 		}
 		return 0;
 	}
 	return EPASSTHROUGH;
 }
 
 static paddr_t
 platinumfb_mmap(void *v, void *vs, off_t offset, int prot)
 {
 	struct vcons_data *vd = v;
 	struct platinumfb_softc *sc = vd->cookie;
 	off_t fb_offset = sc->sc_pfs->fb_offset;
 	paddr_t pa = -1;
 
 	/* XXX need to worry about superuser, or mapping other registers? */
 
 	/* regular framebuffer mmap()ing */
 	if (offset >= 0 && 
 	    (offset < (sc->sc_vram - fb_offset - platinumfb_fb_offset_tweak(sc))))
 	{
 	    pa = (paddr_t)(sc->sc_fb + fb_offset + offset);
 	}
 
 	return pa;
 }
 
 static void
 platinumfb_init_screen(void *cookie, struct vcons_screen *scr,
     int existing, long *defattr)
 {
 	struct platinumfb_softc *sc = cookie;
 	struct rasops_info *ri = &scr->scr_ri;
 
 	memset(ri, 0, sizeof(struct rasops_info));
 	ri->ri_depth = sc->sc_depth;
 	ri->ri_width = sc->sc_width;
 	ri->ri_height = sc->sc_height;
 	ri->ri_stride = sc->sc_linebytes;
 	ri->ri_bits = sc->sc_fb + sc->sc_pfs->fb_offset + platinumfb_fb_offset_tweak(sc);
 	ri->ri_flg = RI_CENTER;
 
 	switch (sc->sc_cmode) {
 	case PLATINUM_CMODE_8:
 	default:
 	    /* 640x480x60 800x600x75 1024x768x60 1280x1024x75 worked */
 	    ri->ri_flg |= RI_ENABLE_ALPHA | RI_8BIT_IS_RGB;
 	    break;
 	case PLATINUM_CMODE_16:
 	    /* XXX stamp[] in rasops*.c may need bytes swapped somehow */
 	    /* ri->ri_flg |= RI_BSWAP; */
 
 	    /* 1024x768x60 didn't work with this flag,
 	       not enough vram to test 1280x1024x75 */
 	    if ( strcmp(sc->sc_pfs->vmode_name,"640x480x60") == 0 ||
 		 strcmp(sc->sc_pfs->vmode_name,"800x600x75") == 0 )
 		ri->ri_flg |= RI_ENABLE_ALPHA;
 
 	    break;
 	case PLATINUM_CMODE_32:
 	    /* XXX stamp[] in rasops*.c may need bytes swapped somehow */
 	    /*ri->ri_flg |= RI_BSWAP; */
 
 	    /* 640x480x60 800x600x75 worked with this flag,
 	       not enough vram to test others */
 	    if ( strcmp(sc->sc_pfs->vmode_name,"640x480x60") == 0 ||
 		 strcmp(sc->sc_pfs->vmode_name,"800x600x75") == 0 )
 		ri->ri_flg |= RI_ENABLE_ALPHA;
 
 	    break;
 	}
 
 	scr->scr_flags |= VCONS_DONT_READ;
 	
 	rasops_init(ri, 0, 0);
 	ri->ri_caps = WSSCREEN_WSCOLORS;
 
 	rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
 		    sc->sc_width / ri->ri_font->fontwidth);
 
 	ri->ri_hw = scr;
 
 	/* XXX override colormap for 16 & 32 bit, which seems to be CMY, but 8 bit is RGB?? */
 	if (ri->ri_depth >= 24)	{
 	    /* 32 bit no swap */
 	    /* XXX sometimes works, sometimes background looks yellow */
 	    ri->ri_devcmap[0] = 0x007f7f7f; // black
 	    ri->ri_devcmap[1] = 0x00007f7f; // red
 	    ri->ri_devcmap[2] = 0x007f007f; // green
 	    ri->ri_devcmap[3] = 0x0000007f; // yellow
 	    ri->ri_devcmap[4] = 0x007f7f00; // blue
 	    ri->ri_devcmap[5] = 0x00007f00; // magenta
 	    ri->ri_devcmap[6] = 0x007f0000; // cyan
 	    ri->ri_devcmap[7] = 0x00000000; // grey/white
 
 	    ri->ri_devcmap[8] = 0x00ffffff; // black
 	    ri->ri_devcmap[9] = 0x0000ffff; // red
 	    ri->ri_devcmap[10] = 0x00ff00ff; // green
 	    ri->ri_devcmap[11] = 0x000000ff; // yellow
 	    ri->ri_devcmap[12] = 0x00ffff00; // blue
 	    ri->ri_devcmap[13] = 0x0000ff00; // magenta
 	    ri->ri_devcmap[14] = 0x00ff0000; // cyan
 	    ri->ri_devcmap[15] = 0x00000000; // white
 	} 
 	else if (ri->ri_depth >= 15)	{
 	    /* 15 bit no swap */
 	    /* XXX don't understand how to get a good black or why white is 0x0003 */
 	    ri->ri_devcmap[0] = 0x3def3def; // black
 	    ri->ri_devcmap[1] = 0x01ef01ef; // red
 	    ri->ri_devcmap[2] = 0x3c0f3c0f; // green
 	    ri->ri_devcmap[3] = 0x000f000f; // yellow
 	    ri->ri_devcmap[4] = 0x3de03de0; // blue
 	    ri->ri_devcmap[5] = 0x01e001e0; // magenta
 	    ri->ri_devcmap[6] = 0x3c003c00; // cyan
 	    ri->ri_devcmap[7] = 0x00020002; // grey/white
 
 	    ri->ri_devcmap[8]  = 0x7fff7fff; // black
 	    ri->ri_devcmap[9]  = 0x03ff03ff; // red
 	    ri->ri_devcmap[10] = 0x7c1f7c1f; // green
 	    ri->ri_devcmap[11] = 0x001f001f; // yellow
 	    ri->ri_devcmap[12] = 0x7fe07fe0; // blue
 	    ri->ri_devcmap[13] = 0x03e003e0; // magenta
 	    ri->ri_devcmap[14] = 0x7c007c00; // cyan
 	    ri->ri_devcmap[15] = 0x00030003; // white
 	}
 
 }
 ===================================================================
 ==== new file
 sys/arch/macppc/dev/platinumfbreg.h
 ===================================================================
 /*
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: platinumfbreg.h,v 1.1 2014/10/31 12:00:00 macallan Exp $");
 
 #ifndef PLATINUMFBREG_H
 #define PLATINUMFBREG_H
 
 /*
  * platinum register address offsets.
  * registers are each 32 bits with 12*8bits of padding,
  * 128 registers total
  */
 #define PLATINUM_REG_OFFSET_ADDR(x) (x * 0x10)
 #define PLATINUM_REG_COUNT          128
 
 /*
  * colormap register addresses.
  * registers are each 8 bits with 15*8 bits of padding
  */
 #define PLATINUM_CMAP_BASE_ADDR   0xf301b000 /* XXX not in ofw ? */
 #define PLATINUM_CMAP_ADDR_OFFSET 0x00000000
 #define PLATINUM_CMAP_D1_OFFSET   0x00000010
 #define PLATINUM_CMAP_D2_OFFSET   0x00000020
 #define PLATINUM_CMAP_LUT_OFFSET  0x00000030
 #define PLATINUM_CMAP_SIZE        0x1000     /* XXX ofw says 0x800? */
 
 /* framebuffer */
 #define PLATINUM_FB_BANK_SIZE 0x100000
 #define PLATINUM_FB_MIN_SIZE (1 * PLATINUM_FB_BANK_SIZE)
 #define PLATINUM_FB_MAX_SIZE (4 * PLATINUM_FB_BANK_SIZE)
 
 /* depth/colormodes */
 #define PLATINUM_CMODE_8  0
 #define PLATINUM_CMODE_16 1
 #define PLATINUM_CMODE_32 2
 
 /* DACula types */
 #define PLATINUM_DAC_0 0x84
 #define PLATINUM_DAC_1 0x3c
 
 #endif /* PLATINUMFBREG_H */
 


Home | Main Index | Thread Index | Old Index