0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 #include <linux/fb.h>
0051 #include <linux/nmi.h>
0052
0053 #include "nv_type.h"
0054 #include "nv_proto.h"
0055 #include "nv_dma.h"
0056 #include "nv_local.h"
0057
0058
0059
0060
0061
0062 #define SKIPS 8
0063
0064 static const int NVCopyROP[16] = {
0065 0xCC,
0066 0x55
0067 };
0068
0069 static const int NVCopyROP_PM[16] = {
0070 0xCA,
0071 0x5A,
0072 };
0073
0074 static inline void nvidiafb_safe_mode(struct fb_info *info)
0075 {
0076 struct nvidia_par *par = info->par;
0077
0078 touch_softlockup_watchdog();
0079 info->pixmap.scan_align = 1;
0080 par->lockup = 1;
0081 }
0082
0083 static inline void NVFlush(struct fb_info *info)
0084 {
0085 struct nvidia_par *par = info->par;
0086 int count = 1000000000;
0087
0088 while (--count && READ_GET(par) != par->dmaPut) ;
0089
0090 if (!count) {
0091 printk("nvidiafb: DMA Flush lockup\n");
0092 nvidiafb_safe_mode(info);
0093 }
0094 }
0095
0096 static inline void NVSync(struct fb_info *info)
0097 {
0098 struct nvidia_par *par = info->par;
0099 int count = 1000000000;
0100
0101 while (--count && NV_RD32(par->PGRAPH, 0x0700)) ;
0102
0103 if (!count) {
0104 printk("nvidiafb: DMA Sync lockup\n");
0105 nvidiafb_safe_mode(info);
0106 }
0107 }
0108
0109 static void NVDmaKickoff(struct nvidia_par *par)
0110 {
0111 if (par->dmaCurrent != par->dmaPut) {
0112 par->dmaPut = par->dmaCurrent;
0113 WRITE_PUT(par, par->dmaPut);
0114 }
0115 }
0116
0117 static void NVDmaWait(struct fb_info *info, int size)
0118 {
0119 struct nvidia_par *par = info->par;
0120 int dmaGet;
0121 int count = 1000000000, cnt;
0122 size++;
0123
0124 while (par->dmaFree < size && --count && !par->lockup) {
0125 dmaGet = READ_GET(par);
0126
0127 if (par->dmaPut >= dmaGet) {
0128 par->dmaFree = par->dmaMax - par->dmaCurrent;
0129 if (par->dmaFree < size) {
0130 NVDmaNext(par, 0x20000000);
0131 if (dmaGet <= SKIPS) {
0132 if (par->dmaPut <= SKIPS)
0133 WRITE_PUT(par, SKIPS + 1);
0134 cnt = 1000000000;
0135 do {
0136 dmaGet = READ_GET(par);
0137 } while (--cnt && dmaGet <= SKIPS);
0138 if (!cnt) {
0139 printk("DMA Get lockup\n");
0140 par->lockup = 1;
0141 }
0142 }
0143 WRITE_PUT(par, SKIPS);
0144 par->dmaCurrent = par->dmaPut = SKIPS;
0145 par->dmaFree = dmaGet - (SKIPS + 1);
0146 }
0147 } else
0148 par->dmaFree = dmaGet - par->dmaCurrent - 1;
0149 }
0150
0151 if (!count) {
0152 printk("nvidiafb: DMA Wait Lockup\n");
0153 nvidiafb_safe_mode(info);
0154 }
0155 }
0156
0157 static void NVSetPattern(struct fb_info *info, u32 clr0, u32 clr1,
0158 u32 pat0, u32 pat1)
0159 {
0160 struct nvidia_par *par = info->par;
0161
0162 NVDmaStart(info, par, PATTERN_COLOR_0, 4);
0163 NVDmaNext(par, clr0);
0164 NVDmaNext(par, clr1);
0165 NVDmaNext(par, pat0);
0166 NVDmaNext(par, pat1);
0167 }
0168
0169 static void NVSetRopSolid(struct fb_info *info, u32 rop, u32 planemask)
0170 {
0171 struct nvidia_par *par = info->par;
0172
0173 if (planemask != ~0) {
0174 NVSetPattern(info, 0, planemask, ~0, ~0);
0175 if (par->currentRop != (rop + 32)) {
0176 NVDmaStart(info, par, ROP_SET, 1);
0177 NVDmaNext(par, NVCopyROP_PM[rop]);
0178 par->currentRop = rop + 32;
0179 }
0180 } else if (par->currentRop != rop) {
0181 if (par->currentRop >= 16)
0182 NVSetPattern(info, ~0, ~0, ~0, ~0);
0183 NVDmaStart(info, par, ROP_SET, 1);
0184 NVDmaNext(par, NVCopyROP[rop]);
0185 par->currentRop = rop;
0186 }
0187 }
0188
0189 static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1,
0190 int x2, int y2)
0191 {
0192 struct nvidia_par *par = info->par;
0193 int h = y2 - y1 + 1;
0194 int w = x2 - x1 + 1;
0195
0196 NVDmaStart(info, par, CLIP_POINT, 2);
0197 NVDmaNext(par, (y1 << 16) | x1);
0198 NVDmaNext(par, (h << 16) | w);
0199 }
0200
0201 void NVResetGraphics(struct fb_info *info)
0202 {
0203 struct nvidia_par *par = info->par;
0204 u32 surfaceFormat, patternFormat, rectFormat, lineFormat;
0205 int pitch, i;
0206
0207 pitch = info->fix.line_length;
0208
0209 par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]);
0210
0211 for (i = 0; i < SKIPS; i++)
0212 NV_WR32(&par->dmaBase[i], 0, 0x00000000);
0213
0214 NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000);
0215 NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010);
0216 NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000);
0217 NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011);
0218 NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000);
0219 NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012);
0220 NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000);
0221 NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013);
0222 NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000);
0223 NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014);
0224 NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000);
0225 NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015);
0226 NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000);
0227 NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016);
0228 NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000);
0229 NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017);
0230
0231 par->dmaPut = 0;
0232 par->dmaCurrent = 16 + SKIPS;
0233 par->dmaMax = 8191;
0234 par->dmaFree = par->dmaMax - par->dmaCurrent;
0235
0236 switch (info->var.bits_per_pixel) {
0237 case 32:
0238 case 24:
0239 surfaceFormat = SURFACE_FORMAT_DEPTH24;
0240 patternFormat = PATTERN_FORMAT_DEPTH24;
0241 rectFormat = RECT_FORMAT_DEPTH24;
0242 lineFormat = LINE_FORMAT_DEPTH24;
0243 break;
0244 case 16:
0245 surfaceFormat = SURFACE_FORMAT_DEPTH16;
0246 patternFormat = PATTERN_FORMAT_DEPTH16;
0247 rectFormat = RECT_FORMAT_DEPTH16;
0248 lineFormat = LINE_FORMAT_DEPTH16;
0249 break;
0250 default:
0251 surfaceFormat = SURFACE_FORMAT_DEPTH8;
0252 patternFormat = PATTERN_FORMAT_DEPTH8;
0253 rectFormat = RECT_FORMAT_DEPTH8;
0254 lineFormat = LINE_FORMAT_DEPTH8;
0255 break;
0256 }
0257
0258 NVDmaStart(info, par, SURFACE_FORMAT, 4);
0259 NVDmaNext(par, surfaceFormat);
0260 NVDmaNext(par, pitch | (pitch << 16));
0261 NVDmaNext(par, 0);
0262 NVDmaNext(par, 0);
0263
0264 NVDmaStart(info, par, PATTERN_FORMAT, 1);
0265 NVDmaNext(par, patternFormat);
0266
0267 NVDmaStart(info, par, RECT_FORMAT, 1);
0268 NVDmaNext(par, rectFormat);
0269
0270 NVDmaStart(info, par, LINE_FORMAT, 1);
0271 NVDmaNext(par, lineFormat);
0272
0273 par->currentRop = ~0;
0274 NVSetRopSolid(info, ROP_COPY, ~0);
0275
0276 NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual,
0277 info->var.yres_virtual);
0278
0279 NVDmaKickoff(par);
0280 }
0281
0282 int nvidiafb_sync(struct fb_info *info)
0283 {
0284 struct nvidia_par *par = info->par;
0285
0286 if (info->state != FBINFO_STATE_RUNNING)
0287 return 0;
0288
0289 if (!par->lockup)
0290 NVFlush(info);
0291
0292 if (!par->lockup)
0293 NVSync(info);
0294
0295 return 0;
0296 }
0297
0298 void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
0299 {
0300 struct nvidia_par *par = info->par;
0301
0302 if (info->state != FBINFO_STATE_RUNNING)
0303 return;
0304
0305 if (par->lockup) {
0306 cfb_copyarea(info, region);
0307 return;
0308 }
0309
0310 NVDmaStart(info, par, BLIT_POINT_SRC, 3);
0311 NVDmaNext(par, (region->sy << 16) | region->sx);
0312 NVDmaNext(par, (region->dy << 16) | region->dx);
0313 NVDmaNext(par, (region->height << 16) | region->width);
0314
0315 NVDmaKickoff(par);
0316 }
0317
0318 void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
0319 {
0320 struct nvidia_par *par = info->par;
0321 u32 color;
0322
0323 if (info->state != FBINFO_STATE_RUNNING)
0324 return;
0325
0326 if (par->lockup) {
0327 cfb_fillrect(info, rect);
0328 return;
0329 }
0330
0331 if (info->var.bits_per_pixel == 8)
0332 color = rect->color;
0333 else
0334 color = ((u32 *) info->pseudo_palette)[rect->color];
0335
0336 if (rect->rop != ROP_COPY)
0337 NVSetRopSolid(info, rect->rop, ~0);
0338
0339 NVDmaStart(info, par, RECT_SOLID_COLOR, 1);
0340 NVDmaNext(par, color);
0341
0342 NVDmaStart(info, par, RECT_SOLID_RECTS(0), 2);
0343 NVDmaNext(par, (rect->dx << 16) | rect->dy);
0344 NVDmaNext(par, (rect->width << 16) | rect->height);
0345
0346 NVDmaKickoff(par);
0347
0348 if (rect->rop != ROP_COPY)
0349 NVSetRopSolid(info, ROP_COPY, ~0);
0350 }
0351
0352 static void nvidiafb_mono_color_expand(struct fb_info *info,
0353 const struct fb_image *image)
0354 {
0355 struct nvidia_par *par = info->par;
0356 u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel));
0357 u32 dsize, width, *data = (u32 *) image->data, tmp;
0358 int j, k = 0;
0359
0360 width = (image->width + 31) & ~31;
0361 dsize = (width * image->height) >> 5;
0362
0363 if (info->var.bits_per_pixel == 8) {
0364 fg = image->fg_color | mask;
0365 bg = image->bg_color | mask;
0366 } else {
0367 fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask;
0368 bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask;
0369 }
0370
0371 NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_CLIP, 7);
0372 NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
0373 NVDmaNext(par, ((image->dy + image->height) << 16) |
0374 ((image->dx + image->width) & 0xffff));
0375 NVDmaNext(par, bg);
0376 NVDmaNext(par, fg);
0377 NVDmaNext(par, (image->height << 16) | width);
0378 NVDmaNext(par, (image->height << 16) | width);
0379 NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
0380
0381 while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) {
0382 NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0),
0383 RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS);
0384
0385 for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) {
0386 tmp = data[k++];
0387 reverse_order(&tmp);
0388 NVDmaNext(par, tmp);
0389 }
0390
0391 dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS;
0392 }
0393
0394 if (dsize) {
0395 NVDmaStart(info, par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
0396
0397 for (j = dsize; j--;) {
0398 tmp = data[k++];
0399 reverse_order(&tmp);
0400 NVDmaNext(par, tmp);
0401 }
0402 }
0403
0404 NVDmaKickoff(par);
0405 }
0406
0407 void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
0408 {
0409 struct nvidia_par *par = info->par;
0410
0411 if (info->state != FBINFO_STATE_RUNNING)
0412 return;
0413
0414 if (image->depth == 1 && !par->lockup)
0415 nvidiafb_mono_color_expand(info, image);
0416 else
0417 cfb_imageblit(info, image);
0418 }