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 1765

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

powered by: WebSVN 2.1.0

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