2 * linux/drivers/video/accel.c - nVidia RIVA 128/TNT/TNT2 fb driver
4 * Copyright 2000 Jindrich Makovicka, Ani Joshi
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
13 /* acceleration routines */
15 inline void wait_for_idle(struct rivafb_info *rinfo)
17 while (rinfo->riva.Busy(&rinfo->riva));
20 /* set copy ROP, no mask */
21 static void riva_setup_ROP(struct rivafb_info *rinfo)
23 RIVA_FIFO_FREE(rinfo->riva, Patt, 5);
24 rinfo->riva.Patt->Shape = 0;
25 rinfo->riva.Patt->Color0 = 0xffffffff;
26 rinfo->riva.Patt->Color1 = 0xffffffff;
27 rinfo->riva.Patt->Monochrome[0] = 0xffffffff;
28 rinfo->riva.Patt->Monochrome[1] = 0xffffffff;
30 RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
31 rinfo->riva.Rop->Rop3 = 0xCC;
34 void riva_setup_accel(struct rivafb_info *rinfo)
36 RIVA_FIFO_FREE(rinfo->riva, Clip, 2);
37 rinfo->riva.Clip->TopLeft = 0x0;
38 rinfo->riva.Clip->WidthHeight = 0x80008000;
39 riva_setup_ROP(rinfo);
43 static void riva_rectfill(struct rivafb_info *rinfo, int sy,
44 int sx, int height, int width, u_int color)
46 RIVA_FIFO_FREE(rinfo->riva, Bitmap, 1);
47 rinfo->riva.Bitmap->Color1A = color;
49 RIVA_FIFO_FREE(rinfo->riva, Bitmap, 2);
50 rinfo->riva.Bitmap->UnclippedRectangle[0].TopLeft = (sx << 16) | sy;
51 rinfo->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (width << 16) | height;
54 static void fbcon_riva_bmove(struct display *p, int sy, int sx, int dy, int dx,
55 int height, int width)
57 struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
63 width *= fontwidth(p);
64 height *= fontheight(p);
66 RIVA_FIFO_FREE(rinfo->riva, Blt, 3);
67 rinfo->riva.Blt->TopLeftSrc = (sy << 16) | sx;
68 rinfo->riva.Blt->TopLeftDst = (dy << 16) | dx;
69 rinfo->riva.Blt->WidthHeight = (height << 16) | width;
74 static void riva_clear_margins(struct vc_data *conp, struct display *p,
75 int bottom_only, u32 bgx)
77 struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
79 unsigned int right_start = conp->vc_cols*fontwidth(p);
80 unsigned int bottom_start = conp->vc_rows*fontheight(p);
81 unsigned int right_width, bottom_width;
83 if (!bottom_only && (right_width = p->var.xres - right_start))
84 riva_rectfill(rinfo, 0, right_start, p->var.yres_virtual,
86 if ((bottom_width = p->var.yres - bottom_start))
87 riva_rectfill(rinfo, p->var.yoffset + bottom_start, 0,
88 bottom_width, right_start, bgx);
91 static u8 byte_rev[256] = {
92 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
93 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
94 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
95 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
96 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
97 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
98 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
99 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
100 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
101 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
102 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
103 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
104 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
105 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
106 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
107 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
110 static inline void fbcon_reverse_order(u32 *l)
113 *a = byte_rev[*a], a++;
114 /* *a = byte_rev[*a], a++;
115 *a = byte_rev[*a], a++;*/
119 static void fbcon_riva_writechr(struct vc_data *conp, struct display *p,
120 int c, int fgx, int bgx, int yy, int xx)
123 struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
133 cdat = p->fontdata + (c & p->charmask) * h;
135 cdat = p->fontdata + ((c & p->charmask) * h << 1);
137 RIVA_FIFO_FREE(rinfo->riva, Bitmap, 7);
138 rinfo->riva.Bitmap->ClipE.TopLeft = (yy << 16) | (xx & 0xFFFF);
139 rinfo->riva.Bitmap->ClipE.BottomRight = ((yy+h) << 16) | ((xx+w) & 0xffff);
140 rinfo->riva.Bitmap->Color0E = bgx;
141 rinfo->riva.Bitmap->Color1E = fgx;
142 rinfo->riva.Bitmap->WidthHeightInE = (h << 16) | 32;
143 rinfo->riva.Bitmap->WidthHeightOutE = (h << 16) | 32;
144 rinfo->riva.Bitmap->PointE = (yy << 16) | (xx & 0xFFFF);
146 d = &rinfo->riva.Bitmap->MonochromeData01E;
147 for (i = h; i > 0; i-=16) {
152 RIVA_FIFO_FREE(rinfo->riva, Bitmap, cnt);
153 for (j = 0; j < cnt; j++) {
157 cdat2 = *((u16*)cdat)++;
158 fbcon_reverse_order(&cdat2);
164 #ifdef FBCON_HAS_CFB8
165 void fbcon_riva8_setup(struct display *p)
167 p->next_line = p->line_length ? p->line_length : p->var.xres_virtual;
171 static void fbcon_riva8_clear(struct vc_data *conp, struct display *p, int sy,
172 int sx, int height, int width)
176 struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
178 bgx = attr_bgcol_ec(p, conp);
182 width *= fontwidth(p);
183 height *= fontheight(p);
185 riva_rectfill(rinfo, sy, sx, height, width, bgx);
188 static void fbcon_riva8_putc(struct vc_data *conp, struct display *p, int c,
193 fgx = attr_fgcol(p,c);
194 bgx = attr_bgcol(p,c);
199 fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
202 static void fbcon_riva8_putcs(struct vc_data *conp, struct display *p,
203 const unsigned short *s, int count, int yy,
213 fgx = attr_fgcol(p, c);
214 bgx = attr_bgcol(p, c);
217 fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
222 static void fbcon_riva8_revc(struct display *p, int xx, int yy)
224 struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
229 RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
230 rinfo->riva.Rop->Rop3 = 0x66; // XOR
231 riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0x0f);
232 RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
233 rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
236 static void fbcon_riva8_clear_margins(struct vc_data *conp, struct display *p,
239 riva_clear_margins(conp, p, bottom_only, attr_bgcol_ec(p, conp));
242 struct display_switch fbcon_riva8 = {
243 setup: fbcon_riva8_setup,
244 bmove: fbcon_riva_bmove,
245 clear: fbcon_riva8_clear,
246 putc: fbcon_riva8_putc,
247 putcs: fbcon_riva8_putcs,
248 revc: fbcon_riva8_revc,
249 clear_margins: fbcon_riva8_clear_margins,
250 fontwidthmask: FONTWIDTHRANGE(4, 16)
254 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
255 static void fbcon_riva1632_revc(struct display *p, int xx, int yy)
257 struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
262 RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
263 rinfo->riva.Rop->Rop3 = 0x66; // XOR
264 riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0xffffffff);
265 RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
266 rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
270 #ifdef FBCON_HAS_CFB16
271 void fbcon_riva16_setup(struct display *p)
273 p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
277 static void fbcon_riva16_clear(struct vc_data *conp, struct display *p, int sy,
278 int sx, int height, int width)
282 struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
284 bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
288 width *= fontwidth(p);
289 height *= fontheight(p);
291 riva_rectfill(rinfo, sy, sx, height, width, bgx);
294 static inline void convert_bgcolor_16(u32 *col)
296 *col = ((*col & 0x00007C00) << 9)
297 | ((*col & 0x000003E0) << 6)
298 | ((*col & 0x0000001F) << 3)
302 static void fbcon_riva16_putc(struct vc_data *conp, struct display *p, int c,
307 fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
308 bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
309 if (p->var.green.length == 6)
310 convert_bgcolor_16(&bgx);
314 fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
317 static void fbcon_riva16_putcs(struct vc_data *conp, struct display *p,
318 const unsigned short *s, int count, int yy,
328 fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
329 bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
330 if (p->var.green.length == 6)
331 convert_bgcolor_16(&bgx);
334 fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
339 static void fbcon_riva16_clear_margins(struct vc_data *conp, struct display *p,
342 riva_clear_margins(conp, p, bottom_only, ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
345 struct display_switch fbcon_riva16 = {
346 setup: fbcon_riva16_setup,
347 bmove: fbcon_riva_bmove,
348 clear: fbcon_riva16_clear,
349 putc: fbcon_riva16_putc,
350 putcs: fbcon_riva16_putcs,
351 revc: fbcon_riva1632_revc,
352 clear_margins: fbcon_riva16_clear_margins,
353 fontwidthmask: FONTWIDTHRANGE(4, 16)
357 #ifdef FBCON_HAS_CFB32
358 void fbcon_riva32_setup(struct display *p)
360 p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2;
364 static void fbcon_riva32_clear(struct vc_data *conp, struct display *p, int sy,
365 int sx, int height, int width)
369 struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
371 bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
375 width *= fontwidth(p);
376 height *= fontheight(p);
378 riva_rectfill(rinfo, sy, sx, height, width, bgx);
381 static void fbcon_riva32_putc(struct vc_data *conp, struct display *p, int c,
386 fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
387 bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
390 fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
393 static void fbcon_riva32_putcs(struct vc_data *conp, struct display *p,
394 const unsigned short *s, int count, int yy,
404 fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
405 bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
408 fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
413 static void fbcon_riva32_clear_margins(struct vc_data *conp, struct display *p,
416 riva_clear_margins(conp, p, bottom_only, ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
419 struct display_switch fbcon_riva32 = {
420 setup: fbcon_riva32_setup,
421 bmove: fbcon_riva_bmove,
422 clear: fbcon_riva32_clear,
423 putc: fbcon_riva32_putc,
424 putcs: fbcon_riva32_putcs,
425 revc: fbcon_riva1632_revc,
426 clear_margins: fbcon_riva32_clear_margins,
427 fontwidthmask: FONTWIDTHRANGE(4, 16)