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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [video/] [sgivwfb.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device
3
 *
4
 *      Copyright (C) 1999 Silicon Graphics, Inc.
5
 *      Jeffrey Newquist, newquist@engr.sgi.som
6
 *
7
 *  This file is subject to the terms and conditions of the GNU General Public
8
 *  License. See the file COPYING in the main directory of this archive for
9
 *  more details.
10
 */
11
 
12
#include <linux/module.h>
13
#include <linux/kernel.h>
14
#include <linux/mm.h>
15
#include <linux/errno.h>
16
#include <linux/delay.h>
17
#include <linux/fb.h>
18
#include <linux/init.h>
19
#include <linux/ioport.h>
20
#include <linux/platform_device.h>
21
 
22
#include <asm/io.h>
23
#include <asm/mtrr.h>
24
 
25
#include <setup_arch.h>
26
 
27
#define INCLUDE_TIMING_TABLE_DATA
28
#define DBE_REG_BASE par->regs
29
#include <video/sgivw.h>
30
 
31
struct sgivw_par {
32
        struct asregs *regs;
33
        u32 cmap_fifo;
34
        u_long timing_num;
35
};
36
 
37
#define FLATPANEL_SGI_1600SW    5
38
 
39
/*
40
 *  RAM we reserve for the frame buffer. This defines the maximum screen
41
 *  size
42
 *
43
 *  The default can be overridden if the driver is compiled as a module
44
 */
45
 
46
static int ypan = 0;
47
static int ywrap = 0;
48
 
49
static int flatpanel_id = -1;
50
 
51
static struct fb_fix_screeninfo sgivwfb_fix __initdata = {
52
        .id             = "SGI Vis WS FB",
53
        .type           = FB_TYPE_PACKED_PIXELS,
54
        .visual         = FB_VISUAL_PSEUDOCOLOR,
55
        .mmio_start     = DBE_REG_PHYS,
56
        .mmio_len       = DBE_REG_SIZE,
57
        .accel          = FB_ACCEL_NONE,
58
        .line_length    = 640,
59
};
60
 
61
static struct fb_var_screeninfo sgivwfb_var __initdata = {
62
        /* 640x480, 8 bpp */
63
        .xres           = 640,
64
        .yres           = 480,
65
        .xres_virtual   = 640,
66
        .yres_virtual   = 480,
67
        .bits_per_pixel = 8,
68
        .red            = { 0, 8, 0 },
69
        .green          = { 0, 8, 0 },
70
        .blue           = { 0, 8, 0 },
71
        .height         = -1,
72
        .width          = -1,
73
        .pixclock       = 20000,
74
        .left_margin    = 64,
75
        .right_margin   = 64,
76
        .upper_margin   = 32,
77
        .lower_margin   = 32,
78
        .hsync_len      = 64,
79
        .vsync_len      = 2,
80
        .vmode          = FB_VMODE_NONINTERLACED
81
};
82
 
83
static struct fb_var_screeninfo sgivwfb_var1600sw __initdata = {
84
        /* 1600x1024, 8 bpp */
85
        .xres           = 1600,
86
        .yres           = 1024,
87
        .xres_virtual   = 1600,
88
        .yres_virtual   = 1024,
89
        .bits_per_pixel = 8,
90
        .red            = { 0, 8, 0 },
91
        .green          = { 0, 8, 0 },
92
        .blue           = { 0, 8, 0 },
93
        .height         = -1,
94
        .width          = -1,
95
        .pixclock       = 9353,
96
        .left_margin    = 20,
97
        .right_margin   = 30,
98
        .upper_margin   = 37,
99
        .lower_margin   = 3,
100
        .hsync_len      = 20,
101
        .vsync_len      = 3,
102
        .vmode          = FB_VMODE_NONINTERLACED
103
};
104
 
105
/*
106
 *  Interface used by the world
107
 */
108
int sgivwfb_init(void);
109
 
110
static int sgivwfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
111
static int sgivwfb_set_par(struct fb_info *info);
112
static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
113
                             u_int blue, u_int transp,
114
                             struct fb_info *info);
115
static int sgivwfb_mmap(struct fb_info *info,
116
                        struct vm_area_struct *vma);
117
 
118
static struct fb_ops sgivwfb_ops = {
119
        .owner          = THIS_MODULE,
120
        .fb_check_var   = sgivwfb_check_var,
121
        .fb_set_par     = sgivwfb_set_par,
122
        .fb_setcolreg   = sgivwfb_setcolreg,
123
        .fb_fillrect    = cfb_fillrect,
124
        .fb_copyarea    = cfb_copyarea,
125
        .fb_imageblit   = cfb_imageblit,
126
        .fb_mmap        = sgivwfb_mmap,
127
};
128
 
129
/*
130
 *  Internal routines
131
 */
132
static unsigned long bytes_per_pixel(int bpp)
133
{
134
        switch (bpp) {
135
                case 8:
136
                        return 1;
137
                case 16:
138
                        return 2;
139
                case 32:
140
                        return 4;
141
                default:
142
                        printk(KERN_INFO "sgivwfb: unsupported bpp %d\n", bpp);
143
                        return 0;
144
        }
145
}
146
 
147
static unsigned long get_line_length(int xres_virtual, int bpp)
148
{
149
        return (xres_virtual * bytes_per_pixel(bpp));
150
}
151
 
152
/*
153
 * Function:    dbe_TurnOffDma
154
 * Parameters:  (None)
155
 * Description: This should turn off the monitor and dbe.  This is used
156
 *              when switching between the serial console and the graphics
157
 *              console.
158
 */
159
 
160
static void dbe_TurnOffDma(struct sgivw_par *par)
161
{
162
        unsigned int readVal;
163
        int i;
164
 
165
        // Check to see if things are already turned off:
166
        // 1) Check to see if dbe is not using the internal dotclock.
167
        // 2) Check to see if the xy counter in dbe is already off.
168
 
169
        DBE_GETREG(ctrlstat, readVal);
170
        if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2)
171
                return;
172
 
173
        DBE_GETREG(vt_xy, readVal);
174
        if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
175
                return;
176
 
177
        // Otherwise, turn off dbe
178
 
179
        DBE_GETREG(ovr_control, readVal);
180
        SET_DBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, readVal, 0);
181
        DBE_SETREG(ovr_control, readVal);
182
        udelay(1000);
183
        DBE_GETREG(frm_control, readVal);
184
        SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, readVal, 0);
185
        DBE_SETREG(frm_control, readVal);
186
        udelay(1000);
187
        DBE_GETREG(did_control, readVal);
188
        SET_DBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, readVal, 0);
189
        DBE_SETREG(did_control, readVal);
190
        udelay(1000);
191
 
192
        // XXX HACK:
193
        //
194
        //    This was necessary for GBE--we had to wait through two
195
        //    vertical retrace periods before the pixel DMA was
196
        //    turned off for sure.  I've left this in for now, in
197
        //    case dbe needs it.
198
 
199
        for (i = 0; i < 10000; i++) {
200
                DBE_GETREG(frm_inhwctrl, readVal);
201
                if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) ==
202
                    0)
203
                        udelay(10);
204
                else {
205
                        DBE_GETREG(ovr_inhwctrl, readVal);
206
                        if (GET_DBE_FIELD
207
                            (OVR_INHWCTRL, OVR_DMA_ENABLE, readVal) == 0)
208
                                udelay(10);
209
                        else {
210
                                DBE_GETREG(did_inhwctrl, readVal);
211
                                if (GET_DBE_FIELD
212
                                    (DID_INHWCTRL, DID_DMA_ENABLE,
213
                                     readVal) == 0)
214
                                        udelay(10);
215
                                else
216
                                        break;
217
                        }
218
                }
219
        }
220
}
221
 
222
/*
223
 *  Set the User Defined Part of the Display. Again if par use it to get
224
 *  real video mode.
225
 */
226
static int sgivwfb_check_var(struct fb_var_screeninfo *var,
227
                             struct fb_info *info)
228
{
229
        struct sgivw_par *par = (struct sgivw_par *)info->par;
230
        struct dbe_timing_info *timing;
231
        u_long line_length;
232
        u_long min_mode;
233
        int req_dot;
234
        int test_mode;
235
 
236
        /*
237
         *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
238
         *  as FB_VMODE_SMOOTH_XPAN is only used internally
239
         */
240
 
241
        if (var->vmode & FB_VMODE_CONUPDATE) {
242
                var->vmode |= FB_VMODE_YWRAP;
243
                var->xoffset = info->var.xoffset;
244
                var->yoffset = info->var.yoffset;
245
        }
246
 
247
        /* XXX FIXME - forcing var's */
248
        var->xoffset = 0;
249
        var->yoffset = 0;
250
 
251
        /* Limit bpp to 8, 16, and 32 */
252
        if (var->bits_per_pixel <= 8)
253
                var->bits_per_pixel = 8;
254
        else if (var->bits_per_pixel <= 16)
255
                var->bits_per_pixel = 16;
256
        else if (var->bits_per_pixel <= 32)
257
                var->bits_per_pixel = 32;
258
        else
259
                return -EINVAL;
260
 
261
        var->grayscale = 0;      /* No grayscale for now */
262
 
263
        /* determine valid resolution and timing */
264
        for (min_mode = 0; min_mode < DBE_VT_SIZE; min_mode++) {
265
                if (dbeVTimings[min_mode].width >= var->xres &&
266
                    dbeVTimings[min_mode].height >= var->yres)
267
                        break;
268
        }
269
 
270
        if (min_mode == DBE_VT_SIZE)
271
                return -EINVAL; /* Resolution to high */
272
 
273
        /* XXX FIXME - should try to pick best refresh rate */
274
        /* for now, pick closest dot-clock within 3MHz */
275
        req_dot = PICOS2KHZ(var->pixclock);
276
        printk(KERN_INFO "sgivwfb: requested pixclock=%d ps (%d KHz)\n",
277
               var->pixclock, req_dot);
278
        test_mode = min_mode;
279
        while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) {
280
                if (dbeVTimings[test_mode].cfreq + 3000 > req_dot)
281
                        break;
282
                test_mode++;
283
        }
284
        if (dbeVTimings[min_mode].width != dbeVTimings[test_mode].width)
285
                test_mode--;
286
        min_mode = test_mode;
287
        timing = &dbeVTimings[min_mode];
288
        printk(KERN_INFO "sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq);
289
 
290
        /* Adjust virtual resolution, if necessary */
291
        if (var->xres > var->xres_virtual || (!ywrap && !ypan))
292
                var->xres_virtual = var->xres;
293
        if (var->yres > var->yres_virtual || (!ywrap && !ypan))
294
                var->yres_virtual = var->yres;
295
 
296
        /*
297
         *  Memory limit
298
         */
299
        line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
300
        if (line_length * var->yres_virtual > sgivwfb_mem_size)
301
                return -ENOMEM; /* Virtual resolution to high */
302
 
303
        info->fix.line_length = line_length;
304
 
305
        switch (var->bits_per_pixel) {
306
        case 8:
307
                var->red.offset = 0;
308
                var->red.length = 8;
309
                var->green.offset = 0;
310
                var->green.length = 8;
311
                var->blue.offset = 0;
312
                var->blue.length = 8;
313
                var->transp.offset = 0;
314
                var->transp.length = 0;
315
                break;
316
        case 16:                /* RGBA 5551 */
317
                var->red.offset = 11;
318
                var->red.length = 5;
319
                var->green.offset = 6;
320
                var->green.length = 5;
321
                var->blue.offset = 1;
322
                var->blue.length = 5;
323
                var->transp.offset = 0;
324
                var->transp.length = 0;
325
                break;
326
        case 32:                /* RGB 8888 */
327
                var->red.offset = 0;
328
                var->red.length = 8;
329
                var->green.offset = 8;
330
                var->green.length = 8;
331
                var->blue.offset = 16;
332
                var->blue.length = 8;
333
                var->transp.offset = 24;
334
                var->transp.length = 8;
335
                break;
336
        }
337
        var->red.msb_right = 0;
338
        var->green.msb_right = 0;
339
        var->blue.msb_right = 0;
340
        var->transp.msb_right = 0;
341
 
342
        /* set video timing information */
343
        var->pixclock = KHZ2PICOS(timing->cfreq);
344
        var->left_margin = timing->htotal - timing->hsync_end;
345
        var->right_margin = timing->hsync_start - timing->width;
346
        var->upper_margin = timing->vtotal - timing->vsync_end;
347
        var->lower_margin = timing->vsync_start - timing->height;
348
        var->hsync_len = timing->hsync_end - timing->hsync_start;
349
        var->vsync_len = timing->vsync_end - timing->vsync_start;
350
 
351
        /* Ouch. This breaks the rules but timing_num is only important if you
352
        * change a video mode */
353
        par->timing_num = min_mode;
354
 
355
        printk(KERN_INFO "sgivwfb: new video mode xres=%d yres=%d bpp=%d\n",
356
                var->xres, var->yres, var->bits_per_pixel);
357
        printk(KERN_INFO "         vxres=%d vyres=%d\n", var->xres_virtual,
358
                var->yres_virtual);
359
        return 0;
360
}
361
 
362
/*
363
 *  Setup flatpanel related registers.
364
 */
365
static void sgivwfb_setup_flatpanel(struct sgivw_par *par, struct dbe_timing_info *currentTiming)
366
{
367
        int fp_wid, fp_hgt, fp_vbs, fp_vbe;
368
        u32 outputVal = 0;
369
 
370
        SET_DBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal,
371
                (currentTiming->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
372
        SET_DBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal,
373
                (currentTiming->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
374
        DBE_SETREG(vt_flags, outputVal);
375
 
376
        /* Turn on the flat panel */
377
        switch (flatpanel_id) {
378
                case FLATPANEL_SGI_1600SW:
379
                        fp_wid = 1600;
380
                        fp_hgt = 1024;
381
                        fp_vbs = 0;
382
                        fp_vbe = 1600;
383
                        currentTiming->pll_m = 4;
384
                        currentTiming->pll_n = 1;
385
                        currentTiming->pll_p = 0;
386
                        break;
387
                default:
388
                        fp_wid = fp_hgt = fp_vbs = fp_vbe = 0xfff;
389
        }
390
 
391
        outputVal = 0;
392
        SET_DBE_FIELD(FP_DE, FP_DE_ON, outputVal, fp_vbs);
393
        SET_DBE_FIELD(FP_DE, FP_DE_OFF, outputVal, fp_vbe);
394
        DBE_SETREG(fp_de, outputVal);
395
        outputVal = 0;
396
        SET_DBE_FIELD(FP_HDRV, FP_HDRV_OFF, outputVal, fp_wid);
397
        DBE_SETREG(fp_hdrv, outputVal);
398
        outputVal = 0;
399
        SET_DBE_FIELD(FP_VDRV, FP_VDRV_ON, outputVal, 1);
400
        SET_DBE_FIELD(FP_VDRV, FP_VDRV_OFF, outputVal, fp_hgt + 1);
401
        DBE_SETREG(fp_vdrv, outputVal);
402
}
403
 
404
/*
405
 *  Set the hardware according to 'par'.
406
 */
407
static int sgivwfb_set_par(struct fb_info *info)
408
{
409
        struct sgivw_par *par = info->par;
410
        int i, j, htmp, temp;
411
        u32 readVal, outputVal;
412
        int wholeTilesX, maxPixelsPerTileX;
413
        int frmWrite1, frmWrite2, frmWrite3b;
414
        struct dbe_timing_info *currentTiming; /* Current Video Timing */
415
        int xpmax, ypmax;       // Monitor resolution
416
        int bytesPerPixel;      // Bytes per pixel
417
 
418
        currentTiming = &dbeVTimings[par->timing_num];
419
        bytesPerPixel = bytes_per_pixel(info->var.bits_per_pixel);
420
        xpmax = currentTiming->width;
421
        ypmax = currentTiming->height;
422
 
423
        /* dbe_InitGraphicsBase(); */
424
        /* Turn on dotclock PLL */
425
        DBE_SETREG(ctrlstat, 0x20000000);
426
 
427
        dbe_TurnOffDma(par);
428
 
429
        /* dbe_CalculateScreenParams(); */
430
        maxPixelsPerTileX = 512 / bytesPerPixel;
431
        wholeTilesX = xpmax / maxPixelsPerTileX;
432
        if (wholeTilesX * maxPixelsPerTileX < xpmax)
433
                wholeTilesX++;
434
 
435
        printk(KERN_DEBUG "sgivwfb: pixPerTile=%d wholeTilesX=%d\n",
436
               maxPixelsPerTileX, wholeTilesX);
437
 
438
        /* dbe_InitGammaMap(); */
439
        udelay(10);
440
 
441
        for (i = 0; i < 256; i++) {
442
                DBE_ISETREG(gmap, i, (i << 24) | (i << 16) | (i << 8));
443
        }
444
 
445
        /* dbe_TurnOn(); */
446
        DBE_GETREG(vt_xy, readVal);
447
        if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1) {
448
                DBE_SETREG(vt_xy, 0x00000000);
449
                udelay(1);
450
        } else
451
                dbe_TurnOffDma(par);
452
 
453
        /* dbe_Initdbe(); */
454
        for (i = 0; i < 256; i++) {
455
                for (j = 0; j < 100; j++) {
456
                        DBE_GETREG(cm_fifo, readVal);
457
                        if (readVal != 0x00000000)
458
                                break;
459
                        else
460
                                udelay(10);
461
                }
462
 
463
                // DBE_ISETREG(cmap, i, 0x00000000);
464
                DBE_ISETREG(cmap, i, (i << 8) | (i << 16) | (i << 24));
465
        }
466
 
467
        /* dbe_InitFramebuffer(); */
468
        frmWrite1 = 0;
469
        SET_DBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, frmWrite1,
470
                      wholeTilesX);
471
        SET_DBE_FIELD(FRM_SIZE_TILE, FRM_RHS, frmWrite1, 0);
472
 
473
        switch (bytesPerPixel) {
474
        case 1:
475
                SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
476
                              DBE_FRM_DEPTH_8);
477
                break;
478
        case 2:
479
                SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
480
                              DBE_FRM_DEPTH_16);
481
                break;
482
        case 4:
483
                SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
484
                              DBE_FRM_DEPTH_32);
485
                break;
486
        }
487
 
488
        frmWrite2 = 0;
489
        SET_DBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, frmWrite2, ypmax);
490
 
491
        // Tell dbe about the framebuffer location and type
492
        // XXX What format is the FRM_TILE_PTR??  64K aligned address?
493
        frmWrite3b = 0;
494
        SET_DBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, frmWrite3b,
495
                      sgivwfb_mem_phys >> 9);
496
        SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, frmWrite3b, 1);
497
        SET_DBE_FIELD(FRM_CONTROL, FRM_LINEAR, frmWrite3b, 1);
498
 
499
        /* Initialize DIDs */
500
 
501
        outputVal = 0;
502
        switch (bytesPerPixel) {
503
        case 1:
504
                SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_I8);
505
                break;
506
        case 2:
507
                SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGBA5);
508
                break;
509
        case 4:
510
                SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGB8);
511
                break;
512
        }
513
        SET_DBE_FIELD(WID, BUF, outputVal, DBE_BMODE_BOTH);
514
 
515
        for (i = 0; i < 32; i++) {
516
                DBE_ISETREG(mode_regs, i, outputVal);
517
        }
518
 
519
        /* dbe_InitTiming(); */
520
        DBE_SETREG(vt_intr01, 0xffffffff);
521
        DBE_SETREG(vt_intr23, 0xffffffff);
522
 
523
        DBE_GETREG(dotclock, readVal);
524
        DBE_SETREG(dotclock, readVal & 0xffff);
525
 
526
        DBE_SETREG(vt_xymax, 0x00000000);
527
        outputVal = 0;
528
        SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_ON, outputVal,
529
                      currentTiming->vsync_start);
530
        SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_OFF, outputVal,
531
                      currentTiming->vsync_end);
532
        DBE_SETREG(vt_vsync, outputVal);
533
        outputVal = 0;
534
        SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_ON, outputVal,
535
                      currentTiming->hsync_start);
536
        SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_OFF, outputVal,
537
                      currentTiming->hsync_end);
538
        DBE_SETREG(vt_hsync, outputVal);
539
        outputVal = 0;
540
        SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_ON, outputVal,
541
                      currentTiming->vblank_start);
542
        SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_OFF, outputVal,
543
                      currentTiming->vblank_end);
544
        DBE_SETREG(vt_vblank, outputVal);
545
        outputVal = 0;
546
        SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_ON, outputVal,
547
                      currentTiming->hblank_start);
548
        SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_OFF, outputVal,
549
                      currentTiming->hblank_end - 3);
550
        DBE_SETREG(vt_hblank, outputVal);
551
        outputVal = 0;
552
        SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_ON, outputVal,
553
                      currentTiming->vblank_start);
554
        SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_OFF, outputVal,
555
                      currentTiming->vblank_end);
556
        DBE_SETREG(vt_vcmap, outputVal);
557
        outputVal = 0;
558
        SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_ON, outputVal,
559
                      currentTiming->hblank_start);
560
        SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_OFF, outputVal,
561
                      currentTiming->hblank_end - 3);
562
        DBE_SETREG(vt_hcmap, outputVal);
563
 
564
        if (flatpanel_id != -1)
565
                sgivwfb_setup_flatpanel(par, currentTiming);
566
 
567
        outputVal = 0;
568
        temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
569
        if (temp > 0)
570
                temp = -temp;
571
 
572
        SET_DBE_FIELD(DID_START_XY, DID_STARTY, outputVal, (u32) temp);
573
        if (currentTiming->hblank_end >= 20)
574
                SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
575
                              currentTiming->hblank_end - 20);
576
        else
577
                SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
578
                              currentTiming->htotal - (20 -
579
                                                       currentTiming->
580
                                                       hblank_end));
581
        DBE_SETREG(did_start_xy, outputVal);
582
 
583
        outputVal = 0;
584
        SET_DBE_FIELD(CRS_START_XY, CRS_STARTY, outputVal,
585
                      (u32) (temp + 1));
586
        if (currentTiming->hblank_end >= DBE_CRS_MAGIC)
587
                SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
588
                              currentTiming->hblank_end - DBE_CRS_MAGIC);
589
        else
590
                SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
591
                              currentTiming->htotal - (DBE_CRS_MAGIC -
592
                                                       currentTiming->
593
                                                       hblank_end));
594
        DBE_SETREG(crs_start_xy, outputVal);
595
 
596
        outputVal = 0;
597
        SET_DBE_FIELD(VC_START_XY, VC_STARTY, outputVal, (u32) temp);
598
        SET_DBE_FIELD(VC_START_XY, VC_STARTX, outputVal,
599
                      currentTiming->hblank_end - 4);
600
        DBE_SETREG(vc_start_xy, outputVal);
601
 
602
        DBE_SETREG(frm_size_tile, frmWrite1);
603
        DBE_SETREG(frm_size_pixel, frmWrite2);
604
 
605
        outputVal = 0;
606
        SET_DBE_FIELD(DOTCLK, M, outputVal, currentTiming->pll_m - 1);
607
        SET_DBE_FIELD(DOTCLK, N, outputVal, currentTiming->pll_n - 1);
608
        SET_DBE_FIELD(DOTCLK, P, outputVal, currentTiming->pll_p);
609
        SET_DBE_FIELD(DOTCLK, RUN, outputVal, 1);
610
        DBE_SETREG(dotclock, outputVal);
611
 
612
        udelay(11 * 1000);
613
 
614
        DBE_SETREG(vt_vpixen, 0xffffff);
615
        DBE_SETREG(vt_hpixen, 0xffffff);
616
 
617
        outputVal = 0;
618
        SET_DBE_FIELD(VT_XYMAX, VT_MAXX, outputVal, currentTiming->htotal);
619
        SET_DBE_FIELD(VT_XYMAX, VT_MAXY, outputVal, currentTiming->vtotal);
620
        DBE_SETREG(vt_xymax, outputVal);
621
 
622
        outputVal = frmWrite1;
623
        SET_DBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, outputVal, 1);
624
        DBE_SETREG(frm_size_tile, outputVal);
625
        DBE_SETREG(frm_size_tile, frmWrite1);
626
 
627
        outputVal = 0;
628
        SET_DBE_FIELD(OVR_WIDTH_TILE, OVR_FIFO_RESET, outputVal, 1);
629
        DBE_SETREG(ovr_width_tile, outputVal);
630
        DBE_SETREG(ovr_width_tile, 0);
631
 
632
        DBE_SETREG(frm_control, frmWrite3b);
633
        DBE_SETREG(did_control, 0);
634
 
635
        // Wait for dbe to take frame settings
636
        for (i = 0; i < 100000; i++) {
637
                DBE_GETREG(frm_inhwctrl, readVal);
638
                if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) !=
639
                    0)
640
                        break;
641
                else
642
                        udelay(1);
643
        }
644
 
645
        if (i == 100000)
646
                printk(KERN_INFO
647
                       "sgivwfb: timeout waiting for frame DMA enable.\n");
648
 
649
        outputVal = 0;
650
        htmp = currentTiming->hblank_end - 19;
651
        if (htmp < 0)
652
                htmp += currentTiming->htotal;  /* allow blank to wrap around */
653
        SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_ON, outputVal, htmp);
654
        SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_OFF, outputVal,
655
                      ((htmp + currentTiming->width -
656
                        2) % currentTiming->htotal));
657
        DBE_SETREG(vt_hpixen, outputVal);
658
 
659
        outputVal = 0;
660
        SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_OFF, outputVal,
661
                      currentTiming->vblank_start);
662
        SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_ON, outputVal,
663
                      currentTiming->vblank_end);
664
        DBE_SETREG(vt_vpixen, outputVal);
665
 
666
        // Turn off mouse cursor
667
        par->regs->crs_ctl = 0;
668
 
669
        // XXX What's this section for??
670
        DBE_GETREG(ctrlstat, readVal);
671
        readVal &= 0x02000000;
672
 
673
        if (readVal != 0) {
674
                DBE_SETREG(ctrlstat, 0x30000000);
675
        }
676
        return 0;
677
}
678
 
679
/*
680
 *  Set a single color register. The values supplied are already
681
 *  rounded down to the hardware's capabilities (according to the
682
 *  entries in the var structure). Return != 0 for invalid regno.
683
 */
684
 
685
static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
686
                             u_int blue, u_int transp,
687
                             struct fb_info *info)
688
{
689
        struct sgivw_par *par = (struct sgivw_par *) info->par;
690
 
691
        if (regno > 255)
692
                return 1;
693
        red >>= 8;
694
        green >>= 8;
695
        blue >>= 8;
696
 
697
        /* wait for the color map FIFO to have a free entry */
698
        while (par->cmap_fifo == 0)
699
                par->cmap_fifo = par->regs->cm_fifo;
700
 
701
        par->regs->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
702
        par->cmap_fifo--;       /* assume FIFO is filling up */
703
        return 0;
704
}
705
 
706
static int sgivwfb_mmap(struct fb_info *info,
707
                        struct vm_area_struct *vma)
708
{
709
        unsigned long size = vma->vm_end - vma->vm_start;
710
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
711
 
712
        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
713
                return -EINVAL;
714
        if (offset + size > sgivwfb_mem_size)
715
                return -EINVAL;
716
        offset += sgivwfb_mem_phys;
717
        pgprot_val(vma->vm_page_prot) =
718
            pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
719
        vma->vm_flags |= VM_IO;
720
        if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
721
                                                size, vma->vm_page_prot))
722
                return -EAGAIN;
723
        printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
724
               offset, vma->vm_start);
725
        return 0;
726
}
727
 
728
int __init sgivwfb_setup(char *options)
729
{
730
        char *this_opt;
731
 
732
        if (!options || !*options)
733
                return 0;
734
 
735
        while ((this_opt = strsep(&options, ",")) != NULL) {
736
                if (!strncmp(this_opt, "monitor:", 8)) {
737
                        if (!strncmp(this_opt + 8, "crt", 3))
738
                                flatpanel_id = -1;
739
                        else if (!strncmp(this_opt + 8, "1600sw", 6))
740
                                flatpanel_id = FLATPANEL_SGI_1600SW;
741
                }
742
        }
743
        return 0;
744
}
745
 
746
/*
747
 *  Initialisation
748
 */
749
static int __init sgivwfb_probe(struct platform_device *dev)
750
{
751
        struct sgivw_par *par;
752
        struct fb_info *info;
753
        char *monitor;
754
 
755
        info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 16, &dev->dev);
756
        if (!info)
757
                return -ENOMEM;
758
        par = info->par;
759
 
760
        if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
761
                printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
762
                framebuffer_release(info);
763
                return -EBUSY;
764
        }
765
 
766
        par->regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
767
        if (!par->regs) {
768
                printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
769
                goto fail_ioremap_regs;
770
        }
771
 
772
        mtrr_add(sgivwfb_mem_phys, sgivwfb_mem_size, MTRR_TYPE_WRCOMB, 1);
773
 
774
        sgivwfb_fix.smem_start = sgivwfb_mem_phys;
775
        sgivwfb_fix.smem_len = sgivwfb_mem_size;
776
        sgivwfb_fix.ywrapstep = ywrap;
777
        sgivwfb_fix.ypanstep = ypan;
778
 
779
        info->fix = sgivwfb_fix;
780
 
781
        switch (flatpanel_id) {
782
                case FLATPANEL_SGI_1600SW:
783
                        info->var = sgivwfb_var1600sw;
784
                        monitor = "SGI 1600SW flatpanel";
785
                        break;
786
                default:
787
                        info->var = sgivwfb_var;
788
                        monitor = "CRT";
789
        }
790
 
791
        printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
792
 
793
        info->fbops = &sgivwfb_ops;
794
        info->pseudo_palette = (void *) (par + 1);
795
        info->flags = FBINFO_DEFAULT;
796
 
797
        info->screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
798
        if (!info->screen_base) {
799
                printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
800
                goto fail_ioremap_fbmem;
801
        }
802
 
803
        if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
804
                goto fail_color_map;
805
 
806
        if (register_framebuffer(info) < 0) {
807
                printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
808
                goto fail_register_framebuffer;
809
        }
810
 
811
        platform_set_drvdata(dev, info);
812
 
813
        printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",
814
                info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
815
        return 0;
816
 
817
fail_register_framebuffer:
818
        fb_dealloc_cmap(&info->cmap);
819
fail_color_map:
820
        iounmap((char *) info->screen_base);
821
fail_ioremap_fbmem:
822
        iounmap(par->regs);
823
fail_ioremap_regs:
824
        release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
825
        framebuffer_release(info);
826
        return -ENXIO;
827
}
828
 
829
static int sgivwfb_remove(struct platform_device *dev)
830
{
831
        struct fb_info *info = platform_get_drvdata(dev);
832
 
833
        if (info) {
834
                struct sgivw_par *par = info->par;
835
 
836
                unregister_framebuffer(info);
837
                dbe_TurnOffDma(par);
838
                iounmap(par->regs);
839
                iounmap(info->screen_base);
840
                release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
841
        }
842
        return 0;
843
}
844
 
845
static struct platform_driver sgivwfb_driver = {
846
        .probe  = sgivwfb_probe,
847
        .remove = sgivwfb_remove,
848
        .driver = {
849
                .name   = "sgivwfb",
850
        },
851
};
852
 
853
static struct platform_device *sgivwfb_device;
854
 
855
int __init sgivwfb_init(void)
856
{
857
        int ret;
858
 
859
#ifndef MODULE
860
        char *option = NULL;
861
 
862
        if (fb_get_options("sgivwfb", &option))
863
                return -ENODEV;
864
        sgivwfb_setup(option);
865
#endif
866
        ret = platform_driver_register(&sgivwfb_driver);
867
        if (!ret) {
868
                sgivwfb_device = platform_device_alloc("sgivwfb", 0);
869
                if (sgivwfb_device) {
870
                        ret = platform_device_add(sgivwfb_device);
871
                } else
872
                        ret = -ENOMEM;
873
                if (ret) {
874
                        platform_driver_unregister(&sgivwfb_driver);
875
                        platform_device_put(sgivwfb_device);
876
                }
877
        }
878
        return ret;
879
}
880
 
881
module_init(sgivwfb_init);
882
 
883
#ifdef MODULE
884
MODULE_LICENSE("GPL");
885
 
886
static void __exit sgivwfb_exit(void)
887
{
888
        platform_device_unregister(sgivwfb_device);
889
        platform_driver_unregister(&sgivwfb_driver);
890
}
891
 
892
module_exit(sgivwfb_exit);
893
 
894
#endif                          /* MODULE */

powered by: WebSVN 2.1.0

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