Lynx framebuffers multidomain implementation.
[linux/elbrus.git] / drivers / video / mgam83 / mgam83fb_base.c
blobf7545135b31df9dd76010b94e253697460641671
1 /* MGA-M83 framebuffer driver
3 * make -C ../linux-2.6.14 SUBDIRS=$PWD modules
5 * Copyright (C) 2005-2006, Alexander Shmelev <ashmelev@task.sun.mcst.ru>
7 * To specify a video mode at bootup, use the following boot options:
8 * video=mgam83fb:<xres>x<yres>[-<bpp>][@refresh]
9 *
10 * Supported resolutions:
11 * 640x480, 800x600, 1024x768, 1280x1024, 1600x1200
12 * Supported depths:
13 * 8bpp, 16bpp, 24bpp, 32bpp
15 * Details about modes can be found in Linux/Documentation/fb/modedb.txt
17 * History:
18 * 1.0 PCI model support only
19 * 1.1 SBUS model support added
20 * 2.0 Linux-2.6 version
23 /* Debuging - mga debug, dma debug */
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
29 #include <linux/mm.h>
30 #include <linux/tty.h>
31 #include <linux/slab.h>
32 #include <linux/delay.h>
33 #include <linux/fb.h>
34 #include <linux/init.h>
35 #include <linux/proc_fs.h>
36 #include <linux/rmap.h>
37 #include <linux/dma-mapping.h>
38 #include <linux/interrupt.h>
39 #include <asm/mman.h>
40 #include <asm/uaccess.h>
41 #ifdef CONFIG_E90
42 #include <asm/e90.h>
43 #endif
44 #ifdef CONFIG_E90_FASTBOOT
45 #include <asm/bootinfo.h>
46 #endif
47 #include <linux/pci.h>
48 #include <asm/io.h>
49 #include "mgam83fb.h"
50 #ifdef CONFIG_FB_SOFT_CURSOR
51 extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
52 #endif
53 static char *mgam83fb_default_mode = "1024x768-8@60";
54 static int next_index = 0;
55 static bool use_irq = 0;
57 /*******************************************************************************
58 * Structures
59 *******************************************************************************
61 struct mgam83fb_par {
62 struct version vers;
63 int index; // MGAM index
65 struct {
66 #ifdef __sparc__
67 int iospace; // iospace
68 #endif
69 unsigned long base; // phys address
70 uint8_t* vbase; // virtual address
71 unsigned int len;
72 } mem;
73 struct {
74 unsigned long base; // phys address
75 uint8_t* vbase; // virtual address
76 unsigned int len;
77 } mmio;
78 struct {
79 unsigned long base; // phys address
80 uint8_t* vbase; // virtual address
81 unsigned int len;
82 } i2c;
84 struct {
85 void* kvaddr;
86 unsigned long ioaddr;
87 unsigned int size;
88 } video_buf;
90 struct pci_dev *pdev;
91 struct fb_info* info;
92 int dma_not_supported;
94 /* Current videomode **************************************************/
95 __u32 xres; // visible resolution
96 __u32 yres;
97 __u32 xres_virtual; // virtual resolution
98 __u32 yres_virtual;
99 __u32 xoffset; // offset from virtual to visible
100 __u32 yoffset; // resolution
102 __u32 bits_per_pixel; // Bits per pixel
104 __u32 pixclock; // pixel clock in ps (pico seconds)
105 __u32 left_margin; // time from sync to picture
106 __u32 right_margin; // time from picture to sync
107 __u32 upper_margin; // time from sync to picture
108 __u32 lower_margin;
109 __u32 hsync_len; // length of horizontal sync
110 __u32 vsync_len; // length of vertical sync
112 __u32 sync;
114 u32 pseudo_palette[16];
119 /*******************************************************************************
120 * Prototypes
121 *******************************************************************************
123 /* Framebuffer entry points */
124 static int mgam83fb_check_var(struct fb_var_screeninfo* var, struct fb_info* info);
125 static int mgam83fb_set_par(struct fb_info* info);
126 static int mgam83fb_setcolreg(unsigned regno, unsigned red, unsigned green,
127 unsigned blue, unsigned transp,
128 struct fb_info *info);
129 #if defined(__e2k__)
130 static int mgam83fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
131 #endif
132 void __proc_init( struct mgam83fb_par* p );
133 int mgafb_proc_write(struct file *file, const char *buffer, unsigned long count, void *data);
134 int mgafb_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data);
135 void __fb_fill ( struct mgam83fb_par* p );
136 void __dump_var( const struct fb_var_screeninfo* var );
137 void __dump_par( const struct mgam83fb_par* p );
138 void __dump_mmio( struct mgam83fb_par* p );
140 #undef MGAM_TRACE_FUNC
141 #ifdef MGAM_TRACE_FUNC
142 extern void mgam_trace_func(unsigned int i);
143 #define trace_func(x) mgam_trace_func(x)
144 #else
145 #define trace_func(x)
146 #endif
148 /* After the sync (FULL) bug is fixed must be removed (defined) */
149 #undef AFTER_FIXING_SYNC_BUG
151 /*******************************************************************************
152 * MMIO BitBlt Module Registers
153 *******************************************************************************
155 #define REG_BB_CTRL 0x1000 /* BitBlt module control register (write only)*/
156 #define REG_BB_STAT 0x1000 /* BitBlt module status register (read only) */
158 #define REG_BB_WINDOW 0x1004 /* Operation geometry */
159 #define REG_BB_SADDR 0x1008 /* Source start address */
160 #define REG_BB_DADDR 0x100c /* Destination start address */
161 #define REG_BB_PITCH 0x1010 /* */
162 #define REG_BB_BG 0x1014 /* Background color */
163 #define REG_BB_FG 0x1018 /* Foreground color */
165 /* BitBlt status register bits */
166 #define BB_STAT_PROCESS (0x1<<31) /* 1 - processing operation, 0 - idle */
167 #define BB_STAT_FULL (0x1<<30) /* 1 - pipeline full */
168 #define BB_STAT_DMA (0x1<<26) /* DMA support */
171 #define BB_CTRL_CMD_MASK 0xC0000000
172 #define BB_CTRL_CMD_START (0x1<<31)
173 #define BB_CTRL_CMD_ABORT (0x1<<30)
175 #define BB_CTRL_HALFWORD_TWISTER (0x1<<24)
176 #define BB_CTRL_BYTES_TWISTER (0x1<<23)
177 #define BB_CTRL_BITS_IN_BYTE_TWISTER (0x1<<22)
179 #define BB_CTRL_DDMA_EN (0x1<<21)
180 #define BB_CTRL_SDMA_EN (0x1<<20)
181 #define BB_CTRL_SOFFS_MASK (0x7<<16)
183 /* Binary raster operations */
184 #define BB_CTRL_ROP_MASK 0x0000F000
186 #define BB_CTRL_ROP_0 (0x0<<12) /* clear */
187 #define BB_CTRL_ROP_AND (0x1<<12) /* and */
188 #define BB_CTRL_ROP_NOT_SRC_AND_DST (0x2<<12) /* andReverse */
189 #define BB_CTRL_ROP_DST (0x3<<12) /* copy */
190 #define BB_CTRL_ROP_SRC_AND_NOT_DST (0x4<<12) /* andInverted */
191 #define BB_CTRL_ROP_SRC (0x5<<12) /* noop */
192 #define BB_CTRL_ROP_XOR (0x6<<12) /* xor */
193 #define BB_CTRL_ROP_OR (0x7<<12) /* or */
194 #define BB_CTRL_ROP_NOR (0x8<<12) /* nor */
195 #define BB_CTRL_ROP_NXOR (0x9<<12) /* equiv */
196 #define BB_CTRL_ROP_NOT_SRC (0xa<<12) /* invert */
197 #define BB_CTRL_ROP_NOT_SRC_OR_DST (0xb<<12) /* orReverse */
198 #define BB_CTRL_ROP_NOT_DST (0xc<<12) /* copyInverted */
199 #define BB_CTRL_ROP_SRC_OR_NOT_DST (0xd<<12) /* orInverted */
200 #define BB_CTRL_ROP_NAND (0xe<<12) /* nand */
201 #define BB_CTRL_ROP_1 (0xf<<12) /* set */
204 #define BB_CTRL_HDIR (0x1<<5)
205 #define BB_CTRL_VDIR (0x1<<6)
207 #define BB_CTRL_CE_EN (0x1<<0)
208 #define BB_CTRL_PAT_EN (0x1<<1)
209 #define BB_CTRL_SFILL_EN (0x1<<2)
210 #define BB_CTRL_TR_EN (0x1<<4)
212 #define BB_CTRL_SRC_MODE (0x1<<7)
214 #define BB_CTRL_TERM_00 (0x0<<8)
215 #define BB_CTRL_TERM_01 (0x1<<8)
216 #define BB_CTRL_TERM_10 (0x2<<8)
219 #define BB_CTRL_BPP_8 (0x0<<10)
220 #define BB_CTRL_BPP_16 (0x1<<10)
221 #define BB_CTRL_BPP_24 (0x2<<10)
222 #define BB_CTRL_BPP_32 (0x3<<10)
223 #ifdef __BIG_ENDIAN
224 #define BB_CTRL_BPP_CD_8 (BB_CTRL_BPP_8)
225 #define BB_CTRL_BPP_CD_16 (BB_CTRL_BPP_16 | 0x0800000)
226 #define BB_CTRL_BPP_CD_24 (BB_CTRL_BPP_24 | 0x1800000)
227 #define BB_CTRL_BPP_CD_32 (BB_CTRL_BPP_32 | 0x1800000)
228 #else /* __BIG_ENDIAN */
229 #define BB_CTRL_BPP_CD_8 BB_CTRL_BPP_8
230 #define BB_CTRL_BPP_CD_16 BB_CTRL_BPP_16
231 #define BB_CTRL_BPP_CD_24 BB_CTRL_BPP_24
232 #define BB_CTRL_BPP_CD_32 BB_CTRL_BPP_32
233 #endif /* __BIG_ENDIAN */
235 /*******************************************************************************
236 * MMIO Registers
237 *******************************************************************************
239 static void MMIO_WRITE( struct mgam83fb_par* p, unsigned long reg, uint32_t val )
241 TRACE_MSG( "MMIO[0x%03lx] <= 0x%08x\n", reg, val );
243 switch( p->vers.bus ) {
244 case BUS_TYPE_PCI :
245 writel( val, (void*)((unsigned long)p->mmio.vbase + reg) );
246 break;
247 default :
248 printk( KERN_WARNING "Cannot write to mmio: unsupported MGA/M video card model!\n" );
251 TRACE_MSG( "Sleeping 10 msecs...\n" );
254 static uint32_t MMIO_READ( struct mgam83fb_par* p, unsigned long reg )
256 uint32_t result;
258 switch( p->vers.bus ) {
259 case BUS_TYPE_PCI :
260 result = readl( (void*)((unsigned long) p->mmio.vbase + reg) );
261 break;
262 default :
263 result = ~(uint32_t)0;
264 printk( KERN_WARNING "Cannot write to mmio: unsupported MGA/M video card model!\n" );
266 TRACE_MSG( "MMIO[0x%03lx] => 0x%08x\n", reg, result );
267 return result;
270 /*******************************************************************************
271 * External entry points
272 *******************************************************************************
275 static struct { struct fb_bitfield transp, red, green, blue; } ver_05_2009_colors[] = {
276 { { 0, 0, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0} }, // 8bpp
277 { { 0, 0, 0}, { 11, 5, 0}, { 5, 6, 0}, { 0, 5, 0} }, // 16bpp
278 #ifdef __LITTLE_ENDIAN
279 { { 0, 0, 0}, { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0} }, // 24bpp
280 #else /* __BIG_ENDIAN */
281 { { 0, 0, 0}, { 0, 8, 0}, { 8, 8, 0}, { 16, 8, 0} }, // 24bpp
282 #endif
283 { { 24, 8, 0}, { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0} }, // 32bpp
286 static struct { struct fb_bitfield transp, red, green, blue; } ver_old_colors[] = {
287 #ifdef __LITTLE_ENDIAN
288 { { 0, 0, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0} }, // 8bpp
289 { { 0, 0, 0}, { 11, 5, 0}, { 5, 6, 0}, { 0, 5, 0} }, // 16bpp
290 { { 0, 0, 0}, { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0} }, // 24bpp
291 { { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0}, {24, 8, 0} }, // 32bpp
292 #else
293 { { 0, 0, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0} }, // 8bpp
294 { { 0, 0, 0}, { 11, 5, 0}, { 5, 6, 0}, { 0, 5, 0} }, // 16bpp
295 { { 0, 0, 0}, { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0} }, // 24bpp
296 { { 24, 8, 0}, { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0} }, // 32bpp
297 #endif /* __LITTLE_ENDIAN */
300 static struct { struct fb_bitfield transp, red, green, blue; } colors[4];
302 void set_up_colors_bounds(struct mgam83fb_par* p)
304 printk("entering set_up_colors bounds routine, revision = %d\n",
305 p->vers.revision);
306 if (p->vers.revision >= VER_05_2009
307 && p->vers.revision != MGA_MODEL_PMUP2_0
308 && p->vers.revision != MGA_MODEL_PMUP2_1) {
309 printk("using ver_05_2009_colors map\n");
310 memcpy(colors, ver_05_2009_colors, sizeof(colors));
311 } else {
312 printk("using ver_old_colors map\n");
313 memcpy(colors, ver_old_colors, sizeof(colors));
315 return;
318 static int mgam83fb_check_var(struct fb_var_screeninfo* var, struct fb_info* info)
320 struct mgam83fb_par* p = (struct mgam83fb_par*)info->par;
321 int colors_index = (var->bits_per_pixel>>3) - 1; // Index in colors table
323 DEBUG_MSG("mgam83fb: mgam83fb_check_var start\n");
324 if ( (var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED ) {
325 INFO_MSG( "mode %dx%dx%d rejected, interlaced not supported\n",
326 var->xres, var->yres, var->bits_per_pixel);
327 return -EINVAL;
330 if ( var->bits_per_pixel != 8 &&
331 var->bits_per_pixel != 16 &&
332 var->bits_per_pixel != 24 &&
333 var->bits_per_pixel != 32 )
335 INFO_MSG( "mode %dx%dx%d rejected, color depth invalid\n",
336 var->xres, var->yres, var->bits_per_pixel);
337 printk("mgam83fb: mgam83fb_check_var finish with error\n");
338 return -EINVAL;
341 if (var->xres_virtual * var->yres_virtual * ( var->bits_per_pixel >> 3) > p->mem.len) {
342 INFO_MSG( "mode %dx%dx%d rejected, not enough memory\n",
343 var->xres, var->yres, var->bits_per_pixel);
344 printk("mgam83fb: mgam83fb_check_var finish with error\n");
345 return -EINVAL;
348 var->red = colors[colors_index].red;
349 var->green = colors[colors_index].green;
350 var->blue = colors[colors_index].blue;
351 var->transp = colors[colors_index].transp;
352 DEBUG_MSG("mgam83fb: mgam83fb_check_var finish\n");
354 return 0;
357 static int __set_mode(struct mgam83fb_par *p)
359 struct fb_info *info = p->info;
360 struct fb_var_screeninfo *var = &info->var;
361 int hsync = p->hsync_len; // The Horizontal Syncronization Time (Sync Pulse )
362 int hgdel = p->left_margin; // The Horizontal Gate Delay Time (Back Porch)
363 int hgate = p->xres; // The Horizontal Gate Time (Active Time)
364 int hlen = hsync + hgdel + hgate + p->right_margin; // The Horizontal Length Time (Line Total)
365 int vsync = p->vsync_len; // The Vertical Syncronization Time (Sync Pulse )
366 int vgdel = p->upper_margin; // The Vertical Gate Delay Time (Back Porch)
367 int vgate = p->yres; // The Vertical Gate Time (Active Time)
368 int vlen = vsync + vgdel + vgate + p->lower_margin; // The Vertical Length Time (Frame total)
369 int vbl = CTRL_VBL1024; // Video Memory Burst Length
370 int ctrl = CTRL_BL_NEG | vbl;
373 CHECKPOINT_ENTER;
375 /* MGA device always works in little endian mode */
376 switch( p->bits_per_pixel ) {
377 case 8 :
378 ctrl |= CTRL_CD_8BPP | CTRL_PC_PSEUDO;
379 break;
380 case 16 :
381 ctrl |= CTRL_CD_16BPP;
382 if (p->vers.revision >= VER_05_2009
383 && p->vers.revision != MGA_MODEL_PMUP2_0
384 && p->vers.revision != MGA_MODEL_PMUP2_1){
385 #ifdef __LITTLE_ENDIAN
386 /* Turn off bytes-in-half word twister (seted by default) */
387 ctrl |= CTRL_IN_WORDS16_TWISTER;
388 #endif
390 break;
391 case 24 :
392 ctrl |= CTRL_CD_24BPP;
393 DEBUG_MSG("mga: revision = %d\n", p->vers.revision);
394 if (p->vers.revision >= VER_05_2009
395 && p->vers.revision != MGA_MODEL_PMUP2_0
396 && p->vers.revision != MGA_MODEL_PMUP2_1){
397 #ifndef __LITTLE_ENDIAN
398 DEBUG_MSG("mga: New version! not __LE\n");
399 DEBUG_MSG("ctrl to setup is 0x%x\n", ctrl);
400 #endif
402 break;
403 case 32 :
404 ctrl |= CTRL_CD_32BPP;
405 if (p->vers.revision >= VER_05_2009
406 && p->vers.revision != MGA_MODEL_PMUP2_0
407 && p->vers.revision != MGA_MODEL_PMUP2_1){
408 #ifdef __LITTLE_ENDIAN
409 /* Turn off half words twister (seted by default ) */
410 ctrl |= CTRL_WORDS16_IN_WORDS32_TWISTER;
411 /* Turn off bytes-in-half word twister (seted by default) */
412 ctrl |= CTRL_IN_WORDS16_TWISTER;
413 #endif
415 break;
416 default:
417 ERROR_MSG( "Invalid color depth: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__ );
418 CHECKPOINT_LEAVE;
419 return -EINVAL;
422 ctrl |= ( p->sync & FB_SYNC_COMP_HIGH_ACT ) ? CTRL_CSYNC_HIGH : CTRL_CSYNC_LOW;
423 ctrl |= ( p->sync & FB_SYNC_VERT_HIGH_ACT ) ? CTRL_VSYNC_HIGH : CTRL_VSYNC_LOW;
424 ctrl |= ( p->sync & FB_SYNC_HOR_HIGH_ACT ) ? CTRL_HSYNC_HIGH : CTRL_HSYNC_LOW;
426 hsync--, hgdel--, hgate--, vsync--, vgdel--, vgate--, hlen--, vlen--;
427 trace_func(18);
428 MMIO_WRITE( p, REG_CTRL, ctrl );
429 mdelay(1);
430 trace_func(19);
431 MMIO_WRITE( p, REG_HTIM, hsync << 24 | hgdel << 16 | hgate );
432 trace_func(20);
433 MMIO_WRITE( p, REG_VTIM, vsync << 24 | vgdel << 16 | vgate );
434 trace_func(21);
435 MMIO_WRITE( p, REG_HVLEN, hlen << 16 | vlen );
436 trace_func(22);
437 MMIO_WRITE(p, REG_VBARa, var->yoffset * info->fix.line_length);
439 DEBUG_MSG( "hsync: %d hgdel: %d hgate %d\n", hsync, hgdel, hgate );
440 DEBUG_MSG( "vsync: %d vgdel: %d vgate %d\n", vsync, vgdel, vgate );
441 DEBUG_MSG( "hlen: %d vlen: %d\n", hlen, vlen );
442 trace_func(23);
443 MMIO_WRITE(p, REG_CTRL, ctrl | CTRL_VEN);
444 mdelay(1);
446 CHECKPOINT_LEAVE;
447 return 0;
450 #ifdef CONFIG_E90
451 # define DEBUG_MSG_SET_PAR_MODE 0
452 #else
453 # define DEBUG_MSG_SET_PAR_MODE 0
454 #endif
455 #if DEBUG_MSG_SET_PAR_MODE
456 # define DEBUG_MSG_SET_PAR prom_printf
457 #else
458 # define DEBUG_MSG_SET_PAR(...)
459 #endif
461 static int mgam83fb_set_par(struct fb_info* info)
463 struct fb_var_screeninfo* mode = &info->var;
464 struct mgam83fb_par* p = (struct mgam83fb_par*)info->par;
466 CHECKPOINT_ENTER;
468 DEBUG_MSG_SET_PAR("mgam83fb_set_par: start\n");
469 /* Update fix */
470 info->fix.visual = (mode->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
471 info->fix.line_length = mode->xres_virtual * (mode->bits_per_pixel >> 3) ;
473 /* Update par */
474 p->xres = mode->xres;
475 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->xres = 0x%x\n", p->xres);
476 p->yres = mode->yres;
477 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->yres = 0x%x\n", p->yres);
478 p->xres_virtual = mode->xres_virtual;
479 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->xres_virtual = 0x%x\n", p->xres_virtual);
480 p->yres_virtual = mode->yres_virtual;
481 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->yres_virtual = 0x%x\n", p->yres_virtual);
482 p->xoffset = mode->xoffset;
483 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->xoffset = 0x%x\n", p->xoffset);
484 p->yoffset = mode->yoffset;
485 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->yoffset = 0x%x\n", p->yoffset);
486 p->left_margin = mode->left_margin;
487 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->left_margin = 0x%x\n", p->left_margin);
488 p->right_margin = mode->right_margin;
489 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->right_margin = 0x%x\n", p->right_margin);
490 p->hsync_len = mode->hsync_len;
491 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->hsync_len = 0x%x\n", p->hsync_len);
492 p->upper_margin = mode->upper_margin;
493 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->upper_margin = 0x%x\n", p->upper_margin);
494 p->lower_margin = mode->lower_margin;
495 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->lower_margin = 0x%x\n", p->lower_margin );
496 p->vsync_len = mode->vsync_len;
497 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->vsync_len = 0x%x\n", p->vsync_len);
498 p->bits_per_pixel = mode->bits_per_pixel;
499 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->bits_per_pixel = 0x%x\n", p->bits_per_pixel);
500 p->pixclock = mode->pixclock;
501 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->pixclock = 0x%x\n", p->pixclock);
502 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->sync = 0x%x\n", p->sync);
504 #ifdef MGA_DEBUG
505 __dump_par( p );
506 #endif
507 DEBUG_MSG_SET_PAR( KERN_DEBUG " xres:%d yres:%d xvirt:%d yvirt:%d bpp:%d\n",
508 p->xres, p->yres,
509 p->xres_virtual, p->yres_virtual, p->bits_per_pixel);
510 DEBUG_MSG_SET_PAR( KERN_DEBUG " pixclock:%d left:%d right:%d upper:%d "
511 "lower:%d hslen:%d vslen:%d\n",
512 p->pixclock, p->left_margin, p->right_margin,
513 p->upper_margin, p->lower_margin,
514 p->hsync_len, p->vsync_len);
516 /* Turning of display*/
517 MMIO_WRITE(p, REG_CTRL, MMIO_READ(p, REG_CTRL) & ~CTRL_VEN);
519 trace_func(3);
520 __set_pixclock( &p->vers, (unsigned long)p->i2c.vbase, p->pixclock );
521 trace_func(17);
522 __set_mode( p );
523 trace_func(24);
525 #ifdef MGA_DEBUG
526 __dump_mmio( p );
527 #endif
528 DEBUG_MSG_SET_PAR("mgam83fb_set_par finish\n");
529 return 0;
533 static int mgam83_get_cmap_len(int bpp)
535 switch(bpp) {
536 case 8: return 256; /* pseudocolor... 256 entries HW palette */
537 case 16:
538 case 24:
539 case 32: return 16; /* directcolor... 16 entries SW palette */
540 default: return 0;
544 static inline u16 flip_16 (u16 l)
546 return ((l&0xff)<<8) | ((l>>8)&0xff);
549 static int mgam83fb_setcolreg(unsigned regno, unsigned red, unsigned green,
550 unsigned blue, unsigned transp,
551 struct fb_info *info)
553 struct mgam83fb_par* p = (struct mgam83fb_par*)info->par;
555 trace_func(25);
556 DEBUG_MSG("mgam83fb_setcolreg start\n");
557 if (regno >= mgam83_get_cmap_len(p->bits_per_pixel)){ /* no. of hw registers */
558 DEBUG_MSG("mgam83fb: mgam83fb_setcolreg finish with error\n");
559 return -EINVAL;
561 /* grayscale works only partially under directcolor */
562 if (info->var.grayscale) {
563 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
564 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
567 red >>= (16 - info->var.red.length);
568 green >>= (16 - info->var.green.length);
569 blue >>= (16 - info->var.blue.length);
570 transp >>= (16 - info->var.transp.length);
572 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
573 uint32_t val = (red << 16) | (green << 8) | blue;
574 DEBUG_MSG("Using pseudocolors\n");
575 // using CLUT0
576 trace_func(26);
577 MMIO_WRITE( p, 0x800 + regno * 4, val );
580 /* Truecolor has hardware independent palette */
581 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
582 u32 v;
584 DEBUG_MSG("Using truecolors\n");
585 if (regno >= 16){
586 INFO_MSG("mgam83fb_setcolreg finish "
587 "with error, regno = 0x%x\n", regno);
588 return -EINVAL;
591 v = (red << info->var.red.offset) |
592 (green << info->var.green.offset) |
593 (blue << info->var.blue.offset) |
594 (transp << info->var.transp.offset);
595 DEBUG_MSG("setcolreg: red off = %d, green off = %d,"
596 "blue off = %d, v = 0x%x\n", info->var.red.offset,
597 info->var.green.offset, info->var.blue.offset, v);
598 if (p->vers.revision < VER_05_2009){
599 #ifdef __LITTLE_ENDIAN
600 if (p->bits_per_pixel == 16){
601 u16 tmp_v = 0;
602 tmp_v = (u16)v;
603 v = flip_16(tmp_v);
605 #endif
607 // 16bpp, 24bpp or 32bpp
608 trace_func(27);
609 ((u32*)(info->pseudo_palette))[regno] = v;
611 trace_func(28);
612 DEBUG_MSG("mgam83fb_setcolreg finish\n");
613 return 0;
616 struct dma_mem {
617 unsigned long phys_addr; /* dma addr */
618 size_t size;
621 struct dma_mem32 {
622 u32 phys_addr; /* dma addr */
623 unsigned int size;
626 struct ker_dma_mem {
627 unsigned long phys_addr; /* dma addr */
628 void * kvaddr;
629 void *mapaddr;
630 size_t size;
631 struct ker_dma_mem *next;
634 #define FBIOALLOC_DMA_MEM 0x4631
635 #define FBIOFREE_ALL_DMA_MEMS 0x4632
636 #define FBIOWHOAMI 0x4633
638 #define DEBUG_IOCTL_MSG_ON 0
639 #define DEBUG_IOCTL_MSG if (DEBUG_IOCTL_MSG_ON) printk
641 static int
642 mgam83fb_ioctl(struct fb_info *info,
643 unsigned int cmd, unsigned long arg)
645 void *kvaddr = NULL;
646 struct dma_mem dmem;
647 int order;
648 struct page *map, *mapend;
649 struct mgam83fb_par* par = (struct mgam83fb_par*)info->par;
650 void __user *argp = (void __user *)arg;
652 DEBUG_IOCTL_MSG("mgam83fb_ioctl: cmd = 0x%x\n", cmd);
653 switch (cmd) {
654 case FBIOWHOAMI:
655 return 0;
656 case FBIOALLOC_DMA_MEM:
657 if (!par->video_buf.ioaddr) {
658 if (copy_from_user(&dmem, argp, sizeof(dmem))) {
659 DEBUG_IOCTL_MSG("mgam83fb_ioctl: can't copy_from_user\n");
660 return -EFAULT;
662 DEBUG_IOCTL_MSG("mgam83fb_ioctl: Ask to alloc 0x%lx bytes\n", (unsigned long)dmem.size);
663 order = get_order(dmem.size);
664 if (order >= MAX_ORDER) {
665 DEBUG_IOCTL_MSG("mgam83fb_ioctl: order fail\n");
666 return -ENOMEM;
668 DEBUG_IOCTL_MSG("mgam83fb_ioctl: order = %d\n", order);
669 kvaddr = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order);
671 if (!kvaddr){
672 DEBUG_IOCTL_MSG("mgam83fb_ioctl: failed to alloc dma buffer\n");
673 return -ENOMEM;
675 mapend = virt_to_page (kvaddr + (PAGE_SIZE << order) - 1);
676 for (map = virt_to_page(kvaddr); map <= mapend; map++) {
677 SetPageReserved(map);
679 par->video_buf.ioaddr = pci_map_single(par->pdev, (void *)kvaddr, dmem.size,
680 PCI_DMA_BIDIRECTIONAL);
682 par->video_buf.kvaddr = kvaddr;
683 dmem.phys_addr = par->video_buf.ioaddr;
684 par->video_buf.size = dmem.size;
685 } else {
686 dmem.size = par->video_buf.size;
687 dmem.phys_addr = par->video_buf.ioaddr;
689 DEBUG_IOCTL_MSG("FBIOALLOC_DMA_MEM: kvaddr = 0x%08lx; dmem.phys_addr = 0x%08lx\n",
690 (unsigned long)par->video_buf.kvaddr, dmem.phys_addr);
692 if (copy_to_user(argp, &dmem, sizeof(dmem))){
693 DEBUG_IOCTL_MSG("mgam83fb_ioctl: failed to copy_to_user\n");
694 return -EFAULT;
696 return 0;
697 default:
698 DEBUG_IOCTL_MSG("Unsupported cmd 0x%x\n", cmd);
699 return -EINVAL;
704 #ifdef CONFIG_COMPAT
705 static int
706 mgam83fb_compat_ioctl(struct fb_info *info, unsigned int cmd,
707 unsigned long arg)
709 unsigned long kvaddr;
710 struct dma_mem32 dmem;
711 int order;
712 struct page *map, *mapend;
713 struct mgam83fb_par* par = (struct mgam83fb_par*)info->par;
714 void __user *argp = (void __user *)arg;
716 switch (cmd) {
717 case FBIOWHOAMI:
718 return 0;
719 case FBIOALLOC_DMA_MEM:
720 if (!par->video_buf.ioaddr) {
721 if (copy_from_user(&dmem, argp, sizeof(dmem))) {
722 return -EFAULT;
724 DEBUG_IOCTL_MSG("mgam83fbicompat__ioctl: Ask to alloc 0x%x bytes\n", dmem.size);
725 order = get_order(dmem.size);
726 if (order >= MAX_ORDER) {
727 DEBUG_IOCTL_MSG("mgam83fb_ioctl: order fail\n");
728 return -ENOMEM;
731 kvaddr = __get_free_pages(GFP_KERNEL | GFP_DMA, order);
733 if (!kvaddr){
734 DEBUG_IOCTL_MSG("mgam83fb_compat__ioctl: failed to alloc dma buffer\n");
735 return -ENOMEM;
737 mapend = virt_to_page (kvaddr + (PAGE_SIZE << order) - 1);
738 for (map = virt_to_page(kvaddr); map <= mapend; map++) {
739 SetPageReserved(map);
741 par->video_buf.ioaddr = pci_map_single(par->pdev, (void *)kvaddr, dmem.size,
742 PCI_DMA_BIDIRECTIONAL);
743 par->video_buf.kvaddr = (void *) kvaddr;
744 par->video_buf.size = dmem.size;
745 dmem.phys_addr = (u32)par->video_buf.ioaddr;
746 } else {
747 dmem.size = par->video_buf.size;
748 dmem.phys_addr = (u32)par->video_buf.ioaddr;
750 DEBUG_IOCTL_MSG("FBIOALLOC_DMA_MEM: kvaddr = 0x%08lx; dmem.phys_addr = 0x%08x / 0x%08lx\n",
751 (unsigned long)par->video_buf.kvaddr, dmem.phys_addr, par->video_buf.ioaddr);
753 if (copy_to_user(argp, &dmem, sizeof(dmem))){
754 DEBUG_IOCTL_MSG("mgam83fb_compat_ioctl: failed to copy_to_user\n");
755 return -EFAULT;
757 return 0;
758 default:
759 return -ENOIOCTLCMD;
762 #endif
764 #define DEBUG_MMAP_MSG_ON 0
765 #define DEBUG_MMAP_MSG if (DEBUG_MMAP_MSG_ON) printk
767 static int mgam83fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
769 unsigned long off;
770 unsigned long start;
771 struct mgam83fb_par* p = (struct mgam83fb_par*)info->par;
772 u32 len;
773 unsigned long pfn;
775 off = vma->vm_pgoff << PAGE_SHIFT;
777 vma->vm_pgoff = off >> PAGE_SHIFT;
778 /* frame buffer memory */
779 start = info->fix.smem_start;
780 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
781 DEBUG_MMAP_MSG("mgam83fb_mmap: start = 0x%lx, off = 0x%lx, len = 0x%x\n",
782 start, off, len);
783 /* off that's in range of 0..."fb len" corresponds to framebuffer */
784 /* off that's in range of "fb len"..."io len" corresponds to mmio */
785 if (off < len) {
786 DEBUG_MMAP_MSG("mgam83fb_mmap: given off corresponds to fbmem\n");
787 #ifdef CONFIG_E2K
788 vma->vm_page_prot = (cpu_has(CPU_FEAT_WC_PCI_PREFETCH)) ?
789 pgprot_writecombine(vma->vm_page_prot) :
790 pgprot_noncached(vma->vm_page_prot);
791 #endif
794 if ((off >= len) && (off < 0x80000000)) {
795 /* memory mapped io */
796 DEBUG_MMAP_MSG("mgam83fb_mmap: given off corresponds to mmio\n");
797 off -= len;
798 start = info->fix.mmio_start;
799 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
800 #ifdef CONFIG_E2K
801 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
802 #endif
805 if (off >= 0x80000000) {
806 if (vma->vm_end - vma->vm_start > p->video_buf.size) {
807 DEBUG_MMAP_MSG("%s: Len to map too big 0x%x > 0x%x\n",
808 __FUNCTION__, len, p->video_buf.size);
809 return -EINVAL;
811 if (!p->video_buf.ioaddr) {
812 DEBUG_MMAP_MSG("%s: Video buf not allocated\n", __FUNCTION__);
813 return -ENOMEM;
815 off = virt_to_phys(p->video_buf.kvaddr);
816 DEBUG_MMAP_MSG("%s: dvma_pha = 0x%08lx\n", __FUNCTION__, off);
817 vma->vm_pgoff = off >> PAGE_SHIFT;
818 vma->vm_flags |= VM_IO;
819 #if defined(__e2k__)
820 if (vma->vm_flags & VM_WRITECOMBINED)
821 vma->vm_page_prot =
822 pgprot_writecombine(vma->vm_page_prot);
823 #endif
824 if (remap_pfn_range(vma, vma->vm_start,
825 off >> PAGE_SHIFT,
826 vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
827 DEBUG_MMAP_MSG("Mapping failed\n");
828 return -EAGAIN;
831 DEBUG_MMAP_MSG("mgam83fb_mmap: mapping done successfully"
832 " to addr 0x%08lx\n", vma->vm_start);
833 return 0;
836 start &= PAGE_MASK;
837 if ((off + vma->vm_end - vma->vm_start) > len)
838 return -EINVAL;
840 off += start;
841 vma->vm_pgoff = off >> PAGE_SHIFT;
842 /* This is an IO map - tell maydump to skip this VMA */
843 vma->vm_flags |= VM_IO | VM_IO;
845 #if !defined(__e2k__)
846 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
847 #endif
849 DEBUG_MMAP_MSG("%s: mapping iospace 0x%08lx to 0x%08lx - 0x%08lx\n",
850 __FUNCTION__, off, vma->vm_start, vma->vm_end);
851 #ifdef CONFIG_E90
852 pfn = MK_IOSPACE_PFN(0xa, (off >> PAGE_SHIFT));
853 #else
854 pfn = off >> PAGE_SHIFT;
855 #endif
856 if (io_remap_pfn_range(vma, vma->vm_start, pfn,
857 vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
858 DEBUG_MMAP_MSG("Mapping failed\n");
859 return -EAGAIN;
862 return 0;
865 struct dma_image {
866 unsigned long virt_addr;
867 dma_addr_t dma_addr;
868 size_t size;
871 static unsigned int rnum = 0;
872 static struct dma_image d_image[2];
875 static inline void mgam83fb_do_sync(struct mgam83fb_par *p)
877 while (MMIO_READ(p, BBR0) & PROCESS)
878 barrier();
881 #ifdef CONFIG_MGA_HWIMAGEBLIT
883 #define FB_WRITEL fb_writel
884 #define FB_READL fb_readl
887 static int expand_dma_buf(struct pci_dev *dev, struct dma_image *d,
888 size_t size)
890 struct page *map, *mapend;
891 int order;
893 /* Free previous allocated pages */
894 if (d->size != 0) {
895 mapend = virt_to_page(d->virt_addr + d->size - 1);
897 for (map = virt_to_page(d->virt_addr); map <= mapend; map++)
898 ClearPageReserved(map);
900 pci_unmap_single(dev, d->dma_addr, d->size, PCI_DMA_FROMDEVICE);
901 free_pages(d->virt_addr, get_order(d->size));
904 /* Allocate new pages */
905 order = get_order(size);
906 size = PAGE_SIZE << order;
908 d->virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, order);
909 if (!d->virt_addr)
910 goto zero_d;
912 mapend = virt_to_page(d->virt_addr + size - 1);
913 for (map = virt_to_page(d->virt_addr); map <= mapend; map++)
914 SetPageReserved(map);
915 d->dma_addr = pci_map_single(dev, (void *)d->virt_addr,
916 size, PCI_DMA_FROMDEVICE);
917 if (pci_dma_mapping_error(dev, d->dma_addr))
918 goto clear_page;
920 d->size = size;
922 return 0;
924 clear_page:
925 for (map = virt_to_page(d->virt_addr); map <= mapend; map++)
926 ClearPageReserved(map);
928 free_pages(d->virt_addr, order);
929 zero_d:
930 d->size = 0;
931 d->virt_addr = 0;
932 d->dma_addr = 0;
933 return -ENOMEM;
936 static void mgam83fb_imageblit(struct fb_info *p, const struct fb_image *image)
938 struct mgam83fb_par* par = (struct mgam83fb_par*)p->par;
939 u32 fgcolor, bgcolor;
940 u32 Bpp = p->var.bits_per_pixel / 8;
941 u32 dx, dy, width, height;
942 size_t size;
943 unsigned line_length; /* bytes per line */
944 u32 dst_idx, src_idx;
945 u8 *sf, *st;
946 unsigned cbpp;
947 unsigned ctrl = BB_CTRL_CE_EN | BB_CTRL_SDMA_EN |
948 BB_CTRL_CMD_START | BB_CTRL_ROP_SRC |
949 BB_CTRL_SRC_MODE | BITS_IN_BYTE_TWISTER;
951 if (p->state != FBINFO_STATE_RUNNING)
952 return;
954 if (par->vers.revision < VER_05_2009 ||
955 par->vers.revision == MGA_MODEL_PMUP2_0 ||
956 par->vers.revision == MGA_MODEL_PMUP2_1) {
957 cfb_imageblit(p, image);
958 return;
961 if (par->dma_not_supported) {
962 cfb_imageblit(p, image);
963 return;
966 if ((p->flags & FBINFO_HWACCEL_DISABLED)) {
967 cfb_imageblit(p, image);
968 return;
971 switch (Bpp) {
972 case 4:
973 cbpp = BB_CTRL_BPP_32;
974 break;
975 case 3:
976 cbpp = BB_CTRL_BPP_24;
977 break;
978 case 2:
979 cbpp = BB_CTRL_BPP_16;
980 break;
981 case 1:
982 cbpp = BB_CTRL_BPP_8;
983 break;
984 default:
985 return;
988 dx = image->dx;
989 dy = image->dy;
991 width = image->width;
992 height = image->height;
994 size = width * height * Bpp; /* Size in bytes */
996 if (d_image[rnum].size < size) {
997 if (expand_dma_buf(par->pdev, &d_image[rnum], size)) {
998 cfb_imageblit(p, image);
999 return;
1003 st = (u8 *)d_image[rnum].virt_addr;
1004 sf = (u8 *)image->data;
1006 mgam83fb_do_sync(par);
1008 memcpy(st, sf, size);
1010 line_length = p->var.xres_virtual * Bpp;
1011 src_idx = d_image[rnum].dma_addr;
1012 dst_idx = dy * line_length + dx * Bpp;
1014 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
1015 p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1016 fgcolor = ((u32 *)(p->pseudo_palette))[image->fg_color];
1017 bgcolor = ((u32 *)(p->pseudo_palette))[image->bg_color];
1018 } else {
1019 fgcolor = image->fg_color;
1020 bgcolor = image->bg_color;
1023 MMIO_WRITE(par, REG_BB_FG, fgcolor);
1024 MMIO_WRITE(par, REG_BB_BG, bgcolor);
1025 MMIO_WRITE(par, BBR1, ((height << 16) | width * Bpp));
1026 MMIO_WRITE(par, BBR2, src_idx);
1027 MMIO_WRITE(par, BBR3, dst_idx);
1028 MMIO_WRITE(par, BBR4, (line_length << 16));
1030 ctrl |= cbpp;
1032 MMIO_WRITE(par, BBR0, ctrl);
1034 rnum = rnum ^ 1;
1036 #endif
1038 #ifdef CONFIG_MGA_HWCOPYAREA
1039 static void mgam83fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
1041 struct mgam83fb_par* p = (struct mgam83fb_par*)info->par;
1042 unsigned int line_length = info->var.xres_virtual * (info->var.bits_per_pixel >> 3); /* Bytes */
1043 unsigned int command = 0;
1044 struct fb_copyarea modded;
1045 u32 dx = region->dx, dy = region->dy;
1046 u32 sx = region->sx, sy = region->sy;
1047 int dst_idx = 0, src_idx = 0;
1048 u32 spitch = line_length;
1049 u32 dpitch = line_length;
1050 u32 width = 0;
1051 u32 height = 0;
1052 u32 vxres, vyres;
1054 modded.width = region->width;
1055 modded.height = region->height;
1057 if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
1058 cfb_copyarea(info, region);
1059 return;
1062 vxres = info->var.xres_virtual;
1063 vyres = info->var.yres_virtual;
1065 if(!region->width || !region->height ||
1066 sx >= vxres || sy >= vyres ||
1067 dx >= vxres || dy >= vyres)
1068 return;
1070 if(sx + modded.width > vxres) modded.width = vxres - sx;
1071 if(dx + modded.width > vxres) modded.width = vxres - dx;
1072 if(sy + modded.height > vyres) modded.height = vyres - sy;
1073 if(dy + modded.height > vyres) modded.height = vyres - dy;
1075 width = ((modded.width)*(info->var.bits_per_pixel >> 3)); /* window lenght in bytes */
1076 height = modded.height; /* number of lines */
1078 if (sy < dy){
1079 sy = sy + height;
1080 dy = dy + height;
1082 dst_idx = dy*line_length + dx*(info->var.bits_per_pixel >> 3); /* Bytes */
1083 src_idx = sy*line_length + sx*(info->var.bits_per_pixel >> 3); /* Bytes */
1085 mgam83fb_do_sync(p);
1087 MMIO_WRITE(p, BBR1, ((height << 16) | width));
1088 MMIO_WRITE(p, BBR2, src_idx);
1089 MMIO_WRITE(p, BBR3, dst_idx);
1090 MMIO_WRITE(p, BBR4, ((dpitch << 16) | spitch));
1092 command |= (ROP_05 | START);
1093 if (sy < dy){
1094 command |= VDIR;
1097 MMIO_WRITE(p, BBR0, command);
1100 #endif
1103 * fb_blank - NOT a required function. Blanks the display.
1104 * @blank_mode: the blank mode we want.
1105 * @info: frame buffer structure that represents a single frame buffer
1107 * Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
1108 * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
1109 * e.g. a video mode which doesn't support it.
1111 * Implements VESA suspend and powerdown modes on hardware that supports
1112 * disabling hsync/vsync:
1114 * FB_BLANK_NORMAL = display is blanked, syncs are on.
1115 * FB_BLANK_HSYNC_SUSPEND = hsync off
1116 * FB_BLANK_VSYNC_SUSPEND = vsync off
1117 * FB_BLANK_POWERDOWN = hsync and vsync off
1119 * If implementing this function, at least support FB_BLANK_UNBLANK.
1120 * Return !0 for any modes that are unimplemented.
1123 static int mgam83fb_blank(int blank, struct fb_info *info)
1125 struct mgam83fb_par *p = (struct mgam83fb_par *)info->par;
1126 u32 val = MMIO_READ(p, REG_CTRL);
1128 switch (blank) {
1129 case FB_BLANK_UNBLANK: /* Unblanking */
1130 val |= CTRL_VEN;
1131 break;
1133 case FB_BLANK_NORMAL: /* Normal blanking */
1134 case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
1135 case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
1136 case FB_BLANK_POWERDOWN: /* Poweroff */
1137 val &= ~CTRL_VEN;
1138 break;
1141 MMIO_WRITE(p, REG_CTRL, val);
1142 return 0;
1146 * fb_fillrect - REQUIRED function. Can use generic routines if
1147 * non acclerated hardware and packed pixel based.
1148 * Draws a rectangle on the screen.
1150 * @info: frame buffer structure that represents a single frame buffer
1151 * @region: The structure representing the rectangular region we
1152 * wish to draw to.
1154 * This drawing operation places/removes a retangle on the screen
1155 * depending on the rastering operation with the value of color which
1156 * is in the current color depth format.
1158 void mgam83fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1160 struct fb_var_screeninfo *var = &info->var;
1161 struct mgam83fb_par *p = (struct mgam83fb_par *)info->par;
1163 u32 x = rect->dx; u32 y = rect->dy;
1164 u32 height = rect->height; u32 width = rect->width;
1165 u32 pitch = info->fix.line_length;
1166 u32 Bpp = info->var.bits_per_pixel >> 3;
1168 u32 color = (Bpp == 1) ? rect->color :
1169 ((u32 *) info->pseudo_palette)[rect->color];
1170 u32 rop = (rect->rop != ROP_COPY) ? BB_CTRL_ROP_XOR : BB_CTRL_ROP_SRC;
1172 u32 ctrl = rop | BB_CTRL_CE_EN | BB_CTRL_SFILL_EN
1173 | ((Bpp - 1) & 0x3) << 10;
1175 u32 daddr = var->yoffset * pitch + y * pitch + x * Bpp;
1177 mgam83fb_do_sync(p);
1179 MMIO_WRITE(p, REG_BB_FG, color);
1180 MMIO_WRITE(p, REG_BB_WINDOW, (height << 16) | (width * Bpp));
1181 MMIO_WRITE(p, REG_BB_DADDR, daddr);
1182 MMIO_WRITE(p, REG_BB_PITCH, pitch << 16 | 0);
1183 MMIO_WRITE(p, REG_BB_CTRL, ctrl | BB_CTRL_CMD_START);
1187 * pan_display - NOT a required function. Pans the display.
1188 * @var: frame buffer variable screen structure
1189 * @info: frame buffer structure that represents a single frame buffer
1191 * Pan (or wrap, depending on the `vmode' field) the display using the
1192 * `xoffset' and `yoffset' fields of the `var' structure.
1193 * If the values don't fit, return -EINVAL.
1195 * Returns negative errno on error, or zero on success.
1197 static int mgam83fb_pan_display(struct fb_var_screeninfo *var,
1198 struct fb_info *info)
1200 struct mgam83fb_par *p = (struct mgam83fb_par *)info->par;
1201 u32 addr = var->yoffset * info->fix.line_length;
1203 if (var->xoffset)
1204 return -EINVAL;
1205 MMIO_WRITE(p, REG_VBARa, addr);
1206 return 0;
1210 * fb_sync - NOT a required function. Normally the accel engine
1211 * for a graphics card take a specific amount of time.
1212 * Often we have to wait for the accelerator to finish
1213 * its operation before we can write to the framebuffer
1214 * so we can have consistent display output.
1216 * @info: frame buffer structure that represents a single frame buffer
1218 * If the driver has implemented its own hardware-based drawing function,
1219 * implementing this function is highly recommended.
1222 static int mgam83fb_sync(struct fb_info *info)
1224 struct mgam83fb_par *p = (struct mgam83fb_par *)info->par;
1225 mgam83fb_do_sync(p);
1226 return 0;
1230 * Driver initialization
1233 static struct fb_ops mgam83fb_ops = {
1234 .owner = THIS_MODULE,
1236 .fb_check_var = mgam83fb_check_var,
1237 .fb_set_par = mgam83fb_set_par,
1238 .fb_setcolreg = mgam83fb_setcolreg,
1239 .fb_blank = mgam83fb_blank,
1240 .fb_ioctl = mgam83fb_ioctl,
1241 #ifdef CONFIG_COMPAT
1242 .fb_compat_ioctl = mgam83fb_compat_ioctl,
1243 #endif
1244 .fb_mmap = mgam83fb_mmap,
1245 .fb_pan_display = mgam83fb_pan_display,
1246 .fb_sync = mgam83fb_sync,
1247 .fb_fillrect = mgam83fb_fillrect, /*HW function*/
1248 #ifdef CONFIG_MGA_HWCOPYAREA
1249 .fb_copyarea = mgam83fb_copyarea, /*HW function*/
1250 #else
1251 .fb_copyarea = cfb_copyarea, /*Generic function*/
1252 #endif
1253 #ifdef CONFIG_MGA_HWIMAGEBLIT
1254 .fb_imageblit = mgam83fb_imageblit, /*HW function*/
1255 #else
1256 .fb_imageblit = cfb_imageblit, /*Generic function*/
1257 #endif
1260 static irqreturn_t mga_debug_handler(int irq, void *data)
1262 struct mgam83fb_par *p = data;
1263 uint32_t stat = MMIO_READ(p, REG_STAT);
1265 /* Check if bit 0 or bit 1 are set */
1266 if (stat & 0x3) {
1267 printk(KERN_ALERT "mga_debug_handler: stat=0x%08lx\n",
1268 (unsigned long)stat);
1270 * All magic constants were received from Maxim Vorontsov.
1271 * See bug62291 for details.
1273 MMIO_WRITE(p, REG_STAT, 0xf3);
1274 return IRQ_HANDLED;
1276 return IRQ_NONE;
1279 static int __fb_init(struct fb_info *info)
1281 struct mgam83fb_par *p = (struct mgam83fb_par *)info->par;
1282 int retval;
1284 INFO_MSG("MEM : base 0x%08lx vbase 0x%08lx len 0x%lx\n",
1285 (unsigned long)p->mem.base, (unsigned long)p->mem.vbase,
1286 (unsigned long)p->mem.len );
1287 INFO_MSG("MMIO: base 0x%08lx vbase 0x%08lx len 0x%lx\n",
1288 (unsigned long)p->mmio.base, (unsigned long)p->mmio.vbase,
1289 (unsigned long)p->mmio.len );
1290 INFO_MSG("I2C : base 0x%08lx vbase 0x%08lx len 0x%lx\n",
1291 (unsigned long)p->i2c.base, (unsigned long)p->i2c.vbase,
1292 (unsigned long)p->i2c.len );
1295 * Here we set the screen_base to the virtual memory address
1296 * for the framebuffer.
1298 info->screen_base = p->mem.vbase; // Framebuffer virtual memory
1299 info->fbops = &mgam83fb_ops;
1301 strncpy( info->fix.id, "mcst_mga", 8 );
1302 info->fix.smem_start = p->mem.base;
1303 info->fix.smem_len = p->mem.len;
1304 info->fix.type = FB_TYPE_PACKED_PIXELS;
1305 info->fix.type_aux = 0;
1306 info->fix.xpanstep = 0;
1307 info->fix.ypanstep = 0;
1308 info->fix.ywrapstep = 0;
1309 info->fix.mmio_start = p->mmio.base;
1310 info->fix.mmio_len = p->mmio.len;
1311 info->fix.accel = 0;
1313 info->pseudo_palette = p->pseudo_palette; /* The pseudopalette is an
1314 * 16-member array
1316 /* Set up flags to indicate what sort of acceleration driver can provide */
1318 info->flags = FBINFO_DEFAULT
1319 | FBINFO_HWACCEL_YPAN
1320 #ifdef CONFIG_MGA_HWCOPYAREA
1321 | FBINFO_HWACCEL_COPYAREA
1322 #endif
1323 #ifdef CONFIG_MGA_HWIMAGEBLIT
1324 | FBINFO_HWACCEL_IMAGEBLIT
1325 #endif
1328 retval = fb_find_mode(&info->var, info, mgam83fb_default_mode,
1329 NULL, 0, NULL, 8);
1330 if (!retval || retval == 4) {
1331 ERROR_MSG( "fb_find_mode() failed\n");
1332 return -EINVAL;
1334 INFO_MSG("default mode %dx%d-%d\n", info->var.xres, info->var.yres,
1335 info->var.bits_per_pixel);
1337 /* úÄÅÓØ ÉÎÉÃÉÁÌÉÚÉÒÕÅÔÓÑ ÓÔÒÕËÔÕÒÁ cmap É ÚÁÐÏÌÎÑÅÔÓÑ Ã×ÅÔÁÍÉ ÐÏ default
1338 îÁ ÒÅÇÉÓÔÒÙ ÒÁÓËÌÁÄËÁ ÌÏÖÉÔÓÑ Æ-ÅÊ fb_set_cmap -> fb_setcolreg ÉÌÉ ÐÏ default
1339 ÉÌÉ ÐÏÌØÚÏ×ÁÔÅÌØÓËÁÑ ÉÓÐÏÌØÚÕÑ FBIOPUTCMAP */
1340 retval = fb_alloc_cmap(&info->cmap, 256, 0);
1341 if (retval) {
1342 ERROR_MSG( "unable to allocate colormap\n" );
1343 return -ENOMEM;
1347 * For drivers that can...
1349 /* ÚÄÅÓØ ÉÎÉÃÉÁÌÉÚÉÒÕÅÔÓÑ ÍÁÓÓÉ× fb_bitfield ÄÌÑ Ã×ÅÔÏ× */
1350 DEBUG_MSG("__fb_init: fb_bitfield initialization\n");
1351 if (mgam83fb_check_var(&info->var, info)) {
1352 ERROR_MSG( "unable to validate variable\n" );
1353 return -EINVAL;
1356 if (register_framebuffer(info) < 0) {
1357 ERROR_MSG( "register_framebuffer() failed\n" );
1358 fb_dealloc_cmap(&info->cmap);
1359 return -EINVAL;
1361 INFO_MSG("fb%d: %s frame buffer device\n", info->node, info->fix.id);
1362 p->index = next_index++;
1363 #ifdef MGA_DEBUG
1364 __proc_init( p );
1365 #endif
1367 return 0;
1370 static int mgam83fb_probe(struct pci_dev *dev,
1371 const struct pci_device_id *ent)
1373 #ifdef CONFIG_E90
1374 static struct mfgid mfg;
1375 #endif
1376 struct fb_info* info;
1377 struct mgam83fb_par* p;
1378 int ret = -EINVAL;
1379 char revision;
1381 DEBUG_MSG("mgam83fb: pci driver_init\n");
1382 if ( (ret = pci_enable_device(dev)) ) {
1383 printk( KERN_ERR "%s: cannot enable pci device\n", pci_name(dev));
1384 return ret;
1387 pci_set_master(dev);
1390 * Dynamically allocate info and par
1392 info = framebuffer_alloc(sizeof(struct mgam83fb_par), &dev->dev );
1393 if (!info) {
1394 ERROR_MSG( "failed to allocate fb_info instance!\n");
1395 ret = -ENOMEM;
1396 goto fail;
1398 p = info->par;
1399 p->vers.bus = BUS_TYPE_PCI;
1400 p->pdev = dev;
1401 p->info = info;
1402 #ifdef CONFIG_E90
1403 // TODO what to do if it is sparc, but not E90?
1404 p->mem.iospace = PCI_IOSPACE;
1405 #endif
1406 p->mem.base = pci_resource_start(dev, PCI_MEM_BAR);
1407 if ((ret = pci_read_config_byte(dev, PCI_REVISION_ID, &revision))) {
1408 printk( KERN_ERR "%s: cannot read revision id\n", pci_name(dev));
1409 return ret;
1411 if (revision == 0) {
1412 // This card has wrong size in bar
1413 p->mem.len = MGA_MEM_SIZE;
1414 } else {
1415 p->mem.len = pci_resource_len( dev, PCI_MEM_BAR );
1418 if ( (ret = pci_request_region(dev, PCI_MEM_BAR, "mgam83 FB")) )
1419 goto fail_mem;
1421 p->mem.vbase = ioremap(p->mem.base, p->mem.len);
1423 if ( !p->mem.vbase)
1425 ERROR_MSG( "cannot ioremap MEM (%lx, 0x%x)\n", p->mem.base, p->mem.len);
1426 ret = -ENOMEM;
1427 goto fail_ioremap_mem;
1430 // Video card registers
1431 p->mmio.base = pci_resource_start( dev, PCI_MMIO_BAR );
1432 p->mmio.len = pci_resource_len( dev, PCI_MMIO_BAR );
1434 if ( (ret = pci_request_region(dev, PCI_MMIO_BAR, "mgam83 MMIO")) )
1435 goto fail_mmio;
1437 p->mmio.vbase = ioremap( p->mmio.base, p->mmio.len );
1438 if ( !p->mmio.vbase )
1440 ERROR_MSG( "cannot ioremap MMIO (0x%08lx:0x%x)\n", p->mmio.base, p->mmio.len );
1441 ret = -ENOMEM;
1442 goto fail_mmio_ioremap;
1445 // I2C bus registers
1446 p->i2c.base = pci_resource_start( dev, PCI_I2C_BAR );
1447 p->i2c.len = pci_resource_len( dev, PCI_I2C_BAR );
1448 if ( (ret = pci_request_region(dev, PCI_I2C_BAR, "mgam83 I2C")) )
1449 goto fail_i2c;
1450 p->i2c.vbase = ioremap( p->i2c.base, p->i2c.len );
1451 if ( !p->i2c.vbase )
1453 ERROR_MSG( "cannot ioremap I2C (0x%08lx:0x%x)\n", p->i2c.base, p->i2c.len );
1454 ret = -ENOMEM;
1455 goto fail_i2c_ioremap;
1458 /* Debug handler (bug62291) */
1459 if (use_irq) {
1460 ret = request_irq(dev->irq, mga_debug_handler, IRQF_SHARED,
1461 "mgam83", p);
1462 if (ret)
1463 goto fail_irq;
1466 /* Mga driver version on all other machines depends on RevID
1467 * in pci configuration space */
1468 pci_read_config_byte(dev, PCI_REVISION_ID, &p->vers.revision);
1469 INFO_MSG("MGA version driver from pci config space = 0x%x\n",
1470 p->vers.revision);
1471 #ifdef CONFIG_E90
1472 #ifdef CONFIG_E90_FASTBOOT
1473 if (!bootblock) // OpenPROM boot
1474 #endif
1475 if(p->vers.revision != MGA_MODEL_PMUP2_0
1476 && p->vers.revision != MGA_MODEL_PMUP2_1) {
1477 get_mcst_mfgid(&mfg);
1478 p->vers.revision = mfg.tty1Mbit;
1479 printk(KERN_NOTICE "mgam83fb: MGA version driver from mfgid = 0x%x\n",
1480 p->vers.revision);
1482 #endif
1484 set_up_colors_bounds(p);
1485 /* Turning of display */
1486 MMIO_WRITE(p, REG_CTRL, MMIO_READ(p, REG_CTRL) & ~CTRL_VEN);
1488 p->dma_not_supported = (MMIO_READ(p, BBR0) & DMA_SUPPORT) == 0;
1490 // Filling info, selecting mode and initializating framebuffer
1491 DEBUG_MSG("mgam83fb: framebuffer init ...\n");
1492 if ( (ret = __fb_init( info )) )
1493 goto fail_register_fb;
1495 pci_set_drvdata(dev, info);
1496 return 0;
1498 fail_register_fb:
1499 if (use_irq)
1500 free_irq(dev->irq, p);
1501 fail_irq:
1502 iounmap(p->i2c.vbase);
1503 fail_i2c_ioremap:
1504 pci_release_region(dev, PCI_I2C_BAR);
1505 fail_i2c:
1506 iounmap(p->mmio.vbase);
1507 fail_mmio_ioremap:
1508 pci_release_region(dev, PCI_MMIO_BAR);
1509 fail_mmio:
1510 iounmap(p->mem.vbase);
1511 fail_ioremap_mem:
1512 pci_release_region(dev, PCI_MEM_BAR);
1513 fail_mem:
1514 framebuffer_release(info);
1515 fail:
1516 return ret;
1519 static void mgam83fb_remove(struct pci_dev *dev)
1521 struct fb_info *info = pci_get_drvdata(dev);
1522 struct page *map, *mapend;
1523 struct mgam83fb_par* p;
1525 if (info == NULL) {
1526 return;
1529 p = (struct mgam83fb_par*)info->par;
1531 if (use_irq)
1532 free_irq(dev->irq, p);
1534 if (p->video_buf.ioaddr) {
1535 struct page *map, *mapend;
1536 pci_unmap_single(p->pdev, p->video_buf.ioaddr,
1537 p->video_buf.size, PCI_DMA_FROMDEVICE);
1538 mapend = virt_to_page(p->video_buf.kvaddr + p->video_buf.size -1);
1539 for (map = virt_to_page(p->video_buf.kvaddr); map <= mapend; map++) {
1540 ClearPageReserved(map);
1542 free_pages((unsigned long)p->video_buf.kvaddr, get_order(p->video_buf.size));
1543 p->video_buf.ioaddr = 0;
1544 p->video_buf.kvaddr = 0;
1545 p->video_buf.size = 0;
1547 for (rnum = 0; rnum != 2; rnum++) {
1548 if (d_image[rnum].size != 0){
1549 mapend = virt_to_page((d_image[rnum].virt_addr) +
1550 (PAGE_SIZE << get_order(d_image[rnum].size)) - 1);
1551 for (map = virt_to_page((d_image[rnum].virt_addr)); map <= mapend; map++) {
1552 ClearPageReserved(map);
1554 pci_unmap_single(p->pdev, d_image[rnum].dma_addr,
1555 d_image[rnum].size, PCI_DMA_FROMDEVICE);
1556 free_pages(d_image[rnum].virt_addr, get_order(d_image[rnum].size));
1557 d_image[rnum].size = 0;
1558 d_image[rnum].virt_addr = 0;
1559 d_image[rnum].dma_addr = 0;
1562 /* Turning of display */
1563 MMIO_WRITE(p, REG_CTRL, MMIO_READ(p, REG_CTRL) & ~CTRL_VEN);
1565 unregister_framebuffer(info);
1566 fb_dealloc_cmap(&info->cmap);
1567 iounmap(p->i2c.vbase);
1568 pci_release_region(dev, PCI_I2C_BAR);
1569 iounmap(p->mmio.vbase);
1570 pci_release_region(dev, PCI_MMIO_BAR);
1571 iounmap(p->mem.vbase);
1572 pci_release_region(dev, PCI_MEM_BAR);
1573 framebuffer_release(info);
1575 /* First time when we load driver drvdata is NULL, but if we reload it,
1576 * we get garbage here, because drvdata is not cleared after driver unload
1578 pci_set_drvdata(dev, NULL);
1581 static int mgam83fb_suspend(struct pci_dev *dev, pm_message_t state)
1583 return pci_save_state(dev);
1586 static int mgam83fb_resume(struct pci_dev *dev)
1588 struct fb_info *info = pci_get_drvdata(dev);
1589 pci_restore_state(dev);
1590 mgam83fb_set_par(info);
1591 return 0;
1594 static struct pci_device_id mgam83fb_devices[] = {
1595 { PCI_DEVICE(PCI_VENDOR_ID_MGAM83, PCI_DEVICE_ID_MGAM83) },
1596 { 0, }
1599 static struct pci_driver mgam83fb_driver = {
1600 .name = "mgam83fb",
1601 .id_table = mgam83fb_devices,
1602 .probe = mgam83fb_probe,
1603 .remove = mgam83fb_remove,
1604 .suspend = mgam83fb_suspend,
1605 .resume = mgam83fb_resume,
1609 #ifndef MODULE
1610 static int __init mgam83fb_setup(char *options)
1612 if (!options || !*options)
1613 return 0;
1614 mgam83fb_default_mode = options;
1615 return 0;
1617 #endif /* MODULE */
1619 static int __init mgam83fb_init(void)
1621 int pci_ret = 0;
1622 #ifndef MODULE
1623 char *option = NULL;
1624 if (fb_get_options("mgam83fb", &option))
1625 return -ENODEV;
1626 mgam83fb_setup(option);
1627 #endif
1628 DEBUG_MSG("Module initialization\n");
1630 pci_ret = pci_register_driver(&mgam83fb_driver);
1632 return 0;
1637 static void mgam83fb_cleanup(void)
1639 pci_unregister_driver(&mgam83fb_driver);
1642 ////////////////////////////////////////////////////////////////////////////////
1643 // Modularization
1644 ////////////////////////////////////////////////////////////////////////////////
1646 module_init(mgam83fb_init);
1647 module_exit(mgam83fb_cleanup);
1649 module_param(use_irq, bool, S_IRUGO);
1650 MODULE_PARM_DESC(use_irq, "Register interrupt handler");
1651 MODULE_LICENSE("GPL");
1653 #ifdef MGA_DEBUG
1654 /*******************************************************************************
1655 * Debug
1656 *******************************************************************************
1659 void __dump_mmio( struct mgam83fb_par* p )
1662 DEBUG_MSG( "CTRL: 0x%08x\n", MMIO_READ( p, REG_CTRL) );
1663 DEBUG_MSG( "STAT: 0x%08x\n", MMIO_READ( p, REG_STAT) );
1664 DEBUG_MSG( "HTIM: 0x%08x\n", MMIO_READ( p, REG_HTIM) );
1665 DEBUG_MSG( "VTIM: 0x%08x\n", MMIO_READ( p, REG_VTIM) );
1666 DEBUG_MSG( "HVLEN: 0x%08x\n", MMIO_READ( p, REG_HVLEN) );
1667 DEBUG_MSG( "VBARa: 0x%08x\n", MMIO_READ( p, REG_VBARa) );
1668 DEBUG_MSG( "VBARb: 0x%08x\n", MMIO_READ( p, REG_VBARb) );
1669 DEBUG_MSG( "C0XY: 0x%08x\n", MMIO_READ( p, REG_C0XY) );
1670 DEBUG_MSG( "C0BAR: 0x%08x\n", MMIO_READ( p, REG_C0BAR) );
1671 DEBUG_MSG( "C0CR: 0x%08x\n", MMIO_READ( p, REG_C0CR) );
1672 DEBUG_MSG( "C1XY: 0x%08x\n", MMIO_READ( p, REG_C1XY) );
1673 DEBUG_MSG( "C1BAR: 0x%08x\n", MMIO_READ( p, REG_C1BAR) );
1674 DEBUG_MSG( "C1CR: 0x%08x\n", MMIO_READ( p, REG_C1CR) );
1676 if ( 8 == p->bits_per_pixel ) {
1677 unsigned long col_regno;
1678 DEBUG_MSG( "CLUT0 ==================================DUMP BEGIN\n" );
1679 for( col_regno = 0; col_regno < 256; col_regno++ ) {
1680 int val = MMIO_READ( p, 0x800 + col_regno * 4 );
1681 DEBUG_MSG( "%03ld: r %02x g %02x b %02x\n", col_regno, (val & 0x00FF0000) >> 16, (val & 0x0000FF00), (val & 0x000000FF) );
1683 DEBUG_MSG( "CLUT0 ====================================DUMP END\n" );
1687 void __dump_par( const struct mgam83fb_par* p )
1689 char buf[256] = { 0, };
1691 int pos = 0;
1692 if ( p->sync & FB_SYNC_HOR_HIGH_ACT )
1693 pos += sprintf( buf + pos, "FB_SYNC_HOR_HIGH_ACT " );
1694 if ( p->sync & FB_SYNC_VERT_HIGH_ACT )
1695 pos += sprintf( buf + pos, "FB_SYNC_VERT_HIGH_ACT " );
1696 if ( p->sync & FB_SYNC_COMP_HIGH_ACT )
1697 pos += sprintf( buf + pos, "FB_SYNC_COMP_HIGH_ACT " );
1699 DEBUG_MSG( "mgafb_par ==============================DUMP BEGIN\n" );
1700 DEBUG_MSG( "Resolution: %dx%d\n", p->xres, p->yres );
1701 DEBUG_MSG( "Virtual resolution: %dx%d\n", p->xres_virtual, p->yres_virtual );
1702 DEBUG_MSG( "Offset: x %d y %d\n", p->xoffset, p->yoffset );
1703 DEBUG_MSG( "Bpp: %d\n", p->bits_per_pixel );
1704 DEBUG_MSG( "Pixclock: %d\n", p->pixclock );
1705 DEBUG_MSG( "Margins: left %d right %d upper %d lower %d\n",
1706 p->left_margin, p->right_margin, p->upper_margin, p->lower_margin );
1707 DEBUG_MSG( "Sync length: horizontal %d vertical %d\n",
1708 p->hsync_len, p->vsync_len );
1709 DEBUG_MSG( "%s\n", buf );
1710 DEBUG_MSG( "mgafb_par ================================DUMP END\n" );
1714 void __dump_var( const struct fb_var_screeninfo* var )
1716 char buf[256] = { 0, };
1717 int pos = 0;
1718 if ( var->sync & FB_SYNC_HOR_HIGH_ACT )
1719 pos += sprintf( buf + pos, "FB_SYNC_HOR_HIGH_ACT " );
1720 if ( var->sync & FB_SYNC_VERT_HIGH_ACT )
1721 pos += sprintf( buf + pos, "FB_SYNC_VERT_HIGH_ACT " );
1722 if ( var->sync & FB_SYNC_COMP_HIGH_ACT )
1723 pos += sprintf( buf + pos, "FB_SYNC_COMP_HIGH_ACT " );
1725 DEBUG_MSG( "fb_var_screeninfo ======================DUMP BEGIN\n" );
1726 DEBUG_MSG( "Resolution: %dx%d\n", var->xres, var->yres );
1727 DEBUG_MSG( "Virtual resolution: %dx%d\n", var->xres_virtual, var->yres_virtual );
1728 DEBUG_MSG( "Offset: x %d y %d\n", var->xoffset, var->yoffset );
1729 DEBUG_MSG( "Bpp: %d, Grayscale: %d\n", var->bits_per_pixel, var->grayscale );
1730 DEBUG_MSG( "Bitfields: \n" );
1731 DEBUG_MSG( " color | offset | length | msb_right\n" );
1732 DEBUG_MSG( " red | %2d | %2d | %1d \n", var->red.offset, var->red.length, var->red.msb_right );
1733 DEBUG_MSG( " green | %2d | %2d | %1d \n", var->green.offset, var->green.length, var->green.msb_right );
1734 DEBUG_MSG( " blue | %2d | %2d | %1d \n", var->blue.offset, var->blue.length, var->blue.msb_right );
1735 DEBUG_MSG( " transp | %2d | %2d | %1d \n", var->transp.offset, var->transp.length, var->transp.msb_right );
1736 DEBUG_MSG( "Pixclock: %d\n", var->pixclock );
1737 DEBUG_MSG( "Margins: left %d right %d upper %d lower %d\n",
1738 var->left_margin, var->right_margin, var->upper_margin, var->lower_margin );
1739 DEBUG_MSG( "Sync length: horizontal %d vertical %d\n",
1740 var->hsync_len, var->vsync_len );
1741 DEBUG_MSG( "%s\n", buf );
1742 DEBUG_MSG( "fb_var_screeninfo ========================DUMP END\n" );
1745 /*******************************************************************************
1746 * Proc
1747 *******************************************************************************
1750 #define PROC_FILENAME "mgam83_"
1751 #define PROC_INPUT_MAX_LEN 32
1752 #define CTRL_VBL_MASK (~(CTRL_VBL_1 | CTRL_VBL_2 | CTRL_VBL_4 | CTRL_VBL_8 | CTRL_VBL1024))
1754 char regs_buf[4096];
1756 void spill_regs(struct mgam83fb_par* p){
1757 int len = 0;
1758 int i = 0;
1759 for (i = 0; i != 4096; i++){
1760 regs_buf[i] = 0;
1762 len += sprintf( regs_buf + len, "CTRL: 0x%08x\n", MMIO_READ( p, REG_CTRL) );
1763 len += sprintf( regs_buf + len, "STAT: 0x%08x\n", MMIO_READ( p, REG_STAT) );
1764 len += sprintf( regs_buf + len, "HTIM: 0x%08x\n", MMIO_READ( p, REG_HTIM) );
1765 len += sprintf( regs_buf + len, "VTIM: 0x%08x\n", MMIO_READ( p, REG_VTIM) );
1766 len += sprintf( regs_buf + len, "HVLEN: 0x%08x\n", MMIO_READ( p, REG_HVLEN) );
1767 len += sprintf( regs_buf + len, "VBARa: 0x%08x\n", MMIO_READ( p, REG_VBARa) );
1768 len += sprintf( regs_buf + len, "VBARb: 0x%08x\n", MMIO_READ( p, REG_VBARb) );
1769 len += sprintf( regs_buf + len, "C0XY: 0x%08x\n", MMIO_READ( p, REG_C0XY) );
1770 len += sprintf( regs_buf + len, "C0BAR: 0x%08x\n", MMIO_READ( p, REG_C0BAR) );
1771 len += sprintf( regs_buf + len, "C0CR: 0x%08x\n", MMIO_READ( p, REG_C0CR) );
1772 len += sprintf( regs_buf + len, "C1XY: 0x%08x\n", MMIO_READ( p, REG_C1XY) );
1773 len += sprintf( regs_buf + len, "C1BAR: 0x%08x\n", MMIO_READ( p, REG_C1BAR) );
1774 len += sprintf( regs_buf + len, "C1CR: 0x%08x\n", MMIO_READ( p, REG_C1CR) );
1775 len += sprintf( regs_buf + len, "TST_D: 0x%08x\n", MMIO_READ( p, REG_TST_D) );
1776 len += sprintf( regs_buf + len, "BBR0: 0x%08x\n", MMIO_READ( p, BBR0) );
1777 len += sprintf( regs_buf + len, "BBR1: 0x%08x\n", MMIO_READ( p, BBR1) );
1778 len += sprintf( regs_buf + len, "BBR2: 0x%08x\n", MMIO_READ( p, BBR2) );
1779 len += sprintf( regs_buf + len, "BBR3: 0x%08x\n", MMIO_READ( p, BBR3) );
1780 len += sprintf( regs_buf + len, "BBR4: 0x%08x\n", MMIO_READ( p, BBR4) );
1781 len += sprintf( regs_buf + len, "BBR5: 0x%08x\n", MMIO_READ( p, BBR5) );
1782 sprintf( regs_buf + len, "BBR6: 0x%08x\n", MMIO_READ( p, BBR6) );
1785 int mgafb_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
1787 struct mgam83fb_par* p = (struct mgam83fb_par* )data;
1788 int len = 0;
1789 int i = 0;
1790 u32 bpp = p->info->var.bits_per_pixel;
1791 size_t screen_length;
1792 u8 *s;
1793 int rgval;
1796 if ( p ) {
1797 #if 0
1798 uint32_t vbl = MMIO_READ( p, REG_CTRL ) & ~CTRL_VBL_MASK;
1800 len += sprintf( buf + len, "CTRL: 0x%08x\n", MMIO_READ( p, REG_CTRL) );
1801 len += sprintf( buf + len, "STAT: 0x%08x\n", MMIO_READ( p, REG_STAT) );
1802 len += sprintf( buf + len, "HTIM: 0x%08x\n", MMIO_READ( p, REG_HTIM) );
1803 len += sprintf( buf + len, "VTIM: 0x%08x\n", MMIO_READ( p, REG_VTIM) );
1804 len += sprintf( buf + len, "HVLEN: 0x%08x\n", MMIO_READ( p, REG_HVLEN) );
1805 len += sprintf( buf + len, "VBARa: 0x%08x\n", MMIO_READ( p, REG_VBARa) );
1806 len += sprintf( buf + len, "VBARb: 0x%08x\n", MMIO_READ( p, REG_VBARb) );
1807 len += sprintf( buf + len, "C0XY: 0x%08x\n", MMIO_READ( p, REG_C0XY) );
1808 len += sprintf( buf + len, "C0BAR: 0x%08x\n", MMIO_READ( p, REG_C0BAR) );
1809 len += sprintf( buf + len, "C0CR: 0x%08x\n", MMIO_READ( p, REG_C0CR) );
1810 len += sprintf( buf + len, "C1XY: 0x%08x\n", MMIO_READ( p, REG_C1XY) );
1811 len += sprintf( buf + len, "C1BAR: 0x%08x\n", MMIO_READ( p, REG_C1BAR) );
1812 len += sprintf( buf + len, "C1CR: 0x%08x\n", MMIO_READ( p, REG_C1CR) );
1813 len += sprintf( buf + len, "TST_D: 0x%08x\n", MMIO_READ( p, REG_TST_D) );
1815 len += sprintf( buf + len, "\n" );
1817 switch( vbl ) {
1818 case CTRL_VBL_1 :
1819 len += sprintf( buf + len, "VBL: 1\n" );
1820 break;
1821 case CTRL_VBL_2 :
1822 len += sprintf( buf + len, "VBL: 2\n" );
1823 break;
1824 case CTRL_VBL_4 :
1825 len += sprintf( buf + len, "VBL: 4\n" );
1826 break;
1827 case CTRL_VBL_8 :
1828 len += sprintf( buf + len, "VBL: 8\n" );
1829 break;
1830 case CTRL_VBL1024 :
1831 len += sprintf( buf + len, "VBL: 1024\n" );
1832 break;
1833 default :
1834 len += sprintf( buf + len, "VBL: N/A\n" );
1838 clk_t clk = __calc( p->pixclock );
1839 len += sprintf( buf + len, "div: %d\n", clk.div );
1840 len += sprintf( buf + len, "q: %d\n", clk.q );
1841 len += sprintf( buf + len, "p: %d\n", clk.p );
1842 len += sprintf( buf + len, "po: %d\n", clk.po );
1845 #endif
1846 #if 0
1847 if (last_info != NULL)
1848 cfb_copyarea(last_info, &last_area);
1850 if (last_info != NULL)
1851 mgam83fb_copyarea(last_info, &last_area);
1852 #endif
1853 #if 0
1854 for (i = area_count; i != 10; i++){
1855 len += sprintf( buf + len, "dx = %d\n", last_area[i].dx);
1856 len += sprintf( buf + len, "dy = %d\n", last_area[i].dy);
1857 len += sprintf( buf + len, "sx = %d\n", last_area[i].sx);
1858 len += sprintf( buf + len, "sy = %d\n", last_area[i].sy);
1859 len += sprintf( buf + len, "width = %d\n", last_area[i].width);
1860 len += sprintf( buf + len, "height = %d\n", last_area[i].height);
1862 for (i = 0; i != area_count; i++){
1863 len += sprintf( buf + len, "dx = %d\n", last_area[i].dx);
1864 len += sprintf( buf + len, "dy = %d\n", last_area[i].dy);
1865 len += sprintf( buf + len, "sx = %d\n", last_area[i].sx);
1866 len += sprintf( buf + len, "sy = %d\n", last_area[i].sy);
1867 len += sprintf( buf + len, "width = %d\n", last_area[i].width);
1868 len += sprintf( buf + len, "height = %d\n", last_area[i].height);
1870 #endif
1871 #if 0 /* getting framebuffer into file */
1872 screen_length = ((p->info->var.yres_virtual) *
1873 (p->info->var.xres_virtual) *
1874 (bpp >> 3)); /* in bytes */
1875 s = (u8 *)p->info->screen_base;
1876 for (i = 0; i != screen_length; i++)
1878 *buf = *s;
1879 buf++;
1880 s++;
1881 len++;
1883 #endif
1884 #if 1
1885 /* getting reg */
1886 if (start == 0x100){
1887 if (count == 1) {rgval = MMIO_READ(p, REG_STAT);}
1888 if (count == 2) {rgval = MMIO_READ(p, REG_HTIM);}
1889 if (count == 3) {rgval = MMIO_READ(p, REG_VTIM);}
1890 if (count == 4) {rgval = MMIO_READ(p, REG_HVLEN);}
1891 if (count == 5) {rgval = MMIO_READ(p, REG_VBARa);}
1892 if (count == 6) {rgval = MMIO_READ(p, REG_VBARb);}
1893 if (count == 7) {rgval = MMIO_READ(p, REG_C0XY);}
1894 if (count == 8) {rgval = MMIO_READ(p, REG_C0BAR);}
1895 if (count == 9) {rgval = MMIO_READ(p, REG_C0CR);}
1896 if (count == 10) {rgval = MMIO_READ(p, REG_C1XY);}
1897 if (count == 11) {rgval = MMIO_READ(p, REG_C1BAR);}
1898 if (count == 12) {rgval = MMIO_READ(p, REG_C1CR);}
1899 if (count == 13) {rgval = MMIO_READ(p, REG_TST_D);}
1900 if (count == 14) {rgval = MMIO_READ(p, BBR0);}
1901 if (count == 15) {rgval = MMIO_READ(p, BBR1);}
1902 if (count == 16) {rgval = MMIO_READ(p, BBR2);}
1903 if (count == 17) {rgval = MMIO_READ(p, BBR3);}
1904 if (count == 18) {rgval = MMIO_READ(p, BBR4);}
1905 if (count == 19) {rgval = MMIO_READ(p, BBR5);}
1906 if (count == 20) {rgval = MMIO_READ(p, BBR6);}
1908 if (count >= 32)
1909 return 0;
1911 *(u32 *)buf = rgval;
1912 return 4;
1915 /* getting all regs (last values before write) */
1916 #if 0
1917 if (start == 0x1000){
1918 s = regs_buf;
1919 for (i = 0; i != PAGE_SIZE; i++){
1920 *buf = *s;
1921 buf++;
1922 s++;
1923 len++;
1925 return len;
1927 #endif
1928 /* getting all regs */
1929 #if 1
1930 spill_regs(p);
1931 if (start == 0x1000){
1932 s = regs_buf;
1933 for (i = 0; i != PAGE_SIZE; i++){
1934 *buf = *s;
1935 buf++;
1936 s++;
1937 len++;
1939 return len;
1941 #endif
1943 /* getting framebuffer */
1944 screen_length = ((p->info->var.yres_virtual) *
1945 (p->info->var.xres_virtual) *
1946 (bpp >> 3)); /* in bytes */
1947 if (off >= screen_length)
1948 return 0;
1949 if (count > (screen_length - off))
1950 count = (screen_length - off);
1951 s = (u8 *)((u8 *)p->info->screen_base + off);
1952 for (i = 0; i != count; i++)
1954 *buf = *s;
1955 buf++;
1956 s++;
1957 len++;
1959 #endif
1962 return len;
1966 int mgafb_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
1968 struct mgam83fb_par* p = (struct mgam83fb_par*)data;
1969 char kern_buf[PROC_INPUT_MAX_LEN] = { 0, };
1970 char *new_buf;
1971 unsigned int reg;
1972 int vbl = 0;
1973 int command;
1974 struct page *map, *mapend;
1975 int dpitch, spitch;
1977 int i = 0;
1978 u32 bpp = p->info->var.bits_per_pixel;
1979 size_t screen_length, len;
1980 char *s;
1981 char *buf;
1982 char *st, *sf;
1983 int rgval;
1985 #if 1 /* (writing register) */
1986 if (count <= 32){
1987 if (copy_from_user(&rgval, buffer, 4)) {
1988 ERROR_MSG( "Failed to copy from user\n" );
1989 return -EFAULT;
1993 if (count == 1){ MMIO_WRITE(p, REG_STAT, rgval); return 4;}
1994 if (count == 2){ MMIO_WRITE( p, REG_HTIM, rgval ); return 4;}
1995 if (count == 3){ MMIO_WRITE( p, REG_VTIM, rgval ); return 4;}
1996 if (count == 4){ MMIO_WRITE( p, REG_HVLEN, rgval );return 4;}
1997 if (count == 5){ MMIO_WRITE( p, REG_VBARa, rgval );return 4;}
1998 if (count == 6){ MMIO_WRITE( p, REG_VBARb, rgval );return 4;}
1999 if (count == 7){ MMIO_WRITE( p, REG_C0XY, rgval ); return 4;}
2000 if (count == 8){ MMIO_WRITE( p, REG_C0BAR, rgval );return 4;}
2001 if (count == 9){ MMIO_WRITE( p, REG_C0CR, rgval ); return 4;}
2002 if (count == 10){ MMIO_WRITE( p, REG_C1XY, rgval ); return 4;}
2003 if (count == 11){ MMIO_WRITE( p, REG_C1BAR, rgval );return 4;}
2004 if (count == 12){ MMIO_WRITE( p, REG_C1CR, rgval ); return 4;}
2005 if (count == 13){ MMIO_WRITE( p, REG_TST_D, rgval );return 4;}
2006 if (count == 14){ MMIO_WRITE( p, BBR0, rgval ); return 4;}
2007 if (count == 15){ MMIO_WRITE( p, BBR1, rgval ); return 4;}
2008 if (count == 16){ MMIO_WRITE( p, BBR2, rgval ); return 4;}
2009 if (count == 17){ MMIO_WRITE( p, BBR3, rgval ); return 4;}
2010 if (count == 18){ MMIO_WRITE( p, BBR4, rgval ); return 4;}
2011 if (count == 19){ MMIO_WRITE( p, BBR5, rgval ); return 4;}
2012 if (count == 20){ MMIO_WRITE( p, BBR6, rgval ); return 4;}
2013 if (count == 21){ MMIO_WRITE(p, REG_CTRL, rgval);
2014 mdelay(1); return 4;}
2016 if (count <= 32)
2017 return 0;
2018 #endif
2019 #if 0
2020 if ( !count || count > PROC_INPUT_MAX_LEN ) {
2021 ERROR_MSG( "Command length is too big\n" );
2022 return -EINVAL;
2024 if ( copy_from_user( &kern_buf, buffer, count ) ) {
2025 ERROR_MSG( "Failed to copy from user\n" );
2026 return -EFAULT;
2029 if ( sscanf( kern_buf, "CTRL=0x%x", &reg ) == 1 || sscanf( kern_buf, "CTRL=0x%x", &reg ) == 1 ) {
2030 DEBUG_MSG( "CTRL <= 0x%x\n", reg );
2031 MMIO_WRITE( p, REG_CTRL, reg );
2032 // } else if ( sscanf( kern_buf, "FB=%d", &fb_cmd ) == 1 ) {
2033 // DEBUG_MSG( "Unregistering FB..." );
2034 // if ( unregister_framebuffer( &p->gen.info ) ) {
2035 // printk( "Failed\n" );
2036 // } else {
2037 // printk( "Ok\n" );
2038 // p->fb_registered = 0;
2039 // }
2040 } else {
2041 int enabled = MMIO_READ( p, REG_CTRL ) & CTRL_VEN;
2042 unsigned int offset;
2043 // int index, time;
2044 MMIO_WRITE( p, REG_CTRL, MMIO_READ( p, REG_CTRL ) & ~CTRL_VEN );
2046 if ( sscanf( kern_buf, "STAT=0x%x", &reg ) == 1 || sscanf( kern_buf, "STAT=%x", &reg ) == 1 ) {
2047 DEBUG_MSG( "STAT <= 0x%x\n", reg );
2048 MMIO_WRITE( p, REG_STAT, reg );
2049 } else if ( sscanf( kern_buf, "HTIM=0x%x", &reg ) == 1 || sscanf( kern_buf, "HTIM=%x", &reg ) == 1 ) {
2050 DEBUG_MSG( "HTIM <= 0x%x\n", reg );
2051 MMIO_WRITE( p, REG_HTIM, reg );
2052 } else if ( sscanf( kern_buf, "VTIM=0x%x", &reg ) == 1 || sscanf( kern_buf, "VTIM=%x", &reg ) == 1 ) {
2053 DEBUG_MSG( "VTIM <= 0x%x\n", reg );
2054 MMIO_WRITE( p, REG_VTIM, reg );
2055 } else if ( sscanf( kern_buf, "HVLEN=0x%x", &reg ) == 1 || sscanf( kern_buf, "HVLEN=%x", &reg ) == 1 ) {
2056 DEBUG_MSG( "HVLEN <= 0x%x\n", reg );
2057 MMIO_WRITE( p, REG_HVLEN, reg );
2058 } else if ( sscanf( kern_buf, "VBARa=0x%x", &reg ) == 1 || sscanf( kern_buf, "VBARa=%x", &reg ) == 1 ) {
2059 DEBUG_MSG( "VBARa <= 0x%x\n", reg );
2060 MMIO_WRITE( p, REG_VBARa, reg );
2061 } else if ( sscanf( kern_buf, "VBARb=0x%x", &reg ) == 1 || sscanf( kern_buf, "VBARb=%x", &reg ) == 1 ) {
2062 DEBUG_MSG( "VBARb <= 0x%x\n", reg );
2063 MMIO_WRITE( p, REG_VBARb, reg );
2064 } else if ( sscanf( kern_buf, "C0XY=0x%x", &reg ) == 1 || sscanf( kern_buf, "C0XY=%x", &reg ) == 1 ) {
2065 DEBUG_MSG( "C0XY <= 0x%x\n", reg );
2066 MMIO_WRITE( p, REG_C0XY, reg );
2067 } else if ( sscanf( kern_buf, "C0BAR=0x%x", &reg ) == 1 || sscanf( kern_buf, "C0BAR=%x", &reg ) == 1 ) {
2068 DEBUG_MSG( "C0BAR <= 0x%x\n", reg );
2069 MMIO_WRITE( p, REG_C0BAR, reg );
2070 } else if ( sscanf( kern_buf, "C0CR=0x%x", &reg ) == 1 || sscanf( kern_buf, "C0CR=%x", &reg ) == 1 ) {
2071 DEBUG_MSG( "C0CR <= 0x%x\n", reg );
2072 MMIO_WRITE( p, REG_C0CR, reg );
2073 } else if ( sscanf( kern_buf, "C1XY=0x%x", &reg ) == 1 || sscanf( kern_buf, "C1XY=%x", &reg ) == 1 ) {
2074 DEBUG_MSG( "C1XY <= 0x%x\n", reg );
2075 MMIO_WRITE( p, REG_C1XY, reg );
2076 } else if ( sscanf( kern_buf, "C1BAR=0x%x", &reg ) == 1 || sscanf( kern_buf, "C1BAR=%x", &reg ) == 1 ) {
2077 DEBUG_MSG( "C1BAR <= 0x%x\n", reg );
2078 MMIO_WRITE( p, REG_C1BAR, reg );
2079 } else if ( sscanf( kern_buf, "C1CR=0x%x", &reg ) == 1 || sscanf( kern_buf, "C1CR=%x", &reg ) == 1 ) {
2080 DEBUG_MSG( "C1CR <= 0x%x\n", reg );
2081 MMIO_WRITE( p, REG_C1CR, reg );
2082 } else if ( sscanf( kern_buf, "TST_D=0x%x", &reg ) == 1 || sscanf( kern_buf, "TST_D=%x", &reg ) == 1 ) {
2083 DEBUG_MSG( "TST_D <= 0x%x\n", reg );
2084 MMIO_WRITE( p, REG_TST_D, reg );
2085 } else if ( sscanf( kern_buf, "VBL=%d", &vbl ) == 1 ) {
2086 switch( vbl ) {
2087 case 1 :
2088 DEBUG_MSG( "VBL: 1\n" );
2089 vbl = CTRL_VBL_1;
2090 break;
2091 case 2 :
2092 DEBUG_MSG( "VBL: 2\n" );
2093 vbl = CTRL_VBL_2;
2094 break;
2095 case 4 :
2096 DEBUG_MSG( "VBL: 4\n" );
2097 vbl = CTRL_VBL_4;
2098 break;
2099 case 8 :
2100 DEBUG_MSG( "VBL: 8\n" );
2101 vbl = CTRL_VBL_8;
2102 break;
2103 case 1024 :
2104 DEBUG_MSG( "VBL: 1024\n" );
2105 vbl = CTRL_VBL1024;
2106 break;
2107 default :
2108 DEBUG_MSG( "Unknown VBL value. Using VBL1024\n" );
2109 vbl = CTRL_VBL1024;
2111 MMIO_WRITE( p, REG_CTRL, ( MMIO_READ( p, REG_CTRL ) & CTRL_VBL_MASK ) | vbl );
2112 } else if ( sscanf( kern_buf, "RS 0x%x=0x%x", &offset, &reg ) == 2 ) {
2113 DEBUG_MSG( "REG(0x%x) <= 0x%x\n", offset, reg );
2114 MMIO_WRITE( p, offset, reg );
2115 } else if ( sscanf( kern_buf, "RG 0x%x", &offset ) == 1 ) {
2116 DEBUG_MSG( "REG(0x%x) => 0x%x\n", offset, MMIO_READ( p, offset ) );
2117 } else {
2118 ERROR_MSG( "Unknown command line: %s\n", kern_buf );
2121 MMIO_WRITE( p, REG_CTRL, MMIO_READ( p, REG_CTRL ) | enabled );
2123 #endif
2125 #if 0 /* no dma mode (buffer like in dma) (source is file) */
2126 screen_length = (p->info->var.yres_virtual) *
2127 (p->info->var.xres_virtual)*(bpp >> 3); /* in bytes */
2128 d_image.size = screen_length;
2129 d_image.virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA,
2130 get_order(d_image.size));
2132 st = (u8 *)d_image.virt_addr;
2133 sf = (u8 *)buffer;
2135 if ( copy_from_user( st, sf, d_image.size ) ) {
2136 ERROR_MSG( "Failed to copy from user\n" );
2137 return -EFAULT;
2139 st = (u8 *)p->info->screen_base;
2140 sf = (u8 *)d_image.virt_addr;
2142 for (i = 0; i != d_image.size; i++)
2144 *st = *sf;
2145 st++;
2146 sf++;
2147 vbl++;
2149 free_pages(d_image.virt_addr, get_order(d_image.size));
2150 #endif
2151 #if 0 /* dma mode (source is file) */
2152 d_image.size = (p->info->var.yres_virtual) *
2153 (p->info->var.xres_virtual)*(bpp >> 3); /* in bytes */
2154 d_image.virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA,
2155 get_order(d_image.size));
2156 mapend = virt_to_page ((d_image.virt_addr) +
2157 (PAGE_SIZE << get_order(d_image.size)) - 1);
2158 for (map = virt_to_page((d_image.virt_addr)); map <= mapend; map++)
2159 SetPageReserved(map);
2160 d_image.dma_addr = pci_map_single(p->pdev,
2161 (void *)d_image.virt_addr, d_image.size,
2162 PCI_DMA_FROMDEVICE);
2164 st = (u8 *)d_image.virt_addr;
2165 sf = (u8 *)buffer;
2167 if ( copy_from_user( st, sf, d_image.size ) ) {
2168 ERROR_MSG( "Failed to copy from user\n" );
2169 return -EFAULT;
2172 vbl = d_image.size;
2174 while (MMIO_READ(p, BBR0) & PROCESS){
2176 dpitch = (p->info->var.xres_virtual) * (bpp >> 3);
2177 spitch = dpitch;
2179 MMIO_WRITE(p, BBR1, ((p->info->var.yres_virtual << 16) |
2180 ((p->info->var.xres_virtual) * (bpp >> 3))));
2181 MMIO_WRITE(p, BBR2, d_image.dma_addr);
2182 MMIO_WRITE(p, BBR3, 0);
2183 MMIO_WRITE(p, BBR4, (dpitch << 16) | spitch);
2184 command |= ( ROP_05 | SDMA_EN | START);
2186 spill_regs(p);
2187 MMIO_WRITE(p, BBR0, command);
2189 while ( MMIO_READ(p, BBR0) & PROCESS) {
2191 pci_unmap_single(p->pdev, d_image.dma_addr,
2192 d_image.size, PCI_DMA_FROMDEVICE);
2193 free_pages(d_image.virt_addr, get_order(d_image.size));
2194 #endif
2195 #if 0 /* dma mode (source is framebuffer) */
2196 while (MMIO_READ(p, BBR0) & PROCESS){
2198 dpitch = (p->info->var.xres_virtual) * (bpp >> 3);
2199 spitch = dpitch;
2201 MMIO_WRITE(p, BBR1, ((p->info->var.yres_virtual << 16) |
2202 ((p->info->var.xres_virtual) * (bpp >> 3))));
2203 MMIO_WRITE(p, BBR2, p->mem.base);
2204 MMIO_WRITE(p, BBR3, 0);
2205 MMIO_WRITE(p, BBR4, (dpitch << 16) | spitch);
2206 command |= ( ROP_05 | SDMA_EN | START);
2208 MMIO_WRITE(p, BBR0, command);
2210 spill_regs(p);
2212 while ( MMIO_READ(p, BBR0) & PROCESS) {
2214 pci_unmap_single(p->pdev, d_image.dma_addr,
2215 d_image.size, PCI_DMA_FROMDEVICE);
2216 free_pages(d_image.virt_addr, get_order(d_image.size));
2217 #endif
2218 #if 0 /* dma - dma mode (source is file) */
2219 d_image.size = (p->info->var.yres_virtual) *
2220 (p->info->var.xres_virtual)*(bpp >> 3); /* in bytes */
2221 d_image.virt_addr = __get_free_pages(GFP_KERNEL | GFP_DMA,
2222 get_order(d_image.size));
2223 mapend = virt_to_page ((d_image.virt_addr) +
2224 (PAGE_SIZE << get_order(d_image.size)) - 1);
2225 for (map = virt_to_page((d_image.virt_addr)); map <= mapend; map++)
2226 SetPageReserved(map);
2227 d_image.dma_addr = pci_map_single(p->pdev,
2228 (void *)d_image.virt_addr, d_image.size,
2229 PCI_DMA_FROMDEVICE);
2231 st = (u8 *)d_image.virt_addr;
2232 sf = (u8 *)buffer;
2234 if ( copy_from_user( st, sf, d_image.size ) ) {
2235 ERROR_MSG( "Failed to copy from user\n" );
2236 return -EFAULT;
2239 vbl = d_image.size;
2241 while (MMIO_READ(p, BBR0) & PROCESS){
2244 dpitch = (p->info->var.xres_virtual) * (bpp >> 3);
2245 spitch = dpitch;
2247 MMIO_WRITE(p, BBR1, ((p->info->var.yres_virtual << 16) |
2248 ((p->info->var.xres_virtual) * (bpp >> 3))));
2249 MMIO_WRITE(p, BBR2, d_image.dma_addr);
2250 MMIO_WRITE(p, BBR3, p->mem.base);
2251 MMIO_WRITE(p, BBR4, (dpitch << 16) | spitch);
2252 command |= ( ROP_05 | SDMA_EN | DDMA_EN | START);
2254 spill_regs(p);
2255 MMIO_WRITE(p, BBR0, command);
2257 while ( MMIO_READ(p, BBR0) & PROCESS) {
2259 pci_unmap_single(p->pdev, d_image.dma_addr,
2260 d_image.size, PCI_DMA_FROMDEVICE);
2261 free_pages(d_image.virt_addr, get_order(d_image.size));
2262 #endif
2263 return vbl;
2266 void __proc_init( struct mgam83fb_par* p )
2268 char buf[256] = { 0, };
2269 struct proc_dir_entry* entry;
2271 // TODO not index but pci slot id
2272 sprintf( buf, PROC_FILENAME "%d", p->index );
2274 entry = create_proc_entry( buf, 0, &proc_root );
2276 if ( entry ) {
2277 entry->data = (void*)p;
2278 entry->read_proc = mgafb_proc_read;
2279 entry->write_proc = mgafb_proc_write;
2283 #endif /* End of MGA_DEBUG */