162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Version: 1.65 2002/08/14 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Contributors: "menion?" <menion@mindless.com> 1362306a36Sopenharmony_ci * Betatesting, fixes, ideas 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * "Kurt Garloff" <garloff@suse.de> 1662306a36Sopenharmony_ci * Betatesting, fixes, ideas, videomodes, videomodes timmings 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * "Tom Rini" <trini@kernel.crashing.org> 1962306a36Sopenharmony_ci * MTRR stuff, PPC cleanups, betatesting, fixes, ideas 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * "Bibek Sahu" <scorpio@dodds.net> 2262306a36Sopenharmony_ci * Access device through readb|w|l and write b|w|l 2362306a36Sopenharmony_ci * Extensive debugging stuff 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * "Daniel Haun" <haund@usa.net> 2662306a36Sopenharmony_ci * Testing, hardware cursor fixes 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * "Scott Wood" <sawst46+@pitt.edu> 2962306a36Sopenharmony_ci * Fixes 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de> 3262306a36Sopenharmony_ci * Betatesting 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * "Kelly French" <targon@hazmat.com> 3562306a36Sopenharmony_ci * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es> 3662306a36Sopenharmony_ci * Betatesting, bug reporting 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * "Pablo Bianucci" <pbian@pccp.com.ar> 3962306a36Sopenharmony_ci * Fixes, ideas, betatesting 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es> 4262306a36Sopenharmony_ci * Fixes, enhandcements, ideas, betatesting 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp> 4562306a36Sopenharmony_ci * PPC betatesting, PPC support, backward compatibility 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * "Paul Womar" <Paul@pwomar.demon.co.uk> 4862306a36Sopenharmony_ci * "Owen Waller" <O.Waller@ee.qub.ac.uk> 4962306a36Sopenharmony_ci * PPC betatesting 5062306a36Sopenharmony_ci * 5162306a36Sopenharmony_ci * "Thomas Pornin" <pornin@bolet.ens.fr> 5262306a36Sopenharmony_ci * Alpha betatesting 5362306a36Sopenharmony_ci * 5462306a36Sopenharmony_ci * "Pieter van Leuven" <pvl@iae.nl> 5562306a36Sopenharmony_ci * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de> 5662306a36Sopenharmony_ci * G100 testing 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * "H. Peter Arvin" <hpa@transmeta.com> 5962306a36Sopenharmony_ci * Ideas 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * "Cort Dougan" <cort@cs.nmt.edu> 6262306a36Sopenharmony_ci * CHRP fixes and PReP cleanup 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci * "Mark Vojkovich" <mvojkovi@ucsd.edu> 6562306a36Sopenharmony_ci * G400 support 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * (following author is not in any relation with this code, but his code 6862306a36Sopenharmony_ci * is included in this driver) 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * Based on framebuffer driver for VBE 2.0 compliant graphic boards 7162306a36Sopenharmony_ci * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * (following author is not in any relation with this code, but his ideas 7462306a36Sopenharmony_ci * were used when writing this driver) 7562306a36Sopenharmony_ci * 7662306a36Sopenharmony_ci * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#include "matroxfb_accel.h" 8162306a36Sopenharmony_ci#include "matroxfb_DAC1064.h" 8262306a36Sopenharmony_ci#include "matroxfb_Ti3026.h" 8362306a36Sopenharmony_ci#include "matroxfb_misc.h" 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define curr_ydstorg(x) ((x)->curr.ydstorg.pixels) 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l)) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic inline void matrox_cfb4_pal(u_int32_t* pal) { 9062306a36Sopenharmony_ci unsigned int i; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci for (i = 0; i < 16; i++) { 9362306a36Sopenharmony_ci pal[i] = i * 0x11111111U; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic inline void matrox_cfb8_pal(u_int32_t* pal) { 9862306a36Sopenharmony_ci unsigned int i; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci for (i = 0; i < 16; i++) { 10162306a36Sopenharmony_ci pal[i] = i * 0x01010101U; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area); 10662306a36Sopenharmony_cistatic void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect); 10762306a36Sopenharmony_cistatic void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image); 10862306a36Sopenharmony_cistatic void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect); 10962306a36Sopenharmony_cistatic void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_civoid matrox_cfbX_init(struct matrox_fb_info *minfo) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci u_int32_t maccess; 11462306a36Sopenharmony_ci u_int32_t mpitch; 11562306a36Sopenharmony_ci u_int32_t mopmode; 11662306a36Sopenharmony_ci int accel; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci DBG(__func__) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci mpitch = minfo->fbcon.var.xres_virtual; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci minfo->fbops.fb_copyarea = cfb_copyarea; 12362306a36Sopenharmony_ci minfo->fbops.fb_fillrect = cfb_fillrect; 12462306a36Sopenharmony_ci minfo->fbops.fb_imageblit = cfb_imageblit; 12562306a36Sopenharmony_ci minfo->fbops.fb_cursor = NULL; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci accel = (minfo->fbcon.var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci switch (minfo->fbcon.var.bits_per_pixel) { 13062306a36Sopenharmony_ci case 4: maccess = 0x00000000; /* accelerate as 8bpp video */ 13162306a36Sopenharmony_ci mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */ 13262306a36Sopenharmony_ci mopmode = M_OPMODE_4BPP; 13362306a36Sopenharmony_ci matrox_cfb4_pal(minfo->cmap); 13462306a36Sopenharmony_ci if (accel && !(mpitch & 1)) { 13562306a36Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_cfb4_copyarea; 13662306a36Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_cfb4_fillrect; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci break; 13962306a36Sopenharmony_ci case 8: maccess = 0x00000000; 14062306a36Sopenharmony_ci mopmode = M_OPMODE_8BPP; 14162306a36Sopenharmony_ci matrox_cfb8_pal(minfo->cmap); 14262306a36Sopenharmony_ci if (accel) { 14362306a36Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_copyarea; 14462306a36Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_fillrect; 14562306a36Sopenharmony_ci minfo->fbops.fb_imageblit = matroxfb_imageblit; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci break; 14862306a36Sopenharmony_ci case 16: if (minfo->fbcon.var.green.length == 5) 14962306a36Sopenharmony_ci maccess = 0xC0000001; 15062306a36Sopenharmony_ci else 15162306a36Sopenharmony_ci maccess = 0x40000001; 15262306a36Sopenharmony_ci mopmode = M_OPMODE_16BPP; 15362306a36Sopenharmony_ci if (accel) { 15462306a36Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_copyarea; 15562306a36Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_fillrect; 15662306a36Sopenharmony_ci minfo->fbops.fb_imageblit = matroxfb_imageblit; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci break; 15962306a36Sopenharmony_ci case 24: maccess = 0x00000003; 16062306a36Sopenharmony_ci mopmode = M_OPMODE_24BPP; 16162306a36Sopenharmony_ci if (accel) { 16262306a36Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_copyarea; 16362306a36Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_fillrect; 16462306a36Sopenharmony_ci minfo->fbops.fb_imageblit = matroxfb_imageblit; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci break; 16762306a36Sopenharmony_ci case 32: maccess = 0x00000002; 16862306a36Sopenharmony_ci mopmode = M_OPMODE_32BPP; 16962306a36Sopenharmony_ci if (accel) { 17062306a36Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_copyarea; 17162306a36Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_fillrect; 17262306a36Sopenharmony_ci minfo->fbops.fb_imageblit = matroxfb_imageblit; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci break; 17562306a36Sopenharmony_ci default: maccess = 0x00000000; 17662306a36Sopenharmony_ci mopmode = 0x00000000; 17762306a36Sopenharmony_ci break; /* turn off acceleration!!! */ 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci mga_fifo(8); 18062306a36Sopenharmony_ci mga_outl(M_PITCH, mpitch); 18162306a36Sopenharmony_ci mga_outl(M_YDSTORG, curr_ydstorg(minfo)); 18262306a36Sopenharmony_ci if (minfo->capable.plnwt) 18362306a36Sopenharmony_ci mga_outl(M_PLNWT, -1); 18462306a36Sopenharmony_ci if (minfo->capable.srcorg) { 18562306a36Sopenharmony_ci mga_outl(M_SRCORG, 0); 18662306a36Sopenharmony_ci mga_outl(M_DSTORG, 0); 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci mga_outl(M_OPMODE, mopmode); 18962306a36Sopenharmony_ci mga_outl(M_CXBNDRY, 0xFFFF0000); 19062306a36Sopenharmony_ci mga_outl(M_YTOP, 0); 19162306a36Sopenharmony_ci mga_outl(M_YBOT, 0x01FFFFFF); 19262306a36Sopenharmony_ci mga_outl(M_MACCESS, maccess); 19362306a36Sopenharmony_ci minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO; 19462306a36Sopenharmony_ci if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC; 19562306a36Sopenharmony_ci minfo->accel.m_opmode = mopmode; 19662306a36Sopenharmony_ci minfo->accel.m_access = maccess; 19762306a36Sopenharmony_ci minfo->accel.m_pitch = mpitch; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ciEXPORT_SYMBOL(matrox_cfbX_init); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic void matrox_accel_restore_maccess(struct matrox_fb_info *minfo) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci mga_outl(M_MACCESS, minfo->accel.m_access); 20562306a36Sopenharmony_ci mga_outl(M_PITCH, minfo->accel.m_pitch); 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy, 20962306a36Sopenharmony_ci int sx, int dy, int dx, int height, int width) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci int start, end; 21262306a36Sopenharmony_ci CRITFLAGS 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci DBG(__func__) 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci CRITBEGIN 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci if ((dy < sy) || ((dy == sy) && (dx <= sx))) { 21962306a36Sopenharmony_ci mga_fifo(4); 22062306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 22162306a36Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO | 22262306a36Sopenharmony_ci M_DWG_BFCOL | M_DWG_REPLACE); 22362306a36Sopenharmony_ci mga_outl(M_AR5, vxres); 22462306a36Sopenharmony_ci width--; 22562306a36Sopenharmony_ci start = sy*vxres+sx+curr_ydstorg(minfo); 22662306a36Sopenharmony_ci end = start+width; 22762306a36Sopenharmony_ci } else { 22862306a36Sopenharmony_ci mga_fifo(5); 22962306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 23062306a36Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE); 23162306a36Sopenharmony_ci mga_outl(M_SGN, 5); 23262306a36Sopenharmony_ci mga_outl(M_AR5, -vxres); 23362306a36Sopenharmony_ci width--; 23462306a36Sopenharmony_ci end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo); 23562306a36Sopenharmony_ci start = end+width; 23662306a36Sopenharmony_ci dy += height-1; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci mga_fifo(6); 23962306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 24062306a36Sopenharmony_ci mga_outl(M_AR0, end); 24162306a36Sopenharmony_ci mga_outl(M_AR3, start); 24262306a36Sopenharmony_ci mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx); 24362306a36Sopenharmony_ci mga_ydstlen(dy, height); 24462306a36Sopenharmony_ci WaitTillIdle(); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci CRITEND 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres, 25062306a36Sopenharmony_ci int sy, int sx, int dy, int dx, int height, 25162306a36Sopenharmony_ci int width) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci int start, end; 25462306a36Sopenharmony_ci CRITFLAGS 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci DBG(__func__) 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci CRITBEGIN 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci if ((dy < sy) || ((dy == sy) && (dx <= sx))) { 26162306a36Sopenharmony_ci mga_fifo(4); 26262306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 26362306a36Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO | 26462306a36Sopenharmony_ci M_DWG_BFCOL | M_DWG_REPLACE); 26562306a36Sopenharmony_ci mga_outl(M_AR5, vxres); 26662306a36Sopenharmony_ci width--; 26762306a36Sopenharmony_ci start = sy*vxres+sx+curr_ydstorg(minfo); 26862306a36Sopenharmony_ci end = start+width; 26962306a36Sopenharmony_ci } else { 27062306a36Sopenharmony_ci mga_fifo(5); 27162306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 27262306a36Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE); 27362306a36Sopenharmony_ci mga_outl(M_SGN, 5); 27462306a36Sopenharmony_ci mga_outl(M_AR5, -vxres); 27562306a36Sopenharmony_ci width--; 27662306a36Sopenharmony_ci end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo); 27762306a36Sopenharmony_ci start = end+width; 27862306a36Sopenharmony_ci dy += height-1; 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci mga_fifo(7); 28162306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 28262306a36Sopenharmony_ci mga_outl(M_AR0, end); 28362306a36Sopenharmony_ci mga_outl(M_AR3, start); 28462306a36Sopenharmony_ci mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx); 28562306a36Sopenharmony_ci mga_outl(M_YDST, dy*vxres >> 5); 28662306a36Sopenharmony_ci mga_outl(M_LEN | M_EXEC, height); 28762306a36Sopenharmony_ci WaitTillIdle(); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci CRITEND 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) { 29362306a36Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if ((area->sx | area->dx | area->width) & 1) 29662306a36Sopenharmony_ci cfb_copyarea(info, area); 29762306a36Sopenharmony_ci else 29862306a36Sopenharmony_ci 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); 29962306a36Sopenharmony_ci} 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) { 30262306a36Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci matrox_accel_bmove(minfo, minfo->fbcon.var.xres_virtual, area->sy, area->sx, area->dy, area->dx, area->height, area->width); 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color, 30862306a36Sopenharmony_ci int sy, int sx, int height, int width) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci CRITFLAGS 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci DBG(__func__) 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci CRITBEGIN 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci mga_fifo(7); 31762306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 31862306a36Sopenharmony_ci mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE); 31962306a36Sopenharmony_ci mga_outl(M_FCOL, color); 32062306a36Sopenharmony_ci mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); 32162306a36Sopenharmony_ci mga_ydstlen(sy, height); 32262306a36Sopenharmony_ci WaitTillIdle(); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci CRITEND 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { 32862306a36Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci switch (rect->rop) { 33162306a36Sopenharmony_ci case ROP_COPY: 33262306a36Sopenharmony_ci matroxfb_accel_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); 33362306a36Sopenharmony_ci break; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx, 33862306a36Sopenharmony_ci int sy, int sx, int height, int width) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci int whattodo; 34162306a36Sopenharmony_ci CRITFLAGS 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci DBG(__func__) 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci CRITBEGIN 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci whattodo = 0; 34862306a36Sopenharmony_ci if (sx & 1) { 34962306a36Sopenharmony_ci sx ++; 35062306a36Sopenharmony_ci if (!width) return; 35162306a36Sopenharmony_ci width --; 35262306a36Sopenharmony_ci whattodo = 1; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci if (width & 1) { 35562306a36Sopenharmony_ci whattodo |= 2; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci width >>= 1; 35862306a36Sopenharmony_ci sx >>= 1; 35962306a36Sopenharmony_ci if (width) { 36062306a36Sopenharmony_ci mga_fifo(7); 36162306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 36262306a36Sopenharmony_ci mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2); 36362306a36Sopenharmony_ci mga_outl(M_FCOL, bgx); 36462306a36Sopenharmony_ci mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); 36562306a36Sopenharmony_ci mga_outl(M_YDST, sy * minfo->fbcon.var.xres_virtual >> 6); 36662306a36Sopenharmony_ci mga_outl(M_LEN | M_EXEC, height); 36762306a36Sopenharmony_ci WaitTillIdle(); 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci if (whattodo) { 37062306a36Sopenharmony_ci u_int32_t step = minfo->fbcon.var.xres_virtual >> 1; 37162306a36Sopenharmony_ci vaddr_t vbase = minfo->video.vbase; 37262306a36Sopenharmony_ci if (whattodo & 1) { 37362306a36Sopenharmony_ci unsigned int uaddr = sy * step + sx - 1; 37462306a36Sopenharmony_ci u_int32_t loop; 37562306a36Sopenharmony_ci u_int8_t bgx2 = bgx & 0xF0; 37662306a36Sopenharmony_ci for (loop = height; loop > 0; loop --) { 37762306a36Sopenharmony_ci mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2); 37862306a36Sopenharmony_ci uaddr += step; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci if (whattodo & 2) { 38262306a36Sopenharmony_ci unsigned int uaddr = sy * step + sx + width; 38362306a36Sopenharmony_ci u_int32_t loop; 38462306a36Sopenharmony_ci u_int8_t bgx2 = bgx & 0x0F; 38562306a36Sopenharmony_ci for (loop = height; loop > 0; loop --) { 38662306a36Sopenharmony_ci mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2); 38762306a36Sopenharmony_ci uaddr += step; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci CRITEND 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { 39662306a36Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci switch (rect->rop) { 39962306a36Sopenharmony_ci case ROP_COPY: 40062306a36Sopenharmony_ci matroxfb_cfb4_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); 40162306a36Sopenharmony_ci break; 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx, 40662306a36Sopenharmony_ci u_int32_t bgx, const u_int8_t *chardata, 40762306a36Sopenharmony_ci int width, int height, int yy, int xx) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci u_int32_t step; 41062306a36Sopenharmony_ci u_int32_t ydstlen; 41162306a36Sopenharmony_ci u_int32_t xlen; 41262306a36Sopenharmony_ci u_int32_t ar0; 41362306a36Sopenharmony_ci u_int32_t charcell; 41462306a36Sopenharmony_ci u_int32_t fxbndry; 41562306a36Sopenharmony_ci vaddr_t mmio; 41662306a36Sopenharmony_ci int easy; 41762306a36Sopenharmony_ci CRITFLAGS 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci DBG_HEAVY(__func__); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci step = (width + 7) >> 3; 42262306a36Sopenharmony_ci charcell = height * step; 42362306a36Sopenharmony_ci xlen = (charcell + 3) & ~3; 42462306a36Sopenharmony_ci ydstlen = (yy << 16) | height; 42562306a36Sopenharmony_ci if (width == step << 3) { 42662306a36Sopenharmony_ci ar0 = height * width - 1; 42762306a36Sopenharmony_ci easy = 1; 42862306a36Sopenharmony_ci } else { 42962306a36Sopenharmony_ci ar0 = width - 1; 43062306a36Sopenharmony_ci easy = 0; 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci CRITBEGIN 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci mga_fifo(5); 43662306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 43762306a36Sopenharmony_ci if (easy) 43862306a36Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE); 43962306a36Sopenharmony_ci else 44062306a36Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE); 44162306a36Sopenharmony_ci mga_outl(M_FCOL, fgx); 44262306a36Sopenharmony_ci mga_outl(M_BCOL, bgx); 44362306a36Sopenharmony_ci fxbndry = ((xx + width - 1) << 16) | xx; 44462306a36Sopenharmony_ci mmio = minfo->mmio.vbase; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci mga_fifo(8); 44762306a36Sopenharmony_ci matrox_accel_restore_maccess(minfo); 44862306a36Sopenharmony_ci mga_writel(mmio, M_FXBNDRY, fxbndry); 44962306a36Sopenharmony_ci mga_writel(mmio, M_AR0, ar0); 45062306a36Sopenharmony_ci mga_writel(mmio, M_AR3, 0); 45162306a36Sopenharmony_ci if (easy) { 45262306a36Sopenharmony_ci mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen); 45362306a36Sopenharmony_ci mga_memcpy_toio(mmio, chardata, xlen); 45462306a36Sopenharmony_ci } else { 45562306a36Sopenharmony_ci mga_writel(mmio, M_AR5, 0); 45662306a36Sopenharmony_ci mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen); 45762306a36Sopenharmony_ci if ((step & 3) == 0) { 45862306a36Sopenharmony_ci /* Great. Source has 32bit aligned lines, so we can feed them 45962306a36Sopenharmony_ci directly to the accelerator. */ 46062306a36Sopenharmony_ci mga_memcpy_toio(mmio, chardata, charcell); 46162306a36Sopenharmony_ci } else if (step == 1) { 46262306a36Sopenharmony_ci /* Special case for 1..8bit widths */ 46362306a36Sopenharmony_ci while (height--) { 46462306a36Sopenharmony_ci#if defined(__BIG_ENDIAN) 46562306a36Sopenharmony_ci fb_writel((*chardata) << 24, mmio.vaddr); 46662306a36Sopenharmony_ci#else 46762306a36Sopenharmony_ci fb_writel(*chardata, mmio.vaddr); 46862306a36Sopenharmony_ci#endif 46962306a36Sopenharmony_ci chardata++; 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci } else if (step == 2) { 47262306a36Sopenharmony_ci /* Special case for 9..15bit widths */ 47362306a36Sopenharmony_ci while (height--) { 47462306a36Sopenharmony_ci#if defined(__BIG_ENDIAN) 47562306a36Sopenharmony_ci fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr); 47662306a36Sopenharmony_ci#else 47762306a36Sopenharmony_ci fb_writel(*(u_int16_t*)chardata, mmio.vaddr); 47862306a36Sopenharmony_ci#endif 47962306a36Sopenharmony_ci chardata += 2; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci } else { 48262306a36Sopenharmony_ci /* Tell... well, why bother... */ 48362306a36Sopenharmony_ci while (height--) { 48462306a36Sopenharmony_ci size_t i; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci for (i = 0; i < step; i += 4) { 48762306a36Sopenharmony_ci /* Hope that there are at least three readable bytes beyond the end of bitmap */ 48862306a36Sopenharmony_ci fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr); 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci chardata += step; 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci WaitTillIdle(); 49562306a36Sopenharmony_ci CRITEND 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_cistatic void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) { 50062306a36Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci DBG_HEAVY(__func__); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci if (image->depth == 1) { 50562306a36Sopenharmony_ci u_int32_t fgx, bgx; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color]; 50862306a36Sopenharmony_ci bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color]; 50962306a36Sopenharmony_ci matroxfb_1bpp_imageblit(minfo, fgx, bgx, image->data, image->width, image->height, image->dy, image->dx); 51062306a36Sopenharmony_ci } else { 51162306a36Sopenharmony_ci /* Danger! image->depth is useless: logo painting code always 51262306a36Sopenharmony_ci passes framebuffer color depth here, although logo data are 51362306a36Sopenharmony_ci always 8bpp and info->pseudo_palette is changed to contain 51462306a36Sopenharmony_ci logo palette to be used (but only for true/direct-color... sic...). 51562306a36Sopenharmony_ci So do it completely in software... */ 51662306a36Sopenharmony_ci cfb_imageblit(info, image); 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 521