1 /***************************************************************************\
3 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
5 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
6 |* international laws. Users and possessors of this source code are *|
7 |* hereby granted a nonexclusive, royalty-free copyright license to *|
8 |* use this code in individual and commercial software. *|
10 |* Any use of this source code must include, in the user documenta- *|
11 |* tion and internal comments to the code, notices to the end user *|
14 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
16 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
17 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
18 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
19 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
20 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
21 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
22 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
23 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
24 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
25 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
26 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
28 |* U.S. Government End Users. This source code is a "commercial *|
29 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
30 |* consisting of "commercial computer software" and "commercial *|
31 |* computer software documentation," as such terms are used in *|
32 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
33 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
34 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
35 |* all U.S. Government End Users acquire the source code with only *|
36 |* those rights set forth herein. *|
38 \***************************************************************************/
41 * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
42 * XFree86 'nv' driver, this source code is provided under MIT-style licensing
43 * where the source code is provided "as is" without warranty of any kind.
44 * The only usage restriction is for the copyright notices to be retained
45 * whenever code is used.
47 * Antonino Daplas <adaplas@pol.net> 2005-03-11
51 #include <linux/nmi.h>
58 /* There is a HW race condition with videoram command buffers.
59 You can't jump to the location of your put offset. We write put
60 at the jump offset + SKIPS dwords with noop padding in between
61 to solve this problem */
64 static const int NVCopyROP
[16] = {
69 static const int NVCopyROP_PM
[16] = {
74 static inline void nvidiafb_safe_mode(struct fb_info
*info
)
76 struct nvidia_par
*par
= info
->par
;
78 touch_softlockup_watchdog();
79 info
->pixmap
.scan_align
= 1;
83 static inline void NVFlush(struct fb_info
*info
)
85 struct nvidia_par
*par
= info
->par
;
86 int count
= 1000000000;
88 while (--count
&& READ_GET(par
) != par
->dmaPut
) ;
91 printk("nvidiafb: DMA Flush lockup\n");
92 nvidiafb_safe_mode(info
);
96 static inline void NVSync(struct fb_info
*info
)
98 struct nvidia_par
*par
= info
->par
;
99 int count
= 1000000000;
101 while (--count
&& NV_RD32(par
->PGRAPH
, 0x0700)) ;
104 printk("nvidiafb: DMA Sync lockup\n");
105 nvidiafb_safe_mode(info
);
109 static void NVDmaKickoff(struct nvidia_par
*par
)
111 if (par
->dmaCurrent
!= par
->dmaPut
) {
112 par
->dmaPut
= par
->dmaCurrent
;
113 WRITE_PUT(par
, par
->dmaPut
);
117 static void NVDmaWait(struct fb_info
*info
, int size
)
119 struct nvidia_par
*par
= info
->par
;
121 int count
= 1000000000, cnt
;
124 while (par
->dmaFree
< size
&& --count
&& !par
->lockup
) {
125 dmaGet
= READ_GET(par
);
127 if (par
->dmaPut
>= dmaGet
) {
128 par
->dmaFree
= par
->dmaMax
- par
->dmaCurrent
;
129 if (par
->dmaFree
< size
) {
130 NVDmaNext(par
, 0x20000000);
131 if (dmaGet
<= SKIPS
) {
132 if (par
->dmaPut
<= SKIPS
)
133 WRITE_PUT(par
, SKIPS
+ 1);
136 dmaGet
= READ_GET(par
);
137 } while (--cnt
&& dmaGet
<= SKIPS
);
139 printk("DMA Get lockup\n");
143 WRITE_PUT(par
, SKIPS
);
144 par
->dmaCurrent
= par
->dmaPut
= SKIPS
;
145 par
->dmaFree
= dmaGet
- (SKIPS
+ 1);
148 par
->dmaFree
= dmaGet
- par
->dmaCurrent
- 1;
152 printk("nvidiafb: DMA Wait Lockup\n");
153 nvidiafb_safe_mode(info
);
157 static void NVSetPattern(struct fb_info
*info
, u32 clr0
, u32 clr1
,
160 struct nvidia_par
*par
= info
->par
;
162 NVDmaStart(info
, par
, PATTERN_COLOR_0
, 4);
163 NVDmaNext(par
, clr0
);
164 NVDmaNext(par
, clr1
);
165 NVDmaNext(par
, pat0
);
166 NVDmaNext(par
, pat1
);
169 static void NVSetRopSolid(struct fb_info
*info
, u32 rop
, u32 planemask
)
171 struct nvidia_par
*par
= info
->par
;
173 if (planemask
!= ~0) {
174 NVSetPattern(info
, 0, planemask
, ~0, ~0);
175 if (par
->currentRop
!= (rop
+ 32)) {
176 NVDmaStart(info
, par
, ROP_SET
, 1);
177 NVDmaNext(par
, NVCopyROP_PM
[rop
]);
178 par
->currentRop
= rop
+ 32;
180 } else if (par
->currentRop
!= rop
) {
181 if (par
->currentRop
>= 16)
182 NVSetPattern(info
, ~0, ~0, ~0, ~0);
183 NVDmaStart(info
, par
, ROP_SET
, 1);
184 NVDmaNext(par
, NVCopyROP
[rop
]);
185 par
->currentRop
= rop
;
189 static void NVSetClippingRectangle(struct fb_info
*info
, int x1
, int y1
,
192 struct nvidia_par
*par
= info
->par
;
196 NVDmaStart(info
, par
, CLIP_POINT
, 2);
197 NVDmaNext(par
, (y1
<< 16) | x1
);
198 NVDmaNext(par
, (h
<< 16) | w
);
201 void NVResetGraphics(struct fb_info
*info
)
203 struct nvidia_par
*par
= info
->par
;
204 u32 surfaceFormat
, patternFormat
, rectFormat
, lineFormat
;
207 pitch
= info
->fix
.line_length
;
209 par
->dmaBase
= (u32 __iomem
*) (&par
->FbStart
[par
->FbUsableSize
]);
211 for (i
= 0; i
< SKIPS
; i
++)
212 NV_WR32(&par
->dmaBase
[i
], 0, 0x00000000);
214 NV_WR32(&par
->dmaBase
[0x0 + SKIPS
], 0, 0x00040000);
215 NV_WR32(&par
->dmaBase
[0x1 + SKIPS
], 0, 0x80000010);
216 NV_WR32(&par
->dmaBase
[0x2 + SKIPS
], 0, 0x00042000);
217 NV_WR32(&par
->dmaBase
[0x3 + SKIPS
], 0, 0x80000011);
218 NV_WR32(&par
->dmaBase
[0x4 + SKIPS
], 0, 0x00044000);
219 NV_WR32(&par
->dmaBase
[0x5 + SKIPS
], 0, 0x80000012);
220 NV_WR32(&par
->dmaBase
[0x6 + SKIPS
], 0, 0x00046000);
221 NV_WR32(&par
->dmaBase
[0x7 + SKIPS
], 0, 0x80000013);
222 NV_WR32(&par
->dmaBase
[0x8 + SKIPS
], 0, 0x00048000);
223 NV_WR32(&par
->dmaBase
[0x9 + SKIPS
], 0, 0x80000014);
224 NV_WR32(&par
->dmaBase
[0xA + SKIPS
], 0, 0x0004A000);
225 NV_WR32(&par
->dmaBase
[0xB + SKIPS
], 0, 0x80000015);
226 NV_WR32(&par
->dmaBase
[0xC + SKIPS
], 0, 0x0004C000);
227 NV_WR32(&par
->dmaBase
[0xD + SKIPS
], 0, 0x80000016);
228 NV_WR32(&par
->dmaBase
[0xE + SKIPS
], 0, 0x0004E000);
229 NV_WR32(&par
->dmaBase
[0xF + SKIPS
], 0, 0x80000017);
232 par
->dmaCurrent
= 16 + SKIPS
;
234 par
->dmaFree
= par
->dmaMax
- par
->dmaCurrent
;
236 switch (info
->var
.bits_per_pixel
) {
239 surfaceFormat
= SURFACE_FORMAT_DEPTH24
;
240 patternFormat
= PATTERN_FORMAT_DEPTH24
;
241 rectFormat
= RECT_FORMAT_DEPTH24
;
242 lineFormat
= LINE_FORMAT_DEPTH24
;
245 surfaceFormat
= SURFACE_FORMAT_DEPTH16
;
246 patternFormat
= PATTERN_FORMAT_DEPTH16
;
247 rectFormat
= RECT_FORMAT_DEPTH16
;
248 lineFormat
= LINE_FORMAT_DEPTH16
;
251 surfaceFormat
= SURFACE_FORMAT_DEPTH8
;
252 patternFormat
= PATTERN_FORMAT_DEPTH8
;
253 rectFormat
= RECT_FORMAT_DEPTH8
;
254 lineFormat
= LINE_FORMAT_DEPTH8
;
258 NVDmaStart(info
, par
, SURFACE_FORMAT
, 4);
259 NVDmaNext(par
, surfaceFormat
);
260 NVDmaNext(par
, pitch
| (pitch
<< 16));
264 NVDmaStart(info
, par
, PATTERN_FORMAT
, 1);
265 NVDmaNext(par
, patternFormat
);
267 NVDmaStart(info
, par
, RECT_FORMAT
, 1);
268 NVDmaNext(par
, rectFormat
);
270 NVDmaStart(info
, par
, LINE_FORMAT
, 1);
271 NVDmaNext(par
, lineFormat
);
273 par
->currentRop
= ~0; /* set to something invalid */
274 NVSetRopSolid(info
, ROP_COPY
, ~0);
276 NVSetClippingRectangle(info
, 0, 0, info
->var
.xres_virtual
,
277 info
->var
.yres_virtual
);
282 int nvidiafb_sync(struct fb_info
*info
)
284 struct nvidia_par
*par
= info
->par
;
286 if (info
->state
!= FBINFO_STATE_RUNNING
)
298 void nvidiafb_copyarea(struct fb_info
*info
, const struct fb_copyarea
*region
)
300 struct nvidia_par
*par
= info
->par
;
302 if (info
->state
!= FBINFO_STATE_RUNNING
)
306 cfb_copyarea(info
, region
);
310 NVDmaStart(info
, par
, BLIT_POINT_SRC
, 3);
311 NVDmaNext(par
, (region
->sy
<< 16) | region
->sx
);
312 NVDmaNext(par
, (region
->dy
<< 16) | region
->dx
);
313 NVDmaNext(par
, (region
->height
<< 16) | region
->width
);
318 void nvidiafb_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
320 struct nvidia_par
*par
= info
->par
;
323 if (info
->state
!= FBINFO_STATE_RUNNING
)
327 cfb_fillrect(info
, rect
);
331 if (info
->var
.bits_per_pixel
== 8)
334 color
= ((u32
*) info
->pseudo_palette
)[rect
->color
];
336 if (rect
->rop
!= ROP_COPY
)
337 NVSetRopSolid(info
, rect
->rop
, ~0);
339 NVDmaStart(info
, par
, RECT_SOLID_COLOR
, 1);
340 NVDmaNext(par
, color
);
342 NVDmaStart(info
, par
, RECT_SOLID_RECTS(0), 2);
343 NVDmaNext(par
, (rect
->dx
<< 16) | rect
->dy
);
344 NVDmaNext(par
, (rect
->width
<< 16) | rect
->height
);
348 if (rect
->rop
!= ROP_COPY
)
349 NVSetRopSolid(info
, ROP_COPY
, ~0);
352 static void nvidiafb_mono_color_expand(struct fb_info
*info
,
353 const struct fb_image
*image
)
355 struct nvidia_par
*par
= info
->par
;
356 u32 fg
, bg
, mask
= ~(~0 >> (32 - info
->var
.bits_per_pixel
));
357 u32 dsize
, width
, *data
= (u32
*) image
->data
, tmp
;
360 width
= (image
->width
+ 31) & ~31;
361 dsize
= (width
* image
->height
) >> 5;
363 if (info
->var
.bits_per_pixel
== 8) {
364 fg
= image
->fg_color
| mask
;
365 bg
= image
->bg_color
| mask
;
367 fg
= ((u32
*) info
->pseudo_palette
)[image
->fg_color
] | mask
;
368 bg
= ((u32
*) info
->pseudo_palette
)[image
->bg_color
] | mask
;
371 NVDmaStart(info
, par
, RECT_EXPAND_TWO_COLOR_CLIP
, 7);
372 NVDmaNext(par
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
373 NVDmaNext(par
, ((image
->dy
+ image
->height
) << 16) |
374 ((image
->dx
+ image
->width
) & 0xffff));
377 NVDmaNext(par
, (image
->height
<< 16) | width
);
378 NVDmaNext(par
, (image
->height
<< 16) | width
);
379 NVDmaNext(par
, (image
->dy
<< 16) | (image
->dx
& 0xffff));
381 while (dsize
>= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS
) {
382 NVDmaStart(info
, par
, RECT_EXPAND_TWO_COLOR_DATA(0),
383 RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS
);
385 for (j
= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS
; j
--;) {
391 dsize
-= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS
;
395 NVDmaStart(info
, par
, RECT_EXPAND_TWO_COLOR_DATA(0), dsize
);
397 for (j
= dsize
; j
--;) {
407 void nvidiafb_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
409 struct nvidia_par
*par
= info
->par
;
411 if (info
->state
!= FBINFO_STATE_RUNNING
)
414 if (image
->depth
== 1 && !par
->lockup
)
415 nvidiafb_mono_color_expand(info
, image
);
417 cfb_imageblit(info
, image
);