162306a36Sopenharmony_ci /***************************************************************************\ 262306a36Sopenharmony_ci|* *| 362306a36Sopenharmony_ci|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| 462306a36Sopenharmony_ci|* *| 562306a36Sopenharmony_ci|* NOTICE TO USER: The source code is copyrighted under U.S. and *| 662306a36Sopenharmony_ci|* international laws. Users and possessors of this source code are *| 762306a36Sopenharmony_ci|* hereby granted a nonexclusive, royalty-free copyright license to *| 862306a36Sopenharmony_ci|* use this code in individual and commercial software. *| 962306a36Sopenharmony_ci|* *| 1062306a36Sopenharmony_ci|* Any use of this source code must include, in the user documenta- *| 1162306a36Sopenharmony_ci|* tion and internal comments to the code, notices to the end user *| 1262306a36Sopenharmony_ci|* as follows: *| 1362306a36Sopenharmony_ci|* *| 1462306a36Sopenharmony_ci|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *| 1562306a36Sopenharmony_ci|* *| 1662306a36Sopenharmony_ci|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| 1762306a36Sopenharmony_ci|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| 1862306a36Sopenharmony_ci|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| 1962306a36Sopenharmony_ci|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| 2062306a36Sopenharmony_ci|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| 2162306a36Sopenharmony_ci|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| 2262306a36Sopenharmony_ci|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| 2362306a36Sopenharmony_ci|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| 2462306a36Sopenharmony_ci|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| 2562306a36Sopenharmony_ci|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| 2662306a36Sopenharmony_ci|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| 2762306a36Sopenharmony_ci|* *| 2862306a36Sopenharmony_ci|* U.S. Government End Users. This source code is a "commercial *| 2962306a36Sopenharmony_ci|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| 3062306a36Sopenharmony_ci|* consisting of "commercial computer software" and "commercial *| 3162306a36Sopenharmony_ci|* computer software documentation," as such terms are used in *| 3262306a36Sopenharmony_ci|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| 3362306a36Sopenharmony_ci|* ment only as a commercial end item. Consistent with 48 C.F.R. *| 3462306a36Sopenharmony_ci|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| 3562306a36Sopenharmony_ci|* all U.S. Government End Users acquire the source code with only *| 3662306a36Sopenharmony_ci|* those rights set forth herein. *| 3762306a36Sopenharmony_ci|* *| 3862306a36Sopenharmony_ci \***************************************************************************/ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/ 4262306a36Sopenharmony_ci * XFree86 'nv' driver, this source code is provided under MIT-style licensing 4362306a36Sopenharmony_ci * where the source code is provided "as is" without warranty of any kind. 4462306a36Sopenharmony_ci * The only usage restriction is for the copyright notices to be retained 4562306a36Sopenharmony_ci * whenever code is used. 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * Antonino Daplas <adaplas@pol.net> 2005-03-11 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#include <linux/fb.h> 5162306a36Sopenharmony_ci#include <linux/nmi.h> 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#include "nv_type.h" 5462306a36Sopenharmony_ci#include "nv_proto.h" 5562306a36Sopenharmony_ci#include "nv_dma.h" 5662306a36Sopenharmony_ci#include "nv_local.h" 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* There is a HW race condition with videoram command buffers. 5962306a36Sopenharmony_ci You can't jump to the location of your put offset. We write put 6062306a36Sopenharmony_ci at the jump offset + SKIPS dwords with noop padding in between 6162306a36Sopenharmony_ci to solve this problem */ 6262306a36Sopenharmony_ci#define SKIPS 8 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic const int NVCopyROP[16] = { 6562306a36Sopenharmony_ci 0xCC, /* copy */ 6662306a36Sopenharmony_ci 0x55 /* invert */ 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic const int NVCopyROP_PM[16] = { 7062306a36Sopenharmony_ci 0xCA, /* copy */ 7162306a36Sopenharmony_ci 0x5A, /* invert */ 7262306a36Sopenharmony_ci}; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic inline void nvidiafb_safe_mode(struct fb_info *info) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct nvidia_par *par = info->par; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci touch_softlockup_watchdog(); 7962306a36Sopenharmony_ci info->pixmap.scan_align = 1; 8062306a36Sopenharmony_ci par->lockup = 1; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic inline void NVFlush(struct fb_info *info) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct nvidia_par *par = info->par; 8662306a36Sopenharmony_ci int count = 1000000000; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci while (--count && READ_GET(par) != par->dmaPut) ; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (!count) { 9162306a36Sopenharmony_ci printk("nvidiafb: DMA Flush lockup\n"); 9262306a36Sopenharmony_ci nvidiafb_safe_mode(info); 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic inline void NVSync(struct fb_info *info) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci struct nvidia_par *par = info->par; 9962306a36Sopenharmony_ci int count = 1000000000; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci while (--count && NV_RD32(par->PGRAPH, 0x0700)) ; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if (!count) { 10462306a36Sopenharmony_ci printk("nvidiafb: DMA Sync lockup\n"); 10562306a36Sopenharmony_ci nvidiafb_safe_mode(info); 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic void NVDmaKickoff(struct nvidia_par *par) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci if (par->dmaCurrent != par->dmaPut) { 11262306a36Sopenharmony_ci par->dmaPut = par->dmaCurrent; 11362306a36Sopenharmony_ci WRITE_PUT(par, par->dmaPut); 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic void NVDmaWait(struct fb_info *info, int size) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci struct nvidia_par *par = info->par; 12062306a36Sopenharmony_ci int dmaGet; 12162306a36Sopenharmony_ci int count = 1000000000, cnt; 12262306a36Sopenharmony_ci size++; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci while (par->dmaFree < size && --count && !par->lockup) { 12562306a36Sopenharmony_ci dmaGet = READ_GET(par); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (par->dmaPut >= dmaGet) { 12862306a36Sopenharmony_ci par->dmaFree = par->dmaMax - par->dmaCurrent; 12962306a36Sopenharmony_ci if (par->dmaFree < size) { 13062306a36Sopenharmony_ci NVDmaNext(par, 0x20000000); 13162306a36Sopenharmony_ci if (dmaGet <= SKIPS) { 13262306a36Sopenharmony_ci if (par->dmaPut <= SKIPS) 13362306a36Sopenharmony_ci WRITE_PUT(par, SKIPS + 1); 13462306a36Sopenharmony_ci cnt = 1000000000; 13562306a36Sopenharmony_ci do { 13662306a36Sopenharmony_ci dmaGet = READ_GET(par); 13762306a36Sopenharmony_ci } while (--cnt && dmaGet <= SKIPS); 13862306a36Sopenharmony_ci if (!cnt) { 13962306a36Sopenharmony_ci printk("DMA Get lockup\n"); 14062306a36Sopenharmony_ci par->lockup = 1; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci WRITE_PUT(par, SKIPS); 14462306a36Sopenharmony_ci par->dmaCurrent = par->dmaPut = SKIPS; 14562306a36Sopenharmony_ci par->dmaFree = dmaGet - (SKIPS + 1); 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci } else 14862306a36Sopenharmony_ci par->dmaFree = dmaGet - par->dmaCurrent - 1; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (!count) { 15262306a36Sopenharmony_ci printk("nvidiafb: DMA Wait Lockup\n"); 15362306a36Sopenharmony_ci nvidiafb_safe_mode(info); 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic void NVSetPattern(struct fb_info *info, u32 clr0, u32 clr1, 15862306a36Sopenharmony_ci u32 pat0, u32 pat1) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci struct nvidia_par *par = info->par; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci NVDmaStart(info, par, PATTERN_COLOR_0, 4); 16362306a36Sopenharmony_ci NVDmaNext(par, clr0); 16462306a36Sopenharmony_ci NVDmaNext(par, clr1); 16562306a36Sopenharmony_ci NVDmaNext(par, pat0); 16662306a36Sopenharmony_ci NVDmaNext(par, pat1); 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic void NVSetRopSolid(struct fb_info *info, u32 rop, u32 planemask) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct nvidia_par *par = info->par; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if (planemask != ~0) { 17462306a36Sopenharmony_ci NVSetPattern(info, 0, planemask, ~0, ~0); 17562306a36Sopenharmony_ci if (par->currentRop != (rop + 32)) { 17662306a36Sopenharmony_ci NVDmaStart(info, par, ROP_SET, 1); 17762306a36Sopenharmony_ci NVDmaNext(par, NVCopyROP_PM[rop]); 17862306a36Sopenharmony_ci par->currentRop = rop + 32; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci } else if (par->currentRop != rop) { 18162306a36Sopenharmony_ci if (par->currentRop >= 16) 18262306a36Sopenharmony_ci NVSetPattern(info, ~0, ~0, ~0, ~0); 18362306a36Sopenharmony_ci NVDmaStart(info, par, ROP_SET, 1); 18462306a36Sopenharmony_ci NVDmaNext(par, NVCopyROP[rop]); 18562306a36Sopenharmony_ci par->currentRop = rop; 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic void NVSetClippingRectangle(struct fb_info *info, int x1, int y1, 19062306a36Sopenharmony_ci int x2, int y2) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci struct nvidia_par *par = info->par; 19362306a36Sopenharmony_ci int h = y2 - y1 + 1; 19462306a36Sopenharmony_ci int w = x2 - x1 + 1; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci NVDmaStart(info, par, CLIP_POINT, 2); 19762306a36Sopenharmony_ci NVDmaNext(par, (y1 << 16) | x1); 19862306a36Sopenharmony_ci NVDmaNext(par, (h << 16) | w); 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_civoid NVResetGraphics(struct fb_info *info) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct nvidia_par *par = info->par; 20462306a36Sopenharmony_ci u32 surfaceFormat, patternFormat, rectFormat, lineFormat; 20562306a36Sopenharmony_ci int pitch, i; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci pitch = info->fix.line_length; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci for (i = 0; i < SKIPS; i++) 21262306a36Sopenharmony_ci NV_WR32(&par->dmaBase[i], 0, 0x00000000); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000); 21562306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010); 21662306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000); 21762306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011); 21862306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000); 21962306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012); 22062306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000); 22162306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013); 22262306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000); 22362306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014); 22462306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000); 22562306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015); 22662306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000); 22762306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016); 22862306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000); 22962306a36Sopenharmony_ci NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci par->dmaPut = 0; 23262306a36Sopenharmony_ci par->dmaCurrent = 16 + SKIPS; 23362306a36Sopenharmony_ci par->dmaMax = 8191; 23462306a36Sopenharmony_ci par->dmaFree = par->dmaMax - par->dmaCurrent; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci switch (info->var.bits_per_pixel) { 23762306a36Sopenharmony_ci case 32: 23862306a36Sopenharmony_ci case 24: 23962306a36Sopenharmony_ci surfaceFormat = SURFACE_FORMAT_DEPTH24; 24062306a36Sopenharmony_ci patternFormat = PATTERN_FORMAT_DEPTH24; 24162306a36Sopenharmony_ci rectFormat = RECT_FORMAT_DEPTH24; 24262306a36Sopenharmony_ci lineFormat = LINE_FORMAT_DEPTH24; 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci case 16: 24562306a36Sopenharmony_ci surfaceFormat = SURFACE_FORMAT_DEPTH16; 24662306a36Sopenharmony_ci patternFormat = PATTERN_FORMAT_DEPTH16; 24762306a36Sopenharmony_ci rectFormat = RECT_FORMAT_DEPTH16; 24862306a36Sopenharmony_ci lineFormat = LINE_FORMAT_DEPTH16; 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci default: 25162306a36Sopenharmony_ci surfaceFormat = SURFACE_FORMAT_DEPTH8; 25262306a36Sopenharmony_ci patternFormat = PATTERN_FORMAT_DEPTH8; 25362306a36Sopenharmony_ci rectFormat = RECT_FORMAT_DEPTH8; 25462306a36Sopenharmony_ci lineFormat = LINE_FORMAT_DEPTH8; 25562306a36Sopenharmony_ci break; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci NVDmaStart(info, par, SURFACE_FORMAT, 4); 25962306a36Sopenharmony_ci NVDmaNext(par, surfaceFormat); 26062306a36Sopenharmony_ci NVDmaNext(par, pitch | (pitch << 16)); 26162306a36Sopenharmony_ci NVDmaNext(par, 0); 26262306a36Sopenharmony_ci NVDmaNext(par, 0); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci NVDmaStart(info, par, PATTERN_FORMAT, 1); 26562306a36Sopenharmony_ci NVDmaNext(par, patternFormat); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci NVDmaStart(info, par, RECT_FORMAT, 1); 26862306a36Sopenharmony_ci NVDmaNext(par, rectFormat); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci NVDmaStart(info, par, LINE_FORMAT, 1); 27162306a36Sopenharmony_ci NVDmaNext(par, lineFormat); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci par->currentRop = ~0; /* set to something invalid */ 27462306a36Sopenharmony_ci NVSetRopSolid(info, ROP_COPY, ~0); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual, 27762306a36Sopenharmony_ci info->var.yres_virtual); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci NVDmaKickoff(par); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ciint nvidiafb_sync(struct fb_info *info) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci struct nvidia_par *par = info->par; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 28762306a36Sopenharmony_ci return 0; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci if (!par->lockup) 29062306a36Sopenharmony_ci NVFlush(info); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (!par->lockup) 29362306a36Sopenharmony_ci NVSync(info); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci return 0; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_civoid nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci struct nvidia_par *par = info->par; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 30362306a36Sopenharmony_ci return; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci if (par->lockup) { 30662306a36Sopenharmony_ci cfb_copyarea(info, region); 30762306a36Sopenharmony_ci return; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci NVDmaStart(info, par, BLIT_POINT_SRC, 3); 31162306a36Sopenharmony_ci NVDmaNext(par, (region->sy << 16) | region->sx); 31262306a36Sopenharmony_ci NVDmaNext(par, (region->dy << 16) | region->dx); 31362306a36Sopenharmony_ci NVDmaNext(par, (region->height << 16) | region->width); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci NVDmaKickoff(par); 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_civoid nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci struct nvidia_par *par = info->par; 32162306a36Sopenharmony_ci u32 color; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 32462306a36Sopenharmony_ci return; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (par->lockup) { 32762306a36Sopenharmony_ci cfb_fillrect(info, rect); 32862306a36Sopenharmony_ci return; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (info->var.bits_per_pixel == 8) 33262306a36Sopenharmony_ci color = rect->color; 33362306a36Sopenharmony_ci else 33462306a36Sopenharmony_ci color = ((u32 *) info->pseudo_palette)[rect->color]; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (rect->rop != ROP_COPY) 33762306a36Sopenharmony_ci NVSetRopSolid(info, rect->rop, ~0); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci NVDmaStart(info, par, RECT_SOLID_COLOR, 1); 34062306a36Sopenharmony_ci NVDmaNext(par, color); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci NVDmaStart(info, par, RECT_SOLID_RECTS(0), 2); 34362306a36Sopenharmony_ci NVDmaNext(par, (rect->dx << 16) | rect->dy); 34462306a36Sopenharmony_ci NVDmaNext(par, (rect->width << 16) | rect->height); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci NVDmaKickoff(par); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if (rect->rop != ROP_COPY) 34962306a36Sopenharmony_ci NVSetRopSolid(info, ROP_COPY, ~0); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic void nvidiafb_mono_color_expand(struct fb_info *info, 35362306a36Sopenharmony_ci const struct fb_image *image) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci struct nvidia_par *par = info->par; 35662306a36Sopenharmony_ci u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel)); 35762306a36Sopenharmony_ci u32 dsize, width, *data = (u32 *) image->data, tmp; 35862306a36Sopenharmony_ci int j, k = 0; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci width = (image->width + 31) & ~31; 36162306a36Sopenharmony_ci dsize = (width * image->height) >> 5; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci if (info->var.bits_per_pixel == 8) { 36462306a36Sopenharmony_ci fg = image->fg_color | mask; 36562306a36Sopenharmony_ci bg = image->bg_color | mask; 36662306a36Sopenharmony_ci } else { 36762306a36Sopenharmony_ci fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask; 36862306a36Sopenharmony_ci bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_CLIP, 7); 37262306a36Sopenharmony_ci NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff)); 37362306a36Sopenharmony_ci NVDmaNext(par, ((image->dy + image->height) << 16) | 37462306a36Sopenharmony_ci ((image->dx + image->width) & 0xffff)); 37562306a36Sopenharmony_ci NVDmaNext(par, bg); 37662306a36Sopenharmony_ci NVDmaNext(par, fg); 37762306a36Sopenharmony_ci NVDmaNext(par, (image->height << 16) | width); 37862306a36Sopenharmony_ci NVDmaNext(par, (image->height << 16) | width); 37962306a36Sopenharmony_ci NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff)); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) { 38262306a36Sopenharmony_ci NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), 38362306a36Sopenharmony_ci RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) { 38662306a36Sopenharmony_ci tmp = data[k++]; 38762306a36Sopenharmony_ci reverse_order(&tmp); 38862306a36Sopenharmony_ci NVDmaNext(par, tmp); 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (dsize) { 39562306a36Sopenharmony_ci NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci for (j = dsize; j--;) { 39862306a36Sopenharmony_ci tmp = data[k++]; 39962306a36Sopenharmony_ci reverse_order(&tmp); 40062306a36Sopenharmony_ci NVDmaNext(par, tmp); 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci NVDmaKickoff(par); 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_civoid nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci struct nvidia_par *par = info->par; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 41262306a36Sopenharmony_ci return; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci if (image->depth == 1 && !par->lockup) 41562306a36Sopenharmony_ci nvidiafb_mono_color_expand(info, image); 41662306a36Sopenharmony_ci else 41762306a36Sopenharmony_ci cfb_imageblit(info, image); 41862306a36Sopenharmony_ci} 419