18c2ecf20Sopenharmony_ci /***************************************************************************\ 28c2ecf20Sopenharmony_ci|* *| 38c2ecf20Sopenharmony_ci|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| 48c2ecf20Sopenharmony_ci|* *| 58c2ecf20Sopenharmony_ci|* NOTICE TO USER: The source code is copyrighted under U.S. and *| 68c2ecf20Sopenharmony_ci|* international laws. Users and possessors of this source code are *| 78c2ecf20Sopenharmony_ci|* hereby granted a nonexclusive, royalty-free copyright license to *| 88c2ecf20Sopenharmony_ci|* use this code in individual and commercial software. *| 98c2ecf20Sopenharmony_ci|* *| 108c2ecf20Sopenharmony_ci|* Any use of this source code must include, in the user documenta- *| 118c2ecf20Sopenharmony_ci|* tion and internal comments to the code, notices to the end user *| 128c2ecf20Sopenharmony_ci|* as follows: *| 138c2ecf20Sopenharmony_ci|* *| 148c2ecf20Sopenharmony_ci|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| 158c2ecf20Sopenharmony_ci|* *| 168c2ecf20Sopenharmony_ci|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| 178c2ecf20Sopenharmony_ci|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| 188c2ecf20Sopenharmony_ci|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| 198c2ecf20Sopenharmony_ci|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| 208c2ecf20Sopenharmony_ci|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| 218c2ecf20Sopenharmony_ci|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| 228c2ecf20Sopenharmony_ci|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| 238c2ecf20Sopenharmony_ci|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| 248c2ecf20Sopenharmony_ci|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| 258c2ecf20Sopenharmony_ci|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| 268c2ecf20Sopenharmony_ci|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| 278c2ecf20Sopenharmony_ci|* *| 288c2ecf20Sopenharmony_ci|* U.S. Government End Users. This source code is a "commercial *| 298c2ecf20Sopenharmony_ci|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| 308c2ecf20Sopenharmony_ci|* consisting of "commercial computer software" and "commercial *| 318c2ecf20Sopenharmony_ci|* computer software documentation," as such terms are used in *| 328c2ecf20Sopenharmony_ci|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| 338c2ecf20Sopenharmony_ci|* ment only as a commercial end item. Consistent with 48 C.F.R. *| 348c2ecf20Sopenharmony_ci|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| 358c2ecf20Sopenharmony_ci|* all U.S. Government End Users acquire the source code with only *| 368c2ecf20Sopenharmony_ci|* those rights set forth herein. *| 378c2ecf20Sopenharmony_ci|* *| 388c2ecf20Sopenharmony_ci \***************************************************************************/ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ 428c2ecf20Sopenharmony_ci * XFree86 'nv' driver, this source code is provided under MIT-style licensing 438c2ecf20Sopenharmony_ci * where the source code is provided "as is" without warranty of any kind. 448c2ecf20Sopenharmony_ci * The only usage restriction is for the copyright notices to be retained 458c2ecf20Sopenharmony_ci * whenever code is used. 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * Antonino Daplas <adaplas@pol.net> 2005-03-11 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#include <linux/fb.h> 518c2ecf20Sopenharmony_ci#include <linux/nmi.h> 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#include "nv_type.h" 548c2ecf20Sopenharmony_ci#include "nv_proto.h" 558c2ecf20Sopenharmony_ci#include "nv_dma.h" 568c2ecf20Sopenharmony_ci#include "nv_local.h" 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* There is a HW race condition with videoram command buffers. 598c2ecf20Sopenharmony_ci You can't jump to the location of your put offset. We write put 608c2ecf20Sopenharmony_ci at the jump offset + SKIPS dwords with noop padding in between 618c2ecf20Sopenharmony_ci to solve this problem */ 628c2ecf20Sopenharmony_ci#define SKIPS 8 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic const int NVCopyROP[16] = { 658c2ecf20Sopenharmony_ci 0xCC, /* copy */ 668c2ecf20Sopenharmony_ci 0x55 /* invert */ 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic const int NVCopyROP_PM[16] = { 708c2ecf20Sopenharmony_ci 0xCA, /* copy */ 718c2ecf20Sopenharmony_ci 0x5A, /* invert */ 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic inline void nvidiafb_safe_mode(struct fb_info *info) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci touch_softlockup_watchdog(); 798c2ecf20Sopenharmony_ci info->pixmap.scan_align = 1; 808c2ecf20Sopenharmony_ci par->lockup = 1; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic inline void NVFlush(struct fb_info *info) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 868c2ecf20Sopenharmony_ci int count = 1000000000; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci while (--count && READ_GET(par) != par->dmaPut) ; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (!count) { 918c2ecf20Sopenharmony_ci printk("nvidiafb: DMA Flush lockup\n"); 928c2ecf20Sopenharmony_ci nvidiafb_safe_mode(info); 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic inline void NVSync(struct fb_info *info) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 998c2ecf20Sopenharmony_ci int count = 1000000000; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci while (--count && NV_RD32(par->PGRAPH, 0x0700)) ; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (!count) { 1048c2ecf20Sopenharmony_ci printk("nvidiafb: DMA Sync lockup\n"); 1058c2ecf20Sopenharmony_ci nvidiafb_safe_mode(info); 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic void NVDmaKickoff(struct nvidia_par *par) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci if (par->dmaCurrent != par->dmaPut) { 1128c2ecf20Sopenharmony_ci par->dmaPut = par->dmaCurrent; 1138c2ecf20Sopenharmony_ci WRITE_PUT(par, par->dmaPut); 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic void NVDmaWait(struct fb_info *info, int size) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 1208c2ecf20Sopenharmony_ci int dmaGet; 1218c2ecf20Sopenharmony_ci int count = 1000000000, cnt; 1228c2ecf20Sopenharmony_ci size++; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci while (par->dmaFree < size && --count && !par->lockup) { 1258c2ecf20Sopenharmony_ci dmaGet = READ_GET(par); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (par->dmaPut >= dmaGet) { 1288c2ecf20Sopenharmony_ci par->dmaFree = par->dmaMax - par->dmaCurrent; 1298c2ecf20Sopenharmony_ci if (par->dmaFree < size) { 1308c2ecf20Sopenharmony_ci NVDmaNext(par, 0x20000000); 1318c2ecf20Sopenharmony_ci if (dmaGet <= SKIPS) { 1328c2ecf20Sopenharmony_ci if (par->dmaPut <= SKIPS) 1338c2ecf20Sopenharmony_ci WRITE_PUT(par, SKIPS + 1); 1348c2ecf20Sopenharmony_ci cnt = 1000000000; 1358c2ecf20Sopenharmony_ci do { 1368c2ecf20Sopenharmony_ci dmaGet = READ_GET(par); 1378c2ecf20Sopenharmony_ci } while (--cnt && dmaGet <= SKIPS); 1388c2ecf20Sopenharmony_ci if (!cnt) { 1398c2ecf20Sopenharmony_ci printk("DMA Get lockup\n"); 1408c2ecf20Sopenharmony_ci par->lockup = 1; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci WRITE_PUT(par, SKIPS); 1448c2ecf20Sopenharmony_ci par->dmaCurrent = par->dmaPut = SKIPS; 1458c2ecf20Sopenharmony_ci par->dmaFree = dmaGet - (SKIPS + 1); 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci } else 1488c2ecf20Sopenharmony_ci par->dmaFree = dmaGet - par->dmaCurrent - 1; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (!count) { 1528c2ecf20Sopenharmony_ci printk("nvidiafb: DMA Wait Lockup\n"); 1538c2ecf20Sopenharmony_ci nvidiafb_safe_mode(info); 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic void NVSetPattern(struct fb_info *info, u32 clr0, u32 clr1, 1588c2ecf20Sopenharmony_ci u32 pat0, u32 pat1) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci NVDmaStart(info, par, PATTERN_COLOR_0, 4); 1638c2ecf20Sopenharmony_ci NVDmaNext(par, clr0); 1648c2ecf20Sopenharmony_ci NVDmaNext(par, clr1); 1658c2ecf20Sopenharmony_ci NVDmaNext(par, pat0); 1668c2ecf20Sopenharmony_ci NVDmaNext(par, pat1); 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic void NVSetRopSolid(struct fb_info *info, u32 rop, u32 planemask) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (planemask != ~0) { 1748c2ecf20Sopenharmony_ci NVSetPattern(info, 0, planemask, ~0, ~0); 1758c2ecf20Sopenharmony_ci if (par->currentRop != (rop + 32)) { 1768c2ecf20Sopenharmony_ci NVDmaStart(info, par, ROP_SET, 1); 1778c2ecf20Sopenharmony_ci NVDmaNext(par, NVCopyROP_PM[rop]); 1788c2ecf20Sopenharmony_ci par->currentRop = rop + 32; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci } else if (par->currentRop != rop) { 1818c2ecf20Sopenharmony_ci if (par->currentRop >= 16) 1828c2ecf20Sopenharmony_ci NVSetPattern(info, ~0, ~0, ~0, ~0); 1838c2ecf20Sopenharmony_ci NVDmaStart(info, par, ROP_SET, 1); 1848c2ecf20Sopenharmony_ci NVDmaNext(par, NVCopyROP[rop]); 1858c2ecf20Sopenharmony_ci par->currentRop = rop; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic void NVSetClippingRectangle(struct fb_info *info, int x1, int y1, 1908c2ecf20Sopenharmony_ci int x2, int y2) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 1938c2ecf20Sopenharmony_ci int h = y2 - y1 + 1; 1948c2ecf20Sopenharmony_ci int w = x2 - x1 + 1; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci NVDmaStart(info, par, CLIP_POINT, 2); 1978c2ecf20Sopenharmony_ci NVDmaNext(par, (y1 << 16) | x1); 1988c2ecf20Sopenharmony_ci NVDmaNext(par, (h << 16) | w); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_civoid NVResetGraphics(struct fb_info *info) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 2048c2ecf20Sopenharmony_ci u32 surfaceFormat, patternFormat, rectFormat, lineFormat; 2058c2ecf20Sopenharmony_ci int pitch, i; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci pitch = info->fix.line_length; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci for (i = 0; i < SKIPS; i++) 2128c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[i], 0, 0x00000000); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000); 2158c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010); 2168c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000); 2178c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011); 2188c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000); 2198c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012); 2208c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000); 2218c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013); 2228c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000); 2238c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014); 2248c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000); 2258c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015); 2268c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000); 2278c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016); 2288c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000); 2298c2ecf20Sopenharmony_ci NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci par->dmaPut = 0; 2328c2ecf20Sopenharmony_ci par->dmaCurrent = 16 + SKIPS; 2338c2ecf20Sopenharmony_ci par->dmaMax = 8191; 2348c2ecf20Sopenharmony_ci par->dmaFree = par->dmaMax - par->dmaCurrent; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci switch (info->var.bits_per_pixel) { 2378c2ecf20Sopenharmony_ci case 32: 2388c2ecf20Sopenharmony_ci case 24: 2398c2ecf20Sopenharmony_ci surfaceFormat = SURFACE_FORMAT_DEPTH24; 2408c2ecf20Sopenharmony_ci patternFormat = PATTERN_FORMAT_DEPTH24; 2418c2ecf20Sopenharmony_ci rectFormat = RECT_FORMAT_DEPTH24; 2428c2ecf20Sopenharmony_ci lineFormat = LINE_FORMAT_DEPTH24; 2438c2ecf20Sopenharmony_ci break; 2448c2ecf20Sopenharmony_ci case 16: 2458c2ecf20Sopenharmony_ci surfaceFormat = SURFACE_FORMAT_DEPTH16; 2468c2ecf20Sopenharmony_ci patternFormat = PATTERN_FORMAT_DEPTH16; 2478c2ecf20Sopenharmony_ci rectFormat = RECT_FORMAT_DEPTH16; 2488c2ecf20Sopenharmony_ci lineFormat = LINE_FORMAT_DEPTH16; 2498c2ecf20Sopenharmony_ci break; 2508c2ecf20Sopenharmony_ci default: 2518c2ecf20Sopenharmony_ci surfaceFormat = SURFACE_FORMAT_DEPTH8; 2528c2ecf20Sopenharmony_ci patternFormat = PATTERN_FORMAT_DEPTH8; 2538c2ecf20Sopenharmony_ci rectFormat = RECT_FORMAT_DEPTH8; 2548c2ecf20Sopenharmony_ci lineFormat = LINE_FORMAT_DEPTH8; 2558c2ecf20Sopenharmony_ci break; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci NVDmaStart(info, par, SURFACE_FORMAT, 4); 2598c2ecf20Sopenharmony_ci NVDmaNext(par, surfaceFormat); 2608c2ecf20Sopenharmony_ci NVDmaNext(par, pitch | (pitch << 16)); 2618c2ecf20Sopenharmony_ci NVDmaNext(par, 0); 2628c2ecf20Sopenharmony_ci NVDmaNext(par, 0); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci NVDmaStart(info, par, PATTERN_FORMAT, 1); 2658c2ecf20Sopenharmony_ci NVDmaNext(par, patternFormat); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci NVDmaStart(info, par, RECT_FORMAT, 1); 2688c2ecf20Sopenharmony_ci NVDmaNext(par, rectFormat); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci NVDmaStart(info, par, LINE_FORMAT, 1); 2718c2ecf20Sopenharmony_ci NVDmaNext(par, lineFormat); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci par->currentRop = ~0; /* set to something invalid */ 2748c2ecf20Sopenharmony_ci NVSetRopSolid(info, ROP_COPY, ~0); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual, 2778c2ecf20Sopenharmony_ci info->var.yres_virtual); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci NVDmaKickoff(par); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ciint nvidiafb_sync(struct fb_info *info) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 2878c2ecf20Sopenharmony_ci return 0; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (!par->lockup) 2908c2ecf20Sopenharmony_ci NVFlush(info); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (!par->lockup) 2938c2ecf20Sopenharmony_ci NVSync(info); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci return 0; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_civoid nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 3038c2ecf20Sopenharmony_ci return; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (par->lockup) { 3068c2ecf20Sopenharmony_ci cfb_copyarea(info, region); 3078c2ecf20Sopenharmony_ci return; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci NVDmaStart(info, par, BLIT_POINT_SRC, 3); 3118c2ecf20Sopenharmony_ci NVDmaNext(par, (region->sy << 16) | region->sx); 3128c2ecf20Sopenharmony_ci NVDmaNext(par, (region->dy << 16) | region->dx); 3138c2ecf20Sopenharmony_ci NVDmaNext(par, (region->height << 16) | region->width); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci NVDmaKickoff(par); 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_civoid nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 3218c2ecf20Sopenharmony_ci u32 color; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 3248c2ecf20Sopenharmony_ci return; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (par->lockup) { 3278c2ecf20Sopenharmony_ci cfb_fillrect(info, rect); 3288c2ecf20Sopenharmony_ci return; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci if (info->var.bits_per_pixel == 8) 3328c2ecf20Sopenharmony_ci color = rect->color; 3338c2ecf20Sopenharmony_ci else 3348c2ecf20Sopenharmony_ci color = ((u32 *) info->pseudo_palette)[rect->color]; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (rect->rop != ROP_COPY) 3378c2ecf20Sopenharmony_ci NVSetRopSolid(info, rect->rop, ~0); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci NVDmaStart(info, par, RECT_SOLID_COLOR, 1); 3408c2ecf20Sopenharmony_ci NVDmaNext(par, color); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci NVDmaStart(info, par, RECT_SOLID_RECTS(0), 2); 3438c2ecf20Sopenharmony_ci NVDmaNext(par, (rect->dx << 16) | rect->dy); 3448c2ecf20Sopenharmony_ci NVDmaNext(par, (rect->width << 16) | rect->height); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci NVDmaKickoff(par); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci if (rect->rop != ROP_COPY) 3498c2ecf20Sopenharmony_ci NVSetRopSolid(info, ROP_COPY, ~0); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic void nvidiafb_mono_color_expand(struct fb_info *info, 3538c2ecf20Sopenharmony_ci const struct fb_image *image) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 3568c2ecf20Sopenharmony_ci u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel)); 3578c2ecf20Sopenharmony_ci u32 dsize, width, *data = (u32 *) image->data, tmp; 3588c2ecf20Sopenharmony_ci int j, k = 0; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci width = (image->width + 31) & ~31; 3618c2ecf20Sopenharmony_ci dsize = (width * image->height) >> 5; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if (info->var.bits_per_pixel == 8) { 3648c2ecf20Sopenharmony_ci fg = image->fg_color | mask; 3658c2ecf20Sopenharmony_ci bg = image->bg_color | mask; 3668c2ecf20Sopenharmony_ci } else { 3678c2ecf20Sopenharmony_ci fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask; 3688c2ecf20Sopenharmony_ci bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask; 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_CLIP, 7); 3728c2ecf20Sopenharmony_ci NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff)); 3738c2ecf20Sopenharmony_ci NVDmaNext(par, ((image->dy + image->height) << 16) | 3748c2ecf20Sopenharmony_ci ((image->dx + image->width) & 0xffff)); 3758c2ecf20Sopenharmony_ci NVDmaNext(par, bg); 3768c2ecf20Sopenharmony_ci NVDmaNext(par, fg); 3778c2ecf20Sopenharmony_ci NVDmaNext(par, (image->height << 16) | width); 3788c2ecf20Sopenharmony_ci NVDmaNext(par, (image->height << 16) | width); 3798c2ecf20Sopenharmony_ci NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff)); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) { 3828c2ecf20Sopenharmony_ci NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), 3838c2ecf20Sopenharmony_ci RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) { 3868c2ecf20Sopenharmony_ci tmp = data[k++]; 3878c2ecf20Sopenharmony_ci reverse_order(&tmp); 3888c2ecf20Sopenharmony_ci NVDmaNext(par, tmp); 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci if (dsize) { 3958c2ecf20Sopenharmony_ci NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci for (j = dsize; j--;) { 3988c2ecf20Sopenharmony_ci tmp = data[k++]; 3998c2ecf20Sopenharmony_ci reverse_order(&tmp); 4008c2ecf20Sopenharmony_ci NVDmaNext(par, tmp); 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci NVDmaKickoff(par); 4058c2ecf20Sopenharmony_ci} 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_civoid nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci struct nvidia_par *par = info->par; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 4128c2ecf20Sopenharmony_ci return; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (image->depth == 1 && !par->lockup) 4158c2ecf20Sopenharmony_ci nvidiafb_mono_color_expand(info, image); 4168c2ecf20Sopenharmony_ci else 4178c2ecf20Sopenharmony_ci cfb_imageblit(info, image); 4188c2ecf20Sopenharmony_ci} 419