int GGI_m2164w_fillscreen(struct ggi_visual *vis) { struct m2164w_priv *priv = M2164W_PRIV(vis); volatile uint8_t *mmioaddr = FBDEV_PRIV(vis)->mmioaddr; int virtx = LIBGGI_VIRTX(vis); int virty = LIBGGI_VIRTY(vis); int yadd = vis->w_frame_num * LIBGGI_VIRTY(vis); mga_gcupdate(mmioaddr, priv, LIBGGI_MODE(vis), LIBGGI_GC(vis), LIBGGI_VIRTX(vis), yadd); if (priv->dwgctl != priv->drawboxcmd) { mga_waitfifo(mmioaddr, 3); mga_setdwgctl(mmioaddr, priv, priv->drawboxcmd); } else { mga_waitfifo(mmioaddr, 2); } mga_out32(mmioaddr, (unsigned)RS16(virtx) << 16, FXBNDRY); mga_out32(mmioaddr, (unsigned)(RS16(yadd) << 16) | RS16(virty + yadd), YDSTLEN | EXECUTE); vis->accelactive = 1; return 0; }
int GGI_m2164w_drawline(ggi_visual *vis, int x, int y, int x2, int y2) { struct m2164w_priv *priv = M2164W_PRIV(vis); volatile uint8_t *mmioaddr = FBDEV_PRIV(vis)->mmioaddr; int yadd = vis->w_frame_num * LIBGGI_VIRTY(vis); uint32_t dwgctl; if (yadd) { y += yadd; y2 += yadd; } dwgctl = OP_AUTOLINE_CLOSE | SOLID | SHFTZERO | BOP_COPY | BLTMOD_BFCOL; mga_gcupdate(mmioaddr, priv, LIBGGI_MODE(vis), LIBGGI_GC(vis), LIBGGI_VIRTX(vis), yadd); if (priv->dwgctl != dwgctl) { mga_waitfifo(mmioaddr, 3); mga_setdwgctl(mmioaddr, priv, dwgctl); } else { mga_waitfifo(mmioaddr, 2); } mga_out32(mmioaddr, (unsigned)RS16(x) | (RS16(y) << 16), XYSTRT); mga_out32(mmioaddr, (unsigned)RS16(x2) | (RS16(y2) << 16), XYEND | EXECUTE); vis->accelactive = 1; return 0; }
/* This could be moved to default/color as a stub. It isn't fbdev-local. */ int GGI_fbdev_getgammamap(ggi_visual *vis, int start, int len, ggi_color *colormap) { ggi_fbdev_priv *priv; int i; priv = FBDEV_PRIV(vis); if (colormap == NULL) return GGI_EARGINVAL; if (vis->gamma == NULL) return GGI_ENOMATCH; /* wrong GT if not hooked */ if (vis->gamma->map == NULL) return GGI_EARGINVAL; if (start < 0 || start >= vis->gamma->len) return GGI_ENOSPACE; if (len > (vis->gamma->len - start)) return GGI_ENOSPACE; i = 0; do { if ((start + i) < vis->gamma->maxread_r) colormap[i].r = vis->gamma->map[start + i].r; if ((start + i) < vis->gamma->maxread_g) colormap[i].g = vis->gamma->map[start + i].g; if ((start + i) < vis->gamma->maxread_b) colormap[i].b = vis->gamma->map[start + i].b; } while (i++ < len); return 0; }
/* Free palette/gamma entries. Called before changing modes. */ void GGI_fbdev_color_free(ggi_visual *vis) { ggi_fbdev_priv *priv = FBDEV_PRIV(vis); /* Unhook the entry points */ LIBGGI_PAL(vis)->setPalette = NULL; LIBGGI_PAL(vis)->getPrivSize = NULL; vis->opcolor->getpalvec = NULL; /* ##### */ vis->opcolor->setgammamap = NULL; vis->opcolor->getgammamap = NULL; /* Free the convenience array */ free (LIBGGI_PAL(vis)->priv); LIBGGI_PAL(vis)->priv = NULL; /* * Clean up any pointers that could be problematic if left set. * Technically they should be taken care of below, but why not... */ priv->reds = priv->greens = priv->blues = NULL; vis->gamma = NULL; /* Free the storage area for the palettes. */ priv->gamma.map = priv->orig_cmap = NULL; free (LIBGGI_PAL(vis)->clut.data); LIBGGI_PAL(vis)->clut.data = NULL; }
int GGI_m2164w_drawbox(struct ggi_visual *vis, int x, int y, int w, int h) { if (w > 0 && h > 0) { /* 0 width is not OK! */ struct m2164w_priv *priv = M2164W_PRIV(vis); volatile uint8_t *mmioaddr = FBDEV_PRIV(vis)->mmioaddr; int yadd = vis->w_frame_num * LIBGGI_VIRTY(vis); y += yadd; mga_gcupdate(mmioaddr, priv, LIBGGI_MODE(vis), LIBGGI_GC(vis), LIBGGI_VIRTX(vis), yadd); if (priv->dwgctl != priv->drawboxcmd) { mga_waitfifo(mmioaddr, 3); mga_setdwgctl(mmioaddr, priv, priv->drawboxcmd); } else { mga_waitfifo(mmioaddr, 2); } mga_out32(mmioaddr, (unsigned)(RS16(x + w) << 16) | RS16(x), FXBNDRY); mga_out32(mmioaddr, (unsigned)(RS16(y) << 16) | RS16(h), YDSTLEN | EXECUTE); vis->accelactive = 1; } return 0; }
int GGI_mga_g400_drawhline(ggi_visual *vis, int x, int y, int w) { struct mga_g400_priv *priv = MGA_G400_PRIV(vis); volatile uint8_t *mmioaddr = FBDEV_PRIV(vis)->mmioaddr; int yadd = vis->w_frame_num * LIBGGI_VIRTY(vis); uint32_t dwgctl; y += yadd; y = RS16(y) << 16; dwgctl = OP_AUTOLINE_CLOSE | SOLID | SHFTZERO | BOP_COPY | BLTMOD_BFCOL; mga_gcupdate(mmioaddr, priv, LIBGGI_MODE(vis), LIBGGI_GC(vis), LIBGGI_VIRTX(vis), yadd); if (priv->dwgctl != dwgctl) { mga_waitfifo(mmioaddr, 3); mga_setdwgctl(mmioaddr, priv, dwgctl); } else { mga_waitfifo(mmioaddr, 2); } /* y has been shifted above */ mga_out32(mmioaddr, (unsigned)RS16(x) | y, XYSTRT); mga_out32(mmioaddr, (unsigned)RS16(x + w-1) | y, XYEND | EXECUTE); vis->accelactive = 1; return 0; }
int GGI_3dlabs_pm2_drawhline(struct ggi_visual *vis, int x, int y, int w) { struct _3dlabs_pm2_priv *priv = PM2_PRIV(vis); volatile uint8_t *mmioaddr = FBDEV_PRIV(vis)->mmioaddr; int yadd = vis->w_frame_num * LIBGGI_VIRTY(vis); DPRINT_DRAW("drawhline(%p, %i,%i, %i) entered\n", vis, x,y, w); y += yadd; pm2_gcupdate(mmioaddr, priv, LIBGGI_MODE(vis), LIBGGI_GC(vis), yadd); pm2_waitfifo(mmioaddr, 6); pm2_out32(mmioaddr, x << 16, PM2R_START_X_DOM); pm2_out32(mmioaddr, y << 16, PM2R_START_Y); /* Horizontal */ pm2_out32(mmioaddr, 1 << 16, PM2R_D_X_DOM); pm2_out32(mmioaddr, 0 << 16, PM2R_D_Y); pm2_out32(mmioaddr, w, PM2R_COUNT); pm2_out32(mmioaddr, PM2F_RENDER_LINE | PM2F_RENDER_XPOSITIVE | PM2F_RENDER_YPOSITIVE, PM2R_RENDER); vis->accelactive = 1; return 0; }
static int m2164w_idleaccel(ggi_visual *vis) { DPRINT_DRAW("m2164w_idleaccel(%p) called \n", vis); mga_waitidle(FBDEV_PRIV(vis)->mmioaddr); vis->accelactive = 0; return 0; }
static int do_cleanup(ggi_visual *vis) { ggi_fbdev_priv *fbdevpriv = FBDEV_PRIV(vis); struct m2164w_priv *priv = NULL; int i; DPRINT_MISC("mga-2164w: Starting cleanup\n"); if (fbdevpriv != NULL) { priv = M2164W_PRIV(vis); } /* We may be called more than once due to the LibGG cleanup stuff */ if (priv == NULL) return 0; /* Restore OPMODE and terminate any pending DMA operations Manual says we should write to byte 0 to terminate DMA sequence, but it doesn't say whether a 8 bit access is required, or if any access will do. We play it safe here... */ mga_out8(fbdevpriv->mmioaddr, priv->origopmode & 0xff, OPMODE); mga_out16(fbdevpriv->mmioaddr, priv->origopmode, OPMODE); mga_waitidle(fbdevpriv->mmioaddr); munmap((void*)fbdevpriv->mmioaddr, fbdevpriv->orig_fix.mmio_len); DPRINT_MISC("mga-2164w: Unmapped MMIO\n"); /* Free DB resource structures */ for (i = LIBGGI_APPLIST(vis)->num-1; i >= 0; i--) { if (LIBGGI_APPBUFS(vis)[i]->resource) { free(LIBGGI_APPBUFS(vis)[i]->resource); LIBGGI_APPBUFS(vis)[i]->resource = NULL; } } free(priv); FBDEV_PRIV(vis)->accelpriv = NULL; ggUnregisterCleanup((ggcleanup_func *)do_cleanup, vis); return 0; }
static int GGIopen(ggi_visual *vis, struct ggi_dlhandle *dlh, const char *args, void *argptr, uint32_t *dlret) { struct fbdev_directfb_global *globals; globals = argptr; globals->dfb_config_ptr = &dfb_config; globals->dfb_fbdev_ptr = &dfb_fbdev; ggi_fbdev_dfb_framebuffer_base = FBDEV_PRIV(vis)->fb_ptr; return 0; }
/* In fbdev the gamma uses the same interface as the palette. * Therefore, no simultaneous use of 8-bit LUT and gamma. * * Since this is the case we reuse some of the priv/vis palette members. * */ static int GGI_fbdev_setgammamap(ggi_visual *vis, int start, int len, const ggi_color *colormap) { ggi_fbdev_priv *priv; struct fb_cmap gam; int i; priv = FBDEV_PRIV(vis); if (colormap == NULL) return GGI_EARGINVAL; if (vis->gamma == NULL) return GGI_ENOMATCH; /* Wrong GT if not hooked */ if (start < 0 || start >= priv->gamma.len) return GGI_ENOSPACE; if (len > (priv->gamma.len - start)) return GGI_ENOSPACE; gam.start = start; gam.len = len; gam.red = priv->reds; gam.green = priv->greens; gam.blue = priv->blues; gam.transp = NULL; i = 0; do { if ((start + i) < priv->gamma.maxwrite_r) vis->gamma->map[start + i].r = priv->reds[start + i] = colormap[i].r; if ((start + i) < priv->gamma.maxwrite_g) vis->gamma->map[start + i].g = priv->greens[start + i] = colormap[i].g; if ((start + i) < priv->gamma.maxwrite_b) vis->gamma->map[start + i].b = priv->blues[start + i] = colormap[i].b; } while (i++ < len); if (fbdev_doioctl(vis, FBIOPUTCMAP, &gam) < 0) { DPRINT_COLOR("display-fbdev: PUTCMAP failed."); return -1; } return 0; }
static int GGI_fbdev_setPalette(ggi_visual *vis, size_t start, size_t size, const ggi_color *colormap) { ggi_fbdev_priv *priv = FBDEV_PRIV(vis); struct fb_cmap cmap; int len = (int)size; const ggi_color* src = colormap; DPRINT_COLOR("display-fbdev: SetPalette(%d,%d)\n", start, size); memcpy(LIBGGI_PAL(vis)->clut.data+start, colormap, size*sizeof(ggi_color)); if (!priv->ismapped) return 0; cmap.start = start; cmap.len = size; cmap.red = priv->reds + start; cmap.green = priv->greens + start; cmap.blue = priv->blues + start; cmap.transp = NULL; for (; len > 0; start++, src++, len--) { priv->reds[start] = src->r; priv->greens[start] = src->g; priv->blues[start] = src->b; } if (fbdev_doioctl(vis, FBIOPUTCMAP, &cmap) < 0) { DPRINT_COLOR("display-fbdev: PUTCMAP failed."); return -1; } return 0; }
static int GGIopen(ggi_visual *vis, struct ggi_dlhandle *dlh, const char *args, void *argptr, uint32_t *dlret) { ggi_fbdev_priv *fbdevpriv = FBDEV_PRIV(vis); struct m2164w_priv *priv; unsigned long usedmemend; size_t fontlen; int pixbytes; int fd = LIBGGI_FD(vis); int i; if (GT_SIZE(LIBGGI_GT(vis)) % 8 != 0 || GT_SIZE(LIBGGI_GT(vis)) > 32 || GT_SIZE(LIBGGI_GT(vis)) < 8) { /* Unsupported mode */ return GGI_ENOFUNC; } pixbytes = GT_ByPP(LIBGGI_GT(vis)); priv = malloc(sizeof(struct m2164w_priv)); if (priv == NULL) { return GGI_ENOMEM; } fbdevpriv->mmioaddr = mmap(NULL, fbdevpriv->orig_fix.mmio_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (signed)fbdevpriv->orig_fix.smem_len); if (fbdevpriv->mmioaddr == MAP_FAILED) { /* Can't mmap() MMIO region - bail out */ DPRINT_LIBS("mga-2164w: Unable to map MMIO region: %s\n" " fd: %d, len: %ld, offset: %ld\n", strerror(errno), fd, fbdevpriv->orig_fix.mmio_len, fbdevpriv->orig_fix.smem_len); fbdevpriv->mmioaddr = NULL; free(priv); return GGI_ENODEVICE; } DPRINT_MISC("mga-2164w: Mapped MMIO region at %p\n", fbdevpriv->mmioaddr); /* Set up DirectBuffers */ for (i=0; i < LIBGGI_MODE(vis)->frames; i++) { ggi_directbuffer *buf = LIBGGI_APPBUFS(vis)[i]; ggi_resource *res; res = malloc(sizeof(ggi_resource)); if (res == NULL) { do_cleanup(vis); return GGI_ENOMEM; } buf->resource = res; buf->resource->acquire = m2164w_acquire; buf->resource->release = m2164w_release; buf->resource->self = buf; buf->resource->priv = vis; buf->resource->count = 0; buf->resource->curactype = 0; } priv->drawboxcmd = BOP_COPY | SHFTZERO | SGNZERO | ARZERO | SOLID | OP_TRAP; if (pixbytes != 3) { switch (fbdevpriv->orig_fix.accel) { case FB_ACCEL_MATROX_MGA2064W: case FB_ACCEL_MATROX_MGA1064SG: case FB_ACCEL_MATROX_MGA2164W: case FB_ACCEL_MATROX_MGA2164W_AGP: /* Use block mode */ priv->drawboxcmd |= ATYPE_BLK; break; default: /* For now - assume SDRAM for other cards */ break; } } priv->dwgctl = 0; priv->oldfgcol = LIBGGI_GC(vis)->fg_color - 1; priv->oldbgcol = LIBGGI_GC(vis)->bg_color - 1; priv->oldtl.x = -1; priv->oldtl.y = -1; priv->oldbr.x = -1; priv->oldbr.y = -1; priv->oldyadd = -1; priv->curopmode = priv->origopmode = mga_in16(fbdevpriv->mmioaddr, OPMODE); /* Use the 7k Pseudo-DMA window */ priv->dmaaddr = (void*)fbdevpriv->mmioaddr; priv->dma_len = 0x1c00; vis->needidleaccel = 1; fbdevpriv->idleaccel = m2164w_idleaccel; /* Accelerate fonts if possible */ priv->font = (uint8_t *)(font); usedmemend = LIBGGI_MODE(vis)->frames * fbdevpriv->fix.line_length * LIBGGI_VIRTY(vis); fontlen = 256*8; priv->fontoffset = fbdevpriv->orig_fix.smem_len - fontlen; priv->fontoffset &= ~127; /* Align */ DPRINT_MISC("mga-2164w: usedmemend: %ld, fontoffset: %ld\n", usedmemend, priv->fontoffset); if (usedmemend <= priv->fontoffset) { memcpy((uint8_t*)fbdevpriv->fb_ptr + priv->fontoffset, font, fontlen); priv->fontoffset *= 8; /* In bits */ priv->charadd = FWIDTH*FHEIGHT; vis->opdraw->putc = GGI_m2164w_fastputc; vis->opdraw->puts = GGI_m2164w_fastputs; DPRINT_MISC("mga-2164w: Using fast chars\n"); } else { priv->fontoffset = 0; vis->opdraw->putc = GGI_m2164w_putc; vis->opdraw->puts = GGI_m2164w_puts; DPRINT_MISC("mga-2164w: Using slow chars\n"); } /* Save previous function pointers */ priv->crossblit = vis->opdraw->crossblit; /* Initialize function pointers */ vis->opdraw->getcharsize= GGI_m2164w_getcharsize; vis->opdraw->drawhline = GGI_m2164w_drawhline; vis->opdraw->drawvline = GGI_m2164w_drawvline; vis->opdraw->drawline = GGI_m2164w_drawline; vis->opdraw->drawbox = GGI_m2164w_drawbox; vis->opdraw->copybox = GGI_m2164w_copybox; vis->opdraw->fillscreen = GGI_m2164w_fillscreen; /* The crossblit in linear-* is faster on truecolor modes! */ if (GT_SCHEME(LIBGGI_GT(vis)) == GT_PALETTE || GT_SCHEME(LIBGGI_GT(vis)) == GT_STATIC_PALETTE) { vis->opdraw->crossblit = GGI_m2164w_crossblit; } FBDEV_PRIV(vis)->accelpriv = priv; /* Register cleanup handler */ ggRegisterCleanup((ggcleanup_func *)do_cleanup, vis); *dlret = GGI_DL_OPDRAW; return 0; }
int GGI_mga_g400_copybox(ggi_visual *vis, int x, int y, int w, int h, int dstx, int dsty) { struct mga_g400_priv *priv = MGA_G400_PRIV(vis); volatile uint8_t *mmioaddr = FBDEV_PRIV(vis)->mmioaddr; int virtx = LIBGGI_VIRTX(vis); int yadd = vis->w_frame_num * LIBGGI_VIRTY(vis); int32_t ar5 = virtx; int32_t begin, end; uint32_t sgn = 0; uint32_t dwgctl; #define COPY_LEFT 1 #define COPY_UP 4 dsty += yadd; y += vis->r_frame_num*LIBGGI_VIRTY(vis); if (dsty > y) { sgn |= COPY_UP; y += h - 1; dsty += h - 1; ar5 = - ar5; } begin = end = y * virtx + x; w--; if (dstx > x) { sgn |= COPY_LEFT; begin += w; } else { end += w; } dwgctl = BLTMOD_BFCOL | BOP_COPY | SHFTZERO | OP_BITBLT | (sgn ? 0 : SGNZERO); mga_gcupdate(mmioaddr, priv, LIBGGI_MODE(vis), LIBGGI_GC(vis), virtx, yadd); if (priv->dwgctl != dwgctl) { if (sgn) mga_waitfifo(mmioaddr, 7); else mga_waitfifo(mmioaddr, 6); mga_setdwgctl(mmioaddr, priv, dwgctl); } else { if (sgn) mga_waitfifo(mmioaddr, 6); else mga_waitfifo(mmioaddr, 5); } if (sgn) { mga_out32(mmioaddr, sgn, SGN); } #if 0 mga_out32(mmioaddr, RS18(end), AR0); mga_out32(mmioaddr, RS24(begin), AR3); mga_out32(mmioaddr, RS18(ar5), AR5); #else mga_out32(mmioaddr, RS22(end), AR0); mga_out32(mmioaddr, RS24(begin), AR3); mga_out32(mmioaddr, RS22(ar5), AR5); #endif mga_out32(mmioaddr, (unsigned)(RS16(dstx + w) << 16) | RS16(dstx), FXBNDRY); mga_out32(mmioaddr, (unsigned)(RS16(dsty) << 16) | RS16(h), YDSTLEN | EXECUTE); vis->accelactive = 1; return 0; }
static inline void dbblit_32bpp(ggi_visual *src, int sx, int sy, int w, int h, ggi_visual *dst, int dx, int dy, uint32_t srcfmt) { struct m2164w_priv *priv = M2164W_PRIV(dst); volatile uint8_t *mmioaddr = FBDEV_PRIV(dst)->mmioaddr; int yadd = dst->w_frame_num * LIBGGI_VIRTY(dst); volatile uint32_t *dstptr; uint32_t dwgctl, bltmod = BLTMOD_BU32RGB; uint16_t opmode; uint8_t *srcptr; uint32_t *srcptr32; int srcinc; int maxpix; dstptr = priv->dmaaddr; srcinc = LIBGGI_FB_R_STRIDE(src); srcptr = (uint8_t*) LIBGGI_CURWRITE(src) + sy*srcinc + sx*4; srcinc -= w*4; maxpix = priv->dma_len/4; dy += yadd; switch (srcfmt) { #if 0 /* This case is the default. */ case GGI_DB_STD_24a32p8r8g8b8: bltmod = BLTMOD_BU32RGB; break; #endif case GGI_DB_STD_24a32p8b8g8r8: bltmod = BLTMOD_BU32BGR; break; } dwgctl = bltmod | BOP_COPY | SHFTZERO | OP_ILOAD | SGNZERO; #ifdef GGI_BIG_ENDIAN opmode = OPMODE_DMA_BLIT_WRITE | OPMODE_DMA_BE_32BPP; #else opmode = OPMODE_DMA_BLIT_WRITE | OPMODE_DMA_LE; #endif mga_gcupdate(mmioaddr, priv, LIBGGI_MODE(dst), LIBGGI_GC(dst), LIBGGI_VIRTX(dst), yadd); if (priv->curopmode != opmode) { priv->curopmode = opmode; mga_waitidle(mmioaddr); mga_out16(mmioaddr, opmode, OPMODE); } if (priv->dwgctl != dwgctl) { mga_waitfifo(mmioaddr, 6); mga_setdwgctl(mmioaddr, priv, dwgctl); } else { mga_waitfifo(mmioaddr, 5); } mga_out32(mmioaddr, RS18(w-1), AR0); mga_out32(mmioaddr, 0, AR3); mga_out32(mmioaddr, 0, AR5); mga_out32(mmioaddr, (unsigned)(RS16(dx + w - 1) << 16) | RS16(dx), FXBNDRY); mga_out32(mmioaddr, (unsigned)(RS16(dy) << 16) | RS16(h), YDSTLEN | EXECUTE); dst->accelactive = 1; if (w > maxpix) { while (h--) { int tmpw = w; while (tmpw) { int tmpw2 = (tmpw > maxpix ? maxpix : tmpw); tmpw -= tmpw2; while (tmpw2--) { srcptr32 = (uint32_t *)srcptr; *(dstptr++) = *(srcptr32++); srcptr = (uint8_t *)srcptr32; } dstptr = priv->dmaaddr; } srcptr += srcinc; } } else { while (h--) { int tmpw = w; while (tmpw--) { srcptr32 = (uint32_t *)srcptr; *(dstptr++) = *(srcptr32++); srcptr = (uint8_t *)srcptr32; } srcptr += srcinc; dstptr = priv->dmaaddr; } } }
void GGI_fbdev_color_setup(ggi_visual *vis) { ggi_fbdev_priv *priv = FBDEV_PRIV(vis); struct fb_cmap cmap; int len; /* We rely on caller to have deallocated old storage */ priv->orig_cmap = LIBGGI_PAL(vis)->clut.data = priv->gamma.map = NULL; vis->gamma = NULL; priv->reds = priv->greens = priv->blues = NULL; priv->gamma.maxread_r = priv->gamma.maxread_g = priv->gamma.maxread_b = priv->gamma.maxread_r = priv->gamma.maxwrite_g = priv->gamma.maxwrite_b = -1; priv->gamma.len = priv->gamma.start = 0; if (!priv->var.bits_per_pixel) return; if (priv->fix.visual == FB_VISUAL_TRUECOLOR) return; /* No gamma. */ if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR) { DPRINT("display-fbdev: trying gamma.\n"); priv->gamma.maxwrite_r = priv->gamma.maxread_r = 1 << priv->var.red.length; priv->gamma.maxwrite_g = priv->gamma.maxread_g = 1 << priv->var.green.length; priv->gamma.maxwrite_b = priv->gamma.maxread_b = 1 << priv->var.blue.length; len = priv->gamma.maxread_r; if (len < priv->gamma.maxread_g) len = priv->gamma.maxread_g; if (len < priv->gamma.maxread_b) len = priv->gamma.maxread_b; priv->gamma.len = len; priv->gamma.start = 0; LIBGGI_PAL(vis)->clut.size = len * 2; LIBGGI_PAL(vis)->clut.data = calloc(len * 2 /* orig */, sizeof(ggi_color)); if (LIBGGI_PAL(vis)->clut.data == NULL) return; priv->gamma.map = LIBGGI_PAL(vis)->clut.data; /* All of the above is moot until we turn it on like so: */ vis->gamma = &(priv->gamma); } else { DPRINT("display-fbdev: trying palette.\n"); len = 1 << priv->var.bits_per_pixel; LIBGGI_PAL(vis)->clut.size = len * 2; LIBGGI_PAL(vis)->clut.data = calloc(len * 2 /* orig */, sizeof(ggi_color)); if (LIBGGI_PAL(vis)->clut.data == NULL) return; } cmap.start = 0; cmap.len = len; cmap.red = calloc(len * 3, 2); if (cmap.red == NULL) goto bail; cmap.green = cmap.red + len; cmap.blue = cmap.green + len; cmap.transp = NULL; if (ioctl(LIBGGI_FD(vis), FBIOGETCMAP, &cmap) < 0) { DPRINT_COLOR("display-fbdev: GETCMAP failed.\n"); free(cmap.red); goto bail; } priv->orig_cmap = LIBGGI_PAL(vis)->clut.data + len; if (vis->gamma != NULL) { DPRINT_COLOR("display-fbdev: Saved gamma (len=%d/%d/%d).\n", priv->gamma.maxread_r, priv->gamma.maxread_g, priv->gamma.maxread_b); while (len--) { if (len < priv->gamma.maxread_r) priv->orig_cmap[len].r = cmap.red[len]; if (len < priv->gamma.maxread_g) priv->orig_cmap[len].g = cmap.green[len]; if (len < priv->gamma.maxread_b) priv->orig_cmap[len].b = cmap.blue[len]; } vis->opcolor->getgammamap = GGI_fbdev_getgammamap; vis->opcolor->setgammamap = GGI_fbdev_setgammamap; } else { DPRINT_COLOR("display-fbdev: Saved palette (len=%d).\n", len); while (len--) { priv->orig_cmap[len].r = cmap.red[len]; priv->orig_cmap[len].g = cmap.green[len]; priv->orig_cmap[len].b = cmap.blue[len]; } if (priv->fix.visual != FB_VISUAL_STATIC_PSEUDOCOLOR) { LIBGGI_PAL(vis)->setPalette = GGI_fbdev_setPalette; LIBGGI_PAL(vis)->getPrivSize = GGI_fbdev_getPrivSize; } } LIBGGI_PAL(vis)->priv = cmap.red; priv->reds = cmap.red; priv->greens = cmap.green; priv->blues = cmap.blue; return; bail: free(LIBGGI_PAL(vis)->clut.data); LIBGGI_PAL(vis)->clut.data = NULL; vis->gamma = NULL; return; }
int GGI_3dlabs_pm2_puthline(struct ggi_visual *vis, int x, int y, int w, const void *buf) { struct _3dlabs_pm2_priv *priv = PM2_PRIV(vis); volatile uint8_t *mmioaddr = FBDEV_PRIV(vis)->mmioaddr; int yadd = vis->w_frame_num * LIBGGI_VIRTY(vis); int count; #if 0 uint32_t srcwidth; #endif const uint8_t *src; const uint32_t *srcp; uint32_t *dest; /* 0 width not OK */ if (w == 0) return 0; DPRINT_DRAW("puthline(%p, %i,%i, %i, %p) entered\n", vis, x, y, w, buf); y += yadd; #if 0 if (LIBGGI_GT(vis) & GT_SUB_PACKED_GETPUT) { srcwidth = GT_ByPPP(w, LIBGGI_GT(vis)); } else { srcwidth = w * GT_ByPP(LIBGGI_GT(vis)); } #endif pm2_gcupdate(mmioaddr, priv, LIBGGI_MODE(vis), LIBGGI_GC(vis), yadd); pm2_waitfifo(mmioaddr, 6); /* Setting for Image download from Host */ pm2_out32(mmioaddr, priv->pprod, PM2R_FB_READ_MODE); pm2_out32(mmioaddr, UNIT_ENABLE, PM2R_FB_WRITE_MODE); pm2_out32(mmioaddr, UNIT_DISABLE, PM2R_COLOR_DDA_MODE); pm2_loadcoord(mmioaddr, x,y, w, 1); pm2_out32(mmioaddr, PM2F_RENDER_RECTANGLE | PM2F_RENDER_XPOSITIVE | PM2F_RENDER_YPOSITIVE | PM2F_RENDER_SYNC_ON_HOST, PM2R_RENDER); src = (const uint8_t *)buf; dest = (uint32_t *)((volatile uint8_t *) (mmioaddr + PM2R_OUT_FIFO + 4)); count = w; srcp = (const uint32_t *)src; while (count >= priv->fifosize) { pm2_waitfifo(mmioaddr, priv->fifosize); /* 0x0155 is the TAG for FBSourceData */ pm2_out32(mmioaddr, ((priv->fifosize - 2) << 16) | 0x0155, PM2R_OUT_FIFO); pm2_move32(dest, srcp, priv->fifosize - 1); count -= priv->fifosize - 1; srcp += priv->fifosize - 1; } if (count) { pm2_waitfifo(mmioaddr, count + 1); pm2_out32(mmioaddr, ((count - 1) << 16) | 0x0155, PM2R_OUT_FIFO); pm2_move32(dest, srcp, count); } /* Re-enable fb readmode when done */ pm2_waitfifo(mmioaddr, 2); pm2_out32(mmioaddr, 0, PM2R_WAIT_FOR_COMPLETION); priv->oldfgcol = ~priv->oldfgcol; vis->accelactive = 1; return 0; }