2005-09-10 00:04:45 +04:00
/*
* SiS 300 / 540 / 630 [ S ] / 730 [ S ]
* SiS 315 [ E | PRO ] / 550 / [ M ] 65 x / [ M ] 66 x [ F | M | G ] X / [ M ] 74 x [ GX ] / 330 / [ M ] 76 x [ GX ]
* XGI V3XT / V5 / V8 , Z7
* frame buffer driver for Linux kernels > = 2.4 .14 and > = 2.6 .3
*
* Linux kernel specific extensions to init . c / init301 . c
*
* Copyright ( C ) 2001 - 2005 Thomas Winischhofer , Vienna , Austria .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the named License ,
* or any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 , USA
*
* Author : Thomas Winischhofer < thomas @ winischhofer . net >
*/
# include "osdef.h"
# include "initdef.h"
# include "vgatypes.h"
# include "vstruct.h"
# include <linux/types.h>
# include <linux/fb.h>
int sisfb_mode_rate_to_dclock ( struct SiS_Private * SiS_Pr ,
unsigned char modeno , unsigned char rateindex ) ;
int sisfb_mode_rate_to_ddata ( struct SiS_Private * SiS_Pr , unsigned char modeno ,
unsigned char rateindex , struct fb_var_screeninfo * var ) ;
2007-02-12 11:55:06 +03:00
bool sisfb_gettotalfrommode ( struct SiS_Private * SiS_Pr , unsigned char modeno ,
2005-09-10 00:04:45 +04:00
int * htotal , int * vtotal , unsigned char rateindex ) ;
2007-02-12 11:55:06 +03:00
extern bool SiSInitPtr ( struct SiS_Private * SiS_Pr ) ;
extern bool SiS_SearchModeID ( struct SiS_Private * SiS_Pr , unsigned short * ModeNo ,
2005-09-10 00:04:45 +04:00
unsigned short * ModeIdIndex ) ;
extern void SiS_Generic_ConvertCRData ( struct SiS_Private * SiS_Pr , unsigned char * crdata ,
2007-02-12 11:55:06 +03:00
int xres , int yres , struct fb_var_screeninfo * var , bool writeres ) ;
2005-09-10 00:04:45 +04:00
int
sisfb_mode_rate_to_dclock ( struct SiS_Private * SiS_Pr , unsigned char modeno ,
unsigned char rateindex )
{
unsigned short ModeNo = modeno ;
unsigned short ModeIdIndex = 0 , ClockIndex = 0 ;
unsigned short RRTI = 0 ;
int Clock ;
if ( ! SiSInitPtr ( SiS_Pr ) ) return 65000 ;
if ( rateindex > 0 ) rateindex - - ;
# ifdef SIS315H
switch ( ModeNo ) {
case 0x5a : ModeNo = 0x50 ; break ;
case 0x5b : ModeNo = 0x56 ;
}
# endif
if ( ! ( SiS_SearchModeID ( SiS_Pr , & ModeNo , & ModeIdIndex ) ) ) { ;
printk ( KERN_ERR " Could not find mode %x \n " , ModeNo ) ;
return 65000 ;
}
RRTI = SiS_Pr - > SiS_EModeIDTable [ ModeIdIndex ] . REFindex ;
if ( SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_InfoFlag & HaveWideTiming ) {
if ( SiS_Pr - > SiS_UseWide = = 1 ) {
/* Wide screen: Ignore rateindex */
ClockIndex = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRTVCLK_WIDE ;
} else {
RRTI + = rateindex ;
ClockIndex = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRTVCLK_NORM ;
}
} else {
RRTI + = rateindex ;
ClockIndex = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRTVCLK ;
}
Clock = SiS_Pr - > SiS_VCLKData [ ClockIndex ] . CLOCK * 1000 ;
return Clock ;
}
int
sisfb_mode_rate_to_ddata ( struct SiS_Private * SiS_Pr , unsigned char modeno ,
unsigned char rateindex , struct fb_var_screeninfo * var )
{
unsigned short ModeNo = modeno ;
unsigned short ModeIdIndex = 0 , index = 0 , RRTI = 0 ;
int j ;
if ( ! SiSInitPtr ( SiS_Pr ) ) return 0 ;
if ( rateindex > 0 ) rateindex - - ;
# ifdef SIS315H
switch ( ModeNo ) {
case 0x5a : ModeNo = 0x50 ; break ;
case 0x5b : ModeNo = 0x56 ;
}
# endif
if ( ! ( SiS_SearchModeID ( SiS_Pr , & ModeNo , & ModeIdIndex ) ) ) return 0 ;
RRTI = SiS_Pr - > SiS_EModeIDTable [ ModeIdIndex ] . REFindex ;
if ( SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_InfoFlag & HaveWideTiming ) {
if ( SiS_Pr - > SiS_UseWide = = 1 ) {
/* Wide screen: Ignore rateindex */
index = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRT1CRTC_WIDE ;
} else {
RRTI + = rateindex ;
index = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRT1CRTC_NORM ;
}
} else {
RRTI + = rateindex ;
index = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRT1CRTC ;
}
SiS_Generic_ConvertCRData ( SiS_Pr ,
( unsigned char * ) & SiS_Pr - > SiS_CRT1Table [ index ] . CR [ 0 ] ,
SiS_Pr - > SiS_RefIndex [ RRTI ] . XRes ,
SiS_Pr - > SiS_RefIndex [ RRTI ] . YRes ,
2007-02-12 11:55:06 +03:00
var , false ) ;
2005-09-10 00:04:45 +04:00
if ( SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_InfoFlag & 0x8000 )
var - > sync & = ~ FB_SYNC_VERT_HIGH_ACT ;
else
var - > sync | = FB_SYNC_VERT_HIGH_ACT ;
if ( SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_InfoFlag & 0x4000 )
var - > sync & = ~ FB_SYNC_HOR_HIGH_ACT ;
else
var - > sync | = FB_SYNC_HOR_HIGH_ACT ;
var - > vmode = FB_VMODE_NONINTERLACED ;
if ( SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_InfoFlag & 0x0080 )
var - > vmode = FB_VMODE_INTERLACED ;
else {
j = 0 ;
while ( SiS_Pr - > SiS_EModeIDTable [ j ] . Ext_ModeID ! = 0xff ) {
if ( SiS_Pr - > SiS_EModeIDTable [ j ] . Ext_ModeID = =
SiS_Pr - > SiS_RefIndex [ RRTI ] . ModeID ) {
if ( SiS_Pr - > SiS_EModeIDTable [ j ] . Ext_ModeFlag & DoubleScanMode ) {
var - > vmode = FB_VMODE_DOUBLE ;
}
break ;
}
j + + ;
}
}
if ( ( var - > vmode & FB_VMODE_MASK ) = = FB_VMODE_INTERLACED ) {
#if 0 /* Do this? */
var - > upper_margin < < = 1 ;
var - > lower_margin < < = 1 ;
var - > vsync_len < < = 1 ;
# endif
} else if ( ( var - > vmode & FB_VMODE_MASK ) = = FB_VMODE_DOUBLE ) {
var - > upper_margin > > = 1 ;
var - > lower_margin > > = 1 ;
var - > vsync_len > > = 1 ;
}
return 1 ;
}
2007-02-12 11:55:06 +03:00
bool
2005-09-10 00:04:45 +04:00
sisfb_gettotalfrommode ( struct SiS_Private * SiS_Pr , unsigned char modeno , int * htotal ,
int * vtotal , unsigned char rateindex )
{
unsigned short ModeNo = modeno ;
unsigned short ModeIdIndex = 0 , CRT1Index = 0 ;
unsigned short RRTI = 0 ;
unsigned char sr_data , cr_data , cr_data2 ;
2007-02-12 11:55:06 +03:00
if ( ! SiSInitPtr ( SiS_Pr ) ) return false ;
2005-09-10 00:04:45 +04:00
if ( rateindex > 0 ) rateindex - - ;
# ifdef SIS315H
switch ( ModeNo ) {
case 0x5a : ModeNo = 0x50 ; break ;
case 0x5b : ModeNo = 0x56 ;
}
# endif
2007-02-12 11:55:06 +03:00
if ( ! ( SiS_SearchModeID ( SiS_Pr , & ModeNo , & ModeIdIndex ) ) ) return false ;
2005-09-10 00:04:45 +04:00
RRTI = SiS_Pr - > SiS_EModeIDTable [ ModeIdIndex ] . REFindex ;
if ( SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_InfoFlag & HaveWideTiming ) {
if ( SiS_Pr - > SiS_UseWide = = 1 ) {
/* Wide screen: Ignore rateindex */
CRT1Index = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRT1CRTC_WIDE ;
} else {
RRTI + = rateindex ;
CRT1Index = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRT1CRTC_NORM ;
}
} else {
RRTI + = rateindex ;
CRT1Index = SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_CRT1CRTC ;
}
sr_data = SiS_Pr - > SiS_CRT1Table [ CRT1Index ] . CR [ 14 ] ;
cr_data = SiS_Pr - > SiS_CRT1Table [ CRT1Index ] . CR [ 0 ] ;
* htotal = ( ( ( cr_data & 0xff ) | ( ( unsigned short ) ( sr_data & 0x03 ) < < 8 ) ) + 5 ) * 8 ;
sr_data = SiS_Pr - > SiS_CRT1Table [ CRT1Index ] . CR [ 13 ] ;
cr_data = SiS_Pr - > SiS_CRT1Table [ CRT1Index ] . CR [ 6 ] ;
cr_data2 = SiS_Pr - > SiS_CRT1Table [ CRT1Index ] . CR [ 7 ] ;
* vtotal = ( ( cr_data & 0xFF ) |
( ( unsigned short ) ( cr_data2 & 0x01 ) < < 8 ) |
( ( unsigned short ) ( cr_data2 & 0x20 ) < < 4 ) |
( ( unsigned short ) ( sr_data & 0x01 ) < < 10 ) ) + 2 ;
if ( SiS_Pr - > SiS_RefIndex [ RRTI ] . Ext_InfoFlag & InterlaceMode )
* vtotal * = 2 ;
2007-02-12 11:55:06 +03:00
return true ;
2005-09-10 00:04:45 +04:00
}