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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [or32/] [console/] [crtfb.c] - Blame information for rev 798

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

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

powered by: WebSVN 2.1.0

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