~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/video/S3triofb.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/drivers/video/S3Triofb.c -- Open Firmware based frame buffer device
  3  *
  4  *      Copyright (C) 1997 Peter De Schrijver
  5  *
  6  *  This driver is partly based on the PowerMac console driver:
  7  *
  8  *      Copyright (C) 1996 Paul Mackerras
  9  *
 10  *  and on the Open Firmware based frame buffer device:
 11  *
 12  *      Copyright (C) 1997 Geert Uytterhoeven
 13  *
 14  *  This file is subject to the terms and conditions of the GNU General Public
 15  *  License. See the file COPYING in the main directory of this archive for
 16  *  more details.
 17  */
 18 
 19 /*
 20         Bugs : + OF dependencies should be removed.
 21                + This driver should be merged with the CyberVision driver. The
 22                  CyberVision is a Zorro III implementation of the S3Trio64 chip.
 23 
 24 */
 25 
 26 #include <linux/config.h>
 27 #include <linux/kernel.h>
 28 #include <linux/module.h>
 29 #include <linux/errno.h>
 30 #include <linux/string.h>
 31 #include <linux/mm.h>
 32 #include <linux/tty.h>
 33 #include <linux/malloc.h>
 34 #include <linux/vmalloc.h>
 35 #include <linux/delay.h>
 36 #include <linux/interrupt.h>
 37 #include <linux/fb.h>
 38 #include <linux/init.h>
 39 #include <linux/selection.h>
 40 #include <asm/io.h>
 41 #include <asm/prom.h>
 42 #include <asm/pci-bridge.h>
 43 #include <linux/pci.h>
 44 #ifdef CONFIG_FB_COMPAT_XPMAC
 45 #include <asm/vc_ioctl.h>
 46 #endif
 47 
 48 #include <video/fbcon.h>
 49 #include <video/fbcon-cfb8.h>
 50 #include <video/s3blit.h>
 51 
 52 
 53 #define mem_in8(addr)           in_8((void *)(addr))
 54 #define mem_in16(addr)          in_le16((void *)(addr))
 55 #define mem_in32(addr)          in_le32((void *)(addr))
 56 
 57 #define mem_out8(val, addr)     out_8((void *)(addr), val)
 58 #define mem_out16(val, addr)    out_le16((void *)(addr), val)
 59 #define mem_out32(val, addr)    out_le32((void *)(addr), val)
 60 
 61 #define IO_OUT16VAL(v, r)       (((v) << 8) | (r))
 62 
 63 static int currcon = 0;
 64 static struct display disp;
 65 static struct fb_info fb_info;
 66 static struct { u_char red, green, blue, pad; } palette[256];
 67 static char s3trio_name[16] = "S3Trio ";
 68 static char *s3trio_base;
 69 
 70 static struct fb_fix_screeninfo fb_fix;
 71 static struct fb_var_screeninfo fb_var = { 0, };
 72 
 73 
 74     /*
 75      *  Interface used by the world
 76      */
 77 
 78 static void __init s3triofb_of_init(struct device_node *dp);
 79 static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con,
 80                           struct fb_info *info);
 81 static int s3trio_get_var(struct fb_var_screeninfo *var, int con,
 82                           struct fb_info *info);
 83 static int s3trio_set_var(struct fb_var_screeninfo *var, int con,
 84                           struct fb_info *info);
 85 static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 86                            struct fb_info *info);
 87 static int s3trio_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 88                            struct fb_info *info);
 89 static int s3trio_pan_display(struct fb_var_screeninfo *var, int con,
 90                               struct fb_info *info);
 91 
 92 
 93     /*
 94      *  Interface to the low level console driver
 95      */
 96 
 97 int s3triofb_init(void);
 98 static int s3triofbcon_switch(int con, struct fb_info *info);
 99 static int s3triofbcon_updatevar(int con, struct fb_info *info);
100 static void s3triofbcon_blank(int blank, struct fb_info *info);
101 #if 0
102 static int s3triofbcon_setcmap(struct fb_cmap *cmap, int con);
103 #endif
104 
105     /*
106      *  Text console acceleration
107      */
108 
109 #ifdef FBCON_HAS_CFB8
110 static struct display_switch fbcon_trio8;
111 #endif
112 
113     /*
114      *    Accelerated Functions used by the low level console driver
115      */
116 
117 static void Trio_WaitQueue(u_short fifo);
118 static void Trio_WaitBlit(void);
119 static void Trio_BitBLT(u_short curx, u_short cury, u_short destx,
120                         u_short desty, u_short width, u_short height,
121                         u_short mode);
122 static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height,
123                           u_short mode, u_short color);
124 static void Trio_MoveCursor(u_short x, u_short y);
125 
126 
127     /*
128      *  Internal routines
129      */
130 
131 static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
132                          u_int *transp, struct fb_info *info);
133 static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
134                          u_int transp, struct fb_info *info);
135 static void do_install_cmap(int con, struct fb_info *info);
136 
137 
138 static struct fb_ops s3trio_ops = {
139         owner:          THIS_MODULE,
140         fb_get_fix:     s3trio_get_fix,
141         fb_get_var:     s3trio_get_var,
142         fb_set_var:     s3trio_set_var,
143         fb_get_cmap:    s3trio_get_cmap,
144         fb_set_cmap:    s3trio_set_cmap,
145         fb_pan_display: s3trio_pan_display,
146 };
147 
148     /*
149      *  Get the Fixed Part of the Display
150      */
151 
152 static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con,
153                           struct fb_info *info)
154 {
155     memcpy(fix, &fb_fix, sizeof(fb_fix));
156     return 0;
157 }
158 
159 
160     /*
161      *  Get the User Defined Part of the Display
162      */
163 
164 static int s3trio_get_var(struct fb_var_screeninfo *var, int con,
165                           struct fb_info *info)
166 {
167     memcpy(var, &fb_var, sizeof(fb_var));
168     return 0;
169 }
170 
171 
172     /*
173      *  Set the User Defined Part of the Display
174      */
175 
176 static int s3trio_set_var(struct fb_var_screeninfo *var, int con,
177                           struct fb_info *info)
178 {
179     if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
180         var->bits_per_pixel > fb_var.bits_per_pixel )
181         /* || var->nonstd || var->vmode != FB_VMODE_NONINTERLACED) */
182         return -EINVAL;
183     if (var->xres_virtual > fb_var.xres_virtual) {
184         outw(IO_OUT16VAL((var->xres_virtual /8) & 0xff, 0x13), 0x3d4);
185         outw(IO_OUT16VAL(((var->xres_virtual /8 ) & 0x300) >> 3, 0x51), 0x3d4);
186         fb_var.xres_virtual = var->xres_virtual;
187         fb_fix.line_length = var->xres_virtual;
188     }
189     fb_var.yres_virtual = var->yres_virtual;
190     memcpy(var, &fb_var, sizeof(fb_var));
191     return 0;
192 }
193 
194 
195     /*
196      *  Pan or Wrap the Display
197      *
198      *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
199      */
200 
201 static int s3trio_pan_display(struct fb_var_screeninfo *var, int con,
202                               struct fb_info *info)
203 {
204     unsigned int base;
205 
206     if (var->xoffset > (var->xres_virtual - var->xres))
207         return -EINVAL;
208     if (var->yoffset > (var->yres_virtual - var->yres))
209         return -EINVAL;
210 
211     fb_var.xoffset = var->xoffset;
212     fb_var.yoffset = var->yoffset;
213 
214     base = var->yoffset * fb_fix.line_length + var->xoffset;
215 
216     outw(IO_OUT16VAL((base >> 8) & 0xff, 0x0c),0x03D4);
217     outw(IO_OUT16VAL(base  & 0xff, 0x0d),0x03D4);
218     outw(IO_OUT16VAL((base >> 16) & 0xf, 0x69),0x03D4);
219     return 0;
220 }
221 
222 
223     /*
224      *  Get the Colormap
225      */
226 
227 static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con,
228                            struct fb_info *info)
229 {
230     if (con == currcon) /* current console? */
231         return fb_get_cmap(cmap, kspc, s3trio_getcolreg, info);
232     else if (fb_display[con].cmap.len) /* non default colormap? */
233         fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
234     else
235         fb_copy_cmap(fb_default_cmap(1 << fb_display[con].var.bits_per_pixel),
236                      cmap, kspc ? 0 : 2);
237     return 0;
238 }
239 
240     /*
241      *  Set the Colormap
242      */
243 
244 static int s3trio_set_cmap(struct fb_cmap *cmap, int kspc, int con,
245                            struct fb_info *info)
246 {
247     int err;
248 
249 
250     if (!fb_display[con].cmap.len) {    /* no colormap allocated? */
251         if ((err = fb_alloc_cmap(&fb_display[con].cmap,
252                                  1<<fb_display[con].var.bits_per_pixel, 0)))
253             return err;
254     }
255     if (con == currcon)                 /* current console? */
256         return fb_set_cmap(cmap, kspc, s3trio_setcolreg, info);
257     else
258         fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
259     return 0;
260 }
261 
262 
263 int __init s3triofb_init(void)
264 {
265         struct device_node *dp;
266 
267         dp = find_devices("S3Trio");
268         if (dp != 0)
269             s3triofb_of_init(dp);
270         return 0;
271 }
272 
273 void __init s3trio_resetaccel(void){
274 
275 
276 #define EC01_ENH_ENB    0x0005
277 #define EC01_LAW_ENB    0x0010
278 #define EC01_MMIO_ENB   0x0020
279 
280 #define EC00_RESET      0x8000
281 #define EC00_ENABLE     0x4000
282 #define MF_MULT_MISC    0xE000
283 #define SRC_FOREGROUND  0x0020
284 #define SRC_BACKGROUND  0x0000
285 #define MIX_SRC                 0x0007
286 #define MF_T_CLIP       0x1000
287 #define MF_L_CLIP       0x2000
288 #define MF_B_CLIP       0x3000
289 #define MF_R_CLIP       0x4000
290 #define MF_PIX_CONTROL  0xA000
291 #define MFA_SRC_FOREGR_MIX      0x0000
292 #define MF_PIX_CONTROL  0xA000
293 
294         outw(EC00_RESET,  0x42e8);
295         inw(  0x42e8);
296         outw(EC00_ENABLE,  0x42e8);
297         inw(  0x42e8);
298         outw(EC01_ENH_ENB | EC01_LAW_ENB,
299                    0x4ae8);
300         outw(MF_MULT_MISC,  0xbee8); /* 16 bit I/O registers */
301 
302         /* Now set some basic accelerator registers */
303         Trio_WaitQueue(0x0400);
304         outw(SRC_FOREGROUND | MIX_SRC, 0xbae8);
305         outw(SRC_BACKGROUND | MIX_SRC,  0xb6e8);/* direct color*/
306         outw(MF_T_CLIP | 0, 0xbee8 );     /* clip virtual area  */
307         outw(MF_L_CLIP | 0, 0xbee8 );
308         outw(MF_R_CLIP | (640 - 1), 0xbee8);
309         outw(MF_B_CLIP | (480 - 1),  0xbee8);
310         Trio_WaitQueue(0x0400);
311         outw(0xffff,  0xaae8);       /* Enable all planes */
312         outw(0xffff, 0xaae8);       /* Enable all planes */
313         outw( MF_PIX_CONTROL | MFA_SRC_FOREGR_MIX,  0xbee8);
314 }
315 
316 int __init s3trio_init(struct device_node *dp){
317 
318     u_char bus, dev;
319     unsigned int t32;
320     unsigned short cmd;
321 
322         pci_device_loc(dp,&bus,&dev);
323                 pcibios_read_config_dword(bus, dev, PCI_VENDOR_ID, &t32);
324                 if(t32 == (PCI_DEVICE_ID_S3_TRIO << 16) + PCI_VENDOR_ID_S3) {
325                         pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32);
326                         pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_1, &t32);
327                         pcibios_read_config_word(bus, dev, PCI_COMMAND,&cmd);
328 
329                         pcibios_write_config_word(bus, dev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
330 
331                         pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_0,0xffffffff);
332                         pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32);
333 
334 /* This is a gross hack as OF only maps enough memory for the framebuffer and
335    we want to use MMIO too. We should find out which chunk of address space
336    we can use here */
337                         pcibios_write_config_dword(bus,dev,PCI_BASE_ADDRESS_0,0xc6000000);
338 
339                         /* unlock s3 */
340 
341                         outb(0x01, 0x3C3);
342 
343                         outb(inb(0x03CC) | 1, 0x3c2);
344 
345                         outw(IO_OUT16VAL(0x48, 0x38),0x03D4);
346                         outw(IO_OUT16VAL(0xA0, 0x39),0x03D4);
347                         outb(0x33,0x3d4);
348                         outw(IO_OUT16VAL((inb(0x3d5) & ~(0x2 | 0x10 |  0x40)) |
349                                           0x20, 0x33), 0x3d4);
350 
351                         outw(IO_OUT16VAL(0x6, 0x8), 0x3c4);
352 
353                         /* switch to MMIO only mode */
354 
355                         outb(0x58, 0x3d4);
356                         outw(IO_OUT16VAL(inb(0x3d5) | 3 | 0x10, 0x58), 0x3d4);
357                         outw(IO_OUT16VAL(8, 0x53), 0x3d4);
358 
359                         /* switch off I/O accesses */
360 
361 #if 0
362                         pcibios_write_config_word(bus, dev, PCI_COMMAND,
363                                         PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
364 #endif
365                         return 1;
366                 }
367 
368         return 0;
369 }
370 
371 
372     /*
373      *  Initialisation
374      *  We heavily rely on OF for the moment. This needs fixing.
375      */
376 
377 static void __init s3triofb_of_init(struct device_node *dp)
378 {
379     int i, *pp, len;
380     unsigned long address, size;
381     u_long *CursorBase;
382 
383     strncat(s3trio_name, dp->name, sizeof(s3trio_name));
384     s3trio_name[sizeof(s3trio_name)-1] = '\0';
385     strcpy(fb_fix.id, s3trio_name);
386 
387     if((pp = (int *)get_property(dp, "vendor-id", &len)) != NULL
388         && *pp!=PCI_VENDOR_ID_S3) {
389         printk("%s: can't find S3 Trio board\n", dp->full_name);
390         return;
391     }
392 
393     if((pp = (int *)get_property(dp, "device-id", &len)) != NULL
394         && *pp!=PCI_DEVICE_ID_S3_TRIO) {
395         printk("%s: can't find S3 Trio board\n", dp->full_name);
396         return;
397     }
398 
399     if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
400         && len == sizeof(int) && *pp != 8) {
401         printk("%s: can't use depth = %d\n", dp->full_name, *pp);
402         return;
403     }
404     if ((pp = (int *)get_property(dp, "width", &len)) != NULL
405         && len == sizeof(int))
406         fb_var.xres = fb_var.xres_virtual = *pp;
407     if ((pp = (int *)get_property(dp, "height", &len)) != NULL
408         && len == sizeof(int))
409         fb_var.yres = fb_var.yres_virtual = *pp;
410     if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
411         && len == sizeof(int))
412         fb_fix.line_length = *pp;
413     else
414         fb_fix.line_length = fb_var.xres_virtual;
415     fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
416 
417     address = 0xc6000000;
418     size = 64*1024*1024;
419     if (!request_mem_region(address, size, "S3triofb"))
420         return;
421 
422     s3trio_init(dp);
423     s3trio_base = ioremap(address, size);
424     fb_fix.smem_start = address;
425     fb_fix.type = FB_TYPE_PACKED_PIXELS;
426     fb_fix.type_aux = 0;
427     fb_fix.accel = FB_ACCEL_S3_TRIO64;
428     fb_fix.mmio_start = address+0x1000000;
429     fb_fix.mmio_len = 0x1000000;
430 
431     fb_fix.xpanstep = 1;
432     fb_fix.ypanstep = 1;
433 
434     s3trio_resetaccel();
435 
436     mem_out8(0x30, s3trio_base+0x1008000 + 0x03D4);
437     mem_out8(0x2d, s3trio_base+0x1008000 + 0x03D4);
438     mem_out8(0x2e, s3trio_base+0x1008000 + 0x03D4);
439 
440     mem_out8(0x50, s3trio_base+0x1008000 + 0x03D4);
441 
442     /* disable HW cursor */
443 
444     mem_out8(0x39, s3trio_base+0x1008000 + 0x03D4);
445     mem_out8(0xa0, s3trio_base+0x1008000 + 0x03D5);
446 
447     mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
448     mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
449 
450     mem_out8(0x4e, s3trio_base+0x1008000 + 0x03D4);
451     mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
452 
453     mem_out8(0x4f, s3trio_base+0x1008000 + 0x03D4);
454     mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
455 
456     /* init HW cursor */
457 
458     CursorBase = (u_long *)(s3trio_base + 2*1024*1024 - 0x400);
459         for (i = 0; i < 8; i++) {
460                 *(CursorBase  +(i*4)) = 0xffffff00;
461                 *(CursorBase+1+(i*4)) = 0xffff0000;
462                 *(CursorBase+2+(i*4)) = 0xffff0000;
463                 *(CursorBase+3+(i*4)) = 0xffff0000;
464         }
465         for (i = 8; i < 64; i++) {
466                 *(CursorBase  +(i*4)) = 0xffff0000;
467                 *(CursorBase+1+(i*4)) = 0xffff0000;
468                 *(CursorBase+2+(i*4)) = 0xffff0000;
469                 *(CursorBase+3+(i*4)) = 0xffff0000;
470         }
471 
472 
473     mem_out8(0x4c, s3trio_base+0x1008000 + 0x03D4);
474     mem_out8(((2*1024 - 1)&0xf00)>>8, s3trio_base+0x1008000 + 0x03D5);
475 
476     mem_out8(0x4d, s3trio_base+0x1008000 + 0x03D4);
477     mem_out8((2*1024 - 1) & 0xff, s3trio_base+0x1008000 + 0x03D5);
478 
479     mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
480     mem_in8(s3trio_base+0x1008000 + 0x03D4);
481 
482     mem_out8(0x4a, s3trio_base+0x1008000 + 0x03D4);
483     mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
484     mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
485     mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
486 
487     mem_out8(0x4b, s3trio_base+0x1008000 + 0x03D4);
488     mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
489     mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
490     mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
491 
492     mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
493     mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
494 
495     /* setup default color table */
496 
497         for(i = 0; i < 16; i++) {
498                 int j = color_table[i];
499                 palette[i].red=default_red[j];
500                 palette[i].green=default_grn[j];
501                 palette[i].blue=default_blu[j];
502         }
503 
504     s3trio_setcolreg(255, 56, 100, 160, 0, NULL /* not used */);
505     s3trio_setcolreg(254, 0, 0, 0, 0, NULL /* not used */);
506     memset((char *)s3trio_base, 0, 640*480);
507 
508 #if 0
509     Trio_RectFill(0, 0, 90, 90, 7, 1);
510 #endif
511 
512     fb_fix.visual = FB_VISUAL_PSEUDOCOLOR ;
513     fb_var.xoffset = fb_var.yoffset = 0;
514     fb_var.bits_per_pixel = 8;
515     fb_var.grayscale = 0;
516     fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0;
517     fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
518     fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
519     fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
520     fb_var.nonstd = 0;
521     fb_var.activate = 0;
522     fb_var.height = fb_var.width = -1;
523     fb_var.accel_flags = FB_ACCELF_TEXT;
524 #warning FIXME: always obey fb_var.accel_flags
525     fb_var.pixclock = 1;
526     fb_var.left_margin = fb_var.right_margin = 0;
527     fb_var.upper_margin = fb_var.lower_margin = 0;
528     fb_var.hsync_len = fb_var.vsync_len = 0;
529     fb_var.sync = 0;
530     fb_var.vmode = FB_VMODE_NONINTERLACED;
531 
532     disp.var = fb_var;
533     disp.cmap.start = 0;
534     disp.cmap.len = 0;
535     disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
536     disp.screen_base = s3trio_base;
537     disp.visual = fb_fix.visual;
538     disp.type = fb_fix.type;
539     disp.type_aux = fb_fix.type_aux;
540     disp.ypanstep = 0;
541     disp.ywrapstep = 0;
542     disp.line_length = fb_fix.line_length;
543     disp.can_soft_blank = 1;
544     disp.inverse = 0;
545 #ifdef FBCON_HAS_CFB8
546     if (fb_var.accel_flags & FB_ACCELF_TEXT)
547         disp.dispsw = &fbcon_trio8;
548     else
549         disp.dispsw = &fbcon_cfb8;
550 #else
551     disp.dispsw = &fbcon_dummy;
552 #endif
553     disp.scrollmode = fb_var.accel_flags & FB_ACCELF_TEXT ? 0 : SCROLL_YREDRAW;
554 
555     strcpy(fb_info.modename, "Trio64 ");
556     strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename));
557     fb_info.node = -1;
558     fb_info.fbops = &s3trio_ops;
559 #if 0
560     fb_info.fbvar_num = 1;
561     fb_info.fbvar = &fb_var;
562 #endif
563     fb_info.disp = &disp;
564     fb_info.fontname[0] = '\0';
565     fb_info.changevar = NULL;
566     fb_info.switch_con = &s3triofbcon_switch;
567     fb_info.updatevar = &s3triofbcon_updatevar;
568     fb_info.blank = &s3triofbcon_blank;
569 #if 0
570     fb_info.setcmap = &s3triofbcon_setcmap;
571 #endif
572 
573 #ifdef CONFIG_FB_COMPAT_XPMAC
574     if (!console_fb_info) {
575         display_info.height = fb_var.yres;
576         display_info.width = fb_var.xres;
577         display_info.depth = 8;
578         display_info.pitch = fb_fix.line_length;
579         display_info.mode = 0;
580         strncpy(display_info.name, dp->name, sizeof(display_info.name));
581         display_info.fb_address = (unsigned long)fb_fix.smem_start;
582         display_info.disp_reg_address = address + 0x1008000;
583         display_info.cmap_adr_address = address + 0x1008000 + 0x3c8;
584         display_info.cmap_data_address = address + 0x1008000 + 0x3c9;
585         console_fb_info = &fb_info;
586     }
587 #endif /* CONFIG_FB_COMPAT_XPMAC) */
588 
589     fb_info.flags = FBINFO_FLAG_DEFAULT;
590     if (register_framebuffer(&fb_info) < 0)
591         return;
592 
593     printk("fb%d: S3 Trio frame buffer device on %s\n",
594            GET_FB_IDX(fb_info.node), dp->full_name);
595 }
596 
597 
598 static int s3triofbcon_switch(int con, struct fb_info *info)
599 {
600     /* Do we have to save the colormap? */
601     if (fb_display[currcon].cmap.len)
602         fb_get_cmap(&fb_display[currcon].cmap, 1, s3trio_getcolreg, info);
603 
604     currcon = con;
605     /* Install new colormap */
606     do_install_cmap(con,info);
607     return 0;
608 }
609 
610     /*
611      *  Update the `var' structure (called by fbcon.c)
612      */
613 
614 static int s3triofbcon_updatevar(int con, struct fb_info *info)
615 {
616     /* Nothing */
617     return 0;
618 }
619 
620     /*
621      *  Blank the display.
622      */
623 
624 static void s3triofbcon_blank(int blank, struct fb_info *info)
625 {
626     unsigned char x;
627 
628     mem_out8(0x1, s3trio_base+0x1008000 + 0x03c4);
629     x = mem_in8(s3trio_base+0x1008000 + 0x03c5);
630     mem_out8((x & (~0x20)) | (blank << 5), s3trio_base+0x1008000 + 0x03c5);
631 }
632 
633     /*
634      *  Set the colormap
635      */
636 
637 #if 0
638 static int s3triofbcon_setcmap(struct fb_cmap *cmap, int con)
639 {
640     return(s3trio_set_cmap(cmap, 1, con, &fb_info));
641 }
642 #endif
643 
644 
645     /*
646      *  Read a single color register and split it into
647      *  colors/transparent. Return != 0 for invalid regno.
648      */
649 
650 static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
651                          u_int *transp, struct fb_info *info)
652 {
653     if (regno > 255)
654         return 1;
655     *red = (palette[regno].red << 8) | palette[regno].red;
656     *green = (palette[regno].green << 8) | palette[regno].green;
657     *blue = (palette[regno].blue << 8) | palette[regno].blue;
658     *transp = 0;
659     return 0;
660 }
661 
662 
663     /*
664      *  Set a single color register. Return != 0 for invalid regno.
665      */
666 
667 static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
668                             u_int transp, struct fb_info *info)
669 {
670     if (regno > 255)
671         return 1;
672 
673     red >>= 8;
674     green >>= 8;
675     blue >>= 8;
676     palette[regno].red = red;
677     palette[regno].green = green;
678     palette[regno].blue = blue;
679 
680     mem_out8(regno,s3trio_base+0x1008000 + 0x3c8);
681     mem_out8((red & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
682     mem_out8((green & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
683     mem_out8((blue & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
684 
685     return 0;
686 }
687 
688 
689 static void do_install_cmap(int con, struct fb_info *info)
690 {
691     if (con != currcon)
692         return;
693     if (fb_display[con].cmap.len)
694         fb_set_cmap(&fb_display[con].cmap, 1, s3trio_setcolreg, &fb_info);
695     else
696         fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), 1,
697                     s3trio_setcolreg, &fb_info);
698 }
699 
700 static void Trio_WaitQueue(u_short fifo) {
701 
702         u_short status;
703 
704         do
705         {
706                 status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8);
707         }  while (!(status & fifo));
708 
709 }
710 
711 static void Trio_WaitBlit(void) {
712 
713         u_short status;
714 
715         do
716         {
717                 status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8);
718         }  while (status & 0x200);
719 
720 }
721 
722 static void Trio_BitBLT(u_short curx, u_short cury, u_short destx,
723                         u_short desty, u_short width, u_short height,
724                         u_short mode) {
725 
726         u_short blitcmd = 0xc011;
727 
728         /* Set drawing direction */
729         /* -Y, X maj, -X (default) */
730 
731         if (curx > destx)
732                 blitcmd |= 0x0020;  /* Drawing direction +X */
733         else {
734                 curx  += (width - 1);
735                 destx += (width - 1);
736         }
737 
738         if (cury > desty)
739                 blitcmd |= 0x0080;  /* Drawing direction +Y */
740         else {
741                 cury  += (height - 1);
742                 desty += (height - 1);
743         }
744 
745         Trio_WaitQueue(0x0400);
746 
747         outw(0xa000,  0xBEE8);
748         outw(0x60 | mode,  0xBAE8);
749 
750         outw(curx,  0x86E8);
751         outw(cury,  0x82E8);
752 
753         outw(destx,  0x8EE8);
754         outw(desty,  0x8AE8);
755 
756         outw(height - 1,  0xBEE8);
757         outw(width - 1,  0x96E8);
758 
759         outw(blitcmd,  0x9AE8);
760 
761 }
762 
763 static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height,
764                           u_short mode, u_short color) {
765 
766         u_short blitcmd = 0x40b1;
767 
768         Trio_WaitQueue(0x0400);
769 
770         outw(0xa000,  0xBEE8);
771         outw((0x20 | mode),  0xBAE8);
772         outw(0xe000,  0xBEE8);
773         outw(color,  0xA6E8);
774         outw(x,  0x86E8);
775         outw(y,  0x82E8);
776         outw((height - 1), 0xBEE8);
777         outw((width - 1), 0x96E8);
778         outw(blitcmd,  0x9AE8);
779 
780 }
781 
782 
783 static void Trio_MoveCursor(u_short x, u_short y) {
784 
785         mem_out8(0x39, s3trio_base + 0x1008000 + 0x3d4);
786         mem_out8(0xa0, s3trio_base + 0x1008000 + 0x3d5);
787 
788         mem_out8(0x46, s3trio_base + 0x1008000 + 0x3d4);
789         mem_out8((x & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5);
790         mem_out8(0x47, s3trio_base + 0x1008000 + 0x3d4);
791         mem_out8(x & 0x00ff, s3trio_base + 0x1008000 + 0x3d5);
792 
793         mem_out8(0x48, s3trio_base + 0x1008000 + 0x3d4);
794         mem_out8((y & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5);
795         mem_out8(0x49, s3trio_base + 0x1008000 + 0x3d4);
796         mem_out8(y & 0x00ff, s3trio_base + 0x1008000 + 0x3d5);
797 
798 }
799 
800 
801     /*
802      *  Text console acceleration
803      */
804 
805 #ifdef FBCON_HAS_CFB8
806 static void fbcon_trio8_bmove(struct display *p, int sy, int sx, int dy,
807                               int dx, int height, int width)
808 {
809     sx *= 8; dx *= 8; width *= 8;
810     Trio_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
811                  (u_short)(dy*fontheight(p)), (u_short)width,
812                  (u_short)(height*fontheight(p)), (u_short)S3_NEW);
813 }
814 
815 static void fbcon_trio8_clear(struct vc_data *conp, struct display *p, int sy,
816                               int sx, int height, int width)
817 {
818     unsigned char bg;
819 
820     sx *= 8; width *= 8;
821     bg = attr_bgcol_ec(p,conp);
822     Trio_RectFill((u_short)sx,
823                    (u_short)(sy*fontheight(p)),
824                    (u_short)width,
825                    (u_short)(height*fontheight(p)),
826                    (u_short)S3_NEW,
827                    (u_short)bg);
828 }
829 
830 static void fbcon_trio8_putc(struct vc_data *conp, struct display *p, int c,
831                              int yy, int xx)
832 {
833     Trio_WaitBlit();
834     fbcon_cfb8_putc(conp, p, c, yy, xx);
835 }
836 
837 static void fbcon_trio8_putcs(struct vc_data *conp, struct display *p,
838                               const unsigned short *s, int count, int yy, int xx)
839 {
840     Trio_WaitBlit();
841     fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
842 }
843 
844 static void fbcon_trio8_revc(struct display *p, int xx, int yy)
845 {
846     Trio_WaitBlit();
847     fbcon_cfb8_revc(p, xx, yy);
848 }
849 
850 static struct display_switch fbcon_trio8 = {
851    setup:               fbcon_cfb8_setup,
852    bmove:               fbcon_trio8_bmove,
853    clear:               fbcon_trio8_clear,
854    putc:                fbcon_trio8_putc,
855    putcs:               fbcon_trio8_putcs,
856    revc:                fbcon_trio8_revc,
857    clear_margins:       fbcon_cfb8_clear_margins,
858    fontwidthmask:       FONTWIDTH(8)
859 };
860 #endif
861 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.