18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Version: 1.65 2002/08/14 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Contributors: "menion?" <menion@mindless.com> 138c2ecf20Sopenharmony_ci * Betatesting, fixes, ideas 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * "Kurt Garloff" <garloff@suse.de> 168c2ecf20Sopenharmony_ci * Betatesting, fixes, ideas, videomodes, videomodes timmings 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * "Tom Rini" <trini@kernel.crashing.org> 198c2ecf20Sopenharmony_ci * MTRR stuff, PPC cleanups, betatesting, fixes, ideas 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * "Bibek Sahu" <scorpio@dodds.net> 228c2ecf20Sopenharmony_ci * Access device through readb|w|l and write b|w|l 238c2ecf20Sopenharmony_ci * Extensive debugging stuff 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * "Daniel Haun" <haund@usa.net> 268c2ecf20Sopenharmony_ci * Testing, hardware cursor fixes 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * "Scott Wood" <sawst46+@pitt.edu> 298c2ecf20Sopenharmony_ci * Fixes 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de> 328c2ecf20Sopenharmony_ci * Betatesting 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * "Kelly French" <targon@hazmat.com> 358c2ecf20Sopenharmony_ci * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es> 368c2ecf20Sopenharmony_ci * Betatesting, bug reporting 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci * "Pablo Bianucci" <pbian@pccp.com.ar> 398c2ecf20Sopenharmony_ci * Fixes, ideas, betatesting 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es> 428c2ecf20Sopenharmony_ci * Fixes, enhandcements, ideas, betatesting 438c2ecf20Sopenharmony_ci * 448c2ecf20Sopenharmony_ci * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp> 458c2ecf20Sopenharmony_ci * PPC betatesting, PPC support, backward compatibility 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * "Paul Womar" <Paul@pwomar.demon.co.uk> 488c2ecf20Sopenharmony_ci * "Owen Waller" <O.Waller@ee.qub.ac.uk> 498c2ecf20Sopenharmony_ci * PPC betatesting 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci * "Thomas Pornin" <pornin@bolet.ens.fr> 528c2ecf20Sopenharmony_ci * Alpha betatesting 538c2ecf20Sopenharmony_ci * 548c2ecf20Sopenharmony_ci * "Pieter van Leuven" <pvl@iae.nl> 558c2ecf20Sopenharmony_ci * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de> 568c2ecf20Sopenharmony_ci * G100 testing 578c2ecf20Sopenharmony_ci * 588c2ecf20Sopenharmony_ci * "H. Peter Arvin" <hpa@transmeta.com> 598c2ecf20Sopenharmony_ci * Ideas 608c2ecf20Sopenharmony_ci * 618c2ecf20Sopenharmony_ci * "Cort Dougan" <cort@cs.nmt.edu> 628c2ecf20Sopenharmony_ci * CHRP fixes and PReP cleanup 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * "Mark Vojkovich" <mvojkovi@ucsd.edu> 658c2ecf20Sopenharmony_ci * G400 support 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * (following author is not in any relation with this code, but his code 688c2ecf20Sopenharmony_ci * is included in this driver) 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * Based on framebuffer driver for VBE 2.0 compliant graphic boards 718c2ecf20Sopenharmony_ci * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> 728c2ecf20Sopenharmony_ci * 738c2ecf20Sopenharmony_ci * (following author is not in any relation with this code, but his ideas 748c2ecf20Sopenharmony_ci * were used when writing this driver) 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> 778c2ecf20Sopenharmony_ci * 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#include "matroxfb_accel.h" 818c2ecf20Sopenharmony_ci#include "matroxfb_DAC1064.h" 828c2ecf20Sopenharmony_ci#include "matroxfb_Ti3026.h" 838c2ecf20Sopenharmony_ci#include "matroxfb_misc.h" 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define curr_ydstorg(x) ((x)->curr.ydstorg.pixels) 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l)) 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic inline void matrox_cfb4_pal(u_int32_t* pal) { 908c2ecf20Sopenharmony_ci unsigned int i; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 938c2ecf20Sopenharmony_ci pal[i] = i * 0x11111111U; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic inline void matrox_cfb8_pal(u_int32_t* pal) { 988c2ecf20Sopenharmony_ci unsigned int i; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 1018c2ecf20Sopenharmony_ci pal[i] = i * 0x01010101U; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area); 1068c2ecf20Sopenharmony_cistatic void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect); 1078c2ecf20Sopenharmony_cistatic void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image); 1088c2ecf20Sopenharmony_cistatic void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect); 1098c2ecf20Sopenharmony_cistatic void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_civoid matrox_cfbX_init(struct matrox_fb_info *minfo) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci u_int32_t maccess; 1148c2ecf20Sopenharmony_ci u_int32_t mpitch; 1158c2ecf20Sopenharmony_ci u_int32_t mopmode; 1168c2ecf20Sopenharmony_ci int accel; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci DBG(__func__) 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci mpitch = minfo->fbcon.var.xres_virtual; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci minfo->fbops.fb_copyarea = cfb_copyarea; 1238c2ecf20Sopenharmony_ci minfo->fbops.fb_fillrect = cfb_fillrect; 1248c2ecf20Sopenharmony_ci minfo->fbops.fb_imageblit = cfb_imageblit; 1258c2ecf20Sopenharmony_ci minfo->fbops.fb_cursor = NULL; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci accel = (minfo->fbcon.var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci switch (minfo->fbcon.var.bits_per_pixel) { 1308c2ecf20Sopenharmony_ci case 4: maccess = 0x00000000; /* accelerate as 8bpp video */ 1318c2ecf20Sopenharmony_ci mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */ 1328c2ecf20Sopenharmony_ci mopmode = M_OPMODE_4BPP; 1338c2ecf20Sopenharmony_ci matrox_cfb4_pal(minfo->cmap); 1348c2ecf20Sopenharmony_ci if (accel && !(mpitch & 1)) { 1358c2ecf20Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_cfb4_copyarea; 1368c2ecf20Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_cfb4_fillrect; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci break; 1398c2ecf20Sopenharmony_ci case 8: maccess = 0x00000000; 1408c2ecf20Sopenharmony_ci mopmode = M_OPMODE_8BPP; 1418c2ecf20Sopenharmony_ci matrox_cfb8_pal(minfo->cmap); 1428c2ecf20Sopenharmony_ci if (accel) { 1438c2ecf20Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_copyarea; 1448c2ecf20Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_fillrect; 1458c2ecf20Sopenharmony_ci minfo->fbops.fb_imageblit = matroxfb_imageblit; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci break; 1488c2ecf20Sopenharmony_ci case 16: if (minfo->fbcon.var.green.length == 5) 1498c2ecf20Sopenharmony_ci maccess = 0xC0000001; 1508c2ecf20Sopenharmony_ci else 1518c2ecf20Sopenharmony_ci maccess = 0x40000001; 1528c2ecf20Sopenharmony_ci mopmode = M_OPMODE_16BPP; 1538c2ecf20Sopenharmony_ci if (accel) { 1548c2ecf20Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_copyarea; 1558c2ecf20Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_fillrect; 1568c2ecf20Sopenharmony_ci minfo->fbops.fb_imageblit = matroxfb_imageblit; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci case 24: maccess = 0x00000003; 1608c2ecf20Sopenharmony_ci mopmode = M_OPMODE_24BPP; 1618c2ecf20Sopenharmony_ci if (accel) { 1628c2ecf20Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_copyarea; 1638c2ecf20Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_fillrect; 1648c2ecf20Sopenharmony_ci minfo->fbops.fb_imageblit = matroxfb_imageblit; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci break; 1678c2ecf20Sopenharmony_ci case 32: maccess = 0x00000002; 1688c2ecf20Sopenharmony_ci mopmode = M_OPMODE_32BPP; 1698c2ecf20Sopenharmony_ci if (accel) { 1708c2ecf20Sopenharmony_ci minfo->fbops.fb_copyarea = matroxfb_copyarea; 1718c2ecf20Sopenharmony_ci minfo->fbops.fb_fillrect = matroxfb_fillrect; 1728c2ecf20Sopenharmony_ci minfo->fbops.fb_imageblit = matroxfb_imageblit; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci break; 1758c2ecf20Sopenharmony_ci default: maccess = 0x00000000; 1768c2ecf20Sopenharmony_ci mopmode = 0x00000000; 1778c2ecf20Sopenharmony_ci break; /* turn off acceleration!!! */ 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci mga_fifo(8); 1808c2ecf20Sopenharmony_ci mga_outl(M_PITCH, mpitch); 1818c2ecf20Sopenharmony_ci mga_outl(M_YDSTORG, curr_ydstorg(minfo)); 1828c2ecf20Sopenharmony_ci if (minfo->capable.plnwt) 1838c2ecf20Sopenharmony_ci mga_outl(M_PLNWT, -1); 1848c2ecf20Sopenharmony_ci if (minfo->capable.srcorg) { 1858c2ecf20Sopenharmony_ci mga_outl(M_SRCORG, 0); 1868c2ecf20Sopenharmony_ci mga_outl(M_DSTORG, 0); 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci mga_outl(M_OPMODE, mopmode); 1898c2ecf20Sopenharmony_ci mga_outl(M_CXBNDRY, 0xFFFF0000); 1908c2ecf20Sopenharmony_ci mga_outl(M_YTOP, 0); 1918c2ecf20Sopenharmony_ci mga_outl(M_YBOT, 0x01FFFFFF); 1928c2ecf20Sopenharmony_ci mga_outl(M_MACCESS, maccess); 1938c2ecf20Sopenharmony_ci minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO; 1948c2ecf20Sopenharmony_ci if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC; 1958c2ecf20Sopenharmony_ci minfo->accel.m_opmode = mopmode; 1968c2ecf20Sopenharmony_ci minfo->accel.m_access = maccess; 1978c2ecf20Sopenharmony_ci minfo->accel.m_pitch = mpitch; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ciEXPORT_SYMBOL(matrox_cfbX_init); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic void matrox_accel_restore_maccess(struct matrox_fb_info *minfo) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci mga_outl(M_MACCESS, minfo->accel.m_access); 2058c2ecf20Sopenharmony_ci mga_outl(M_PITCH, minfo->accel.m_pitch); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy, 2098c2ecf20Sopenharmony_ci int sx, int dy, int dx, int height, int width) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci int start, end; 2128c2ecf20Sopenharmony_ci CRITFLAGS 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci DBG(__func__) 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci CRITBEGIN 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci if ((dy < sy) || ((dy == sy) && (dx <= sx))) { 2198c2ecf20Sopenharmony_ci mga_fifo(4); 2208c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 2218c2ecf20Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO | 2228c2ecf20Sopenharmony_ci M_DWG_BFCOL | M_DWG_REPLACE); 2238c2ecf20Sopenharmony_ci mga_outl(M_AR5, vxres); 2248c2ecf20Sopenharmony_ci width--; 2258c2ecf20Sopenharmony_ci start = sy*vxres+sx+curr_ydstorg(minfo); 2268c2ecf20Sopenharmony_ci end = start+width; 2278c2ecf20Sopenharmony_ci } else { 2288c2ecf20Sopenharmony_ci mga_fifo(5); 2298c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 2308c2ecf20Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE); 2318c2ecf20Sopenharmony_ci mga_outl(M_SGN, 5); 2328c2ecf20Sopenharmony_ci mga_outl(M_AR5, -vxres); 2338c2ecf20Sopenharmony_ci width--; 2348c2ecf20Sopenharmony_ci end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo); 2358c2ecf20Sopenharmony_ci start = end+width; 2368c2ecf20Sopenharmony_ci dy += height-1; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci mga_fifo(6); 2398c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 2408c2ecf20Sopenharmony_ci mga_outl(M_AR0, end); 2418c2ecf20Sopenharmony_ci mga_outl(M_AR3, start); 2428c2ecf20Sopenharmony_ci mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx); 2438c2ecf20Sopenharmony_ci mga_ydstlen(dy, height); 2448c2ecf20Sopenharmony_ci WaitTillIdle(); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci CRITEND 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres, 2508c2ecf20Sopenharmony_ci int sy, int sx, int dy, int dx, int height, 2518c2ecf20Sopenharmony_ci int width) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci int start, end; 2548c2ecf20Sopenharmony_ci CRITFLAGS 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci DBG(__func__) 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci CRITBEGIN 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci if ((dy < sy) || ((dy == sy) && (dx <= sx))) { 2618c2ecf20Sopenharmony_ci mga_fifo(4); 2628c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 2638c2ecf20Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO | 2648c2ecf20Sopenharmony_ci M_DWG_BFCOL | M_DWG_REPLACE); 2658c2ecf20Sopenharmony_ci mga_outl(M_AR5, vxres); 2668c2ecf20Sopenharmony_ci width--; 2678c2ecf20Sopenharmony_ci start = sy*vxres+sx+curr_ydstorg(minfo); 2688c2ecf20Sopenharmony_ci end = start+width; 2698c2ecf20Sopenharmony_ci } else { 2708c2ecf20Sopenharmony_ci mga_fifo(5); 2718c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 2728c2ecf20Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE); 2738c2ecf20Sopenharmony_ci mga_outl(M_SGN, 5); 2748c2ecf20Sopenharmony_ci mga_outl(M_AR5, -vxres); 2758c2ecf20Sopenharmony_ci width--; 2768c2ecf20Sopenharmony_ci end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo); 2778c2ecf20Sopenharmony_ci start = end+width; 2788c2ecf20Sopenharmony_ci dy += height-1; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci mga_fifo(7); 2818c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 2828c2ecf20Sopenharmony_ci mga_outl(M_AR0, end); 2838c2ecf20Sopenharmony_ci mga_outl(M_AR3, start); 2848c2ecf20Sopenharmony_ci mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx); 2858c2ecf20Sopenharmony_ci mga_outl(M_YDST, dy*vxres >> 5); 2868c2ecf20Sopenharmony_ci mga_outl(M_LEN | M_EXEC, height); 2878c2ecf20Sopenharmony_ci WaitTillIdle(); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci CRITEND 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) { 2938c2ecf20Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci if ((area->sx | area->dx | area->width) & 1) 2968c2ecf20Sopenharmony_ci cfb_copyarea(info, area); 2978c2ecf20Sopenharmony_ci else 2988c2ecf20Sopenharmony_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); 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) { 3028c2ecf20Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci matrox_accel_bmove(minfo, minfo->fbcon.var.xres_virtual, area->sy, area->sx, area->dy, area->dx, area->height, area->width); 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color, 3088c2ecf20Sopenharmony_ci int sy, int sx, int height, int width) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci CRITFLAGS 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci DBG(__func__) 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci CRITBEGIN 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci mga_fifo(7); 3178c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 3188c2ecf20Sopenharmony_ci mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE); 3198c2ecf20Sopenharmony_ci mga_outl(M_FCOL, color); 3208c2ecf20Sopenharmony_ci mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); 3218c2ecf20Sopenharmony_ci mga_ydstlen(sy, height); 3228c2ecf20Sopenharmony_ci WaitTillIdle(); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci CRITEND 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { 3288c2ecf20Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci switch (rect->rop) { 3318c2ecf20Sopenharmony_ci case ROP_COPY: 3328c2ecf20Sopenharmony_ci matroxfb_accel_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); 3338c2ecf20Sopenharmony_ci break; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx, 3388c2ecf20Sopenharmony_ci int sy, int sx, int height, int width) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci int whattodo; 3418c2ecf20Sopenharmony_ci CRITFLAGS 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci DBG(__func__) 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci CRITBEGIN 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci whattodo = 0; 3488c2ecf20Sopenharmony_ci if (sx & 1) { 3498c2ecf20Sopenharmony_ci sx ++; 3508c2ecf20Sopenharmony_ci if (!width) return; 3518c2ecf20Sopenharmony_ci width --; 3528c2ecf20Sopenharmony_ci whattodo = 1; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci if (width & 1) { 3558c2ecf20Sopenharmony_ci whattodo |= 2; 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci width >>= 1; 3588c2ecf20Sopenharmony_ci sx >>= 1; 3598c2ecf20Sopenharmony_ci if (width) { 3608c2ecf20Sopenharmony_ci mga_fifo(7); 3618c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 3628c2ecf20Sopenharmony_ci mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2); 3638c2ecf20Sopenharmony_ci mga_outl(M_FCOL, bgx); 3648c2ecf20Sopenharmony_ci mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); 3658c2ecf20Sopenharmony_ci mga_outl(M_YDST, sy * minfo->fbcon.var.xres_virtual >> 6); 3668c2ecf20Sopenharmony_ci mga_outl(M_LEN | M_EXEC, height); 3678c2ecf20Sopenharmony_ci WaitTillIdle(); 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci if (whattodo) { 3708c2ecf20Sopenharmony_ci u_int32_t step = minfo->fbcon.var.xres_virtual >> 1; 3718c2ecf20Sopenharmony_ci vaddr_t vbase = minfo->video.vbase; 3728c2ecf20Sopenharmony_ci if (whattodo & 1) { 3738c2ecf20Sopenharmony_ci unsigned int uaddr = sy * step + sx - 1; 3748c2ecf20Sopenharmony_ci u_int32_t loop; 3758c2ecf20Sopenharmony_ci u_int8_t bgx2 = bgx & 0xF0; 3768c2ecf20Sopenharmony_ci for (loop = height; loop > 0; loop --) { 3778c2ecf20Sopenharmony_ci mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2); 3788c2ecf20Sopenharmony_ci uaddr += step; 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci if (whattodo & 2) { 3828c2ecf20Sopenharmony_ci unsigned int uaddr = sy * step + sx + width; 3838c2ecf20Sopenharmony_ci u_int32_t loop; 3848c2ecf20Sopenharmony_ci u_int8_t bgx2 = bgx & 0x0F; 3858c2ecf20Sopenharmony_ci for (loop = height; loop > 0; loop --) { 3868c2ecf20Sopenharmony_ci mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2); 3878c2ecf20Sopenharmony_ci uaddr += step; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci CRITEND 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { 3968c2ecf20Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci switch (rect->rop) { 3998c2ecf20Sopenharmony_ci case ROP_COPY: 4008c2ecf20Sopenharmony_ci matroxfb_cfb4_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); 4018c2ecf20Sopenharmony_ci break; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx, 4068c2ecf20Sopenharmony_ci u_int32_t bgx, const u_int8_t *chardata, 4078c2ecf20Sopenharmony_ci int width, int height, int yy, int xx) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci u_int32_t step; 4108c2ecf20Sopenharmony_ci u_int32_t ydstlen; 4118c2ecf20Sopenharmony_ci u_int32_t xlen; 4128c2ecf20Sopenharmony_ci u_int32_t ar0; 4138c2ecf20Sopenharmony_ci u_int32_t charcell; 4148c2ecf20Sopenharmony_ci u_int32_t fxbndry; 4158c2ecf20Sopenharmony_ci vaddr_t mmio; 4168c2ecf20Sopenharmony_ci int easy; 4178c2ecf20Sopenharmony_ci CRITFLAGS 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci DBG_HEAVY(__func__); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci step = (width + 7) >> 3; 4228c2ecf20Sopenharmony_ci charcell = height * step; 4238c2ecf20Sopenharmony_ci xlen = (charcell + 3) & ~3; 4248c2ecf20Sopenharmony_ci ydstlen = (yy << 16) | height; 4258c2ecf20Sopenharmony_ci if (width == step << 3) { 4268c2ecf20Sopenharmony_ci ar0 = height * width - 1; 4278c2ecf20Sopenharmony_ci easy = 1; 4288c2ecf20Sopenharmony_ci } else { 4298c2ecf20Sopenharmony_ci ar0 = width - 1; 4308c2ecf20Sopenharmony_ci easy = 0; 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci CRITBEGIN 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci mga_fifo(5); 4368c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 4378c2ecf20Sopenharmony_ci if (easy) 4388c2ecf20Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE); 4398c2ecf20Sopenharmony_ci else 4408c2ecf20Sopenharmony_ci mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE); 4418c2ecf20Sopenharmony_ci mga_outl(M_FCOL, fgx); 4428c2ecf20Sopenharmony_ci mga_outl(M_BCOL, bgx); 4438c2ecf20Sopenharmony_ci fxbndry = ((xx + width - 1) << 16) | xx; 4448c2ecf20Sopenharmony_ci mmio = minfo->mmio.vbase; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci mga_fifo(8); 4478c2ecf20Sopenharmony_ci matrox_accel_restore_maccess(minfo); 4488c2ecf20Sopenharmony_ci mga_writel(mmio, M_FXBNDRY, fxbndry); 4498c2ecf20Sopenharmony_ci mga_writel(mmio, M_AR0, ar0); 4508c2ecf20Sopenharmony_ci mga_writel(mmio, M_AR3, 0); 4518c2ecf20Sopenharmony_ci if (easy) { 4528c2ecf20Sopenharmony_ci mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen); 4538c2ecf20Sopenharmony_ci mga_memcpy_toio(mmio, chardata, xlen); 4548c2ecf20Sopenharmony_ci } else { 4558c2ecf20Sopenharmony_ci mga_writel(mmio, M_AR5, 0); 4568c2ecf20Sopenharmony_ci mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen); 4578c2ecf20Sopenharmony_ci if ((step & 3) == 0) { 4588c2ecf20Sopenharmony_ci /* Great. Source has 32bit aligned lines, so we can feed them 4598c2ecf20Sopenharmony_ci directly to the accelerator. */ 4608c2ecf20Sopenharmony_ci mga_memcpy_toio(mmio, chardata, charcell); 4618c2ecf20Sopenharmony_ci } else if (step == 1) { 4628c2ecf20Sopenharmony_ci /* Special case for 1..8bit widths */ 4638c2ecf20Sopenharmony_ci while (height--) { 4648c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN) 4658c2ecf20Sopenharmony_ci fb_writel((*chardata) << 24, mmio.vaddr); 4668c2ecf20Sopenharmony_ci#else 4678c2ecf20Sopenharmony_ci fb_writel(*chardata, mmio.vaddr); 4688c2ecf20Sopenharmony_ci#endif 4698c2ecf20Sopenharmony_ci chardata++; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci } else if (step == 2) { 4728c2ecf20Sopenharmony_ci /* Special case for 9..15bit widths */ 4738c2ecf20Sopenharmony_ci while (height--) { 4748c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN) 4758c2ecf20Sopenharmony_ci fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr); 4768c2ecf20Sopenharmony_ci#else 4778c2ecf20Sopenharmony_ci fb_writel(*(u_int16_t*)chardata, mmio.vaddr); 4788c2ecf20Sopenharmony_ci#endif 4798c2ecf20Sopenharmony_ci chardata += 2; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci } else { 4828c2ecf20Sopenharmony_ci /* Tell... well, why bother... */ 4838c2ecf20Sopenharmony_ci while (height--) { 4848c2ecf20Sopenharmony_ci size_t i; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci for (i = 0; i < step; i += 4) { 4878c2ecf20Sopenharmony_ci /* Hope that there are at least three readable bytes beyond the end of bitmap */ 4888c2ecf20Sopenharmony_ci fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr); 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci chardata += step; 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci } 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci WaitTillIdle(); 4958c2ecf20Sopenharmony_ci CRITEND 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_cistatic void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) { 5008c2ecf20Sopenharmony_ci struct matrox_fb_info *minfo = info2minfo(info); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci DBG_HEAVY(__func__); 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci if (image->depth == 1) { 5058c2ecf20Sopenharmony_ci u_int32_t fgx, bgx; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color]; 5088c2ecf20Sopenharmony_ci bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color]; 5098c2ecf20Sopenharmony_ci matroxfb_1bpp_imageblit(minfo, fgx, bgx, image->data, image->width, image->height, image->dy, image->dx); 5108c2ecf20Sopenharmony_ci } else { 5118c2ecf20Sopenharmony_ci /* Danger! image->depth is useless: logo painting code always 5128c2ecf20Sopenharmony_ci passes framebuffer color depth here, although logo data are 5138c2ecf20Sopenharmony_ci always 8bpp and info->pseudo_palette is changed to contain 5148c2ecf20Sopenharmony_ci logo palette to be used (but only for true/direct-color... sic...). 5158c2ecf20Sopenharmony_ci So do it completely in software... */ 5168c2ecf20Sopenharmony_ci cfb_imageblit(info, image); 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 521