1 /* MGA-M83 framebuffer driver
2 * make -C ../linux-2.6.14 SUBDIRS=$PWD modules
4 * Copyright (C) 2005-2006, Alexander Shmelev <ashmelev@task.sun.mcst.ru>
6 * To specify a video mode at bootup, use the following boot options:
7 * video=mgam83fb:<xres>x<yres>[-<bpp>][@refresh]
9 * Supported resolutions:
10 * 640x480, 800x600, 1024x768, 1280x1024, 1600x1200
12 * 8bpp, 16bpp, 24bpp, 32bpp
14 * Details about modes can be found in Linux/Documentation/fb/modedb.txt
17 * 1.1 SBUS model support added
18 * 2.0 Linux-2.6 version
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/errno.h>
24 #include <linux/string.h>
26 #include <linux/tty.h>
27 #include <linux/slab.h>
28 #include <linux/delay.h>
30 #include <linux/init.h>
31 #include <linux/proc_fs.h>
32 #include <asm/uaccess.h>
33 #include <linux/dma-mapping.h>
34 #include <linux/of_device.h>
36 #if defined(CONFIG_SBUS)
37 #define mga_ioremap of_ioremap
38 #elif defined(CONFIG_PCI2SBUS_MODULE)
39 #include <linux/mcst/p2ssbus.h>
42 #include "sbus_mgam83fb.h"
44 static char* mode_option
= NULL
;
45 static int next_index
= 0;
47 /*******************************************************************************
49 *******************************************************************************
52 int bus_type
; // 0 - PCI, 1 - SBUS
53 int index
; // MGAM index
57 int iospace
; // iospace
59 unsigned long base
; // phys address
60 uint8_t* vbase
; // virtual address
64 unsigned long base
; // phys address
65 uint8_t* vbase
; // virtual address
69 unsigned long base
; // phys address
70 uint8_t* vbase
; // virtual address
79 struct of_device
*mgaop
;
82 /* Current videomode **************************************************/
83 __u32 xres
; // visible resolution
85 __u32 xres_virtual
; // virtual resolution
87 __u32 xoffset
; // offset from virtual to visible
88 __u32 yoffset
; // resolution
90 __u32 bits_per_pixel
; // Bits per pixel
92 __u32 pixclock
; // pixel clock in ps (pico seconds)
93 __u32 left_margin
; // time from sync to picture
94 __u32 right_margin
; // time from picture to sync
95 __u32 upper_margin
; // time from sync to picture
97 __u32 hsync_len
; // length of horizontal sync
98 __u32 vsync_len
; // length of vertical sync
102 u32 pseudo_palette
[16];
107 /*******************************************************************************
109 *******************************************************************************
111 /* Framebuffer entry points */
112 static int mgam83fb_check_var(struct fb_var_screeninfo
* var
, struct fb_info
* info
);
113 static int mgam83fb_set_par(struct fb_info
* info
);
114 static int mgam83fb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
115 unsigned blue
, unsigned transp
,
116 struct fb_info
*info
);
117 static int mgam83fb_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
);
118 void __proc_init( struct mgam83fb_par
* p
);
119 int mgafb_proc_write(struct file
*file
, const char *buffer
, unsigned long count
, void *data
);
120 int mgafb_proc_read(char *buf
, char **start
, off_t off
, int count
, int *eof
, void *data
);
121 void __fb_fill ( struct mgam83fb_par
* p
);
122 void __dump_var( const struct fb_var_screeninfo
* var
);
123 void __dump_par( const struct mgam83fb_par
* p
);
124 void __dump_mmio( struct mgam83fb_par
* p
);
126 #undef MGAM_TRACE_FUNC
127 #ifdef MGAM_TRACE_FUNC
128 extern void mgam_trace_func(unsigned int i
);
129 #define trace_func(x) mgam_trace_func(x)
131 #define trace_func(x)
133 /*******************************************************************************
135 *******************************************************************************
137 static void MMIO_WRITE( struct mgam83fb_par
* p
, unsigned long reg
, uint32_t val
)
139 TRACE_MSG( "MMIO[0x%03lx] <= 0x%08x\n", reg
, val
);
141 switch( p
->bus_type
) {
142 #if defined(CONFIG_SBUS) || defined(CONFIG_PCI2SBUS_MODULE)
144 // registers are little-endian like in PCI model
145 writel( val
, (void*)((unsigned long)p
->mmio
.vbase
+ reg
) );
147 #endif /* CONFIG_SBUS || CONFIG_PCI2SBUS_MODULE */
149 printk( KERN_WARNING
"Cannot write to mmio: unsupported MGA/M video card model!\n" );
152 TRACE_MSG( "Sleeping 10 msecs...\n" );
155 static uint32_t MMIO_READ( struct mgam83fb_par
* p
, unsigned long reg
)
159 switch( p
->bus_type
) {
160 #if defined(CONFIG_SBUS) || defined(CONFIG_PCI2SBUS_MODULE)
162 // registers are little-endian like in PCI model
163 result
= readl( (void*)((unsigned long) p
->mmio
.vbase
+ reg
) );
167 #endif /* CONFIG_SBUS || CONFIG_PCI2SBUS_MODULE */
169 result
= ~(uint32_t)0;
170 printk( KERN_WARNING
"Cannot write to mmio: unsupported MGA/M video card model!\n" );
172 TRACE_MSG( "MMIO[0x%03lx] => 0x%08x\n", reg
, result
);
176 /*******************************************************************************
177 * External entry points
178 *******************************************************************************
180 static struct { struct fb_bitfield transp
, red
, green
, blue
; } colors
[] = {
181 { { 0, 0, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0} }, // 8bpp
182 { { 0, 0, 0}, { 11, 5, 0}, { 5, 6, 0}, { 0, 5, 0} }, // 16bpp
183 { { 0, 0, 0}, { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0} }, // 24bpp
184 { { 24, 8, 0}, { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0} }, // 32bpp
187 static int mgam83fb_check_var(struct fb_var_screeninfo
* var
, struct fb_info
* info
)
189 struct mgam83fb_par
* p
= (struct mgam83fb_par
*)info
->par
;
190 int colors_index
= (var
->bits_per_pixel
>>3) - 1; // Index in colors table
192 DEBUG_MSG("mgam83fb: mgam83fb_check_var start\n");
193 if ( (var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
) {
194 INFO_MSG( "mode %dx%dx%d rejected, interlaced not supported\n",
195 var
->xres
, var
->yres
, var
->bits_per_pixel
);
199 if ( var
->bits_per_pixel
!= 8 &&
200 var
->bits_per_pixel
!= 16 &&
201 var
->bits_per_pixel
!= 24 &&
202 var
->bits_per_pixel
!= 32 )
204 INFO_MSG( "mode %dx%dx%d rejected, color depth invalid\n",
205 var
->xres
, var
->yres
, var
->bits_per_pixel
);
206 printk("mgam83fb: mgam83fb_check_var finish with error\n");
210 if (var
->xres_virtual
* var
->yres_virtual
* ( var
->bits_per_pixel
>> 3) > p
->mem
.len
) {
211 INFO_MSG( "mode %dx%dx%d rejected, not enough memory\n",
212 var
->xres
, var
->yres
, var
->bits_per_pixel
);
213 printk("mgam83fb: mgam83fb_check_var finish with error\n");
217 var
->red
= colors
[colors_index
].red
;
218 var
->green
= colors
[colors_index
].green
;
219 var
->blue
= colors
[colors_index
].blue
;
220 var
->transp
= colors
[colors_index
].transp
;
221 DEBUG_MSG("mgam83fb: mgam83fb_check_var finish\n");
227 static int __set_mode( struct mgam83fb_par
* p
)
229 int hsync
= p
->hsync_len
; // The Horizontal Syncronization Time (Sync Pulse )
230 int hgdel
= p
->left_margin
; // The Horizontal Gate Delay Time (Back Porch)
231 int hgate
= p
->xres
; // The Horizontal Gate Time (Active Time)
232 int hlen
= hsync
+ hgdel
+ hgate
+ p
->right_margin
; // The Horizontal Length Time (Line Total)
233 int vsync
= p
->vsync_len
; // The Vertical Syncronization Time (Sync Pulse )
234 int vgdel
= p
->upper_margin
; // The Vertical Gate Delay Time (Back Porch)
235 int vgate
= p
->yres
; // The Vertical Gate Time (Active Time)
236 int vlen
= vsync
+ vgdel
+ vgate
+ p
->lower_margin
; // The Vertical Length Time (Frame total)
237 int vbl
= CTRL_VBL1024
; // Video Memory Burst Length
238 int ctrl
= CTRL_BL_NEG
| vbl
;
243 switch( p
->bits_per_pixel
) {
245 ctrl
|= CTRL_CD_8BPP
| CTRL_PC_PSEUDO
;
248 ctrl
|= CTRL_CD_16BPP
;
251 ctrl
|= CTRL_CD_24BPP
;
254 ctrl
|= CTRL_CD_32BPP
;
257 ERROR_MSG( "Invalid color depth: %s %s %d\n", __FILE__
, __FUNCTION__
, __LINE__
);
262 ctrl
|= ( p
->sync
& FB_SYNC_COMP_HIGH_ACT
) ? CTRL_CSYNC_HIGH
: CTRL_CSYNC_LOW
;
263 ctrl
|= ( p
->sync
& FB_SYNC_VERT_HIGH_ACT
) ? CTRL_VSYNC_HIGH
: CTRL_VSYNC_LOW
;
264 ctrl
|= ( p
->sync
& FB_SYNC_HOR_HIGH_ACT
) ? CTRL_HSYNC_HIGH
: CTRL_HSYNC_LOW
;
266 hsync
--, hgdel
--, hgate
--, vsync
--, vgdel
--, vgate
--, hlen
--, vlen
--;
268 MMIO_WRITE( p
, REG_CTRL
, ctrl
);
270 MMIO_WRITE( p
, REG_HTIM
, hsync
<< 24 | hgdel
<< 16 | hgate
);
272 MMIO_WRITE( p
, REG_VTIM
, vsync
<< 24 | vgdel
<< 16 | vgate
);
274 MMIO_WRITE( p
, REG_HVLEN
, hlen
<< 16 | vlen
);
276 MMIO_WRITE( p
, REG_VBARa
, 0x0 );
277 MMIO_WRITE(p
, REG_BUGFIX
, 0);
279 DEBUG_MSG( "hsync: %d hgdel: %d hgate %d\n", hsync
, hgdel
, hgate
);
280 DEBUG_MSG( "vsync: %d vgdel: %d vgate %d\n", vsync
, vgdel
, vgate
);
281 DEBUG_MSG( "hlen: %d vlen: %d\n", hlen
, vlen
);
283 MMIO_WRITE( p
, REG_CTRL
, MMIO_READ( p
, REG_CTRL
) | CTRL_VEN
);
284 // MMIO_WRITE( p, REG_CTRL, ctrl | CTRL_VEN );
290 #define DEBUG_MSG_SET_PAR_MODE 0
291 #define DEBUG_MSG_SET_PAR if (DEBUG_MSG_SET_PAR_MODE) printk
292 static int mgam83fb_set_par(struct fb_info
* info
)
294 struct fb_var_screeninfo
* mode
= &info
->var
;
295 struct mgam83fb_par
* p
= (struct mgam83fb_par
*)info
->par
;
299 DEBUG_MSG_SET_PAR("mgam83fb_set_par: start\n");
301 info
->fix
.visual
= (mode
->bits_per_pixel
== 8) ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
302 info
->fix
.line_length
= mode
->xres_virtual
* (mode
->bits_per_pixel
>> 3) ;
305 p
->xres
= mode
->xres
;
306 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->xres = 0x%x\n", p
->xres
);
307 p
->yres
= mode
->yres
;
308 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->yres = 0x%x\n", p
->yres
);
309 p
->xres_virtual
= mode
->xres_virtual
;
310 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->xres_virtual = 0x%x\n", p
->xres_virtual
);
311 p
->yres_virtual
= mode
->yres_virtual
;
312 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->yres_virtual = 0x%x\n", p
->yres_virtual
);
313 p
->xoffset
= mode
->xoffset
;
314 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->xoffset = 0x%x\n", p
->xoffset
);
315 p
->yoffset
= mode
->yoffset
;
316 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->yoffset = 0x%x\n", p
->yoffset
);
317 p
->left_margin
= mode
->left_margin
;
318 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->left_margin = 0x%x\n", p
->left_margin
);
319 p
->right_margin
= mode
->right_margin
;
320 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->right_margin = 0x%x\n", p
->right_margin
);
321 p
->hsync_len
= mode
->hsync_len
;
322 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->hsync_len = 0x%x\n", p
->hsync_len
);
323 p
->upper_margin
= mode
->upper_margin
;
324 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->upper_margin = 0x%x\n", p
->upper_margin
);
325 p
->lower_margin
= mode
->lower_margin
;
326 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->lower_margin = 0x%x\n", p
->lower_margin
);
327 p
->vsync_len
= mode
->vsync_len
;
328 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->vsync_len = 0x%x\n", p
->vsync_len
);
329 p
->bits_per_pixel
= mode
->bits_per_pixel
;
330 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->bits_per_pixel = 0x%x\n", p
->bits_per_pixel
);
331 p
->pixclock
= mode
->pixclock
;
332 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->pixclock = 0x%x\n", p
->pixclock
);
333 DEBUG_MSG_SET_PAR("mgam83fb_set_par: p->sync = 0x%x\n", p
->sync
);
338 DEBUG_MSG_SET_PAR( KERN_DEBUG
" xres:%d yres:%d xvirt:%d yvirt:%d bpp:%d\n",
340 p
->xres_virtual
, p
->yres_virtual
, p
->bits_per_pixel
);
341 DEBUG_MSG_SET_PAR( KERN_DEBUG
" pixclock:%d left:%d right:%d upper:%d "
342 "lower:%d hslen:%d vslen:%d\n",
343 p
->pixclock
, p
->left_margin
, p
->right_margin
,
344 p
->upper_margin
, p
->lower_margin
,
345 p
->hsync_len
, p
->vsync_len
);
348 __sbus_set_pixclock( p
->bus_type
, (unsigned long)p
->i2c
.vbase
, p
->pixclock
);
356 DEBUG_MSG_SET_PAR("mgam83fb_set_par finish\n");
361 static int mgam83_get_cmap_len(int bpp
)
364 case 8: return 256; /* pseudocolor... 256 entries HW palette */
367 case 32: return 16; /* directcolor... 16 entries SW palette */
372 static int mgam83fb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
373 unsigned blue
, unsigned transp
,
374 struct fb_info
*info
)
376 struct mgam83fb_par
* p
= (struct mgam83fb_par
*)info
->par
;
379 DEBUG_MSG("mgam83fb_setcolreg start\n");
380 if (regno
>= mgam83_get_cmap_len(p
->bits_per_pixel
)){ /* no. of hw registers */
381 DEBUG_MSG("mgam83fb: mgam83fb_setcolreg finish with error\n");
384 /* grayscale works only partially under directcolor */
385 if (info
->var
.grayscale
) {
386 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
387 red
= green
= blue
= (red
* 77 + green
* 151 + blue
* 28) >> 8;
390 red
>>= (16 - info
->var
.red
.length
);
391 green
>>= (16 - info
->var
.green
.length
);
392 blue
>>= (16 - info
->var
.blue
.length
);
393 transp
>>= (16 - info
->var
.transp
.length
);
395 if (info
->fix
.visual
== FB_VISUAL_PSEUDOCOLOR
) {
396 uint32_t val
= (red
<< 16) | (green
<< 8) | blue
;
399 MMIO_WRITE( p
, 0x800 + regno
* 4, val
);
402 /* Truecolor has hardware independent palette */
403 if (info
->fix
.visual
== FB_VISUAL_TRUECOLOR
) {
407 printk("mgam83fb: mgam83fb_setcolreg finish with error, regno = 0x%x\n", regno
);
411 v
= (red
<< info
->var
.red
.offset
) |
412 (green
<< info
->var
.green
.offset
) |
413 (blue
<< info
->var
.blue
.offset
) |
414 (transp
<< info
->var
.transp
.offset
);
416 // 16bpp, 24bpp or 32bpp
418 ((u32
*)(info
->pseudo_palette
))[regno
] = v
;
421 DEBUG_MSG("mgam83fb_setcolreg finish\n");
426 unsigned long phys_addr
; /* dma addr */
431 unsigned long phys_addr
; /* dma addr */
432 unsigned long kvaddr
;
434 struct ker_dma_mem
*next
;
437 static struct ker_dma_mem
*dma_mem_list
= NULL
;
439 #define FBIOALLOC_DMA_MEM 0x4631
440 #define FBIOFREE_ALL_DMA_MEMS 0x4632
442 #define DEBUG_IOCTL_MSG_ON 0
443 #define DEBUG_IOCTL_MSG if (DEBUG_IOCTL_MSG_ON) printk
446 mgam83fb_ioctl(struct fb_info
*info
, unsigned int cmd
,
449 unsigned long kvaddr
;
452 struct page
*map
, *mapend
;
453 struct mgam83fb_par
* par
= (struct mgam83fb_par
*)info
->par
;
454 void __user
*argp
= (void __user
*)arg
;
457 case FBIOALLOC_DMA_MEM
:
458 if (!par
->video_buf
.ioaddr
) {
459 if (copy_from_user(&dmem
, argp
, sizeof(dmem
))) {
462 DEBUG_IOCTL_MSG("mgam83fb_ioctl: Ask to alloc 0x%lx bytes\n",
463 (unsigned long)dmem
.size
);
464 order
= get_order(dmem
.size
);
465 kvaddr
= __get_free_pages(GFP_KERNEL
| GFP_DMA
, order
);
468 DEBUG_IOCTL_MSG("mgam83fb_ioctl: failed to alloc dma buffer\n");
471 mapend
= virt_to_page (kvaddr
+ (PAGE_SIZE
<< order
) - 1);
472 for (map
= virt_to_page(kvaddr
); map
<= mapend
; map
++) {
473 SetPageReserved(map
);
475 par
->video_buf
.ioaddr
= dma_map_single(&par
->mgaop
->dev
, (void *)kvaddr
, dmem
.size
,
477 par
->video_buf
.kvaddr
= kvaddr
;
478 par
->video_buf
.size
= dmem
.size
;
480 dmem
.phys_addr
= par
->video_buf
.ioaddr
;
481 DEBUG_IOCTL_MSG("FBIOALLOC_DMA_MEM: kvaddr = 0x%08lx; dmem.phys_addr = 0x%08lx\n", kvaddr
, dmem
.phys_addr
);
483 if (copy_to_user(argp
, &dmem
, sizeof(dmem
))){
484 DEBUG_IOCTL_MSG("mgam83fb_ioctl: failed to copy_to_user\n");
493 #define DEBUG_MMAP_MSG_ON 0
494 #define DEBUG_MMAP_MSG if (DEBUG_MMAP_MSG_ON) printk
496 static struct ker_dma_mem
*lookup_trough_dma_list(unsigned long off
)
498 struct ker_dma_mem
*tmp_list
= dma_mem_list
;
500 if ((off
>= tmp_list
->phys_addr
) &&
501 (off
< (tmp_list
->phys_addr
+ tmp_list
->size
)))
503 tmp_list
= dma_mem_list
->next
;
508 static int mgam83fb_mmap(struct fb_info
*info
, struct vm_area_struct
*vma
)
512 struct ker_dma_mem
*tmp_list
= NULL
;
514 struct mgam83fb_par
* p
= (struct mgam83fb_par
*)info
->par
;
516 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
518 /* frame buffer memory */
519 start
= info
->fix
.smem_start
;
520 len
= PAGE_ALIGN((start
& ~PAGE_MASK
) + info
->fix
.smem_len
);
521 DEBUG_MMAP_MSG("mgam83fb_mmap: start = 0x%lx, off = 0x%lx, len = 0x%x\n",
523 /* off that's in range of 0..."fb len" corresponds to framebuffer */
524 /* off that's in range of "fb len"..."io len" corresponds to mmio */
526 DEBUG_MMAP_MSG("mgam83fb_mmap: given off corresponds to fbmem\n");
528 vma
->vm_page_prot
= (cpu_has(CPU_HAS_WC_PCI_PREFETCH
)) ?
529 pgprot_writecombine(vma
->vm_page_prot
) :
530 pgprot_noncached(vma
->vm_page_prot
);
534 if ((off
>= len
) && (off
< 0x80000000)) {
535 /* memory mapped io */
536 DEBUG_MMAP_MSG("mgam83fb_mmap: given off corresponds to mmio\n");
538 start
= info
->fix
.mmio_start
;
539 len
= PAGE_ALIGN((start
& ~PAGE_MASK
) + info
->fix
.mmio_len
);
541 vma
->vm_page_prot
= pgprot_noncached(vma
->vm_page_prot
);
545 /* off that's more then 0x80000000 corresponds to allocated dma buffers */
546 if (off
>= 0x80000000){
547 DEBUG_MMAP_MSG("mgam83fb_mmap: given off corresponds to dma mem\n");
548 off
= off
- 0x80000000;
549 DEBUG_MMAP_MSG("mgam83fb_mmap: corrected off: 0x%lx\n", off
);
550 tmp_list
= lookup_trough_dma_list(off
);
552 DEBUG_MMAP_MSG("mgam83fb_mmap: relevant dma buffer isn't found\n");
555 DEBUG_MMAP_MSG("mgam83fb_mmap: found dma buffer, the \"off\" corresponds to\n");
556 DEBUG_MMAP_MSG("mgam83fb_mmap: dma buf parms: paddr 0x%lx, size 0x%x\n",
557 tmp_list
->phys_addr
, tmp_list
->size
);
558 DEBUG_MMAP_MSG("mgam83fb_mmap: We desire to map the range from 0x%lx to 0x%lx\n",
559 off
, (off
+ vma
->vm_end
- vma
->vm_start
));
560 if (((off
- tmp_list
->phys_addr
) +
561 (vma
->vm_end
- vma
->vm_start
)) > tmp_list
->size
){
562 DEBUG_MMAP_MSG("mgam83fb_mmap: too much size was given to map in:\n");
563 DEBUG_MMAP_MSG("mgam83fb_mmap: off: 0x%lx given size: 0x%lx, "
564 "found dma buffer size: 0x%x\n", (off
- tmp_list
->phys_addr
),
565 (vma
->vm_end
- vma
->vm_start
), tmp_list
->size
);
569 vma
->vm_pgoff
= off
>> PAGE_SHIFT
;
570 vma
->vm_flags
|= VM_IO
| VM_RESERVED
;
572 if (vma
->vm_flags
& VM_WRITECOMBINED
)
574 pgprot_writecombine(vma
->vm_page_prot
);
577 #if defined (__sparc__)
578 if (remap_pfn_range(vma
, vma
->vm_start
,
579 MK_IOSPACE_PFN(p
->mem
.iospace
, (off
>> PAGE_SHIFT
)),
580 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
))
583 if (remap_pfn_range(vma
, vma
->vm_start
, off
>> PAGE_SHIFT
,
584 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
))
587 DEBUG_MMAP_MSG("mgam83fb_mmap: mapping done successfully\n");
592 if ((off
+ vma
->vm_end
- vma
->vm_start
) > len
)
596 vma
->vm_pgoff
= off
>> PAGE_SHIFT
;
597 /* This is an IO map - tell maydump to skip this VMA */
598 vma
->vm_flags
|= VM_IO
| VM_RESERVED
;
600 #if !defined(__e2k__)
601 vma
->vm_page_prot
= pgprot_noncached(vma
->vm_page_prot
);
604 #if defined (__sparc__)
605 if (io_remap_pfn_range(vma
, vma
->vm_start
,
606 MK_IOSPACE_PFN(p
->mem
.iospace
, (off
>> PAGE_SHIFT
)),
607 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
)) {
611 if (io_remap_pfn_range(vma
, vma
->vm_start
, off
>> PAGE_SHIFT
,
612 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
))
620 extern int soft_cursor(struct fb_info
*info
, struct fb_cursor
*cursor
);
621 extern void cfb_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
);
625 static struct fb_copyarea last_area
[10];
626 static int area_count
= 0;
627 static struct fb_copyarea
*curr_area
= NULL
;
628 static struct fb_info
*last_info
[10];
631 static inline u32
flip_32 (u32 l
)
633 return ((l
&0xff)<<24) | (((l
>>8)&0xff)<<16) |
634 (((l
>>16)&0xff)<<8)| ((l
>>24)&0xff);
637 static inline u32
bitflip_32 (u32 l
)
639 return ((l
&0x1)<<31) | (((l
>>1)&0x1)<<30) |
640 (((l
>>2)&0x1)<<29) | (((l
>>3)&0x1)<<28) |
641 (((l
>>4)&0x1)<<27) | (((l
>>5)&0x1)<<26) |
642 (((l
>>6)&0x1)<<25) | (((l
>>7)&0x1)<<24) |
643 (((l
>>8)&0x1)<<23) | (((l
>>9)&0x1)<<22) |
644 (((l
>>10)&0x1)<<21)| (((l
>>11)&0x1)<<20)|
645 (((l
>>12)&0x1)<<19)| (((l
>>13)&0x1)<<18)|
646 (((l
>>14)&0x1)<<17)| (((l
>>15)&0x1)<<16)|
647 (((l
>>16)&0x1)<<15)| (((l
>>17)&0x1)<<14)|
648 (((l
>>18)&0x1)<<13)| (((l
>>19)&0x1)<<12)|
649 (((l
>>20)&0x1)<<11)| (((l
>>21)&0x1)<<10)|
650 (((l
>>22)&0x1)<<9) | (((l
>>23)&0x1)<<8) |
651 (((l
>>24)&0x1)<<7) | (((l
>>25)&0x1)<<6) |
652 (((l
>>26)&0x1)<<5) | (((l
>>27)&0x1)<<4) |
653 (((l
>>28)&0x1)<<3) | (((l
>>29)&0x1)<<2) |
654 (((l
>>30)&0x1)<<1) | ((l
>>31)&0x1);
659 unsigned long virt_addr
;
664 static struct dma_image d_image
;
667 #define FB_WRITEL fb_writel
668 #define FB_READL fb_readl
672 #ifdef CONFIG_SBUS_MGA_HWCOPYAREA
673 static void mgam83fb_copyarea(struct fb_info
*info
, const struct fb_copyarea
*region
)
675 struct mgam83fb_par
* p
= (struct mgam83fb_par
*)info
->par
;
676 unsigned int line_length
= info
->var
.xres_virtual
* (info
->var
.bits_per_pixel
>> 3); /* Bytes */
677 unsigned int command
= 0;
678 struct fb_copyarea modded
;
679 u32 dx
= region
->dx
, dy
= region
->dy
;
680 u32 sx
= region
->sx
, sy
= region
->sy
;
681 int dst_idx
= 0, src_idx
= 0;
682 u32 spitch
= line_length
;
683 u32 dpitch
= line_length
;
688 modded
.width
= region
->width
;
689 modded
.height
= region
->height
;
693 if (area_count
== 10)
695 last_area
[area_count
].width
= modded
.width
;
696 last_area
[area_count
].height
= modded
.height
;
697 last_area
[area_count
].dx
= dx
;
698 last_area
[area_count
].dy
= dy
;
699 last_area
[area_count
].sx
= sx
;
700 last_area
[area_count
].sy
= sy
;
701 last_info
[area_count
] = info
;
706 if ((info
->flags
& FBINFO_HWACCEL_DISABLED
)) {
707 cfb_copyarea(info
, region
);
711 vxres
= info
->var
.xres_virtual
;
712 vyres
= info
->var
.yres_virtual
;
714 if(!region
->width
|| !region
->height
||
715 sx
>= vxres
|| sy
>= vyres
||
716 dx
>= vxres
|| dy
>= vyres
)
719 if(sx
+ modded
.width
> vxres
) modded
.width
= vxres
- sx
;
720 if(dx
+ modded
.width
> vxres
) modded
.width
= vxres
- dx
;
721 if(sy
+ modded
.height
> vyres
) modded
.height
= vyres
- sy
;
722 if(dy
+ modded
.height
> vyres
) modded
.height
= vyres
- dy
;
724 width
= ((modded
.width
)*(info
->var
.bits_per_pixel
>> 3)); /* window lenght in bytes */
725 height
= modded
.height
; /* number of lines */
727 // Waiting for BitBLT is not full
729 while (MMIO_READ(p
, BBR0
) & PROCESS
){
732 /* FIXME: should be investigated */
733 if (info
->fbops
->fb_sync
)
734 info
->fbops
->fb_sync(info
);
740 dst_idx
= dy
*line_length
+ dx
*(info
->var
.bits_per_pixel
>> 3); /* Bytes */
741 src_idx
= sy
*line_length
+ sx
*(info
->var
.bits_per_pixel
>> 3); /* Bytes */
744 if (area_count
== 10)
746 last_area
[area_count
].width
= modded
.width
;
747 last_area
[area_count
].height
= modded
.height
;
748 last_area
[area_count
].dx
= dx
;
749 last_area
[area_count
].dy
= dy
;
750 last_area
[area_count
].sx
= sx
;
751 last_area
[area_count
].sy
= sy
;
752 last_info
[area_count
] = info
;
756 MMIO_WRITE(p
, BBR1
, ((height
<< 16) | width
));
757 MMIO_WRITE(p
, BBR2
, src_idx
);
758 MMIO_WRITE(p
, BBR3
, dst_idx
);
759 MMIO_WRITE(p
, BBR4
, ((dpitch
<< 16) | spitch
));
761 command
|= (ROP_05
| START
);
766 MMIO_WRITE(p
, BBR0
, command
);
768 while ( MMIO_READ(p
, BBR0
) & PROCESS
) {
774 * Driver initialization
777 extern int soft_cursor(struct fb_info
*info
, struct fb_cursor
*cursor
);
779 static struct fb_ops mgam83fb_ops
= {
780 .owner
= THIS_MODULE
,
782 .fb_check_var
= mgam83fb_check_var
,
783 .fb_set_par
= mgam83fb_set_par
,
784 .fb_setcolreg
= mgam83fb_setcolreg
,
785 .fb_ioctl
= mgam83fb_ioctl
,
786 .fb_mmap
= mgam83fb_mmap
,
787 .fb_fillrect
= cfb_fillrect
, // Generic function
788 #ifdef CONFIG_SBUS_MGA_HWCOPYAREA
789 .fb_copyarea
= mgam83fb_copyarea
, // HW function
791 .fb_copyarea
= cfb_copyarea
, // Generic function
793 .fb_imageblit
= cfb_imageblit
,
795 .fb_cursor
= soft_cursor
798 static int __fb_init( struct fb_info
* info
)
800 struct mgam83fb_par
* p
= (struct mgam83fb_par
*)info
->par
;
806 printk( KERN_INFO
"MEM : base 0x%08lx vbase 0x%08lx len 0x%lx\n",
807 (unsigned long)p
->mem
.base
, (unsigned long)p
->mem
.vbase
,
808 (unsigned long)p
->mem
.len
);
809 printk( KERN_INFO
"MMIO: base 0x%08lx vbase 0x%08lx len 0x%lx\n",
810 (unsigned long)p
->mmio
.base
, (unsigned long)p
->mmio
.vbase
,
811 (unsigned long)p
->mmio
.len
);
812 printk( KERN_INFO
"I2C : base 0x%08lx vbase 0x%08lx len 0x%lx\n",
813 (unsigned long)p
->i2c
.base
, (unsigned long)p
->i2c
.vbase
,
814 (unsigned long)p
->i2c
.len
);
817 * Here we set the screen_base to the virtual memory address
818 * for the framebuffer.
820 info
->screen_base
= p
->mem
.vbase
; // Framebuffer virtual memory
821 info
->fbops
= &mgam83fb_ops
;
823 strncpy( info
->fix
.id
, "mcst_mga", 8 );
824 info
->fix
.smem_start
= p
->mem
.base
;
825 info
->fix
.smem_len
= p
->mem
.len
;
826 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
827 info
->fix
.type_aux
= 0;
828 info
->fix
.xpanstep
= 0;
829 info
->fix
.ypanstep
= 0;
830 info
->fix
.ywrapstep
= 0;
831 info
->fix
.mmio_start
= p
->mmio
.base
;
832 info
->fix
.mmio_len
= p
->mmio
.len
;
835 info
->pseudo_palette
= p
->pseudo_palette
; /* The pseudopalette is an
838 /* Set up flags to indicate what sort of acceleration driver can provide */
840 info
->flags
= FBINFO_DEFAULT
841 #ifdef CONFIG_SBUS_MGA_HWCOPYAREA
842 | FBINFO_HWACCEL_COPYAREA
846 * This should give a reasonable default video mode. The following is
847 * done when we can set a video mode.
850 mode_option
= "640x480@60";
851 // mode_option = "1024x768@60";
853 retval
= fb_find_mode(&info
->var
, info
, mode_option
, NULL
, 0, NULL
, 8);
854 if (!retval
|| retval
== 4) {
855 ERROR_MSG( "fb_find_mode() failed\n");
858 printk(KERN_INFO
"MGA/M-83: default bits_per_pixel: %d\n", info
->var
.bits_per_pixel
);
860 /* úÄÅÓØ ÉÎÉÃÉÁÌÉÚÉÒÕÅÔÓÑ ÓÔÒÕËÔÕÒÁ cmap É ÚÁÐÏÌÎÑÅÔÓÑ Ã×ÅÔÁÍÉ ÐÏ default
861 îÁ ÒÅÇÉÓÔÒÙ ÒÁÓËÌÁÄËÁ ÌÏÖÉÔÓÑ Æ-ÅÊ fb_set_cmap -> fb_setcolreg ÉÌÉ ÐÏ default
862 ÉÌÉ ÐÏÌØÚÏ×ÁÔÅÌØÓËÁÑ ÉÓÐÏÌØÚÕÑ FBIOPUTCMAP */
863 retval
= fb_alloc_cmap(&info
->cmap
, 256, 0);
865 ERROR_MSG( "unable to allocate colormap\n" );
870 * For drivers that can...
872 /* ÚÄÅÓØ ÉÎÉÃÉÁÌÉÚÉÒÕÅÔÓÑ ÍÁÓÓÉ× fb_bitfield ÄÌÑ Ã×ÅÔÏ× */
873 DEBUG_MSG("__fb_init: fb_bitfield initialization\n");
874 if (mgam83fb_check_var(&info
->var
, info
)) {
875 ERROR_MSG( "unable to validate variable\n" );
879 if (p
->bus_type
== BUS_TYPE_SBUS
){
880 DEBUG_MSG("mgam83fb: __init_pixclock - only SBUS\n");
881 __sbus_init_pixclock(p
->bus_type
, (unsigned long)p
->i2c
.vbase
);
883 /* ÚÄÅÓØ ÉÎÉÃÉÁÌÉÚÉÒÕÅÔÓÑ ×ÙÓÏÔÁ, ÛÉÒÉÎÁ, ÒÁÚÒÅÛÅÎÉÅ É Ô.Ä */
884 mgam83fb_set_par(info
);
887 if (register_framebuffer(info
) < 0) {
888 ERROR_MSG( "register_framebuffer() failed\n" );
889 fb_dealloc_cmap(&info
->cmap
);
892 printk(KERN_INFO
"fb%d: %s frame buffer device\n", info
->node
, info
->fix
.id
);
893 p
->index
= next_index
++;
901 #if defined(CONFIG_SBUS) || defined(CONFIG_PCI2SBUS_MODULE)
902 static int mga_sbus_probe(struct of_device
* op
, const struct of_device_id
*match
)
904 struct fb_info
* info
;
905 struct mgam83fb_par
* p
;
907 unsigned long length
= 0;
910 * Dynamically allocate info and par
912 DEBUG_MSG("mgam83fb: sbus driver init\n");
913 info
= framebuffer_alloc(sizeof(struct mgam83fb_par
), NULL
);
915 printk( KERN_ERR
"mgam83: failed to allocate fb_info instance!\n");
920 p
->bus_type
= BUS_TYPE_SBUS
;
923 dev_set_drvdata(&op
->dev
, p
);
924 // Framebuffer memory
926 p
->mem
.iospace
= op
->resource
[SBUS_MEM_BAR
].flags
& IORESOURCE_BITS
;
928 p
->mem
.base
= op
->resource
[SBUS_MEM_BAR
].start
;
929 p
->mem
.len
= op
->resource
[SBUS_MEM_BAR
].end
- op
->resource
[SBUS_MEM_BAR
].start
+ 1;
930 p
->mem
.vbase
= (uint8_t*)of_ioremap(&op
->resource
[SBUS_MEM_BAR
], 0, p
->mem
.len
, "mga_mem");
932 ERROR_MSG( "Cannot ioremap MEM (0x%08lx:0x%x)\n", p
->mem
.base
, p
->mem
.len
);
934 goto fail_mem_ioremap
;
937 // Video card registers
938 p
->mmio
.base
= op
->resource
[SBUS_MMIO_BAR
].start
;
939 p
->mmio
.len
= op
->resource
[SBUS_MMIO_BAR
].end
- op
->resource
[SBUS_MMIO_BAR
].start
+ 1;
940 p
->mmio
.vbase
= (uint8_t*)of_ioremap(&op
->resource
[SBUS_MMIO_BAR
], 0, p
->mmio
.len
, "mga_mmio");
941 if ( !p
->mmio
.vbase
)
943 ERROR_MSG( "Cannot ioremap MMIO (0x%08lx:0x%x)\n", p
->mmio
.base
, p
->mmio
.len
);
945 goto fail_mmio_ioremap
;
949 p
->i2c
.base
= op
->resource
[SBUS_I2C_BAR
].start
;
950 p
->i2c
.len
= op
->resource
[SBUS_I2C_BAR
].end
- op
->resource
[SBUS_I2C_BAR
].start
+ 1;
951 p
->i2c
.vbase
= (uint8_t*)of_ioremap(&op
->resource
[SBUS_I2C_BAR
], 0, p
->i2c
.len
, "mga_i2c");
954 ERROR_MSG("Cannot ioremap I2C (0x%08lx:0x%x)\n", p
->i2c
.base
, p
->i2c
.len
);
956 goto fail_i2c_ioremap
;
960 // Filling info, selecting mode and initializating framebuffer
961 DEBUG_MSG("mgam83fb: framerbuffer init...\n");
962 if ( (ret
= __fb_init( info
)) )
963 goto fail_register_fb
;
965 printk("SBUS MGA video card %d:%d\n", op
->slot
, op
->portid
);
971 of_iounmap(&op
->resource
[SBUS_I2C_BAR
], p
->i2c
.vbase
, length
);
973 sbus_iounmap((unsigned long)p
->i2c
.vbase
, length
);
976 length
= p
->mmio
.len
;
978 of_iounmap(&op
->resource
[SBUS_MMIO_BAR
], p
->mmio
.vbase
, length
);
980 sbus_iounmap((unsigned long)p
->mmio
.vbase
, length
);
985 of_iounmap(&op
->resource
[SBUS_MEM_BAR
], p
->mem
.vbase
, length
);
987 sbus_iounmap((unsigned long)p
->mem
.vbase
, length
);
990 framebuffer_release(info
);
996 static int mga_sbus_remove(struct of_device
*op
)
998 struct mgam83fb_par
* p
= dev_get_drvdata(&op
->dev
);
999 struct fb_info
* info
= p
->info
;
1000 /* or dev_get_drv_data(device); */
1001 unsigned long length
= 0;
1003 if (p
->video_buf
.ioaddr
) {
1004 struct page
*map
, *mapend
;
1005 dma_unmap_single(&p
->mgaop
->dev
, p
->video_buf
.ioaddr
,
1006 p
->video_buf
.size
, DMA_BIDIRECTIONAL
);
1007 mapend
= virt_to_page(p
->video_buf
.kvaddr
+ p
->video_buf
.size
-1);
1008 for (map
= virt_to_page(p
->video_buf
.kvaddr
); map
<= mapend
; map
++) {
1009 ClearPageReserved(map
);
1011 free_pages(p
->video_buf
.kvaddr
, get_order(p
->video_buf
.size
));
1012 p
->video_buf
.ioaddr
= 0;
1013 p
->video_buf
.kvaddr
= 0;
1014 p
->video_buf
.size
= 0;
1019 MMIO_WRITE(p
, REG_CTRL
, MMIO_READ( p
, REG_CTRL
) & ~CTRL_VEN
);
1021 unregister_framebuffer(info
);
1022 fb_dealloc_cmap(&info
->cmap
);
1023 length
= p
->i2c
.len
;
1025 of_iounmap(&op
->resource
[SBUS_I2C_BAR
], p
->i2c
.vbase
, length
);
1027 sbus_iounmap((unsigned long)p
->i2c
.vbase
, length
);
1029 length
= p
->mmio
.len
;
1031 of_iounmap(&op
->resource
[SBUS_MMIO_BAR
], p
->mmio
.vbase
, length
);
1033 sbus_iounmap((unsigned long)p
->mmio
.vbase
, length
);
1035 length
= p
->mem
.len
;
1037 of_iounmap(&op
->resource
[SBUS_MEM_BAR
], p
->mem
.vbase
, length
);
1039 sbus_iounmap((unsigned long)p
->mem
.vbase
, length
);
1041 framebuffer_release(info
);
1050 static const struct of_device_id mgam_sbus_match
[] = {
1063 MODULE_DEVICE_TABLE(of
, mgam_sbus_match
);
1065 static struct of_platform_driver mga_sbus_driver
= {
1067 .match_table
= mgam_sbus_match
,
1068 .probe
= mga_sbus_probe
,
1069 .remove
= mga_sbus_remove
,
1075 ////////////////////////////////////////////////////////////////////////////////
1077 ////////////////////////////////////////////////////////////////////////////////
1078 static int __init
mga_sbus_init(void)
1080 printk("SBUS MGA video card driver loaded\n");
1082 char *option
= NULL
;
1083 if (fb_get_options("mgam83fb", &option
)) {
1086 mode_option
= option
;
1088 return of_register_driver(&mga_sbus_driver
, &of_bus_type
);
1091 static void __exit
mga_sbus_exit(void)
1093 of_unregister_driver(&mga_sbus_driver
);
1096 module_init(mga_sbus_init
);
1097 module_exit(mga_sbus_exit
);
1099 MODULE_LICENSE("GPL");