mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-14 22:44:27 +08:00
5e0f8ad07b
Based on 1 normalized pattern(s): 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 extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 7 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190520170856.731149235@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
219 lines
6.3 KiB
C
219 lines
6.3 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* SiS 300/540/630[S]/730[S]
|
|
* SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[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.
|
|
*
|
|
* Author: Thomas Winischhofer <thomas@winischhofer.net>
|
|
*/
|
|
|
|
#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);
|
|
bool sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
|
|
int *htotal, int *vtotal, unsigned char rateindex);
|
|
|
|
extern bool SiSInitPtr(struct SiS_Private *SiS_Pr);
|
|
extern bool SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
|
|
unsigned short *ModeIdIndex);
|
|
extern void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
|
|
int xres, int yres, struct fb_var_screeninfo *var, bool writeres);
|
|
|
|
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 CONFIG_FB_SIS_315
|
|
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 CONFIG_FB_SIS_315
|
|
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,
|
|
var, false);
|
|
|
|
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;
|
|
}
|
|
|
|
bool
|
|
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;
|
|
|
|
if(!SiSInitPtr(SiS_Pr)) return false;
|
|
|
|
if(rateindex > 0) rateindex--;
|
|
|
|
#ifdef CONFIG_FB_SIS_315
|
|
switch(ModeNo) {
|
|
case 0x5a: ModeNo = 0x50; break;
|
|
case 0x5b: ModeNo = 0x56;
|
|
}
|
|
#endif
|
|
|
|
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
|
|
|
|
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;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|