Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/video/fbdev/matrox/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 14 kB image not shown  

Quelle  matroxfb_accel.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 *
 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
 *
 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
 *
 * Version: 1.65 2002/08/14
 *
 * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
 *
 * Contributors: "menion?" <menion@mindless.com>
 *                     Betatesting, fixes, ideas
 *
 *               "Kurt Garloff" <garloff@suse.de>
 *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
 *
 *               "Tom Rini" <trini@kernel.crashing.org>
 *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
 *
 *               "Bibek Sahu" <scorpio@dodds.net>
 *                     Access device through readb|w|l and write b|w|l
 *                     Extensive debugging stuff
 *
 *               "Daniel Haun" <haund@usa.net>
 *                     Testing, hardware cursor fixes
 *
 *               "Scott Wood" <sawst46+@pitt.edu>
 *                     Fixes
 *
 *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
 *                     Betatesting
 *
 *               "Kelly French" <targon@hazmat.com>
 *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
 *                     Betatesting, bug reporting
 *
 *               "Pablo Bianucci" <pbian@pccp.com.ar>
 *                     Fixes, ideas, betatesting
 *
 *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
 *                     Fixes, enhandcements, ideas, betatesting
 *
 *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
 *                     PPC betatesting, PPC support, backward compatibility
 *
 *               "Paul Womar" <Paul@pwomar.demon.co.uk>
 *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
 *                     PPC betatesting
 *
 *               "Thomas Pornin" <pornin@bolet.ens.fr>
 *                     Alpha betatesting
 *
 *               "Pieter van Leuven" <pvl@iae.nl>
 *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
 *                     G100 testing
 *
 *               "H. Peter Arvin" <hpa@transmeta.com>
 *                     Ideas
 *
 *               "Cort Dougan" <cort@cs.nmt.edu>
 *                     CHRP fixes and PReP cleanup
 *
 *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
 *                     G400 support
 *
 * (following author is not in any relation with this code, but his code
 *  is included in this driver)
 *
 * Based on framebuffer driver for VBE 2.0 compliant graphic boards
 *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
 *
 * (following author is not in any relation with this code, but his ideas
 *  were used when writing this driver)
 *
 *  FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
 *
 */


#include <linux/export.h>

#include "matroxfb_accel.h"
#include "matroxfb_DAC1064.h"
#include "matroxfb_Ti3026.h"
#include "matroxfb_misc.h"

#define curr_ydstorg(x) ((x)->curr.ydstorg.pixels)

#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))

static inline void matrox_cfb4_pal(u_int32_t* pal) {
 unsigned int i;

 for (i = 0; i < 16; i++) {
  pal[i] = i * 0x11111111U;
 }
}

static inline void matrox_cfb8_pal(u_int32_t* pal) {
 unsigned int i;

 for (i = 0; i < 16; i++) {
  pal[i] = i * 0x01010101U;
 }
}

static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area);
static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image);
static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area);

void matrox_cfbX_init(struct matrox_fb_info *minfo)
{
 u_int32_t maccess;
 u_int32_t mpitch;
 u_int32_t mopmode;
 int accel;

 DBG(__func__)

 mpitch = minfo->fbcon.var.xres_virtual;

 minfo->fbops.fb_copyarea = cfb_copyarea;
 minfo->fbops.fb_fillrect = cfb_fillrect;
 minfo->fbops.fb_imageblit = cfb_imageblit;
 minfo->fbops.fb_cursor = NULL;

 accel = (minfo->fbcon.var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT;

 switch (minfo->fbcon.var.bits_per_pixel) {
  case 4:  maccess = 0x00000000; /* accelerate as 8bpp video */
    mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
    mopmode = M_OPMODE_4BPP;
    matrox_cfb4_pal(minfo->cmap);
    if (accel && !(mpitch & 1)) {
     minfo->fbops.fb_copyarea = matroxfb_cfb4_copyarea;
     minfo->fbops.fb_fillrect = matroxfb_cfb4_fillrect;
    }
    break;
  case 8:  maccess = 0x00000000;
    mopmode = M_OPMODE_8BPP;
    matrox_cfb8_pal(minfo->cmap);
    if (accel) {
     minfo->fbops.fb_copyarea = matroxfb_copyarea;
     minfo->fbops.fb_fillrect = matroxfb_fillrect;
     minfo->fbops.fb_imageblit = matroxfb_imageblit;
    }
    break;
  case 16: if (minfo->fbcon.var.green.length == 5)
     maccess = 0xC0000001;
    else
     maccess = 0x40000001;
    mopmode = M_OPMODE_16BPP;
    if (accel) {
     minfo->fbops.fb_copyarea = matroxfb_copyarea;
     minfo->fbops.fb_fillrect = matroxfb_fillrect;
     minfo->fbops.fb_imageblit = matroxfb_imageblit;
    }
    break;
  case 24: maccess = 0x00000003;
    mopmode = M_OPMODE_24BPP;
    if (accel) {
     minfo->fbops.fb_copyarea = matroxfb_copyarea;
     minfo->fbops.fb_fillrect = matroxfb_fillrect;
     minfo->fbops.fb_imageblit = matroxfb_imageblit;
    }
    break;
  case 32: maccess = 0x00000002;
    mopmode = M_OPMODE_32BPP;
    if (accel) {
     minfo->fbops.fb_copyarea = matroxfb_copyarea;
     minfo->fbops.fb_fillrect = matroxfb_fillrect;
     minfo->fbops.fb_imageblit = matroxfb_imageblit;
    }
    break;
  default: maccess = 0x00000000;
    mopmode = 0x00000000;
    break/* turn off acceleration!!! */
 }
 mga_fifo(8);
 mga_outl(M_PITCH, mpitch);
 mga_outl(M_YDSTORG, curr_ydstorg(minfo));
 if (minfo->capable.plnwt)
  mga_outl(M_PLNWT, -1);
 if (minfo->capable.srcorg) {
  mga_outl(M_SRCORG, 0);
  mga_outl(M_DSTORG, 0);
 }
 mga_outl(M_OPMODE, mopmode);
 mga_outl(M_CXBNDRY, 0xFFFF0000);
 mga_outl(M_YTOP, 0);
 mga_outl(M_YBOT, 0x01FFFFFF);
 mga_outl(M_MACCESS, maccess);
 minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
 if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC;
 minfo->accel.m_opmode = mopmode;
 minfo->accel.m_access = maccess;
 minfo->accel.m_pitch = mpitch;
}

EXPORT_SYMBOL(matrox_cfbX_init);

static void matrox_accel_restore_maccess(struct matrox_fb_info *minfo)
{
 mga_outl(M_MACCESS, minfo->accel.m_access);
 mga_outl(M_PITCH, minfo->accel.m_pitch);
}

static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
          int sx, int dy, int dx, int height, int width)
{
 int start, end;
 CRITFLAGS

 DBG(__func__)

 CRITBEGIN

 if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
  mga_fifo(4);
  matrox_accel_restore_maccess(minfo);
  mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
    M_DWG_BFCOL | M_DWG_REPLACE);
  mga_outl(M_AR5, vxres);
  width--;
  start = sy*vxres+sx+curr_ydstorg(minfo);
  end = start+width;
 } else {
  mga_fifo(5);
  matrox_accel_restore_maccess(minfo);
  mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
  mga_outl(M_SGN, 5);
  mga_outl(M_AR5, -vxres);
  width--;
  end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
  start = end+width;
  dy += height-1;
 }
 mga_fifo(6);
 matrox_accel_restore_maccess(minfo);
 mga_outl(M_AR0, end);
 mga_outl(M_AR3, start);
 mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
 mga_ydstlen(dy, height);
 WaitTillIdle();

 CRITEND
}

static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
       int sy, int sx, int dy, int dx, int height,
       int width)
{
 int start, end;
 CRITFLAGS

 DBG(__func__)

 CRITBEGIN

 if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
  mga_fifo(4);
  matrox_accel_restore_maccess(minfo);
  mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
   M_DWG_BFCOL | M_DWG_REPLACE);
  mga_outl(M_AR5, vxres);
  width--;
  start = sy*vxres+sx+curr_ydstorg(minfo);
  end = start+width;
 } else {
  mga_fifo(5);
  matrox_accel_restore_maccess(minfo);
  mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
  mga_outl(M_SGN, 5);
  mga_outl(M_AR5, -vxres);
  width--;
  end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
  start = end+width;
  dy += height-1;
 }
 mga_fifo(7);
 matrox_accel_restore_maccess(minfo);
 mga_outl(M_AR0, end);
 mga_outl(M_AR3, start);
 mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
 mga_outl(M_YDST, dy*vxres >> 5);
 mga_outl(M_LEN | M_EXEC, height);
 WaitTillIdle();

 CRITEND
}

static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
 struct matrox_fb_info *minfo = info2minfo(info);

 if ((area->sx | area->dx | area->width) & 1)
  cfb_copyarea(info, area);
 else
  matrox_accel_bmove_lin(minfo, minfo->fbcon.var.xres_virtual >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1);
}

static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
 struct matrox_fb_info *minfo = info2minfo(info);

 matrox_accel_bmove(minfo, minfo->fbcon.var.xres_virtual, area->sy, area->sx, area->dy, area->dx, area->height, area->width);
}

static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color,
     int sy, int sx, int height, int width)
{
 CRITFLAGS

 DBG(__func__)

 CRITBEGIN

 mga_fifo(7);
 matrox_accel_restore_maccess(minfo);
 mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE);
 mga_outl(M_FCOL, color);
 mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
 mga_ydstlen(sy, height);
 WaitTillIdle();

 CRITEND
}

static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
 struct matrox_fb_info *minfo = info2minfo(info);

 switch (rect->rop) {
  case ROP_COPY:
   matroxfb_accel_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
   break;
 }
}

static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx,
    int sy, int sx, int height, int width)
{
 int whattodo;
 CRITFLAGS

 DBG(__func__)

 CRITBEGIN

 whattodo = 0;
 if (sx & 1) {
  sx ++;
  if (!width) return;
  width --;
  whattodo = 1;
 }
 if (width & 1) {
  whattodo |= 2;
 }
 width >>= 1;
 sx >>= 1;
 if (width) {
  mga_fifo(7);
  matrox_accel_restore_maccess(minfo);
  mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2);
  mga_outl(M_FCOL, bgx);
  mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
  mga_outl(M_YDST, sy * minfo->fbcon.var.xres_virtual >> 6);
  mga_outl(M_LEN | M_EXEC, height);
  WaitTillIdle();
 }
 if (whattodo) {
  u_int32_t step = minfo->fbcon.var.xres_virtual >> 1;
  vaddr_t vbase = minfo->video.vbase;
  if (whattodo & 1) {
   unsigned int uaddr = sy * step + sx - 1;
   u_int32_t loop;
   u_int8_t bgx2 = bgx & 0xF0;
   for (loop = height; loop > 0; loop --) {
    mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2);
    uaddr += step;
   }
  }
  if (whattodo & 2) {
   unsigned int uaddr = sy * step + sx + width;
   u_int32_t loop;
   u_int8_t bgx2 = bgx & 0x0F;
   for (loop = height; loop > 0; loop --) {
    mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2);
    uaddr += step;
   }
  }
 }

 CRITEND
}

static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
 struct matrox_fb_info *minfo = info2minfo(info);

 switch (rect->rop) {
  case ROP_COPY:
   matroxfb_cfb4_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
   break;
 }
}

static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
        u_int32_t bgx, const u_int8_t *chardata,
        int width, int height, int yy, int xx)
{
 u_int32_t step;
 u_int32_t ydstlen;
 u_int32_t xlen;
 u_int32_t ar0;
 u_int32_t charcell;
 u_int32_t fxbndry;
 vaddr_t mmio;
 int easy;
 CRITFLAGS

 DBG_HEAVY(__func__);

 step = (width + 7) >> 3;
 charcell = height * step;
 xlen = (charcell + 3) & ~3;
 ydstlen = (yy << 16) | height;
 if (width == step << 3) {
  ar0 = height * width - 1;
  easy = 1;
 } else {
  ar0 = width - 1;
  easy = 0;
 }

 CRITBEGIN

 mga_fifo(5);
 matrox_accel_restore_maccess(minfo);
 if (easy)
  mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
 else
  mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
 mga_outl(M_FCOL, fgx);
 mga_outl(M_BCOL, bgx);
 fxbndry = ((xx + width - 1) << 16) | xx;
 mmio = minfo->mmio.vbase;

 mga_fifo(8);
 matrox_accel_restore_maccess(minfo);
 mga_writel(mmio, M_FXBNDRY, fxbndry);
 mga_writel(mmio, M_AR0, ar0);
 mga_writel(mmio, M_AR3, 0);
 if (easy) {
  mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
  mga_memcpy_toio(mmio, chardata, xlen);
 } else {
  mga_writel(mmio, M_AR5, 0);
  mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
  if ((step & 3) == 0) {
   /* Great. Source has 32bit aligned lines, so we can feed them
   directly to the accelerator. */

   mga_memcpy_toio(mmio, chardata, charcell);
  } else if (step == 1) {
   /* Special case for 1..8bit widths */
   while (height--) {
#if defined(__BIG_ENDIAN)
    fb_writel((*chardata) << 24, mmio.vaddr);
#else
    fb_writel(*chardata, mmio.vaddr);
#endif
    chardata++;
   }
  } else if (step == 2) {
   /* Special case for 9..15bit widths */
   while (height--) {
#if defined(__BIG_ENDIAN)
    fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr);
#else
    fb_writel(*(u_int16_t*)chardata, mmio.vaddr);
#endif
    chardata += 2;
   }
  } else {
   /* Tell... well, why bother... */
   while (height--) {
    size_t i;

    for (i = 0; i < step; i += 4) {
     /* Hope that there are at least three readable bytes beyond the end of bitmap */
     fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr);
    }
    chardata += step;
   }
  }
 }
 WaitTillIdle();
 CRITEND
}


static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) {
 struct matrox_fb_info *minfo = info2minfo(info);

 DBG_HEAVY(__func__);

 if (image->depth == 1) {
  u_int32_t fgx, bgx;

  fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color];
  bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color];
  matroxfb_1bpp_imageblit(minfo, fgx, bgx, image->data, image->width, image->height, image->dy, image->dx);
 } else {
  /* Danger! image->depth is useless: logo painting code always
   passes framebuffer color depth here, although logo data are
   always 8bpp and info->pseudo_palette is changed to contain
   logo palette to be used (but only for true/direct-color... sic...).
   So do it completely in software... */

  cfb_imageblit(info, image);
 }
}

MODULE_DESCRIPTION("Accelerated fbops for Matrox Millennium/Mystique/G100/G200/G400/G450/G550");
MODULE_LICENSE("GPL");

Messung V0.5
C=99 H=92 G=95

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.