OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [amiga/] [cyberfb.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*
2
 * linux/arch/m68k/amiga/cyberfb.c -- Low level implementation of the
3
 *                                    Cybervision frame buffer device
4
 *
5
 *    Copyright (C) 1996 Martin Apel
6
 *                       Geert Uytterhoeven
7
 *
8
 *
9
 * This file is based on the Amiga frame buffer device (amifb.c):
10
 *
11
 *    Copyright (C) 1995 Geert Uytterhoeven
12
 *
13
 *
14
 * History:
15
 *   - 22 Dec 95: Original version by Martin Apel
16
 *   - 05 Jan 96: Geert: integration into the current source tree
17
 *
18
 *
19
 * This file is subject to the terms and conditions of the GNU General Public
20
 * License.  See the file COPYING in the main directory of this archive
21
 * for more details.
22
 */
23
 
24
 
25
#include <linux/kernel.h>
26
#include <linux/errno.h>
27
#include <linux/string.h>
28
#include <linux/mm.h>
29
#include <linux/tty.h>
30
#include <linux/malloc.h>
31
#include <linux/delay.h>
32
#include <asm/segment.h>
33
#include <asm/system.h>
34
#include <asm/irq.h>
35
#include <asm/bootinfo.h>
36
#include <asm/zorro.h>
37
#include <asm/pgtable.h>
38
#include <linux/fb.h>
39
#include "s3blit.h"
40
 
41
 
42
#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
43
 
44
struct Cyber_fb_par {
45
   int xres;
46
   int yres;
47
   int bpp;
48
};
49
 
50
static struct Cyber_fb_par current_par;
51
 
52
static int current_par_valid = 0;
53
static int currcon = 0;
54
 
55
static struct display disp[MAX_NR_CONSOLES];
56
static struct fb_info fb_info;
57
 
58
static int node;        /* node of the /dev/fb?current file */
59
 
60
 
61
   /*
62
    *    Switch for Chipset Independency
63
    */
64
 
65
static struct fb_hwswitch {
66
 
67
   /* Initialisation */
68
 
69
   int (*init)(void);
70
 
71
   /* Display Control */
72
 
73
   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct Cyber_fb_par *par);
74
   int (*decode_var)(struct fb_var_screeninfo *var, struct Cyber_fb_par *par);
75
   int (*encode_var)(struct fb_var_screeninfo *var, struct Cyber_fb_par *par);
76
   int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
77
                    u_int *transp);
78
   int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
79
                    u_int transp);
80
   void (*blank)(int blank);
81
} *fbhw;
82
 
83
 
84
   /*
85
    *    Frame Buffer Name
86
    */
87
 
88
static char Cyber_fb_name[16] = "Cybervision";
89
 
90
 
91
   /*
92
    *    Cybervision Graphics Board
93
    */
94
 
95
#define CYBER8_WIDTH 1152
96
#define CYBER8_HEIGHT 886
97
#define CYBER8_PIXCLOCK 12500    /* ++Geert: Just a guess */
98
 
99
#define CYBER16_WIDTH 800
100
#define CYBER16_HEIGHT 600
101
#define CYBER16_PIXCLOCK 25000   /* ++Geert: Just a guess */
102
 
103
 
104
static int CyberKey = 0;
105
static u_char Cyber_colour_table [256][4];
106
static unsigned long CyberMem;
107
static unsigned long CyberSize;
108
static volatile char *CyberRegs;
109
 
110
static long *memstart;
111
 
112
 
113
   /*
114
    *    Predefined Video Mode Names
115
    */
116
 
117
static char *Cyber_fb_modenames[] = {
118
 
119
   /*
120
    *    Autodetect (Default) Video Mode
121
    */
122
 
123
   "default",
124
 
125
   /*
126
    *    Predefined Video Modes
127
    */
128
 
129
   "cyber8",            /* Cybervision 8 bpp */
130
   "cyber16",           /* Cybervision 16 bpp */
131
 
132
   /*
133
    *    Dummy Video Modes
134
    */
135
 
136
   "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
137
   "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
138
   "dummy", "dummy", "dummy", "dummy",
139
 
140
   /*
141
    *    User Defined Video Modes
142
    *
143
    *    This doesn't work yet!!
144
    */
145
 
146
   "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"
147
};
148
 
149
 
150
   /*
151
    *    Predefined Video Mode Definitions
152
    */
153
 
154
static struct fb_var_screeninfo Cyber_fb_predefined[] = {
155
 
156
   /*
157
    *    Autodetect (Default) Video Mode
158
    */
159
 
160
   { 0, },
161
 
162
   /*
163
    *    Predefined Video Modes
164
    */
165
 
166
   {
167
      /* Cybervision 8 bpp */
168
      CYBER8_WIDTH, CYBER8_HEIGHT, CYBER8_WIDTH, CYBER8_HEIGHT, 0, 0, 8, 0,
169
      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
170
      0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2,
171
      FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
172
   }, {
173
      /* Cybervision 16 bpp */
174
      CYBER16_WIDTH, CYBER16_HEIGHT, CYBER16_WIDTH, CYBER16_HEIGHT, 0, 0, 16, 0,
175
      {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
176
      0, 0, -1, -1, FB_ACCEL_NONE, CYBER16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
177
      FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
178
   },
179
 
180
   /*
181
    *    Dummy Video Modes
182
    */
183
 
184
   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
185
   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
186
   { 0, }, { 0, },
187
 
188
   /*
189
    *    User Defined Video Modes
190
    */
191
 
192
   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
193
};
194
 
195
 
196
#define NUM_TOTAL_MODES    arraysize(Cyber_fb_predefined)
197
#define NUM_PREDEF_MODES   (3)
198
 
199
 
200
static int Cyberfb_inverse = 0;
201
static int Cyberfb_Cyber8 = 0;        /* Use Cybervision board */
202
static int Cyberfb_Cyber16 = 0;       /* Use Cybervision board */
203
static int Cyberfb_mode = 0;
204
 
205
 
206
   /*
207
    *    Some default modes
208
    */
209
 
210
#define CYBER8_DEFMODE     (1)
211
#define CYBER16_DEFMODE    (2)
212
 
213
 
214
   /*
215
    *    Interface used by the world
216
    */
217
 
218
int Cyber_probe(void);
219
void Cyber_video_setup(char *options, int *ints);
220
 
221
static int Cyber_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
222
static int Cyber_fb_get_var(struct fb_var_screeninfo *var, int con);
223
static int Cyber_fb_set_var(struct fb_var_screeninfo *var, int con);
224
static int Cyber_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
225
static int Cyber_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
226
static int Cyber_fb_pan_display(struct fb_var_screeninfo *var, int con);
227
static int Cyber_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
228
                          u_long arg, int con);
229
 
230
 
231
   /*
232
    *    Interface to the low level console driver
233
    */
234
 
235
struct fb_info *Cyber_fb_init(long *mem_start); /* Through amiga_fb_init() */
236
static int Cyberfb_switch(int con);
237
static int Cyberfb_updatevar(int con);
238
static void Cyberfb_blank(int blank);
239
 
240
 
241
   /*
242
    *    Accelerated Functions used by the low level console driver
243
    */
244
 
245
void Cyber_WaitQueue(u_short fifo);
246
void Cyber_WaitBlit(void);
247
void Cyber_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
248
                  u_short width, u_short height, u_short mode);
249
void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
250
                    u_short mode, u_short color);
251
void Cyber_MoveCursor(u_short x, u_short y);
252
 
253
 
254
   /*
255
    *   Hardware Specific Routines
256
    */
257
 
258
static int Cyber_init(void);
259
static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
260
                          struct Cyber_fb_par *par);
261
static int Cyber_decode_var(struct fb_var_screeninfo *var,
262
                          struct Cyber_fb_par *par);
263
static int Cyber_encode_var(struct fb_var_screeninfo *var,
264
                          struct Cyber_fb_par *par);
265
static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
266
                         u_int *transp);
267
static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
268
                         u_int transp);
269
static void Cyber_blank(int blank);
270
 
271
 
272
   /*
273
    *    Internal routines
274
    */
275
 
276
static void Cyber_fb_get_par(struct Cyber_fb_par *par);
277
static void Cyber_fb_set_par(struct Cyber_fb_par *par);
278
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
279
static struct fb_cmap *get_default_colormap(int bpp);
280
static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
281
                          int kspc);
282
static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
283
                          int kspc);
284
static void do_install_cmap(int con);
285
static void memcpy_fs(int fsfromto, void *to, void *from, int len);
286
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
287
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
288
static void Cyber_fb_set_disp(int con);
289
static int get_video_mode(const char *name);
290
 
291
 
292
/* -------------------- Hardware specific routines -------------------------- */
293
 
294
 
295
   /*
296
    *    Initialization
297
    *
298
    *    Set the default video mode for this chipset. If a video mode was
299
    *    specified on the command line, it will override the default mode.
300
    */
301
 
302
static int Cyber_init(void)
303
{
304
int i;
305
char size;
306
volatile u_long *CursorBase;
307
unsigned long board_addr;
308
struct ConfigDev *cd;
309
 
310
if (Cyberfb_mode == -1)
311
  {
312
  if (Cyberfb_Cyber8)
313
    Cyberfb_mode = CYBER8_DEFMODE;
314
  else
315
    Cyberfb_mode = CYBER16_DEFMODE;
316
  }
317
 
318
cd = zorro_get_board (CyberKey);
319
zorro_config_board (CyberKey, 0);
320
board_addr = (unsigned long)cd->cd_BoardAddr;
321
 
322
for (i = 0; i < 256; i++)
323
 
324
for (i = 0; i < 256; i++)
325
  {
326
  Cyber_colour_table [i][0] = i;
327
  Cyber_colour_table [i][1] = i;
328
  Cyber_colour_table [i][2] = i;
329
  Cyber_colour_table [i][3] = 0;
330
  }
331
 
332
*memstart = (*memstart + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
333
CyberMem = kernel_map (board_addr + 0x01400000, 0x00400000,
334
                       KERNELMAP_NOCACHE_SER, memstart);
335
 
336
if (Cyberfb_Cyber8)
337
  memset ((char*)CyberMem, 0, CYBER8_WIDTH * CYBER8_HEIGHT);
338
else
339
  memset ((char*)CyberMem, 0, CYBER16_WIDTH * CYBER16_HEIGHT);
340
 
341
CyberRegs = (char*) kernel_map (board_addr + 0x02000000, 0xf000,
342
                                KERNELMAP_NOCACHE_SER, memstart);
343
 
344
/* Disable hardware cursor */
345
*(CyberRegs + S3_CRTC_ADR)  = S3_REG_LOCK2;
346
*(CyberRegs + S3_CRTC_DATA) = 0xa0;
347
*(CyberRegs + S3_CRTC_ADR)  = S3_HGC_MODE;
348
*(CyberRegs + S3_CRTC_DATA) = 0x00;
349
*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_DX;
350
*(CyberRegs + S3_CRTC_DATA) = 0x00;
351
*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_DY;
352
*(CyberRegs + S3_CRTC_DATA) = 0x00;
353
 
354
/* Set clipping rectangle to current screen size */
355
*((u_short volatile *)(CyberRegs + 0xbee8)) = 0x1000;
356
*((u_short volatile *)(CyberRegs + 0xbee8)) = 0x2000;
357
if (Cyberfb_Cyber8)
358
  {
359
  *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x3000 | (CYBER8_HEIGHT - 1);
360
  *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x4000 | (CYBER8_WIDTH - 1);
361
  }
362
else
363
  {
364
  *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x3000 | (CYBER16_HEIGHT - 1);
365
  *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x4000 | (CYBER16_WIDTH - 1);
366
  }
367
 
368
/* Get memory size (if not 2MB it is 4MB) */
369
*(CyberRegs + S3_CRTC_ADR) = S3_LAW_CTL;
370
size = *(CyberRegs + S3_CRTC_DATA);
371
if ((size & 0x03) == 0x02)
372
  CyberSize = 0x00200000; /* 2 MB */
373
else
374
  CyberSize = 0x00400000; /* 4 MB */
375
 
376
/* Initialize hardware cursor */
377
CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
378
for (i=0; i < 8; i++)
379
  {
380
  *(CursorBase  +(i*4)) = 0xffffff00;
381
  *(CursorBase+1+(i*4)) = 0xffff0000;
382
  *(CursorBase+2+(i*4)) = 0xffff0000;
383
  *(CursorBase+3+(i*4)) = 0xffff0000;
384
  }
385
for (i=8; i < 64; i++)
386
  {
387
  *(CursorBase  +(i*4)) = 0xffff0000;
388
  *(CursorBase+1+(i*4)) = 0xffff0000;
389
  *(CursorBase+2+(i*4)) = 0xffff0000;
390
  *(CursorBase+3+(i*4)) = 0xffff0000;
391
  }
392
 
393
Cyber_setcolreg (255, 56, 100, 160, 0);
394
Cyber_setcolreg (254, 0, 0, 0, 0);
395
 
396
return (0);
397
}
398
 
399
 
400
   /*
401
    *    This function should fill in the `fix' structure based on the
402
    *    values in the `par' structure.
403
    */
404
 
405
static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
406
                          struct Cyber_fb_par *par)
407
{
408
   int i;
409
 
410
   strcpy(fix->id, Cyber_fb_name);
411
   fix->smem_start = CyberMem;
412
   fix->smem_len = CyberSize;
413
 
414
   fix->type = FB_TYPE_PACKED_PIXELS;
415
   fix->type_aux = 0;
416
   if (par->bpp == 8)
417
      fix->visual = FB_VISUAL_PSEUDOCOLOR;
418
   else
419
      fix->visual = FB_VISUAL_DIRECTCOLOR;
420
 
421
   fix->xpanstep = 0;
422
   fix->ypanstep = 0;
423
   fix->ywrapstep = 0;
424
 
425
   for (i = 0; i < arraysize(fix->reserved); i++)
426
      fix->reserved[i] = 0;
427
 
428
   return(0);
429
}
430
 
431
 
432
   /*
433
    *    Get the video params out of `var'. If a value doesn't fit, round
434
    *    it up, if it's too big, return -EINVAL.
435
    */
436
 
437
static int Cyber_decode_var(struct fb_var_screeninfo *var,
438
                          struct Cyber_fb_par *par)
439
{
440
   if (Cyberfb_Cyber8) {
441
      par->xres = CYBER8_WIDTH;
442
      par->yres = CYBER8_HEIGHT;
443
      par->bpp = 8;
444
   } else {
445
      par->xres = CYBER16_WIDTH;
446
      par->yres = CYBER16_HEIGHT;
447
      par->bpp = 16;
448
   }
449
   return(0);
450
}
451
 
452
 
453
   /*
454
    *    Fill the `var' structure based on the values in `par' and maybe
455
    *    other values read out of the hardware.
456
    */
457
 
458
static int Cyber_encode_var(struct fb_var_screeninfo *var,
459
                          struct Cyber_fb_par *par)
460
{
461
   int i;
462
 
463
   var->xres = par->xres;
464
   var->yres = par->yres;
465
   var->xres_virtual = par->xres;
466
   var->yres_virtual = par->yres;
467
   var->xoffset = 0;
468
   var->yoffset = 0;
469
 
470
   var->bits_per_pixel = par->bpp;
471
   var->grayscale = 0;
472
 
473
   if (par->bpp == 8) {
474
      var->red.offset = 0;
475
      var->red.length = 8;
476
      var->red.msb_right = 0;
477
      var->blue = var->green = var->red;
478
   } else {
479
      var->red.offset = 11;
480
      var->red.length = 5;
481
      var->red.msb_right = 0;
482
      var->green.offset = 5;
483
      var->green.length = 6;
484
      var->green.msb_right = 0;
485
      var->blue.offset = 0;
486
      var->blue.length = 5;
487
      var->blue.msb_right = 0;
488
   }
489
   var->transp.offset = 0;
490
   var->transp.length = 0;
491
   var->transp.msb_right = 0;
492
 
493
   var->nonstd = 0;
494
   var->activate = 0;
495
 
496
   var->height = -1;
497
   var->width = -1;
498
   var->accel = FB_ACCEL_CYBERVISION;
499
   var->vmode = FB_VMODE_NONINTERLACED;
500
 
501
   /* Dummy values */
502
 
503
   if (par->bpp == 8)
504
      var->pixclock = CYBER8_PIXCLOCK;
505
   else
506
      var->pixclock = CYBER16_PIXCLOCK;
507
   var->sync = 0;
508
   var->left_margin = 64;
509
   var->right_margin = 96;
510
   var->upper_margin = 35;
511
   var->lower_margin = 12;
512
   var->hsync_len = 112;
513
   var->vsync_len = 2;
514
 
515
   for (i = 0; i < arraysize(var->reserved); i++)
516
      var->reserved[i] = 0;
517
 
518
   return(0);
519
}
520
 
521
 
522
   /*
523
    *    Set a single color register. The values supplied are already
524
    *    rounded down to the hardware's capabilities (according to the
525
    *    entries in the var structure). Return != 0 for invalid regno.
526
    */
527
 
528
static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
529
                         u_int transp)
530
{
531
if (regno > 255)
532
  return (1);
533
 
534
*(CyberRegs + 0x3c8) = (char)regno;
535
Cyber_colour_table [regno][0] = red & 0xff;
536
Cyber_colour_table [regno][1] = green & 0xff;
537
Cyber_colour_table [regno][2] = blue & 0xff;
538
Cyber_colour_table [regno][3] = transp;
539
 
540
*(CyberRegs + 0x3c9) = (red & 0xff) >> 2;
541
*(CyberRegs + 0x3c9) = (green & 0xff) >> 2;
542
*(CyberRegs + 0x3c9) = (blue & 0xff) >> 2;
543
 
544
return (0);
545
}
546
 
547
 
548
   /*
549
    *    Read a single color register and split it into
550
    *    colors/transparent. Return != 0 for invalid regno.
551
    */
552
 
553
static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
554
                         u_int *transp)
555
{
556
if (regno >= 256)
557
  return (1);
558
*red    = Cyber_colour_table [regno][0];
559
*green  = Cyber_colour_table [regno][1];
560
*blue   = Cyber_colour_table [regno][2];
561
*transp = Cyber_colour_table [regno][3];
562
return (0);
563
}
564
 
565
 
566
   /*
567
    *    (Un)Blank the screen
568
    */
569
 
570
void Cyber_blank(int blank)
571
{
572
int i;
573
 
574
if (blank)
575
  for (i = 0; i < 256; i++)
576
    {
577
    *(CyberRegs + 0x3c8) = i;
578
    *(CyberRegs + 0x3c9) = 0;
579
    *(CyberRegs + 0x3c9) = 0;
580
    *(CyberRegs + 0x3c9) = 0;
581
    }
582
else
583
  for (i = 0; i < 256; i++)
584
    {
585
    *(CyberRegs + 0x3c8) = i;
586
    *(CyberRegs + 0x3c9) = Cyber_colour_table [i][0] >> 2;
587
    *(CyberRegs + 0x3c9) = Cyber_colour_table [i][1] >> 2;
588
    *(CyberRegs + 0x3c9) = Cyber_colour_table [i][2] >> 2;
589
    }
590
}
591
 
592
 
593
/**************************************************************
594
 * We are waiting for "fifo" FIFO-slots empty
595
 */
596
void Cyber_WaitQueue (u_short fifo)
597
{
598
u_short status;
599
 
600
do
601
  {
602
  status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
603
  }
604
while (status & fifo);
605
}
606
 
607
/**************************************************************
608
 * We are waiting for Hardware (Graphics Engine) not busy
609
 */
610
void Cyber_WaitBlit (void)
611
{
612
u_short status;
613
 
614
do
615
  {
616
  status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
617
  }
618
while (status & S3_HDW_BUSY);
619
}
620
 
621
/**************************************************************
622
 * BitBLT - Through the Plane
623
 */
624
void Cyber_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty,
625
                   u_short width, u_short height, u_short mode)
626
{
627
u_short blitcmd = S3_BITBLT;
628
 
629
/* Set drawing direction */
630
/* -Y, X maj, -X (default) */
631
if (curx > destx)
632
  blitcmd |= 0x0020;  /* Drawing direction +X */
633
else
634
  {
635
  curx  += (width - 1);
636
  destx += (width - 1);
637
  }
638
 
639
if (cury > desty)
640
  blitcmd |= 0x0080;  /* Drawing direction +Y */
641
else
642
  {
643
  cury  += (height - 1);
644
  desty += (height - 1);
645
  }
646
 
647
Cyber_WaitQueue (0x8000);
648
 
649
*((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000;
650
*((u_short volatile *)(CyberRegs + S3_FRGD_MIX)) = (0x0060 | mode);
651
 
652
*((u_short volatile *)(CyberRegs + S3_CUR_X)) = curx;
653
*((u_short volatile *)(CyberRegs + S3_CUR_Y)) = cury;
654
 
655
*((u_short volatile *)(CyberRegs + S3_DESTX_DIASTP)) = destx;
656
*((u_short volatile *)(CyberRegs + S3_DESTY_AXSTP)) = desty;
657
 
658
*((u_short volatile *)(CyberRegs + S3_MIN_AXIS_PCNT)) = height - 1;
659
*((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width  - 1;
660
 
661
*((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd;
662
}
663
 
664
/**************************************************************
665
 * Rectangle Fill Solid
666
 */
667
void Cyber_RectFill (u_short x, u_short y, u_short width, u_short height,
668
                     u_short mode, u_short color)
669
{
670
u_short blitcmd = S3_FILLEDRECT;
671
 
672
Cyber_WaitQueue (0x8000);
673
 
674
*((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000;
675
*((u_short volatile *)(CyberRegs + S3_FRGD_MIX)) = (0x0020 | mode);
676
 
677
*((u_short volatile *)(CyberRegs + S3_MULT_MISC)) = 0xe000;
678
*((u_short volatile *)(CyberRegs + S3_FRGD_COLOR)) = color;
679
 
680
*((u_short volatile *)(CyberRegs + S3_CUR_X)) = x;
681
*((u_short volatile *)(CyberRegs + S3_CUR_Y)) = y;
682
 
683
*((u_short volatile *)(CyberRegs + S3_MIN_AXIS_PCNT)) = height - 1;
684
*((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width  - 1;
685
 
686
*((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd;
687
}
688
 
689
 
690
/**************************************************************
691
 * Move cursor to x, y
692
 */
693
void Cyber_MoveCursor (u_short x, u_short y)
694
{
695
*(CyberRegs + S3_CRTC_ADR)  = 0x39;
696
*(CyberRegs + S3_CRTC_DATA) = 0xa0;
697
 
698
*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
699
*(CyberRegs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
700
*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
701
*(CyberRegs + S3_CRTC_DATA) = (char)(x & 0x00ff);
702
 
703
*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
704
*(CyberRegs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
705
*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
706
*(CyberRegs + S3_CRTC_DATA) = (char)(y & 0x00ff);
707
}
708
 
709
 
710
/* -------------------- Interfaces to hardware functions -------------------- */
711
 
712
 
713
static struct fb_hwswitch Cyber_switch = {
714
   Cyber_init, Cyber_encode_fix, Cyber_decode_var, Cyber_encode_var,
715
   Cyber_getcolreg, Cyber_setcolreg, Cyber_blank
716
};
717
 
718
 
719
/* -------------------- Generic routines ------------------------------------ */
720
 
721
 
722
   /*
723
    *    Fill the hardware's `par' structure.
724
    */
725
 
726
static void Cyber_fb_get_par(struct Cyber_fb_par *par)
727
{
728
   if (current_par_valid)
729
      *par = current_par;
730
   else
731
      fbhw->decode_var(&Cyber_fb_predefined[Cyberfb_mode], par);
732
}
733
 
734
 
735
static void Cyber_fb_set_par(struct Cyber_fb_par *par)
736
{
737
   current_par = *par;
738
   current_par_valid = 1;
739
}
740
 
741
 
742
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
743
{
744
   int err, activate;
745
   struct Cyber_fb_par par;
746
 
747
   if ((err = fbhw->decode_var(var, &par)))
748
      return(err);
749
   activate = var->activate;
750
   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
751
      Cyber_fb_set_par(&par);
752
   fbhw->encode_var(var, &par);
753
   var->activate = activate;
754
   return(0);
755
}
756
 
757
 
758
   /*
759
    *    Default Colormaps
760
    */
761
 
762
static u_short red16[] =
763
   { 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000,
764
     0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff};
765
static u_short green16[] =
766
   { 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000,
767
     0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff};
768
static u_short blue16[] =
769
   { 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000,
770
     0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff};
771
 
772
 
773
static struct fb_cmap default_16_colors =
774
   { 0, 16, red16, green16, blue16, NULL };
775
 
776
 
777
static struct fb_cmap *get_default_colormap(int bpp)
778
{
779
   return(&default_16_colors);
780
}
781
 
782
 
783
#define CNVT_TOHW(val,width)     ((((val)<<(width))+0x7fff-(val))>>16)
784
#define CNVT_FROMHW(val,width)   (((width) ? ((((val)<<16)-(val)) / \
785
                                              ((1<<(width))-1)) : 0))
786
 
787
static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
788
                          int kspc)
789
{
790
   int i, start;
791
   u_short *red, *green, *blue, *transp;
792
   u_int hred, hgreen, hblue, htransp;
793
 
794
   red = cmap->red;
795
   green = cmap->green;
796
   blue = cmap->blue;
797
   transp = cmap->transp;
798
   start = cmap->start;
799
   if (start < 0)
800
      return(-EINVAL);
801
   for (i = 0; i < cmap->len; i++) {
802
      if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
803
         return(0);
804
      hred = CNVT_FROMHW(hred, var->red.length);
805
      hgreen = CNVT_FROMHW(hgreen, var->green.length);
806
      hblue = CNVT_FROMHW(hblue, var->blue.length);
807
      htransp = CNVT_FROMHW(htransp, var->transp.length);
808
      if (kspc) {
809
         *red = hred;
810
         *green = hgreen;
811
         *blue = hblue;
812
         if (transp)
813
            *transp = htransp;
814
      } else {
815
         put_fs_word(hred, red);
816
         put_fs_word(hgreen, green);
817
         put_fs_word(hblue, blue);
818
         if (transp)
819
            put_fs_word(htransp, transp);
820
      }
821
      red++;
822
      green++;
823
      blue++;
824
      if (transp)
825
         transp++;
826
   }
827
   return(0);
828
}
829
 
830
 
831
static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
832
                          int kspc)
833
{
834
   int i, start;
835
   u_short *red, *green, *blue, *transp;
836
   u_int hred, hgreen, hblue, htransp;
837
 
838
   red = cmap->red;
839
   green = cmap->green;
840
   blue = cmap->blue;
841
   transp = cmap->transp;
842
   start = cmap->start;
843
 
844
   if (start < 0)
845
      return(-EINVAL);
846
   for (i = 0; i < cmap->len; i++) {
847
      if (kspc) {
848
         hred = *red;
849
         hgreen = *green;
850
         hblue = *blue;
851
         htransp = transp ? *transp : 0;
852
      } else {
853
         hred = get_fs_word(red);
854
         hgreen = get_fs_word(green);
855
         hblue = get_fs_word(blue);
856
         htransp = transp ? get_fs_word(transp) : 0;
857
      }
858
      hred = CNVT_TOHW(hred, var->red.length);
859
      hgreen = CNVT_TOHW(hgreen, var->green.length);
860
      hblue = CNVT_TOHW(hblue, var->blue.length);
861
      htransp = CNVT_TOHW(htransp, var->transp.length);
862
      red++;
863
      green++;
864
      blue++;
865
      if (transp)
866
         transp++;
867
      if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
868
         return(0);
869
   }
870
   return(0);
871
}
872
 
873
 
874
static void do_install_cmap(int con)
875
{
876
   if (con != currcon)
877
      return;
878
   if (disp[con].cmap.len)
879
      do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
880
   else
881
      do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
882
                                          &disp[con].var, 1);
883
}
884
 
885
 
886
static void memcpy_fs(int fsfromto, void *to, void *from, int len)
887
{
888
   switch (fsfromto) {
889
      case 0:
890
         memcpy(to, from, len);
891
         return;
892
      case 1:
893
         memcpy_fromfs(to, from, len);
894
         return;
895
      case 2:
896
         memcpy_tofs(to, from, len);
897
         return;
898
   }
899
}
900
 
901
 
902
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
903
{
904
   int size;
905
   int tooff = 0, fromoff = 0;
906
 
907
   if (to->start > from->start)
908
      fromoff = to->start-from->start;
909
   else
910
      tooff = from->start-to->start;
911
   size = to->len-tooff;
912
   if (size > from->len-fromoff)
913
      size = from->len-fromoff;
914
   if (size < 0)
915
      return;
916
   size *= sizeof(u_short);
917
   memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
918
   memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
919
   memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
920
   if (from->transp && to->transp)
921
      memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
922
}
923
 
924
 
925
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
926
{
927
   int size = len*sizeof(u_short);
928
 
929
   if (cmap->len != len) {
930
      if (cmap->red)
931
         kfree(cmap->red);
932
      if (cmap->green)
933
         kfree(cmap->green);
934
      if (cmap->blue)
935
         kfree(cmap->blue);
936
      if (cmap->transp)
937
         kfree(cmap->transp);
938
      cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
939
      cmap->len = 0;
940
      if (!len)
941
         return(0);
942
      if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
943
         return(-1);
944
      if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
945
         return(-1);
946
      if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
947
         return(-1);
948
      if (transp) {
949
         if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
950
            return(-1);
951
      } else
952
         cmap->transp = NULL;
953
   }
954
   cmap->start = 0;
955
   cmap->len = len;
956
   copy_cmap(get_default_colormap(len), cmap, 0);
957
   return(0);
958
}
959
 
960
 
961
   /*
962
    *    Get the Fixed Part of the Display
963
    */
964
 
965
static int Cyber_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
966
{
967
   struct Cyber_fb_par par;
968
   int error = 0;
969
 
970
   if (con == -1)
971
      Cyber_fb_get_par(&par);
972
   else
973
      error = fbhw->decode_var(&disp[con].var, &par);
974
   return(error ? error : fbhw->encode_fix(fix, &par));
975
}
976
 
977
 
978
   /*
979
    *    Get the User Defined Part of the Display
980
    */
981
 
982
static int Cyber_fb_get_var(struct fb_var_screeninfo *var, int con)
983
{
984
   struct Cyber_fb_par par;
985
   int error = 0;
986
 
987
   if (con == -1) {
988
      Cyber_fb_get_par(&par);
989
      error = fbhw->encode_var(var, &par);
990
   } else
991
      *var = disp[con].var;
992
   return(error);
993
}
994
 
995
 
996
static void Cyber_fb_set_disp(int con)
997
{
998
   struct fb_fix_screeninfo fix;
999
 
1000
   Cyber_fb_get_fix(&fix, con);
1001
   if (con == -1)
1002
      con = 0;
1003
   disp[con].screen_base = (u_char *)fix.smem_start;
1004
   disp[con].visual = fix.visual;
1005
   disp[con].type = fix.type;
1006
   disp[con].type_aux = fix.type_aux;
1007
   disp[con].ypanstep = fix.ypanstep;
1008
   disp[con].ywrapstep = fix.ywrapstep;
1009
   disp[con].can_soft_blank = 1;
1010
   disp[con].inverse = Cyberfb_inverse;
1011
}
1012
 
1013
 
1014
   /*
1015
    *    Set the User Defined Part of the Display
1016
    */
1017
 
1018
static int Cyber_fb_set_var(struct fb_var_screeninfo *var, int con)
1019
{
1020
   int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
1021
 
1022
   if ((err = do_fb_set_var(var, con == currcon)))
1023
      return(err);
1024
   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
1025
      oldxres = disp[con].var.xres;
1026
      oldyres = disp[con].var.yres;
1027
      oldvxres = disp[con].var.xres_virtual;
1028
      oldvyres = disp[con].var.yres_virtual;
1029
      oldbpp = disp[con].var.bits_per_pixel;
1030
      disp[con].var = *var;
1031
      if (oldxres != var->xres || oldyres != var->yres ||
1032
          oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
1033
          oldbpp != var->bits_per_pixel) {
1034
         Cyber_fb_set_disp(con);
1035
         (*fb_info.changevar)(con);
1036
         alloc_cmap(&disp[con].cmap, 0, 0);
1037
         do_install_cmap(con);
1038
      }
1039
   }
1040
   var->activate = 0;
1041
   return(0);
1042
}
1043
 
1044
 
1045
   /*
1046
    *    Get the Colormap
1047
    */
1048
 
1049
static int Cyber_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
1050
{
1051
   if (con == currcon) /* current console? */
1052
      return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
1053
   else if (disp[con].cmap.len) /* non default colormap? */
1054
      copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
1055
   else
1056
      copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
1057
                kspc ? 0 : 2);
1058
   return(0);
1059
}
1060
 
1061
 
1062
   /*
1063
    *    Set the Colormap
1064
    */
1065
 
1066
static int Cyber_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
1067
{
1068
   int err;
1069
 
1070
   if (!disp[con].cmap.len) {       /* no colormap allocated? */
1071
      if ((err = alloc_cmap(&disp[con].cmap, 1<<disp[con].var.bits_per_pixel,
1072
                            0)))
1073
         return(err);
1074
   }
1075
   if (con == currcon)              /* current console? */
1076
      return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
1077
   else
1078
      copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
1079
   return(0);
1080
}
1081
 
1082
 
1083
   /*
1084
    *    Pan or Wrap the Display
1085
    *
1086
    *    This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1087
    */
1088
 
1089
static int Cyber_fb_pan_display(struct fb_var_screeninfo *var, int con)
1090
{
1091
   return(-EINVAL);
1092
}
1093
 
1094
 
1095
   /*
1096
    *    Cybervision Frame Buffer Specific ioctls
1097
    */
1098
 
1099
static int Cyber_fb_ioctl(struct inode *inode, struct file *file,
1100
                          u_int cmd, u_long arg, int con)
1101
{
1102
   return(-EINVAL);
1103
}
1104
 
1105
 
1106
static struct fb_ops Cyber_fb_ops = {
1107
   Cyber_fb_get_fix, Cyber_fb_get_var, Cyber_fb_set_var, Cyber_fb_get_cmap,
1108
   Cyber_fb_set_cmap, Cyber_fb_pan_display, Cyber_fb_ioctl
1109
};
1110
 
1111
 
1112
int Cyber_probe(void)
1113
{
1114
   CyberKey = zorro_find(MANUF_PHASE5, PROD_CYBERVISION, 0, 0);
1115
   return(CyberKey);
1116
}
1117
 
1118
 
1119
void Cyber_video_setup(char *options, int *ints)
1120
{
1121
   char *this_opt;
1122
   int i;
1123
 
1124
   fb_info.fontname[0] = '\0';
1125
 
1126
   if (!options || !*options)
1127
      return;
1128
 
1129
   for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
1130
      if (!strcmp(this_opt, "inverse")) {
1131
         Cyberfb_inverse = 1;
1132
         for (i = 0; i < 16; i++) {
1133
            red16[i] = ~red16[i];
1134
            green16[i] = ~green16[i];
1135
            blue16[i] = ~blue16[i];
1136
         }
1137
      } else if (!strncmp(this_opt, "font:", 5))
1138
         strcpy(fb_info.fontname, this_opt+5);
1139
      else if (!strcmp (this_opt, "cyber8"))
1140
         Cyberfb_Cyber8 = 1;
1141
      else if (!strcmp (this_opt, "cyber16"))
1142
         Cyberfb_Cyber16 = 1;
1143
      else
1144
         Cyberfb_mode = get_video_mode(this_opt);
1145
}
1146
 
1147
 
1148
   /*
1149
    *    Initialization
1150
    */
1151
 
1152
struct fb_info *Cyber_fb_init(long *mem_start)
1153
{
1154
   int err;
1155
   struct Cyber_fb_par par;
1156
 
1157
   memstart = mem_start;
1158
 
1159
   fbhw = &Cyber_switch;
1160
 
1161
   err = register_framebuffer(Cyber_fb_name, &node, &Cyber_fb_ops,
1162
                              NUM_TOTAL_MODES, Cyber_fb_predefined);
1163
   if (err < 0)
1164
      panic("Cannot register frame buffer\n");
1165
 
1166
   fbhw->init();
1167
   fbhw->decode_var(&Cyber_fb_predefined[Cyberfb_mode], &par);
1168
   fbhw->encode_var(&Cyber_fb_predefined[0], &par);
1169
 
1170
   strcpy(fb_info.modename, Cyber_fb_name);
1171
   fb_info.disp = disp;
1172
   fb_info.switch_con = &Cyberfb_switch;
1173
   fb_info.updatevar = &Cyberfb_updatevar;
1174
   fb_info.blank = &Cyberfb_blank;
1175
 
1176
   do_fb_set_var(&Cyber_fb_predefined[0], 1);
1177
   Cyber_fb_get_var(&disp[0].var, -1);
1178
   Cyber_fb_set_disp(-1);
1179
   do_install_cmap(0);
1180
   return(&fb_info);
1181
}
1182
 
1183
 
1184
static int Cyberfb_switch(int con)
1185
{
1186
   /* Do we have to save the colormap? */
1187
   if (disp[currcon].cmap.len)
1188
      do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
1189
 
1190
   do_fb_set_var(&disp[con].var, 1);
1191
   currcon = con;
1192
   /* Install new colormap */
1193
   do_install_cmap(con);
1194
   return(0);
1195
}
1196
 
1197
 
1198
   /*
1199
    *    Update the `var' structure (called by fbcon.c)
1200
    *
1201
    *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1202
    *    Since it's called by a kernel driver, no range checking is done.
1203
    */
1204
 
1205
static int Cyberfb_updatevar(int con)
1206
{
1207
   return(0);
1208
}
1209
 
1210
 
1211
   /*
1212
    *    Blank the display.
1213
    */
1214
 
1215
static void Cyberfb_blank(int blank)
1216
{
1217
   fbhw->blank(blank);
1218
}
1219
 
1220
 
1221
   /*
1222
    *    Get a Video Mode
1223
    */
1224
 
1225
static int get_video_mode(const char *name)
1226
{
1227
   int i;
1228
 
1229
   for (i = 1; i < NUM_PREDEF_MODES; i++)
1230
      if (!strcmp(name, Cyber_fb_modenames[i]))
1231
         return(i);
1232
   return(0);
1233
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.