lugin for Real-Time Systems journal paper
aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/video/pm3fb.c
blob: 070659992c1841bd6fccac6f9d2abd56ec174011 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                                                       





                                                                             
                             


                                                       


                                              

                                                                         




                                                                              

   




                         
                       
                        


                       


                     
 
                        
 

                                          

      

                         

                                                               
     
                        
      
 

                                  


              
                        
                                       
                                 


                  
                                
      
 
  








                                                                            
                                                                          
                                    
                                    

  











                                                                             
                                                  

  


                    
 



                                                            
 



                                                                     
 

                                                       

                                                     

 
                                                                           
 


                                                             

                                                 
              

 

                                                                            
 








                                                             






                                                                          
                                  

                                                 

 
                                          



                                                         



                            
                     



                                                          





                                                                             


                                                          



                                 

 
                                                                  
 
                                      








                                                          

                                




                                
                                               
                 

 









                                                             

                                                                 














































































                                                                      

                                                



                                                                     


                                      



                                                                      


                                      
























































                                                                       
                                           













                                                      
                                                




                                                                 
                
                                                               
                                                                             


                                                
                                                    


                                           




                                                                  





                                                            

                                                     

                       
                                              
                                                  
                                              

                                                  
                                          
                                    
                                           


                                     
                               
                                       

                                                         
                             
                                                   



                                                      

                                                                 





                                                    

                                                         
 




















                                                               


                                                       

                       
                                             
                                                 
                                             
                                                 
                                              
                                                  
                                              












                                                                                
                                                                            












                                                                             

                                                                           






                                                                               

                                                                   






                                                                               
                                                  
 





                                                    
                                   








                                                    
         
                              
                                                  
 








                                             
                         





                                                    
                                                       

                                                         
                                                        

                                                   




                                                                             
                                                

                                                                 




                                                             

                                                           


                          

                                                              
                            


















                                                                            

                                   














































































































                                                                                
                                 
                                                  
 
                                        

                             









                                                            

























                                                              
               
                                                      
                                                                     
                                                      


                                                                     

                    
                                                      
                                                                      
                                                      

                                                                      
                                                      

                                                                      
                                                      






                                                                      
                                                      
                                                                      
                                                      

                                                                      
                                                      

                                                                      
                                                      





                                                                      
                                                       









                                                                    
                                                




                                                            
                                                           
         
                                      
                                                                         

                                                     
                                                                            
 
              
         












                                                                              

          
                                                            

           
                                                             
           
                                                        

                                                                
                                                        

                                                                
 




                                                            
                                          
               
                                                       
                                                                
                                                         




                                                                          
                                                       
                                                                 
                                                         




                                                                             
                      
                
                                                       
                                                                 
                                                         




                                                                             
                      
                
                                                       
                                                                 
                                                         






                                                                             
                                                       
                                                                 
                                                         





                                                                          
                                                            

 


                                 


                                                                               

                                                                
 
                                         

                                                                     
                                              
                       





                                              



                                               

                                             



                                               


                                              


                                               

                                                            



                                       
                                       



                                                                        
         

                         
 
                                             

                                                                 

                               
 
                                            

                                                                
                               
         
 


                                                   

         


                                                                  
         
 
                                                                      
                                                              
 



                                                                
 



                                                                 
 






                                                                           

                                                       
                               

         
                                                              
 



                                                             
 



                                                     
                                                      
 
                                                                   

                                                             
 



                                                                
 



                                                                
 

                                                                 
 
                                                                       
                                                     
            
                                               
 
                      


                                                             








                                                              
         
 
                          
                                                                         
                                                                           
 

                                           
                                                    
                                

                               

 


                                                                        
 





                                                              

                                                  
                                                                          





                                                                   

                                                                     




                                                          

                                                                        



                                                             
 



                                                                           
                                                                           





















                                                            
                        
                                                                   


                              
                                                             
                                                              
 
                 

 

                                                           
 

                                                
 


                                                             

                                                     

                 
 



                                                            
 









                                                                    
 

                              
                                                
                      
                             
                                                 

                                    

                                                            

                                    

                                                            

                                


                                                            



                                                                 

         
                         
                                                   
                 

 


                                   
 





                                            
                                         

                                          
                                      
                                     
                                       
  
 
                                                                               
 


                          
 


                                                                   
 

                                                    
                                            
 
                                                                                




                                                                         
         





                                                                             

         

                                                                           
 
                                                              
 
                                                                    
 

                                                              
 


                                                           




                                                               
 


                                                                                
                    
                              
         
 
                                                                       
 


                                                                            
                                                                        
                 
                      
 












                                                                          
                 
         
                                                                
 

                                                              
 


                                                                     
 
                                                      
 
                       

 

                                                                  
 

                             


                                                                
 



                                                                              
         



                                                                 
 


                               
 





                                                                    



                                                             















                                                                             


                                                              
                                  

                                                                            
         



                                                                         
         





                                                                             
         
                                               
 
                  
                    


                                                                     
      
                                 
 
                                                        
 

                                            
                                      

                                             


                                                  
 
                      

                                                              
         










                                                                 





                                                                             
 
                                                                               
 


                                     
         
 


                                                     
         
 



                                          
 


                                             
         

                                                                      
                                   
                 
 


                                     

                                 







                                                                     

 



                                                       
 
                                                    
 


                                                           
 

                                             
 




                                                                



                                                                   
 
                                           
                                         
                                          
         

 

                                                
                                            

              
 






                                                  
 
                                         
 



















                                                            
                                                          
                                    

                                                                         
                  
                                                         

                                   
                    
                                               




                   
                                  
 


                                                                       
              


                                             
                               
                            
      
 
                                                  

 
             
                                   
 
                                             

 
                        




                                                  


                                                            



                                                                               
 
                                                          
                      
/*
 *  linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device
 *
 *  Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>.
 *
 *  Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl>
 *	based on pm2fb.c
 *
 *  Based on code written by:
 *	   Sven Luther, <luther@dpt-info.u-strasbg.fr>
 *	   Alan Hourihane, <alanh@fairlite.demon.co.uk>
 *	   Russell King, <rmk@arm.linux.org.uk>
 *  Based on linux/drivers/video/skeletonfb.c:
 *	Copyright (C) 1997 Geert Uytterhoeven
 *  Based on linux/driver/video/pm2fb.c:
 *	Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
 *	Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
 *
 *  This file is subject to the terms and conditions of the GNU General Public
 *  License. See the file COPYING in the main directory of this archive for
 *  more details.
 *
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif

#include <video/pm3fb.h>

#if !defined(CONFIG_PCI)
#error "Only generic PCI cards supported."
#endif

#undef PM3FB_MASTER_DEBUG
#ifdef PM3FB_MASTER_DEBUG
#define DPRINTK(a, b...)	\
	printk(KERN_DEBUG "pm3fb: %s: " a, __FUNCTION__ , ## b)
#else
#define DPRINTK(a, b...)
#endif

#define PM3_PIXMAP_SIZE	(2048 * 4)

/*
 * Driver data
 */
static int hwcursor = 1;
static char *mode_option __devinitdata;
static int noaccel __devinitdata;

/* mtrr option */
#ifdef CONFIG_MTRR
static int nomtrr __devinitdata;
#endif

/*
 * This structure defines the hardware state of the graphics card. Normally
 * you place this in a header file in linux/include/video. This file usually
 * also includes register information. That allows other driver subsystems
 * and userland applications the ability to use the same header file to
 * avoid duplicate work and easy porting of software.
 */
struct pm3_par {
	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
	u32		video;		/* video flags before blanking */
	u32		base;		/* screen base in 128 bits unit */
	u32		palette[16];
	int		mtrr_handle;
};

/*
 * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
 * if we don't use modedb. If we do use modedb see pm3fb_init how to use it
 * to get a fb_var_screeninfo. Otherwise define a default var as well.
 */
static struct fb_fix_screeninfo pm3fb_fix __devinitdata = {
	.id =		"Permedia3",
	.type =		FB_TYPE_PACKED_PIXELS,
	.visual =	FB_VISUAL_PSEUDOCOLOR,
	.xpanstep =	1,
	.ypanstep =	1,
	.ywrapstep =	0,
	.accel =	FB_ACCEL_3DLABS_PERMEDIA3,
};

/*
 * Utility functions
 */

static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off)
{
	return fb_readl(par->v_regs + off);
}

static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
{
	fb_writel(v, par->v_regs + off);
}

static inline void PM3_WAIT(struct pm3_par *par, u32 n)
{
	while (PM3_READ_REG(par, PM3InFIFOSpace) < n)
		cpu_relax();
}

static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
{
	PM3_WAIT(par, 3);
	PM3_WRITE_REG(par, PM3RD_IndexHigh, (r >> 8) & 0xff);
	PM3_WRITE_REG(par, PM3RD_IndexLow, r & 0xff);
	wmb();
	PM3_WRITE_REG(par, PM3RD_IndexedData, v);
	wmb();
}

static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
			unsigned char r, unsigned char g, unsigned char b)
{
	PM3_WAIT(par, 4);
	PM3_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
	wmb();
	PM3_WRITE_REG(par, PM3RD_PaletteData, r);
	wmb();
	PM3_WRITE_REG(par, PM3RD_PaletteData, g);
	wmb();
	PM3_WRITE_REG(par, PM3RD_PaletteData, b);
	wmb();
}

static void pm3fb_clear_colormap(struct pm3_par *par,
			unsigned char r, unsigned char g, unsigned char b)
{
	int i;

	for (i = 0; i < 256 ; i++)
		pm3fb_set_color(par, i, r, g, b);

}

/* Calculating various clock parameters */
static void pm3fb_calculate_clock(unsigned long reqclock,
				unsigned char *prescale,
				unsigned char *feedback,
				unsigned char *postscale)
{
	int f, pre, post;
	unsigned long freq;
	long freqerr = 1000;
	long currerr;

	for (f = 1; f < 256; f++) {
		for (pre = 1; pre < 256; pre++) {
			for (post = 0; post < 5; post++) {
				freq = ((2*PM3_REF_CLOCK * f) >> post) / pre;
				currerr = (reqclock > freq)
					? reqclock - freq
					: freq - reqclock;
				if (currerr < freqerr) {
					freqerr = currerr;
					*feedback = f;
					*prescale = pre;
					*postscale = post;
				}
			}
		}
	}
}

static inline int pm3fb_depth(const struct fb_var_screeninfo *var)
{
	if (var->bits_per_pixel == 16)
		return var->red.length + var->green.length
			+ var->blue.length;

	return var->bits_per_pixel;
}

static inline int pm3fb_shift_bpp(unsigned bpp, int v)
{
	switch (bpp) {
	case 8:
		return (v >> 4);
	case 16:
		return (v >> 3);
	case 32:
		return (v >> 2);
	}
	DPRINTK("Unsupported depth %u\n", bpp);
	return 0;
}

/* acceleration */
static int pm3fb_sync(struct fb_info *info)
{
	struct pm3_par *par = info->par;

	PM3_WAIT(par, 2);
	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
	PM3_WRITE_REG(par, PM3Sync, 0);
	mb();
	do {
		while ((PM3_READ_REG(par, PM3OutFIFOWords)) == 0)
			cpu_relax();
	} while ((PM3_READ_REG(par, PM3OutputFifo)) != PM3Sync_Tag);

	return 0;
}

static void pm3fb_init_engine(struct fb_info *info)
{
	struct pm3_par *par = info->par;
	const u32 width = (info->var.xres_virtual + 7) & ~7;

	PM3_WAIT(par, 50);
	PM3_WRITE_REG(par, PM3FilterMode, PM3FilterModeSync);
	PM3_WRITE_REG(par, PM3StatisticMode, 0x0);
	PM3_WRITE_REG(par, PM3DeltaMode, 0x0);
	PM3_WRITE_REG(par, PM3RasterizerMode, 0x0);
	PM3_WRITE_REG(par, PM3ScissorMode, 0x0);
	PM3_WRITE_REG(par, PM3LineStippleMode, 0x0);
	PM3_WRITE_REG(par, PM3AreaStippleMode, 0x0);
	PM3_WRITE_REG(par, PM3GIDMode, 0x0);
	PM3_WRITE_REG(par, PM3DepthMode, 0x0);
	PM3_WRITE_REG(par, PM3StencilMode, 0x0);
	PM3_WRITE_REG(par, PM3StencilData, 0x0);
	PM3_WRITE_REG(par, PM3ColorDDAMode, 0x0);
	PM3_WRITE_REG(par, PM3TextureCoordMode, 0x0);
	PM3_WRITE_REG(par, PM3TextureIndexMode0, 0x0);
	PM3_WRITE_REG(par, PM3TextureIndexMode1, 0x0);
	PM3_WRITE_REG(par, PM3TextureReadMode, 0x0);
	PM3_WRITE_REG(par, PM3LUTMode, 0x0);
	PM3_WRITE_REG(par, PM3TextureFilterMode, 0x0);
	PM3_WRITE_REG(par, PM3TextureCompositeMode, 0x0);
	PM3_WRITE_REG(par, PM3TextureApplicationMode, 0x0);
	PM3_WRITE_REG(par, PM3TextureCompositeColorMode1, 0x0);
	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode1, 0x0);
	PM3_WRITE_REG(par, PM3TextureCompositeColorMode0, 0x0);
	PM3_WRITE_REG(par, PM3TextureCompositeAlphaMode0, 0x0);
	PM3_WRITE_REG(par, PM3FogMode, 0x0);
	PM3_WRITE_REG(par, PM3ChromaTestMode, 0x0);
	PM3_WRITE_REG(par, PM3AlphaTestMode, 0x0);
	PM3_WRITE_REG(par, PM3AntialiasMode, 0x0);
	PM3_WRITE_REG(par, PM3YUVMode, 0x0);
	PM3_WRITE_REG(par, PM3AlphaBlendColorMode, 0x0);
	PM3_WRITE_REG(par, PM3AlphaBlendAlphaMode, 0x0);
	PM3_WRITE_REG(par, PM3DitherMode, 0x0);
	PM3_WRITE_REG(par, PM3LogicalOpMode, 0x0);
	PM3_WRITE_REG(par, PM3RouterMode, 0x0);
	PM3_WRITE_REG(par, PM3Window, 0x0);

	PM3_WRITE_REG(par, PM3Config2D, 0x0);

	PM3_WRITE_REG(par, PM3SpanColorMask, 0xffffffff);

	PM3_WRITE_REG(par, PM3XBias, 0x0);
	PM3_WRITE_REG(par, PM3YBias, 0x0);
	PM3_WRITE_REG(par, PM3DeltaControl, 0x0);

	PM3_WRITE_REG(par, PM3BitMaskPattern, 0xffffffff);

	PM3_WRITE_REG(par, PM3FBDestReadEnables,
			   PM3FBDestReadEnables_E(0xff) |
			   PM3FBDestReadEnables_R(0xff) |
			   PM3FBDestReadEnables_ReferenceAlpha(0xff));
	PM3_WRITE_REG(par, PM3FBDestReadBufferAddr0, 0x0);
	PM3_WRITE_REG(par, PM3FBDestReadBufferOffset0, 0x0);
	PM3_WRITE_REG(par, PM3FBDestReadBufferWidth0,
			   PM3FBDestReadBufferWidth_Width(width));

	PM3_WRITE_REG(par, PM3FBDestReadMode,
			   PM3FBDestReadMode_ReadEnable |
			   PM3FBDestReadMode_Enable0);
	PM3_WRITE_REG(par, PM3FBSourceReadBufferAddr, 0x0);
	PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset, 0x0);
	PM3_WRITE_REG(par, PM3FBSourceReadBufferWidth,
			   PM3FBSourceReadBufferWidth_Width(width));
	PM3_WRITE_REG(par, PM3FBSourceReadMode,
			   PM3FBSourceReadMode_Blocking |
			   PM3FBSourceReadMode_ReadEnable);

	PM3_WAIT(par, 2);
	{
		/* invert bits in bitmask */
		unsigned long rm = 1 | (3 << 7);
		switch (info->var.bits_per_pixel) {
		case 8:
			PM3_WRITE_REG(par, PM3PixelSize,
					   PM3PixelSize_GLOBAL_8BIT);
#ifdef __BIG_ENDIAN
			rm |= 3 << 15;
#endif
			break;
		case 16:
			PM3_WRITE_REG(par, PM3PixelSize,
					   PM3PixelSize_GLOBAL_16BIT);
#ifdef __BIG_ENDIAN
			rm |= 2 << 15;
#endif
			break;
		case 32:
			PM3_WRITE_REG(par, PM3PixelSize,
					   PM3PixelSize_GLOBAL_32BIT);
			break;
		default:
			DPRINTK(1, "Unsupported depth %d\n",
				info->var.bits_per_pixel);
			break;
		}
		PM3_WRITE_REG(par, PM3RasterizerMode, rm);
	}

	PM3_WAIT(par, 20);
	PM3_WRITE_REG(par, PM3FBSoftwareWriteMask, 0xffffffff);
	PM3_WRITE_REG(par, PM3FBHardwareWriteMask, 0xffffffff);
	PM3_WRITE_REG(par, PM3FBWriteMode,
			   PM3FBWriteMode_WriteEnable |
			   PM3FBWriteMode_OpaqueSpan |
			   PM3FBWriteMode_Enable0);
	PM3_WRITE_REG(par, PM3FBWriteBufferAddr0, 0x0);
	PM3_WRITE_REG(par, PM3FBWriteBufferOffset0, 0x0);
	PM3_WRITE_REG(par, PM3FBWriteBufferWidth0,
			   PM3FBWriteBufferWidth_Width(width));

	PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 0x0);
	{
		/* size in lines of FB */
		unsigned long sofb = info->screen_size /
			info->fix.line_length;
		if (sofb > 4095)
			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, 4095);
		else
			PM3_WRITE_REG(par, PM3SizeOfFramebuffer, sofb);

		switch (info->var.bits_per_pixel) {
		case 8:
			PM3_WRITE_REG(par, PM3DitherMode,
					   (1 << 10) | (2 << 3));
			break;
		case 16:
			PM3_WRITE_REG(par, PM3DitherMode,
					   (1 << 10) | (1 << 3));
			break;
		case 32:
			PM3_WRITE_REG(par, PM3DitherMode,
					   (1 << 10) | (0 << 3));
			break;