Here's an attempt to bloat the linux source a bit more ;-)
This patch brings, yet missing, parts that make a Linux-driven Indigo2
Impact (IP28 and most probably IP22-Impact) an usable desktop-machine
"out of the box".
The driver provides the framebuffer console and an interface for the
Xserver (mmap'ing a DMA-pool to the shadow framebuffer and doing the
necessary cacheflush).
Meanwhile only a few files are affected and obviously no side-effects
to other parts of the kernel are to be expected.
BTW: it would be appreciated, if someone could verify, that this driver
also works for IP22 Impact.
Signed-off-by: peter fuerst <post@pfrst.de>
---
1) Preparation
drivers/video/Kconfig | 6 ++++++
drivers/video/Makefile | 1 +
drivers/video/logo/Kconfig | 2 +-
arch/mips/sgi-ip22/ip22-setup.c | 37 +++++++++++++++++++++++++++++++++++++
arch/mips/configs/ip28_defconfig | 1 +
5 files changed, 46 insertions(+), 1 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 549b960..43dbc9f 100644
--- a/drivers/video/Kconfig Thu Jan 1 00:00:00 1970
+++ b/drivers/video/Kconfig Thu Mar 10 23:37:58 2011
@@ -2383,6 +2383,12 @@ config FB_PUV3_UNIGFX
Choose this option if you want to use the Unigfx device as a
framebuffer device. Without the support of PCI & AGP.
+config FB_IMPACT
+ tristate "SGI Indigo2 Impact graphics support"
+ depends on FB && (SGI_IP22 || SGI_IP28 || SGI_IP30)
+ help
+ SGI Indigo2 Impact (SI/HI/MI) graphics card support.
+
source "drivers/video/omap/Kconfig"
source "drivers/video/omap2/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 8b83129..278c8fa 100644
--- a/drivers/video/Makefile Thu Jan 1 00:00:00 1970
+++ b/drivers/video/Makefile Thu Mar 10 23:44:40 2011
@@ -141,6 +141,7 @@ obj-$(CONFIG_FB_MSM) += msm/
obj-$(CONFIG_FB_NUC900) += nuc900fb.o
obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
+obj-$(CONFIG_FB_IMPACT) += impact.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_UVESA) += uvesafb.o
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 39ac49e..3ac6da4 100644
--- a/drivers/video/logo/Kconfig Thu Jan 1 00:00:00 1970
+++ b/drivers/video/logo/Kconfig Fri May 8 00:51:01 2009
@@ -54,7 +54,7 @@ config LOGO_PARISC_CLUT224
config LOGO_SGI_CLUT224
bool "224-color SGI Linux logo"
- depends on SGI_IP22 || SGI_IP27 || SGI_IP32 || X86_VISWS
+ depends on SGI_IP22 || SGI_IP27 || SGI_IP28 || SGI_IP30 || SGI_IP32 ||
X86_VISWS
default y
config LOGO_SUN_CLUT224
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index 5e66213..085b612 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c Thu Jan 1 00:00:00 1970
+++ b/arch/mips/sgi-ip22/ip22-setup.c Fri May 8 01:05:13 2009
@@ -96,4 +96,41 @@ void __init plat_mem_setup(void)
}
}
#endif
+#if defined(CONFIG_FB_IMPACT)
+ {
+ extern void setup_impact_earlycons(void);
+ /*
+ * Get graphics info before it is overwritten...
+ * E.g. @ 9000000020f02f78: ffffffff9fc6d770,900000001f000000
+ */
+#ifdef CONFIG_ARC64
+ ULONG * (*__vec)(void) = (typeof(__vec))
+ ((ULONG*)PROMBLOCK->pvector)[8];
+ ULONG *gfxinfo = (*__vec)();
+#else
+ /* supposed to work on both 32/64-bit kernels. */
+ int (*__vec)(void) = (typeof(__vec))
+ (long) ((int*)PROMBLOCK->pvector)[8];
+ int *gfxinfo = (typeof(gfxinfo)) (*__vec)();
+#endif
+ /* See note on __pa() in impact.c */
+ sgi_gfxaddr = __pa((void*)gfxinfo[1]);
+ if (sgi_gfxaddr < 0x1f000000 || 0x1fa00000 <= sgi_gfxaddr)
+ sgi_gfxaddr = 0;
+ /*
+ * Early params are not yet avaialble, so this setting
+ * must be done in the ARCS environment.
+ */
+ ctype = ArcGetEnvironmentVariable("OSLoadOptions");
+ if (!ctype || !strstr(ctype, "impact=noearly"))
+#ifndef CONFIG_EARLY_PRINTK
+ if (ctype && strstr(ctype, "impact=early"))
+#endif
+ setup_impact_earlycons();
+
+ printk(KERN_DEBUG "ARCS gfx info @ %p: %p,%p\n",
+ gfxinfo, (void*)gfxinfo[0], (void*)gfxinfo[1]);
+ printk(KERN_INFO "SGI graphics system @ 0x%08lx\n",
sgi_gfxaddr);
+ }
+#endif
}
diff --git a/arch/mips/configs/ip28_defconfig b/arch/mips/configs/ip28_defconfig
index 4dbf626..b316c86 100644
--- a/arch/mips/configs/ip28_defconfig
+++ b/arch/mips/configs/ip28_defconfig
@@ -78,3 +78,4 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HW is not set
# CONFIG_CRC32 is not set
+CONFIG_FB_IMPACT=y
2) The driver
drivers/video/impact.c | 1154 ++++++++++++++++++++++++++++++++++++++++++++++++
include/video/impact.h | 210 +++++++++
2 files changed, 1364 insertions(+), 0 deletions(-)
diff --git a/drivers/video/impact.c b/drivers/video/impact.c
new file mode 100644
index 0000000..5ffc948
--- /dev/null Wed Dec 8 00:46:04 2004
+++ b/drivers/video/impact.c Mon Jul 25 00:06:58 2011
@@ -0,0 +1,1154 @@
+/*
+ * linux/drivers/video/impactsr.c -- SGI Octane MardiGras (IMPACTSR) graphics
+ * linux/drivers/video/impact.c -- SGI Indigo2 MardiGras (IMPACT) graphics
+ *
+ * Copyright (c) 2004-2006 by Stanislaw Skowronek (skylark@linux-mips.org)
+ * Adapted to Indigo2 by pf, 2005,2006,2009,2011 (post@pfrst.de)
+ *
+ * Based on linux/drivers/video/skeletonfb.c
+ *
+ * This driver, as most of the IP30 (SGI Octane) port, is a result of massive
+ * amounts of reverse engineering and trial-and-error. If anyone is interested
+ * in helping with it, please contact me: <skylark@linux-mips.org>.
+ *
+ * The basic functions of this driver are filling and blitting rectangles.
+ * To achieve the latter, two DMA operations are used on Impact. It is unclear
+ * to me, why is it so, but even Xsgi (the IRIX X11 server) does it this way.
+ * It seems that fb->fb operations are not operational on these cards.
+ *
+ * For this purpose, a kernel DMA pool is allocated (pool number 0). This pool
+ * is (by default) 64kB in size. An ioctl could be used to set the value at
+ * run-time. Applications can use this pool, however proper locking has to be
+ * guaranteed. Kernel should be locked out from this pool by an ioctl.
+ *
+ * The IMPACTSR is quite well worked-out currently, except for the Geometry
+ * Engines (GE11). Any information about use of those devices would be very
+ * useful. It would enable a Linux OpenGL driver, as most of OpenGL calls are
+ * supported directly by the hardware. So far, I can't initialize the GE11.
+ * Verification of microcode crashes the graphics.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/font.h>
+#include <linux/platform_device.h>
+#include <linux/console.h>
+#include <linux/version.h>
+
+#ifndef CONFIG_64BIT
+#error (S)he, who can afford Impact-graphics, shall afford a 64bit-kernel also!
+#endif
+#ifdef CONFIG_SGI_IP30
+# include <asm/mach-ip30/xtalk.h>
+# define IPNR 30
+#else
+# if defined(CONFIG_SGI_IP22)
+# define IPNR 22
+# elif defined(CONFIG_SGI_IP26)
+# define IPNR 26
+# else
+# define IPNR 28
+# endif
+#endif
+#define isSR (IPNR > 28) /* avoid nasty #if... where possible. */
+#include <video/impact.h>
+
+/* Some fixed register values. */
+
+#if isSR /* ImpactSR (HQ4) registers */
+#define VAL_CFIFO_HW 0x47
+#define VAL_CFIFO_LW 0x14
+#define VAL_CFIFO_DELAY 0x64
+#define VAL_DFIFO_HW 0x40
+#define VAL_DFIFO_LW 0x10
+#define VAL_DFIFO_DELAY 0
+#define MSK_CFIFO_CNT 0xff
+#define USEPOOLS 5
+#else /* Impact (HQ3) registers */
+#define VAL_CFIFO_HW 0x20 /* 0x18 ? */
+#define VAL_CFIFO_LW 0x14
+#define VAL_CFIFO_DELAY 0x64
+#define VAL_DFIFO_HW 0x28
+#define VAL_DFIFO_LW 0x14
+#define VAL_DFIFO_DELAY 0xfff
+#define MSK_CFIFO_CNT 0x7f
+#define USEPOOLS 4
+#endif
+#define POOLS 5
+
+#define IMPACT_KPOOL_SIZE 65536
+
+struct impact_par {
+ /* physical mmio base in HEART XTalk space */
+ unsigned long mmio_base;
+ /* virtual mmio base in kernel space */
+ unsigned long mmio_virt;
+ struct {
+ /* DMA pool management, txtbl[0..num-1] passed to card */
+ unsigned int *txtbl; /* txtbl[i] = pgidx(phys[i]) */
+ unsigned int txnum; /* valid: txtbl[0..txnum-1] */
+ unsigned int txmax; /* alloc: txtbl[0..txmax-1] */
+ unsigned long txphys; /* txphys = dma_addr(txtbl) */
+ /* kernel DMA pools, the actual DMA-buffers */
+ void* *virt; /* virt[0..txnum-1]: dma-page-addresses */
+ unsigned long *phys; /* phys[i] = dma_addr(virt[i]) */
+ unsigned int size;
+ unsigned long uaddr; /* DMA-buffer's userland-address */
+ } pools[POOLS];
+ /* board config */
+ unsigned int num_ge, num_rss;
+ /* locks to prevent simultaneous user and kernel access */
+ int open_flag;
+ int mmap_flag;
+ spinlock_t lock;
+ unsigned xoffset; /* fb_var_screeninfo.[xy]offset, are ... */
+ unsigned yoffset; /* ...used inconsistently (at the best). */
+};
+
+static struct fb_fix_screeninfo impact_fix = {
+ .id = "ImpactSR 0RSS",
+ .smem_start = 0,
+ .smem_len = 0,
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 0,
+ .ypanstep = 0,
+ .ywrapstep = 0,
+ .line_length = 0,
+ .accel = FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo impact_var = {
+ .xres = 960,
+ .yres = 960,
+ .xres_virtual = 1280,
+ .yres_virtual = 1024,
+ .bits_per_pixel = 24,
+ .red = { .offset = 0, .length = 8 },
+ .green = { .offset = 8, .length = 8 },
+ .blue = { .offset = 16, .length = 8 },
+ .transp = { .offset = 24, .length = 8 },
+};
+
+static struct fb_info info;
+
+static unsigned int pseudo_palette[256];
+
+static struct impact_par current_par;
+
+/* --------------------- Gory Details --------------------- */
+#define PAR(p) (*((struct impact_par *)(p)->par))
+#define MMIO(p) (PAR(p).mmio_virt)
+
+static void impact_wait_cfifo(unsigned long mmio, int nslots)
+{
+ while ((IMPACT_FIFOSTATUS(mmio) & MSK_CFIFO_CNT) >
(IMPACT_CFIFO_MAX-nslots));
+}
+static void impact_wait_cfifo_empty(unsigned long mmio)
+{
+ while (IMPACT_FIFOSTATUS(mmio) & MSK_CFIFO_CNT);
+}
+static void impact_wait_bfifo(unsigned long mmio, int nslots)
+{
+ while ((IMPACT_GIOSTATUS(mmio) & 0x1f) > (IMPACT_BFIFO_MAX-nslots));
+}
+static void impact_wait_bfifo_empty(unsigned long mmio)
+{
+ while (IMPACT_GIOSTATUS(mmio) & 0x1f);
+}
+static void impact_wait_dma(unsigned long mmio)
+{
+ while (IMPACT_DMABUSY(mmio) & 0x1f);
+ while (!(IMPACT_STATUS(mmio) & 1));
+ while (!(IMPACT_STATUS(mmio) & 2));
+ while (!(IMPACT_RESTATUS(mmio) & 0x100));
+}
+static void impact_wait_dmaready(unsigned long mmio)
+{
+ IMPACT_CFIFOW(mmio) = 0x000e0100;
+ while (IMPACT_DMABUSY(mmio) & 0x1eff);
+ while (!(IMPACT_STATUS(mmio) & 2));
+}
+#define impact_wait_rss_idle impact_wait_dmaready
+
+static void impact_inithq(unsigned long mmio)
+{
+ /* Not really needed, the friendly PROM did this already for us... */
+ /* CFIFO parameters */
+ IMPACT_CFIFO_HW(mmio) = VAL_CFIFO_HW;
+ IMPACT_CFIFO_LW(mmio) = VAL_CFIFO_LW;
+ IMPACT_CFIFO_DELAY(mmio) = VAL_CFIFO_DELAY;
+ /* DFIFO parameters */
+ IMPACT_DFIFO_HW(mmio) = VAL_DFIFO_HW;
+ IMPACT_DFIFO_LW(mmio) = VAL_DFIFO_LW;
+ IMPACT_DFIFO_DELAY(mmio) = VAL_DFIFO_DELAY;
+}
+
+static void impact_initrss(unsigned long mmio)
+{
+ volatile typeof(IMPACT_CFIFO(0)) *cfifo = &IMPACT_CFIFO(mmio);
+ /* transfer mask registers */
+ *cfifo = IMPACT_CMD_COLORMASKLSBSA(0xffffff);
+ *cfifo = IMPACT_CMD_COLORMASKLSBSB(0xffffff);
+ *cfifo = IMPACT_CMD_COLORMASKMSBS(0);
+ *cfifo = IMPACT_CMD_XFRMASKLO(0xffffff);
+ *cfifo = IMPACT_CMD_XFRMASKHI(0xffffff);
+ /* use the main plane */
+ *cfifo = IMPACT_CMD_DRBPOINTERS(0xc8240);
+ /* set the RE into vertical flip mode */
+ *cfifo = IMPACT_CMD_CONFIG(0xcac);
+ *cfifo = IMPACT_CMD_XYWIN(0, 0x3ff);
+}
+
+static void impact_initxmap(unsigned long mmio)
+{
+ /* set XMAP into 24-bpp mode */
+ IMPACT_XMAP_PP1SELECT(mmio) = 0x01;
+ IMPACT_XMAP_INDEX(mmio) = 0x00;
+ IMPACT_XMAP_MAIN_MODE(mmio) = 0x07a4;
+}
+
+static void impact_initvc3(unsigned long mmio)
+{
+ /* cursor-b-gone (disable DISPLAY bit) */
+ IMPACT_VC3_INDEXDATA(mmio) = 0x1d000100;
+}
+
+static void impact_detachtxtbl(unsigned long mmio, unsigned long pool)
+{
+ volatile typeof(IMPACT_CFIFOP(0)) *cfifop = &IMPACT_CFIFOP(mmio);
+ /* clear DMA pool */
+ impact_wait_cfifo_empty(mmio);
+ impact_wait_dma(mmio);
+ IMPACT_CFIFOPW1(mmio) = IMPACT_CMD_HQ_TXBASE(pool);
+ *cfifop = 9;
+ *cfifop = IMPACT_CMD_HQ_TXMAX(pool, 0);
+ *cfifop = IMPACT_CMD_HQ_PGBITS(pool, 0);
+ if (isSR)
+ *cfifop = IMPACT_CMD_HQ_484B(pool, 0x00080000);
+ impact_wait_cfifo_empty(mmio);
+ impact_wait_dmaready(mmio);
+}
+
+static void impact_initdma(struct fb_info *p)
+{
+ volatile typeof(IMPACT_CFIFOPW(0)) *cfifopw = &IMPACT_CFIFOPW(MMIO(p));
+ volatile typeof(IMPACT_CFIFOP(0)) *cfifop = &IMPACT_CFIFOP(MMIO(p));
+ int pool;
+ /* clear DMA pools */
+ for (pool = 0; pool < POOLS; pool++) {
+ impact_detachtxtbl(MMIO(p), pool);
+ PAR(p).pools[pool].txmax = 0;
+ PAR(p).pools[pool].txnum = 0;
+ }
+ /* set DMA parameters */
+ impact_wait_cfifo_empty(MMIO(p));
+ *cfifop = IMPACT_CMD_HQ_PGSIZE(0);
+ *cfifop = IMPACT_CMD_HQ_STACKPTR(0);
+ if (isSR)
+ *cfifop = IMPACT_CMD_HQ_484A(0, 0x00180000);
+ *cfifopw = 0x000e0100;
+ *cfifopw = 0x000e0100;
+ *cfifopw = 0x000e0100;
+ *cfifopw = 0x000e0100;
+ *cfifopw = 0x000e0100;
+ if (isSR) {
+ IMPACT_REG32(MMIO(p), 0x40918) = 0x00680000;
+ IMPACT_REG32(MMIO(p), 0x40920) = 0x80280000;
+ IMPACT_REG32(MMIO(p), 0x40928) = 0x00000000;
+ }
+}
+
+static void impact_alloctxtbl(struct fb_info *p, int pool, int pages)
+{
+ /* realloc array of pool's page-indices to be passed to the card. */
+ dma_addr_t dma_handle;
+ int alloc_count;
+ if (pages > PAR(p).pools[pool].txmax) { /* grow the pool - unlikely but
supported */
+ alloc_count = pages;
+ if (alloc_count < 1024)
+ alloc_count = 1024;
+ if (PAR(p).pools[pool].txmax)
+ dma_free_noncoherent(NULL, PAR(p).pools[pool].txmax*4,
+ PAR(p).pools[pool].txtbl,
PAR(p).pools[pool].txphys);
+ PAR(p).pools[pool].txtbl =
+ dma_alloc_noncoherent(NULL, alloc_count*4, &dma_handle,
GFP_KERNEL);
+ PAR(p).pools[pool].txphys = dma_handle;
+ PAR(p).pools[pool].txmax = alloc_count;
+ }
+ PAR(p).pools[pool].txnum = pages;
+}
+
+static void impact_writetxtbl(struct fb_info *p, int pool)
+{
+ volatile typeof(IMPACT_CFIFOPW(0)) *cfifopw = &IMPACT_CFIFOPW(MMIO(p));
+ volatile typeof(IMPACT_CFIFOP(0)) *cfifop = &IMPACT_CFIFOP(MMIO(p));
+ impact_wait_cfifo_empty(MMIO(p));
+ impact_wait_dma(MMIO(p));
+ /* inform the card about a new DMA pool */
+ IMPACT_CFIFOPW1(MMIO(p)) = IMPACT_CMD_HQ_TXBASE(pool);
+ *cfifop = PAR(p).pools[pool].txphys;
+ *cfifop = IMPACT_CMD_HQ_TXMAX(pool, PAR(p).pools[pool].txnum);
+ *cfifop = IMPACT_CMD_HQ_PGBITS(pool, 0x0a);
+ if (isSR)
+ *cfifop = IMPACT_CMD_HQ_484B(pool, 0x00180000);
+ *cfifopw = 0x000e0100;
+ *cfifopw = 0x000e0100;
+ *cfifopw = 0x000e0100;
+ *cfifopw = 0x000e0100;
+ *cfifopw = 0x000e0100;
+ impact_wait_cfifo_empty(MMIO(p));
+ impact_wait_dmaready(MMIO(p));
+}
+
+static void
+impact_settxtbl(struct fb_info *p, int pool, unsigned *txtbl, int txmax)
+{
+ impact_alloctxtbl(p, pool, txmax);
+ memcpy(PAR(p).pools[pool].txtbl, txtbl, txmax*4);
+ dma_cache_wback_inv((unsigned long)PAR(p).pools[pool].txtbl, txmax*4);
+ impact_writetxtbl(p, pool);
+}
+
+/*
+ * Screw the vaddress, or this damned virt_to_page() will blow up the
+ * driver for DMA_NONCOHERENT (i.e. on any Indigo2).
+ * (For 64Bit, though not for 32Bit, __pa() now does the right thing,
+ * and with a bit of luck there will be no regression...)
+ */
+static inline struct page *dma_virt_to_page(void *virt)
+{
+ return virt_to_page(phys_to_virt(__pa(virt)));
+}
+
+static void
+impact_resizekpool(struct fb_info *p, int pool, int size, int growonly)
+{
+ int pages;
+ int i;
+ dma_addr_t dma_handle;
+ if (growonly && PAR(p).pools[pool].size >= size)
+ return;
+ if (size < 8192) /* single line smallcopy (1280*4) *must* work */
+ size = 8192;
+ pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ /* before manipulating the tbl, make it unknown to the card! */
+ impact_detachtxtbl(MMIO(p), pool);
+ if (PAR(p).pools[pool].size > 0) {
+ for (i = 0; i < PAR(p).pools[pool].txnum; i++) {
+
ClearPageReserved(dma_virt_to_page(PAR(p).pools[pool].virt[i]));
+ dma_free_coherent(NULL, PAGE_SIZE,
PAR(p).pools[pool].virt[i],
+ PAR(p).pools[pool].phys[i]);
+ }
+ vfree(PAR(p).pools[pool].phys);
+ vfree(PAR(p).pools[pool].virt);
+ }
+ impact_alloctxtbl(p, pool, pages);
+ PAR(p).pools[pool].virt = vmalloc(pages*sizeof(unsigned long));
+ PAR(p).pools[pool].phys = vmalloc(pages*sizeof(unsigned long));
+ for (i = 0; i < PAR(p).pools[pool].txnum; i++) {
+ PAR(p).pools[pool].virt[i] =
+ dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle,
GFP_KERNEL);
+ SetPageReserved(dma_virt_to_page(PAR(p).pools[pool].virt[i]));
+ PAR(p).pools[pool].phys[i] = dma_handle;
+ PAR(p).pools[pool].txtbl[i] = dma_handle >> PAGE_SHIFT;
+ }
+ i = sizeof(*PAR(p).pools[pool].txtbl) * PAR(p).pools[pool].txnum;
+ dma_cache_wback_inv((unsigned long)PAR(p).pools[pool].txtbl, i);
+ impact_writetxtbl(p, pool); /* finally attach the tbl to the card. */
+ PAR(p).pools[pool].size = pages * PAGE_SIZE;
+}
+
+static void
+impact_rect(unsigned long mmio, int x, int y, int w, int h, unsigned c, int lo)
+{
+ volatile typeof(IMPACT_CFIFO(0)) *cfifo = &IMPACT_CFIFO(mmio);
+ unsigned mode = lo != IMPACT_LO_COPY ? 0x6304:0x6300;
+ impact_wait_cfifo_empty(mmio);
+ impact_wait_rss_idle(mmio);
+ *cfifo = IMPACT_CMD_PP1FILLMODE(mode, lo);
+ *cfifo = IMPACT_CMD_FILLMODE(0);
+ *cfifo = IMPACT_CMD_PACKEDCOLOR(c);
+ *cfifo = IMPACT_CMD_BLOCKXYSTARTI(x, y);
+ *cfifo = IMPACT_CMD_BLOCKXYENDI(x+w-1, y+h-1);
+ *cfifo = IMPACT_CMD_IR_ALIAS(0x18);
+}
+
+static void
+impact_framerect(unsigned long mmio, int x, int y, int w, int h,
+ int bx, int by, unsigned c)
+{
+ impact_rect(mmio, x, y, w, by, c, IMPACT_LO_COPY);
+ impact_rect(mmio, x, y+h-by, w, by, c, IMPACT_LO_COPY);
+ impact_rect(mmio, x, y, bx, h, c, IMPACT_LO_COPY);
+ impact_rect(mmio, x+w-bx, y, bx, h, c, IMPACT_LO_COPY);
+}
+
+static unsigned long dcntr;
+static void impact_debug(struct fb_info *p, int v)
+{
+ int i;
+ IMPACT_CFIFO(MMIO(p)) = IMPACT_CMD_PIXCMD(3);
+ IMPACT_CFIFO(MMIO(p)) = IMPACT_CMD_HQ_PIXELFORMAT(0xe00);
+ switch(v) {
+ case 0:
+ for (i = 0; i < 64; i++)
+ impact_rect(MMIO(p), 4*(i&7), 28-4*(i>>3), 4, 4,
+ dcntr & (1L<<i) ? 0xa080ff:0x100030,
IMPACT_LO_COPY);
+ break;
+ case 1:
+ dcntr++;
+ for (i = 0; i < 64; i++)
+ impact_rect(MMIO(p), 4*(i&7), 28-4*(i>>3), 4, 4,
+ dcntr & (1L<<i) ? 0xff80a0:0x300010,
IMPACT_LO_COPY);
+ break;
+ case 2:
+ for (i = 0; i < 64; i++)
+ impact_rect(MMIO(p), 4*(i&7), 28-4*(i>>3), 4, 4,
+ dcntr & (1L<<i) ? 0xa0ff80:0x103000,
IMPACT_LO_COPY);
+ }
+}
+
+static void impact_smallcopy(struct fb_info *p, unsigned sx, unsigned sy,
+ unsigned dx, unsigned dy, unsigned w, unsigned
h)
+{
+ volatile typeof(IMPACT_CFIFO(0)) *cfifo = &IMPACT_CFIFO(MMIO(p));
+ if (w < 1 || h < 1)
+ return;
+ w = (w+1) & ~1;
+ impact_wait_cfifo_empty(MMIO(p));
+ /* setup and perform DMA from RE to HOST */
+ impact_wait_dma(MMIO(p));
+ if (PAR(p).num_rss == 2 && (sy & 1))
+ *cfifo = IMPACT_CMD_CONFIG(0xca5);
+ else /* Beware, only I2 MaxImpact has 2 REs, SI, HI will hang ! */
+ *cfifo = IMPACT_CMD_CONFIG(0xca4);
+ *cfifo = IMPACT_CMD_PIXCMD(2);
+ *cfifo = IMPACT_CMD_PP1FILLMODE(0x2200, IMPACT_LO_COPY);
+ *cfifo = IMPACT_CMD_COLORMASKLSBSA(0xffffff);
+ *cfifo = IMPACT_CMD_COLORMASKLSBSB(0xffffff);
+ *cfifo = IMPACT_CMD_COLORMASKMSBS(0);
+ *cfifo = IMPACT_CMD_DRBPOINTERS(0xc8240);
+ *cfifo = IMPACT_CMD_BLOCKXYSTARTI(sx, sy+h-1);
+ *cfifo = IMPACT_CMD_BLOCKXYENDI(sx+w-1, sy);
+ *cfifo = IMPACT_CMD_XFRMASKLO(0xffffff);
+ *cfifo = IMPACT_CMD_XFRMASKHI(0xffffff);
+ *cfifo = IMPACT_CMD_XFRSIZE(w, h);
+ *cfifo = IMPACT_CMD_XFRCOUNTERS(w, h);
+ *cfifo = IMPACT_CMD_XFRMODE(0x00080);
+ *cfifo = IMPACT_CMD_FILLMODE(0x01000000);
+ *cfifo = IMPACT_CMD_HQ_PIXELFORMAT(0x200);
+ *cfifo = IMPACT_CMD_HQ_SCANWIDTH(w << 2);
+ *cfifo = IMPACT_CMD_HQ_DMATYPE(0x0a);
+ *cfifo = IMPACT_CMD_HQ_PG_LIST_0(0x80000000);
+ *cfifo = IMPACT_CMD_HQ_PG_WIDTH(w << 2);
+ *cfifo = IMPACT_CMD_HQ_PG_OFFSET(0);
+ *cfifo = IMPACT_CMD_HQ_PG_STARTADDR(0);
+ *cfifo = IMPACT_CMD_HQ_PG_LINECNT(h);
+ *cfifo = IMPACT_CMD_HQ_PG_WIDTHA(w << 2);
+ *cfifo = IMPACT_CMD_XFRCONTROL(8);
+ *cfifo = IMPACT_CMD_GLINE_XSTARTF(1);
+ *cfifo = IMPACT_CMD_IR_ALIAS(0x18);
+ *cfifo = IMPACT_CMD_HQ_DMACTRL_0(8);
+ *cfifo = IMPACT_CMD_XFRCONTROL(9);
+ impact_wait_dmaready(MMIO(p));
+ *cfifo = IMPACT_CMD_GLINE_XSTARTF(0);
+ *cfifo = IMPACT_CMD_RE_TOGGLECNTX(0);
+ *cfifo = IMPACT_CMD_XFRCOUNTERS(0, 0);
+ /* setup and perform DMA from HOST to RE */
+ impact_wait_dma(MMIO(p));
+ *cfifo = IMPACT_CMD_CONFIG(0xca4);
+ *cfifo = IMPACT_CMD_PP1FILLMODE(0x6200, IMPACT_LO_COPY);
+ *cfifo = IMPACT_CMD_BLOCKXYSTARTI(dx, dy+h-1);
+ *cfifo = IMPACT_CMD_BLOCKXYENDI(dx+w-1, dy);
+ *cfifo = IMPACT_CMD_FILLMODE(0x01400000);
+ *cfifo = IMPACT_CMD_XFRMODE(0x00080);
+ *cfifo = IMPACT_CMD_HQ_PIXELFORMAT(0x600);
+ *cfifo = IMPACT_CMD_HQ_SCANWIDTH(w << 2);
+ *cfifo = IMPACT_CMD_HQ_DMATYPE(0x0c);
+ *cfifo = IMPACT_CMD_PIXCMD(3);
+ *cfifo = IMPACT_CMD_XFRSIZE(w, h);
+ *cfifo = IMPACT_CMD_XFRCOUNTERS(w, h);
+ *cfifo = IMPACT_CMD_GLINE_XSTARTF(1);
+ *cfifo = IMPACT_CMD_IR_ALIAS(0x18);
+ *cfifo = IMPACT_CMD_XFRCONTROL(1);
+ *cfifo = IMPACT_CMD_HQ_PG_LIST_0(0x80000000);
+ *cfifo = IMPACT_CMD_HQ_PG_OFFSET(0);
+ *cfifo = IMPACT_CMD_HQ_PG_STARTADDR(0);
+ *cfifo = IMPACT_CMD_HQ_PG_LINECNT(h);
+ *cfifo = IMPACT_CMD_HQ_PG_WIDTHA(w << 2);
+ *cfifo = IMPACT_CMD_HQ_DMACTRL_0(0);
+ IMPACT_CFIFOW1(MMIO(p)) = 0x000e0400;
+ impact_wait_dma(MMIO(p));
+ *cfifo = IMPACT_CMD_GLINE_XSTARTF(0);
+ *cfifo = IMPACT_CMD_RE_TOGGLECNTX(0);
+ *cfifo = IMPACT_CMD_XFRCOUNTERS(0, 0);
+}
+
+static unsigned impact_getpalreg(struct fb_info *p, unsigned i)
+{
+ return ((unsigned *)p->pseudo_palette)[i];
+}
+
+/* ------------ Accelerated Functions --------------------- */
+
+static void impact_fillrect(struct fb_info *p, const struct fb_fillrect
*region)
+{
+ unsigned long flags;
+ unsigned x = region->dx+PAR(p).xoffset;
+ unsigned y = region->dy+PAR(p).yoffset;
+ spin_lock_irqsave(&PAR(p).lock, flags);
+ if (!PAR(p).open_flag)
+ switch(region->rop) {
+ case ROP_XOR:
+ impact_rect(MMIO(p), x, y, region->width,
region->height,
+ impact_getpalreg(p, region->color),
IMPACT_LO_XOR);
+ break;
+ case ROP_COPY:
+ default:
+ impact_rect(MMIO(p), x, y, region->width,
region->height,
+ impact_getpalreg(p, region->color),
IMPACT_LO_COPY);
+ break;
+ }
+ spin_unlock_irqrestore(&PAR(p).lock, flags);
+}
+
+static void impact_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+ volatile typeof(IMPACT_CFIFO(0)) *cfifo = &IMPACT_CFIFO(MMIO(p));
+ unsigned sx, sy, dx, dy, w, h;
+ unsigned th, ah;
+ unsigned long flags;
+ w = area->width;
+ h = area->height;
+ if (w < 1 || h < 1)
+ return;
+ spin_lock_irqsave(&PAR(p).lock, flags);
+ if (PAR(p).open_flag) {
+ spin_unlock_irqrestore(&PAR(p).lock, flags);
+ return;
+ }
+ sx = area->sx + PAR(p).xoffset;
+ sy = 0x3ff - (area->sy + h - 1 + PAR(p).yoffset);
+ dx = area->dx + PAR(p).xoffset;
+ dy = 0x3ff - (area->dy + h - 1 + PAR(p).yoffset);
+ th = PAR(p).pools[0].size / (w*4);
+ *cfifo = IMPACT_CMD_XYWIN(0, 0);
+ if (dy > sy) {
+ dy += h;
+ sy += h;
+ while (h > 0) {
+ ah = th > h ? h:th;
+ impact_smallcopy(p, sx, sy-ah, dx, dy-ah, w, ah);
+ dy -= ah;
+ sy -= ah;
+ h -= ah;
+ }
+ } else {
+ while (h > 0) {
+ ah = th > h ? h:th;
+ impact_smallcopy(p, sx, sy, dx, dy, w, ah);
+ dy += ah;
+ sy += ah;
+ h -= ah;
+ }
+ }
+ *cfifo = IMPACT_CMD_PIXCMD(0);
+ *cfifo = IMPACT_CMD_HQ_PIXELFORMAT(0xe00);
+ *cfifo = IMPACT_CMD_CONFIG(0xcac);
+ *cfifo = IMPACT_CMD_XYWIN(0, 0x3ff);
+ spin_unlock_irqrestore(&PAR(p).lock, flags);
+}
+
+/* 8-bpp blits are done as PIO draw operation; the pixels are unpacked into
+ 32-bpp values from the current palette in software */
+static void
+impact_imageblit_8bpp(struct fb_info *p, const struct fb_image *image)
+{
+ volatile typeof(IMPACT_CFIFO(0)) *cfifo = &IMPACT_CFIFO(MMIO(p));
+ int i, u, v;
+ const unsigned char *dp;
+ unsigned pix;
+ unsigned pal[256];
+ unsigned x = image->dx + PAR(p).xoffset;
+ unsigned y = image->dy + PAR(p).yoffset;
+ /* setup PIO to RE */
+ impact_wait_cfifo_empty(MMIO(p));
+ impact_wait_rss_idle(MMIO(p));
+ *cfifo = IMPACT_CMD_PP1FILLMODE(0x6300, IMPACT_LO_COPY);
+ *cfifo = IMPACT_CMD_BLOCKXYSTARTI(x, y);
+ *cfifo = IMPACT_CMD_BLOCKXYENDI(x+image->width-1, y+image->height-1);
+ *cfifo = IMPACT_CMD_FILLMODE(0x00c00000);
+ *cfifo = IMPACT_CMD_XFRMODE(0x00080);
+ *cfifo = IMPACT_CMD_XFRSIZE(image->width, image->height);
+ *cfifo = IMPACT_CMD_XFRCOUNTERS(image->width, image->height);
+ *cfifo = IMPACT_CMD_GLINE_XSTARTF(1);
+ *cfifo = IMPACT_CMD_IR_ALIAS(0x18);
+ /* another workaround.. 33 writes to alpha... hmm... */
+ for (i = 0; i < 33; i++)
+ *cfifo = IMPACT_CMD_ALPHA(0);
+ *cfifo = IMPACT_CMD_XFRCONTROL(2);
+ /* pairs of pixels are sent in two writes to the RE */
+ i = 0;
+ dp = image->data;
+ for (v = 0; v < 256; v++)
+ pal[v] = impact_getpalreg(p, v);
+ for (v = 0; v < image->height; v++) {
+ for (u = 0; u < image->width; u++) {
+ pix = pal[*(dp++)];
+ if (i)
+ *cfifo = IMPACT_CMD_CHAR_L(pix);
+ else
+ *cfifo = IMPACT_CMD_CHAR_H(pix);
+ i ^= 1;
+ }
+ }
+ if (i)
+ *cfifo = IMPACT_CMD_CHAR_L(0);
+ *cfifo = IMPACT_CMD_GLINE_XSTARTF(0);
+ *cfifo = IMPACT_CMD_RE_TOGGLECNTX(0);
+ *cfifo = IMPACT_CMD_XFRCOUNTERS(0, 0);
+}
+
+/* 1-bpp blits are done as character drawing; the bitmaps are drawn as 8-bit
wide
+ strips; technically, Impact supports 16-pixel wide characters, but Linux
bitmap
+ alignment is 8 bits and most draws are 8 pixels wide (font width), anyway */
+static void
+impact_imageblit_1bpp(struct fb_info *p, const struct fb_image *image)
+{
+ volatile typeof(IMPACT_CFIFO(0)) *cfifo = &IMPACT_CFIFO(MMIO(p));
+ int x, y, w, h, b;
+ int u, v, a;
+ const unsigned char *d;
+ impact_wait_cfifo_empty(MMIO(p));
+ impact_wait_rss_idle(MMIO(p));
+ *cfifo = IMPACT_CMD_PP1FILLMODE(0x6300, IMPACT_LO_COPY);
+ *cfifo = IMPACT_CMD_FILLMODE(0x400018);
+ a = impact_getpalreg(p, image->fg_color);
+ *cfifo = IMPACT_CMD_PACKEDCOLOR(a);
+ a = impact_getpalreg(p, image->bg_color);
+ /* Hmm, only the lower 4 bits are taken from red and blue. */
+ if (!isSR) a = (a>>4) & 0x0f000f | a & 0x00ff00;
+ *cfifo = IMPACT_CMD_BKGRD_RG(a & 0xffff);
+ *cfifo = IMPACT_CMD_BKGRD_BA((a & 0xff0000) >> 16);
+ x = image->dx + PAR(p).xoffset;
+ y = image->dy + PAR(p).yoffset;
+ w = image->width;
+ h = image->height;
+ b = (w+7) / 8;
+ for (u = 0; u < b; u++) {
+ impact_wait_cfifo_empty(MMIO(p));
+ a = (w<8) ? w:8;
+ d = image->data+u;
+ *cfifo = IMPACT_CMD_BLOCKXYSTARTI(x, y);
+ *cfifo = IMPACT_CMD_BLOCKXYENDI(x+a-1, y+h-1);
+ *cfifo = IMPACT_CMD_IR_ALIAS(0x18);
+ for (v = 0; v < h; v++) {
+ *cfifo = IMPACT_CMD_CHAR(*d << 24);
+ d += b;
+ }
+ w -= a;
+ x += a;
+ }
+}
+
+static void impact_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&PAR(p).lock, flags);
+ if (!PAR(p).open_flag)
+ switch(image->depth) {
+ case 1:
+ impact_imageblit_1bpp(p, image);
+ break;
+ case 8:
+ impact_imageblit_8bpp(p, image);
+ break;
+ }
+ spin_unlock_irqrestore(&PAR(p).lock, flags);
+}
+
+static int impact_sync(struct fb_info *info)
+{
+ return 0;
+}
+
+static int impact_blank(int blank_mode, struct fb_info *info)
+{
+ /* TODO */
+ return 0;
+}
+
+static int impact_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info)
+{
+ if (regno > 255)
+ return 1;
+ ((unsigned *)info->pseudo_palette)[regno] =
+ (red >> 8) | (green & 0xff00) | ((blue << 8) & 0xff0000);
+ return 0;
+}
+
+/* ------------------- Framebuffer Access -------------------- */
+
+static ssize_t
+impact_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ return -EINVAL;
+}
+
+static ssize_t
+impact_write(struct file *file, const char __user *buf, size_t count, loff_t
*ppos)
+{
+ return -EINVAL;
+}
+
+/* --------------------- Userland Access --------------------- */
+
+static int
+impact_cacheflush(struct fb_info *p, int pool, const struct impact_cf_args
*arg)
+{
+ unsigned short w = arg->box.ws_xpixel << 2;
+ unsigned short h = arg->box.ws_ypixel;
+
+ if (w && h)
+ { unsigned long a = arg->bpitch*arg->box.ws_row + (arg->box.ws_col
<< 2);
+ unsigned long b = arg->base + PAR(p).pools[pool].size - w;
+
+ for (a += arg->base; h; h--, a += arg->bpitch)
+ { if (!access_ok(VERIFY_WRITE, (void __user*)a, w))
+ return -EFAULT;
+ if (b <= a)
+ return -EINVAL;
+ (*_dma_cache_wback_inv)(a, w);
+ }
+ }
+ return 0;
+}
+
+static int
+impact_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+ if (!isSR && IPNR != 22 && TCFLSH == cmd) {
+ static struct impact_cf_args cfpar;
+ int i;
+
+ if ( copy_from_user(&cfpar,(void __user*)arg,sizeof(cfpar)) )
+ return -EFAULT;
+
+ if (!cfpar.base)
+ return -EINVAL;
+
+ for (i = 0; i < POOLS; i++)
+ if (cfpar.base == PAR(info).pools[i].uaddr) {
+ int r = impact_cacheflush(info, i, &cfpar);
+ /* Might be munmapped behind our back. */
+ if (-EFAULT == r) {
+ printk(KERN_INFO "impact_ioctl: shut down
user"
+ " cache-flush for DMA-pool %d
(%p)\n",
+ i, cfpar.base);
+ PAR(info).pools[i].uaddr = 0;
+ }
+ return r;
+ }
+ }
+ return -EINVAL;
+}
+
+static int impact_mmap(struct fb_info *p, struct vm_area_struct *vma)
+{
+ unsigned pool, i, n;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long start;
+
+ switch(offset) {
+ case 0x0000000: /* map Impact-registers */
+ if (size > (isSR ? 0x200000:0x400000))
+ return -EINVAL;
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+ return -EINVAL;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_IO;
+ if (remap_pfn_range(vma, vma->vm_start,
(MMIO(p)+offset)>>PAGE_SHIFT,
+ size, vma->vm_page_prot))
+ return -EAGAIN;
+ PAR(p).mmap_flag = 1;
+ break;
+ case 0x1000000: /* map e.g. shadow-frame-buffer */
+ case 0x2000000:
+ case 0x3000000:
+ case 0x8000000:
+ case 0x9000000:
+ case 0xa000000:
+ case 0xb000000:
+ if (size > (isSR ? 0x1000000:0xc00000))
+ return -EINVAL;
+ pool = (offset >> 24) & 3; /* growonly = (offset>>24) & 8 */
+ n = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ if (n*PAGE_SIZE != PAR(p).pools[pool].size)
+ impact_resizekpool(p, pool, size, offset & 0x8000000);
+ if (22 == IPNR) /* IP22 memory may be written uncached */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ for (start = vma->vm_start, i = 0; i < n; i++) {
+ if (remap_pfn_range(vma, start,
+ PAR(p).pools[pool].phys[i] >>
PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot)) {
+ PAR(p).pools[pool].uaddr = 0;
+ return -EAGAIN;
+ }
+ start += PAGE_SIZE;
+ }
+ PAR(p).pools[pool].uaddr = vma->vm_start;
+ PAR(p).mmap_flag = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int impact_open(struct fb_info *p, int user)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&PAR(p).lock, flags);
+ if (user)
+ PAR(p).open_flag++;
+ spin_unlock_irqrestore(&PAR(p).lock, flags);
+ return 0;
+}
+
+static int impact_release(struct fb_info *p, int user)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&PAR(p).lock, flags);
+ if (user && PAR(p).open_flag)
+ PAR(p).open_flag--;
+ spin_unlock_irqrestore(&PAR(p).lock, flags);
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+ /*
+ * Frame buffer operations
+ */
+
+static struct fb_ops impact_ops = {
+ .owner = THIS_MODULE,
+ .fb_read = impact_read,
+ .fb_write = impact_write,
+ .fb_blank = impact_blank,
+ .fb_fillrect = impact_fillrect,
+ .fb_copyarea = impact_copyarea,
+ .fb_imageblit = impact_imageblit,
+ .fb_sync = impact_sync,
+ .fb_ioctl = impact_ioctl,
+ .fb_setcolreg = impact_setcolreg,
+ .fb_mmap = impact_mmap,
+ .fb_open = impact_open,
+ .fb_release = impact_release,
+};
+
+/* ------------------------------------------------------------------------- */
+
+ /*
+ * Private early console
+ */
+
+#define MMIO_FIXED (isSR ? 0x900000001c000000LL:0x900000001f000000LL)
+
+static inline void impact_earlyrect(int x, int y, int w, int h, unsigned c)
+{
+ impact_rect(MMIO_FIXED, x, y, w, h, c, IMPACT_LO_COPY);
+}
+
+static void
+impact_paintchar(int x, int y, unsigned char *b, unsigned c, unsigned a)
+{
+ volatile typeof(IMPACT_CFIFO(0)) *cfifo = &IMPACT_CFIFO(MMIO_FIXED);
+ int v;
+ /* Hmm, only the lower 4 bits are taken from red and blue. */
+ if (!isSR) a = (a>>4) & 0x0f000f | a & 0x00ff00;
+ impact_wait_cfifo_empty(MMIO_FIXED);
+ *cfifo = IMPACT_CMD_PP1FILLMODE(0x6300, IMPACT_LO_COPY);
+ *cfifo = IMPACT_CMD_FILLMODE(0x400018);
+ *cfifo = IMPACT_CMD_PACKEDCOLOR(c);
+ *cfifo = IMPACT_CMD_BKGRD_RG(a & 0xffff);
+ *cfifo = IMPACT_CMD_BKGRD_BA((a & 0xff0000) >> 16);
+ *cfifo = IMPACT_CMD_BLOCKXYSTARTI(x, y);
+ *cfifo = IMPACT_CMD_BLOCKXYENDI(x+7, y+15);
+ *cfifo = IMPACT_CMD_IR_ALIAS(0x18);
+ for (v = 0; v < 16; v++)
+ *cfifo = IMPACT_CMD_CHAR(*b++ << 24);
+}
+static void impact_earlyhwinit(void)
+{
+ impact_inithq(MMIO_FIXED);
+ impact_initrss(MMIO_FIXED);
+ impact_initxmap(MMIO_FIXED);
+ impact_initvc3(MMIO_FIXED);
+}
+
+static inline unsigned char *p8x16(unsigned char c)
+{
+ return ((unsigned char(*)[16])font_vga_8x16.data)[c];
+}
+
+static void impact_earlywrite(struct console*, const char*, unsigned);
+enum {
+ LightBlue = (230<<16)|(216<<8)|173,
+ DarkViolet2 = (105<<16)|74, LightGoldenrod = (130<<16)|(221<<8)|238,
+};
+#define EARLYBG 0x3f3f3f
+
+static struct {
+ int posx, posy;
+ spinlock_t lock;
+ struct console console;
+}
+early = {
+ .posx = -1,
+ .lock = __SPIN_LOCK_UNLOCKED(early.lock),
+ .console = {
+ .name = "earlyimpact",
+ .write = impact_earlywrite,
+ /*
+ * Omit CON_BOOT, so 'early' shall persist until fbcon takes
over!
+ * Add CON_CONSDEV to detach a possibly active arc boot-console.
+ */
+ .flags = CON_CONSDEV | CON_PRINTBUFFER,
+ .index = -1,
+ },
+};
+
+void impact_earlychar(unsigned char c)
+{
+ if (early.posx != -1) {
+ unsigned long flags;
+ spin_lock_irqsave(&early.lock, flags);
+ if (c == '\n') {
+ early.posy += 16;
+ if (early.posy >= 800)
+ early.posy = 0;
+ early.posx = 0;
+ goto out;
+ }
+ if (early.posx == 0) {
+ impact_earlyrect(240, 112+early.posy, 800, 16, EARLYBG);
+ if (early.posy+16*2 < 800)
+ impact_earlyrect(240, 112+16+early.posy, 800,
16, EARLYBG);
+ }
+ impact_paintchar(240+early.posx, 112+early.posy, p8x16(c),
0xffffff, EARLYBG);
+ early.posx += 8;
+ if (early.posx >= 800) {
+ early.posx = 0;
+ early.posy += 16;
+ if (early.posy >= 800)
+ early.posy = 0;
+ }
+out:
+ spin_unlock_irqrestore(&early.lock, flags);
+ }
+}
+void impact_earlystring(char *s)
+{
+ while (*s)
+ impact_earlychar(*s++);
+}
+static void impact_earlywrite(struct console *con, const char *s, unsigned n)
+{
+ while (n-- && *s)
+ impact_earlychar(*s++);
+}
+void __init impact_earlyinit(void)
+{
+ static int up;
+ if (!up) {
+ impact_earlyhwinit();
+ impact_framerect(MMIO_FIXED, 0, 0, 1280, 1024, 240, 112,
LightBlue);
+ impact_framerect(MMIO_FIXED, 240-4, 112-4, 800+8, 800+8, 4, 4,
LightGoldenrod);
+ impact_earlyrect(240, 112, 800, 800, EARLYBG);
+ early.posx = 0;
+ early.posy = 0;
+ impact_earlystring("ImpactSR early console ready.\n");
+ up++;
+ }
+}
+void __init setup_impact_earlycons(void)
+{
+ static int up;
+ if (!up) {
+ impact_earlyinit();
+ register_console(&early.console);
+ up++;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+ /*
+ * Initialization
+ */
+
+static inline unsigned long gfxphysaddr(void)
+{
+#if isSR
+ /* first card in Octane? */
+ int xwid = ip30_xtalk_find(IMPACT_XTALK_MFGR, IMPACT_XTALK_PART,
+ IP30_XTALK_NUM_WID);
+ return xwid == -1 ? 0:ip30_xtalk_swin(xwid);
+#else
+ extern unsigned long sgi_gfxaddr; /* provided by ARCS */
+ return sgi_gfxaddr;
+#endif
+}
+
+static void __init impact_hwinit(struct fb_info *info)
+{
+ early.posx = -1;
+ /* initialize hardware */
+ impact_inithq(MMIO(info));
+ impact_initvc3(MMIO(info));
+ impact_initrss(MMIO(info));
+ impact_initxmap(MMIO(info));
+ impact_initdma(info);
+}
+
+static int __init impact_devinit(void)
+{
+ int i, x, y;
+ current_par.open_flag = 0;
+ current_par.mmap_flag = 0;
+ current_par.lock = __SPIN_LOCK_UNLOCKED(current_par.lock);
+
+ current_par.mmio_base = gfxphysaddr();
+ if (!current_par.mmio_base) {
+ printk(KERN_INFO "impact_devinit: !gfxaddr\n");
+ return -EINVAL;
+ }
+ current_par.mmio_virt = (unsigned long)
+ ioremap(current_par.mmio_base, 0x200000);
+ impact_fix.mmio_start = current_par.mmio_base;
+ impact_fix.mmio_len = 0x200000;
+
+ /* get board config */
+ current_par.num_ge = IMPACT_BDVERS1(current_par.mmio_virt) & 3;
+ if (!isSR) {
+ /* To do: desirably remove "... = 1; ". BDVERS1 fits on
+ * Solid-Impact, but couldn't check High-/Max- yet.
+ */
+ current_par.num_ge = 1;
+ /* Caveat: XImpact depends on the 'S' in id[6] to distinguish
+ * between ImpactSR and Impact by examining /proc/fb!
+ */
+ impact_fix.id[6] = '2';
+ impact_fix.id[7] = '0' + IPNR - 20;
+ }
+ current_par.num_rss = current_par.num_ge;
+ impact_fix.id[9] = '0' + current_par.num_rss;
+
+ info.flags = FBINFO_FLAG_DEFAULT;
+ info.screen_base = NULL;
+ info.fbops = &impact_ops;
+ info.fix = impact_fix;
+ info.var = impact_var;
+ info.par = ¤t_par;
+ info.pseudo_palette = pseudo_palette;
+
+ /* Can't wait any longer to switch off the early stuff */
+ unregister_console(&early.console);
+
+ impact_hwinit(&info);
+ /* initialize buffers */
+ impact_resizekpool(&info, 0, 65536, 0);
+ for (i = 1; i < USEPOOLS; ++i)
+ impact_resizekpool(&info, i, 8192, 0);
+
+ /* This has to been done !!! */
+ fb_alloc_cmap(&info.cmap, 256, 0);
+
+ if (register_framebuffer(&info) < 0) {
+ fb_dealloc_cmap(&info.cmap);
+ return -EINVAL;
+ }
+ x = (1280 - impact_var.xres) / 2;
+ y = (1024 - impact_var.yres) / 2;
+
+ /* Now we can take care of the nice-to-have stuff :-) */
+ impact_framerect(MMIO(&info), 0, 0, 1280, 1024, x, y, DarkViolet2);
+ impact_framerect(MMIO(&info), x-4, y-4, impact_var.xres+8,
+ impact_var.yres+8, 4, 4, LightGoldenrod);
+
+#if defined(CONFIG_LOGO)
+ if (fb_prepare_logo(&info, 0)) {
+ fb_set_cmap(&info.cmap, &info);
+ fb_show_logo(&info, 0);
+ }
+#endif
+ current_par.xoffset = x;
+ current_par.yoffset = y;
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node,
info.fix.id);
+ return 0;
+}
+
+static int __init impact_probe(struct device *dev)
+{
+ return impact_devinit();
+}
+
+static struct platform_driver impact_driver = {
+ .driver = {
+ .name = (isSR ? "impactsr":"impact"),
+ .bus = &platform_bus_type,
+ .probe = impact_probe,
+ /* add remove someday */
+ },
+};
+
+static struct platform_device impact_device = {
+ .name = (isSR ? "impactsr":"impact"),
+};
+
+static int __init impact_init(void)
+{
+ int ret = driver_register(&impact_driver.driver);
+ if (!ret) {
+ ret = platform_device_register(&impact_device);
+ if (ret)
+ driver_unregister(&impact_driver.driver);
+ }
+ return ret;
+}
+
+static void __exit impact_exit(void)
+{
+ driver_unregister(&impact_driver.driver);
+}
+
+module_init(impact_init);
+module_exit(impact_exit);
+
+MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>, "\
+ "Indigo2-adaption: pf <post@pfrst.de>");
+MODULE_DESCRIPTION("SGI Octane ImpactSR HQ4, Indigo2 Impact HQ3 Video Driver");
+MODULE_VERSION("R28/R1.7");
+MODULE_LICENSE("GPL");
diff --git a/include/video/impact.h b/include/video/impact.h
new file mode 100644
index 0000000..e4b013c
--- /dev/null Wed Dec 8 00:46:04 2004
+++ b/include/video/impact.h Mon Jul 25 00:06:58 2011
@@ -0,0 +1,210 @@
+/*
+ * linux/drivers/video/impactsr.h -- SGI Octane MardiGras (IMPACTSR) graphics
+ * linux/include/video/impact.h -- SGI Indigo2 MardiGras (IMPACT) graphics
+ *
+ * Copyright (c) 2004-2006 by Stanislaw Skowronek (skylark@linux-mips.org)
+ * Adapted to Indigo2 by pf, 2005,2006,2009 (post@pfrst.de)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef IMPACT_H
+#define IMPACT_H
+
+/* Convenient access macros */
+#define IMPACT_REG64(vma,off) (*(volatile unsigned long long *)((vma)+(off)))
+#define IMPACT_REG32(vma,off) (*(volatile unsigned int *)((vma)+(off)))
+#define IMPACT_REG16(vma,off) (*(volatile unsigned short *)((vma)+(off)))
+#define IMPACT_REG8(vma,off) (*(volatile unsigned char *)((vma)+(off)))
+
+#if defined(CONFIG_SGI_IP30) /* Octane: Impact for "SpeedRacer" */
+
+/* Xtalk */
+#define IMPACTSR_XTALK_MFGR 0x2aa
+#define IMPACTSR_XTALK_PART 0xc003
+
+/* ImpactSR (HQ4) register offsets */
+#define IMPACT_CFIFO(vma) IMPACT_REG64(vma,0x20400)
+#define IMPACT_CFIFOW(vma) IMPACT_REG32(vma,0x20400)
+#define IMPACT_CFIFOW1 IMPACT_CFIFOW /* ? ? ? */
+#define IMPACT_CFIFOP(vma) IMPACT_REG64(vma,0x130400)
+#define IMPACT_CFIFOPW(vma) IMPACT_REG32(vma,0x130400)
+#define IMPACT_CFIFOPW1 IMPACT_CFIFOPW /* ? ? ? */
+
+#define IMPACT_STATUS(vma) IMPACT_REG32(vma,0x20000)
+#define IMPACT_FIFOSTATUS(vma) IMPACT_REG32(vma,0x20008)
+#define IMPACT_GIOSTATUS(vma) IMPACT_REG32(vma,0x20100)
+#define IMPACT_DMABUSY(vma) IMPACT_REG32(vma,0x20200)
+
+#define IMPACT_CFIFO_HW(vma) IMPACT_REG32(vma,0x40000)
+#define IMPACT_CFIFO_LW(vma) IMPACT_REG32(vma,0x40008)
+#define IMPACT_CFIFO_DELAY(vma) IMPACT_REG32(vma,0x40010)
+#define IMPACT_DFIFO_HW(vma) IMPACT_REG32(vma,0x40020)
+#define IMPACT_DFIFO_LW(vma) IMPACT_REG32(vma,0x40028)
+#define IMPACT_DFIFO_DELAY(vma) IMPACT_REG32(vma,0x40030)
+
+#define IMPACT_XMAP_OFF(off) (0x71c00+(off))
+#define IMPACT_VC3_OFF(off) (0x72000+(off))
+#define IMPACT_RSS_OFF(off) (0x2c000+(off))
+
+#else /* Indigo2: IP28, IP26, IP22: Impact graphics */
+
+/* Impact (HQ3) register offsets */
+#define IMPACT_CFIFO(vma) IMPACT_REG64(vma,0x70080)
+#define IMPACT_CFIFOW(vma) IMPACT_REG32(vma,0x70080)
+#define IMPACT_CFIFOW1(vma) IMPACT_REG32(vma,0x70084)
+#define IMPACT_CFIFOP(vma) IMPACT_REG64(vma,0x50080)
+#define IMPACT_CFIFOPW(vma) IMPACT_REG32(vma,0x50080)
+#define IMPACT_CFIFOPW1(vma) IMPACT_REG32(vma,0x50084)
+
+#define IMPACT_STATUS(vma) IMPACT_REG32(vma,0x70000)
+#define IMPACT_FIFOSTATUS(vma) IMPACT_REG32(vma,0x70004)
+#define IMPACT_GIOSTATUS(vma) IMPACT_REG32(vma,0x70100)
+#define IMPACT_DMABUSY(vma) IMPACT_REG32(vma,0x70104)
+
+#define IMPACT_CFIFO_HW(vma) IMPACT_REG32(vma,0x50020)
+#define IMPACT_CFIFO_LW(vma) IMPACT_REG32(vma,0x50024)
+#define IMPACT_CFIFO_DELAY(vma) IMPACT_REG32(vma,0x50028)
+#define IMPACT_DFIFO_HW(vma) IMPACT_REG32(vma,0x5002c)
+#define IMPACT_DFIFO_LW(vma) IMPACT_REG32(vma,0x50030)
+#define IMPACT_DFIFO_DELAY(vma) IMPACT_REG32(vma,0x50034)
+
+#define IMPACT_XMAP_OFF(off) (0x61c00+(off))
+#define IMPACT_VC3_OFF(off) (0x62000+(off))
+#define IMPACT_RSS_OFF(off) (0x7c000+(off))
+
+#endif
+
+#define IMPACT_RESTATUS(vma) IMPACT_REG32(vma,IMPACT_RSS_OFF(0x578))
+
+#define IMPACT_XMAP_PP1SELECT(vma) IMPACT_REG8(vma,IMPACT_XMAP_OFF(0x008))
+#define IMPACT_XMAP_INDEX(vma) IMPACT_REG8(vma,IMPACT_XMAP_OFF(0x088))
+#define IMPACT_XMAP_CONFIG(vma) IMPACT_REG32(vma,IMPACT_XMAP_OFF(0x100))
+#define IMPACT_XMAP_CONFIGB(vma) IMPACT_REG8(vma,IMPACT_XMAP_OFF(0x108))
+#define IMPACT_XMAP_BUF_SELECT(vma) IMPACT_REG32(vma,IMPACT_XMAP_OFF(0x180))
+#define IMPACT_XMAP_MAIN_MODE(vma) IMPACT_REG32(vma,IMPACT_XMAP_OFF(0x200))
+#define IMPACT_XMAP_OVERLAY_MODE(vma) IMPACT_REG32(vma,IMPACT_XMAP_OFF(0x280))
+#define IMPACT_XMAP_DIB(vma) IMPACT_REG32(vma,IMPACT_XMAP_OFF(0x300))
+#define IMPACT_XMAP_DIB_DW(vma) IMPACT_REG32(vma,IMPACT_XMAP_OFF(0x340))
+#define IMPACT_XMAP_RE_RAC(vma) IMPACT_REG32(vma,IMPACT_XMAP_OFF(0x380))
+
+#define IMPACT_VC3_INDEX(vma) IMPACT_REG8(vma,IMPACT_VC3_OFF(0x008))
+#define IMPACT_VC3_INDEXDATA(vma) IMPACT_REG32(vma,IMPACT_VC3_OFF(0x038))
+#define IMPACT_VC3_DATA(vma) IMPACT_REG16(vma,IMPACT_VC3_OFF(0x0b0))
+#define IMPACT_VC3_RAM(vma) IMPACT_REG16(vma,IMPACT_VC3_OFF(0x190))
+
+#define IMPACT_BDVERS0(vma) IMPACT_REG8(vma,IMPACT_VC3_OFF(0x408))
+#define IMPACT_BDVERS1(vma) IMPACT_REG8(vma,IMPACT_VC3_OFF(0x488))
+
+/* FIFO status */
+#if defined(CONFIG_SGI_IP30)
+#define IMPACT_CFIFO_MAX 128
+#else
+#define IMPACT_CFIFO_MAX 64
+#endif
+#define IMPACT_BFIFO_MAX 16
+
+/* Commands for CFIFO */
+static __inline__
+unsigned long long ImpactCmdCFifo64( unsigned cmd, unsigned reg, unsigned val )
+{
+ return (unsigned long long)(cmd | reg<<8) << 32 | val;
+}
+static __inline__
+unsigned long long ImpactCmdWriteRSS( unsigned reg, unsigned val )
+{
+ return (0x00180004LL | reg<<8) << 32 | val;
+}
+static __inline__
+unsigned long long ImpactCmdExecRSS( unsigned reg, unsigned val )
+{
+ return (0x001c0004LL | reg<<8) << 32 | val;
+}
+
+#define IMPACT_CMD_GLINE_XSTARTF(v) ImpactCmdWriteRSS(0x00c,v)
+#define IMPACT_CMD_IR_ALIAS(v) ImpactCmdExecRSS(0x045,v)
+#define IMPACT_CMD_BLOCKXYSTARTI(x,y) ImpactCmdWriteRSS(0x046,((x)<<16)|(y))
+#define IMPACT_CMD_BLOCKXYENDI(x,y) ImpactCmdWriteRSS(0x047,((x)<<16)|(y))
+#define IMPACT_CMD_PACKEDCOLOR(v) ImpactCmdWriteRSS(0x05b,v)
+#define IMPACT_CMD_RED(v) ImpactCmdWriteRSS(0x05c,v)
+#define IMPACT_CMD_ALPHA(v) ImpactCmdWriteRSS(0x05f,v)
+#define IMPACT_CMD_CHAR(v) ImpactCmdExecRSS(0x070,v)
+#define IMPACT_CMD_CHAR_H(v) ImpactCmdWriteRSS(0x070,v)
+#define IMPACT_CMD_CHAR_L(v) ImpactCmdExecRSS(0x071,v)
+#define IMPACT_CMD_XFRCONTROL(v) ImpactCmdWriteRSS(0x102,v)
+#define IMPACT_CMD_FILLMODE(v) ImpactCmdWriteRSS(0x110,v)
+#define IMPACT_CMD_CONFIG(v) ImpactCmdWriteRSS(0x112,v)
+#define IMPACT_CMD_XYWIN(x,y) ImpactCmdWriteRSS(0x115,((y)<<16)|(x))
+#define IMPACT_CMD_BKGRD_RG(v) ImpactCmdWriteRSS(0x140,((v)<<8))
+#define IMPACT_CMD_BKGRD_BA(v) ImpactCmdWriteRSS(0x141,((v)<<8))
+#define IMPACT_CMD_WINMODE(v) ImpactCmdWriteRSS(0x14f,v)
+#define IMPACT_CMD_XFRSIZE(x,y)
ImpactCmdWriteRSS(0x153,((y)<<16)|(x))
+#define IMPACT_CMD_XFRMASKLO(v) ImpactCmdWriteRSS(0x156,v)
+#define IMPACT_CMD_XFRMASKHI(v) ImpactCmdWriteRSS(0x157,v)
+#define IMPACT_CMD_XFRCOUNTERS(x,y) ImpactCmdWriteRSS(0x158,((y)<<16)|(x))
+#define IMPACT_CMD_XFRMODE(v) ImpactCmdWriteRSS(0x159,v)
+#define IMPACT_CMD_RE_TOGGLECNTX(v) ImpactCmdWriteRSS(0x15f,v)
+#define IMPACT_CMD_PIXCMD(v) ImpactCmdWriteRSS(0x160,v)
+#define IMPACT_CMD_PP1FILLMODE(m,o) ImpactCmdWriteRSS(0x161,(m)|(o<<26))
+#define IMPACT_CMD_COLORMASKMSBS(v) ImpactCmdWriteRSS(0x162,v)
+#define IMPACT_CMD_COLORMASKLSBSA(v) ImpactCmdWriteRSS(0x163,v)
+#define IMPACT_CMD_COLORMASKLSBSB(v) ImpactCmdWriteRSS(0x164,v)
+#define IMPACT_CMD_BLENDFACTOR(v) ImpactCmdWriteRSS(0x165,v)
+#define IMPACT_CMD_DRBPOINTERS(v) ImpactCmdWriteRSS(0x16d,v)
+
+#define IMPACT_CMD_HQ_PIXELFORMAT(v) ImpactCmdCFifo64(0x000c0004,0,v)
+#define IMPACT_CMD_HQ_SCANWIDTH(v) ImpactCmdCFifo64(0x000a0204,0,v)
+#define IMPACT_CMD_HQ_DMATYPE(v) ImpactCmdCFifo64(0x000a0604,0,v)
+#define IMPACT_CMD_HQ_PG_LIST_0(v) ImpactCmdCFifo64(0x00080004,0,v)
+#define IMPACT_CMD_HQ_PG_WIDTH(v) ImpactCmdCFifo64(0x00080404,0,v)
+#define IMPACT_CMD_HQ_PG_OFFSET(v) ImpactCmdCFifo64(0x00080504,0,v)
+#define IMPACT_CMD_HQ_PG_STARTADDR(v) ImpactCmdCFifo64(0x00080604,0,v)
+#define IMPACT_CMD_HQ_PG_LINECNT(v) ImpactCmdCFifo64(0x00080704,0,v)
+#define IMPACT_CMD_HQ_PG_WIDTHA(v) ImpactCmdCFifo64(0x00080804,0,v)
+#define IMPACT_CMD_HQ_DMACTRL_0(v) (0x00080b04000000b1LL|(v)&8)
+#define IMPACT_CMD_HQ_TXBASE(p) (0x00482008|((p)<<9))
+#define IMPACT_CMD_HQ_TXMAX(p,v) ImpactCmdCFifo64(0x00483004,p,v)
+#define IMPACT_CMD_HQ_PGBITS(p,v) ImpactCmdCFifo64(0x00482b04,p,v)
+#define IMPACT_CMD_HQ_PGSIZE(v) ImpactCmdCFifo64(0x00482a04,0,v)
+#define IMPACT_CMD_HQ_STACKPTR(v) ImpactCmdCFifo64(0x00483a04,0,v)
+#define IMPACT_CMD_HQ_484A(p,v) ImpactCmdCFifo64(0x00484a04,p,v)
+#define IMPACT_CMD_HQ_484B(p,v) ImpactCmdCFifo64(0x00484b04,p,v)
+
+/* Logic operations for the PP1 (SI=source invert, DI=dest invert, RI=result
invert) */
+#define IMPACT_LO_CLEAR 0
+#define IMPACT_LO_AND 1
+#define IMPACT_LO_DIAND 2
+#define IMPACT_LO_COPY 3
+#define IMPACT_LO_SIAND 4
+#define IMPACT_LO_NOP 5
+#define IMPACT_LO_XOR 6
+#define IMPACT_LO_OR 7
+#define IMPACT_LO_RIOR 8
+#define IMPACT_LO_RIXOR 9
+#define IMPACT_LO_RINOP 10
+#define IMPACT_LO_DIOR 11
+#define IMPACT_LO_RICOPY 12
+#define IMPACT_LO_SIOR 13
+#define IMPACT_LO_RIAND 14
+#define IMPACT_LO_SET 15
+
+/* Blending factors */
+#define IMPACT_BLEND_ALPHA 0x0704c900
+
+#ifdef __KERNEL__
+extern void impact_earlychar(unsigned char c);
+extern void impact_earlystring(char *s);
+extern void impact_earlyinit(void);
+extern void setup_impact_earlycons(void);
+#endif
+
+struct impact_cf_args
+{
+ struct winsize box; /* termios.h */
+ unsigned long long base;
+ unsigned bpitch;
+};
+
+#endif /* IMPACT_H */
|